Merge tag 'v3.3-rc4' into for-3.4 in order to resolve the conflict
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 20 Feb 2012 02:35:12 +0000 (18:35 -0800)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 20 Feb 2012 02:35:12 +0000 (18:35 -0800)
resolved below within the FSI driver and allow the application of the
dmaeengine conversion that depends on this resolution.

Linux 3.3-rc4

Conflicts:
sound/soc/sh/fsi.c

153 files changed:
Documentation/devicetree/bindings/sound/alc5632.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/tegra-audio-alc5632.txt [new file with mode: 0644]
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/driver-model/devres.txt
arch/arm/mach-ep93xx/core.c
arch/arm/mach-ep93xx/include/mach/platform.h
arch/arm/mach-kirkwood/openrd-setup.c
arch/arm/mach-kirkwood/t5325-setup.c
arch/arm/mach-s3c64xx/mach-crag6410-module.c
arch/arm/mach-shmobile/board-ap4evb.c
arch/arm/mach-shmobile/board-mackerel.c
arch/mips/jz4740/board-qi_lb60.c
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/boards/mach-se/7724/setup.c
drivers/base/regmap/internal.h
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap.c
drivers/regulator/core.c
include/linux/regmap.h
include/linux/regulator/consumer.h
include/sound/control.h
include/sound/max9768.h [new file with mode: 0644]
include/sound/pcm.h
include/sound/sh_fsi.h
include/sound/soc-dai.h
include/sound/soc-dapm.h
include/sound/soc.h
include/sound/wm2200.h [new file with mode: 0644]
include/sound/wm8962.h
sound/core/pcm.c
sound/soc/atmel/atmel-pcm.c
sound/soc/atmel/snd-soc-afeb9260.c
sound/soc/blackfin/bf5xx-ad1836.c
sound/soc/blackfin/bf5xx-ad193x.c
sound/soc/blackfin/bf5xx-ad73311.c
sound/soc/blackfin/bf5xx-ssm2602.c
sound/soc/blackfin/bfin-eval-adau1373.c
sound/soc/blackfin/bfin-eval-adau1701.c
sound/soc/blackfin/bfin-eval-adav80x.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ad1836.c
sound/soc/codecs/ad1980.c
sound/soc/codecs/adau1373.c
sound/soc/codecs/adau1701.c
sound/soc/codecs/ak4535.c
sound/soc/codecs/ak4535.h
sound/soc/codecs/ak4642.c
sound/soc/codecs/ak4671.c
sound/soc/codecs/alc5623.c
sound/soc/codecs/alc5632.c
sound/soc/codecs/alc5632.h
sound/soc/codecs/cq93vc.c
sound/soc/codecs/cs4270.c
sound/soc/codecs/cs4271.c
sound/soc/codecs/lm4857.c
sound/soc/codecs/max9768.c [new file with mode: 0644]
sound/soc/codecs/max98088.c
sound/soc/codecs/max98095.c
sound/soc/codecs/max9877.c
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/sn95031.c
sound/soc/codecs/ssm2602.c
sound/soc/codecs/stac9766.c
sound/soc/codecs/tlv320aic23.c
sound/soc/codecs/tlv320aic26.c
sound/soc/codecs/tlv320aic32x4.c
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/tlv320aic3x.h
sound/soc/codecs/tlv320dac33.c
sound/soc/codecs/tpa6130a2.c
sound/soc/codecs/twl4030.c
sound/soc/codecs/twl6040.c
sound/soc/codecs/twl6040.h
sound/soc/codecs/uda134x.c
sound/soc/codecs/wl1273.c
sound/soc/codecs/wm2200.c [new file with mode: 0644]
sound/soc/codecs/wm2200.h [new file with mode: 0644]
sound/soc/codecs/wm5100.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8737.c
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8770.c
sound/soc/codecs/wm8804.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8904.h
sound/soc/codecs/wm8940.c
sound/soc/codecs/wm8955.c
sound/soc/codecs/wm8958-dsp2.c
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm8961.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8971.c
sound/soc/codecs/wm8974.c
sound/soc/codecs/wm8978.c
sound/soc/codecs/wm8978.h
sound/soc/codecs/wm8983.c
sound/soc/codecs/wm8985.c
sound/soc/codecs/wm8988.c
sound/soc/codecs/wm8990.c
sound/soc/codecs/wm8991.c
sound/soc/codecs/wm8993.c
sound/soc/codecs/wm8993.h
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/wm9705.c
sound/soc/codecs/wm9712.c
sound/soc/codecs/wm9713.c
sound/soc/codecs/wm_hubs.c
sound/soc/codecs/wm_hubs.h
sound/soc/davinci/davinci-pcm.c
sound/soc/ep93xx/edb93xx.c
sound/soc/ep93xx/ep93xx-pcm.c
sound/soc/ep93xx/snappercl15.c
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/mpc5200_dma.c
sound/soc/imx/mx27vis-aic32x4.c
sound/soc/jz4740/qi_lb60.c
sound/soc/kirkwood/kirkwood-dma.c
sound/soc/kirkwood/kirkwood-openrd.c
sound/soc/kirkwood/kirkwood-t5325.c
sound/soc/mid-x86/mfld_machine.c
sound/soc/mxs/mxs-saif.c
sound/soc/omap/ams-delta.c
sound/soc/omap/n810.c
sound/soc/omap/omap-dmic.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcbsp.h
sound/soc/omap/omap-mcpdm.c
sound/soc/omap/rx51.c
sound/soc/pxa/corgi.c
sound/soc/pxa/magician.c
sound/soc/pxa/poodle.c
sound/soc/pxa/pxa2xx-ac97.c
sound/soc/pxa/spitz.c
sound/soc/pxa/tosa.c
sound/soc/s6000/s6000-pcm.c
sound/soc/samsung/dma.c
sound/soc/samsung/littlemill.c
sound/soc/samsung/neo1973_wm8753.c
sound/soc/samsung/s3c24xx_simtec.c
sound/soc/sh/fsi.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-io.c
sound/soc/soc-pcm.c
sound/soc/soc-utils.c
sound/soc/tegra/tegra_alc5632.c
sound/soc/tegra/tegra_pcm.c

diff --git a/Documentation/devicetree/bindings/sound/alc5632.txt b/Documentation/devicetree/bindings/sound/alc5632.txt
new file mode 100644 (file)
index 0000000..8608f74
--- /dev/null
@@ -0,0 +1,24 @@
+ALC5632 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+  - compatible : "realtek,alc5632"
+
+  - reg : the I2C address of the device.
+
+  - gpio-controller : Indicates this device is a GPIO controller.
+
+  - #gpio-cells : Should be two. The first cell is the pin number and the
+    second cell is used to specify optional parameters (currently unused).
+
+Example:
+
+alc5632: alc5632@1e {
+       compatible = "realtek,alc5632";
+       reg = <0x1a>;
+
+       gpio-controller;
+       #gpio-cells = <2>;
+};
diff --git a/Documentation/devicetree/bindings/sound/tegra-audio-alc5632.txt b/Documentation/devicetree/bindings/sound/tegra-audio-alc5632.txt
new file mode 100644 (file)
index 0000000..65b001e
--- /dev/null
@@ -0,0 +1,57 @@
+NVIDIA Tegra audio complex
+
+Required properties:
+- compatible : "nvidia,tegra-audio-alc5632"
+- nvidia,model : The user-visible name of this sound complex.
+- nvidia,audio-routing : A list of the connections between audio components.
+  Each entry is a pair of strings, the first being the connection's sink,
+  the second being the connection's source. Valid names for sources and
+  sinks are the ALC5632's pins:
+
+  ALC5632 pins:
+
+  * SPK_OUTP
+  * SPK_OUTN
+  * HP_OUT_L
+  * HP_OUT_R
+  * AUX_OUT_P
+  * AUX_OUT_N
+  * LINE_IN_L
+  * LINE_IN_R
+  * PHONE_P
+  * PHONE_N
+  * MIC1_P
+  * MIC1_N
+  * MIC2_P
+  * MIC2_N
+  * MICBIAS1
+
+  Board connectors:
+
+  * Headset Stereophone
+  * Int Spk
+  * Headset Mic
+
+- nvidia,i2s-controller : The phandle of the Tegra I2S controller
+- nvidia,audio-codec : The phandle of the ALC5632 audio codec
+
+Example:
+
+sound {
+       compatible = "nvidia,tegra-audio-alc5632-paz00",
+                                "nvidia,tegra-audio-alc5632";
+
+       nvidia,model = "Compal PAZ00";
+
+       nvidia,audio-routing =
+                               "Int Spk", "SPK_OUTP",
+                               "Int Spk", "SPK_OUTN",
+                               "Headset Mic","MICBIAS1",
+                               "MIC1_N", "Headset Mic",
+                               "MIC1_P", "Headset Mic",
+                               "Headset Stereophone", "HP_OUT_R",
+                               "Headset Stereophone", "HP_OUT_L";
+
+       nvidia,i2s-controller = <&tegra_i2s1>;
+       nvidia,audio-codec = <&alc5632>;
+};
index ecc6a6cd26c198ff412ce2af839cc3b602d73a29..ca8ee14bf00449b0fa6540c25ce11415fc532a3d 100644 (file)
@@ -33,6 +33,7 @@ nxp   NXP Semiconductors
 powervr        Imagination Technologies
 qcom   Qualcomm, Inc.
 ramtron        Ramtron International
+realtek Realtek Semiconductor Corp.
 samsung        Samsung Semiconductor
 sbs    Smart Battery System
 schindler      Schindler
index 41c0c5d1ba145a392e17d42dc4ce8ac9c3c41a49..b49829eca792bf180c79a0c37a98b984b152f96c 100644 (file)
@@ -271,3 +271,6 @@ IOMAP
   pcim_iounmap()
   pcim_iomap_table()   : array of mapped addresses indexed by BAR
   pcim_iomap_regions() : do request_region() and iomap() on multiple BARs
+
+REGULATOR
+  devm_regulator_get()
index 24203f9a67967df314a6d3776d6ac581a8d22fb3..b5c1dae8327fd87ccf945913a185397142135ca5 100644 (file)
@@ -817,23 +817,12 @@ void __init ep93xx_register_i2s(void)
 #define EP93XX_I2SCLKDIV_MASK          (EP93XX_SYSCON_I2SCLKDIV_ORIDE | \
                                         EP93XX_SYSCON_I2SCLKDIV_SPOL)
 
-int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config)
+int ep93xx_i2s_acquire(void)
 {
        unsigned val;
 
-       /* Sanity check */
-       if (i2s_pins & ~EP93XX_SYSCON_DEVCFG_I2S_MASK)
-               return -EINVAL;
-       if (i2s_config & ~EP93XX_I2SCLKDIV_MASK)
-               return -EINVAL;
-
-       /* Must have only one of I2SONSSP/I2SONAC97 set */
-       if ((i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONSSP) ==
-           (i2s_pins & EP93XX_SYSCON_DEVCFG_I2SONAC97))
-               return -EINVAL;
-
-       ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK);
-       ep93xx_devcfg_set_bits(i2s_pins);
+       ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_I2SONAC97,
+                       EP93XX_SYSCON_DEVCFG_I2S_MASK);
 
        /*
         * This is potentially racy with the clock api for i2s_mclk, sclk and 
@@ -843,7 +832,7 @@ int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config)
         */
        val = __raw_readl(EP93XX_SYSCON_I2SCLKDIV);
        val &= ~EP93XX_I2SCLKDIV_MASK;
-       val |= i2s_config;
+       val |= EP93XX_SYSCON_I2SCLKDIV_ORIDE | EP93XX_SYSCON_I2SCLKDIV_SPOL;
        ep93xx_syscon_swlocked_write(val, EP93XX_SYSCON_I2SCLKDIV);
 
        return 0;
index d4c934931f9d4cbf85c580355a0115f154ca241e..ad63d4be693fbfeca164a080a73e871118df2425 100644 (file)
@@ -59,7 +59,7 @@ void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data);
 int ep93xx_keypad_acquire_gpio(struct platform_device *pdev);
 void ep93xx_keypad_release_gpio(struct platform_device *pdev);
 void ep93xx_register_i2s(void);
-int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config);
+int ep93xx_i2s_acquire(void);
 void ep93xx_i2s_release(void);
 void ep93xx_register_ac97(void);
 
index 01f8c8992880450d1a69d861d718d63434133977..7e99c3f340fc5e61c85e7023afc9e345a5a130d8 100644 (file)
@@ -83,6 +83,11 @@ static struct i2c_board_info i2c_board_info[] __initdata = {
        },
 };
 
+static struct platform_device openrd_client_audio_device = {
+       .name           = "openrd-client-audio",
+       .id             = -1,
+};
+
 static int __initdata uart1;
 
 static int __init sd_uart_selection(char *str)
@@ -172,6 +177,7 @@ static void __init openrd_init(void)
        kirkwood_i2c_init();
 
        if (machine_is_openrd_client() || machine_is_openrd_ultimate()) {
+               platform_device_register(&openrd_client_audio_device);
                i2c_register_board_info(0, i2c_board_info,
                        ARRAY_SIZE(i2c_board_info));
                kirkwood_audio_init();
index 966b2b3bb8136a6e0ecb4b1a41190f10f379ba19..f9d2a11b7f9649468c26a882323df785e27783a0 100644 (file)
@@ -106,6 +106,11 @@ static struct platform_device hp_t5325_button_device = {
        }
 };
 
+static struct platform_device hp_t5325_audio_device = {
+       .name           = "t5325-audio",
+       .id             = -1,
+};
+
 static unsigned int hp_t5325_mpp_config[] __initdata = {
        MPP0_NF_IO2,
        MPP1_SPI_MOSI,
@@ -179,6 +184,7 @@ static void __init hp_t5325_init(void)
        kirkwood_sata_init(&hp_t5325_sata_data);
        kirkwood_ehci_init();
        platform_device_register(&hp_t5325_button_device);
+       platform_device_register(&hp_t5325_audio_device);
 
        i2c_register_board_info(0, i2c_board_info, ARRAY_SIZE(i2c_board_info));
        kirkwood_audio_init();
index cd3c97e2ee75045afb4a855f7adf03066bca478b..32a30f38ba0ce65d243a7d3f6cbeaa70bf08dbec 100644 (file)
@@ -102,6 +102,7 @@ static struct wm8962_pdata wm8962_pdata __initdata = {
                0x8000 | WM8962_GPIO_FN_DMICDAT,
                WM8962_GPIO_FN_IRQ,    /* Open drain mode */
        },
+       .in4_dc_measure = true,
 };
 
 static struct wm9081_pdata wm9081_pdata __initdata = {
index aab0a349f759baaa6469373270539cab35b9cee4..2ac08b29e2784153394b5a24b0a69175e2418a6d 100644 (file)
@@ -745,26 +745,18 @@ fsi_set_rate_end:
        return ret;
 }
 
-static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
-{
-       int ret;
-
-       if (is_porta)
-               ret = fsi_ak4642_set_rate(dev, rate, enable);
-       else
-               ret = fsi_hdmi_set_rate(dev, rate, enable);
-
-       return ret;
-}
-
 static struct sh_fsi_platform_info fsi_info = {
-       .porta_flags = SH_FSI_BRS_INV,
-
-       .portb_flags = SH_FSI_BRS_INV |
-                      SH_FSI_BRM_INV |
-                      SH_FSI_LRS_INV |
-                      SH_FSI_FMT_SPDIF,
-       .set_rate = fsi_set_rate,
+       .port_a = {
+               .flags          = SH_FSI_BRS_INV,
+               .set_rate       = fsi_ak4642_set_rate,
+       },
+       .port_b = {
+               .flags          = SH_FSI_BRS_INV |
+                                 SH_FSI_BRM_INV |
+                                 SH_FSI_LRS_INV |
+                                 SH_FSI_FMT_SPDIF,
+               .set_rate       = fsi_hdmi_set_rate,
+       },
 };
 
 static struct resource fsi_resources[] = {
index 9b42fbd10f8edf2873dbfba0bf6399305c8603db..28d6d1f9dad4bf69f9280586faf7335d6c14fd36 100644 (file)
@@ -901,7 +901,7 @@ static int __fsi_set_round_rate(struct clk *clk, long rate, int enable)
        return clk_enable(clk);
 }
 
-static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
+static int fsi_b_set_rate(struct device *dev, int rate, int enable)
 {
        struct clk *fsib_clk;
        struct clk *fdiv_clk = &sh7372_fsidivb_clk;
@@ -910,10 +910,6 @@ static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
        int ackmd_bpfmd;
        int ret;
 
-       /* FSIA is slave mode. nothing to do here */
-       if (is_porta)
-               return 0;
-
        /* clock start */
        switch (rate) {
        case 44100:
@@ -957,14 +953,16 @@ fsi_set_rate_end:
 }
 
 static struct sh_fsi_platform_info fsi_info = {
-       .porta_flags =  SH_FSI_BRS_INV,
-
-       .portb_flags =  SH_FSI_BRS_INV  |
+       .port_a = {
+               .flags = SH_FSI_BRS_INV,
+       },
+       .port_b = {
+               .flags = SH_FSI_BRS_INV |
                        SH_FSI_BRM_INV  |
                        SH_FSI_LRS_INV  |
                        SH_FSI_FMT_SPDIF,
-
-       .set_rate = fsi_set_rate,
+               .set_rate = fsi_b_set_rate,
+       }
 };
 
 static struct resource fsi_resources[] = {
index 639e3ce6c264d4f8af8137efffff5fdf280992cf..9a91fe9de69675ff1d74140bc658257637356090 100644 (file)
@@ -418,6 +418,11 @@ static struct platform_device qi_lb60_charger_device = {
        },
 };
 
+/* audio */
+static struct platform_device qi_lb60_audio_device = {
+       .name = "qi-lb60-audio",
+       .id = -1,
+};
 
 static struct platform_device *jz_platform_devices[] __initdata = {
        &jz4740_udc_device,
@@ -434,6 +439,7 @@ static struct platform_device *jz_platform_devices[] __initdata = {
        &qi_lb60_gpio_keys,
        &qi_lb60_pwm_beeper,
        &qi_lb60_charger_device,
+       &qi_lb60_audio_device,
 };
 
 static void __init board_gpio_setup(void)
index 033ef2ba621f008c5c92ac0dace7808a5b21035b..1e146fcdb8a0e6a619b39a29de1dad6fd811468f 100644 (file)
@@ -767,7 +767,9 @@ static struct platform_device camera_devices[] = {
 
 /* FSI */
 static struct sh_fsi_platform_info fsi_info = {
-       .portb_flags = SH_FSI_BRS_INV,
+       .port_b = {
+               .flags = SH_FSI_BRS_INV,
+       },
 };
 
 static struct resource fsi_resources[] = {
index 036fe1adaef17b4367259a71d59e3ba642f9f64a..1fc5d47a5687024a1048fd93d8d7c552a56bb4a4 100644 (file)
@@ -277,7 +277,9 @@ static struct platform_device ceu1_device = {
 /* FSI */
 /* change J20, J21, J22 pin to 1-2 connection to use slave mode */
 static struct sh_fsi_platform_info fsi_info = {
-       .porta_flags = SH_FSI_BRS_INV,
+       .port_a = {
+               .flags = SH_FSI_BRS_INV,
+       },
 };
 
 static struct resource fsi_resources[] = {
index 1a02b7537c8bbac9d59d21ee51c1361dd03c01c0..d141b80479b5257d9fff00b9be47e47029e0f163 100644 (file)
@@ -75,6 +75,9 @@ struct regmap {
        const void *reg_defaults_raw;
        void *cache;
        bool cache_dirty;
+
+       struct reg_default *patch;
+       int patch_regs;
 };
 
 struct regcache_ops {
index d1daa5e9fadf322b4a6e4d9e7f5d60e71eea0e40..5cd2a37e7688a3d7fec59d9a9a6d9f181107a6d3 100644 (file)
@@ -268,6 +268,17 @@ int regcache_sync(struct regmap *map)
                map->cache_ops->name);
        name = map->cache_ops->name;
        trace_regcache_sync(map->dev, name, "start");
+
+       /* Apply any patch first */
+       for (i = 0; i < map->patch_regs; i++) {
+               ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def);
+               if (ret != 0) {
+                       dev_err(map->dev, "Failed to write %x = %x: %d\n",
+                               map->patch[i].reg, map->patch[i].def, ret);
+                       goto out;
+               }
+       }
+
        if (!map->cache_dirty)
                goto out;
        if (map->cache_ops->sync) {
index 65558034318f3f295abde2fe7a599c4971e7d7ec..2cf4bbc5d30f4feb183bce09fbeaf3327e88c5fa 100644 (file)
@@ -672,6 +672,64 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
 }
 EXPORT_SYMBOL_GPL(regmap_update_bits_check);
 
+/**
+ * regmap_register_patch: Register and apply register updates to be applied
+ *                        on device initialistion
+ *
+ * @map: Register map to apply updates to.
+ * @regs: Values to update.
+ * @num_regs: Number of entries in regs.
+ *
+ * Register a set of register updates to be applied to the device
+ * whenever the device registers are synchronised with the cache and
+ * apply them immediately.  Typically this is used to apply
+ * corrections to be applied to the device defaults on startup, such
+ * as the updates some vendors provide to undocumented registers.
+ */
+int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
+                         int num_regs)
+{
+       int i, ret;
+       bool bypass;
+
+       /* If needed the implementation can be extended to support this */
+       if (map->patch)
+               return -EBUSY;
+
+       mutex_lock(&map->lock);
+
+       bypass = map->cache_bypass;
+
+       map->cache_bypass = true;
+
+       /* Write out first; it's useful to apply even if we fail later. */
+       for (i = 0; i < num_regs; i++) {
+               ret = _regmap_write(map, regs[i].reg, regs[i].def);
+               if (ret != 0) {
+                       dev_err(map->dev, "Failed to write %x = %x: %d\n",
+                               regs[i].reg, regs[i].def, ret);
+                       goto out;
+               }
+       }
+
+       map->patch = kcalloc(sizeof(struct reg_default), num_regs, GFP_KERNEL);
+       if (map->patch != NULL) {
+               memcpy(map->patch, regs,
+                      num_regs * sizeof(struct reg_default));
+               map->patch_regs = num_regs;
+       } else {
+               ret = -ENOMEM;
+       }
+
+out:
+       map->cache_bypass = bypass;
+
+       mutex_unlock(&map->lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_register_patch);
+
 static int __init regmap_initcall(void)
 {
        regmap_debugfs_initcall();
index e9a83f84adaf53771d94bd3b3761deb7cad2ca32..aa5186608aecee07009187433c071fc3d1178c72 100644 (file)
@@ -1320,6 +1320,40 @@ struct regulator *regulator_get(struct device *dev, const char *id)
 }
 EXPORT_SYMBOL_GPL(regulator_get);
 
+static void devm_regulator_release(struct device *dev, void *res)
+{
+       regulator_put(*(struct regulator **)res);
+}
+
+/**
+ * devm_regulator_get - Resource managed regulator_get()
+ * @dev: device for regulator "consumer"
+ * @id: Supply name or regulator ID.
+ *
+ * Managed regulator_get(). Regulators returned from this function are
+ * automatically regulator_put() on driver detach. See regulator_get() for more
+ * information.
+ */
+struct regulator *devm_regulator_get(struct device *dev, const char *id)
+{
+       struct regulator **ptr, *regulator;
+
+       ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       regulator = regulator_get(dev, id);
+       if (!IS_ERR(regulator)) {
+               *ptr = regulator;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return regulator;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_get);
+
 /**
  * regulator_get_exclusive - obtain exclusive access to a regulator.
  * @dev: device for regulator "consumer"
@@ -1387,6 +1421,34 @@ void regulator_put(struct regulator *regulator)
 }
 EXPORT_SYMBOL_GPL(regulator_put);
 
+static int devm_regulator_match(struct device *dev, void *res, void *data)
+{
+       struct regulator **r = res;
+       if (!r || !*r) {
+               WARN_ON(!r || !*r);
+               return 0;
+       }
+       return *r == data;
+}
+
+/**
+ * devm_regulator_put - Resource managed regulator_put()
+ * @regulator: regulator to free
+ *
+ * Deallocate a regulator allocated with devm_regulator_get(). Normally
+ * this function will not need to be called and the resource management
+ * code will ensure that the resource is freed.
+ */
+void devm_regulator_put(struct regulator *regulator)
+{
+       int rc;
+
+       rc = devres_destroy(regulator->dev, devm_regulator_release,
+                           devm_regulator_match, regulator);
+       WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_put);
+
 static int _regulator_can_change_status(struct regulator_dev *rdev)
 {
        if (!rdev->constraints)
@@ -2401,6 +2463,52 @@ err:
 }
 EXPORT_SYMBOL_GPL(regulator_bulk_get);
 
+/**
+ * devm_regulator_bulk_get - managed get multiple regulator consumers
+ *
+ * @dev:           Device to supply
+ * @num_consumers: Number of consumers to register
+ * @consumers:     Configuration of consumers; clients are stored here.
+ *
+ * @return 0 on success, an errno on failure.
+ *
+ * This helper function allows drivers to get several regulator
+ * consumers in one operation with management, the regulators will
+ * automatically be freed when the device is unbound.  If any of the
+ * regulators cannot be acquired then any regulators that were
+ * allocated will be freed before returning to the caller.
+ */
+int devm_regulator_bulk_get(struct device *dev, int num_consumers,
+                           struct regulator_bulk_data *consumers)
+{
+       int i;
+       int ret;
+
+       for (i = 0; i < num_consumers; i++)
+               consumers[i].consumer = NULL;
+
+       for (i = 0; i < num_consumers; i++) {
+               consumers[i].consumer = devm_regulator_get(dev,
+                                                          consumers[i].supply);
+               if (IS_ERR(consumers[i].consumer)) {
+                       ret = PTR_ERR(consumers[i].consumer);
+                       dev_err(dev, "Failed to get supply '%s': %d\n",
+                               consumers[i].supply, ret);
+                       consumers[i].consumer = NULL;
+                       goto err;
+               }
+       }
+
+       return 0;
+
+err:
+       for (i = 0; i < num_consumers && consumers[i].consumer; i++)
+               devm_regulator_put(consumers[i].consumer);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
+
 static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
 {
        struct regulator_bulk_data *bulk = data;
index eb93921cdd30252b1c960cf6872585e308c9e9fc..860739a8a6dde429d637e27202df78509342fb71 100644 (file)
@@ -149,6 +149,9 @@ void regcache_cache_only(struct regmap *map, bool enable);
 void regcache_cache_bypass(struct regmap *map, bool enable);
 void regcache_mark_dirty(struct regmap *map);
 
+int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
+                         int num_regs);
+
 /**
  * Description of an IRQ for the generic regmap irq_chip.
  *
index f2698a0edfc44486a95bd8379b1fa40dd56e1e70..35c42834ba3de03f0d5c18a1f73b09b125ee6bf8 100644 (file)
@@ -132,9 +132,12 @@ struct regulator_bulk_data {
 /* regulator get and put */
 struct regulator *__must_check regulator_get(struct device *dev,
                                             const char *id);
+struct regulator *__must_check devm_regulator_get(struct device *dev,
+                                            const char *id);
 struct regulator *__must_check regulator_get_exclusive(struct device *dev,
                                                       const char *id);
 void regulator_put(struct regulator *regulator);
+void devm_regulator_free(struct regulator *regulator);
 
 /* regulator output control and status */
 int regulator_enable(struct regulator *regulator);
@@ -145,6 +148,8 @@ int regulator_disable_deferred(struct regulator *regulator, int ms);
 
 int regulator_bulk_get(struct device *dev, int num_consumers,
                       struct regulator_bulk_data *consumers);
+int devm_regulator_bulk_get(struct device *dev, int num_consumers,
+                           struct regulator_bulk_data *consumers);
 int regulator_bulk_enable(int num_consumers,
                          struct regulator_bulk_data *consumers);
 int regulator_bulk_disable(int num_consumers,
@@ -200,6 +205,13 @@ static inline struct regulator *__must_check regulator_get(struct device *dev,
         */
        return NULL;
 }
+
+static inline struct regulator *__must_check
+devm_regulator_get(struct device *dev, const char *id)
+{
+       return NULL;
+}
+
 static inline void regulator_put(struct regulator *regulator)
 {
 }
index b2796e83c7acf3d1b4dd5bfacd76966a4c3eff4e..57815f6a02b95f64dfcf49aa5c68089b768724df 100644 (file)
@@ -40,7 +40,7 @@ struct snd_kcontrol_new {
        snd_ctl_elem_iface_t iface;     /* interface identifier */
        unsigned int device;            /* device/client number */
        unsigned int subdevice;         /* subdevice (substream) number */
-       unsigned char *name;            /* ASCII name of item */
+       const unsigned char *name;      /* ASCII name of item */
        unsigned int index;             /* index of item */
        unsigned int access;            /* access rights */
        unsigned int count;             /* count of same elements */
diff --git a/include/sound/max9768.h b/include/sound/max9768.h
new file mode 100644 (file)
index 0000000..0f78b41
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Platform data for MAX9768
+ * Copyright (C) 2011, 2012 by Wolfram Sang, Pengutronix e.K.
+ * same licence as the driver
+ */
+
+#ifndef __SOUND_MAX9768_PDATA_H__
+#define __SOUND_MAX9768_PDATA_H__
+
+/**
+ * struct max9768_pdata - optional platform specific MAX9768 configuration
+ * @shdn_gpio: GPIO to SHDN pin. If not valid, pin must be hardwired HIGH
+ * @mute_gpio: GPIO to MUTE pin. If not valid, control for mute won't be added
+ * @flags: configuration flags, e.g. set classic PWM mode (check datasheet
+ *         regarding "filterless modulation" which is default).
+ */
+struct max9768_pdata {
+       int shdn_gpio;
+       int mute_gpio;
+       unsigned flags;
+#define MAX9768_FLAG_CLASSIC_PWM       (1 << 0)
+};
+
+#endif /* __SOUND_MAX9768_PDATA_H__*/
index 0cf91b2f08caaf4f9a8a70cee07a25cacc108986..1d58d7957390568ffeed055d47b6991580398409 100644 (file)
@@ -454,6 +454,7 @@ struct snd_pcm {
        void *private_data;
        void (*private_free) (struct snd_pcm *pcm);
        struct device *dev; /* actual hw device this belongs to */
+       bool internal; /* pcm is for internal use only */
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
        struct snd_pcm_oss oss;
 #endif
@@ -475,6 +476,9 @@ extern const struct file_operations snd_pcm_f_ops[2];
 int snd_pcm_new(struct snd_card *card, const char *id, int device,
                int playback_count, int capture_count,
                struct snd_pcm **rpcm);
+int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
+               int playback_count, int capture_count,
+               struct snd_pcm **rpcm);
 int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count);
 
 int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree);
index 9b1aacaa82fedd0fcb63365fae33237627c496c9..78cd77aff1f4c6a9195496d4e57a3e55ec6c1496 100644 (file)
 #define SH_FSI_BPFMD_32                (5 << 4)
 #define SH_FSI_BPFMD_16                (6 << 4)
 
+struct sh_fsi_port_info {
+       unsigned long flags;
+       int (*set_rate)(struct device *dev, int rate, int enable);
+};
+
 struct sh_fsi_platform_info {
-       unsigned long porta_flags;
-       unsigned long portb_flags;
-       int (*set_rate)(struct device *dev, int is_porta, int rate, int enable);
+       struct sh_fsi_port_info port_a;
+       struct sh_fsi_port_info port_b;
 };
 
 /*
index 2413acc54883aad471cf0256b3fc2f8fc6d7ae11..adb07fcd712c162351a576c5a229fa3ebef438af 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/list.h>
 
 struct snd_pcm_substream;
+struct snd_soc_dapm_widget;
 
 /*
  * DAI hardware audio formats.
@@ -238,6 +239,9 @@ struct snd_soc_dai {
        unsigned char pop_wait:1;
        unsigned char probed:1;
 
+       struct snd_soc_dapm_widget *playback_widget;
+       struct snd_soc_dapm_widget *capture_widget;
+
        /* DAI DMA data */
        void *playback_dma_data;
        void *capture_dma_data;
index d26a9b784772d797e88a529f199342f277e32390..e46107fffeb48b8c5832eea797bb7ec2b69c92a0 100644 (file)
 {      .id = snd_soc_dapm_supply, .name = wname, .reg = wreg,  \
        .shift = wshift, .invert = winvert, .event = wevent, \
        .event_flags = wflags}
+#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay) \
+{      .id = snd_soc_dapm_regulator_supply, .name = wname, \
+       .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \
+       .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }
 
 /* dapm kcontrol types */
 #define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \
@@ -322,6 +326,8 @@ struct snd_soc_dapm_context;
 
 int dapm_reg_event(struct snd_soc_dapm_widget *w,
                   struct snd_kcontrol *kcontrol, int event);
+int dapm_regulator_event(struct snd_soc_dapm_widget *w,
+                        struct snd_kcontrol *kcontrol, int event);
 
 /* dapm controls */
 int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
@@ -346,11 +352,12 @@ int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *uncontrol);
 int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *uncontrol);
-int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
-       const struct snd_soc_dapm_widget *widget);
 int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
        const struct snd_soc_dapm_widget *widget,
        int num);
+int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
+                                struct snd_soc_dai *dai);
+int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card);
 
 /* dapm path setup */
 int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm);
@@ -361,10 +368,16 @@ int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm,
                             const struct snd_soc_dapm_route *route, int num);
 
 /* dapm events */
-int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
-       const char *stream, int event);
+int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
+                             struct snd_soc_dai *dai, int event);
 void snd_soc_dapm_shutdown(struct snd_soc_card *card);
 
+/* external DAPM widget events */
+int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
+               struct snd_kcontrol *kcontrol, int connect);
+int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
+                                struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e);
+
 /* dapm sys fs - used by the core */
 int snd_soc_dapm_sys_add(struct device *dev);
 void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
@@ -411,9 +424,11 @@ enum snd_soc_dapm_type {
        snd_soc_dapm_pre,                       /* machine specific pre widget - exec first */
        snd_soc_dapm_post,                      /* machine specific post widget - exec last */
        snd_soc_dapm_supply,            /* power/clock supply */
+       snd_soc_dapm_regulator_supply,  /* external regulator */
        snd_soc_dapm_aif_in,            /* audio interface input */
        snd_soc_dapm_aif_out,           /* audio interface output */
        snd_soc_dapm_siggen,            /* signal generator */
+       snd_soc_dapm_dai,               /* link to DAI structure */
 };
 
 /*
@@ -434,8 +449,8 @@ struct snd_soc_dapm_route {
 
 /* dapm audio path between two widgets */
 struct snd_soc_dapm_path {
-       char *name;
-       char *long_name;
+       const char *name;
+       const char *long_name;
 
        /* source (input) and sink (output) widgets */
        struct snd_soc_dapm_widget *source;
@@ -458,13 +473,15 @@ struct snd_soc_dapm_path {
 /* dapm widget */
 struct snd_soc_dapm_widget {
        enum snd_soc_dapm_type id;
-       char *name;             /* widget name */
-       char *sname;    /* stream name */
+       const char *name;               /* widget name */
+       const char *sname;      /* stream name */
        struct snd_soc_codec *codec;
        struct snd_soc_platform *platform;
        struct list_head list;
        struct snd_soc_dapm_context *dapm;
 
+       void *priv;                             /* widget specific data */
+
        /* dapm control */
        short reg;                                              /* negative reg = no direct dapm */
        unsigned char shift;                    /* bits to shift */
index 0992dff559593d7015fcef0e5a58dd42134539d6..1e16d6e3f2a8c7211698b73a94b5b097df7ed44b 100644 (file)
@@ -366,12 +366,16 @@ void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
  *Controls
  */
 struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
-                                 void *data, char *long_name,
+                                 void *data, const char *long_name,
                                  const char *prefix);
-int snd_soc_add_controls(struct snd_soc_codec *codec,
+int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
        const struct snd_kcontrol_new *controls, int num_controls);
 int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
        const struct snd_kcontrol_new *controls, int num_controls);
+int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
+       const struct snd_kcontrol_new *controls, int num_controls);
+int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
+       const struct snd_kcontrol_new *controls, int num_controls);
 int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_info *uinfo);
 int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
@@ -505,6 +509,7 @@ struct snd_soc_pcm_stream {
        unsigned int rate_max;          /* max rate */
        unsigned int channels_min;      /* min channels */
        unsigned int channels_max;      /* max channels */
+       unsigned int sig_bits;          /* number of bits of content */
 };
 
 /* SoC audio ops */
@@ -559,6 +564,7 @@ struct snd_soc_codec {
        unsigned int ac97_created:1; /* Codec has been created by SoC */
        unsigned int sysfs_registered:1; /* codec has been sysfs registered */
        unsigned int cache_init:1; /* codec cache has been initialized */
+       unsigned int using_regmap:1; /* using regmap access */
        u32 cache_only;  /* Suppress writes to hardware */
        u32 cache_sync; /* Cache needs to be synced to hardware */
 
@@ -637,6 +643,8 @@ struct snd_soc_codec_driver {
        /* codec stream completion event */
        int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
 
+       bool ignore_pmdown_time;  /* Doesn't benefit from pmdown delay */
+
        /* probe ordering - for components with runtime dependencies */
        int probe_order;
        int remove_order;
@@ -698,6 +706,11 @@ struct snd_soc_platform {
        struct list_head card_list;
 
        struct snd_soc_dapm_context dapm;
+
+#ifdef CONFIG_DEBUG_FS
+       struct dentry *debugfs_platform_root;
+       struct dentry *debugfs_dapm;
+#endif
 };
 
 struct snd_soc_dai_link {
diff --git a/include/sound/wm2200.h b/include/sound/wm2200.h
new file mode 100644 (file)
index 0000000..79bf55b
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * linux/sound/wm2200.h -- Platform data for WM2200
+ *
+ * Copyright 2012 Wolfson Microelectronics. PLC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_WM2200_H
+#define __LINUX_SND_WM2200_H
+
+#define WM2200_GPIO_SET 0x10000
+
+enum wm2200_in_mode {
+       WM2200_IN_SE = 0,
+       WM2200_IN_DIFF = 1,
+       WM2200_IN_DMIC = 2,
+};
+
+enum wm2200_dmic_sup {
+       WM2200_DMIC_SUP_MICVDD = 0,
+       WM2200_DMIC_SUP_MICBIAS1 = 1,
+       WM2200_DMIC_SUP_MICBIAS2 = 2,
+};
+
+struct wm2200_pdata {
+       int reset;      /** GPIO controlling /RESET, if any */
+       int ldo_ena;    /** GPIO controlling LODENA, if any */
+       int irq_flags;
+
+       int gpio_defaults[4];
+
+       enum wm2200_in_mode in_mode[3];
+       enum wm2200_dmic_sup dmic_sup[3];
+
+       int micbias_cfg[2];  /** Register value to configure MICBIAS */
+};
+
+#endif
index 1750bed7c2f6ed66d92152c089e810e0332b1251..79e6d427b8582b3f9460c25b5fc4fe4bcc086580 100644 (file)
@@ -49,6 +49,12 @@ struct wm8962_pdata {
        bool irq_active_low;
 
        bool spk_mono;   /* Speaker outputs tied together as mono */
+
+       /**
+        * This flag should be set if one or both IN4 inputs is wired
+        * in a DC measurement configuration.
+        */
+       bool in4_dc_measure;
 };
 
 #endif
index 8928ca871c223f17da58f086a75e3b52d1edcf11..6e4bfcc14254cda1c38eb294b9cfce564de76ada 100644 (file)
@@ -650,7 +650,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
        pstr->stream = stream;
        pstr->pcm = pcm;
        pstr->substream_count = substream_count;
-       if (substream_count > 0) {
+       if (substream_count > 0 && !pcm->internal) {
                err = snd_pcm_stream_proc_init(pstr);
                if (err < 0) {
                        snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
@@ -674,15 +674,18 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
                        pstr->substream = substream;
                else
                        prev->next = substream;
-               err = snd_pcm_substream_proc_init(substream);
-               if (err < 0) {
-                       snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
-                       if (prev == NULL)
-                               pstr->substream = NULL;
-                       else
-                               prev->next = NULL;
-                       kfree(substream);
-                       return err;
+
+               if (!pcm->internal) {
+                       err = snd_pcm_substream_proc_init(substream);
+                       if (err < 0) {
+                               snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
+                               if (prev == NULL)
+                                       pstr->substream = NULL;
+                               else
+                                       prev->next = NULL;
+                               kfree(substream);
+                               return err;
+                       }
                }
                substream->group = &substream->self_group;
                spin_lock_init(&substream->self_group.lock);
@@ -696,25 +699,9 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
 
 EXPORT_SYMBOL(snd_pcm_new_stream);
 
-/**
- * snd_pcm_new - create a new PCM instance
- * @card: the card instance
- * @id: the id string
- * @device: the device index (zero based)
- * @playback_count: the number of substreams for playback
- * @capture_count: the number of substreams for capture
- * @rpcm: the pointer to store the new pcm instance
- *
- * Creates a new PCM instance.
- *
- * The pcm operators have to be set afterwards to the new instance
- * via snd_pcm_set_ops().
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_new(struct snd_card *card, const char *id, int device,
-               int playback_count, int capture_count,
-               struct snd_pcm ** rpcm)
+static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
+               int playback_count, int capture_count, bool internal,
+               struct snd_pcm **rpcm)
 {
        struct snd_pcm *pcm;
        int err;
@@ -735,6 +722,7 @@ int snd_pcm_new(struct snd_card *card, const char *id, int device,
        }
        pcm->card = card;
        pcm->device = device;
+       pcm->internal = internal;
        if (id)
                strlcpy(pcm->id, id, sizeof(pcm->id));
        if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) {
@@ -756,8 +744,59 @@ int snd_pcm_new(struct snd_card *card, const char *id, int device,
        return 0;
 }
 
+/**
+ * snd_pcm_new - create a new PCM instance
+ * @card: the card instance
+ * @id: the id string
+ * @device: the device index (zero based)
+ * @playback_count: the number of substreams for playback
+ * @capture_count: the number of substreams for capture
+ * @rpcm: the pointer to store the new pcm instance
+ *
+ * Creates a new PCM instance.
+ *
+ * The pcm operators have to be set afterwards to the new instance
+ * via snd_pcm_set_ops().
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_new(struct snd_card *card, const char *id, int device,
+               int playback_count, int capture_count, struct snd_pcm **rpcm)
+{
+       return _snd_pcm_new(card, id, device, playback_count, capture_count,
+                       false, rpcm);
+}
 EXPORT_SYMBOL(snd_pcm_new);
 
+/**
+ * snd_pcm_new_internal - create a new internal PCM instance
+ * @card: the card instance
+ * @id: the id string
+ * @device: the device index (zero based - shared with normal PCMs)
+ * @playback_count: the number of substreams for playback
+ * @capture_count: the number of substreams for capture
+ * @rpcm: the pointer to store the new pcm instance
+ *
+ * Creates a new internal PCM instance with no userspace device or procfs
+ * entries. This is used by ASoC Back End PCMs in order to create a PCM that
+ * will only be used internally by kernel drivers. i.e. it cannot be opened
+ * by userspace. It provides existing ASoC components drivers with a substream
+ * and access to any private data.
+ *
+ * The pcm operators have to be set afterwards to the new instance
+ * via snd_pcm_set_ops().
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
+       int playback_count, int capture_count,
+       struct snd_pcm **rpcm)
+{
+       return _snd_pcm_new(card, id, device, playback_count, capture_count,
+                       true, rpcm);
+}
+EXPORT_SYMBOL(snd_pcm_new_internal);
+
 static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
 {
        struct snd_pcm_substream *substream, *substream_next;
@@ -994,7 +1033,7 @@ static int snd_pcm_dev_register(struct snd_device *device)
        }
        for (cidx = 0; cidx < 2; cidx++) {
                int devtype = -1;
-               if (pcm->streams[cidx].substream == NULL)
+               if (pcm->streams[cidx].substream == NULL || pcm->internal)
                        continue;
                switch (cidx) {
                case SNDRV_PCM_STREAM_PLAYBACK:
index a21ff459e5d3e0d53a6d50264c3f150dbaf6b0c9..9b84f985770ee4e09ca1d7a8ab04cbe410fda037 100644 (file)
@@ -362,7 +362,7 @@ static struct snd_pcm_ops atmel_pcm_ops = {
 /*--------------------------------------------------------------------------*\
  * ASoC platform driver
 \*--------------------------------------------------------------------------*/
-static u64 atmel_pcm_dmamask = 0xffffffff;
+static u64 atmel_pcm_dmamask = DMA_BIT_MASK(32);
 
 static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
@@ -373,7 +373,7 @@ static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
        if (!card->dev->dma_mask)
                card->dev->dma_mask = &atmel_pcm_dmamask;
        if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = 0xffffffff;
+               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = atmel_pcm_preallocate_dma_buffer(pcm,
index 4ca667d477f9f332e77a9ab60b0ce3805f4418ce..f65f08beac31487248139e594f16d5f51381e08b 100644 (file)
@@ -46,29 +46,8 @@ static int afeb9260_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int err;
 
-       /* Set codec DAI configuration */
-       err = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_I2S|
-                                 SND_SOC_DAIFMT_NB_IF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (err < 0) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return err;
-       }
-
-       /* Set cpu DAI configuration */
-       err = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_IF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (err < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return err;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        err =
            snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
@@ -91,7 +70,7 @@ static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
        SND_SOC_DAPM_MIC("Mic Jack", NULL),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route afeb9260_audio_map[] = {
        {"Headphone Jack", NULL, "LHPOUT"},
        {"Headphone Jack", NULL, "RHPOUT"},
 
@@ -106,13 +85,6 @@ static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
        struct snd_soc_codec *codec = rtd->codec;
        struct snd_soc_dapm_context *dapm = &codec->dapm;
 
-       /* Add afeb9260 specific widgets */
-       snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
-                                 ARRAY_SIZE(tlv320aic23_dapm_widgets));
-
-       /* Set up afeb9260 specific audio path audio_map */
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
        snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
        snd_soc_dapm_enable_pin(dapm, "Line In");
        snd_soc_dapm_enable_pin(dapm, "Mic Jack");
@@ -129,6 +101,8 @@ static struct snd_soc_dai_link afeb9260_dai = {
        .platform_name = "atmel_pcm-audio",
        .codec_name = "tlv320aic23-codec.0-001a",
        .init = afeb9260_tlv320aic23_init,
+       .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
+                  SND_SOC_DAIFMT_CBM_CFM,
        .ops = &afeb9260_ops,
 };
 
@@ -138,6 +112,11 @@ static struct snd_soc_card snd_soc_machine_afeb9260 = {
        .owner = THIS_MODULE,
        .dai_link = &afeb9260_dai,
        .num_links = 1,
+
+       .dapm_widgets = tlv320aic23_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
+       .dapm_routes = afeb9260_audio_map,
+       .num_dapm_routes = ARRAY_SIZE(afeb9260_audio_map),
 };
 
 static struct platform_device *afeb9260_snd_device;
index 60962ce6cd4d06c96536ca9ee124a8ac66e10467..d542d4063771a4daaec9048ad0b6aa0e4d640afb 100644 (file)
@@ -40,20 +40,8 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       struct snd_soc_dai *codec_dai = rtd->codec_dai;
        unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7};
        int ret = 0;
-       /* set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
-               SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0)
-               return ret;
-
-       /* set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
-               SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0)
-               return ret;
 
        /* set cpu DAI channel mapping */
        ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map),
@@ -68,6 +56,9 @@ static struct snd_soc_ops bf5xx_ad1836_ops = {
        .hw_params = bf5xx_ad1836_hw_params,
 };
 
+#define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \
+                               SND_SOC_DAIFMT_CBM_CFM)
+
 static struct snd_soc_dai_link bf5xx_ad1836_dai[] = {
        {
                .name = "ad1836",
@@ -77,6 +68,7 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai[] = {
                .platform_name = "bfin-tdm-pcm-audio",
                .codec_name = "spi0.4",
                .ops = &bf5xx_ad1836_ops,
+               .dai_fmt = BF5XX_AD1836_DAIFMT,
        },
        {
                .name = "ad1836",
@@ -86,6 +78,7 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai[] = {
                .platform_name = "bfin-tdm-pcm-audio",
                .codec_name = "spi0.4",
                .ops = &bf5xx_ad1836_ops,
+               .dai_fmt = BF5XX_AD1836_DAIFMT,
        },
 };
 
index 2d8d82dbc159ef6326b553e8ce2916fd0c1e771f..0e55e9f2a514df69473365a7222d93908ea1bdcd 100644 (file)
@@ -60,18 +60,6 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
                break;
        }
 
-       /* set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
-               SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0)
-               return ret;
-
-       /* set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
-               SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0)
-               return ret;
-
        /* set the codec system clock for DAC and ADC */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk,
                SND_SOC_CLOCK_IN);
@@ -92,6 +80,9 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
+#define BF5XX_AD193X_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \
+                               SND_SOC_DAIFMT_CBM_CFM)
+
 static struct snd_soc_ops bf5xx_ad193x_ops = {
        .hw_params = bf5xx_ad193x_hw_params,
 };
@@ -105,6 +96,7 @@ static struct snd_soc_dai_link bf5xx_ad193x_dai[] = {
                .platform_name = "bfin-tdm-pcm-audio",
                .codec_name = "spi0.5",
                .ops = &bf5xx_ad193x_ops,
+               .dai_fmt = BF5XX_AD193X_DAIFMT,
        },
        {
                .name = "ad193x",
@@ -114,6 +106,7 @@ static struct snd_soc_dai_link bf5xx_ad193x_dai[] = {
                .platform_name = "bfin-tdm-pcm-audio",
                .codec_name = "spi0.5",
                .ops = &bf5xx_ad193x_ops,
+               .dai_fmt = BF5XX_AD193X_DAIFMT,
        },
 };
 
index 8e49508596dad59911ab3ac3c4ae1baa006cc678..61cc91d4a028f8916d9c48adf0d14df2406368e2 100644 (file)
@@ -145,29 +145,8 @@ static int bf5xx_probe(struct snd_soc_card *card)
        return 0;
 }
 
-static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream,
-       struct snd_pcm_hw_params *params)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       int ret = 0;
-
-       pr_debug("%s rate %d format %x\n", __func__, params_rate(params),
-               params_format(params));
-
-       /* set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
-               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-
-static struct snd_soc_ops bf5xx_ad73311_ops = {
-       .hw_params = bf5xx_ad73311_hw_params,
-};
+#define BF5XX_AD7311_DAI_FMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | \
+                               SND_SOC_DAIFMT_CBM_CFM)
 
 static struct snd_soc_dai_link bf5xx_ad73311_dai[] = {
        {
@@ -177,7 +156,7 @@ static struct snd_soc_dai_link bf5xx_ad73311_dai[] = {
                .codec_dai_name = "ad73311-hifi",
                .platform_name = "bfin-i2s-pcm-audio",
                .codec_name = "ad73311",
-               .ops = &bf5xx_ad73311_ops,
+               .dai_fmt = BF5XX_AD7311_DAI_FMT,
        },
        {
                .name = "ad73311",
@@ -186,7 +165,7 @@ static struct snd_soc_dai_link bf5xx_ad73311_dai[] = {
                .codec_dai_name = "ad73311-hifi",
                .platform_name = "bfin-i2s-pcm-audio",
                .codec_name = "ad73311",
-               .ops = &bf5xx_ad73311_ops,
+               .dai_fmt = BF5XX_AD7311_DAI_FMT,
        },
 };
 
index 0303032380420eb7bd12d198ca4be3f5ea684149..df3ac73f8778288d6666e29728e6136b44630827 100644 (file)
@@ -49,7 +49,6 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        unsigned int clk = 0;
        int ret = 0;
 
@@ -75,21 +74,6 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
                break;
        }
 
-       /*
-        * CODEC is master for BCLK and LRC in this configuration.
-        */
-
-       /* set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0)
-               return ret;
-       /* set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0)
-               return ret;
-
        ret = snd_soc_dai_set_sysclk(codec_dai, SSM2602_SYSCLK, clk,
                SND_SOC_CLOCK_IN);
        if (ret < 0)
@@ -102,6 +86,10 @@ static struct snd_soc_ops bf5xx_ssm2602_ops = {
        .hw_params = bf5xx_ssm2602_hw_params,
 };
 
+/* CODEC is master for BCLK and LRC in this configuration. */
+#define BF5XX_SSM2602_DAIFMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \
+                               SND_SOC_DAIFMT_CBM_CFM)
+
 static struct snd_soc_dai_link bf5xx_ssm2602_dai[] = {
        {
                .name = "ssm2602",
index 26b271c62efa392825f95c64c627fc7fc63d1a68..f3adbdbdd5e1a0a96f93caf305c6ba0a74619e2d 100644 (file)
@@ -67,21 +67,10 @@ static int bfin_eval_adau1373_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
        int ret;
        int pll_rate;
 
-       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-                       SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret)
-               return ret;
-
-       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-                       SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret)
-               return ret;
-
        switch (params_rate(params)) {
        case 48000:
        case 8000:
@@ -143,6 +132,8 @@ static struct snd_soc_dai_link bfin_eval_adau1373_dai = {
        .codec_name = "adau1373.0-001a",
        .ops = &bfin_eval_adau1373_ops,
        .init = bfin_eval_adau1373_codec_init,
+       .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                       SND_SOC_DAIFMT_CBM_CFM,
 };
 
 static struct snd_soc_card bfin_eval_adau1373 = {
index c0064fa1dca653c7395062b5ee0076b5f24fbce2..b0531fc9d814058409b5cf585e99eaf0e3f7352d 100644 (file)
@@ -37,20 +37,9 @@ static int bfin_eval_adau1701_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
        int ret;
 
-       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-                       SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret)
-               return ret;
-
-       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-                       SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret)
-               return ret;
-
        ret = snd_soc_dai_set_sysclk(codec_dai, ADAU1701_CLK_SRC_OSC, 12288000,
                        SND_SOC_CLOCK_IN);
 
@@ -61,6 +50,9 @@ static struct snd_soc_ops bfin_eval_adau1701_ops = {
        .hw_params = bfin_eval_adau1701_hw_params,
 };
 
+#define BFIN_EVAL_ADAU1701_DAI_FMT (SND_SOC_DAIFMT_I2S | \
+                               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM)
+
 static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = {
        {
                .name = "adau1701",
@@ -70,6 +62,7 @@ static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = {
                .platform_name = "bfin-i2s-pcm-audio",
                .codec_name = "adau1701.0-0034",
                .ops = &bfin_eval_adau1701_ops,
+               .dai_fmt = BFIN_EVAL_ADAU1701_DAI_FMT,
        },
        {
                .name = "adau1701",
@@ -79,6 +72,7 @@ static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = {
                .platform_name = "bfin-i2s-pcm-audio",
                .codec_name = "adau1701.0-0034",
                .ops = &bfin_eval_adau1701_ops,
+               .dai_fmt = BFIN_EVAL_ADAU1701_DAI_FMT,
        },
 };
 
index 4ef079f95e2ede670a97f782fad67e573a516eed..84b09987b7f319cbaf01e2cb05be11c666404280 100644 (file)
@@ -34,20 +34,9 @@ static int bfin_eval_adav80x_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
        int ret;
 
-       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-                       SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret)
-               return ret;
-
-       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-                       SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret)
-               return ret;
-
        ret = snd_soc_dai_set_pll(codec_dai, ADAV80X_PLL1, ADAV80X_PLL_SRC_XTAL,
                        27000000, params_rate(params) * 256);
        if (ret)
@@ -88,6 +77,8 @@ static struct snd_soc_dai_link bfin_eval_adav80x_dais[] = {
                .platform_name = "bfin-i2s-pcm-audio",
                .init = bfin_eval_adav80x_codec_init,
                .ops = &bfin_eval_adav80x_ops,
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                               SND_SOC_DAIFMT_CBM_CFM,
        },
 };
 
index 7c205e77d83aa8af2439955b56cecc9fc1e7419b..6508e8b790bb16076d3539261db7df43032438e4 100644 (file)
@@ -40,6 +40,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_MAX98088 if I2C
        select SND_SOC_MAX98095 if I2C
        select SND_SOC_MAX9850 if I2C
+       select SND_SOC_MAX9768 if I2C
        select SND_SOC_MAX9877 if I2C
        select SND_SOC_PCM3008
        select SND_SOC_RT5631 if I2C
@@ -62,6 +63,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_WL1273 if MFD_WL1273_CORE
        select SND_SOC_WM1250_EV1 if I2C
        select SND_SOC_WM2000 if I2C
+       select SND_SOC_WM2200 if I2C
        select SND_SOC_WM5100 if I2C
        select SND_SOC_WM8350 if MFD_WM8350
        select SND_SOC_WM8400 if MFD_WM8400
@@ -292,6 +294,9 @@ config SND_SOC_WM1250_EV1
 config SND_SOC_WM2000
        tristate
 
+config SND_SOC_WM2200
+       tristate
+
 config SND_SOC_WM5100
        tristate
 
@@ -425,6 +430,9 @@ config SND_SOC_WM9713
 config SND_SOC_LM4857
        tristate
 
+config SND_SOC_MAX9768
+       tristate
+
 config SND_SOC_MAX9877
        tristate
 
index de8078178f86be523f75071207a776c6ff2b4657..6662eb0cdcc0724f2364760a15730346278267ab 100644 (file)
@@ -25,6 +25,7 @@ snd-soc-dmic-objs := dmic.o
 snd-soc-jz4740-codec-objs := jz4740.o
 snd-soc-l3-objs := l3.o
 snd-soc-lm4857-objs := lm4857.o
+snd-soc-max9768-objs := max9768.o
 snd-soc-max98088-objs := max98088.o
 snd-soc-max98095-objs := max98095.o
 snd-soc-max9850-objs := max9850.o
@@ -51,6 +52,7 @@ snd-soc-uda1380-objs := uda1380.o
 snd-soc-wl1273-objs := wl1273.o
 snd-soc-wm1250-ev1-objs := wm1250-ev1.o
 snd-soc-wm2000-objs := wm2000.o
+snd-soc-wm2200-objs := wm2200.o
 snd-soc-wm5100-objs := wm5100.o wm5100-tables.o
 snd-soc-wm8350-objs := wm8350.o
 snd-soc-wm8400-objs := wm8400.o
@@ -129,6 +131,7 @@ obj-$(CONFIG_SND_SOC_DMIC)  += snd-soc-dmic.o
 obj-$(CONFIG_SND_SOC_L3)       += snd-soc-l3.o
 obj-$(CONFIG_SND_SOC_LM4857)   += snd-soc-lm4857.o
 obj-$(CONFIG_SND_SOC_JZ4740_CODEC)     += snd-soc-jz4740-codec.o
+obj-$(CONFIG_SND_SOC_MAX9768)  += snd-soc-max9768.o
 obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
 obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
 obj-$(CONFIG_SND_SOC_MAX9850)  += snd-soc-max9850.o
@@ -153,6 +156,7 @@ obj-$(CONFIG_SND_SOC_UDA1380)       += snd-soc-uda1380.o
 obj-$(CONFIG_SND_SOC_WL1273)   += snd-soc-wl1273.o
 obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
 obj-$(CONFIG_SND_SOC_WM2000)   += snd-soc-wm2000.o
+obj-$(CONFIG_SND_SOC_WM2200)   += snd-soc-wm2200.o
 obj-$(CONFIG_SND_SOC_WM5100)   += snd-soc-wm5100.o
 obj-$(CONFIG_SND_SOC_WM8350)   += snd-soc-wm8350.o
 obj-$(CONFIG_SND_SOC_WM8400)   += snd-soc-wm8400.o
index 982d201c2e8699589ab049544e517d2f69db3678..12e3b4118557388b5cbb1a62fc0dea3264ba082f 100644 (file)
@@ -277,7 +277,7 @@ static int ad1836_probe(struct snd_soc_codec *codec)
        if (ad1836->type == AD1836) {
                /* left/right diff:PGA/MUX */
                snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A);
-               ret = snd_soc_add_controls(codec, ad1836_controls,
+               ret = snd_soc_add_codec_controls(codec, ad1836_controls,
                                ARRAY_SIZE(ad1836_controls));
                if (ret)
                        return ret;
@@ -285,11 +285,11 @@ static int ad1836_probe(struct snd_soc_codec *codec)
                snd_soc_write(codec, AD1836_ADC_CTRL3, 0x00);
        }
 
-       ret = snd_soc_add_controls(codec, ad183x_dac_controls, num_dacs * 2);
+       ret = snd_soc_add_codec_controls(codec, ad183x_dac_controls, num_dacs * 2);
        if (ret)
                return ret;
 
-       ret = snd_soc_add_controls(codec, ad183x_adc_controls, num_adcs);
+       ret = snd_soc_add_codec_controls(codec, ad183x_adc_controls, num_adcs);
        if (ret)
                return ret;
 
index 9bba7f849464391778e5c33f0076c0e20b3ea44f..8c39dddd7d0063d90adcf587c5e6dc19c37f73ad 100644 (file)
@@ -228,7 +228,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)
        ext_status = ac97_read(codec, AC97_EXTENDED_STATUS);
        ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800);
 
-       snd_soc_add_controls(codec, ad1980_snd_ac97_controls,
+       snd_soc_add_codec_controls(codec, ad1980_snd_ac97_controls,
                                ARRAY_SIZE(ad1980_snd_ac97_controls));
 
        return 0;
index 971ba45291717d9c9c87dc662b07b23deb2b55a2..44f59064d8de11247187a8d124661361e7913e65 100644 (file)
@@ -1244,8 +1244,6 @@ static int adau1373_probe(struct snd_soc_codec *codec)
                return ret;
        }
 
-       codec->dapm.idle_bias_off = true;
-
        if (pdata) {
                if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting))
                        return -EINVAL;
@@ -1259,7 +1257,7 @@ static int adau1373_probe(struct snd_soc_codec *codec)
                                pdata->drc_setting[i]);
                }
 
-               snd_soc_add_controls(codec, adau1373_drc_controls,
+               snd_soc_add_codec_controls(codec, adau1373_drc_controls,
                        pdata->num_drc);
 
                val = 0;
@@ -1284,7 +1282,7 @@ static int adau1373_probe(struct snd_soc_codec *codec)
        }
 
        if (!lineout_differential) {
-               snd_soc_add_controls(codec, adau1373_lineout2_controls,
+               snd_soc_add_codec_controls(codec, adau1373_lineout2_controls,
                        ARRAY_SIZE(adau1373_lineout2_controls));
        }
 
@@ -1340,6 +1338,7 @@ static struct snd_soc_codec_driver adau1373_codec_driver = {
        .suspend =      adau1373_suspend,
        .resume =       adau1373_resume,
        .set_bias_level = adau1373_set_bias_level,
+       .idle_bias_off = true,
        .reg_cache_size = ARRAY_SIZE(adau1373_default_regs),
        .reg_cache_default = adau1373_default_regs,
        .reg_word_size = sizeof(uint8_t),
index 6b325ea03869f4758247cec758c96ed71ab60b7e..78e9ce48bb99e6402987a0083d124219bd3400f7 100644 (file)
@@ -457,7 +457,6 @@ static int adau1701_probe(struct snd_soc_codec *codec)
 {
        int ret;
 
-       codec->dapm.idle_bias_off = 1;
        codec->control_data = to_i2c_client(codec->dev);
 
        ret = adau1701_load_firmware(codec);
@@ -473,6 +472,7 @@ static int adau1701_probe(struct snd_soc_codec *codec)
 static struct snd_soc_codec_driver adau1701_codec_drv = {
        .probe                  = adau1701_probe,
        .set_bias_level         = adau1701_set_bias_level,
+       .idle_bias_off          = true,
 
        .reg_cache_size         = ADAU1701_NUM_REGS,
        .reg_word_size          = sizeof(u16),
index 9e809e05d06644aa52fb11bf4ad96867c5c63aef..838ae8b22b500f8461f2baa151f4164d303ec85d 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 
 #include "ak4535.h"
 
-#define AK4535_VERSION "0.3"
-
 /* codec private data */
 struct ak4535_priv {
+       struct regmap *regmap;
        unsigned int sysclk;
-       enum snd_soc_control_type control_type;
 };
 
 /*
  * ak4535 register cache
  */
-static const u8 ak4535_reg[AK4535_CACHEREGNUM] = {
-       0x00, 0x80, 0x00, 0x03,
-       0x02, 0x00, 0x11, 0x01,
-       0x00, 0x40, 0x36, 0x10,
-       0x00, 0x00, 0x57, 0x00,
+static const struct reg_default ak4535_reg_defaults[] = {
+       { 0, 0x00 },
+       { 1, 0x80 },
+       { 2, 0x00 },
+       { 3, 0x03 },
+       { 4, 0x02 },
+       { 5, 0x00 },
+       { 6, 0x11 },
+       { 7, 0x01 },
+       { 8, 0x00 },
+       { 9, 0x40 },
+       { 10, 0x36 },
+       { 11, 0x10 },
+       { 12, 0x00 },
+       { 13, 0x00 },
+       { 14, 0x57 },
 };
 
+static bool ak4535_volatile(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case AK4535_STATUS:
+               return true;
+       default:
+               return false;
+       }
+}
+
 static const char *ak4535_mono_gain[] = {"+6dB", "-17dB"};
 static const char *ak4535_mono_out[] = {"(L + R)/2", "Hi-Z"};
 static const char *ak4535_hp_out[] = {"Stereo", "Mono"};
@@ -372,9 +392,8 @@ static int ak4535_probe(struct snd_soc_codec *codec)
        struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
-       printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
-
-       ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4535->control_type);
+       codec->control_data = ak4535->regmap;
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
@@ -382,7 +401,7 @@ static int ak4535_probe(struct snd_soc_codec *codec)
        /* power on device */
        ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       snd_soc_add_controls(codec, ak4535_snd_controls,
+       snd_soc_add_codec_controls(codec, ak4535_snd_controls,
                                ARRAY_SIZE(ak4535_snd_controls));
        return 0;
 }
@@ -394,22 +413,30 @@ static int ak4535_remove(struct snd_soc_codec *codec)
        return 0;
 }
 
+static const struct regmap_config ak4535_regmap = {
+       .reg_bits = 8,
+       .val_bits = 8,
+
+       .max_register = AK4535_STATUS,
+       .volatile_reg = ak4535_volatile,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = ak4535_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(ak4535_reg_defaults),
+};
+
 static struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
        .probe =        ak4535_probe,
        .remove =       ak4535_remove,
        .suspend =      ak4535_suspend,
        .resume =       ak4535_resume,
        .set_bias_level = ak4535_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(ak4535_reg),
-       .reg_word_size = sizeof(u8),
-       .reg_cache_default = ak4535_reg,
        .dapm_widgets = ak4535_dapm_widgets,
        .num_dapm_widgets = ARRAY_SIZE(ak4535_dapm_widgets),
        .dapm_routes = ak4535_audio_map,
        .num_dapm_routes = ARRAY_SIZE(ak4535_audio_map),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
@@ -421,17 +448,29 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
        if (ak4535 == NULL)
                return -ENOMEM;
 
+       ak4535->regmap = regmap_init_i2c(i2c, &ak4535_regmap);
+       if (IS_ERR(ak4535->regmap)) {
+               ret = PTR_ERR(ak4535->regmap);
+               dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
+               return ret;
+       }
+
        i2c_set_clientdata(i2c, ak4535);
-       ak4535->control_type = SND_SOC_I2C;
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_ak4535, &ak4535_dai, 1);
+       if (ret != 0)
+               regmap_exit(ak4535->regmap);
+
        return ret;
 }
 
 static __devexit int ak4535_i2c_remove(struct i2c_client *client)
 {
+       struct ak4535_priv *ak4535 = i2c_get_clientdata(client);
+
        snd_soc_unregister_codec(&client->dev);
+       regmap_exit(ak4535->regmap);
        return 0;
 }
 
@@ -443,36 +482,15 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id);
 
 static struct i2c_driver ak4535_i2c_driver = {
        .driver = {
-               .name = "ak4535-codec",
+               .name = "ak4535",
                .owner = THIS_MODULE,
        },
        .probe =    ak4535_i2c_probe,
        .remove =   __devexit_p(ak4535_i2c_remove),
        .id_table = ak4535_i2c_id,
 };
-#endif
 
-static int __init ak4535_modinit(void)
-{
-       int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       ret = i2c_add_driver(&ak4535_i2c_driver);
-       if (ret != 0) {
-               printk(KERN_ERR "Failed to register AK4535 I2C driver: %d\n",
-                      ret);
-       }
-#endif
-       return ret;
-}
-module_init(ak4535_modinit);
-
-static void __exit ak4535_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       i2c_del_driver(&ak4535_i2c_driver);
-#endif
-}
-module_exit(ak4535_exit);
+module_i2c_driver(ak4535_i2c_driver);
 
 MODULE_DESCRIPTION("Soc AK4535 driver");
 MODULE_AUTHOR("Richard Purdie");
index 0431e5f634a2440c8ef9f0206fe1c0959a6cd553..402de1d274bf8ac426b07c84fe2dde4d8f06250f 100644 (file)
@@ -34,6 +34,4 @@
 #define AK4535_VOL             0xe
 #define AK4535_STATUS          0xf
 
-#define AK4535_CACHEREGNUM     0x10
-
 #endif
index 5ef70b5d27e4eae85f6e4e1a1c310ea273e0eb60..16bd1e7d2384f8115b2bf2f02c19ceb4143d9ee1 100644 (file)
@@ -476,7 +476,7 @@ static int ak4642_probe(struct snd_soc_codec *codec)
                return ret;
        }
 
-       snd_soc_add_controls(codec, ak4642_snd_controls,
+       snd_soc_add_codec_controls(codec, ak4642_snd_controls,
                             ARRAY_SIZE(ak4642_snd_controls));
 
        ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
index a53b152e6a07a529fc4e1298fc33bc4ccb3abdb2..5fb7c2a80e6daa5e8e68948a09b95a852fba778e 100644 (file)
@@ -628,7 +628,7 @@ static int ak4671_probe(struct snd_soc_codec *codec)
                return ret;
        }
 
-       snd_soc_add_controls(codec, ak4671_snd_controls,
+       snd_soc_add_codec_controls(codec, ak4671_snd_controls,
                             ARRAY_SIZE(ak4671_snd_controls));
 
        ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
index 3feee569ceea1bacab11ac78ad6b83bbf01bab7b..d47b62ddb210dbf68b5eeb4b4e0dc4abadc5556d 100644 (file)
@@ -925,22 +925,22 @@ static int alc5623_probe(struct snd_soc_codec *codec)
 
        switch (alc5623->id) {
        case 0x21:
-               snd_soc_add_controls(codec, alc5621_vol_snd_controls,
+               snd_soc_add_codec_controls(codec, alc5621_vol_snd_controls,
                        ARRAY_SIZE(alc5621_vol_snd_controls));
                break;
        case 0x22:
-               snd_soc_add_controls(codec, alc5622_vol_snd_controls,
+               snd_soc_add_codec_controls(codec, alc5622_vol_snd_controls,
                        ARRAY_SIZE(alc5622_vol_snd_controls));
                break;
        case 0x23:
-               snd_soc_add_controls(codec, alc5623_vol_snd_controls,
+               snd_soc_add_codec_controls(codec, alc5623_vol_snd_controls,
                        ARRAY_SIZE(alc5623_vol_snd_controls));
                break;
        default:
                return -EINVAL;
        }
 
-       snd_soc_add_controls(codec, alc5623_snd_controls,
+       snd_soc_add_codec_controls(codec, alc5623_snd_controls,
                        ARRAY_SIZE(alc5623_snd_controls));
 
        snd_soc_dapm_new_controls(dapm, alc5623_dapm_widgets,
@@ -992,7 +992,7 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
  *    low  = 0x1a
  *    high = 0x1b
  */
-static int alc5623_i2c_probe(struct i2c_client *client,
+static __devinit int alc5623_i2c_probe(struct i2c_client *client,
                                const struct i2c_device_id *id)
 {
        struct alc5623_platform_data *pdata;
@@ -1059,7 +1059,7 @@ static int alc5623_i2c_probe(struct i2c_client *client,
        return ret;
 }
 
-static int alc5623_i2c_remove(struct i2c_client *client)
+static __devexit int alc5623_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
        return 0;
index 390e437d7c5e08ef75a8406b5572f245d90eaaeb..e2111e0ccad7eedad086e5bc791d690f86388a15 100644 (file)
@@ -145,15 +145,14 @@ static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0);
 /* -16.5db min scale, 1.5db steps, no mute */
 static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0);
 static const unsigned int boost_tlv[] = {
-       TLV_DB_RANGE_HEAD(3),
-       0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
-       1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
-       2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
+       TLV_DB_RANGE_HEAD(2),
+       0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0),
+       1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0),
 };
 /* 0db min scale, 6 db steps, no mute */
 static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0);
 /* 0db min scalem 0.75db steps, no mute */
-static const DECLARE_TLV_DB_SCALE(vdac_tlv, -3525, 075, 0);
+static const DECLARE_TLV_DB_SCALE(vdac_tlv, -3525, 75, 0);
 
 static const struct snd_kcontrol_new alc5632_vol_snd_controls[] = {
        /* left starts at bit 8, right at bit 0 */
@@ -176,26 +175,32 @@ static const struct snd_kcontrol_new alc5632_snd_controls[] = {
                        ALC5632_AUX_OUT_VOL, 15, 7, 1, 1),
        SOC_SINGLE_TLV("Voice DAC Playback Volume",
                        ALC5632_VOICE_DAC_VOL, 0, 63, 0, vdac_tlv),
-       SOC_SINGLE_TLV("Phone Capture Volume",
+       SOC_SINGLE("Voice DAC Playback Switch",
+                       ALC5632_VOICE_DAC_VOL, 12, 1, 1),
+       SOC_SINGLE_TLV("Phone Playback Volume",
                        ALC5632_PHONE_IN_VOL, 8, 31, 1, vol_tlv),
-       SOC_DOUBLE_TLV("LineIn Capture Volume",
+       SOC_DOUBLE_TLV("LineIn Playback Volume",
                        ALC5632_LINE_IN_VOL, 8, 0, 31, 1, vol_tlv),
        SOC_DOUBLE_TLV("Master Playback Volume",
                        ALC5632_STEREO_DAC_IN_VOL, 8, 0, 63, 1, vdac_tlv),
        SOC_DOUBLE("Master Playback Switch",
                        ALC5632_STEREO_DAC_IN_VOL, 15, 7, 1, 1),
-       SOC_SINGLE_TLV("Mic1 Capture Volume",
+       SOC_SINGLE_TLV("Mic1 Playback Volume",
                        ALC5632_MIC_VOL, 8, 31, 1, vol_tlv),
-       SOC_SINGLE_TLV("Mic2 Capture Volume",
+       SOC_SINGLE_TLV("Mic2 Playback Volume",
                        ALC5632_MIC_VOL, 0, 31, 1, vol_tlv),
        SOC_DOUBLE_TLV("Rec Capture Volume",
                        ALC5632_ADC_REC_GAIN, 8, 0, 31, 0, adc_rec_tlv),
        SOC_SINGLE_TLV("Mic 1 Boost Volume",
-                       ALC5632_MIC_CTRL, 10, 2, 0, boost_tlv),
+                       ALC5632_MIC_CTRL, 10, 3, 0, boost_tlv),
        SOC_SINGLE_TLV("Mic 2 Boost Volume",
-                       ALC5632_MIC_CTRL, 8, 2, 0, boost_tlv),
-       SOC_SINGLE_TLV("Digital Boost Volume",
+                       ALC5632_MIC_CTRL, 8, 3, 0, boost_tlv),
+       SOC_SINGLE_TLV("DMIC Boost Capture Volume",
                        ALC5632_DIGI_BOOST_CTRL, 0, 7, 0, dig_tlv),
+       SOC_SINGLE("DMIC En Capture Switch",
+                       ALC5632_DIGI_BOOST_CTRL, 15, 1, 0),
+       SOC_SINGLE("DMIC PreFilter Capture Switch",
+                       ALC5632_DIGI_BOOST_CTRL, 12, 1, 0),
 };
 
 /*
@@ -244,36 +249,48 @@ SOC_DAPM_SINGLE("VOICE2SPK Playback Switch", ALC5632_VOICE_DAC_VOL, 14, 1, 1),
 
 /* Left Record Mixer */
 static const struct snd_kcontrol_new alc5632_captureL_mixer_controls[] = {
-SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5632_ADC_REC_MIXER, 14, 1, 1),
-SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5632_ADC_REC_MIXER, 13, 1, 1),
-SOC_DAPM_SINGLE("LineInL Capture Switch", ALC5632_ADC_REC_MIXER, 12, 1, 1),
-SOC_DAPM_SINGLE("Left Phone Capture Switch", ALC5632_ADC_REC_MIXER, 11, 1, 1),
-SOC_DAPM_SINGLE("HPMixerL Capture Switch", ALC5632_ADC_REC_MIXER, 10, 1, 1),
-SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5632_ADC_REC_MIXER, 9, 1, 1),
-SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5632_ADC_REC_MIXER, 8, 1, 1),
+SOC_DAPM_SINGLE("MIC12REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 14, 1, 1),
+SOC_DAPM_SINGLE("MIC22REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 13, 1, 1),
+SOC_DAPM_SINGLE("LIL2REC Capture Switch", ALC5632_ADC_REC_MIXER, 12, 1, 1),
+SOC_DAPM_SINGLE("PH2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 11, 1, 1),
+SOC_DAPM_SINGLE("HPL2REC Capture Switch", ALC5632_ADC_REC_MIXER, 10, 1, 1),
+SOC_DAPM_SINGLE("SPK2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 9, 1, 1),
+SOC_DAPM_SINGLE("MONO2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 8, 1, 1),
 };
 
 /* Right Record Mixer */
 static const struct snd_kcontrol_new alc5632_captureR_mixer_controls[] = {
-SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5632_ADC_REC_MIXER, 6, 1, 1),
-SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5632_ADC_REC_MIXER, 5, 1, 1),
-SOC_DAPM_SINGLE("LineInR Capture Switch", ALC5632_ADC_REC_MIXER, 4, 1, 1),
-SOC_DAPM_SINGLE("Right Phone Capture Switch", ALC5632_ADC_REC_MIXER, 3, 1, 1),
-SOC_DAPM_SINGLE("HPMixerR Capture Switch", ALC5632_ADC_REC_MIXER, 2, 1, 1),
-SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5632_ADC_REC_MIXER, 1, 1, 1),
-SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5632_ADC_REC_MIXER, 0, 1, 1),
+SOC_DAPM_SINGLE("MIC12REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 6, 1, 1),
+SOC_DAPM_SINGLE("MIC22REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 5, 1, 1),
+SOC_DAPM_SINGLE("LIR2REC Capture Switch", ALC5632_ADC_REC_MIXER, 4, 1, 1),
+SOC_DAPM_SINGLE("PH2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 3, 1, 1),
+SOC_DAPM_SINGLE("HPR2REC Capture Switch", ALC5632_ADC_REC_MIXER, 2, 1, 1),
+SOC_DAPM_SINGLE("SPK2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 1, 1, 1),
+SOC_DAPM_SINGLE("MONO2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 0, 1, 1),
 };
 
-static const char *alc5632_spk_n_sour_sel[] = {
+/* Dmic Mixer */
+static const struct snd_kcontrol_new alc5632_dmicl_mixer_controls[] = {
+SOC_DAPM_SINGLE("DMICL2ADC Capture Switch", ALC5632_DIGI_BOOST_CTRL, 7, 1, 1),
+};
+static const struct snd_kcontrol_new alc5632_dmicr_mixer_controls[] = {
+SOC_DAPM_SINGLE("DMICR2ADC Capture Switch", ALC5632_DIGI_BOOST_CTRL, 6, 1, 1),
+};
+
+static const char * const alc5632_spk_n_sour_sel[] = {
                "RN/-R", "RP/+R", "LN/-R", "Mute"};
-static const char *alc5632_hpl_out_input_sel[] = {
+static const char * const alc5632_hpl_out_input_sel[] = {
                "Vmid", "HP Left Mix"};
-static const char *alc5632_hpr_out_input_sel[] = {
+static const char * const alc5632_hpr_out_input_sel[] = {
                "Vmid", "HP Right Mix"};
-static const char *alc5632_spkout_input_sel[] = {
+static const char * const alc5632_spkout_input_sel[] = {
                "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
-static const char *alc5632_aux_out_input_sel[] = {
+static const char * const alc5632_aux_out_input_sel[] = {
                "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
+static const char * const alc5632_adcr_func_sel[] = {
+               "Stereo ADC", "Voice ADC"};
+static const char * const alc5632_i2s_out_sel[] = {
+               "ADC LR", "Voice Stereo Digital"};
 
 /* auxout output mux */
 static const struct soc_enum alc5632_aux_out_input_enum =
@@ -312,6 +329,17 @@ static const struct soc_enum alc5632_amp_enum =
 static const struct snd_kcontrol_new alc5632_amp_mux_controls =
        SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum);
 
+/* ADC output select */
+static const struct soc_enum alc5632_adcr_func_enum =
+       SOC_ENUM_SINGLE(ALC5632_DAC_FUNC_SELECT, 5, 2, alc5632_adcr_func_sel);
+static const struct snd_kcontrol_new alc5632_adcr_func_controls =
+       SOC_DAPM_ENUM("ADCR Mux", alc5632_adcr_func_enum);
+
+/* I2S out select */
+static const struct soc_enum alc5632_i2s_out_enum =
+       SOC_ENUM_SINGLE(ALC5632_I2S_OUT_CTL, 5, 2, alc5632_i2s_out_sel);
+static const struct snd_kcontrol_new alc5632_i2s_out_controls =
+       SOC_DAPM_ENUM("I2SOut Mux", alc5632_i2s_out_enum);
 
 static const struct snd_soc_dapm_widget alc5632_dapm_widgets[] = {
 /* Muxes */
@@ -325,6 +353,10 @@ SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0,
        &alc5632_hpr_out_mux_controls),
 SND_SOC_DAPM_MUX("SpeakerOut N Mux", SND_SOC_NOPM, 0, 0,
        &alc5632_spkoutn_mux_controls),
+SND_SOC_DAPM_MUX("ADCR Mux", SND_SOC_NOPM, 0, 0,
+       &alc5632_adcr_func_controls),
+SND_SOC_DAPM_MUX("I2SOut Mux", ALC5632_PWR_MANAG_ADD1, 11, 0,
+       &alc5632_i2s_out_controls),
 
 /* output mixers */
 SND_SOC_DAPM_MIXER("HP Mix", SND_SOC_NOPM, 0, 0,
@@ -343,6 +375,12 @@ SND_SOC_DAPM_MIXER("Mono Mix", ALC5632_PWR_MANAG_ADD2, 2, 0,
 SND_SOC_DAPM_MIXER("Speaker Mix", ALC5632_PWR_MANAG_ADD2, 3, 0,
        &alc5632_speaker_mixer_controls[0],
        ARRAY_SIZE(alc5632_speaker_mixer_controls)),
+SND_SOC_DAPM_MIXER("DMICL Mix", SND_SOC_NOPM, 0, 0,
+       &alc5632_dmicl_mixer_controls[0],
+       ARRAY_SIZE(alc5632_dmicl_mixer_controls)),
+SND_SOC_DAPM_MIXER("DMICR Mix", SND_SOC_NOPM, 0, 0,
+       &alc5632_dmicr_mixer_controls[0],
+       ARRAY_SIZE(alc5632_dmicr_mixer_controls)),
 
 /* input mixers */
 SND_SOC_DAPM_MIXER("Left Capture Mix", ALC5632_PWR_MANAG_ADD2, 1, 0,
@@ -352,20 +390,28 @@ SND_SOC_DAPM_MIXER("Right Capture Mix", ALC5632_PWR_MANAG_ADD2, 0, 0,
        &alc5632_captureR_mixer_controls[0],
        ARRAY_SIZE(alc5632_captureR_mixer_controls)),
 
-SND_SOC_DAPM_DAC("Left DAC", "HiFi Playback",
-       ALC5632_PWR_MANAG_ADD2, 9, 0),
-SND_SOC_DAPM_DAC("Right DAC", "HiFi Playback",
-       ALC5632_PWR_MANAG_ADD2, 8, 0),
+SND_SOC_DAPM_AIF_IN("AIFRXL", "Left HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIFRXR", "Right HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIFTXL", "Left HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIFTXR", "Right HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("VAIFRX", "Voice Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("VAIFTX", "Voice Capture", 0, SND_SOC_NOPM, 0, 0),
+
+SND_SOC_DAPM_DAC("Voice DAC", NULL, ALC5632_PWR_MANAG_ADD2, 10, 0),
+SND_SOC_DAPM_DAC("Left DAC", NULL, ALC5632_PWR_MANAG_ADD2, 9, 0),
+SND_SOC_DAPM_DAC("Right DAC", NULL, ALC5632_PWR_MANAG_ADD2, 8, 0),
+SND_SOC_DAPM_ADC("Left ADC", NULL, ALC5632_PWR_MANAG_ADD2, 7, 0),
+SND_SOC_DAPM_ADC("Right ADC", NULL, ALC5632_PWR_MANAG_ADD2, 6, 0),
+
 SND_SOC_DAPM_MIXER("DAC Left Channel", ALC5632_PWR_MANAG_ADD1, 15, 0, NULL, 0),
 SND_SOC_DAPM_MIXER("DAC Right Channel",
        ALC5632_PWR_MANAG_ADD1, 14, 0, NULL, 0),
 SND_SOC_DAPM_MIXER("I2S Mix", ALC5632_PWR_MANAG_ADD1, 11, 0, NULL, 0),
 SND_SOC_DAPM_MIXER("Phone Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
 SND_SOC_DAPM_MIXER("Line Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
-SND_SOC_DAPM_ADC("Left ADC", "HiFi Capture",
-       ALC5632_PWR_MANAG_ADD2, 7, 0),
-SND_SOC_DAPM_ADC("Right ADC", "HiFi Capture",
-       ALC5632_PWR_MANAG_ADD2, 6, 0),
+SND_SOC_DAPM_MIXER("Voice Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("ADCLR", SND_SOC_NOPM, 0, 0, NULL, 0),
+
 SND_SOC_DAPM_PGA("Left Headphone", ALC5632_PWR_MANAG_ADD3, 11, 0, NULL, 0),
 SND_SOC_DAPM_PGA("Right Headphone", ALC5632_PWR_MANAG_ADD3, 10, 0, NULL, 0),
 SND_SOC_DAPM_PGA("Left Speaker", ALC5632_PWR_MANAG_ADD3, 13, 0, NULL, 0),
@@ -393,10 +439,12 @@ SND_SOC_DAPM_OUTPUT("HPL"),
 SND_SOC_DAPM_OUTPUT("HPR"),
 SND_SOC_DAPM_OUTPUT("SPKOUT"),
 SND_SOC_DAPM_OUTPUT("SPKOUTN"),
+
 SND_SOC_DAPM_INPUT("LINEINL"),
 SND_SOC_DAPM_INPUT("LINEINR"),
 SND_SOC_DAPM_INPUT("PHONEP"),
 SND_SOC_DAPM_INPUT("PHONEN"),
+SND_SOC_DAPM_INPUT("DMICDAT"),
 SND_SOC_DAPM_INPUT("MIC1"),
 SND_SOC_DAPM_INPUT("MIC2"),
 SND_SOC_DAPM_VMID("Vmid"),
@@ -404,6 +452,10 @@ SND_SOC_DAPM_VMID("Vmid"),
 
 
 static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
+       /* Playback streams */
+       {"Left DAC", NULL, "AIFRXL"},
+       {"Right DAC", NULL, "AIFRXR"},
+
        /* virtual mixer - mixes left & right channels */
        {"I2S Mix",     NULL,   "Left DAC"},
        {"I2S Mix",     NULL,   "Right DAC"},
@@ -426,9 +478,12 @@ static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
        {"HP Mix",      "PHONE2HP Playback Switch",     "Phone Mix"},
        {"HP Mix",      "MIC12HP Playback Switch",      "MIC1 PGA"},
        {"HP Mix",      "MIC22HP Playback Switch",      "MIC2 PGA"},
-
+       {"HP Mix", "VOICE2HP Playback Switch",  "Voice Mix"},
        {"HPR Mix", "DACR2HP Playback Switch",  "DAC Right Channel"},
        {"HPL Mix", "DACL2HP Playback Switch",  "DAC Left Channel"},
+       {"HPOut Mix", NULL, "HP Mix"},
+       {"HPOut Mix", NULL, "HPR Mix"},
+       {"HPOut Mix", NULL, "HPL Mix"},
 
        /* speaker mixer */
        {"Speaker Mix", "LI2SPK Playback Switch",       "Line Mix"},
@@ -436,35 +491,34 @@ static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
        {"Speaker Mix", "MIC12SPK Playback Switch",     "MIC1 PGA"},
        {"Speaker Mix", "MIC22SPK Playback Switch",     "MIC2 PGA"},
        {"Speaker Mix", "DAC2SPK Playback Switch",      "DAC Left Channel"},
-
-
+       {"Speaker Mix", "VOICE2SPK Playback Switch",    "Voice Mix"},
 
        /* mono mixer */
        {"Mono Mix", "ADC2MONO_L Playback Switch",      "Left Capture Mix"},
        {"Mono Mix", "ADC2MONO_R Playback Switch",      "Right Capture Mix"},
        {"Mono Mix", "LI2MONO Playback Switch",         "Line Mix"},
-       {"Mono Mix", "VOICE2MONO Playback Switch",      "Phone Mix"},
        {"Mono Mix", "MIC12MONO Playback Switch",       "MIC1 PGA"},
        {"Mono Mix", "MIC22MONO Playback Switch",       "MIC2 PGA"},
        {"Mono Mix", "DAC2MONO Playback Switch",        "DAC Left Channel"},
+       {"Mono Mix", "VOICE2MONO Playback Switch",      "Voice Mix"},
 
        /* Left record mixer */
-       {"Left Capture Mix", "LineInL Capture Switch",  "LINEINL"},
-       {"Left Capture Mix", "Left Phone Capture Switch", "PHONEN"},
-       {"Left Capture Mix", "Mic1 Capture Switch",     "MIC1 Pre Amp"},
-       {"Left Capture Mix", "Mic2 Capture Switch",     "MIC2 Pre Amp"},
-       {"Left Capture Mix", "HPMixerL Capture Switch", "HPL Mix"},
-       {"Left Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
-       {"Left Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
+       {"Left Capture Mix", "LIL2REC Capture Switch", "LINEINL"},
+       {"Left Capture Mix", "PH2REC_L Capture Switch", "PHONEN"},
+       {"Left Capture Mix", "MIC12REC_L Capture Switch", "MIC1 Pre Amp"},
+       {"Left Capture Mix", "MIC22REC_L Capture Switch", "MIC2 Pre Amp"},
+       {"Left Capture Mix", "HPL2REC Capture Switch", "HPL Mix"},
+       {"Left Capture Mix", "SPK2REC_L Capture Switch", "Speaker Mix"},
+       {"Left Capture Mix", "MONO2REC_L Capture Switch", "Mono Mix"},
 
        /*Right record mixer */
-       {"Right Capture Mix", "LineInR Capture Switch", "LINEINR"},
-       {"Right Capture Mix", "Right Phone Capture Switch",     "PHONEP"},
-       {"Right Capture Mix", "Mic1 Capture Switch",    "MIC1 Pre Amp"},
-       {"Right Capture Mix", "Mic2 Capture Switch",    "MIC2 Pre Amp"},
-       {"Right Capture Mix", "HPMixerR Capture Switch", "HPR Mix"},
-       {"Right Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
-       {"Right Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
+       {"Right Capture Mix", "LIR2REC Capture Switch", "LINEINR"},
+       {"Right Capture Mix", "PH2REC_R Capture Switch", "PHONEP"},
+       {"Right Capture Mix", "MIC12REC_R Capture Switch", "MIC1 Pre Amp"},
+       {"Right Capture Mix", "MIC22REC_R Capture Switch", "MIC2 Pre Amp"},
+       {"Right Capture Mix", "HPR2REC Capture Switch", "HPR Mix"},
+       {"Right Capture Mix", "SPK2REC_R Capture Switch", "Speaker Mix"},
+       {"Right Capture Mix", "MONO2REC_R Capture Switch", "Mono Mix"},
 
        /* headphone left mux */
        {"Left Headphone Mux", "HP Left Mix",           "HPL Mix"},
@@ -504,10 +558,30 @@ static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
 
        /* left ADC */
        {"Left ADC", NULL,                              "Left Capture Mix"},
+       {"DMICL Mix", "DMICL2ADC Capture Switch", "DMICDAT"},
+       {"Left ADC", NULL,                              "DMICL Mix"},
+       {"ADCLR", NULL,                                 "Left ADC"},
 
        /* right ADC */
-       {"Right ADC", NULL,                             "Right Capture Mix"},
-
+       {"Right ADC", NULL, "Right Capture Mix"},
+       {"DMICR Mix", "DMICR2ADC Capture Switch", "DMICDAT"},
+       {"Right ADC", NULL, "DMICR Mix"},
+       {"ADCR Mux", "Stereo ADC", "Right ADC"},
+       {"ADCR Mux", "Voice ADC", "Right ADC"},
+       {"ADCLR", NULL, "ADCR Mux"},
+       {"VAIFTX", NULL, "ADCR Mux"},
+
+       /* Digital I2S out */
+       {"I2SOut Mux", "ADC LR", "ADCLR"},
+       {"I2SOut Mux", "Voice Stereo Digital", "VAIFRX"},
+       {"AIFTXL", NULL, "I2SOut Mux"},
+       {"AIFTXR", NULL, "I2SOut Mux"},
+
+       /* Voice Mix */
+       {"Voice DAC", NULL, "VAIFRX"},
+       {"Voice Mix", NULL, "Voice DAC"},
+
+       /* Speaker Output */
        {"SpeakerOut N Mux", "RN/-R",                   "Left Speaker"},
        {"SpeakerOut N Mux", "RP/+R",                   "Left Speaker"},
        {"SpeakerOut N Mux", "LN/-R",                   "Left Speaker"},
@@ -714,6 +788,7 @@ static int alc5632_set_dai_sysclk(struct snd_soc_dai *codec_dai,
        struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
 
        switch (freq) {
+       case  4096000:
        case  8192000:
        case 11289600:
        case 12288000:
@@ -994,7 +1069,7 @@ static int alc5632_probe(struct snd_soc_codec *codec)
 
        switch (alc5632->id) {
        case 0x5c:
-               snd_soc_add_controls(codec, alc5632_vol_snd_controls,
+               snd_soc_add_codec_controls(codec, alc5632_vol_snd_controls,
                        ARRAY_SIZE(alc5632_vol_snd_controls));
                break;
        default:
@@ -1109,7 +1184,7 @@ static __devinit int alc5632_i2c_probe(struct i2c_client *client,
        return ret;
 }
 
-static int alc5632_i2c_remove(struct i2c_client *client)
+static __devexit int alc5632_i2c_remove(struct i2c_client *client)
 {
        struct alc5632_priv *alc5632 = i2c_get_clientdata(client);
        snd_soc_unregister_codec(&client->dev);
index 357651ec074e6e2c5f0110c86f65822023b34d6b..1b5bda594ea3a33fb2b63ee704c354a57ecee57c 100644 (file)
@@ -51,6 +51,7 @@
 #define ALC5632_ADC_REC_MONOMIX                        (1 << 0)
 
 #define ALC5632_VOICE_DAC_VOL                  0x18 /* voice dac vol */
+#define ALC5632_I2S_OUT_CTL                            0x1A /* undocumented reg. found in path scheme */
 /* ALC5632_OUTPUT_MIXER_CTRL :                 */
 /* same remark as for reg 2 line vs speaker    */
 #define ALC5632_OUTPUT_MIXER_CTRL              0x1C /* out mix ctrl */
index 4854b472d5fdb98ca5d6cae18863286a17f3b408..064cd6a935163ebf4fa0619b80f67154e1733528 100644 (file)
@@ -38,8 +38,6 @@
 #include <sound/soc.h>
 #include <sound/initval.h>
 
-#include <mach/dm365.h>
-
 static inline unsigned int cq93vc_read(struct snd_soc_codec *codec,
                                                unsigned int reg)
 {
@@ -159,7 +157,7 @@ static int cq93vc_probe(struct snd_soc_codec *codec)
        codec->control_data = davinci_vc;
 
        /* Set controls */
-       snd_soc_add_controls(codec, cq93vc_snd_controls,
+       snd_soc_add_codec_controls(codec, cq93vc_snd_controls,
                             ARRAY_SIZE(cq93vc_snd_controls));
 
        /* Off, with power on */
index 055536645da917e15308cd4abb17d13f2a43bf67..6baccd285df1dd3eefd351e4eb39964405d47869 100644 (file)
@@ -521,7 +521,7 @@ static int cs4270_probe(struct snd_soc_codec *codec)
        }
 
        /* Add the non-DAPM controls */
-       ret = snd_soc_add_controls(codec, cs4270_snd_controls,
+       ret = snd_soc_add_codec_controls(codec, cs4270_snd_controls,
                                ARRAY_SIZE(cs4270_snd_controls));
        if (ret < 0) {
                dev_err(codec->dev, "failed to add controls\n");
index f6fe846b6a6c3d76f8778140261c96b0ed7a65eb..bf7141280a747ab25b311c083b06b82bc8e7ad9e 100644 (file)
@@ -513,7 +513,7 @@ static int cs4271_probe(struct snd_soc_codec *codec)
        /* Power-up sequence requires 85 uS */
        udelay(85);
 
-       return snd_soc_add_controls(codec, cs4271_snd_controls,
+       return snd_soc_add_codec_controls(codec, cs4271_snd_controls,
                ARRAY_SIZE(cs4271_snd_controls));
 }
 
index 319039240e0fafe25412110e81fc548b011df072..ba4fafb93e5624d2aff10f6e20cf81ad34066ea9 100644 (file)
@@ -179,7 +179,7 @@ static int lm4857_probe(struct snd_soc_codec *codec)
 
        codec->control_data = lm4857->i2c;
 
-       ret = snd_soc_add_controls(codec, lm4857_controls,
+       ret = snd_soc_add_codec_controls(codec, lm4857_controls,
                        ARRAY_SIZE(lm4857_controls));
        if (ret)
                return ret;
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c
new file mode 100644 (file)
index 0000000..17b3ec2
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * MAX9768 AMP driver
+ *
+ * Copyright (C) 2011, 2012 by Wolfram Sang, Pengutronix e.K.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/regmap.h>
+
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <sound/max9768.h>
+
+/* "Registers" */
+#define MAX9768_VOL 0
+#define MAX9768_CTRL 3
+
+/* Commands */
+#define MAX9768_CTRL_PWM 0x15
+#define MAX9768_CTRL_FILTERLESS 0x16
+
+struct max9768 {
+       struct regmap *regmap;
+       int mute_gpio;
+       int shdn_gpio;
+       u32 flags;
+};
+
+static struct reg_default max9768_default_regs[] = {
+       { 0, 0 },
+       { 3,  MAX9768_CTRL_FILTERLESS},
+};
+
+static int max9768_get_gpio(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+       int val = gpio_get_value_cansleep(max9768->mute_gpio);
+
+       ucontrol->value.integer.value[0] = !val;
+
+       return 0;
+}
+
+static int max9768_set_gpio(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+
+       gpio_set_value_cansleep(max9768->mute_gpio, !ucontrol->value.integer.value[0]);
+
+       return 0;
+}
+
+static const unsigned int volume_tlv[] = {
+       TLV_DB_RANGE_HEAD(43),
+       0, 0, TLV_DB_SCALE_ITEM(-16150, 0, 0),
+       1, 1, TLV_DB_SCALE_ITEM(-9280, 0, 0),
+       2, 2, TLV_DB_SCALE_ITEM(-9030, 0, 0),
+       3, 3, TLV_DB_SCALE_ITEM(-8680, 0, 0),
+       4, 4, TLV_DB_SCALE_ITEM(-8430, 0, 0),
+       5, 5, TLV_DB_SCALE_ITEM(-8080, 0, 0),
+       6, 6, TLV_DB_SCALE_ITEM(-7830, 0, 0),
+       7, 7, TLV_DB_SCALE_ITEM(-7470, 0, 0),
+       8, 8, TLV_DB_SCALE_ITEM(-7220, 0, 0),
+       9, 9, TLV_DB_SCALE_ITEM(-6870, 0, 0),
+       10, 10, TLV_DB_SCALE_ITEM(-6620, 0, 0),
+       11, 11, TLV_DB_SCALE_ITEM(-6270, 0, 0),
+       12, 12, TLV_DB_SCALE_ITEM(-6020, 0, 0),
+       13, 13, TLV_DB_SCALE_ITEM(-5670, 0, 0),
+       14, 14, TLV_DB_SCALE_ITEM(-5420, 0, 0),
+       15, 17, TLV_DB_SCALE_ITEM(-5060, 250, 0),
+       18, 18, TLV_DB_SCALE_ITEM(-4370, 0, 0),
+       19, 19, TLV_DB_SCALE_ITEM(-4210, 0, 0),
+       20, 20, TLV_DB_SCALE_ITEM(-3960, 0, 0),
+       21, 21, TLV_DB_SCALE_ITEM(-3760, 0, 0),
+       22, 22, TLV_DB_SCALE_ITEM(-3600, 0, 0),
+       23, 23, TLV_DB_SCALE_ITEM(-3340, 0, 0),
+       24, 24, TLV_DB_SCALE_ITEM(-3150, 0, 0),
+       25, 25, TLV_DB_SCALE_ITEM(-2980, 0, 0),
+       26, 26, TLV_DB_SCALE_ITEM(-2720, 0, 0),
+       27, 27, TLV_DB_SCALE_ITEM(-2520, 0, 0),
+       28, 30, TLV_DB_SCALE_ITEM(-2350, 190, 0),
+       31, 31, TLV_DB_SCALE_ITEM(-1750, 0, 0),
+       32, 34, TLV_DB_SCALE_ITEM(-1640, 100, 0),
+       35, 37, TLV_DB_SCALE_ITEM(-1310, 110, 0),
+       38, 39, TLV_DB_SCALE_ITEM(-990, 100, 0),
+       40, 40, TLV_DB_SCALE_ITEM(-710, 0, 0),
+       41, 41, TLV_DB_SCALE_ITEM(-600, 0, 0),
+       42, 42, TLV_DB_SCALE_ITEM(-500, 0, 0),
+       43, 43, TLV_DB_SCALE_ITEM(-340, 0, 0),
+       44, 44, TLV_DB_SCALE_ITEM(-190, 0, 0),
+       45, 45, TLV_DB_SCALE_ITEM(-50, 0, 0),
+       46, 46, TLV_DB_SCALE_ITEM(50, 0, 0),
+       47, 50, TLV_DB_SCALE_ITEM(120, 40, 0),
+       51, 57, TLV_DB_SCALE_ITEM(290, 50, 0),
+       58, 58, TLV_DB_SCALE_ITEM(650, 0, 0),
+       59, 62, TLV_DB_SCALE_ITEM(700, 60, 0),
+       63, 63, TLV_DB_SCALE_ITEM(950, 0, 0),
+};
+
+static const struct snd_kcontrol_new max9768_volume[] = {
+       SOC_SINGLE_TLV("Playback Volume", MAX9768_VOL, 0, 63, 0, volume_tlv),
+};
+
+static const struct snd_kcontrol_new max9768_mute[] = {
+       SOC_SINGLE_BOOL_EXT("Playback Switch", 0, max9768_get_gpio, max9768_set_gpio),
+};
+
+static int max9768_probe(struct snd_soc_codec *codec)
+{
+       struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+       codec->control_data = max9768->regmap;
+       ret = snd_soc_codec_set_cache_io(codec, 2, 6, SND_SOC_REGMAP);
+       if (ret)
+               return ret;
+
+       if (max9768->flags & MAX9768_FLAG_CLASSIC_PWM) {
+               ret = snd_soc_write(codec, MAX9768_CTRL, MAX9768_CTRL_PWM);
+               if (ret)
+                       return ret;
+       }
+
+       if (gpio_is_valid(max9768->mute_gpio)) {
+               ret = snd_soc_add_codec_controls(codec, max9768_mute,
+                               ARRAY_SIZE(max9768_mute));
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static struct snd_soc_codec_driver max9768_codec_driver = {
+       .probe = max9768_probe,
+       .controls = max9768_volume,
+       .num_controls = ARRAY_SIZE(max9768_volume),
+};
+
+static const struct regmap_config max9768_i2c_regmap_config = {
+       .reg_bits = 2,
+       .val_bits = 6,
+       .max_register = 3,
+       .reg_defaults = max9768_default_regs,
+       .num_reg_defaults = ARRAY_SIZE(max9768_default_regs),
+       .cache_type = REGCACHE_RBTREE,
+};
+
+static int __devinit max9768_i2c_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       struct max9768 *max9768;
+       struct max9768_pdata *pdata = client->dev.platform_data;
+       int err;
+
+       max9768 = devm_kzalloc(&client->dev, sizeof(*max9768), GFP_KERNEL);
+       if (!max9768)
+               return -ENOMEM;
+
+       if (pdata) {
+               /* Mute on powerup to avoid clicks */
+               err = gpio_request_one(pdata->mute_gpio, GPIOF_INIT_HIGH, "MAX9768 Mute");
+               max9768->mute_gpio = err ?: pdata->mute_gpio;
+
+               /* Activate chip by releasing shutdown, enables I2C */
+               err = gpio_request_one(pdata->shdn_gpio, GPIOF_INIT_HIGH, "MAX9768 Shutdown");
+               max9768->shdn_gpio = err ?: pdata->shdn_gpio;
+
+               max9768->flags = pdata->flags;
+       } else {
+               max9768->shdn_gpio = -EINVAL;
+               max9768->mute_gpio = -EINVAL;
+       }
+
+       i2c_set_clientdata(client, max9768);
+
+       max9768->regmap = regmap_init_i2c(client, &max9768_i2c_regmap_config);
+       if (IS_ERR(max9768->regmap)) {
+               err = PTR_ERR(max9768->regmap);
+               goto err_gpio_free;
+       }
+
+       err = snd_soc_register_codec(&client->dev, &max9768_codec_driver, NULL, 0);
+       if (err)
+               goto err_regmap_free;
+
+       return 0;
+
+ err_regmap_free:
+       regmap_exit(max9768->regmap);
+ err_gpio_free:
+       if (gpio_is_valid(max9768->shdn_gpio))
+               gpio_free(max9768->shdn_gpio);
+       if (gpio_is_valid(max9768->mute_gpio))
+               gpio_free(max9768->mute_gpio);
+
+       return err;
+}
+
+static int __devexit max9768_i2c_remove(struct i2c_client *client)
+{
+       struct max9768 *max9768 = i2c_get_clientdata(client);
+
+       snd_soc_unregister_codec(&client->dev);
+       regmap_exit(max9768->regmap);
+
+       if (gpio_is_valid(max9768->shdn_gpio))
+               gpio_free(max9768->shdn_gpio);
+       if (gpio_is_valid(max9768->mute_gpio))
+               gpio_free(max9768->mute_gpio);
+
+       return 0;
+}
+
+static const struct i2c_device_id max9768_i2c_id[] = {
+       { "max9768", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, max9768_i2c_id);
+
+static struct i2c_driver max9768_i2c_driver = {
+       .driver = {
+               .name = "max9768",
+               .owner = THIS_MODULE,
+       },
+       .probe = max9768_i2c_probe,
+       .remove = __devexit_p(max9768_i2c_remove),
+       .id_table = max9768_i2c_id,
+};
+module_i2c_driver(max9768_i2c_driver);
+
+MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_DESCRIPTION("ASoC MAX9768 amplifier driver");
+MODULE_LICENSE("GPL v2");
index 006efcfe6dda84b486330bb79cdb0d36b8389efe..af7324b79dd0a8c8ae900277a7bf4abf2a98995a 100644 (file)
@@ -1908,7 +1908,7 @@ static void max98088_handle_eq_pdata(struct snd_soc_codec *codec)
        max98088->eq_enum.texts = max98088->eq_texts;
        max98088->eq_enum.max = max98088->eq_textcnt;
 
-       ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+       ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
        if (ret != 0)
                dev_err(codec->dev, "Failed to add EQ control: %d\n", ret);
 }
@@ -2030,7 +2030,7 @@ static int max98088_probe(struct snd_soc_codec *codec)
 
        max98088_handle_pdata(codec);
 
-       snd_soc_add_controls(codec, max98088_snd_controls,
+       snd_soc_add_codec_controls(codec, max98088_snd_controls,
                             ARRAY_SIZE(max98088_snd_controls));
 
 err_access:
index fcfa7497d7b74aac4777def9e7b7d186ec7c58ef..0bb511a0388de84cfec32f1794dd0a77be63ba1d 100644 (file)
@@ -1284,7 +1284,7 @@ static const struct snd_soc_dapm_route max98095_audio_map[] = {
 
 static int max98095_add_widgets(struct snd_soc_codec *codec)
 {
-       snd_soc_add_controls(codec, max98095_snd_controls,
+       snd_soc_add_codec_controls(codec, max98095_snd_controls,
                             ARRAY_SIZE(max98095_snd_controls));
 
        return 0;
@@ -1984,7 +1984,7 @@ static void max98095_handle_eq_pdata(struct snd_soc_codec *codec)
        max98095->eq_enum.texts = max98095->eq_texts;
        max98095->eq_enum.max = max98095->eq_textcnt;
 
-       ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+       ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
        if (ret != 0)
                dev_err(codec->dev, "Failed to add EQ control: %d\n", ret);
 }
@@ -2139,7 +2139,7 @@ static void max98095_handle_bq_pdata(struct snd_soc_codec *codec)
        max98095->bq_enum.texts = max98095->bq_texts;
        max98095->bq_enum.max = max98095->bq_textcnt;
 
-       ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+       ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
        if (ret != 0)
                dev_err(codec->dev, "Failed to add Biquad control: %d\n", ret);
 }
index dcf6f2a1600ae5726a60d0a7e11ef6e53d57d466..3a2ba3d8fd6de13ec21f8e5b6ed67df85af77256 100644 (file)
@@ -253,7 +253,7 @@ static const struct snd_kcontrol_new max9877_controls[] = {
 /* This function is called from ASoC machine driver */
 int max9877_add_controls(struct snd_soc_codec *codec)
 {
-       return snd_soc_add_controls(codec, max9877_controls,
+       return snd_soc_add_codec_controls(codec, max9877_controls,
                        ARRAY_SIZE(max9877_controls));
 }
 EXPORT_SYMBOL_GPL(max9877_add_controls);
index 7f4ba819a9f681dad3f962ae7c65c60d73b0f2a3..d1926266fe00f4ae10003d9c632a07e4dcd68862 100644 (file)
@@ -227,7 +227,7 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = {
 };
 
 /* routes for sgtl5000 */
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route sgtl5000_dapm_routes[] = {
        {"Capture Mux", "LINE_IN", "LINE_IN"},  /* line_in --> adc_mux */
        {"Capture Mux", "MIC_IN", "MIC_IN"},    /* mic_in --> adc_mux */
 
@@ -1248,7 +1248,7 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
        }
 
        rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT;
-       dev_info(codec->dev, "sgtl5000 revision %d\n", rev);
+       dev_info(codec->dev, "sgtl5000 revision 0x%x\n", rev);
 
        /*
         * workaround for revision 0x11 and later,
@@ -1353,15 +1353,6 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
        if (ret)
                goto err;
 
-       snd_soc_add_controls(codec, sgtl5000_snd_controls,
-                            ARRAY_SIZE(sgtl5000_snd_controls));
-
-       snd_soc_dapm_new_controls(&codec->dapm, sgtl5000_dapm_widgets,
-                                 ARRAY_SIZE(sgtl5000_dapm_widgets));
-
-       snd_soc_dapm_add_routes(&codec->dapm, audio_map,
-                               ARRAY_SIZE(audio_map));
-
        snd_soc_dapm_new_widgets(&codec->dapm);
 
        return 0;
@@ -1402,6 +1393,12 @@ static struct snd_soc_codec_driver sgtl5000_driver = {
        .reg_cache_step = 2,
        .reg_cache_default = sgtl5000_regs,
        .volatile_register = sgtl5000_volatile_register,
+       .controls = sgtl5000_snd_controls,
+       .num_controls = ARRAY_SIZE(sgtl5000_snd_controls),
+       .dapm_widgets = sgtl5000_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(sgtl5000_dapm_widgets),
+       .dapm_routes = sgtl5000_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes),
 };
 
 static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
index f99baa0b8c39133b5cbc342368b4ac98f79cb365..50dbdb9357ead627961f08a170d8430b99faca07 100644 (file)
@@ -827,8 +827,6 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
 {
        pr_debug("codec_probe called\n");
 
-       codec->dapm.idle_bias_off = 1;
-
        /* PCM interface config
         * This sets the pcm rx slot conguration to max 6 slots
         * for max 4 dais (2 stereo and 2 mono)
@@ -871,7 +869,7 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
        snd_soc_write(codec, SN95031_SSR2, 0x10);
        snd_soc_write(codec, SN95031_SSR3, 0x40);
 
-       snd_soc_add_controls(codec, sn95031_snd_controls,
+       snd_soc_add_codec_controls(codec, sn95031_snd_controls,
                             ARRAY_SIZE(sn95031_snd_controls));
 
        return 0;
@@ -891,6 +889,7 @@ struct snd_soc_codec_driver sn95031_codec = {
        .read           = sn95031_read,
        .write          = sn95031_write,
        .set_bias_level = sn95031_set_vaud_bias,
+       .idle_bias_off  = true,
        .dapm_widgets   = sn95031_dapm_widgets,
        .num_dapm_widgets       = ARRAY_SIZE(sn95031_dapm_widgets),
        .dapm_routes    = sn95031_audio_map,
index 333dd98af39ce538868d706a2281f2e7514152ab..de2b20544ceb01cb8ecbecaae507d6b33826e53f 100644 (file)
@@ -548,7 +548,7 @@ static int ssm2602_probe(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, SSM2602_ROUT1V,
                            ROUT1V_RLHP_BOTH, ROUT1V_RLHP_BOTH);
 
-       ret = snd_soc_add_controls(codec, ssm2602_snd_controls,
+       ret = snd_soc_add_codec_controls(codec, ssm2602_snd_controls,
                        ARRAY_SIZE(ssm2602_snd_controls));
        if (ret)
                return ret;
index cc0566c22ec12ecfcf3f67d486b6330fea448f47..982e437799a8e62aa8085a9d5b509fa4d8f8a387 100644 (file)
@@ -355,7 +355,7 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec)
 
        stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       snd_soc_add_controls(codec, stac9766_snd_ac97_controls,
+       snd_soc_add_codec_controls(codec, stac9766_snd_ac97_controls,
                             ARRAY_SIZE(stac9766_snd_ac97_controls));
 
        return 0;
index dfa41a96599b8c61884c04392c6a878e7e715372..16d55f91a6535e088dff5999ee9bae408999dd7e 100644 (file)
@@ -593,7 +593,7 @@ static int tlv320aic23_probe(struct snd_soc_codec *codec)
 
        snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1);
 
-       snd_soc_add_controls(codec, tlv320aic23_snd_controls,
+       snd_soc_add_codec_controls(codec, tlv320aic23_snd_controls,
                                ARRAY_SIZE(tlv320aic23_snd_controls));
 
        return 0;
index a038daec682bfba9dd6997b9acfbb4e0c4855ca2..802064b5030d0b910736ae05d5365941a9d0b74c 100644 (file)
@@ -389,7 +389,7 @@ static int aic26_probe(struct snd_soc_codec *codec)
 
        /* register controls */
        dev_dbg(codec->dev, "Registering controls\n");
-       err = snd_soc_add_controls(codec, aic26_snd_controls,
+       err = snd_soc_add_codec_controls(codec, aic26_snd_controls,
                        ARRAY_SIZE(aic26_snd_controls));
        WARN_ON(err < 0);
 
index 372b0b83bd9f191c104dd18dcff3a7756021f1dc..b0a73d37ed52b4dfb52fb97a367e03f37a6df291 100644 (file)
@@ -671,7 +671,7 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
        }
 
        aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-       snd_soc_add_controls(codec, aic32x4_snd_controls,
+       snd_soc_add_codec_controls(codec, aic32x4_snd_controls,
                             ARRAY_SIZE(aic32x4_snd_controls));
        aic32x4_add_widgets(codec);
 
index 492f22f8a4d7bd8ae30bbd2bb4ae6dae3488ccad..8d20f6ec20f35853b98e13735f5e540ef9c27c47 100644 (file)
@@ -121,30 +121,6 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
        0x00, 0x00, 0x02,       /* 100 */
 };
 
-/*
- * read from the aic3x register space. Only use for this function is if
- * wanting to read volatile bits from those registers that has both read-only
- * and read/write bits. All other cases should use snd_soc_read.
- */
-static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
-                     u8 *value)
-{
-       u8 *cache = codec->reg_cache;
-
-       if (codec->cache_only)
-               return -EINVAL;
-       if (reg >= AIC3X_CACHEREGNUM)
-               return -1;
-
-       codec->cache_bypass = 1;
-       *value = snd_soc_read(codec, reg);
-       codec->cache_bypass = 0;
-
-       cache[reg] = *value;
-
-       return 0;
-}
-
 #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
        .info = snd_soc_info_volsw, \
@@ -1185,25 +1161,6 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state)
-{
-       u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
-       u8 bit = gpio ? 3: 0;
-       u8 val = snd_soc_read(codec, reg) & ~(1 << bit);
-       snd_soc_write(codec, reg, val | (!!state << bit));
-}
-EXPORT_SYMBOL_GPL(aic3x_set_gpio);
-
-int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio)
-{
-       u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
-       u8 val = 0, bit = gpio ? 2 : 1;
-
-       aic3x_read(codec, reg, &val);
-       return (val >> bit) & 1;
-}
-EXPORT_SYMBOL_GPL(aic3x_get_gpio);
-
 void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
                                 int headset_debounce, int button_debounce)
 {
@@ -1221,23 +1178,6 @@ void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
 
        snd_soc_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val);
 }
-EXPORT_SYMBOL_GPL(aic3x_set_headset_detection);
-
-int aic3x_headset_detected(struct snd_soc_codec *codec)
-{
-       u8 val = 0;
-       aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
-       return (val >> 4) & 1;
-}
-EXPORT_SYMBOL_GPL(aic3x_headset_detected);
-
-int aic3x_button_pressed(struct snd_soc_codec *codec)
-{
-       u8 val = 0;
-       aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
-       return (val >> 5) & 1;
-}
-EXPORT_SYMBOL_GPL(aic3x_button_pressed);
 
 #define AIC3X_RATES    SNDRV_PCM_RATE_8000_96000
 #define AIC3X_FORMATS  (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
@@ -1377,7 +1317,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
 
        INIT_LIST_HEAD(&aic3x->list);
        aic3x->codec = codec;
-       codec->dapm.idle_bias_off = 1;
 
        ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type);
        if (ret != 0) {
@@ -1426,10 +1365,10 @@ static int aic3x_probe(struct snd_soc_codec *codec)
                              (aic3x->setup->gpio_func[1] & 0xf) << 4);
        }
 
-       snd_soc_add_controls(codec, aic3x_snd_controls,
+       snd_soc_add_codec_controls(codec, aic3x_snd_controls,
                             ARRAY_SIZE(aic3x_snd_controls));
        if (aic3x->model == AIC3X_MODEL_3007)
-               snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
+               snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
 
        aic3x_add_widgets(codec);
        list_add(&aic3x->list, &reset_list);
@@ -1471,6 +1410,7 @@ static int aic3x_remove(struct snd_soc_codec *codec)
 
 static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
        .set_bias_level = aic3x_set_bias_level,
+       .idle_bias_off = true,
        .reg_cache_size = ARRAY_SIZE(aic3x_reg),
        .reg_word_size = sizeof(u8),
        .reg_cache_default = aic3x_reg,
index 06a19784b162dddfd2f719d850deaf45d52dfef6..6f097fb60683e7b5605b38e373c7f1c75f4158c9 100644 (file)
 /* Default input volume */
 #define DEFAULT_GAIN    0x20
 
-void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state);
-int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio);
-
 /* headset detection / button API */
 
 /* The AIC3x supports detection of stereo headsets (GND + left + right signal)
@@ -252,10 +249,4 @@ enum {
 #define AIC3X_BUTTON_DEBOUNCE_SHIFT    0
 #define AIC3X_BUTTON_DEBOUNCE_MASK     3
 
-/* see the enums above for valid parameters to this function */
-void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
-                                int headset_debounce, int button_debounce);
-int aic3x_headset_detected(struct snd_soc_codec *codec);
-int aic3x_button_pressed(struct snd_soc_codec *codec);
-
 #endif /* _AIC3X_H */
index f0aad26cdb3166ea18456cdfafec5bce35835ac5..4587ddd0fbf8c2e30fa01600dcbd17aed9545e90 100644 (file)
@@ -806,8 +806,6 @@ static int dac33_startup(struct snd_pcm_substream *substream,
        /* Stream started, save the substream pointer */
        dac33->substream = substream;
 
-       snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
-
        return 0;
 }
 
@@ -1397,7 +1395,6 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
 
        codec->control_data = dac33->control_data;
        codec->hw_write = (hw_write_t) i2c_master_send;
-       codec->dapm.idle_bias_off = 1;
        dac33->codec = codec;
 
        /* Read the tlv320dac33 ID registers */
@@ -1440,7 +1437,7 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
 
        /* Only add the FIFO controls, if we have valid IRQ number */
        if (dac33->irq >= 0)
-               snd_soc_add_controls(codec, dac33_mode_snd_controls,
+               snd_soc_add_codec_controls(codec, dac33_mode_snd_controls,
                                     ARRAY_SIZE(dac33_mode_snd_controls));
 
 err_power:
@@ -1478,6 +1475,7 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = {
        .read = dac33_read_reg_cache,
        .write = dac33_write_locked,
        .set_bias_level = dac33_set_bias_level,
+       .idle_bias_off = true,
        .reg_cache_size = ARRAY_SIZE(dac33_reg),
        .reg_word_size = sizeof(u8),
        .reg_cache_default = dac33_reg,
@@ -1515,7 +1513,9 @@ static struct snd_soc_dai_driver dac33_dai = {
                .channels_min = 2,
                .channels_max = 2,
                .rates = DAC33_RATES,
-               .formats = DAC33_FORMATS,},
+               .formats = DAC33_FORMATS,
+               .sig_bits = 24,
+       },
        .ops = &dac33_dai_ops,
 };
 
index 363b99dad8e9539e09cc29134e7d215243dddbc8..6fe4aa3ac54401da4210df65ead54e0a1fe537b2 100644 (file)
@@ -351,10 +351,10 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec)
        data = i2c_get_clientdata(tpa6130a2_client);
 
        if (data->id == TPA6140A2)
-               return snd_soc_add_controls(codec, tpa6140a2_controls,
+               return snd_soc_add_codec_controls(codec, tpa6140a2_controls,
                                                ARRAY_SIZE(tpa6140a2_controls));
        else
-               return snd_soc_add_controls(codec, tpa6130a2_controls,
+               return snd_soc_add_codec_controls(codec, tpa6130a2_controls,
                                                ARRAY_SIZE(tpa6130a2_controls));
 }
 EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
index 18e71014cc2e87a93d82abdca853b62d29ab8a54..d7eee0d502e080aca6c4fbcd1f480faba8c421ca 100644 (file)
@@ -1689,7 +1689,6 @@ static int twl4030_startup(struct snd_pcm_substream *substream,
        struct snd_soc_codec *codec = rtd->codec;
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
 
-       snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
        if (twl4030->master_substream) {
                twl4030->slave_substream = substream;
                /* The DAI has one configuration for playback and capture, so
@@ -2175,13 +2174,15 @@ static struct snd_soc_dai_driver twl4030_dai[] = {
                .channels_min = 2,
                .channels_max = 4,
                .rates = TWL4030_RATES | SNDRV_PCM_RATE_96000,
-               .formats = TWL4030_FORMATS,},
+               .formats = TWL4030_FORMATS,
+               .sig_bits = 24,},
        .capture = {
                .stream_name = "Capture",
                .channels_min = 2,
                .channels_max = 4,
                .rates = TWL4030_RATES,
-               .formats = TWL4030_FORMATS,},
+               .formats = TWL4030_FORMATS,
+               .sig_bits = 24,},
        .ops = &twl4030_dai_hifi_ops,
 },
 {
@@ -2220,13 +2221,12 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
 
        twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL);
        if (twl4030 == NULL) {
-               printk("Can not allocate memroy\n");
+               printk("Can not allocate memory\n");
                return -ENOMEM;
        }
        snd_soc_codec_set_drvdata(codec, twl4030);
        /* Set the defaults, and power up the codec */
        twl4030->sysclk = twl4030_audio_get_mclk() / 1000;
-       codec->dapm.idle_bias_off = 1;
 
        twl4030_init_chip(codec);
 
@@ -2252,6 +2252,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
        .read = twl4030_read_reg_cache,
        .write = twl4030_write,
        .set_bias_level = twl4030_set_bias_level,
+       .idle_bias_off = true,
        .reg_cache_size = sizeof(twl4030_reg),
        .reg_word_size = sizeof(u8),
        .reg_cache_default = twl4030_reg,
index 5b9c79b6f65e104fdbbae4779452d15821752c58..836eb14f7b85a0598aea3aa7f1cdb9c572cf4ebf 100644 (file)
@@ -1052,6 +1052,19 @@ int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim)
 }
 EXPORT_SYMBOL_GPL(twl6040_get_trim_value);
 
+int twl6040_get_hs_step_size(struct snd_soc_codec *codec)
+{
+       struct twl6040 *twl6040 = codec->control_data;
+
+       if (twl6040_get_revid(twl6040) < TWL6040_REV_ES1_2)
+               /* For ES under ES_1.3 HS step is 2 mV */
+               return 2;
+       else
+               /* For ES_1.3 HS step is 1 mV */
+               return 1;
+}
+EXPORT_SYMBOL_GPL(twl6040_get_hs_step_size);
+
 static const struct snd_kcontrol_new twl6040_snd_controls[] = {
        /* Capture gains */
        SOC_DOUBLE_TLV("Capture Preamplifier Volume",
@@ -1527,7 +1540,6 @@ static int twl6040_probe(struct snd_soc_codec *codec)
 
        priv->codec = codec;
        codec->control_data = dev_get_drvdata(codec->dev->parent);
-       codec->ignore_pmdown_time = 1;
 
        if (pdata && pdata->hs_left_step && pdata->hs_right_step) {
                priv->hs_left_step = pdata->hs_left_step;
@@ -1613,6 +1625,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
        .reg_cache_size = ARRAY_SIZE(twl6040_reg),
        .reg_word_size = sizeof(u8),
        .reg_cache_default = twl6040_reg,
+       .ignore_pmdown_time = true,
 
        .controls = twl6040_snd_controls,
        .num_controls = ARRAY_SIZE(twl6040_snd_controls),
index ef273f1fac2f838add14ecc8b01465e4677097af..0611406ca7c0359188575df1e61020c1680e9b4e 100644 (file)
@@ -39,5 +39,6 @@ void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
                            struct snd_soc_jack *jack, int report);
 int twl6040_get_clk_id(struct snd_soc_codec *codec);
 int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim);
+int twl6040_get_hs_step_size(struct snd_soc_codec *codec);
 
 #endif /* End of __TWL6040_H__ */
index 8f4f469d64115cb52ae8c58fd60fcc78d9669e50..797b0dde2c68620910a5870f7e341731aaf3380b 100644 (file)
@@ -531,15 +531,15 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec)
        switch (pd->model) {
        case UDA134X_UDA1340:
        case UDA134X_UDA1344:
-               ret = snd_soc_add_controls(codec, uda1340_snd_controls,
+               ret = snd_soc_add_codec_controls(codec, uda1340_snd_controls,
                                        ARRAY_SIZE(uda1340_snd_controls));
        break;
        case UDA134X_UDA1341:
-               ret = snd_soc_add_controls(codec, uda1341_snd_controls,
+               ret = snd_soc_add_codec_controls(codec, uda1341_snd_controls,
                                        ARRAY_SIZE(uda1341_snd_controls));
        break;
        case UDA134X_UDA1345:
-               ret = snd_soc_add_controls(codec, uda1345_snd_controls,
+               ret = snd_soc_add_codec_controls(codec, uda1345_snd_controls,
                                        ARRAY_SIZE(uda1345_snd_controls));
        break;
        default:
index 44aacf927ba99d6a533524b39859eac9d565c265..3d868dc400921cc22d21ef1ede114fb643dcd6e1 100644 (file)
@@ -464,7 +464,7 @@ static int wl1273_probe(struct snd_soc_codec *codec)
 
        snd_soc_codec_set_drvdata(codec, wl1273);
 
-       r = snd_soc_add_controls(codec, wl1273_controls,
+       r = snd_soc_add_codec_controls(codec, wl1273_controls,
                                 ARRAY_SIZE(wl1273_controls));
        if (r)
                kfree(wl1273);
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c
new file mode 100644 (file)
index 0000000..acbdc5f
--- /dev/null
@@ -0,0 +1,2286 @@
+/*
+ * wm2200.c  --  WM2200 ALSA SoC Audio driver
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/gcd.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/fixed.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/wm2200.h>
+
+#include "wm2200.h"
+
+/* The code assumes DCVDD is generated internally */
+#define WM2200_NUM_CORE_SUPPLIES 2
+static const char *wm2200_core_supply_names[WM2200_NUM_CORE_SUPPLIES] = {
+       "DBVDD",
+       "LDOVDD",
+};
+
+struct wm2200_fll {
+       int fref;
+       int fout;
+       int src;
+       struct completion lock;
+};
+
+/* codec private data */
+struct wm2200_priv {
+       struct regmap *regmap;
+       struct device *dev;
+       struct snd_soc_codec *codec;
+       struct wm2200_pdata pdata;
+       struct regulator_bulk_data core_supplies[WM2200_NUM_CORE_SUPPLIES];
+
+       struct completion fll_lock;
+       int fll_fout;
+       int fll_fref;
+       int fll_src;
+
+       int rev;
+       int sysclk;
+};
+
+static struct reg_default wm2200_reg_defaults[] = {
+       { 0x000B, 0x0000 },   /* R11    - Tone Generator 1 */
+       { 0x0102, 0x0000 },   /* R258   - Clocking 3 */
+       { 0x0103, 0x0011 },   /* R259   - Clocking 4 */
+       { 0x0111, 0x0000 },   /* R273   - FLL Control 1 */
+       { 0x0112, 0x0000 },   /* R274   - FLL Control 2 */
+       { 0x0113, 0x0000 },   /* R275   - FLL Control 3 */
+       { 0x0114, 0x0000 },   /* R276   - FLL Control 4 */
+       { 0x0116, 0x0177 },   /* R278   - FLL Control 6 */
+       { 0x0117, 0x0004 },   /* R279   - FLL Control 7 */
+       { 0x0119, 0x0000 },   /* R281   - FLL EFS 1 */
+       { 0x011A, 0x0002 },   /* R282   - FLL EFS 2 */
+       { 0x0200, 0x0000 },   /* R512   - Mic Charge Pump 1 */
+       { 0x0201, 0x03FF },   /* R513   - Mic Charge Pump 2 */
+       { 0x0202, 0x9BDE },   /* R514   - DM Charge Pump 1 */
+       { 0x020C, 0x0000 },   /* R524   - Mic Bias Ctrl 1 */
+       { 0x020D, 0x0000 },   /* R525   - Mic Bias Ctrl 2 */
+       { 0x020F, 0x0000 },   /* R527   - Ear Piece Ctrl 1 */
+       { 0x0210, 0x0000 },   /* R528   - Ear Piece Ctrl 2 */
+       { 0x0301, 0x0000 },   /* R769   - Input Enables */
+       { 0x0302, 0x2240 },   /* R770   - IN1L Control */
+       { 0x0303, 0x0040 },   /* R771   - IN1R Control */
+       { 0x0304, 0x2240 },   /* R772   - IN2L Control */
+       { 0x0305, 0x0040 },   /* R773   - IN2R Control */
+       { 0x0306, 0x2240 },   /* R774   - IN3L Control */
+       { 0x0307, 0x0040 },   /* R775   - IN3R Control */
+       { 0x030A, 0x0000 },   /* R778   - RXANC_SRC */
+       { 0x030B, 0x0022 },   /* R779   - Input Volume Ramp */
+       { 0x030C, 0x0180 },   /* R780   - ADC Digital Volume 1L */
+       { 0x030D, 0x0180 },   /* R781   - ADC Digital Volume 1R */
+       { 0x030E, 0x0180 },   /* R782   - ADC Digital Volume 2L */
+       { 0x030F, 0x0180 },   /* R783   - ADC Digital Volume 2R */
+       { 0x0310, 0x0180 },   /* R784   - ADC Digital Volume 3L */
+       { 0x0311, 0x0180 },   /* R785   - ADC Digital Volume 3R */
+       { 0x0400, 0x0000 },   /* R1024  - Output Enables */
+       { 0x0401, 0x0000 },   /* R1025  - DAC Volume Limit 1L */
+       { 0x0402, 0x0000 },   /* R1026  - DAC Volume Limit 1R */
+       { 0x0403, 0x0000 },   /* R1027  - DAC Volume Limit 2L */
+       { 0x0404, 0x0000 },   /* R1028  - DAC Volume Limit 2R */
+       { 0x0409, 0x0000 },   /* R1033  - DAC AEC Control 1 */
+       { 0x040A, 0x0022 },   /* R1034  - Output Volume Ramp */
+       { 0x040B, 0x0180 },   /* R1035  - DAC Digital Volume 1L */
+       { 0x040C, 0x0180 },   /* R1036  - DAC Digital Volume 1R */
+       { 0x040D, 0x0180 },   /* R1037  - DAC Digital Volume 2L */
+       { 0x040E, 0x0180 },   /* R1038  - DAC Digital Volume 2R */
+       { 0x0417, 0x0069 },   /* R1047  - PDM 1 */
+       { 0x0418, 0x0000 },   /* R1048  - PDM 2 */
+       { 0x0500, 0x0000 },   /* R1280  - Audio IF 1_1 */
+       { 0x0501, 0x0008 },   /* R1281  - Audio IF 1_2 */
+       { 0x0502, 0x0000 },   /* R1282  - Audio IF 1_3 */
+       { 0x0503, 0x0000 },   /* R1283  - Audio IF 1_4 */
+       { 0x0504, 0x0000 },   /* R1284  - Audio IF 1_5 */
+       { 0x0505, 0x0001 },   /* R1285  - Audio IF 1_6 */
+       { 0x0506, 0x0001 },   /* R1286  - Audio IF 1_7 */
+       { 0x0507, 0x0000 },   /* R1287  - Audio IF 1_8 */
+       { 0x0508, 0x0000 },   /* R1288  - Audio IF 1_9 */
+       { 0x0509, 0x0000 },   /* R1289  - Audio IF 1_10 */
+       { 0x050A, 0x0000 },   /* R1290  - Audio IF 1_11 */
+       { 0x050B, 0x0000 },   /* R1291  - Audio IF 1_12 */
+       { 0x050C, 0x0000 },   /* R1292  - Audio IF 1_13 */
+       { 0x050D, 0x0000 },   /* R1293  - Audio IF 1_14 */
+       { 0x050E, 0x0000 },   /* R1294  - Audio IF 1_15 */
+       { 0x050F, 0x0000 },   /* R1295  - Audio IF 1_16 */
+       { 0x0510, 0x0000 },   /* R1296  - Audio IF 1_17 */
+       { 0x0511, 0x0000 },   /* R1297  - Audio IF 1_18 */
+       { 0x0512, 0x0000 },   /* R1298  - Audio IF 1_19 */
+       { 0x0513, 0x0000 },   /* R1299  - Audio IF 1_20 */
+       { 0x0514, 0x0000 },   /* R1300  - Audio IF 1_21 */
+       { 0x0515, 0x0001 },   /* R1301  - Audio IF 1_22 */
+       { 0x0600, 0x0000 },   /* R1536  - OUT1LMIX Input 1 Source */
+       { 0x0601, 0x0080 },   /* R1537  - OUT1LMIX Input 1 Volume */
+       { 0x0602, 0x0000 },   /* R1538  - OUT1LMIX Input 2 Source */
+       { 0x0603, 0x0080 },   /* R1539  - OUT1LMIX Input 2 Volume */
+       { 0x0604, 0x0000 },   /* R1540  - OUT1LMIX Input 3 Source */
+       { 0x0605, 0x0080 },   /* R1541  - OUT1LMIX Input 3 Volume */
+       { 0x0606, 0x0000 },   /* R1542  - OUT1LMIX Input 4 Source */
+       { 0x0607, 0x0080 },   /* R1543  - OUT1LMIX Input 4 Volume */
+       { 0x0608, 0x0000 },   /* R1544  - OUT1RMIX Input 1 Source */
+       { 0x0609, 0x0080 },   /* R1545  - OUT1RMIX Input 1 Volume */
+       { 0x060A, 0x0000 },   /* R1546  - OUT1RMIX Input 2 Source */
+       { 0x060B, 0x0080 },   /* R1547  - OUT1RMIX Input 2 Volume */
+       { 0x060C, 0x0000 },   /* R1548  - OUT1RMIX Input 3 Source */
+       { 0x060D, 0x0080 },   /* R1549  - OUT1RMIX Input 3 Volume */
+       { 0x060E, 0x0000 },   /* R1550  - OUT1RMIX Input 4 Source */
+       { 0x060F, 0x0080 },   /* R1551  - OUT1RMIX Input 4 Volume */
+       { 0x0610, 0x0000 },   /* R1552  - OUT2LMIX Input 1 Source */
+       { 0x0611, 0x0080 },   /* R1553  - OUT2LMIX Input 1 Volume */
+       { 0x0612, 0x0000 },   /* R1554  - OUT2LMIX Input 2 Source */
+       { 0x0613, 0x0080 },   /* R1555  - OUT2LMIX Input 2 Volume */
+       { 0x0614, 0x0000 },   /* R1556  - OUT2LMIX Input 3 Source */
+       { 0x0615, 0x0080 },   /* R1557  - OUT2LMIX Input 3 Volume */
+       { 0x0616, 0x0000 },   /* R1558  - OUT2LMIX Input 4 Source */
+       { 0x0617, 0x0080 },   /* R1559  - OUT2LMIX Input 4 Volume */
+       { 0x0618, 0x0000 },   /* R1560  - OUT2RMIX Input 1 Source */
+       { 0x0619, 0x0080 },   /* R1561  - OUT2RMIX Input 1 Volume */
+       { 0x061A, 0x0000 },   /* R1562  - OUT2RMIX Input 2 Source */
+       { 0x061B, 0x0080 },   /* R1563  - OUT2RMIX Input 2 Volume */
+       { 0x061C, 0x0000 },   /* R1564  - OUT2RMIX Input 3 Source */
+       { 0x061D, 0x0080 },   /* R1565  - OUT2RMIX Input 3 Volume */
+       { 0x061E, 0x0000 },   /* R1566  - OUT2RMIX Input 4 Source */
+       { 0x061F, 0x0080 },   /* R1567  - OUT2RMIX Input 4 Volume */
+       { 0x0620, 0x0000 },   /* R1568  - AIF1TX1MIX Input 1 Source */
+       { 0x0621, 0x0080 },   /* R1569  - AIF1TX1MIX Input 1 Volume */
+       { 0x0622, 0x0000 },   /* R1570  - AIF1TX1MIX Input 2 Source */
+       { 0x0623, 0x0080 },   /* R1571  - AIF1TX1MIX Input 2 Volume */
+       { 0x0624, 0x0000 },   /* R1572  - AIF1TX1MIX Input 3 Source */
+       { 0x0625, 0x0080 },   /* R1573  - AIF1TX1MIX Input 3 Volume */
+       { 0x0626, 0x0000 },   /* R1574  - AIF1TX1MIX Input 4 Source */
+       { 0x0627, 0x0080 },   /* R1575  - AIF1TX1MIX Input 4 Volume */
+       { 0x0628, 0x0000 },   /* R1576  - AIF1TX2MIX Input 1 Source */
+       { 0x0629, 0x0080 },   /* R1577  - AIF1TX2MIX Input 1 Volume */
+       { 0x062A, 0x0000 },   /* R1578  - AIF1TX2MIX Input 2 Source */
+       { 0x062B, 0x0080 },   /* R1579  - AIF1TX2MIX Input 2 Volume */
+       { 0x062C, 0x0000 },   /* R1580  - AIF1TX2MIX Input 3 Source */
+       { 0x062D, 0x0080 },   /* R1581  - AIF1TX2MIX Input 3 Volume */
+       { 0x062E, 0x0000 },   /* R1582  - AIF1TX2MIX Input 4 Source */
+       { 0x062F, 0x0080 },   /* R1583  - AIF1TX2MIX Input 4 Volume */
+       { 0x0630, 0x0000 },   /* R1584  - AIF1TX3MIX Input 1 Source */
+       { 0x0631, 0x0080 },   /* R1585  - AIF1TX3MIX Input 1 Volume */
+       { 0x0632, 0x0000 },   /* R1586  - AIF1TX3MIX Input 2 Source */
+       { 0x0633, 0x0080 },   /* R1587  - AIF1TX3MIX Input 2 Volume */
+       { 0x0634, 0x0000 },   /* R1588  - AIF1TX3MIX Input 3 Source */
+       { 0x0635, 0x0080 },   /* R1589  - AIF1TX3MIX Input 3 Volume */
+       { 0x0636, 0x0000 },   /* R1590  - AIF1TX3MIX Input 4 Source */
+       { 0x0637, 0x0080 },   /* R1591  - AIF1TX3MIX Input 4 Volume */
+       { 0x0638, 0x0000 },   /* R1592  - AIF1TX4MIX Input 1 Source */
+       { 0x0639, 0x0080 },   /* R1593  - AIF1TX4MIX Input 1 Volume */
+       { 0x063A, 0x0000 },   /* R1594  - AIF1TX4MIX Input 2 Source */
+       { 0x063B, 0x0080 },   /* R1595  - AIF1TX4MIX Input 2 Volume */
+       { 0x063C, 0x0000 },   /* R1596  - AIF1TX4MIX Input 3 Source */
+       { 0x063D, 0x0080 },   /* R1597  - AIF1TX4MIX Input 3 Volume */
+       { 0x063E, 0x0000 },   /* R1598  - AIF1TX4MIX Input 4 Source */
+       { 0x063F, 0x0080 },   /* R1599  - AIF1TX4MIX Input 4 Volume */
+       { 0x0640, 0x0000 },   /* R1600  - AIF1TX5MIX Input 1 Source */
+       { 0x0641, 0x0080 },   /* R1601  - AIF1TX5MIX Input 1 Volume */
+       { 0x0642, 0x0000 },   /* R1602  - AIF1TX5MIX Input 2 Source */
+       { 0x0643, 0x0080 },   /* R1603  - AIF1TX5MIX Input 2 Volume */
+       { 0x0644, 0x0000 },   /* R1604  - AIF1TX5MIX Input 3 Source */
+       { 0x0645, 0x0080 },   /* R1605  - AIF1TX5MIX Input 3 Volume */
+       { 0x0646, 0x0000 },   /* R1606  - AIF1TX5MIX Input 4 Source */
+       { 0x0647, 0x0080 },   /* R1607  - AIF1TX5MIX Input 4 Volume */
+       { 0x0648, 0x0000 },   /* R1608  - AIF1TX6MIX Input 1 Source */
+       { 0x0649, 0x0080 },   /* R1609  - AIF1TX6MIX Input 1 Volume */
+       { 0x064A, 0x0000 },   /* R1610  - AIF1TX6MIX Input 2 Source */
+       { 0x064B, 0x0080 },   /* R1611  - AIF1TX6MIX Input 2 Volume */
+       { 0x064C, 0x0000 },   /* R1612  - AIF1TX6MIX Input 3 Source */
+       { 0x064D, 0x0080 },   /* R1613  - AIF1TX6MIX Input 3 Volume */
+       { 0x064E, 0x0000 },   /* R1614  - AIF1TX6MIX Input 4 Source */
+       { 0x064F, 0x0080 },   /* R1615  - AIF1TX6MIX Input 4 Volume */
+       { 0x0650, 0x0000 },   /* R1616  - EQLMIX Input 1 Source */
+       { 0x0651, 0x0080 },   /* R1617  - EQLMIX Input 1 Volume */
+       { 0x0652, 0x0000 },   /* R1618  - EQLMIX Input 2 Source */
+       { 0x0653, 0x0080 },   /* R1619  - EQLMIX Input 2 Volume */
+       { 0x0654, 0x0000 },   /* R1620  - EQLMIX Input 3 Source */
+       { 0x0655, 0x0080 },   /* R1621  - EQLMIX Input 3 Volume */
+       { 0x0656, 0x0000 },   /* R1622  - EQLMIX Input 4 Source */
+       { 0x0657, 0x0080 },   /* R1623  - EQLMIX Input 4 Volume */
+       { 0x0658, 0x0000 },   /* R1624  - EQRMIX Input 1 Source */
+       { 0x0659, 0x0080 },   /* R1625  - EQRMIX Input 1 Volume */
+       { 0x065A, 0x0000 },   /* R1626  - EQRMIX Input 2 Source */
+       { 0x065B, 0x0080 },   /* R1627  - EQRMIX Input 2 Volume */
+       { 0x065C, 0x0000 },   /* R1628  - EQRMIX Input 3 Source */
+       { 0x065D, 0x0080 },   /* R1629  - EQRMIX Input 3 Volume */
+       { 0x065E, 0x0000 },   /* R1630  - EQRMIX Input 4 Source */
+       { 0x065F, 0x0080 },   /* R1631  - EQRMIX Input 4 Volume */
+       { 0x0660, 0x0000 },   /* R1632  - LHPF1MIX Input 1 Source */
+       { 0x0661, 0x0080 },   /* R1633  - LHPF1MIX Input 1 Volume */
+       { 0x0662, 0x0000 },   /* R1634  - LHPF1MIX Input 2 Source */
+       { 0x0663, 0x0080 },   /* R1635  - LHPF1MIX Input 2 Volume */
+       { 0x0664, 0x0000 },   /* R1636  - LHPF1MIX Input 3 Source */
+       { 0x0665, 0x0080 },   /* R1637  - LHPF1MIX Input 3 Volume */
+       { 0x0666, 0x0000 },   /* R1638  - LHPF1MIX Input 4 Source */
+       { 0x0667, 0x0080 },   /* R1639  - LHPF1MIX Input 4 Volume */
+       { 0x0668, 0x0000 },   /* R1640  - LHPF2MIX Input 1 Source */
+       { 0x0669, 0x0080 },   /* R1641  - LHPF2MIX Input 1 Volume */
+       { 0x066A, 0x0000 },   /* R1642  - LHPF2MIX Input 2 Source */
+       { 0x066B, 0x0080 },   /* R1643  - LHPF2MIX Input 2 Volume */
+       { 0x066C, 0x0000 },   /* R1644  - LHPF2MIX Input 3 Source */
+       { 0x066D, 0x0080 },   /* R1645  - LHPF2MIX Input 3 Volume */
+       { 0x066E, 0x0000 },   /* R1646  - LHPF2MIX Input 4 Source */
+       { 0x066F, 0x0080 },   /* R1647  - LHPF2MIX Input 4 Volume */
+       { 0x0670, 0x0000 },   /* R1648  - DSP1LMIX Input 1 Source */
+       { 0x0671, 0x0080 },   /* R1649  - DSP1LMIX Input 1 Volume */
+       { 0x0672, 0x0000 },   /* R1650  - DSP1LMIX Input 2 Source */
+       { 0x0673, 0x0080 },   /* R1651  - DSP1LMIX Input 2 Volume */
+       { 0x0674, 0x0000 },   /* R1652  - DSP1LMIX Input 3 Source */
+       { 0x0675, 0x0080 },   /* R1653  - DSP1LMIX Input 3 Volume */
+       { 0x0676, 0x0000 },   /* R1654  - DSP1LMIX Input 4 Source */
+       { 0x0677, 0x0080 },   /* R1655  - DSP1LMIX Input 4 Volume */
+       { 0x0678, 0x0000 },   /* R1656  - DSP1RMIX Input 1 Source */
+       { 0x0679, 0x0080 },   /* R1657  - DSP1RMIX Input 1 Volume */
+       { 0x067A, 0x0000 },   /* R1658  - DSP1RMIX Input 2 Source */
+       { 0x067B, 0x0080 },   /* R1659  - DSP1RMIX Input 2 Volume */
+       { 0x067C, 0x0000 },   /* R1660  - DSP1RMIX Input 3 Source */
+       { 0x067D, 0x0080 },   /* R1661  - DSP1RMIX Input 3 Volume */
+       { 0x067E, 0x0000 },   /* R1662  - DSP1RMIX Input 4 Source */
+       { 0x067F, 0x0080 },   /* R1663  - DSP1RMIX Input 4 Volume */
+       { 0x0680, 0x0000 },   /* R1664  - DSP1AUX1MIX Input 1 Source */
+       { 0x0681, 0x0000 },   /* R1665  - DSP1AUX2MIX Input 1 Source */
+       { 0x0682, 0x0000 },   /* R1666  - DSP1AUX3MIX Input 1 Source */
+       { 0x0683, 0x0000 },   /* R1667  - DSP1AUX4MIX Input 1 Source */
+       { 0x0684, 0x0000 },   /* R1668  - DSP1AUX5MIX Input 1 Source */
+       { 0x0685, 0x0000 },   /* R1669  - DSP1AUX6MIX Input 1 Source */
+       { 0x0686, 0x0000 },   /* R1670  - DSP2LMIX Input 1 Source */
+       { 0x0687, 0x0080 },   /* R1671  - DSP2LMIX Input 1 Volume */
+       { 0x0688, 0x0000 },   /* R1672  - DSP2LMIX Input 2 Source */
+       { 0x0689, 0x0080 },   /* R1673  - DSP2LMIX Input 2 Volume */
+       { 0x068A, 0x0000 },   /* R1674  - DSP2LMIX Input 3 Source */
+       { 0x068B, 0x0080 },   /* R1675  - DSP2LMIX Input 3 Volume */
+       { 0x068C, 0x0000 },   /* R1676  - DSP2LMIX Input 4 Source */
+       { 0x068D, 0x0080 },   /* R1677  - DSP2LMIX Input 4 Volume */
+       { 0x068E, 0x0000 },   /* R1678  - DSP2RMIX Input 1 Source */
+       { 0x068F, 0x0080 },   /* R1679  - DSP2RMIX Input 1 Volume */
+       { 0x0690, 0x0000 },   /* R1680  - DSP2RMIX Input 2 Source */
+       { 0x0691, 0x0080 },   /* R1681  - DSP2RMIX Input 2 Volume */
+       { 0x0692, 0x0000 },   /* R1682  - DSP2RMIX Input 3 Source */
+       { 0x0693, 0x0080 },   /* R1683  - DSP2RMIX Input 3 Volume */
+       { 0x0694, 0x0000 },   /* R1684  - DSP2RMIX Input 4 Source */
+       { 0x0695, 0x0080 },   /* R1685  - DSP2RMIX Input 4 Volume */
+       { 0x0696, 0x0000 },   /* R1686  - DSP2AUX1MIX Input 1 Source */
+       { 0x0697, 0x0000 },   /* R1687  - DSP2AUX2MIX Input 1 Source */
+       { 0x0698, 0x0000 },   /* R1688  - DSP2AUX3MIX Input 1 Source */
+       { 0x0699, 0x0000 },   /* R1689  - DSP2AUX4MIX Input 1 Source */
+       { 0x069A, 0x0000 },   /* R1690  - DSP2AUX5MIX Input 1 Source */
+       { 0x069B, 0x0000 },   /* R1691  - DSP2AUX6MIX Input 1 Source */
+       { 0x0700, 0xA101 },   /* R1792  - GPIO CTRL 1 */
+       { 0x0701, 0xA101 },   /* R1793  - GPIO CTRL 2 */
+       { 0x0702, 0xA101 },   /* R1794  - GPIO CTRL 3 */
+       { 0x0703, 0xA101 },   /* R1795  - GPIO CTRL 4 */
+       { 0x0709, 0x0000 },   /* R1801  - Misc Pad Ctrl 1 */
+       { 0x0801, 0x00FF },   /* R2049  - Interrupt Status 1 Mask */
+       { 0x0804, 0xFFFF },   /* R2052  - Interrupt Status 2 Mask */
+       { 0x0808, 0x0000 },   /* R2056  - Interrupt Control */
+       { 0x0900, 0x0000 },   /* R2304  - EQL_1 */
+       { 0x0901, 0x0000 },   /* R2305  - EQL_2 */
+       { 0x0902, 0x0000 },   /* R2306  - EQL_3 */
+       { 0x0903, 0x0000 },   /* R2307  - EQL_4 */
+       { 0x0904, 0x0000 },   /* R2308  - EQL_5 */
+       { 0x0905, 0x0000 },   /* R2309  - EQL_6 */
+       { 0x0906, 0x0000 },   /* R2310  - EQL_7 */
+       { 0x0907, 0x0000 },   /* R2311  - EQL_8 */
+       { 0x0908, 0x0000 },   /* R2312  - EQL_9 */
+       { 0x0909, 0x0000 },   /* R2313  - EQL_10 */
+       { 0x090A, 0x0000 },   /* R2314  - EQL_11 */
+       { 0x090B, 0x0000 },   /* R2315  - EQL_12 */
+       { 0x090C, 0x0000 },   /* R2316  - EQL_13 */
+       { 0x090D, 0x0000 },   /* R2317  - EQL_14 */
+       { 0x090E, 0x0000 },   /* R2318  - EQL_15 */
+       { 0x090F, 0x0000 },   /* R2319  - EQL_16 */
+       { 0x0910, 0x0000 },   /* R2320  - EQL_17 */
+       { 0x0911, 0x0000 },   /* R2321  - EQL_18 */
+       { 0x0912, 0x0000 },   /* R2322  - EQL_19 */
+       { 0x0913, 0x0000 },   /* R2323  - EQL_20 */
+       { 0x0916, 0x0000 },   /* R2326  - EQR_1 */
+       { 0x0917, 0x0000 },   /* R2327  - EQR_2 */
+       { 0x0918, 0x0000 },   /* R2328  - EQR_3 */
+       { 0x0919, 0x0000 },   /* R2329  - EQR_4 */
+       { 0x091A, 0x0000 },   /* R2330  - EQR_5 */
+       { 0x091B, 0x0000 },   /* R2331  - EQR_6 */
+       { 0x091C, 0x0000 },   /* R2332  - EQR_7 */
+       { 0x091D, 0x0000 },   /* R2333  - EQR_8 */
+       { 0x091E, 0x0000 },   /* R2334  - EQR_9 */
+       { 0x091F, 0x0000 },   /* R2335  - EQR_10 */
+       { 0x0920, 0x0000 },   /* R2336  - EQR_11 */
+       { 0x0921, 0x0000 },   /* R2337  - EQR_12 */
+       { 0x0922, 0x0000 },   /* R2338  - EQR_13 */
+       { 0x0923, 0x0000 },   /* R2339  - EQR_14 */
+       { 0x0924, 0x0000 },   /* R2340  - EQR_15 */
+       { 0x0925, 0x0000 },   /* R2341  - EQR_16 */
+       { 0x0926, 0x0000 },   /* R2342  - EQR_17 */
+       { 0x0927, 0x0000 },   /* R2343  - EQR_18 */
+       { 0x0928, 0x0000 },   /* R2344  - EQR_19 */
+       { 0x0929, 0x0000 },   /* R2345  - EQR_20 */
+       { 0x093E, 0x0000 },   /* R2366  - HPLPF1_1 */
+       { 0x093F, 0x0000 },   /* R2367  - HPLPF1_2 */
+       { 0x0942, 0x0000 },   /* R2370  - HPLPF2_1 */
+       { 0x0943, 0x0000 },   /* R2371  - HPLPF2_2 */
+       { 0x0A00, 0x0000 },   /* R2560  - DSP1 Control 1 */
+       { 0x0A02, 0x0000 },   /* R2562  - DSP1 Control 2 */
+       { 0x0A03, 0x0000 },   /* R2563  - DSP1 Control 3 */
+       { 0x0A04, 0x0000 },   /* R2564  - DSP1 Control 4 */
+       { 0x0A06, 0x0000 },   /* R2566  - DSP1 Control 5 */
+       { 0x0A07, 0x0000 },   /* R2567  - DSP1 Control 6 */
+       { 0x0A08, 0x0000 },   /* R2568  - DSP1 Control 7 */
+       { 0x0A09, 0x0000 },   /* R2569  - DSP1 Control 8 */
+       { 0x0A0A, 0x0000 },   /* R2570  - DSP1 Control 9 */
+       { 0x0A0B, 0x0000 },   /* R2571  - DSP1 Control 10 */
+       { 0x0A0C, 0x0000 },   /* R2572  - DSP1 Control 11 */
+       { 0x0A0D, 0x0000 },   /* R2573  - DSP1 Control 12 */
+       { 0x0A0F, 0x0000 },   /* R2575  - DSP1 Control 13 */
+       { 0x0A10, 0x0000 },   /* R2576  - DSP1 Control 14 */
+       { 0x0A11, 0x0000 },   /* R2577  - DSP1 Control 15 */
+       { 0x0A12, 0x0000 },   /* R2578  - DSP1 Control 16 */
+       { 0x0A13, 0x0000 },   /* R2579  - DSP1 Control 17 */
+       { 0x0A14, 0x0000 },   /* R2580  - DSP1 Control 18 */
+       { 0x0A16, 0x0000 },   /* R2582  - DSP1 Control 19 */
+       { 0x0A17, 0x0000 },   /* R2583  - DSP1 Control 20 */
+       { 0x0A18, 0x0000 },   /* R2584  - DSP1 Control 21 */
+       { 0x0A1A, 0x1800 },   /* R2586  - DSP1 Control 22 */
+       { 0x0A1B, 0x1000 },   /* R2587  - DSP1 Control 23 */
+       { 0x0A1C, 0x0400 },   /* R2588  - DSP1 Control 24 */
+       { 0x0A1E, 0x0000 },   /* R2590  - DSP1 Control 25 */
+       { 0x0A20, 0x0000 },   /* R2592  - DSP1 Control 26 */
+       { 0x0A21, 0x0000 },   /* R2593  - DSP1 Control 27 */
+       { 0x0A22, 0x0000 },   /* R2594  - DSP1 Control 28 */
+       { 0x0A23, 0x0000 },   /* R2595  - DSP1 Control 29 */
+       { 0x0A24, 0x0000 },   /* R2596  - DSP1 Control 30 */
+       { 0x0A26, 0x0000 },   /* R2598  - DSP1 Control 31 */
+       { 0x0B00, 0x0000 },   /* R2816  - DSP2 Control 1 */
+       { 0x0B02, 0x0000 },   /* R2818  - DSP2 Control 2 */
+       { 0x0B03, 0x0000 },   /* R2819  - DSP2 Control 3 */
+       { 0x0B04, 0x0000 },   /* R2820  - DSP2 Control 4 */
+       { 0x0B06, 0x0000 },   /* R2822  - DSP2 Control 5 */
+       { 0x0B07, 0x0000 },   /* R2823  - DSP2 Control 6 */
+       { 0x0B08, 0x0000 },   /* R2824  - DSP2 Control 7 */
+       { 0x0B09, 0x0000 },   /* R2825  - DSP2 Control 8 */
+       { 0x0B0A, 0x0000 },   /* R2826  - DSP2 Control 9 */
+       { 0x0B0B, 0x0000 },   /* R2827  - DSP2 Control 10 */
+       { 0x0B0C, 0x0000 },   /* R2828  - DSP2 Control 11 */
+       { 0x0B0D, 0x0000 },   /* R2829  - DSP2 Control 12 */
+       { 0x0B0F, 0x0000 },   /* R2831  - DSP2 Control 13 */
+       { 0x0B10, 0x0000 },   /* R2832  - DSP2 Control 14 */
+       { 0x0B11, 0x0000 },   /* R2833  - DSP2 Control 15 */
+       { 0x0B12, 0x0000 },   /* R2834  - DSP2 Control 16 */
+       { 0x0B13, 0x0000 },   /* R2835  - DSP2 Control 17 */
+       { 0x0B14, 0x0000 },   /* R2836  - DSP2 Control 18 */
+       { 0x0B16, 0x0000 },   /* R2838  - DSP2 Control 19 */
+       { 0x0B17, 0x0000 },   /* R2839  - DSP2 Control 20 */
+       { 0x0B18, 0x0000 },   /* R2840  - DSP2 Control 21 */
+       { 0x0B1A, 0x0800 },   /* R2842  - DSP2 Control 22 */
+       { 0x0B1B, 0x1000 },   /* R2843  - DSP2 Control 23 */
+       { 0x0B1C, 0x0400 },   /* R2844  - DSP2 Control 24 */
+       { 0x0B1E, 0x0000 },   /* R2846  - DSP2 Control 25 */
+       { 0x0B20, 0x0000 },   /* R2848  - DSP2 Control 26 */
+       { 0x0B21, 0x0000 },   /* R2849  - DSP2 Control 27 */
+       { 0x0B22, 0x0000 },   /* R2850  - DSP2 Control 28 */
+       { 0x0B23, 0x0000 },   /* R2851  - DSP2 Control 29 */
+       { 0x0B24, 0x0000 },   /* R2852  - DSP2 Control 30 */
+       { 0x0B26, 0x0000 },   /* R2854  - DSP2 Control 31 */
+};
+
+static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM2200_SOFTWARE_RESET:
+       case WM2200_DEVICE_REVISION:
+       case WM2200_ADPS1_IRQ0:
+       case WM2200_ADPS1_IRQ1:
+       case WM2200_INTERRUPT_STATUS_1:
+       case WM2200_INTERRUPT_STATUS_2:
+       case WM2200_INTERRUPT_RAW_STATUS_2:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool wm2200_readable_register(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM2200_SOFTWARE_RESET:
+       case WM2200_DEVICE_REVISION:
+       case WM2200_TONE_GENERATOR_1:
+       case WM2200_CLOCKING_3:
+       case WM2200_CLOCKING_4:
+       case WM2200_FLL_CONTROL_1:
+       case WM2200_FLL_CONTROL_2:
+       case WM2200_FLL_CONTROL_3:
+       case WM2200_FLL_CONTROL_4:
+       case WM2200_FLL_CONTROL_6:
+       case WM2200_FLL_CONTROL_7:
+       case WM2200_FLL_EFS_1:
+       case WM2200_FLL_EFS_2:
+       case WM2200_MIC_CHARGE_PUMP_1:
+       case WM2200_MIC_CHARGE_PUMP_2:
+       case WM2200_DM_CHARGE_PUMP_1:
+       case WM2200_MIC_BIAS_CTRL_1:
+       case WM2200_MIC_BIAS_CTRL_2:
+       case WM2200_EAR_PIECE_CTRL_1:
+       case WM2200_EAR_PIECE_CTRL_2:
+       case WM2200_INPUT_ENABLES:
+       case WM2200_IN1L_CONTROL:
+       case WM2200_IN1R_CONTROL:
+       case WM2200_IN2L_CONTROL:
+       case WM2200_IN2R_CONTROL:
+       case WM2200_IN3L_CONTROL:
+       case WM2200_IN3R_CONTROL:
+       case WM2200_RXANC_SRC:
+       case WM2200_INPUT_VOLUME_RAMP:
+       case WM2200_ADC_DIGITAL_VOLUME_1L:
+       case WM2200_ADC_DIGITAL_VOLUME_1R:
+       case WM2200_ADC_DIGITAL_VOLUME_2L:
+       case WM2200_ADC_DIGITAL_VOLUME_2R:
+       case WM2200_ADC_DIGITAL_VOLUME_3L:
+       case WM2200_ADC_DIGITAL_VOLUME_3R:
+       case WM2200_OUTPUT_ENABLES:
+       case WM2200_DAC_VOLUME_LIMIT_1L:
+       case WM2200_DAC_VOLUME_LIMIT_1R:
+       case WM2200_DAC_VOLUME_LIMIT_2L:
+       case WM2200_DAC_VOLUME_LIMIT_2R:
+       case WM2200_DAC_AEC_CONTROL_1:
+       case WM2200_OUTPUT_VOLUME_RAMP:
+       case WM2200_DAC_DIGITAL_VOLUME_1L:
+       case WM2200_DAC_DIGITAL_VOLUME_1R:
+       case WM2200_DAC_DIGITAL_VOLUME_2L:
+       case WM2200_DAC_DIGITAL_VOLUME_2R:
+       case WM2200_PDM_1:
+       case WM2200_PDM_2:
+       case WM2200_AUDIO_IF_1_1:
+       case WM2200_AUDIO_IF_1_2:
+       case WM2200_AUDIO_IF_1_3:
+       case WM2200_AUDIO_IF_1_4:
+       case WM2200_AUDIO_IF_1_5:
+       case WM2200_AUDIO_IF_1_6:
+       case WM2200_AUDIO_IF_1_7:
+       case WM2200_AUDIO_IF_1_8:
+       case WM2200_AUDIO_IF_1_9:
+       case WM2200_AUDIO_IF_1_10:
+       case WM2200_AUDIO_IF_1_11:
+       case WM2200_AUDIO_IF_1_12:
+       case WM2200_AUDIO_IF_1_13:
+       case WM2200_AUDIO_IF_1_14:
+       case WM2200_AUDIO_IF_1_15:
+       case WM2200_AUDIO_IF_1_16:
+       case WM2200_AUDIO_IF_1_17:
+       case WM2200_AUDIO_IF_1_18:
+       case WM2200_AUDIO_IF_1_19:
+       case WM2200_AUDIO_IF_1_20:
+       case WM2200_AUDIO_IF_1_21:
+       case WM2200_AUDIO_IF_1_22:
+       case WM2200_OUT1LMIX_INPUT_1_SOURCE:
+       case WM2200_OUT1LMIX_INPUT_1_VOLUME:
+       case WM2200_OUT1LMIX_INPUT_2_SOURCE:
+       case WM2200_OUT1LMIX_INPUT_2_VOLUME:
+       case WM2200_OUT1LMIX_INPUT_3_SOURCE:
+       case WM2200_OUT1LMIX_INPUT_3_VOLUME:
+       case WM2200_OUT1LMIX_INPUT_4_SOURCE:
+       case WM2200_OUT1LMIX_INPUT_4_VOLUME:
+       case WM2200_OUT1RMIX_INPUT_1_SOURCE:
+       case WM2200_OUT1RMIX_INPUT_1_VOLUME:
+       case WM2200_OUT1RMIX_INPUT_2_SOURCE:
+       case WM2200_OUT1RMIX_INPUT_2_VOLUME:
+       case WM2200_OUT1RMIX_INPUT_3_SOURCE:
+       case WM2200_OUT1RMIX_INPUT_3_VOLUME:
+       case WM2200_OUT1RMIX_INPUT_4_SOURCE:
+       case WM2200_OUT1RMIX_INPUT_4_VOLUME:
+       case WM2200_OUT2LMIX_INPUT_1_SOURCE:
+       case WM2200_OUT2LMIX_INPUT_1_VOLUME:
+       case WM2200_OUT2LMIX_INPUT_2_SOURCE:
+       case WM2200_OUT2LMIX_INPUT_2_VOLUME:
+       case WM2200_OUT2LMIX_INPUT_3_SOURCE:
+       case WM2200_OUT2LMIX_INPUT_3_VOLUME:
+       case WM2200_OUT2LMIX_INPUT_4_SOURCE:
+       case WM2200_OUT2LMIX_INPUT_4_VOLUME:
+       case WM2200_OUT2RMIX_INPUT_1_SOURCE:
+       case WM2200_OUT2RMIX_INPUT_1_VOLUME:
+       case WM2200_OUT2RMIX_INPUT_2_SOURCE:
+       case WM2200_OUT2RMIX_INPUT_2_VOLUME:
+       case WM2200_OUT2RMIX_INPUT_3_SOURCE:
+       case WM2200_OUT2RMIX_INPUT_3_VOLUME:
+       case WM2200_OUT2RMIX_INPUT_4_SOURCE:
+       case WM2200_OUT2RMIX_INPUT_4_VOLUME:
+       case WM2200_AIF1TX1MIX_INPUT_1_SOURCE:
+       case WM2200_AIF1TX1MIX_INPUT_1_VOLUME:
+       case WM2200_AIF1TX1MIX_INPUT_2_SOURCE:
+       case WM2200_AIF1TX1MIX_INPUT_2_VOLUME:
+       case WM2200_AIF1TX1MIX_INPUT_3_SOURCE:
+       case WM2200_AIF1TX1MIX_INPUT_3_VOLUME:
+       case WM2200_AIF1TX1MIX_INPUT_4_SOURCE:
+       case WM2200_AIF1TX1MIX_INPUT_4_VOLUME:
+       case WM2200_AIF1TX2MIX_INPUT_1_SOURCE:
+       case WM2200_AIF1TX2MIX_INPUT_1_VOLUME:
+       case WM2200_AIF1TX2MIX_INPUT_2_SOURCE:
+       case WM2200_AIF1TX2MIX_INPUT_2_VOLUME:
+       case WM2200_AIF1TX2MIX_INPUT_3_SOURCE:
+       case WM2200_AIF1TX2MIX_INPUT_3_VOLUME:
+       case WM2200_AIF1TX2MIX_INPUT_4_SOURCE:
+       case WM2200_AIF1TX2MIX_INPUT_4_VOLUME:
+       case WM2200_AIF1TX3MIX_INPUT_1_SOURCE:
+       case WM2200_AIF1TX3MIX_INPUT_1_VOLUME:
+       case WM2200_AIF1TX3MIX_INPUT_2_SOURCE:
+       case WM2200_AIF1TX3MIX_INPUT_2_VOLUME:
+       case WM2200_AIF1TX3MIX_INPUT_3_SOURCE:
+       case WM2200_AIF1TX3MIX_INPUT_3_VOLUME:
+       case WM2200_AIF1TX3MIX_INPUT_4_SOURCE:
+       case WM2200_AIF1TX3MIX_INPUT_4_VOLUME:
+       case WM2200_AIF1TX4MIX_INPUT_1_SOURCE:
+       case WM2200_AIF1TX4MIX_INPUT_1_VOLUME:
+       case WM2200_AIF1TX4MIX_INPUT_2_SOURCE:
+       case WM2200_AIF1TX4MIX_INPUT_2_VOLUME:
+       case WM2200_AIF1TX4MIX_INPUT_3_SOURCE:
+       case WM2200_AIF1TX4MIX_INPUT_3_VOLUME:
+       case WM2200_AIF1TX4MIX_INPUT_4_SOURCE:
+       case WM2200_AIF1TX4MIX_INPUT_4_VOLUME:
+       case WM2200_AIF1TX5MIX_INPUT_1_SOURCE:
+       case WM2200_AIF1TX5MIX_INPUT_1_VOLUME:
+       case WM2200_AIF1TX5MIX_INPUT_2_SOURCE:
+       case WM2200_AIF1TX5MIX_INPUT_2_VOLUME:
+       case WM2200_AIF1TX5MIX_INPUT_3_SOURCE:
+       case WM2200_AIF1TX5MIX_INPUT_3_VOLUME:
+       case WM2200_AIF1TX5MIX_INPUT_4_SOURCE:
+       case WM2200_AIF1TX5MIX_INPUT_4_VOLUME:
+       case WM2200_AIF1TX6MIX_INPUT_1_SOURCE:
+       case WM2200_AIF1TX6MIX_INPUT_1_VOLUME:
+       case WM2200_AIF1TX6MIX_INPUT_2_SOURCE:
+       case WM2200_AIF1TX6MIX_INPUT_2_VOLUME:
+       case WM2200_AIF1TX6MIX_INPUT_3_SOURCE:
+       case WM2200_AIF1TX6MIX_INPUT_3_VOLUME:
+       case WM2200_AIF1TX6MIX_INPUT_4_SOURCE:
+       case WM2200_AIF1TX6MIX_INPUT_4_VOLUME:
+       case WM2200_EQLMIX_INPUT_1_SOURCE:
+       case WM2200_EQLMIX_INPUT_1_VOLUME:
+       case WM2200_EQLMIX_INPUT_2_SOURCE:
+       case WM2200_EQLMIX_INPUT_2_VOLUME:
+       case WM2200_EQLMIX_INPUT_3_SOURCE:
+       case WM2200_EQLMIX_INPUT_3_VOLUME:
+       case WM2200_EQLMIX_INPUT_4_SOURCE:
+       case WM2200_EQLMIX_INPUT_4_VOLUME:
+       case WM2200_EQRMIX_INPUT_1_SOURCE:
+       case WM2200_EQRMIX_INPUT_1_VOLUME:
+       case WM2200_EQRMIX_INPUT_2_SOURCE:
+       case WM2200_EQRMIX_INPUT_2_VOLUME:
+       case WM2200_EQRMIX_INPUT_3_SOURCE:
+       case WM2200_EQRMIX_INPUT_3_VOLUME:
+       case WM2200_EQRMIX_INPUT_4_SOURCE:
+       case WM2200_EQRMIX_INPUT_4_VOLUME:
+       case WM2200_LHPF1MIX_INPUT_1_SOURCE:
+       case WM2200_LHPF1MIX_INPUT_1_VOLUME:
+       case WM2200_LHPF1MIX_INPUT_2_SOURCE:
+       case WM2200_LHPF1MIX_INPUT_2_VOLUME:
+       case WM2200_LHPF1MIX_INPUT_3_SOURCE:
+       case WM2200_LHPF1MIX_INPUT_3_VOLUME:
+       case WM2200_LHPF1MIX_INPUT_4_SOURCE:
+       case WM2200_LHPF1MIX_INPUT_4_VOLUME:
+       case WM2200_LHPF2MIX_INPUT_1_SOURCE:
+       case WM2200_LHPF2MIX_INPUT_1_VOLUME:
+       case WM2200_LHPF2MIX_INPUT_2_SOURCE:
+       case WM2200_LHPF2MIX_INPUT_2_VOLUME:
+       case WM2200_LHPF2MIX_INPUT_3_SOURCE:
+       case WM2200_LHPF2MIX_INPUT_3_VOLUME:
+       case WM2200_LHPF2MIX_INPUT_4_SOURCE:
+       case WM2200_LHPF2MIX_INPUT_4_VOLUME:
+       case WM2200_DSP1LMIX_INPUT_1_SOURCE:
+       case WM2200_DSP1LMIX_INPUT_1_VOLUME:
+       case WM2200_DSP1LMIX_INPUT_2_SOURCE:
+       case WM2200_DSP1LMIX_INPUT_2_VOLUME:
+       case WM2200_DSP1LMIX_INPUT_3_SOURCE:
+       case WM2200_DSP1LMIX_INPUT_3_VOLUME:
+       case WM2200_DSP1LMIX_INPUT_4_SOURCE:
+       case WM2200_DSP1LMIX_INPUT_4_VOLUME:
+       case WM2200_DSP1RMIX_INPUT_1_SOURCE:
+       case WM2200_DSP1RMIX_INPUT_1_VOLUME:
+       case WM2200_DSP1RMIX_INPUT_2_SOURCE:
+       case WM2200_DSP1RMIX_INPUT_2_VOLUME:
+       case WM2200_DSP1RMIX_INPUT_3_SOURCE:
+       case WM2200_DSP1RMIX_INPUT_3_VOLUME:
+       case WM2200_DSP1RMIX_INPUT_4_SOURCE:
+       case WM2200_DSP1RMIX_INPUT_4_VOLUME:
+       case WM2200_DSP1AUX1MIX_INPUT_1_SOURCE:
+       case WM2200_DSP1AUX2MIX_INPUT_1_SOURCE:
+       case WM2200_DSP1AUX3MIX_INPUT_1_SOURCE:
+       case WM2200_DSP1AUX4MIX_INPUT_1_SOURCE:
+       case WM2200_DSP1AUX5MIX_INPUT_1_SOURCE:
+       case WM2200_DSP1AUX6MIX_INPUT_1_SOURCE:
+       case WM2200_DSP2LMIX_INPUT_1_SOURCE:
+       case WM2200_DSP2LMIX_INPUT_1_VOLUME:
+       case WM2200_DSP2LMIX_INPUT_2_SOURCE:
+       case WM2200_DSP2LMIX_INPUT_2_VOLUME:
+       case WM2200_DSP2LMIX_INPUT_3_SOURCE:
+       case WM2200_DSP2LMIX_INPUT_3_VOLUME:
+       case WM2200_DSP2LMIX_INPUT_4_SOURCE:
+       case WM2200_DSP2LMIX_INPUT_4_VOLUME:
+       case WM2200_DSP2RMIX_INPUT_1_SOURCE:
+       case WM2200_DSP2RMIX_INPUT_1_VOLUME:
+       case WM2200_DSP2RMIX_INPUT_2_SOURCE:
+       case WM2200_DSP2RMIX_INPUT_2_VOLUME:
+       case WM2200_DSP2RMIX_INPUT_3_SOURCE:
+       case WM2200_DSP2RMIX_INPUT_3_VOLUME:
+       case WM2200_DSP2RMIX_INPUT_4_SOURCE:
+       case WM2200_DSP2RMIX_INPUT_4_VOLUME:
+       case WM2200_DSP2AUX1MIX_INPUT_1_SOURCE:
+       case WM2200_DSP2AUX2MIX_INPUT_1_SOURCE:
+       case WM2200_DSP2AUX3MIX_INPUT_1_SOURCE:
+       case WM2200_DSP2AUX4MIX_INPUT_1_SOURCE:
+       case WM2200_DSP2AUX5MIX_INPUT_1_SOURCE:
+       case WM2200_DSP2AUX6MIX_INPUT_1_SOURCE:
+       case WM2200_GPIO_CTRL_1:
+       case WM2200_GPIO_CTRL_2:
+       case WM2200_GPIO_CTRL_3:
+       case WM2200_GPIO_CTRL_4:
+       case WM2200_ADPS1_IRQ0:
+       case WM2200_ADPS1_IRQ1:
+       case WM2200_MISC_PAD_CTRL_1:
+       case WM2200_INTERRUPT_STATUS_1:
+       case WM2200_INTERRUPT_STATUS_1_MASK:
+       case WM2200_INTERRUPT_STATUS_2:
+       case WM2200_INTERRUPT_RAW_STATUS_2:
+       case WM2200_INTERRUPT_STATUS_2_MASK:
+       case WM2200_INTERRUPT_CONTROL:
+       case WM2200_EQL_1:
+       case WM2200_EQL_2:
+       case WM2200_EQL_3:
+       case WM2200_EQL_4:
+       case WM2200_EQL_5:
+       case WM2200_EQL_6:
+       case WM2200_EQL_7:
+       case WM2200_EQL_8:
+       case WM2200_EQL_9:
+       case WM2200_EQL_10:
+       case WM2200_EQL_11:
+       case WM2200_EQL_12:
+       case WM2200_EQL_13:
+       case WM2200_EQL_14:
+       case WM2200_EQL_15:
+       case WM2200_EQL_16:
+       case WM2200_EQL_17:
+       case WM2200_EQL_18:
+       case WM2200_EQL_19:
+       case WM2200_EQL_20:
+       case WM2200_EQR_1:
+       case WM2200_EQR_2:
+       case WM2200_EQR_3:
+       case WM2200_EQR_4:
+       case WM2200_EQR_5:
+       case WM2200_EQR_6:
+       case WM2200_EQR_7:
+       case WM2200_EQR_8:
+       case WM2200_EQR_9:
+       case WM2200_EQR_10:
+       case WM2200_EQR_11:
+       case WM2200_EQR_12:
+       case WM2200_EQR_13:
+       case WM2200_EQR_14:
+       case WM2200_EQR_15:
+       case WM2200_EQR_16:
+       case WM2200_EQR_17:
+       case WM2200_EQR_18:
+       case WM2200_EQR_19:
+       case WM2200_EQR_20:
+       case WM2200_HPLPF1_1:
+       case WM2200_HPLPF1_2:
+       case WM2200_HPLPF2_1:
+       case WM2200_HPLPF2_2:
+       case WM2200_DSP1_CONTROL_1:
+       case WM2200_DSP1_CONTROL_2:
+       case WM2200_DSP1_CONTROL_3:
+       case WM2200_DSP1_CONTROL_4:
+       case WM2200_DSP1_CONTROL_5:
+       case WM2200_DSP1_CONTROL_6:
+       case WM2200_DSP1_CONTROL_7:
+       case WM2200_DSP1_CONTROL_8:
+       case WM2200_DSP1_CONTROL_9:
+       case WM2200_DSP1_CONTROL_10:
+       case WM2200_DSP1_CONTROL_11:
+       case WM2200_DSP1_CONTROL_12:
+       case WM2200_DSP1_CONTROL_13:
+       case WM2200_DSP1_CONTROL_14:
+       case WM2200_DSP1_CONTROL_15:
+       case WM2200_DSP1_CONTROL_16:
+       case WM2200_DSP1_CONTROL_17:
+       case WM2200_DSP1_CONTROL_18:
+       case WM2200_DSP1_CONTROL_19:
+       case WM2200_DSP1_CONTROL_20:
+       case WM2200_DSP1_CONTROL_21:
+       case WM2200_DSP1_CONTROL_22:
+       case WM2200_DSP1_CONTROL_23:
+       case WM2200_DSP1_CONTROL_24:
+       case WM2200_DSP1_CONTROL_25:
+       case WM2200_DSP1_CONTROL_26:
+       case WM2200_DSP1_CONTROL_27:
+       case WM2200_DSP1_CONTROL_28:
+       case WM2200_DSP1_CONTROL_29:
+       case WM2200_DSP1_CONTROL_30:
+       case WM2200_DSP1_CONTROL_31:
+       case WM2200_DSP2_CONTROL_1:
+       case WM2200_DSP2_CONTROL_2:
+       case WM2200_DSP2_CONTROL_3:
+       case WM2200_DSP2_CONTROL_4:
+       case WM2200_DSP2_CONTROL_5:
+       case WM2200_DSP2_CONTROL_6:
+       case WM2200_DSP2_CONTROL_7:
+       case WM2200_DSP2_CONTROL_8:
+       case WM2200_DSP2_CONTROL_9:
+       case WM2200_DSP2_CONTROL_10:
+       case WM2200_DSP2_CONTROL_11:
+       case WM2200_DSP2_CONTROL_12:
+       case WM2200_DSP2_CONTROL_13:
+       case WM2200_DSP2_CONTROL_14:
+       case WM2200_DSP2_CONTROL_15:
+       case WM2200_DSP2_CONTROL_16:
+       case WM2200_DSP2_CONTROL_17:
+       case WM2200_DSP2_CONTROL_18:
+       case WM2200_DSP2_CONTROL_19:
+       case WM2200_DSP2_CONTROL_20:
+       case WM2200_DSP2_CONTROL_21:
+       case WM2200_DSP2_CONTROL_22:
+       case WM2200_DSP2_CONTROL_23:
+       case WM2200_DSP2_CONTROL_24:
+       case WM2200_DSP2_CONTROL_25:
+       case WM2200_DSP2_CONTROL_26:
+       case WM2200_DSP2_CONTROL_27:
+       case WM2200_DSP2_CONTROL_28:
+       case WM2200_DSP2_CONTROL_29:
+       case WM2200_DSP2_CONTROL_30:
+       case WM2200_DSP2_CONTROL_31:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static const struct reg_default wm2200_reva_patch[] = {
+       { 0x07, 0x0003 },
+       { 0x102, 0x0200 },
+       { 0x203, 0x0084 },
+       { 0x201, 0x83FF },
+       { 0x20C, 0x0062 },
+       { 0x20D, 0x0062 },
+       { 0x207, 0x2002 },
+       { 0x208, 0x20C0 },
+       { 0x21D, 0x01C0 },
+       { 0x50A, 0x0001 },
+       { 0x50B, 0x0002 },
+       { 0x50C, 0x0003 },
+       { 0x50D, 0x0004 },
+       { 0x50E, 0x0005 },
+       { 0x510, 0x0001 },
+       { 0x511, 0x0002 },
+       { 0x512, 0x0003 },
+       { 0x513, 0x0004 },
+       { 0x514, 0x0005 },
+       { 0x515, 0x0000 },
+       { 0x201, 0x8084 },
+       { 0x202, 0xBBDE },
+       { 0x203, 0x00EC },
+       { 0x500, 0x8000 },
+       { 0x507, 0x1820 },
+       { 0x508, 0x1820 },
+       { 0x505, 0x0300 },
+       { 0x506, 0x0300 },
+       { 0x302, 0x2280 },
+       { 0x303, 0x0080 },
+       { 0x304, 0x2280 },
+       { 0x305, 0x0080 },
+       { 0x306, 0x2280 },
+       { 0x307, 0x0080 },
+       { 0x401, 0x0080 },
+       { 0x402, 0x0080 },
+       { 0x417, 0x3069 },
+       { 0x900, 0x6318 },
+       { 0x901, 0x6300 },
+       { 0x902, 0x0FC8 },
+       { 0x903, 0x03FE },
+       { 0x904, 0x00E0 },
+       { 0x905, 0x1EC4 },
+       { 0x906, 0xF136 },
+       { 0x907, 0x0409 },
+       { 0x908, 0x04CC },
+       { 0x909, 0x1C9B },
+       { 0x90A, 0xF337 },
+       { 0x90B, 0x040B },
+       { 0x90C, 0x0CBB },
+       { 0x90D, 0x16F8 },
+       { 0x90E, 0xF7D9 },
+       { 0x90F, 0x040A },
+       { 0x910, 0x1F14 },
+       { 0x911, 0x058C },
+       { 0x912, 0x0563 },
+       { 0x913, 0x4000 },
+       { 0x916, 0x6318 },
+       { 0x917, 0x6300 },
+       { 0x918, 0x0FC8 },
+       { 0x919, 0x03FE },
+       { 0x91A, 0x00E0 },
+       { 0x91B, 0x1EC4 },
+       { 0x91C, 0xF136 },
+       { 0x91D, 0x0409 },
+       { 0x91E, 0x04CC },
+       { 0x91F, 0x1C9B },
+       { 0x920, 0xF337 },
+       { 0x921, 0x040B },
+       { 0x922, 0x0CBB },
+       { 0x923, 0x16F8 },
+       { 0x924, 0xF7D9 },
+       { 0x925, 0x040A },
+       { 0x926, 0x1F14 },
+       { 0x927, 0x058C },
+       { 0x928, 0x0563 },
+       { 0x929, 0x4000 },
+       { 0x709, 0x2000 },
+       { 0x207, 0x200E },
+       { 0x208, 0x20D4 },
+       { 0x20A, 0x0080 },
+       { 0x07, 0x0000 },
+};
+
+static int wm2200_reset(struct wm2200_priv *wm2200)
+{
+       if (wm2200->pdata.reset) {
+               gpio_set_value_cansleep(wm2200->pdata.reset, 0);
+               gpio_set_value_cansleep(wm2200->pdata.reset, 1);
+
+               return 0;
+       } else {
+               return regmap_write(wm2200->regmap, WM2200_SOFTWARE_RESET,
+                                   0x2200);
+       }
+}
+
+static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0);
+static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
+static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
+
+static const char *wm2200_mixer_texts[] = {
+       "None",
+       "Tone Generator",
+       "AEC loopback",
+       "IN1L",
+       "IN1R",
+       "IN2L",
+       "IN2R",
+       "IN3L",
+       "IN3R",
+       "AIF1RX1",
+       "AIF1RX2",
+       "AIF1RX3",
+       "AIF1RX4",
+       "AIF1RX5",
+       "AIF1RX6",
+       "EQL",
+       "EQR",
+       "LHPF1",
+       "LHPF2",
+       "LHPF3",
+       "LHPF4",
+       "DSP1.1",
+       "DSP1.2",
+       "DSP1.3",
+       "DSP1.4",
+       "DSP1.5",
+       "DSP1.6",
+       "DSP2.1",
+       "DSP2.2",
+       "DSP2.3",
+       "DSP2.4",
+       "DSP2.5",
+       "DSP2.6",
+};
+
+static int wm2200_mixer_values[] = {
+       0x00,
+       0x04,   /* Tone */
+       0x08,   /* AEC */
+       0x10,   /* Input */
+       0x11,
+       0x12,
+       0x13,
+       0x14,
+       0x15,
+       0x20,   /* AIF */
+       0x21,
+       0x22,
+       0x23,
+       0x24,
+       0x25,
+       0x50,   /* EQ */
+       0x51,
+       0x52,
+       0x60,   /* LHPF1 */
+       0x61,   /* LHPF2 */
+       0x68,   /* DSP1 */
+       0x69,
+       0x6a,
+       0x6b,
+       0x6c,
+       0x6d,
+       0x70,   /* DSP2 */
+       0x71,
+       0x72,
+       0x73,
+       0x74,
+       0x75,
+};
+
+#define WM2200_MIXER_CONTROLS(name, base) \
+       SOC_SINGLE_TLV(name " Input 1 Volume", base + 1 , \
+                      WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+       SOC_SINGLE_TLV(name " Input 2 Volume", base + 3 , \
+                      WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+       SOC_SINGLE_TLV(name " Input 3 Volume", base + 5 , \
+                      WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+       SOC_SINGLE_TLV(name " Input 4 Volume", base + 7 , \
+                      WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv)
+
+#define WM2200_MUX_ENUM_DECL(name, reg) \
+       SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff,                  \
+                                  wm2200_mixer_texts, wm2200_mixer_values)
+
+#define WM2200_MUX_CTL_DECL(name) \
+       const struct snd_kcontrol_new name##_mux =      \
+               SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+
+#define WM2200_MIXER_ENUMS(name, base_reg) \
+       static WM2200_MUX_ENUM_DECL(name##_in1_enum, base_reg);      \
+       static WM2200_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2);  \
+       static WM2200_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4);  \
+       static WM2200_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6);  \
+       static WM2200_MUX_CTL_DECL(name##_in1); \
+       static WM2200_MUX_CTL_DECL(name##_in2); \
+       static WM2200_MUX_CTL_DECL(name##_in3); \
+       static WM2200_MUX_CTL_DECL(name##_in4)
+
+static const struct snd_kcontrol_new wm2200_snd_controls[] = {
+SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL,
+          WM2200_IN1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN2 High Performance Switch", WM2200_IN2L_CONTROL,
+          WM2200_IN2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN3 High Performance Switch", WM2200_IN3L_CONTROL,
+          WM2200_IN3_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R_TLV("IN1 Volume", WM2200_IN1L_CONTROL, WM2200_IN1R_CONTROL,
+                WM2200_IN1L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN2 Volume", WM2200_IN2L_CONTROL, WM2200_IN2R_CONTROL,
+                WM2200_IN2L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN3 Volume", WM2200_IN3L_CONTROL, WM2200_IN3R_CONTROL,
+                WM2200_IN3L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
+
+SOC_DOUBLE_R("IN1 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+            WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN2 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+            WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN3 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+            WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_MUTE_SHIFT, 1, 1),
+
+SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_1L,
+                WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_DIG_VOL_SHIFT,
+                0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_2L,
+                WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_DIG_VOL_SHIFT,
+                0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_3L,
+                WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_DIG_VOL_SHIFT,
+                0xbf, 0, digital_tlv),
+
+SOC_SINGLE("OUT1 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_1L,
+          WM2200_OUT1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("OUT2 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_2L,
+          WM2200_OUT2_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R("OUT1 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_1L,
+            WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R_TLV("OUT1 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_1L,
+                WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_VOL_SHIFT, 0x9f, 0,
+                digital_tlv),
+SOC_DOUBLE_R_TLV("OUT1 Volume", WM2200_DAC_VOLUME_LIMIT_1L,
+                WM2200_DAC_VOLUME_LIMIT_1R, WM2200_OUT1L_PGA_VOL_SHIFT,
+                0x46, 0, out_tlv),
+
+SOC_DOUBLE_R("OUT2 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_2L,
+            WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L,
+                WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0,
+                digital_tlv),
+SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT,
+          WM2200_SPK1R_MUTE_SHIFT, 1, 0),
+};
+
+WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(OUT1R, WM2200_OUT1RMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(OUT2L, WM2200_OUT2LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(OUT2R, WM2200_OUT2RMIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(AIF1TX1, WM2200_AIF1TX1MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX2, WM2200_AIF1TX2MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX3, WM2200_AIF1TX3MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX4, WM2200_AIF1TX4MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX5, WM2200_AIF1TX5MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX6, WM2200_AIF1TX6MIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(EQL, WM2200_EQLMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(EQR, WM2200_EQRMIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(DSP1L, WM2200_DSP1LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
+
+#define WM2200_MUX(name, ctrl) \
+       SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+
+#define WM2200_MIXER_WIDGETS(name, name_str)   \
+       WM2200_MUX(name_str " Input 1", &name##_in1_mux), \
+       WM2200_MUX(name_str " Input 2", &name##_in2_mux), \
+       WM2200_MUX(name_str " Input 3", &name##_in3_mux), \
+       WM2200_MUX(name_str " Input 4", &name##_in4_mux), \
+       SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
+
+#define WM2200_MIXER_INPUT_ROUTES(name)        \
+       { name, "Tone Generator", "Tone Generator" }, \
+        { name, "IN1L", "IN1L PGA" }, \
+        { name, "IN1R", "IN1R PGA" }, \
+        { name, "IN2L", "IN2L PGA" }, \
+        { name, "IN2R", "IN2R PGA" }, \
+        { name, "IN3L", "IN3L PGA" }, \
+        { name, "IN3R", "IN3R PGA" }, \
+        { name, "DSP1.1", "DSP1" }, \
+        { name, "DSP1.2", "DSP1" }, \
+        { name, "DSP1.3", "DSP1" }, \
+        { name, "DSP1.4", "DSP1" }, \
+        { name, "DSP1.5", "DSP1" }, \
+        { name, "DSP1.6", "DSP1" }, \
+        { name, "DSP2.1", "DSP2" }, \
+        { name, "DSP2.2", "DSP2" }, \
+        { name, "DSP2.3", "DSP2" }, \
+        { name, "DSP2.4", "DSP2" }, \
+        { name, "DSP2.5", "DSP2" }, \
+        { name, "DSP2.6", "DSP2" }, \
+        { name, "AIF1RX1", "AIF1RX1" }, \
+        { name, "AIF1RX2", "AIF1RX2" }, \
+        { name, "AIF1RX3", "AIF1RX3" }, \
+        { name, "AIF1RX4", "AIF1RX4" }, \
+        { name, "AIF1RX5", "AIF1RX5" }, \
+        { name, "AIF1RX6", "AIF1RX6" }, \
+        { name, "EQL", "EQL" }, \
+        { name, "EQR", "EQR" }, \
+        { name, "LHPF1", "LHPF1" }, \
+        { name, "LHPF2", "LHPF2" }
+
+#define WM2200_MIXER_ROUTES(widget, name) \
+       { widget, NULL, name " Mixer" },         \
+       { name " Mixer", NULL, name " Input 1" }, \
+       { name " Mixer", NULL, name " Input 2" }, \
+       { name " Mixer", NULL, name " Input 3" }, \
+       { name " Mixer", NULL, name " Input 4" }, \
+       WM2200_MIXER_INPUT_ROUTES(name " Input 1"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Input 2"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Input 4")
+
+static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0,
+                   NULL, 0),
+SND_SOC_DAPM_SUPPLY("CP1", WM2200_DM_CHARGE_PUMP_1, WM2200_CPDM_ENA_SHIFT, 0,
+                   NULL, 0),
+SND_SOC_DAPM_SUPPLY("CP2", WM2200_MIC_CHARGE_PUMP_1, WM2200_CPMIC_ENA_SHIFT, 0,
+                   NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS1", WM2200_MIC_BIAS_CTRL_1, WM2200_MICB1_ENA_SHIFT,
+                   0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", WM2200_MIC_BIAS_CTRL_2, WM2200_MICB2_ENA_SHIFT,
+                   0, NULL, 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
+SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20),
+
+SND_SOC_DAPM_INPUT("IN1L"),
+SND_SOC_DAPM_INPUT("IN1R"),
+SND_SOC_DAPM_INPUT("IN2L"),
+SND_SOC_DAPM_INPUT("IN2R"),
+SND_SOC_DAPM_INPUT("IN3L"),
+SND_SOC_DAPM_INPUT("IN3R"),
+
+SND_SOC_DAPM_SIGGEN("TONE"),
+SND_SOC_DAPM_PGA("Tone Generator", WM2200_TONE_GENERATOR_1,
+                WM2200_TONE_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("IN1L PGA", WM2200_INPUT_ENABLES, WM2200_IN1L_ENA_SHIFT, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("IN1R PGA", WM2200_INPUT_ENABLES, WM2200_IN1R_ENA_SHIFT, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("IN2L PGA", WM2200_INPUT_ENABLES, WM2200_IN2L_ENA_SHIFT, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("IN2R PGA", WM2200_INPUT_ENABLES, WM2200_IN2R_ENA_SHIFT, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("IN3L PGA", WM2200_INPUT_ENABLES, WM2200_IN3L_ENA_SHIFT, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("IN3R PGA", WM2200_INPUT_ENABLES, WM2200_IN3R_ENA_SHIFT, 0,
+                NULL, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX1", "Playback", 0,
+                   WM2200_AUDIO_IF_1_22, WM2200_AIF1RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", "Playback", 1,
+                   WM2200_AUDIO_IF_1_22, WM2200_AIF1RX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", "Playback", 2,
+                   WM2200_AUDIO_IF_1_22, WM2200_AIF1RX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", "Playback", 3,
+                   WM2200_AUDIO_IF_1_22, WM2200_AIF1RX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX5", "Playback", 4,
+                   WM2200_AUDIO_IF_1_22, WM2200_AIF1RX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX6", "Playback", 5,
+                   WM2200_AUDIO_IF_1_22, WM2200_AIF1RX6_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA("EQL", WM2200_EQL_1, WM2200_EQL_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQR", WM2200_EQR_1, WM2200_EQR_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0,
+                NULL, 0),
+
+SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
+SND_SOC_DAPM_PGA_E("DSP2", SND_SOC_NOPM, 1, 0, NULL, 0, NULL, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0,
+                   WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", "Capture", 1,
+                   WM2200_AUDIO_IF_1_22, WM2200_AIF1TX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", "Capture", 2,
+                   WM2200_AUDIO_IF_1_22, WM2200_AIF1TX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", "Capture", 3,
+                   WM2200_AUDIO_IF_1_22, WM2200_AIF1TX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4,
+                   WM2200_AUDIO_IF_1_22, WM2200_AIF1TX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5,
+                   WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES,
+                  WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES,
+                  WM2200_OUT1R_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_LP", 1, WM2200_EAR_PIECE_CTRL_1,
+                  WM2200_EPD_LP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_LP", 1, WM2200_EAR_PIECE_CTRL_1,
+                  WM2200_EPD_OUTP_LP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LP", 1, WM2200_EAR_PIECE_CTRL_1,
+                  WM2200_EPD_RMV_SHRT_LP_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_LN", 1, WM2200_EAR_PIECE_CTRL_1,
+                  WM2200_EPD_LN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_LN", 1, WM2200_EAR_PIECE_CTRL_1,
+                  WM2200_EPD_OUTP_LN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LN", 1, WM2200_EAR_PIECE_CTRL_1,
+                  WM2200_EPD_RMV_SHRT_LN_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_RP", 1, WM2200_EAR_PIECE_CTRL_2,
+                  WM2200_EPD_RP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_RP", 1, WM2200_EAR_PIECE_CTRL_2,
+                  WM2200_EPD_OUTP_RP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RP", 1, WM2200_EAR_PIECE_CTRL_2,
+                  WM2200_EPD_RMV_SHRT_RP_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_RN", 1, WM2200_EAR_PIECE_CTRL_2,
+                  WM2200_EPD_RN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_RN", 1, WM2200_EAR_PIECE_CTRL_2,
+                  WM2200_EPD_OUTP_RN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RN", 1, WM2200_EAR_PIECE_CTRL_2,
+                  WM2200_EPD_RMV_SHRT_RN_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("OUT2L", WM2200_OUTPUT_ENABLES, WM2200_OUT2L_ENA_SHIFT,
+                0, NULL, 0),
+SND_SOC_DAPM_PGA("OUT2R", WM2200_OUTPUT_ENABLES, WM2200_OUT2R_ENA_SHIFT,
+                0, NULL, 0),
+
+SND_SOC_DAPM_OUTPUT("EPOUTLN"),
+SND_SOC_DAPM_OUTPUT("EPOUTLP"),
+SND_SOC_DAPM_OUTPUT("EPOUTRN"),
+SND_SOC_DAPM_OUTPUT("EPOUTRP"),
+SND_SOC_DAPM_OUTPUT("SPK"),
+
+WM2200_MIXER_WIDGETS(EQL, "EQL"),
+WM2200_MIXER_WIDGETS(EQR, "EQR"),
+
+WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"),
+WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"),
+
+WM2200_MIXER_WIDGETS(DSP1L, "DSP1L"),
+WM2200_MIXER_WIDGETS(DSP1R, "DSP1R"),
+WM2200_MIXER_WIDGETS(DSP2L, "DSP2L"),
+WM2200_MIXER_WIDGETS(DSP2R, "DSP2R"),
+
+WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
+WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
+WM2200_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
+WM2200_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
+WM2200_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
+WM2200_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
+
+WM2200_MIXER_WIDGETS(OUT1L, "OUT1L"),
+WM2200_MIXER_WIDGETS(OUT1R, "OUT1R"),
+WM2200_MIXER_WIDGETS(OUT2L, "OUT2L"),
+WM2200_MIXER_WIDGETS(OUT2R, "OUT2R"),
+};
+
+static const struct snd_soc_dapm_route wm2200_dapm_routes[] = {
+       /* Everything needs SYSCLK but only hook up things on the edge
+        * of the chip */
+       { "IN1L", NULL, "SYSCLK" },
+       { "IN1R", NULL, "SYSCLK" },
+       { "IN2L", NULL, "SYSCLK" },
+       { "IN2R", NULL, "SYSCLK" },
+       { "IN3L", NULL, "SYSCLK" },
+       { "IN3R", NULL, "SYSCLK" },
+       { "OUT1L", NULL, "SYSCLK" },
+       { "OUT1R", NULL, "SYSCLK" },
+       { "OUT2L", NULL, "SYSCLK" },
+       { "OUT2R", NULL, "SYSCLK" },
+       { "AIF1RX1", NULL, "SYSCLK" },
+       { "AIF1RX2", NULL, "SYSCLK" },
+       { "AIF1RX3", NULL, "SYSCLK" },
+       { "AIF1RX4", NULL, "SYSCLK" },
+       { "AIF1RX5", NULL, "SYSCLK" },
+       { "AIF1RX6", NULL, "SYSCLK" },
+       { "AIF1TX1", NULL, "SYSCLK" },
+       { "AIF1TX2", NULL, "SYSCLK" },
+       { "AIF1TX3", NULL, "SYSCLK" },
+       { "AIF1TX4", NULL, "SYSCLK" },
+       { "AIF1TX5", NULL, "SYSCLK" },
+       { "AIF1TX6", NULL, "SYSCLK" },
+
+       { "IN1L", NULL, "AVDD" },
+       { "IN1R", NULL, "AVDD" },
+       { "IN2L", NULL, "AVDD" },
+       { "IN2R", NULL, "AVDD" },
+       { "IN3L", NULL, "AVDD" },
+       { "IN3R", NULL, "AVDD" },
+       { "OUT1L", NULL, "AVDD" },
+       { "OUT1R", NULL, "AVDD" },
+
+       { "IN1L PGA", NULL, "IN1L" },
+       { "IN1R PGA", NULL, "IN1R" },
+       { "IN2L PGA", NULL, "IN2L" },
+       { "IN2R PGA", NULL, "IN2R" },
+       { "IN3L PGA", NULL, "IN3L" },
+       { "IN3R PGA", NULL, "IN3R" },
+
+       { "Tone Generator", NULL, "TONE" },
+
+       { "CP2", NULL, "CPVDD" },
+       { "MICBIAS1", NULL, "CP2" },
+       { "MICBIAS2", NULL, "CP2" },
+
+       { "CP1", NULL, "CPVDD" },
+       { "EPD_LN", NULL, "CP1" },
+       { "EPD_LP", NULL, "CP1" },
+       { "EPD_RN", NULL, "CP1" },
+       { "EPD_RP", NULL, "CP1" },
+
+       { "EPD_LP", NULL, "OUT1L" },
+       { "EPD_OUTP_LP", NULL, "EPD_LP" },
+       { "EPD_RMV_SHRT_LP", NULL, "EPD_OUTP_LP" },
+       { "EPOUTLP", NULL, "EPD_RMV_SHRT_LP" },
+
+       { "EPD_LN", NULL, "OUT1L" },
+       { "EPD_OUTP_LN", NULL, "EPD_LN" },
+       { "EPD_RMV_SHRT_LN", NULL, "EPD_OUTP_LN" },
+       { "EPOUTLN", NULL, "EPD_RMV_SHRT_LN" },
+
+       { "EPD_RP", NULL, "OUT1R" },
+       { "EPD_OUTP_RP", NULL, "EPD_RP" },
+       { "EPD_RMV_SHRT_RP", NULL, "EPD_OUTP_RP" },
+       { "EPOUTRP", NULL, "EPD_RMV_SHRT_RP" },
+
+       { "EPD_RN", NULL, "OUT1R" },
+       { "EPD_OUTP_RN", NULL, "EPD_RN" },
+       { "EPD_RMV_SHRT_RN", NULL, "EPD_OUTP_RN" },
+       { "EPOUTRN", NULL, "EPD_RMV_SHRT_RN" },
+
+       { "SPK", NULL, "OUT2L" },
+       { "SPK", NULL, "OUT2R" },
+
+       WM2200_MIXER_ROUTES("DSP1", "DSP1L"),
+       WM2200_MIXER_ROUTES("DSP1", "DSP1R"),
+       WM2200_MIXER_ROUTES("DSP2", "DSP2L"),
+       WM2200_MIXER_ROUTES("DSP2", "DSP2R"),
+
+       WM2200_MIXER_ROUTES("OUT1L", "OUT1L"),
+       WM2200_MIXER_ROUTES("OUT1R", "OUT1R"),
+       WM2200_MIXER_ROUTES("OUT2L", "OUT2L"),
+       WM2200_MIXER_ROUTES("OUT2R", "OUT2R"),
+
+       WM2200_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
+       WM2200_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
+       WM2200_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
+       WM2200_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
+       WM2200_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
+       WM2200_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
+
+       WM2200_MIXER_ROUTES("EQL", "EQL"),
+       WM2200_MIXER_ROUTES("EQR", "EQR"),
+
+       WM2200_MIXER_ROUTES("LHPF1", "LHPF1"),
+       WM2200_MIXER_ROUTES("LHPF2", "LHPF2"),
+};
+
+static int wm2200_probe(struct snd_soc_codec *codec)
+{
+       struct wm2200_priv *wm2200 = dev_get_drvdata(codec->dev);
+       int ret;
+
+       wm2200->codec = codec;
+       codec->control_data = wm2200->regmap;
+       codec->dapm.bias_level = SND_SOC_BIAS_OFF;
+
+       ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
+
+       return ret;
+}
+
+static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       int lrclk, bclk, fmt_val;
+
+       lrclk = 0;
+       bclk = 0;
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+               fmt_val = 0;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               fmt_val = 1;
+               break;
+       case SND_SOC_DAIFMT_I2S:
+               fmt_val = 2;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               fmt_val = 3;
+               break;
+       default:
+               dev_err(codec->dev, "Unsupported DAI format %d\n",
+                       fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               break;
+       case SND_SOC_DAIFMT_CBS_CFM:
+               lrclk |= WM2200_AIF1TX_LRCLK_MSTR;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFS:
+               bclk |= WM2200_AIF1_BCLK_MSTR;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFM:
+               lrclk |= WM2200_AIF1TX_LRCLK_MSTR;
+               bclk |= WM2200_AIF1_BCLK_MSTR;
+               break;
+       default:
+               dev_err(codec->dev, "Unsupported master mode %d\n",
+                       fmt & SND_SOC_DAIFMT_MASTER_MASK);
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               bclk |= WM2200_AIF1_BCLK_INV;
+               lrclk |= WM2200_AIF1TX_LRCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               bclk |= WM2200_AIF1_BCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               lrclk |= WM2200_AIF1TX_LRCLK_INV;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1, WM2200_AIF1_BCLK_MSTR |
+                           WM2200_AIF1_BCLK_INV, bclk);
+       snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2,
+                           WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
+                           lrclk);
+       snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_3,
+                           WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
+                           lrclk);
+       snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5,
+                           WM2200_AIF1_FMT_MASK << 1, fmt_val << 1);
+
+       return 0;
+}
+
+static int wm2200_sr_code[] = {
+       0,
+       12000,
+       24000,
+       48000,
+       96000,
+       192000,
+       384000,
+       768000,
+       0,
+       11025,
+       22050,
+       44100,
+       88200,
+       176400,
+       352800,
+       705600,
+       4000,
+       8000,
+       16000,
+       32000,
+       64000,
+       128000,
+       256000,
+       512000,
+};
+
+#define WM2200_NUM_BCLK_RATES 12
+
+static int wm2200_bclk_rates_dat[WM2200_NUM_BCLK_RATES] = {
+       6144000,
+       3072000,
+       2048000,
+       1536000,
+       768000,
+       512000,
+       384000,
+       256000,
+       192000,
+       128000,
+       96000,
+       64000,
+};     
+
+static int wm2200_bclk_rates_cd[WM2200_NUM_BCLK_RATES] = {
+       5644800,
+       2882400,
+       1881600,
+       1411200,
+       705600,
+       470400,
+       352800,
+       176400,
+       117600,
+       88200,
+       58800,
+};
+
+static int wm2200_hw_params(struct snd_pcm_substream *substream,
+                           struct snd_pcm_hw_params *params,
+                           struct snd_soc_dai *dai)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
+       int i, bclk, lrclk, wl, fl, sr_code;
+       int *bclk_rates;
+
+       /* Data sizes if not using TDM */
+       wl = snd_pcm_format_width(params_format(params));
+       if (wl < 0)
+               return wl;
+       fl = snd_soc_params_to_frame_size(params);
+       if (fl < 0)
+               return fl;
+
+       dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n",
+               wl, fl);
+
+       /* Target BCLK rate */
+       bclk = snd_soc_params_to_bclk(params);
+       if (bclk < 0)
+               return bclk;
+
+       if (!wm2200->sysclk) {
+               dev_err(codec->dev, "SYSCLK has no rate set\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm2200_sr_code); i++)
+               if (wm2200_sr_code[i] == params_rate(params))
+                       break;
+       if (i == ARRAY_SIZE(wm2200_sr_code)) {
+               dev_err(codec->dev, "Unsupported sample rate: %dHz\n",
+                       params_rate(params));
+               return -EINVAL;
+       }
+       sr_code = i;
+
+       dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz SYSCLK\n",
+               bclk, wm2200->sysclk);
+
+       if (wm2200->sysclk % 4000)
+               bclk_rates = wm2200_bclk_rates_cd;
+       else
+               bclk_rates = wm2200_bclk_rates_dat;
+
+       for (i = 0; i < WM2200_NUM_BCLK_RATES; i++)
+               if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0))
+                       break;
+       if (i == WM2200_NUM_BCLK_RATES) {
+               dev_err(codec->dev,
+                       "No valid BCLK for %dHz found from %dHz SYSCLK\n",
+                       bclk, wm2200->sysclk);
+               return -EINVAL;
+       }
+
+       bclk = i;
+       dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]);
+       snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1,
+                           WM2200_AIF1_BCLK_DIV_MASK, bclk);
+
+       lrclk = bclk_rates[bclk] / params_rate(params);
+       dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+           dai->symmetric_rates)
+               snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_7,
+                                   WM2200_AIF1RX_BCPF_MASK, lrclk);
+       else
+               snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_6,
+                                   WM2200_AIF1TX_BCPF_MASK, lrclk);
+
+       i = (wl << WM2200_AIF1TX_WL_SHIFT) | wl;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_9,
+                                   WM2200_AIF1RX_WL_MASK |
+                                   WM2200_AIF1RX_SLOT_LEN_MASK, i);
+       else
+               snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_8,
+                                   WM2200_AIF1TX_WL_MASK |
+                                   WM2200_AIF1TX_SLOT_LEN_MASK, i);
+
+       snd_soc_update_bits(codec, WM2200_CLOCKING_4,
+                           WM2200_SAMPLE_RATE_1_MASK, sr_code);
+
+       return 0;
+}
+
+static const struct snd_soc_dai_ops wm2200_dai_ops = {
+       .set_fmt = wm2200_set_fmt,
+       .hw_params = wm2200_hw_params,
+};
+
+static int wm2200_set_sysclk(struct snd_soc_codec *codec, int clk_id,
+                            int source, unsigned int freq, int dir)
+{
+       struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
+       int fval;
+
+       switch (clk_id) {
+       case WM2200_CLK_SYSCLK:
+               break;
+
+       default:
+               dev_err(codec->dev, "Unknown clock %d\n", clk_id);
+               return -EINVAL;
+       }
+
+       switch (source) {
+       case WM2200_CLKSRC_MCLK1:
+       case WM2200_CLKSRC_MCLK2:
+       case WM2200_CLKSRC_FLL:
+       case WM2200_CLKSRC_BCLK1:
+               break;
+       default:
+               dev_err(codec->dev, "Invalid source %d\n", source);
+               return -EINVAL;
+       }
+
+       switch (freq) {
+       case 22579200:
+       case 24576000:
+               fval = 2;
+               break;
+       default:
+               dev_err(codec->dev, "Invalid clock rate: %d\n", freq);
+               return -EINVAL;
+       }
+
+       /* TODO: Check if MCLKs are in use and enable/disable pulls to
+        * match.
+        */
+
+       snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_FREQ_MASK |
+                           WM2200_SYSCLK_SRC_MASK,
+                           fval << WM2200_SYSCLK_FREQ_SHIFT | source);
+
+       wm2200->sysclk = freq;
+
+       return 0;
+}
+
+struct _fll_div {
+       u16 fll_fratio;
+       u16 fll_outdiv;
+       u16 fll_refclk_div;
+       u16 n;
+       u16 theta;
+       u16 lambda;
+};
+
+static struct {
+       unsigned int min;
+       unsigned int max;
+       u16 fll_fratio;
+       int ratio;
+} fll_fratios[] = {
+       {       0,    64000, 4, 16 },
+       {   64000,   128000, 3,  8 },
+       {  128000,   256000, 2,  4 },
+       {  256000,  1000000, 1,  2 },
+       { 1000000, 13500000, 0,  1 },
+};
+
+static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
+                      unsigned int Fout)
+{
+       unsigned int target;
+       unsigned int div;
+       unsigned int fratio, gcd_fll;
+       int i;
+
+       /* Fref must be <=13.5MHz */
+       div = 1;
+       fll_div->fll_refclk_div = 0;
+       while ((Fref / div) > 13500000) {
+               div *= 2;
+               fll_div->fll_refclk_div++;
+
+               if (div > 8) {
+                       pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
+                              Fref);
+                       return -EINVAL;
+               }
+       }
+
+       pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
+
+       /* Apply the division for our remaining calculations */
+       Fref /= div;
+
+       /* Fvco should be 90-100MHz; don't check the upper bound */
+       div = 2;
+       while (Fout * div < 90000000) {
+               div++;
+               if (div > 64) {
+                       pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
+                              Fout);
+                       return -EINVAL;
+               }
+       }
+       target = Fout * div;
+       fll_div->fll_outdiv = div - 1;
+
+       pr_debug("FLL Fvco=%dHz\n", target);
+
+       /* Find an appropraite FLL_FRATIO and factor it out of the target */
+       for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
+               if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
+                       fll_div->fll_fratio = fll_fratios[i].fll_fratio;
+                       fratio = fll_fratios[i].ratio;
+                       break;
+               }
+       }
+       if (i == ARRAY_SIZE(fll_fratios)) {
+               pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
+               return -EINVAL;
+       }
+
+       fll_div->n = target / (fratio * Fref);
+
+       if (target % Fref == 0) {
+               fll_div->theta = 0;
+               fll_div->lambda = 0;
+       } else {
+               gcd_fll = gcd(target, fratio * Fref);
+
+               fll_div->theta = (target - (fll_div->n * fratio * Fref))
+                       / gcd_fll;
+               fll_div->lambda = (fratio * Fref) / gcd_fll;
+       }
+
+       pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
+                fll_div->n, fll_div->theta, fll_div->lambda);
+       pr_debug("FLL_FRATIO=%x(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
+                fll_div->fll_fratio, fratio, fll_div->fll_outdiv,
+                fll_div->fll_refclk_div);
+
+       return 0;
+}
+
+static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
+                         unsigned int Fref, unsigned int Fout)
+{
+       struct i2c_client *i2c = to_i2c_client(codec->dev);
+       struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
+       struct _fll_div factors;
+       int ret, i, timeout;
+
+       if (!Fout) {
+               dev_dbg(codec->dev, "FLL disabled");
+
+               if (wm2200->fll_fout)
+                       pm_runtime_put(codec->dev);
+
+               wm2200->fll_fout = 0;
+               snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1,
+                                   WM2200_FLL_ENA, 0);
+               return 0;
+       }
+
+       switch (source) {
+       case WM2200_FLL_SRC_MCLK1:
+       case WM2200_FLL_SRC_MCLK2:
+       case WM2200_FLL_SRC_BCLK:
+               break;
+       default:
+               dev_err(codec->dev, "Invalid FLL source %d\n", source);
+               return -EINVAL;
+       }
+
+       ret = fll_factors(&factors, Fref, Fout);
+       if (ret < 0)
+               return ret;
+
+       /* Disable the FLL while we reconfigure */
+       snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1, WM2200_FLL_ENA, 0);
+
+       snd_soc_update_bits(codec, WM2200_FLL_CONTROL_2,
+                           WM2200_FLL_OUTDIV_MASK | WM2200_FLL_FRATIO_MASK,
+                           (factors.fll_outdiv << WM2200_FLL_OUTDIV_SHIFT) |
+                           factors.fll_fratio);
+       if (factors.theta) {
+               snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3,
+                                   WM2200_FLL_FRACN_ENA,
+                                   WM2200_FLL_FRACN_ENA);
+               snd_soc_update_bits(codec, WM2200_FLL_EFS_2,
+                                   WM2200_FLL_EFS_ENA,
+                                   WM2200_FLL_EFS_ENA);
+       } else {
+               snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3,
+                                   WM2200_FLL_FRACN_ENA, 0);
+               snd_soc_update_bits(codec, WM2200_FLL_EFS_2,
+                                   WM2200_FLL_EFS_ENA, 0);
+       }
+
+       snd_soc_update_bits(codec, WM2200_FLL_CONTROL_4, WM2200_FLL_THETA_MASK,
+                           factors.theta);
+       snd_soc_update_bits(codec, WM2200_FLL_CONTROL_6, WM2200_FLL_N_MASK,
+                           factors.n);
+       snd_soc_update_bits(codec, WM2200_FLL_CONTROL_7,
+                           WM2200_FLL_CLK_REF_DIV_MASK |
+                           WM2200_FLL_CLK_REF_SRC_MASK,
+                           (factors.fll_refclk_div
+                            << WM2200_FLL_CLK_REF_DIV_SHIFT) | source);
+       snd_soc_update_bits(codec, WM2200_FLL_EFS_1,
+                           WM2200_FLL_LAMBDA_MASK, factors.lambda);
+
+       /* Clear any pending completions */
+       try_wait_for_completion(&wm2200->fll_lock);
+
+       pm_runtime_get_sync(codec->dev);
+
+       snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1,
+                           WM2200_FLL_ENA, WM2200_FLL_ENA);
+
+       if (i2c->irq)
+               timeout = 2;
+       else
+               timeout = 50;
+
+       snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_ENA,
+                           WM2200_SYSCLK_ENA);
+
+       /* Poll for the lock; will use the interrupt to exit quickly */
+       for (i = 0; i < timeout; i++) {
+               if (i2c->irq) {
+                       ret = wait_for_completion_timeout(&wm2200->fll_lock,
+                                                         msecs_to_jiffies(25));
+                       if (ret > 0)
+                               break;
+               } else {
+                       msleep(1);
+               }
+
+               ret = snd_soc_read(codec,
+                                  WM2200_INTERRUPT_RAW_STATUS_2);
+               if (ret < 0) {
+                       dev_err(codec->dev,
+                               "Failed to read FLL status: %d\n",
+                               ret);
+                       continue;
+               }
+               if (ret & WM2200_FLL_LOCK_STS)
+                       break;
+       }
+       if (i == timeout) {
+               dev_err(codec->dev, "FLL lock timed out\n");
+               pm_runtime_put(codec->dev);
+               return -ETIMEDOUT;
+       }
+
+       wm2200->fll_src = source;
+       wm2200->fll_fref = Fref;
+       wm2200->fll_fout = Fout;
+
+       dev_dbg(codec->dev, "FLL running %dHz->%dHz\n", Fref, Fout);
+
+       return 0;
+}
+
+static int wm2200_dai_probe(struct snd_soc_dai *dai)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       unsigned int val = 0;
+       int ret;
+
+       ret = snd_soc_read(codec, WM2200_GPIO_CTRL_1);
+       if (ret >= 0) {
+               if ((ret & WM2200_GP1_FN_MASK) != 0) {
+                       dai->symmetric_rates = true;
+                       val = WM2200_AIF1TX_LRCLK_SRC;
+               }
+       } else {
+               dev_err(codec->dev, "Failed to read GPIO 1 config: %d\n", ret);
+       }
+
+       snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2,
+                           WM2200_AIF1TX_LRCLK_SRC, val);
+
+       return 0;
+}
+
+#define WM2200_RATES SNDRV_PCM_RATE_8000_48000
+
+#define WM2200_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+                       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver wm2200_dai = {
+       .name = "wm2200",
+       .probe = wm2200_dai_probe,
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = WM2200_RATES,
+               .formats = WM2200_FORMATS,
+       },
+       .capture = {
+                .stream_name = "Capture",
+                .channels_min = 2,
+                .channels_max = 2,
+                .rates = WM2200_RATES,
+                .formats = WM2200_FORMATS,
+        },
+       .ops = &wm2200_dai_ops,
+};
+
+static struct snd_soc_codec_driver soc_codec_wm2200 = {
+       .probe = wm2200_probe,
+
+       .idle_bias_off = true,
+       .ignore_pmdown_time = true,
+       .set_sysclk = wm2200_set_sysclk,
+       .set_pll = wm2200_set_fll,
+
+       .controls = wm2200_snd_controls,
+       .num_controls = ARRAY_SIZE(wm2200_snd_controls),
+       .dapm_widgets = wm2200_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm2200_dapm_widgets),
+       .dapm_routes = wm2200_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm2200_dapm_routes),
+};
+
+static irqreturn_t wm2200_irq(int irq, void *data)
+{
+       struct wm2200_priv *wm2200 = data;
+       unsigned int val, mask;
+       int ret;
+
+       ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, &val);
+       if (ret != 0) {
+               dev_err(wm2200->dev, "Failed to read IRQ status: %d\n", ret);
+               return IRQ_NONE;
+       }
+
+       ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2_MASK,
+                          &mask);
+       if (ret != 0) {
+               dev_warn(wm2200->dev, "Failed to read IRQ mask: %d\n", ret);
+               mask = 0;
+       }
+
+       val &= ~mask;
+
+       if (val & WM2200_FLL_LOCK_EINT) {
+               dev_dbg(wm2200->dev, "FLL locked\n");
+               complete(&wm2200->fll_lock);
+       }
+
+       if (val) {
+               regmap_write(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, val);
+               
+               return IRQ_HANDLED;
+       } else {
+               return IRQ_NONE;
+       }
+}
+
+static const struct regmap_config wm2200_regmap = {
+       .reg_bits = 16,
+       .val_bits = 16,
+
+       .max_register = WM2200_MAX_REGISTER,
+       .reg_defaults = wm2200_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults),
+       .volatile_reg = wm2200_volatile_register,
+       .readable_reg = wm2200_readable_register,
+       .cache_type = REGCACHE_RBTREE,
+};
+
+static const unsigned int wm2200_dig_vu[] = {
+       WM2200_DAC_DIGITAL_VOLUME_1L,
+       WM2200_DAC_DIGITAL_VOLUME_1R,
+       WM2200_DAC_DIGITAL_VOLUME_2L,
+       WM2200_DAC_DIGITAL_VOLUME_2R,
+       WM2200_ADC_DIGITAL_VOLUME_1L,
+       WM2200_ADC_DIGITAL_VOLUME_1R,
+       WM2200_ADC_DIGITAL_VOLUME_2L,
+       WM2200_ADC_DIGITAL_VOLUME_2R,
+       WM2200_ADC_DIGITAL_VOLUME_3L,
+       WM2200_ADC_DIGITAL_VOLUME_3R,
+};
+
+static const unsigned int wm2200_mic_ctrl_reg[] = {
+       WM2200_IN1L_CONTROL,
+       WM2200_IN2L_CONTROL,
+       WM2200_IN3L_CONTROL,
+};
+
+static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
+{
+       struct wm2200_pdata *pdata = dev_get_platdata(&i2c->dev);
+       struct wm2200_priv *wm2200;
+       unsigned int reg;
+       int ret, i;
+
+       wm2200 = devm_kzalloc(&i2c->dev, sizeof(struct wm2200_priv),
+                             GFP_KERNEL);
+       if (wm2200 == NULL)
+               return -ENOMEM;
+
+       wm2200->dev = &i2c->dev;
+       init_completion(&wm2200->fll_lock);
+
+       wm2200->regmap = regmap_init_i2c(i2c, &wm2200_regmap);
+       if (IS_ERR(wm2200->regmap)) {
+               ret = PTR_ERR(wm2200->regmap);
+               dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               goto err;
+       }
+
+       if (pdata)
+               wm2200->pdata = *pdata;
+
+       i2c_set_clientdata(i2c, wm2200);
+
+       for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++)
+               wm2200->core_supplies[i].supply = wm2200_core_supply_names[i];
+
+       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm2200->core_supplies),
+                                wm2200->core_supplies);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
+                       ret);
+               goto err_regmap;
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
+                                   wm2200->core_supplies);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
+                       ret);
+               goto err_core;
+       }
+
+       if (wm2200->pdata.ldo_ena) {
+               ret = gpio_request_one(wm2200->pdata.ldo_ena,
+                                      GPIOF_OUT_INIT_HIGH, "WM2200 LDOENA");
+               if (ret < 0) {
+                       dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
+                               wm2200->pdata.ldo_ena, ret);
+                       goto err_enable;
+               }
+               msleep(2);
+       }
+
+       if (wm2200->pdata.reset) {
+               ret = gpio_request_one(wm2200->pdata.reset,
+                                      GPIOF_OUT_INIT_HIGH, "WM2200 /RESET");
+               if (ret < 0) {
+                       dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
+                               wm2200->pdata.reset, ret);
+                       goto err_ldo;
+               }
+       }
+
+       ret = regmap_read(wm2200->regmap, WM2200_SOFTWARE_RESET, &reg);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
+               goto err_reset;
+       }
+       switch (reg) {
+       case 0x2200:
+               break;
+
+       default:
+               dev_err(&i2c->dev, "Device is not a WM2200, ID is %x\n", reg);
+               ret = -EINVAL;
+               goto err_reset;
+       }
+
+       ret = regmap_read(wm2200->regmap, WM2200_DEVICE_REVISION, &reg);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to read revision register\n");
+               goto err_reset;
+       }
+
+       wm2200->rev = reg & WM2200_DEVICE_REVISION_MASK;
+
+       dev_info(&i2c->dev, "revision %c\n", wm2200->rev + 'A');
+
+       switch (wm2200->rev) {
+       case 0:
+               ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch,
+                                           ARRAY_SIZE(wm2200_reva_patch));
+               if (ret != 0) {
+                       dev_err(&i2c->dev, "Failed to register patch: %d\n",
+                               ret);
+               }
+               break;
+       default:
+               break;
+       }
+
+       ret = wm2200_reset(wm2200);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to issue reset\n");
+               goto err_reset;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm2200->pdata.gpio_defaults); i++) {
+               if (!wm2200->pdata.gpio_defaults[i])
+                       continue;
+
+               regmap_write(wm2200->regmap, WM2200_GPIO_CTRL_1 + i,
+                            wm2200->pdata.gpio_defaults[i]);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm2200_dig_vu); i++)
+               regmap_update_bits(wm2200->regmap, wm2200_dig_vu[i],
+                                  WM2200_OUT_VU, WM2200_OUT_VU);
+
+       /* Assign slots 1-6 to channels 1-6 for both TX and RX */
+       for (i = 0; i < 6; i++) {
+               regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_10 + i, i);
+               regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_16 + i, i);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm2200->pdata.in_mode); i++) {
+               regmap_update_bits(wm2200->regmap, wm2200_mic_ctrl_reg[i],
+                                  WM2200_IN1_MODE_MASK |
+                                  WM2200_IN1_DMIC_SUP_MASK,
+                                  (wm2200->pdata.in_mode[i] <<
+                                   WM2200_IN1_MODE_SHIFT) |
+                                  (wm2200->pdata.dmic_sup[i] <<
+                                   WM2200_IN1_DMIC_SUP_SHIFT));
+       }
+
+       if (i2c->irq) {
+               ret = request_threaded_irq(i2c->irq, NULL, wm2200_irq,
+                                          IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                                          "wm2200", wm2200);
+               if (ret == 0)
+                       regmap_update_bits(wm2200->regmap,
+                                          WM2200_INTERRUPT_STATUS_2_MASK,
+                                          WM2200_FLL_LOCK_EINT, 0);
+               else
+                       dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
+                               i2c->irq, ret);
+       }
+
+       pm_runtime_set_active(&i2c->dev);
+       pm_runtime_enable(&i2c->dev);
+       pm_request_idle(&i2c->dev);
+
+       ret = snd_soc_register_codec(&i2c->dev, &soc_codec_wm2200,
+                                    &wm2200_dai, 1);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+               goto err_pm_runtime;
+       }
+
+       return 0;
+
+err_pm_runtime:
+       pm_runtime_disable(&i2c->dev);
+err_reset:
+       if (wm2200->pdata.reset) {
+               gpio_set_value_cansleep(wm2200->pdata.reset, 0);
+               gpio_free(wm2200->pdata.reset);
+       }
+err_ldo:
+       if (wm2200->pdata.ldo_ena) {
+               gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
+               gpio_free(wm2200->pdata.ldo_ena);
+       }
+err_enable:
+       regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
+                              wm2200->core_supplies);
+err_core:
+       regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
+                           wm2200->core_supplies);
+err_regmap:
+       regmap_exit(wm2200->regmap);
+err:
+       return ret;
+}
+
+static __devexit int wm2200_i2c_remove(struct i2c_client *i2c)
+{
+       struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c);
+
+       snd_soc_unregister_codec(&i2c->dev);
+       if (i2c->irq)
+               free_irq(i2c->irq, wm2200);
+       if (wm2200->pdata.reset) {
+               gpio_set_value_cansleep(wm2200->pdata.reset, 0);
+               gpio_free(wm2200->pdata.reset);
+       }
+       if (wm2200->pdata.ldo_ena) {
+               gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
+               gpio_free(wm2200->pdata.ldo_ena);
+       }
+       regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
+                           wm2200->core_supplies);
+       regmap_exit(wm2200->regmap);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int wm2200_runtime_suspend(struct device *dev)
+{
+       struct wm2200_priv *wm2200 = dev_get_drvdata(dev);
+
+       regcache_cache_only(wm2200->regmap, true);
+       regcache_mark_dirty(wm2200->regmap);
+       if (wm2200->pdata.ldo_ena)
+               gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
+       regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
+                              wm2200->core_supplies);
+
+       return 0;
+}
+
+static int wm2200_runtime_resume(struct device *dev)
+{
+       struct wm2200_priv *wm2200 = dev_get_drvdata(dev);
+       int ret;
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
+                                   wm2200->core_supplies);
+       if (ret != 0) {
+               dev_err(dev, "Failed to enable supplies: %d\n",
+                       ret);
+               return ret;
+       }
+
+       if (wm2200->pdata.ldo_ena) {
+               gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 1);
+               msleep(2);
+       }
+
+       regcache_cache_only(wm2200->regmap, false);
+       regcache_sync(wm2200->regmap);
+
+       return 0;
+}
+#endif
+
+static struct dev_pm_ops wm2200_pm = {
+       SET_RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume,
+                          NULL)
+};
+
+static const struct i2c_device_id wm2200_i2c_id[] = {
+       { "wm2200", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id);
+
+static struct i2c_driver wm2200_i2c_driver = {
+       .driver = {
+               .name = "wm2200",
+               .owner = THIS_MODULE,
+               .pm = &wm2200_pm,
+       },
+       .probe =    wm2200_i2c_probe,
+       .remove =   __devexit_p(wm2200_i2c_remove),
+       .id_table = wm2200_i2c_id,
+};
+
+static int __init wm2200_modinit(void)
+{
+       return i2c_add_driver(&wm2200_i2c_driver);
+}
+module_init(wm2200_modinit);
+
+static void __exit wm2200_exit(void)
+{
+       i2c_del_driver(&wm2200_i2c_driver);
+}
+module_exit(wm2200_exit);
+
+MODULE_DESCRIPTION("ASoC WM2200 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm2200.h b/sound/soc/codecs/wm2200.h
new file mode 100644 (file)
index 0000000..5d719d6
--- /dev/null
@@ -0,0 +1,3674 @@
+/*
+ * wm2200.h - WM2200 audio codec interface
+ *
+ * Copyright 2012 Wolfson Microelectronics PLC.
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef _WM2200_H
+#define _WM2200_H
+
+#define WM2200_CLK_SYSCLK 1
+
+#define WM2200_CLKSRC_MCLK1  0
+#define WM2200_CLKSRC_MCLK2  1
+#define WM2200_CLKSRC_FLL    4
+#define WM2200_CLKSRC_BCLK1  8
+
+#define WM2200_FLL_SRC_MCLK1 0
+#define WM2200_FLL_SRC_MCLK2 1
+#define WM2200_FLL_SRC_BCLK  2
+
+/*
+ * Register values.
+ */
+#define WM2200_SOFTWARE_RESET                   0x00
+#define WM2200_DEVICE_REVISION                  0x01
+#define WM2200_TONE_GENERATOR_1                 0x0B
+#define WM2200_CLOCKING_3                       0x102
+#define WM2200_CLOCKING_4                       0x103
+#define WM2200_FLL_CONTROL_1                    0x111
+#define WM2200_FLL_CONTROL_2                    0x112
+#define WM2200_FLL_CONTROL_3                    0x113
+#define WM2200_FLL_CONTROL_4                    0x114
+#define WM2200_FLL_CONTROL_6                    0x116
+#define WM2200_FLL_CONTROL_7                    0x117
+#define WM2200_FLL_EFS_1                        0x119
+#define WM2200_FLL_EFS_2                        0x11A
+#define WM2200_MIC_CHARGE_PUMP_1                0x200
+#define WM2200_MIC_CHARGE_PUMP_2                0x201
+#define WM2200_DM_CHARGE_PUMP_1                 0x202
+#define WM2200_MIC_BIAS_CTRL_1                  0x20C
+#define WM2200_MIC_BIAS_CTRL_2                  0x20D
+#define WM2200_EAR_PIECE_CTRL_1                 0x20F
+#define WM2200_EAR_PIECE_CTRL_2                 0x210
+#define WM2200_INPUT_ENABLES                    0x301
+#define WM2200_IN1L_CONTROL                     0x302
+#define WM2200_IN1R_CONTROL                     0x303
+#define WM2200_IN2L_CONTROL                     0x304
+#define WM2200_IN2R_CONTROL                     0x305
+#define WM2200_IN3L_CONTROL                     0x306
+#define WM2200_IN3R_CONTROL                     0x307
+#define WM2200_RXANC_SRC                        0x30A
+#define WM2200_INPUT_VOLUME_RAMP                0x30B
+#define WM2200_ADC_DIGITAL_VOLUME_1L            0x30C
+#define WM2200_ADC_DIGITAL_VOLUME_1R            0x30D
+#define WM2200_ADC_DIGITAL_VOLUME_2L            0x30E
+#define WM2200_ADC_DIGITAL_VOLUME_2R            0x30F
+#define WM2200_ADC_DIGITAL_VOLUME_3L            0x310
+#define WM2200_ADC_DIGITAL_VOLUME_3R            0x311
+#define WM2200_OUTPUT_ENABLES                   0x400
+#define WM2200_DAC_VOLUME_LIMIT_1L              0x401
+#define WM2200_DAC_VOLUME_LIMIT_1R              0x402
+#define WM2200_DAC_VOLUME_LIMIT_2L              0x403
+#define WM2200_DAC_VOLUME_LIMIT_2R              0x404
+#define WM2200_DAC_AEC_CONTROL_1                0x409
+#define WM2200_OUTPUT_VOLUME_RAMP               0x40A
+#define WM2200_DAC_DIGITAL_VOLUME_1L            0x40B
+#define WM2200_DAC_DIGITAL_VOLUME_1R            0x40C
+#define WM2200_DAC_DIGITAL_VOLUME_2L            0x40D
+#define WM2200_DAC_DIGITAL_VOLUME_2R            0x40E
+#define WM2200_PDM_1                            0x417
+#define WM2200_PDM_2                            0x418
+#define WM2200_AUDIO_IF_1_1                     0x500
+#define WM2200_AUDIO_IF_1_2                     0x501
+#define WM2200_AUDIO_IF_1_3                     0x502
+#define WM2200_AUDIO_IF_1_4                     0x503
+#define WM2200_AUDIO_IF_1_5                     0x504
+#define WM2200_AUDIO_IF_1_6                     0x505
+#define WM2200_AUDIO_IF_1_7                     0x506
+#define WM2200_AUDIO_IF_1_8                     0x507
+#define WM2200_AUDIO_IF_1_9                     0x508
+#define WM2200_AUDIO_IF_1_10                    0x509
+#define WM2200_AUDIO_IF_1_11                    0x50A
+#define WM2200_AUDIO_IF_1_12                    0x50B
+#define WM2200_AUDIO_IF_1_13                    0x50C
+#define WM2200_AUDIO_IF_1_14                    0x50D
+#define WM2200_AUDIO_IF_1_15                    0x50E
+#define WM2200_AUDIO_IF_1_16                    0x50F
+#define WM2200_AUDIO_IF_1_17                    0x510
+#define WM2200_AUDIO_IF_1_18                    0x511
+#define WM2200_AUDIO_IF_1_19                    0x512
+#define WM2200_AUDIO_IF_1_20                    0x513
+#define WM2200_AUDIO_IF_1_21                    0x514
+#define WM2200_AUDIO_IF_1_22                    0x515
+#define WM2200_OUT1LMIX_INPUT_1_SOURCE          0x600
+#define WM2200_OUT1LMIX_INPUT_1_VOLUME          0x601
+#define WM2200_OUT1LMIX_INPUT_2_SOURCE          0x602
+#define WM2200_OUT1LMIX_INPUT_2_VOLUME          0x603
+#define WM2200_OUT1LMIX_INPUT_3_SOURCE          0x604
+#define WM2200_OUT1LMIX_INPUT_3_VOLUME          0x605
+#define WM2200_OUT1LMIX_INPUT_4_SOURCE          0x606
+#define WM2200_OUT1LMIX_INPUT_4_VOLUME          0x607
+#define WM2200_OUT1RMIX_INPUT_1_SOURCE          0x608
+#define WM2200_OUT1RMIX_INPUT_1_VOLUME          0x609
+#define WM2200_OUT1RMIX_INPUT_2_SOURCE          0x60A
+#define WM2200_OUT1RMIX_INPUT_2_VOLUME          0x60B
+#define WM2200_OUT1RMIX_INPUT_3_SOURCE          0x60C
+#define WM2200_OUT1RMIX_INPUT_3_VOLUME          0x60D
+#define WM2200_OUT1RMIX_INPUT_4_SOURCE          0x60E
+#define WM2200_OUT1RMIX_INPUT_4_VOLUME          0x60F
+#define WM2200_OUT2LMIX_INPUT_1_SOURCE          0x610
+#define WM2200_OUT2LMIX_INPUT_1_VOLUME          0x611
+#define WM2200_OUT2LMIX_INPUT_2_SOURCE          0x612
+#define WM2200_OUT2LMIX_INPUT_2_VOLUME          0x613
+#define WM2200_OUT2LMIX_INPUT_3_SOURCE          0x614
+#define WM2200_OUT2LMIX_INPUT_3_VOLUME          0x615
+#define WM2200_OUT2LMIX_INPUT_4_SOURCE          0x616
+#define WM2200_OUT2LMIX_INPUT_4_VOLUME          0x617
+#define WM2200_OUT2RMIX_INPUT_1_SOURCE          0x618
+#define WM2200_OUT2RMIX_INPUT_1_VOLUME          0x619
+#define WM2200_OUT2RMIX_INPUT_2_SOURCE          0x61A
+#define WM2200_OUT2RMIX_INPUT_2_VOLUME          0x61B
+#define WM2200_OUT2RMIX_INPUT_3_SOURCE          0x61C
+#define WM2200_OUT2RMIX_INPUT_3_VOLUME          0x61D
+#define WM2200_OUT2RMIX_INPUT_4_SOURCE          0x61E
+#define WM2200_OUT2RMIX_INPUT_4_VOLUME          0x61F
+#define WM2200_AIF1TX1MIX_INPUT_1_SOURCE        0x620
+#define WM2200_AIF1TX1MIX_INPUT_1_VOLUME        0x621
+#define WM2200_AIF1TX1MIX_INPUT_2_SOURCE        0x622
+#define WM2200_AIF1TX1MIX_INPUT_2_VOLUME        0x623
+#define WM2200_AIF1TX1MIX_INPUT_3_SOURCE        0x624
+#define WM2200_AIF1TX1MIX_INPUT_3_VOLUME        0x625
+#define WM2200_AIF1TX1MIX_INPUT_4_SOURCE        0x626
+#define WM2200_AIF1TX1MIX_INPUT_4_VOLUME        0x627
+#define WM2200_AIF1TX2MIX_INPUT_1_SOURCE        0x628
+#define WM2200_AIF1TX2MIX_INPUT_1_VOLUME        0x629
+#define WM2200_AIF1TX2MIX_INPUT_2_SOURCE        0x62A
+#define WM2200_AIF1TX2MIX_INPUT_2_VOLUME        0x62B
+#define WM2200_AIF1TX2MIX_INPUT_3_SOURCE        0x62C
+#define WM2200_AIF1TX2MIX_INPUT_3_VOLUME        0x62D
+#define WM2200_AIF1TX2MIX_INPUT_4_SOURCE        0x62E
+#define WM2200_AIF1TX2MIX_INPUT_4_VOLUME        0x62F
+#define WM2200_AIF1TX3MIX_INPUT_1_SOURCE        0x630
+#define WM2200_AIF1TX3MIX_INPUT_1_VOLUME        0x631
+#define WM2200_AIF1TX3MIX_INPUT_2_SOURCE        0x632
+#define WM2200_AIF1TX3MIX_INPUT_2_VOLUME        0x633
+#define WM2200_AIF1TX3MIX_INPUT_3_SOURCE        0x634
+#define WM2200_AIF1TX3MIX_INPUT_3_VOLUME        0x635
+#define WM2200_AIF1TX3MIX_INPUT_4_SOURCE        0x636
+#define WM2200_AIF1TX3MIX_INPUT_4_VOLUME        0x637
+#define WM2200_AIF1TX4MIX_INPUT_1_SOURCE        0x638
+#define WM2200_AIF1TX4MIX_INPUT_1_VOLUME        0x639
+#define WM2200_AIF1TX4MIX_INPUT_2_SOURCE        0x63A
+#define WM2200_AIF1TX4MIX_INPUT_2_VOLUME        0x63B
+#define WM2200_AIF1TX4MIX_INPUT_3_SOURCE        0x63C
+#define WM2200_AIF1TX4MIX_INPUT_3_VOLUME        0x63D
+#define WM2200_AIF1TX4MIX_INPUT_4_SOURCE        0x63E
+#define WM2200_AIF1TX4MIX_INPUT_4_VOLUME        0x63F
+#define WM2200_AIF1TX5MIX_INPUT_1_SOURCE        0x640
+#define WM2200_AIF1TX5MIX_INPUT_1_VOLUME        0x641
+#define WM2200_AIF1TX5MIX_INPUT_2_SOURCE        0x642
+#define WM2200_AIF1TX5MIX_INPUT_2_VOLUME        0x643
+#define WM2200_AIF1TX5MIX_INPUT_3_SOURCE        0x644
+#define WM2200_AIF1TX5MIX_INPUT_3_VOLUME        0x645
+#define WM2200_AIF1TX5MIX_INPUT_4_SOURCE        0x646
+#define WM2200_AIF1TX5MIX_INPUT_4_VOLUME        0x647
+#define WM2200_AIF1TX6MIX_INPUT_1_SOURCE        0x648
+#define WM2200_AIF1TX6MIX_INPUT_1_VOLUME        0x649
+#define WM2200_AIF1TX6MIX_INPUT_2_SOURCE        0x64A
+#define WM2200_AIF1TX6MIX_INPUT_2_VOLUME        0x64B
+#define WM2200_AIF1TX6MIX_INPUT_3_SOURCE        0x64C
+#define WM2200_AIF1TX6MIX_INPUT_3_VOLUME        0x64D
+#define WM2200_AIF1TX6MIX_INPUT_4_SOURCE        0x64E
+#define WM2200_AIF1TX6MIX_INPUT_4_VOLUME        0x64F
+#define WM2200_EQLMIX_INPUT_1_SOURCE            0x650
+#define WM2200_EQLMIX_INPUT_1_VOLUME            0x651
+#define WM2200_EQLMIX_INPUT_2_SOURCE            0x652
+#define WM2200_EQLMIX_INPUT_2_VOLUME            0x653
+#define WM2200_EQLMIX_INPUT_3_SOURCE            0x654
+#define WM2200_EQLMIX_INPUT_3_VOLUME            0x655
+#define WM2200_EQLMIX_INPUT_4_SOURCE            0x656
+#define WM2200_EQLMIX_INPUT_4_VOLUME            0x657
+#define WM2200_EQRMIX_INPUT_1_SOURCE            0x658
+#define WM2200_EQRMIX_INPUT_1_VOLUME            0x659
+#define WM2200_EQRMIX_INPUT_2_SOURCE            0x65A
+#define WM2200_EQRMIX_INPUT_2_VOLUME            0x65B
+#define WM2200_EQRMIX_INPUT_3_SOURCE            0x65C
+#define WM2200_EQRMIX_INPUT_3_VOLUME            0x65D
+#define WM2200_EQRMIX_INPUT_4_SOURCE            0x65E
+#define WM2200_EQRMIX_INPUT_4_VOLUME            0x65F
+#define WM2200_LHPF1MIX_INPUT_1_SOURCE          0x660
+#define WM2200_LHPF1MIX_INPUT_1_VOLUME          0x661
+#define WM2200_LHPF1MIX_INPUT_2_SOURCE          0x662
+#define WM2200_LHPF1MIX_INPUT_2_VOLUME          0x663
+#define WM2200_LHPF1MIX_INPUT_3_SOURCE          0x664
+#define WM2200_LHPF1MIX_INPUT_3_VOLUME          0x665
+#define WM2200_LHPF1MIX_INPUT_4_SOURCE          0x666
+#define WM2200_LHPF1MIX_INPUT_4_VOLUME          0x667
+#define WM2200_LHPF2MIX_INPUT_1_SOURCE          0x668
+#define WM2200_LHPF2MIX_INPUT_1_VOLUME          0x669
+#define WM2200_LHPF2MIX_INPUT_2_SOURCE          0x66A
+#define WM2200_LHPF2MIX_INPUT_2_VOLUME          0x66B
+#define WM2200_LHPF2MIX_INPUT_3_SOURCE          0x66C
+#define WM2200_LHPF2MIX_INPUT_3_VOLUME          0x66D
+#define WM2200_LHPF2MIX_INPUT_4_SOURCE          0x66E
+#define WM2200_LHPF2MIX_INPUT_4_VOLUME          0x66F
+#define WM2200_DSP1LMIX_INPUT_1_SOURCE          0x670
+#define WM2200_DSP1LMIX_INPUT_1_VOLUME          0x671
+#define WM2200_DSP1LMIX_INPUT_2_SOURCE          0x672
+#define WM2200_DSP1LMIX_INPUT_2_VOLUME          0x673
+#define WM2200_DSP1LMIX_INPUT_3_SOURCE          0x674
+#define WM2200_DSP1LMIX_INPUT_3_VOLUME          0x675
+#define WM2200_DSP1LMIX_INPUT_4_SOURCE          0x676
+#define WM2200_DSP1LMIX_INPUT_4_VOLUME          0x677
+#define WM2200_DSP1RMIX_INPUT_1_SOURCE          0x678
+#define WM2200_DSP1RMIX_INPUT_1_VOLUME          0x679
+#define WM2200_DSP1RMIX_INPUT_2_SOURCE          0x67A
+#define WM2200_DSP1RMIX_INPUT_2_VOLUME          0x67B
+#define WM2200_DSP1RMIX_INPUT_3_SOURCE          0x67C
+#define WM2200_DSP1RMIX_INPUT_3_VOLUME          0x67D
+#define WM2200_DSP1RMIX_INPUT_4_SOURCE          0x67E
+#define WM2200_DSP1RMIX_INPUT_4_VOLUME          0x67F
+#define WM2200_DSP1AUX1MIX_INPUT_1_SOURCE       0x680
+#define WM2200_DSP1AUX2MIX_INPUT_1_SOURCE       0x681
+#define WM2200_DSP1AUX3MIX_INPUT_1_SOURCE       0x682
+#define WM2200_DSP1AUX4MIX_INPUT_1_SOURCE       0x683
+#define WM2200_DSP1AUX5MIX_INPUT_1_SOURCE       0x684
+#define WM2200_DSP1AUX6MIX_INPUT_1_SOURCE       0x685
+#define WM2200_DSP2LMIX_INPUT_1_SOURCE          0x686
+#define WM2200_DSP2LMIX_INPUT_1_VOLUME          0x687
+#define WM2200_DSP2LMIX_INPUT_2_SOURCE          0x688
+#define WM2200_DSP2LMIX_INPUT_2_VOLUME          0x689
+#define WM2200_DSP2LMIX_INPUT_3_SOURCE          0x68A
+#define WM2200_DSP2LMIX_INPUT_3_VOLUME          0x68B
+#define WM2200_DSP2LMIX_INPUT_4_SOURCE          0x68C
+#define WM2200_DSP2LMIX_INPUT_4_VOLUME          0x68D
+#define WM2200_DSP2RMIX_INPUT_1_SOURCE          0x68E
+#define WM2200_DSP2RMIX_INPUT_1_VOLUME          0x68F
+#define WM2200_DSP2RMIX_INPUT_2_SOURCE          0x690
+#define WM2200_DSP2RMIX_INPUT_2_VOLUME          0x691
+#define WM2200_DSP2RMIX_INPUT_3_SOURCE          0x692
+#define WM2200_DSP2RMIX_INPUT_3_VOLUME          0x693
+#define WM2200_DSP2RMIX_INPUT_4_SOURCE          0x694
+#define WM2200_DSP2RMIX_INPUT_4_VOLUME          0x695
+#define WM2200_DSP2AUX1MIX_INPUT_1_SOURCE       0x696
+#define WM2200_DSP2AUX2MIX_INPUT_1_SOURCE       0x697
+#define WM2200_DSP2AUX3MIX_INPUT_1_SOURCE       0x698
+#define WM2200_DSP2AUX4MIX_INPUT_1_SOURCE       0x699
+#define WM2200_DSP2AUX5MIX_INPUT_1_SOURCE       0x69A
+#define WM2200_DSP2AUX6MIX_INPUT_1_SOURCE       0x69B
+#define WM2200_GPIO_CTRL_1                      0x700
+#define WM2200_GPIO_CTRL_2                      0x701
+#define WM2200_GPIO_CTRL_3                      0x702
+#define WM2200_GPIO_CTRL_4                      0x703
+#define WM2200_ADPS1_IRQ0                       0x707
+#define WM2200_ADPS1_IRQ1                       0x708
+#define WM2200_MISC_PAD_CTRL_1                  0x709
+#define WM2200_INTERRUPT_STATUS_1               0x800
+#define WM2200_INTERRUPT_STATUS_1_MASK          0x801
+#define WM2200_INTERRUPT_STATUS_2               0x802
+#define WM2200_INTERRUPT_RAW_STATUS_2           0x803
+#define WM2200_INTERRUPT_STATUS_2_MASK          0x804
+#define WM2200_INTERRUPT_CONTROL                0x808
+#define WM2200_EQL_1                            0x900
+#define WM2200_EQL_2                            0x901
+#define WM2200_EQL_3                            0x902
+#define WM2200_EQL_4                            0x903
+#define WM2200_EQL_5                            0x904
+#define WM2200_EQL_6                            0x905
+#define WM2200_EQL_7                            0x906
+#define WM2200_EQL_8                            0x907
+#define WM2200_EQL_9                            0x908
+#define WM2200_EQL_10                           0x909
+#define WM2200_EQL_11                           0x90A
+#define WM2200_EQL_12                           0x90B
+#define WM2200_EQL_13                           0x90C
+#define WM2200_EQL_14                           0x90D
+#define WM2200_EQL_15                           0x90E
+#define WM2200_EQL_16                           0x90F
+#define WM2200_EQL_17                           0x910
+#define WM2200_EQL_18                           0x911
+#define WM2200_EQL_19                           0x912
+#define WM2200_EQL_20                           0x913
+#define WM2200_EQR_1                            0x916
+#define WM2200_EQR_2                            0x917
+#define WM2200_EQR_3                            0x918
+#define WM2200_EQR_4                            0x919
+#define WM2200_EQR_5                            0x91A
+#define WM2200_EQR_6                            0x91B
+#define WM2200_EQR_7                            0x91C
+#define WM2200_EQR_8                            0x91D
+#define WM2200_EQR_9                            0x91E
+#define WM2200_EQR_10                           0x91F
+#define WM2200_EQR_11                           0x920
+#define WM2200_EQR_12                           0x921
+#define WM2200_EQR_13                           0x922
+#define WM2200_EQR_14                           0x923
+#define WM2200_EQR_15                           0x924
+#define WM2200_EQR_16                           0x925
+#define WM2200_EQR_17                           0x926
+#define WM2200_EQR_18                           0x927
+#define WM2200_EQR_19                           0x928
+#define WM2200_EQR_20                           0x929
+#define WM2200_HPLPF1_1                         0x93E
+#define WM2200_HPLPF1_2                         0x93F
+#define WM2200_HPLPF2_1                         0x942
+#define WM2200_HPLPF2_2                         0x943
+#define WM2200_DSP1_CONTROL_1                   0xA00
+#define WM2200_DSP1_CONTROL_2                   0xA02
+#define WM2200_DSP1_CONTROL_3                   0xA03
+#define WM2200_DSP1_CONTROL_4                   0xA04
+#define WM2200_DSP1_CONTROL_5                   0xA06
+#define WM2200_DSP1_CONTROL_6                   0xA07
+#define WM2200_DSP1_CONTROL_7                   0xA08
+#define WM2200_DSP1_CONTROL_8                   0xA09
+#define WM2200_DSP1_CONTROL_9                   0xA0A
+#define WM2200_DSP1_CONTROL_10                  0xA0B
+#define WM2200_DSP1_CONTROL_11                  0xA0C
+#define WM2200_DSP1_CONTROL_12                  0xA0D
+#define WM2200_DSP1_CONTROL_13                  0xA0F
+#define WM2200_DSP1_CONTROL_14                  0xA10
+#define WM2200_DSP1_CONTROL_15                  0xA11
+#define WM2200_DSP1_CONTROL_16                  0xA12
+#define WM2200_DSP1_CONTROL_17                  0xA13
+#define WM2200_DSP1_CONTROL_18                  0xA14
+#define WM2200_DSP1_CONTROL_19                  0xA16
+#define WM2200_DSP1_CONTROL_20                  0xA17
+#define WM2200_DSP1_CONTROL_21                  0xA18
+#define WM2200_DSP1_CONTROL_22                  0xA1A
+#define WM2200_DSP1_CONTROL_23                  0xA1B
+#define WM2200_DSP1_CONTROL_24                  0xA1C
+#define WM2200_DSP1_CONTROL_25                  0xA1E
+#define WM2200_DSP1_CONTROL_26                  0xA20
+#define WM2200_DSP1_CONTROL_27                  0xA21
+#define WM2200_DSP1_CONTROL_28                  0xA22
+#define WM2200_DSP1_CONTROL_29                  0xA23
+#define WM2200_DSP1_CONTROL_30                  0xA24
+#define WM2200_DSP1_CONTROL_31                  0xA26
+#define WM2200_DSP2_CONTROL_1                   0xB00
+#define WM2200_DSP2_CONTROL_2                   0xB02
+#define WM2200_DSP2_CONTROL_3                   0xB03
+#define WM2200_DSP2_CONTROL_4                   0xB04
+#define WM2200_DSP2_CONTROL_5                   0xB06
+#define WM2200_DSP2_CONTROL_6                   0xB07
+#define WM2200_DSP2_CONTROL_7                   0xB08
+#define WM2200_DSP2_CONTROL_8                   0xB09
+#define WM2200_DSP2_CONTROL_9                   0xB0A
+#define WM2200_DSP2_CONTROL_10                  0xB0B
+#define WM2200_DSP2_CONTROL_11                  0xB0C
+#define WM2200_DSP2_CONTROL_12                  0xB0D
+#define WM2200_DSP2_CONTROL_13                  0xB0F
+#define WM2200_DSP2_CONTROL_14                  0xB10
+#define WM2200_DSP2_CONTROL_15                  0xB11
+#define WM2200_DSP2_CONTROL_16                  0xB12
+#define WM2200_DSP2_CONTROL_17                  0xB13
+#define WM2200_DSP2_CONTROL_18                  0xB14
+#define WM2200_DSP2_CONTROL_19                  0xB16
+#define WM2200_DSP2_CONTROL_20                  0xB17
+#define WM2200_DSP2_CONTROL_21                  0xB18
+#define WM2200_DSP2_CONTROL_22                  0xB1A
+#define WM2200_DSP2_CONTROL_23                  0xB1B
+#define WM2200_DSP2_CONTROL_24                  0xB1C
+#define WM2200_DSP2_CONTROL_25                  0xB1E
+#define WM2200_DSP2_CONTROL_26                  0xB20
+#define WM2200_DSP2_CONTROL_27                  0xB21
+#define WM2200_DSP2_CONTROL_28                  0xB22
+#define WM2200_DSP2_CONTROL_29                  0xB23
+#define WM2200_DSP2_CONTROL_30                  0xB24
+#define WM2200_DSP2_CONTROL_31                  0xB26
+#define WM2200_ANC_CTRL1                        0xD00
+#define WM2200_ANC_CTRL2                        0xD01
+#define WM2200_ANC_CTRL3                        0xD02
+#define WM2200_ANC_CTRL7                        0xD08
+#define WM2200_ANC_CTRL8                        0xD09
+#define WM2200_ANC_CTRL9                        0xD0A
+#define WM2200_ANC_CTRL10                       0xD0B
+#define WM2200_ANC_CTRL11                       0xD0C
+#define WM2200_ANC_CTRL12                       0xD0D
+#define WM2200_ANC_CTRL13                       0xD0E
+#define WM2200_ANC_CTRL14                       0xD0F
+#define WM2200_ANC_CTRL15                       0xD10
+#define WM2200_ANC_CTRL16                       0xD11
+#define WM2200_ANC_CTRL17                       0xD12
+#define WM2200_ANC_CTRL18                       0xD15
+#define WM2200_ANC_CTRL19                       0xD16
+#define WM2200_ANC_CTRL20                       0xD17
+#define WM2200_ANC_CTRL21                       0xD18
+#define WM2200_ANC_CTRL22                       0xD19
+#define WM2200_ANC_CTRL23                       0xD1A
+#define WM2200_ANC_CTRL24                       0xD1B
+#define WM2200_ANC_CTRL25                       0xD1C
+#define WM2200_ANC_CTRL26                       0xD1D
+#define WM2200_ANC_CTRL27                       0xD1E
+#define WM2200_ANC_CTRL28                       0xD1F
+#define WM2200_ANC_CTRL29                       0xD20
+#define WM2200_ANC_CTRL30                       0xD21
+#define WM2200_ANC_CTRL31                       0xD23
+#define WM2200_ANC_CTRL32                       0xD24
+#define WM2200_ANC_CTRL33                       0xD25
+#define WM2200_ANC_CTRL34                       0xD27
+#define WM2200_ANC_CTRL35                       0xD28
+#define WM2200_ANC_CTRL36                       0xD29
+#define WM2200_ANC_CTRL37                       0xD2A
+#define WM2200_ANC_CTRL38                       0xD2B
+#define WM2200_ANC_CTRL39                       0xD2C
+#define WM2200_ANC_CTRL40                       0xD2D
+#define WM2200_ANC_CTRL41                       0xD2E
+#define WM2200_ANC_CTRL42                       0xD2F
+#define WM2200_ANC_CTRL43                       0xD30
+#define WM2200_ANC_CTRL44                       0xD31
+#define WM2200_ANC_CTRL45                       0xD32
+#define WM2200_ANC_CTRL46                       0xD33
+#define WM2200_ANC_CTRL47                       0xD34
+#define WM2200_ANC_CTRL48                       0xD35
+#define WM2200_ANC_CTRL49                       0xD36
+#define WM2200_ANC_CTRL50                       0xD37
+#define WM2200_ANC_CTRL51                       0xD38
+#define WM2200_ANC_CTRL52                       0xD39
+#define WM2200_ANC_CTRL53                       0xD3A
+#define WM2200_ANC_CTRL54                       0xD3B
+#define WM2200_ANC_CTRL55                       0xD3C
+#define WM2200_ANC_CTRL56                       0xD3D
+#define WM2200_ANC_CTRL57                       0xD3E
+#define WM2200_ANC_CTRL58                       0xD3F
+#define WM2200_ANC_CTRL59                       0xD40
+#define WM2200_ANC_CTRL60                       0xD41
+#define WM2200_ANC_CTRL61                       0xD42
+#define WM2200_ANC_CTRL62                       0xD43
+#define WM2200_ANC_CTRL63                       0xD44
+#define WM2200_ANC_CTRL64                       0xD45
+#define WM2200_ANC_CTRL65                       0xD46
+#define WM2200_ANC_CTRL66                       0xD47
+#define WM2200_ANC_CTRL67                       0xD48
+#define WM2200_ANC_CTRL68                       0xD49
+#define WM2200_ANC_CTRL69                       0xD4A
+#define WM2200_ANC_CTRL70                       0xD4B
+#define WM2200_ANC_CTRL71                       0xD4C
+#define WM2200_ANC_CTRL72                       0xD4D
+#define WM2200_ANC_CTRL73                       0xD4E
+#define WM2200_ANC_CTRL74                       0xD4F
+#define WM2200_ANC_CTRL75                       0xD50
+#define WM2200_ANC_CTRL76                       0xD51
+#define WM2200_ANC_CTRL77                       0xD52
+#define WM2200_ANC_CTRL78                       0xD53
+#define WM2200_ANC_CTRL79                       0xD54
+#define WM2200_ANC_CTRL80                       0xD55
+#define WM2200_ANC_CTRL81                       0xD56
+#define WM2200_ANC_CTRL82                       0xD57
+#define WM2200_ANC_CTRL83                       0xD58
+#define WM2200_ANC_CTRL84                       0xD5B
+#define WM2200_ANC_CTRL85                       0xD5C
+#define WM2200_ANC_CTRL86                       0xD5F
+#define WM2200_ANC_CTRL87                       0xD60
+#define WM2200_ANC_CTRL88                       0xD61
+#define WM2200_ANC_CTRL89                       0xD62
+#define WM2200_ANC_CTRL90                       0xD63
+#define WM2200_ANC_CTRL91                       0xD64
+#define WM2200_ANC_CTRL92                       0xD65
+#define WM2200_ANC_CTRL93                       0xD66
+#define WM2200_ANC_CTRL94                       0xD67
+#define WM2200_ANC_CTRL95                       0xD68
+#define WM2200_ANC_CTRL96                       0xD69
+#define WM2200_DSP1_DM_0                        0x3000
+#define WM2200_DSP1_DM_1                        0x3001
+#define WM2200_DSP1_DM_2                        0x3002
+#define WM2200_DSP1_DM_3                        0x3003
+#define WM2200_DSP1_DM_2044                     0x37FC
+#define WM2200_DSP1_DM_2045                     0x37FD
+#define WM2200_DSP1_DM_2046                     0x37FE
+#define WM2200_DSP1_DM_2047                     0x37FF
+#define WM2200_DSP1_PM_0                        0x3800
+#define WM2200_DSP1_PM_1                        0x3801
+#define WM2200_DSP1_PM_2                        0x3802
+#define WM2200_DSP1_PM_3                        0x3803
+#define WM2200_DSP1_PM_4                        0x3804
+#define WM2200_DSP1_PM_5                        0x3805
+#define WM2200_DSP1_PM_762                      0x3AFA
+#define WM2200_DSP1_PM_763                      0x3AFB
+#define WM2200_DSP1_PM_764                      0x3AFC
+#define WM2200_DSP1_PM_765                      0x3AFD
+#define WM2200_DSP1_PM_766                      0x3AFE
+#define WM2200_DSP1_PM_767                      0x3AFF
+#define WM2200_DSP1_ZM_0                        0x3C00
+#define WM2200_DSP1_ZM_1                        0x3C01
+#define WM2200_DSP1_ZM_2                        0x3C02
+#define WM2200_DSP1_ZM_3                        0x3C03
+#define WM2200_DSP1_ZM_1020                     0x3FFC
+#define WM2200_DSP1_ZM_1021                     0x3FFD
+#define WM2200_DSP1_ZM_1022                     0x3FFE
+#define WM2200_DSP1_ZM_1023                     0x3FFF
+#define WM2200_DSP2_DM_0                        0x4000
+#define WM2200_DSP2_DM_1                        0x4001
+#define WM2200_DSP2_DM_2                        0x4002
+#define WM2200_DSP2_DM_3                        0x4003
+#define WM2200_DSP2_DM_2044                     0x47FC
+#define WM2200_DSP2_DM_2045                     0x47FD
+#define WM2200_DSP2_DM_2046                     0x47FE
+#define WM2200_DSP2_DM_2047                     0x47FF
+#define WM2200_DSP2_PM_0                        0x4800
+#define WM2200_DSP2_PM_1                        0x4801
+#define WM2200_DSP2_PM_2                        0x4802
+#define WM2200_DSP2_PM_3                        0x4803
+#define WM2200_DSP2_PM_4                        0x4804
+#define WM2200_DSP2_PM_5                        0x4805
+#define WM2200_DSP2_PM_762                      0x4AFA
+#define WM2200_DSP2_PM_763                      0x4AFB
+#define WM2200_DSP2_PM_764                      0x4AFC
+#define WM2200_DSP2_PM_765                      0x4AFD
+#define WM2200_DSP2_PM_766                      0x4AFE
+#define WM2200_DSP2_PM_767                      0x4AFF
+#define WM2200_DSP2_ZM_0                        0x4C00
+#define WM2200_DSP2_ZM_1                        0x4C01
+#define WM2200_DSP2_ZM_2                        0x4C02
+#define WM2200_DSP2_ZM_3                        0x4C03
+#define WM2200_DSP2_ZM_1020                     0x4FFC
+#define WM2200_DSP2_ZM_1021                     0x4FFD
+#define WM2200_DSP2_ZM_1022                     0x4FFE
+#define WM2200_DSP2_ZM_1023                     0x4FFF
+
+#define WM2200_REGISTER_COUNT                   494
+#define WM2200_MAX_REGISTER                     0x4FFF
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - software reset
+ */
+#define WM2200_SW_RESET_CHIP_ID1_MASK           0xFFFF  /* SW_RESET_CHIP_ID1 - [15:0] */
+#define WM2200_SW_RESET_CHIP_ID1_SHIFT               0  /* SW_RESET_CHIP_ID1 - [15:0] */
+#define WM2200_SW_RESET_CHIP_ID1_WIDTH              16  /* SW_RESET_CHIP_ID1 - [15:0] */
+
+/*
+ * R1 (0x01) - Device Revision
+ */
+#define WM2200_DEVICE_REVISION_MASK             0x000F  /* DEVICE_REVISION - [3:0] */
+#define WM2200_DEVICE_REVISION_SHIFT                 0  /* DEVICE_REVISION - [3:0] */
+#define WM2200_DEVICE_REVISION_WIDTH                 4  /* DEVICE_REVISION - [3:0] */
+
+/*
+ * R11 (0x0B) - Tone Generator 1
+ */
+#define WM2200_TONE_ENA                         0x0001  /* TONE_ENA */
+#define WM2200_TONE_ENA_MASK                    0x0001  /* TONE_ENA */
+#define WM2200_TONE_ENA_SHIFT                        0  /* TONE_ENA */
+#define WM2200_TONE_ENA_WIDTH                        1  /* TONE_ENA */
+
+/*
+ * R258 (0x102) - Clocking 3
+ */
+#define WM2200_SYSCLK_FREQ_MASK                 0x0700  /* SYSCLK_FREQ - [10:8] */
+#define WM2200_SYSCLK_FREQ_SHIFT                     8  /* SYSCLK_FREQ - [10:8] */
+#define WM2200_SYSCLK_FREQ_WIDTH                     3  /* SYSCLK_FREQ - [10:8] */
+#define WM2200_SYSCLK_ENA                       0x0040  /* SYSCLK_ENA */
+#define WM2200_SYSCLK_ENA_MASK                  0x0040  /* SYSCLK_ENA */
+#define WM2200_SYSCLK_ENA_SHIFT                      6  /* SYSCLK_ENA */
+#define WM2200_SYSCLK_ENA_WIDTH                      1  /* SYSCLK_ENA */
+#define WM2200_SYSCLK_SRC_MASK                  0x000F  /* SYSCLK_SRC - [3:0] */
+#define WM2200_SYSCLK_SRC_SHIFT                      0  /* SYSCLK_SRC - [3:0] */
+#define WM2200_SYSCLK_SRC_WIDTH                      4  /* SYSCLK_SRC - [3:0] */
+
+/*
+ * R259 (0x103) - Clocking 4
+ */
+#define WM2200_SAMPLE_RATE_1_MASK               0x001F  /* SAMPLE_RATE_1 - [4:0] */
+#define WM2200_SAMPLE_RATE_1_SHIFT                   0  /* SAMPLE_RATE_1 - [4:0] */
+#define WM2200_SAMPLE_RATE_1_WIDTH                   5  /* SAMPLE_RATE_1 - [4:0] */
+
+/*
+ * R273 (0x111) - FLL Control 1
+ */
+#define WM2200_FLL_ENA                          0x0001  /* FLL_ENA */
+#define WM2200_FLL_ENA_MASK                     0x0001  /* FLL_ENA */
+#define WM2200_FLL_ENA_SHIFT                         0  /* FLL_ENA */
+#define WM2200_FLL_ENA_WIDTH                         1  /* FLL_ENA */
+
+/*
+ * R274 (0x112) - FLL Control 2
+ */
+#define WM2200_FLL_OUTDIV_MASK                  0x3F00  /* FLL_OUTDIV - [13:8] */
+#define WM2200_FLL_OUTDIV_SHIFT                      8  /* FLL_OUTDIV - [13:8] */
+#define WM2200_FLL_OUTDIV_WIDTH                      6  /* FLL_OUTDIV - [13:8] */
+#define WM2200_FLL_FRATIO_MASK                  0x0007  /* FLL_FRATIO - [2:0] */
+#define WM2200_FLL_FRATIO_SHIFT                      0  /* FLL_FRATIO - [2:0] */
+#define WM2200_FLL_FRATIO_WIDTH                      3  /* FLL_FRATIO - [2:0] */
+
+/*
+ * R275 (0x113) - FLL Control 3
+ */
+#define WM2200_FLL_FRACN_ENA                    0x0001  /* FLL_FRACN_ENA */
+#define WM2200_FLL_FRACN_ENA_MASK               0x0001  /* FLL_FRACN_ENA */
+#define WM2200_FLL_FRACN_ENA_SHIFT                   0  /* FLL_FRACN_ENA */
+#define WM2200_FLL_FRACN_ENA_WIDTH                   1  /* FLL_FRACN_ENA */
+
+/*
+ * R276 (0x114) - FLL Control 4
+ */
+#define WM2200_FLL_THETA_MASK                   0xFFFF  /* FLL_THETA - [15:0] */
+#define WM2200_FLL_THETA_SHIFT                       0  /* FLL_THETA - [15:0] */
+#define WM2200_FLL_THETA_WIDTH                      16  /* FLL_THETA - [15:0] */
+
+/*
+ * R278 (0x116) - FLL Control 6
+ */
+#define WM2200_FLL_N_MASK                       0x03FF  /* FLL_N - [9:0] */
+#define WM2200_FLL_N_SHIFT                           0  /* FLL_N - [9:0] */
+#define WM2200_FLL_N_WIDTH                          10  /* FLL_N - [9:0] */
+
+/*
+ * R279 (0x117) - FLL Control 7
+ */
+#define WM2200_FLL_CLK_REF_DIV_MASK             0x0030  /* FLL_CLK_REF_DIV - [5:4] */
+#define WM2200_FLL_CLK_REF_DIV_SHIFT                 4  /* FLL_CLK_REF_DIV - [5:4] */
+#define WM2200_FLL_CLK_REF_DIV_WIDTH                 2  /* FLL_CLK_REF_DIV - [5:4] */
+#define WM2200_FLL_CLK_REF_SRC_MASK             0x0003  /* FLL_CLK_REF_SRC - [1:0] */
+#define WM2200_FLL_CLK_REF_SRC_SHIFT                 0  /* FLL_CLK_REF_SRC - [1:0] */
+#define WM2200_FLL_CLK_REF_SRC_WIDTH                 2  /* FLL_CLK_REF_SRC - [1:0] */
+
+/*
+ * R281 (0x119) - FLL EFS 1
+ */
+#define WM2200_FLL_LAMBDA_MASK                  0xFFFF  /* FLL_LAMBDA - [15:0] */
+#define WM2200_FLL_LAMBDA_SHIFT                      0  /* FLL_LAMBDA - [15:0] */
+#define WM2200_FLL_LAMBDA_WIDTH                     16  /* FLL_LAMBDA - [15:0] */
+
+/*
+ * R282 (0x11A) - FLL EFS 2
+ */
+#define WM2200_FLL_EFS_ENA                      0x0001  /* FLL_EFS_ENA */
+#define WM2200_FLL_EFS_ENA_MASK                 0x0001  /* FLL_EFS_ENA */
+#define WM2200_FLL_EFS_ENA_SHIFT                     0  /* FLL_EFS_ENA */
+#define WM2200_FLL_EFS_ENA_WIDTH                     1  /* FLL_EFS_ENA */
+
+/*
+ * R512 (0x200) - Mic Charge Pump 1
+ */
+#define WM2200_CPMIC_BYPASS_MODE                0x0020  /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_BYPASS_MODE_MASK           0x0020  /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_BYPASS_MODE_SHIFT               5  /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_BYPASS_MODE_WIDTH               1  /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_ENA                        0x0001  /* CPMIC_ENA */
+#define WM2200_CPMIC_ENA_MASK                   0x0001  /* CPMIC_ENA */
+#define WM2200_CPMIC_ENA_SHIFT                       0  /* CPMIC_ENA */
+#define WM2200_CPMIC_ENA_WIDTH                       1  /* CPMIC_ENA */
+
+/*
+ * R513 (0x201) - Mic Charge Pump 2
+ */
+#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_MASK     0xF800  /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */
+#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_SHIFT        11  /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */
+#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_WIDTH         5  /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */
+
+/*
+ * R514 (0x202) - DM Charge Pump 1
+ */
+#define WM2200_CPDM_ENA                         0x0001  /* CPDM_ENA */
+#define WM2200_CPDM_ENA_MASK                    0x0001  /* CPDM_ENA */
+#define WM2200_CPDM_ENA_SHIFT                        0  /* CPDM_ENA */
+#define WM2200_CPDM_ENA_WIDTH                        1  /* CPDM_ENA */
+
+/*
+ * R524 (0x20C) - Mic Bias Ctrl 1
+ */
+#define WM2200_MICB1_DISCH                      0x0040  /* MICB1_DISCH */
+#define WM2200_MICB1_DISCH_MASK                 0x0040  /* MICB1_DISCH */
+#define WM2200_MICB1_DISCH_SHIFT                     6  /* MICB1_DISCH */
+#define WM2200_MICB1_DISCH_WIDTH                     1  /* MICB1_DISCH */
+#define WM2200_MICB1_RATE                       0x0020  /* MICB1_RATE */
+#define WM2200_MICB1_RATE_MASK                  0x0020  /* MICB1_RATE */
+#define WM2200_MICB1_RATE_SHIFT                      5  /* MICB1_RATE */
+#define WM2200_MICB1_RATE_WIDTH                      1  /* MICB1_RATE */
+#define WM2200_MICB1_LVL_MASK                   0x001C  /* MICB1_LVL - [4:2] */
+#define WM2200_MICB1_LVL_SHIFT                       2  /* MICB1_LVL - [4:2] */
+#define WM2200_MICB1_LVL_WIDTH                       3  /* MICB1_LVL - [4:2] */
+#define WM2200_MICB1_MODE                       0x0002  /* MICB1_MODE */
+#define WM2200_MICB1_MODE_MASK                  0x0002  /* MICB1_MODE */
+#define WM2200_MICB1_MODE_SHIFT                      1  /* MICB1_MODE */
+#define WM2200_MICB1_MODE_WIDTH                      1  /* MICB1_MODE */
+#define WM2200_MICB1_ENA                        0x0001  /* MICB1_ENA */
+#define WM2200_MICB1_ENA_MASK                   0x0001  /* MICB1_ENA */
+#define WM2200_MICB1_ENA_SHIFT                       0  /* MICB1_ENA */
+#define WM2200_MICB1_ENA_WIDTH                       1  /* MICB1_ENA */
+
+/*
+ * R525 (0x20D) - Mic Bias Ctrl 2
+ */
+#define WM2200_MICB2_DISCH                      0x0040  /* MICB2_DISCH */
+#define WM2200_MICB2_DISCH_MASK                 0x0040  /* MICB2_DISCH */
+#define WM2200_MICB2_DISCH_SHIFT                     6  /* MICB2_DISCH */
+#define WM2200_MICB2_DISCH_WIDTH                     1  /* MICB2_DISCH */
+#define WM2200_MICB2_RATE                       0x0020  /* MICB2_RATE */
+#define WM2200_MICB2_RATE_MASK                  0x0020  /* MICB2_RATE */
+#define WM2200_MICB2_RATE_SHIFT                      5  /* MICB2_RATE */
+#define WM2200_MICB2_RATE_WIDTH                      1  /* MICB2_RATE */
+#define WM2200_MICB2_LVL_MASK                   0x001C  /* MICB2_LVL - [4:2] */
+#define WM2200_MICB2_LVL_SHIFT                       2  /* MICB2_LVL - [4:2] */
+#define WM2200_MICB2_LVL_WIDTH                       3  /* MICB2_LVL - [4:2] */
+#define WM2200_MICB2_MODE                       0x0002  /* MICB2_MODE */
+#define WM2200_MICB2_MODE_MASK                  0x0002  /* MICB2_MODE */
+#define WM2200_MICB2_MODE_SHIFT                      1  /* MICB2_MODE */
+#define WM2200_MICB2_MODE_WIDTH                      1  /* MICB2_MODE */
+#define WM2200_MICB2_ENA                        0x0001  /* MICB2_ENA */
+#define WM2200_MICB2_ENA_MASK                   0x0001  /* MICB2_ENA */
+#define WM2200_MICB2_ENA_SHIFT                       0  /* MICB2_ENA */
+#define WM2200_MICB2_ENA_WIDTH                       1  /* MICB2_ENA */
+
+/*
+ * R527 (0x20F) - Ear Piece Ctrl 1
+ */
+#define WM2200_EPD_LP_ENA                       0x4000  /* EPD_LP_ENA */
+#define WM2200_EPD_LP_ENA_MASK                  0x4000  /* EPD_LP_ENA */
+#define WM2200_EPD_LP_ENA_SHIFT                     14  /* EPD_LP_ENA */
+#define WM2200_EPD_LP_ENA_WIDTH                      1  /* EPD_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA                  0x2000  /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA_MASK             0x2000  /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA_SHIFT                13  /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA_WIDTH                 1  /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_RMV_SHRT_LP                  0x1000  /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_RMV_SHRT_LP_MASK             0x1000  /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_RMV_SHRT_LP_SHIFT                12  /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_RMV_SHRT_LP_WIDTH                 1  /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_LN_ENA                       0x0800  /* EPD_LN_ENA */
+#define WM2200_EPD_LN_ENA_MASK                  0x0800  /* EPD_LN_ENA */
+#define WM2200_EPD_LN_ENA_SHIFT                     11  /* EPD_LN_ENA */
+#define WM2200_EPD_LN_ENA_WIDTH                      1  /* EPD_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA                  0x0400  /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA_MASK             0x0400  /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA_SHIFT                10  /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA_WIDTH                 1  /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_RMV_SHRT_LN                  0x0200  /* EPD_RMV_SHRT_LN */
+#define WM2200_EPD_RMV_SHRT_LN_MASK             0x0200  /* EPD_RMV_SHRT_LN */
+#define WM2200_EPD_RMV_SHRT_LN_SHIFT                 9  /* EPD_RMV_SHRT_LN */
+#define WM2200_EPD_RMV_SHRT_LN_WIDTH                 1  /* EPD_RMV_SHRT_LN */
+
+/*
+ * R528 (0x210) - Ear Piece Ctrl 2
+ */
+#define WM2200_EPD_RP_ENA                       0x4000  /* EPD_RP_ENA */
+#define WM2200_EPD_RP_ENA_MASK                  0x4000  /* EPD_RP_ENA */
+#define WM2200_EPD_RP_ENA_SHIFT                     14  /* EPD_RP_ENA */
+#define WM2200_EPD_RP_ENA_WIDTH                      1  /* EPD_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA                  0x2000  /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA_MASK             0x2000  /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA_SHIFT                13  /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA_WIDTH                 1  /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_RMV_SHRT_RP                  0x1000  /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RMV_SHRT_RP_MASK             0x1000  /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RMV_SHRT_RP_SHIFT                12  /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RMV_SHRT_RP_WIDTH                 1  /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RN_ENA                       0x0800  /* EPD_RN_ENA */
+#define WM2200_EPD_RN_ENA_MASK                  0x0800  /* EPD_RN_ENA */
+#define WM2200_EPD_RN_ENA_SHIFT                     11  /* EPD_RN_ENA */
+#define WM2200_EPD_RN_ENA_WIDTH                      1  /* EPD_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA                  0x0400  /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA_MASK             0x0400  /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA_SHIFT                10  /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA_WIDTH                 1  /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_RMV_SHRT_RN                  0x0200  /* EPD_RMV_SHRT_RN */
+#define WM2200_EPD_RMV_SHRT_RN_MASK             0x0200  /* EPD_RMV_SHRT_RN */
+#define WM2200_EPD_RMV_SHRT_RN_SHIFT                 9  /* EPD_RMV_SHRT_RN */
+#define WM2200_EPD_RMV_SHRT_RN_WIDTH                 1  /* EPD_RMV_SHRT_RN */
+
+/*
+ * R769 (0x301) - Input Enables
+ */
+#define WM2200_IN3L_ENA                         0x0020  /* IN3L_ENA */
+#define WM2200_IN3L_ENA_MASK                    0x0020  /* IN3L_ENA */
+#define WM2200_IN3L_ENA_SHIFT                        5  /* IN3L_ENA */
+#define WM2200_IN3L_ENA_WIDTH                        1  /* IN3L_ENA */
+#define WM2200_IN3R_ENA                         0x0010  /* IN3R_ENA */
+#define WM2200_IN3R_ENA_MASK                    0x0010  /* IN3R_ENA */
+#define WM2200_IN3R_ENA_SHIFT                        4  /* IN3R_ENA */
+#define WM2200_IN3R_ENA_WIDTH                        1  /* IN3R_ENA */
+#define WM2200_IN2L_ENA                         0x0008  /* IN2L_ENA */
+#define WM2200_IN2L_ENA_MASK                    0x0008  /* IN2L_ENA */
+#define WM2200_IN2L_ENA_SHIFT                        3  /* IN2L_ENA */
+#define WM2200_IN2L_ENA_WIDTH                        1  /* IN2L_ENA */
+#define WM2200_IN2R_ENA                         0x0004  /* IN2R_ENA */
+#define WM2200_IN2R_ENA_MASK                    0x0004  /* IN2R_ENA */
+#define WM2200_IN2R_ENA_SHIFT                        2  /* IN2R_ENA */
+#define WM2200_IN2R_ENA_WIDTH                        1  /* IN2R_ENA */
+#define WM2200_IN1L_ENA                         0x0002  /* IN1L_ENA */
+#define WM2200_IN1L_ENA_MASK                    0x0002  /* IN1L_ENA */
+#define WM2200_IN1L_ENA_SHIFT                        1  /* IN1L_ENA */
+#define WM2200_IN1L_ENA_WIDTH                        1  /* IN1L_ENA */
+#define WM2200_IN1R_ENA                         0x0001  /* IN1R_ENA */
+#define WM2200_IN1R_ENA_MASK                    0x0001  /* IN1R_ENA */
+#define WM2200_IN1R_ENA_SHIFT                        0  /* IN1R_ENA */
+#define WM2200_IN1R_ENA_WIDTH                        1  /* IN1R_ENA */
+
+/*
+ * R770 (0x302) - IN1L Control
+ */
+#define WM2200_IN1_OSR                          0x2000  /* IN1_OSR */
+#define WM2200_IN1_OSR_MASK                     0x2000  /* IN1_OSR */
+#define WM2200_IN1_OSR_SHIFT                        13  /* IN1_OSR */
+#define WM2200_IN1_OSR_WIDTH                         1  /* IN1_OSR */
+#define WM2200_IN1_DMIC_SUP_MASK                0x1800  /* IN1_DMIC_SUP - [12:11] */
+#define WM2200_IN1_DMIC_SUP_SHIFT                   11  /* IN1_DMIC_SUP - [12:11] */
+#define WM2200_IN1_DMIC_SUP_WIDTH                    2  /* IN1_DMIC_SUP - [12:11] */
+#define WM2200_IN1_MODE_MASK                    0x0600  /* IN1_MODE - [10:9] */
+#define WM2200_IN1_MODE_SHIFT                        9  /* IN1_MODE - [10:9] */
+#define WM2200_IN1_MODE_WIDTH                        2  /* IN1_MODE - [10:9] */
+#define WM2200_IN1L_PGA_VOL_MASK                0x00FE  /* IN1L_PGA_VOL - [7:1] */
+#define WM2200_IN1L_PGA_VOL_SHIFT                    1  /* IN1L_PGA_VOL - [7:1] */
+#define WM2200_IN1L_PGA_VOL_WIDTH                    7  /* IN1L_PGA_VOL - [7:1] */
+
+/*
+ * R771 (0x303) - IN1R Control
+ */
+#define WM2200_IN1R_PGA_VOL_MASK                0x00FE  /* IN1R_PGA_VOL - [7:1] */
+#define WM2200_IN1R_PGA_VOL_SHIFT                    1  /* IN1R_PGA_VOL - [7:1] */
+#define WM2200_IN1R_PGA_VOL_WIDTH                    7  /* IN1R_PGA_VOL - [7:1] */
+
+/*
+ * R772 (0x304) - IN2L Control
+ */
+#define WM2200_IN2_OSR                          0x2000  /* IN2_OSR */
+#define WM2200_IN2_OSR_MASK                     0x2000  /* IN2_OSR */
+#define WM2200_IN2_OSR_SHIFT                        13  /* IN2_OSR */
+#define WM2200_IN2_OSR_WIDTH                         1  /* IN2_OSR */
+#define WM2200_IN2_DMIC_SUP_MASK                0x1800  /* IN2_DMIC_SUP - [12:11] */
+#define WM2200_IN2_DMIC_SUP_SHIFT                   11  /* IN2_DMIC_SUP - [12:11] */
+#define WM2200_IN2_DMIC_SUP_WIDTH                    2  /* IN2_DMIC_SUP - [12:11] */
+#define WM2200_IN2_MODE_MASK                    0x0600  /* IN2_MODE - [10:9] */
+#define WM2200_IN2_MODE_SHIFT                        9  /* IN2_MODE - [10:9] */
+#define WM2200_IN2_MODE_WIDTH                        2  /* IN2_MODE - [10:9] */
+#define WM2200_IN2L_PGA_VOL_MASK                0x00FE  /* IN2L_PGA_VOL - [7:1] */
+#define WM2200_IN2L_PGA_VOL_SHIFT                    1  /* IN2L_PGA_VOL - [7:1] */
+#define WM2200_IN2L_PGA_VOL_WIDTH                    7  /* IN2L_PGA_VOL - [7:1] */
+
+/*
+ * R773 (0x305) - IN2R Control
+ */
+#define WM2200_IN2R_PGA_VOL_MASK                0x00FE  /* IN2R_PGA_VOL - [7:1] */
+#define WM2200_IN2R_PGA_VOL_SHIFT                    1  /* IN2R_PGA_VOL - [7:1] */
+#define WM2200_IN2R_PGA_VOL_WIDTH                    7  /* IN2R_PGA_VOL - [7:1] */
+
+/*
+ * R774 (0x306) - IN3L Control
+ */
+#define WM2200_IN3_OSR                          0x2000  /* IN3_OSR */
+#define WM2200_IN3_OSR_MASK                     0x2000  /* IN3_OSR */
+#define WM2200_IN3_OSR_SHIFT                        13  /* IN3_OSR */
+#define WM2200_IN3_OSR_WIDTH                         1  /* IN3_OSR */
+#define WM2200_IN3_DMIC_SUP_MASK                0x1800  /* IN3_DMIC_SUP - [12:11] */
+#define WM2200_IN3_DMIC_SUP_SHIFT                   11  /* IN3_DMIC_SUP - [12:11] */
+#define WM2200_IN3_DMIC_SUP_WIDTH                    2  /* IN3_DMIC_SUP - [12:11] */
+#define WM2200_IN3_MODE_MASK                    0x0600  /* IN3_MODE - [10:9] */
+#define WM2200_IN3_MODE_SHIFT                        9  /* IN3_MODE - [10:9] */
+#define WM2200_IN3_MODE_WIDTH                        2  /* IN3_MODE - [10:9] */
+#define WM2200_IN3L_PGA_VOL_MASK                0x00FE  /* IN3L_PGA_VOL - [7:1] */
+#define WM2200_IN3L_PGA_VOL_SHIFT                    1  /* IN3L_PGA_VOL - [7:1] */
+#define WM2200_IN3L_PGA_VOL_WIDTH                    7  /* IN3L_PGA_VOL - [7:1] */
+
+/*
+ * R775 (0x307) - IN3R Control
+ */
+#define WM2200_IN3R_PGA_VOL_MASK                0x00FE  /* IN3R_PGA_VOL - [7:1] */
+#define WM2200_IN3R_PGA_VOL_SHIFT                    1  /* IN3R_PGA_VOL - [7:1] */
+#define WM2200_IN3R_PGA_VOL_WIDTH                    7  /* IN3R_PGA_VOL - [7:1] */
+
+/*
+ * R778 (0x30A) - RXANC_SRC
+ */
+#define WM2200_IN_RXANC_SEL_MASK                0x0007  /* IN_RXANC_SEL - [2:0] */
+#define WM2200_IN_RXANC_SEL_SHIFT                    0  /* IN_RXANC_SEL - [2:0] */
+#define WM2200_IN_RXANC_SEL_WIDTH                    3  /* IN_RXANC_SEL - [2:0] */
+
+/*
+ * R779 (0x30B) - Input Volume Ramp
+ */
+#define WM2200_IN_VD_RAMP_MASK                  0x0070  /* IN_VD_RAMP - [6:4] */
+#define WM2200_IN_VD_RAMP_SHIFT                      4  /* IN_VD_RAMP - [6:4] */
+#define WM2200_IN_VD_RAMP_WIDTH                      3  /* IN_VD_RAMP - [6:4] */
+#define WM2200_IN_VI_RAMP_MASK                  0x0007  /* IN_VI_RAMP - [2:0] */
+#define WM2200_IN_VI_RAMP_SHIFT                      0  /* IN_VI_RAMP - [2:0] */
+#define WM2200_IN_VI_RAMP_WIDTH                      3  /* IN_VI_RAMP - [2:0] */
+
+/*
+ * R780 (0x30C) - ADC Digital Volume 1L
+ */
+#define WM2200_IN_VU                            0x0200  /* IN_VU */
+#define WM2200_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM2200_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM2200_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM2200_IN1L_MUTE                        0x0100  /* IN1L_MUTE */
+#define WM2200_IN1L_MUTE_MASK                   0x0100  /* IN1L_MUTE */
+#define WM2200_IN1L_MUTE_SHIFT                       8  /* IN1L_MUTE */
+#define WM2200_IN1L_MUTE_WIDTH                       1  /* IN1L_MUTE */
+#define WM2200_IN1L_DIG_VOL_MASK                0x00FF  /* IN1L_DIG_VOL - [7:0] */
+#define WM2200_IN1L_DIG_VOL_SHIFT                    0  /* IN1L_DIG_VOL - [7:0] */
+#define WM2200_IN1L_DIG_VOL_WIDTH                    8  /* IN1L_DIG_VOL - [7:0] */
+
+/*
+ * R781 (0x30D) - ADC Digital Volume 1R
+ */
+#define WM2200_IN_VU                            0x0200  /* IN_VU */
+#define WM2200_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM2200_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM2200_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM2200_IN1R_MUTE                        0x0100  /* IN1R_MUTE */
+#define WM2200_IN1R_MUTE_MASK                   0x0100  /* IN1R_MUTE */
+#define WM2200_IN1R_MUTE_SHIFT                       8  /* IN1R_MUTE */
+#define WM2200_IN1R_MUTE_WIDTH                       1  /* IN1R_MUTE */
+#define WM2200_IN1R_DIG_VOL_MASK                0x00FF  /* IN1R_DIG_VOL - [7:0] */
+#define WM2200_IN1R_DIG_VOL_SHIFT                    0  /* IN1R_DIG_VOL - [7:0] */
+#define WM2200_IN1R_DIG_VOL_WIDTH                    8  /* IN1R_DIG_VOL - [7:0] */
+
+/*
+ * R782 (0x30E) - ADC Digital Volume 2L
+ */
+#define WM2200_IN_VU                            0x0200  /* IN_VU */
+#define WM2200_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM2200_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM2200_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM2200_IN2L_MUTE                        0x0100  /* IN2L_MUTE */
+#define WM2200_IN2L_MUTE_MASK                   0x0100  /* IN2L_MUTE */
+#define WM2200_IN2L_MUTE_SHIFT                       8  /* IN2L_MUTE */
+#define WM2200_IN2L_MUTE_WIDTH                       1  /* IN2L_MUTE */
+#define WM2200_IN2L_DIG_VOL_MASK                0x00FF  /* IN2L_DIG_VOL - [7:0] */
+#define WM2200_IN2L_DIG_VOL_SHIFT                    0  /* IN2L_DIG_VOL - [7:0] */
+#define WM2200_IN2L_DIG_VOL_WIDTH                    8  /* IN2L_DIG_VOL - [7:0] */
+
+/*
+ * R783 (0x30F) - ADC Digital Volume 2R
+ */
+#define WM2200_IN_VU                            0x0200  /* IN_VU */
+#define WM2200_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM2200_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM2200_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM2200_IN2R_MUTE                        0x0100  /* IN2R_MUTE */
+#define WM2200_IN2R_MUTE_MASK                   0x0100  /* IN2R_MUTE */
+#define WM2200_IN2R_MUTE_SHIFT                       8  /* IN2R_MUTE */
+#define WM2200_IN2R_MUTE_WIDTH                       1  /* IN2R_MUTE */
+#define WM2200_IN2R_DIG_VOL_MASK                0x00FF  /* IN2R_DIG_VOL - [7:0] */
+#define WM2200_IN2R_DIG_VOL_SHIFT                    0  /* IN2R_DIG_VOL - [7:0] */
+#define WM2200_IN2R_DIG_VOL_WIDTH                    8  /* IN2R_DIG_VOL - [7:0] */
+
+/*
+ * R784 (0x310) - ADC Digital Volume 3L
+ */
+#define WM2200_IN_VU                            0x0200  /* IN_VU */
+#define WM2200_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM2200_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM2200_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM2200_IN3L_MUTE                        0x0100  /* IN3L_MUTE */
+#define WM2200_IN3L_MUTE_MASK                   0x0100  /* IN3L_MUTE */
+#define WM2200_IN3L_MUTE_SHIFT                       8  /* IN3L_MUTE */
+#define WM2200_IN3L_MUTE_WIDTH                       1  /* IN3L_MUTE */
+#define WM2200_IN3L_DIG_VOL_MASK                0x00FF  /* IN3L_DIG_VOL - [7:0] */
+#define WM2200_IN3L_DIG_VOL_SHIFT                    0  /* IN3L_DIG_VOL - [7:0] */
+#define WM2200_IN3L_DIG_VOL_WIDTH                    8  /* IN3L_DIG_VOL - [7:0] */
+
+/*
+ * R785 (0x311) - ADC Digital Volume 3R
+ */
+#define WM2200_IN_VU                            0x0200  /* IN_VU */
+#define WM2200_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM2200_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM2200_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM2200_IN3R_MUTE                        0x0100  /* IN3R_MUTE */
+#define WM2200_IN3R_MUTE_MASK                   0x0100  /* IN3R_MUTE */
+#define WM2200_IN3R_MUTE_SHIFT                       8  /* IN3R_MUTE */
+#define WM2200_IN3R_MUTE_WIDTH                       1  /* IN3R_MUTE */
+#define WM2200_IN3R_DIG_VOL_MASK                0x00FF  /* IN3R_DIG_VOL - [7:0] */
+#define WM2200_IN3R_DIG_VOL_SHIFT                    0  /* IN3R_DIG_VOL - [7:0] */
+#define WM2200_IN3R_DIG_VOL_WIDTH                    8  /* IN3R_DIG_VOL - [7:0] */
+
+/*
+ * R1024 (0x400) - Output Enables
+ */
+#define WM2200_OUT2L_ENA                        0x0008  /* OUT2L_ENA */
+#define WM2200_OUT2L_ENA_MASK                   0x0008  /* OUT2L_ENA */
+#define WM2200_OUT2L_ENA_SHIFT                       3  /* OUT2L_ENA */
+#define WM2200_OUT2L_ENA_WIDTH                       1  /* OUT2L_ENA */
+#define WM2200_OUT2R_ENA                        0x0004  /* OUT2R_ENA */
+#define WM2200_OUT2R_ENA_MASK                   0x0004  /* OUT2R_ENA */
+#define WM2200_OUT2R_ENA_SHIFT                       2  /* OUT2R_ENA */
+#define WM2200_OUT2R_ENA_WIDTH                       1  /* OUT2R_ENA */
+#define WM2200_OUT1L_ENA                        0x0002  /* OUT1L_ENA */
+#define WM2200_OUT1L_ENA_MASK                   0x0002  /* OUT1L_ENA */
+#define WM2200_OUT1L_ENA_SHIFT                       1  /* OUT1L_ENA */
+#define WM2200_OUT1L_ENA_WIDTH                       1  /* OUT1L_ENA */
+#define WM2200_OUT1R_ENA                        0x0001  /* OUT1R_ENA */
+#define WM2200_OUT1R_ENA_MASK                   0x0001  /* OUT1R_ENA */
+#define WM2200_OUT1R_ENA_SHIFT                       0  /* OUT1R_ENA */
+#define WM2200_OUT1R_ENA_WIDTH                       1  /* OUT1R_ENA */
+
+/*
+ * R1025 (0x401) - DAC Volume Limit 1L
+ */
+#define WM2200_OUT1_OSR                         0x2000  /* OUT1_OSR */
+#define WM2200_OUT1_OSR_MASK                    0x2000  /* OUT1_OSR */
+#define WM2200_OUT1_OSR_SHIFT                       13  /* OUT1_OSR */
+#define WM2200_OUT1_OSR_WIDTH                        1  /* OUT1_OSR */
+#define WM2200_OUT1L_ANC_SRC                    0x0800  /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_ANC_SRC_MASK               0x0800  /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_ANC_SRC_SHIFT                  11  /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_ANC_SRC_WIDTH                   1  /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_PGA_VOL_MASK               0x00FE  /* OUT1L_PGA_VOL - [7:1] */
+#define WM2200_OUT1L_PGA_VOL_SHIFT                   1  /* OUT1L_PGA_VOL - [7:1] */
+#define WM2200_OUT1L_PGA_VOL_WIDTH                   7  /* OUT1L_PGA_VOL - [7:1] */
+
+/*
+ * R1026 (0x402) - DAC Volume Limit 1R
+ */
+#define WM2200_OUT1R_ANC_SRC                    0x0800  /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_ANC_SRC_MASK               0x0800  /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_ANC_SRC_SHIFT                  11  /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_ANC_SRC_WIDTH                   1  /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_PGA_VOL_MASK               0x00FE  /* OUT1R_PGA_VOL - [7:1] */
+#define WM2200_OUT1R_PGA_VOL_SHIFT                   1  /* OUT1R_PGA_VOL - [7:1] */
+#define WM2200_OUT1R_PGA_VOL_WIDTH                   7  /* OUT1R_PGA_VOL - [7:1] */
+
+/*
+ * R1027 (0x403) - DAC Volume Limit 2L
+ */
+#define WM2200_OUT2_OSR                         0x2000  /* OUT2_OSR */
+#define WM2200_OUT2_OSR_MASK                    0x2000  /* OUT2_OSR */
+#define WM2200_OUT2_OSR_SHIFT                       13  /* OUT2_OSR */
+#define WM2200_OUT2_OSR_WIDTH                        1  /* OUT2_OSR */
+#define WM2200_OUT2L_ANC_SRC                    0x0800  /* OUT2L_ANC_SRC */
+#define WM2200_OUT2L_ANC_SRC_MASK               0x0800  /* OUT2L_ANC_SRC */
+#define WM2200_OUT2L_ANC_SRC_SHIFT                  11  /* OUT2L_ANC_SRC */
+#define WM2200_OUT2L_ANC_SRC_WIDTH                   1  /* OUT2L_ANC_SRC */
+
+/*
+ * R1028 (0x404) - DAC Volume Limit 2R
+ */
+#define WM2200_OUT2R_ANC_SRC                    0x0800  /* OUT2R_ANC_SRC */
+#define WM2200_OUT2R_ANC_SRC_MASK               0x0800  /* OUT2R_ANC_SRC */
+#define WM2200_OUT2R_ANC_SRC_SHIFT                  11  /* OUT2R_ANC_SRC */
+#define WM2200_OUT2R_ANC_SRC_WIDTH                   1  /* OUT2R_ANC_SRC */
+
+/*
+ * R1033 (0x409) - DAC AEC Control 1
+ */
+#define WM2200_AEC_LOOPBACK_ENA                 0x0004  /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_ENA_MASK            0x0004  /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_ENA_SHIFT                2  /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_ENA_WIDTH                1  /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_SRC_MASK            0x0003  /* AEC_LOOPBACK_SRC - [1:0] */
+#define WM2200_AEC_LOOPBACK_SRC_SHIFT                0  /* AEC_LOOPBACK_SRC - [1:0] */
+#define WM2200_AEC_LOOPBACK_SRC_WIDTH                2  /* AEC_LOOPBACK_SRC - [1:0] */
+
+/*
+ * R1034 (0x40A) - Output Volume Ramp
+ */
+#define WM2200_OUT_VD_RAMP_MASK                 0x0070  /* OUT_VD_RAMP - [6:4] */
+#define WM2200_OUT_VD_RAMP_SHIFT                     4  /* OUT_VD_RAMP - [6:4] */
+#define WM2200_OUT_VD_RAMP_WIDTH                     3  /* OUT_VD_RAMP - [6:4] */
+#define WM2200_OUT_VI_RAMP_MASK                 0x0007  /* OUT_VI_RAMP - [2:0] */
+#define WM2200_OUT_VI_RAMP_SHIFT                     0  /* OUT_VI_RAMP - [2:0] */
+#define WM2200_OUT_VI_RAMP_WIDTH                     3  /* OUT_VI_RAMP - [2:0] */
+
+/*
+ * R1035 (0x40B) - DAC Digital Volume 1L
+ */
+#define WM2200_OUT_VU                           0x0200  /* OUT_VU */
+#define WM2200_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM2200_OUT1L_MUTE                       0x0100  /* OUT1L_MUTE */
+#define WM2200_OUT1L_MUTE_MASK                  0x0100  /* OUT1L_MUTE */
+#define WM2200_OUT1L_MUTE_SHIFT                      8  /* OUT1L_MUTE */
+#define WM2200_OUT1L_MUTE_WIDTH                      1  /* OUT1L_MUTE */
+#define WM2200_OUT1L_VOL_MASK                   0x00FF  /* OUT1L_VOL - [7:0] */
+#define WM2200_OUT1L_VOL_SHIFT                       0  /* OUT1L_VOL - [7:0] */
+#define WM2200_OUT1L_VOL_WIDTH                       8  /* OUT1L_VOL - [7:0] */
+
+/*
+ * R1036 (0x40C) - DAC Digital Volume 1R
+ */
+#define WM2200_OUT_VU                           0x0200  /* OUT_VU */
+#define WM2200_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM2200_OUT1R_MUTE                       0x0100  /* OUT1R_MUTE */
+#define WM2200_OUT1R_MUTE_MASK                  0x0100  /* OUT1R_MUTE */
+#define WM2200_OUT1R_MUTE_SHIFT                      8  /* OUT1R_MUTE */
+#define WM2200_OUT1R_MUTE_WIDTH                      1  /* OUT1R_MUTE */
+#define WM2200_OUT1R_VOL_MASK                   0x00FF  /* OUT1R_VOL - [7:0] */
+#define WM2200_OUT1R_VOL_SHIFT                       0  /* OUT1R_VOL - [7:0] */
+#define WM2200_OUT1R_VOL_WIDTH                       8  /* OUT1R_VOL - [7:0] */
+
+/*
+ * R1037 (0x40D) - DAC Digital Volume 2L
+ */
+#define WM2200_OUT_VU                           0x0200  /* OUT_VU */
+#define WM2200_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM2200_OUT2L_MUTE                       0x0100  /* OUT2L_MUTE */
+#define WM2200_OUT2L_MUTE_MASK                  0x0100  /* OUT2L_MUTE */
+#define WM2200_OUT2L_MUTE_SHIFT                      8  /* OUT2L_MUTE */
+#define WM2200_OUT2L_MUTE_WIDTH                      1  /* OUT2L_MUTE */
+#define WM2200_OUT2L_VOL_MASK                   0x00FF  /* OUT2L_VOL - [7:0] */
+#define WM2200_OUT2L_VOL_SHIFT                       0  /* OUT2L_VOL - [7:0] */
+#define WM2200_OUT2L_VOL_WIDTH                       8  /* OUT2L_VOL - [7:0] */
+
+/*
+ * R1038 (0x40E) - DAC Digital Volume 2R
+ */
+#define WM2200_OUT_VU                           0x0200  /* OUT_VU */
+#define WM2200_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM2200_OUT2R_MUTE                       0x0100  /* OUT2R_MUTE */
+#define WM2200_OUT2R_MUTE_MASK                  0x0100  /* OUT2R_MUTE */
+#define WM2200_OUT2R_MUTE_SHIFT                      8  /* OUT2R_MUTE */
+#define WM2200_OUT2R_MUTE_WIDTH                      1  /* OUT2R_MUTE */
+#define WM2200_OUT2R_VOL_MASK                   0x00FF  /* OUT2R_VOL - [7:0] */
+#define WM2200_OUT2R_VOL_SHIFT                       0  /* OUT2R_VOL - [7:0] */
+#define WM2200_OUT2R_VOL_WIDTH                       8  /* OUT2R_VOL - [7:0] */
+
+/*
+ * R1047 (0x417) - PDM 1
+ */
+#define WM2200_SPK1R_MUTE                       0x2000  /* SPK1R_MUTE */
+#define WM2200_SPK1R_MUTE_MASK                  0x2000  /* SPK1R_MUTE */
+#define WM2200_SPK1R_MUTE_SHIFT                     13  /* SPK1R_MUTE */
+#define WM2200_SPK1R_MUTE_WIDTH                      1  /* SPK1R_MUTE */
+#define WM2200_SPK1L_MUTE                       0x1000  /* SPK1L_MUTE */
+#define WM2200_SPK1L_MUTE_MASK                  0x1000  /* SPK1L_MUTE */
+#define WM2200_SPK1L_MUTE_SHIFT                     12  /* SPK1L_MUTE */
+#define WM2200_SPK1L_MUTE_WIDTH                      1  /* SPK1L_MUTE */
+#define WM2200_SPK1_MUTE_ENDIAN                 0x0100  /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_ENDIAN_MASK            0x0100  /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_ENDIAN_SHIFT                8  /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_ENDIAN_WIDTH                1  /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_SEQL_MASK              0x00FF  /* SPK1_MUTE_SEQL - [7:0] */
+#define WM2200_SPK1_MUTE_SEQL_SHIFT                  0  /* SPK1_MUTE_SEQL - [7:0] */
+#define WM2200_SPK1_MUTE_SEQL_WIDTH                  8  /* SPK1_MUTE_SEQL - [7:0] */
+
+/*
+ * R1048 (0x418) - PDM 2
+ */
+#define WM2200_SPK1_FMT                         0x0001  /* SPK1_FMT */
+#define WM2200_SPK1_FMT_MASK                    0x0001  /* SPK1_FMT */
+#define WM2200_SPK1_FMT_SHIFT                        0  /* SPK1_FMT */
+#define WM2200_SPK1_FMT_WIDTH                        1  /* SPK1_FMT */
+
+/*
+ * R1280 (0x500) - Audio IF 1_1
+ */
+#define WM2200_AIF1_BCLK_INV                    0x0040  /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_INV_MASK               0x0040  /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_INV_SHIFT                   6  /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_INV_WIDTH                   1  /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_FRC                    0x0020  /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_FRC_MASK               0x0020  /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_FRC_SHIFT                   5  /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_FRC_WIDTH                   1  /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_MSTR                   0x0010  /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_MSTR_MASK              0x0010  /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_MSTR_SHIFT                  4  /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_MSTR_WIDTH                  1  /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_DIV_MASK               0x000F  /* AIF1_BCLK_DIV - [3:0] */
+#define WM2200_AIF1_BCLK_DIV_SHIFT                   0  /* AIF1_BCLK_DIV - [3:0] */
+#define WM2200_AIF1_BCLK_DIV_WIDTH                   4  /* AIF1_BCLK_DIV - [3:0] */
+
+/*
+ * R1281 (0x501) - Audio IF 1_2
+ */
+#define WM2200_AIF1TX_DAT_TRI                   0x0020  /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_DAT_TRI_MASK              0x0020  /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_DAT_TRI_SHIFT                  5  /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_DAT_TRI_WIDTH                  1  /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_LRCLK_SRC                 0x0008  /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_SRC_MASK            0x0008  /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_SRC_SHIFT                3  /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_SRC_WIDTH                1  /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_INV                 0x0004  /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_INV_MASK            0x0004  /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_INV_SHIFT                2  /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_INV_WIDTH                1  /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_FRC                 0x0002  /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_FRC_MASK            0x0002  /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_FRC_SHIFT                1  /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_FRC_WIDTH                1  /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_MSTR                0x0001  /* AIF1TX_LRCLK_MSTR */
+#define WM2200_AIF1TX_LRCLK_MSTR_MASK           0x0001  /* AIF1TX_LRCLK_MSTR */
+#define WM2200_AIF1TX_LRCLK_MSTR_SHIFT               0  /* AIF1TX_LRCLK_MSTR */
+#define WM2200_AIF1TX_LRCLK_MSTR_WIDTH               1  /* AIF1TX_LRCLK_MSTR */
+
+/*
+ * R1282 (0x502) - Audio IF 1_3
+ */
+#define WM2200_AIF1RX_LRCLK_INV                 0x0004  /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_INV_MASK            0x0004  /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_INV_SHIFT                2  /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_INV_WIDTH                1  /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_FRC                 0x0002  /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_FRC_MASK            0x0002  /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_FRC_SHIFT                1  /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_FRC_WIDTH                1  /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_MSTR                0x0001  /* AIF1RX_LRCLK_MSTR */
+#define WM2200_AIF1RX_LRCLK_MSTR_MASK           0x0001  /* AIF1RX_LRCLK_MSTR */
+#define WM2200_AIF1RX_LRCLK_MSTR_SHIFT               0  /* AIF1RX_LRCLK_MSTR */
+#define WM2200_AIF1RX_LRCLK_MSTR_WIDTH               1  /* AIF1RX_LRCLK_MSTR */
+
+/*
+ * R1283 (0x503) - Audio IF 1_4
+ */
+#define WM2200_AIF1_TRI                         0x0040  /* AIF1_TRI */
+#define WM2200_AIF1_TRI_MASK                    0x0040  /* AIF1_TRI */
+#define WM2200_AIF1_TRI_SHIFT                        6  /* AIF1_TRI */
+#define WM2200_AIF1_TRI_WIDTH                        1  /* AIF1_TRI */
+
+/*
+ * R1284 (0x504) - Audio IF 1_5
+ */
+#define WM2200_AIF1_FMT_MASK                    0x0007  /* AIF1_FMT - [2:0] */
+#define WM2200_AIF1_FMT_SHIFT                        0  /* AIF1_FMT - [2:0] */
+#define WM2200_AIF1_FMT_WIDTH                        3  /* AIF1_FMT - [2:0] */
+
+/*
+ * R1285 (0x505) - Audio IF 1_6
+ */
+#define WM2200_AIF1TX_BCPF_MASK                 0x07FF  /* AIF1TX_BCPF - [10:0] */
+#define WM2200_AIF1TX_BCPF_SHIFT                     0  /* AIF1TX_BCPF - [10:0] */
+#define WM2200_AIF1TX_BCPF_WIDTH                    11  /* AIF1TX_BCPF - [10:0] */
+
+/*
+ * R1286 (0x506) - Audio IF 1_7
+ */
+#define WM2200_AIF1RX_BCPF_MASK                 0x07FF  /* AIF1RX_BCPF - [10:0] */
+#define WM2200_AIF1RX_BCPF_SHIFT                     0  /* AIF1RX_BCPF - [10:0] */
+#define WM2200_AIF1RX_BCPF_WIDTH                    11  /* AIF1RX_BCPF - [10:0] */
+
+/*
+ * R1287 (0x507) - Audio IF 1_8
+ */
+#define WM2200_AIF1TX_WL_MASK                   0x3F00  /* AIF1TX_WL - [13:8] */
+#define WM2200_AIF1TX_WL_SHIFT                       8  /* AIF1TX_WL - [13:8] */
+#define WM2200_AIF1TX_WL_WIDTH                       6  /* AIF1TX_WL - [13:8] */
+#define WM2200_AIF1TX_SLOT_LEN_MASK             0x00FF  /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1TX_SLOT_LEN_SHIFT                 0  /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1TX_SLOT_LEN_WIDTH                 8  /* AIF1TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1288 (0x508) - Audio IF 1_9
+ */
+#define WM2200_AIF1RX_WL_MASK                   0x3F00  /* AIF1RX_WL - [13:8] */
+#define WM2200_AIF1RX_WL_SHIFT                       8  /* AIF1RX_WL - [13:8] */
+#define WM2200_AIF1RX_WL_WIDTH                       6  /* AIF1RX_WL - [13:8] */
+#define WM2200_AIF1RX_SLOT_LEN_MASK             0x00FF  /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1RX_SLOT_LEN_SHIFT                 0  /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1RX_SLOT_LEN_WIDTH                 8  /* AIF1RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1289 (0x509) - Audio IF 1_10
+ */
+#define WM2200_AIF1TX1_SLOT_MASK                0x003F  /* AIF1TX1_SLOT - [5:0] */
+#define WM2200_AIF1TX1_SLOT_SHIFT                    0  /* AIF1TX1_SLOT - [5:0] */
+#define WM2200_AIF1TX1_SLOT_WIDTH                    6  /* AIF1TX1_SLOT - [5:0] */
+
+/*
+ * R1290 (0x50A) - Audio IF 1_11
+ */
+#define WM2200_AIF1TX2_SLOT_MASK                0x003F  /* AIF1TX2_SLOT - [5:0] */
+#define WM2200_AIF1TX2_SLOT_SHIFT                    0  /* AIF1TX2_SLOT - [5:0] */
+#define WM2200_AIF1TX2_SLOT_WIDTH                    6  /* AIF1TX2_SLOT - [5:0] */
+
+/*
+ * R1291 (0x50B) - Audio IF 1_12
+ */
+#define WM2200_AIF1TX3_SLOT_MASK                0x003F  /* AIF1TX3_SLOT - [5:0] */
+#define WM2200_AIF1TX3_SLOT_SHIFT                    0  /* AIF1TX3_SLOT - [5:0] */
+#define WM2200_AIF1TX3_SLOT_WIDTH                    6  /* AIF1TX3_SLOT - [5:0] */
+
+/*
+ * R1292 (0x50C) - Audio IF 1_13
+ */
+#define WM2200_AIF1TX4_SLOT_MASK                0x003F  /* AIF1TX4_SLOT - [5:0] */
+#define WM2200_AIF1TX4_SLOT_SHIFT                    0  /* AIF1TX4_SLOT - [5:0] */
+#define WM2200_AIF1TX4_SLOT_WIDTH                    6  /* AIF1TX4_SLOT - [5:0] */
+
+/*
+ * R1293 (0x50D) - Audio IF 1_14
+ */
+#define WM2200_AIF1TX5_SLOT_MASK                0x003F  /* AIF1TX5_SLOT - [5:0] */
+#define WM2200_AIF1TX5_SLOT_SHIFT                    0  /* AIF1TX5_SLOT - [5:0] */
+#define WM2200_AIF1TX5_SLOT_WIDTH                    6  /* AIF1TX5_SLOT - [5:0] */
+
+/*
+ * R1294 (0x50E) - Audio IF 1_15
+ */
+#define WM2200_AIF1TX6_SLOT_MASK                0x003F  /* AIF1TX6_SLOT - [5:0] */
+#define WM2200_AIF1TX6_SLOT_SHIFT                    0  /* AIF1TX6_SLOT - [5:0] */
+#define WM2200_AIF1TX6_SLOT_WIDTH                    6  /* AIF1TX6_SLOT - [5:0] */
+
+/*
+ * R1295 (0x50F) - Audio IF 1_16
+ */
+#define WM2200_AIF1RX1_SLOT_MASK                0x003F  /* AIF1RX1_SLOT - [5:0] */
+#define WM2200_AIF1RX1_SLOT_SHIFT                    0  /* AIF1RX1_SLOT - [5:0] */
+#define WM2200_AIF1RX1_SLOT_WIDTH                    6  /* AIF1RX1_SLOT - [5:0] */
+
+/*
+ * R1296 (0x510) - Audio IF 1_17
+ */
+#define WM2200_AIF1RX2_SLOT_MASK                0x003F  /* AIF1RX2_SLOT - [5:0] */
+#define WM2200_AIF1RX2_SLOT_SHIFT                    0  /* AIF1RX2_SLOT - [5:0] */
+#define WM2200_AIF1RX2_SLOT_WIDTH                    6  /* AIF1RX2_SLOT - [5:0] */
+
+/*
+ * R1297 (0x511) - Audio IF 1_18
+ */
+#define WM2200_AIF1RX3_SLOT_MASK                0x003F  /* AIF1RX3_SLOT - [5:0] */
+#define WM2200_AIF1RX3_SLOT_SHIFT                    0  /* AIF1RX3_SLOT - [5:0] */
+#define WM2200_AIF1RX3_SLOT_WIDTH                    6  /* AIF1RX3_SLOT - [5:0] */
+
+/*
+ * R1298 (0x512) - Audio IF 1_19
+ */
+#define WM2200_AIF1RX4_SLOT_MASK                0x003F  /* AIF1RX4_SLOT - [5:0] */
+#define WM2200_AIF1RX4_SLOT_SHIFT                    0  /* AIF1RX4_SLOT - [5:0] */
+#define WM2200_AIF1RX4_SLOT_WIDTH                    6  /* AIF1RX4_SLOT - [5:0] */
+
+/*
+ * R1299 (0x513) - Audio IF 1_20
+ */
+#define WM2200_AIF1RX5_SLOT_MASK                0x003F  /* AIF1RX5_SLOT - [5:0] */
+#define WM2200_AIF1RX5_SLOT_SHIFT                    0  /* AIF1RX5_SLOT - [5:0] */
+#define WM2200_AIF1RX5_SLOT_WIDTH                    6  /* AIF1RX5_SLOT - [5:0] */
+
+/*
+ * R1300 (0x514) - Audio IF 1_21
+ */
+#define WM2200_AIF1RX6_SLOT_MASK                0x003F  /* AIF1RX6_SLOT - [5:0] */
+#define WM2200_AIF1RX6_SLOT_SHIFT                    0  /* AIF1RX6_SLOT - [5:0] */
+#define WM2200_AIF1RX6_SLOT_WIDTH                    6  /* AIF1RX6_SLOT - [5:0] */
+
+/*
+ * R1301 (0x515) - Audio IF 1_22
+ */
+#define WM2200_AIF1RX6_ENA                      0x0800  /* AIF1RX6_ENA */
+#define WM2200_AIF1RX6_ENA_MASK                 0x0800  /* AIF1RX6_ENA */
+#define WM2200_AIF1RX6_ENA_SHIFT                    11  /* AIF1RX6_ENA */
+#define WM2200_AIF1RX6_ENA_WIDTH                     1  /* AIF1RX6_ENA */
+#define WM2200_AIF1RX5_ENA                      0x0400  /* AIF1RX5_ENA */
+#define WM2200_AIF1RX5_ENA_MASK                 0x0400  /* AIF1RX5_ENA */
+#define WM2200_AIF1RX5_ENA_SHIFT                    10  /* AIF1RX5_ENA */
+#define WM2200_AIF1RX5_ENA_WIDTH                     1  /* AIF1RX5_ENA */
+#define WM2200_AIF1RX4_ENA                      0x0200  /* AIF1RX4_ENA */
+#define WM2200_AIF1RX4_ENA_MASK                 0x0200  /* AIF1RX4_ENA */
+#define WM2200_AIF1RX4_ENA_SHIFT                     9  /* AIF1RX4_ENA */
+#define WM2200_AIF1RX4_ENA_WIDTH                     1  /* AIF1RX4_ENA */
+#define WM2200_AIF1RX3_ENA                      0x0100  /* AIF1RX3_ENA */
+#define WM2200_AIF1RX3_ENA_MASK                 0x0100  /* AIF1RX3_ENA */
+#define WM2200_AIF1RX3_ENA_SHIFT                     8  /* AIF1RX3_ENA */
+#define WM2200_AIF1RX3_ENA_WIDTH                     1  /* AIF1RX3_ENA */
+#define WM2200_AIF1RX2_ENA                      0x0080  /* AIF1RX2_ENA */
+#define WM2200_AIF1RX2_ENA_MASK                 0x0080  /* AIF1RX2_ENA */
+#define WM2200_AIF1RX2_ENA_SHIFT                     7  /* AIF1RX2_ENA */
+#define WM2200_AIF1RX2_ENA_WIDTH                     1  /* AIF1RX2_ENA */
+#define WM2200_AIF1RX1_ENA                      0x0040  /* AIF1RX1_ENA */
+#define WM2200_AIF1RX1_ENA_MASK                 0x0040  /* AIF1RX1_ENA */
+#define WM2200_AIF1RX1_ENA_SHIFT                     6  /* AIF1RX1_ENA */
+#define WM2200_AIF1RX1_ENA_WIDTH                     1  /* AIF1RX1_ENA */
+#define WM2200_AIF1TX6_ENA                      0x0020  /* AIF1TX6_ENA */
+#define WM2200_AIF1TX6_ENA_MASK                 0x0020  /* AIF1TX6_ENA */
+#define WM2200_AIF1TX6_ENA_SHIFT                     5  /* AIF1TX6_ENA */
+#define WM2200_AIF1TX6_ENA_WIDTH                     1  /* AIF1TX6_ENA */
+#define WM2200_AIF1TX5_ENA                      0x0010  /* AIF1TX5_ENA */
+#define WM2200_AIF1TX5_ENA_MASK                 0x0010  /* AIF1TX5_ENA */
+#define WM2200_AIF1TX5_ENA_SHIFT                     4  /* AIF1TX5_ENA */
+#define WM2200_AIF1TX5_ENA_WIDTH                     1  /* AIF1TX5_ENA */
+#define WM2200_AIF1TX4_ENA                      0x0008  /* AIF1TX4_ENA */
+#define WM2200_AIF1TX4_ENA_MASK                 0x0008  /* AIF1TX4_ENA */
+#define WM2200_AIF1TX4_ENA_SHIFT                     3  /* AIF1TX4_ENA */
+#define WM2200_AIF1TX4_ENA_WIDTH                     1  /* AIF1TX4_ENA */
+#define WM2200_AIF1TX3_ENA                      0x0004  /* AIF1TX3_ENA */
+#define WM2200_AIF1TX3_ENA_MASK                 0x0004  /* AIF1TX3_ENA */
+#define WM2200_AIF1TX3_ENA_SHIFT                     2  /* AIF1TX3_ENA */
+#define WM2200_AIF1TX3_ENA_WIDTH                     1  /* AIF1TX3_ENA */
+#define WM2200_AIF1TX2_ENA                      0x0002  /* AIF1TX2_ENA */
+#define WM2200_AIF1TX2_ENA_MASK                 0x0002  /* AIF1TX2_ENA */
+#define WM2200_AIF1TX2_ENA_SHIFT                     1  /* AIF1TX2_ENA */
+#define WM2200_AIF1TX2_ENA_WIDTH                     1  /* AIF1TX2_ENA */
+#define WM2200_AIF1TX1_ENA                      0x0001  /* AIF1TX1_ENA */
+#define WM2200_AIF1TX1_ENA_MASK                 0x0001  /* AIF1TX1_ENA */
+#define WM2200_AIF1TX1_ENA_SHIFT                     0  /* AIF1TX1_ENA */
+#define WM2200_AIF1TX1_ENA_WIDTH                     1  /* AIF1TX1_ENA */
+
+/*
+ * R1536 (0x600) - OUT1LMIX Input 1 Source
+ */
+#define WM2200_OUT1LMIX_SRC1_MASK               0x007F  /* OUT1LMIX_SRC1 - [6:0] */
+#define WM2200_OUT1LMIX_SRC1_SHIFT                   0  /* OUT1LMIX_SRC1 - [6:0] */
+#define WM2200_OUT1LMIX_SRC1_WIDTH                   7  /* OUT1LMIX_SRC1 - [6:0] */
+
+/*
+ * R1537 (0x601) - OUT1LMIX Input 1 Volume
+ */
+#define WM2200_OUT1LMIX_VOL1_MASK               0x00FE  /* OUT1LMIX_VOL1 - [7:1] */
+#define WM2200_OUT1LMIX_VOL1_SHIFT                   1  /* OUT1LMIX_VOL1 - [7:1] */
+#define WM2200_OUT1LMIX_VOL1_WIDTH                   7  /* OUT1LMIX_VOL1 - [7:1] */
+
+/*
+ * R1538 (0x602) - OUT1LMIX Input 2 Source
+ */
+#define WM2200_OUT1LMIX_SRC2_MASK               0x007F  /* OUT1LMIX_SRC2 - [6:0] */
+#define WM2200_OUT1LMIX_SRC2_SHIFT                   0  /* OUT1LMIX_SRC2 - [6:0] */
+#define WM2200_OUT1LMIX_SRC2_WIDTH                   7  /* OUT1LMIX_SRC2 - [6:0] */
+
+/*
+ * R1539 (0x603) - OUT1LMIX Input 2 Volume
+ */
+#define WM2200_OUT1LMIX_VOL2_MASK               0x00FE  /* OUT1LMIX_VOL2 - [7:1] */
+#define WM2200_OUT1LMIX_VOL2_SHIFT                   1  /* OUT1LMIX_VOL2 - [7:1] */
+#define WM2200_OUT1LMIX_VOL2_WIDTH                   7  /* OUT1LMIX_VOL2 - [7:1] */
+
+/*
+ * R1540 (0x604) - OUT1LMIX Input 3 Source
+ */
+#define WM2200_OUT1LMIX_SRC3_MASK               0x007F  /* OUT1LMIX_SRC3 - [6:0] */
+#define WM2200_OUT1LMIX_SRC3_SHIFT                   0  /* OUT1LMIX_SRC3 - [6:0] */
+#define WM2200_OUT1LMIX_SRC3_WIDTH                   7  /* OUT1LMIX_SRC3 - [6:0] */
+
+/*
+ * R1541 (0x605) - OUT1LMIX Input 3 Volume
+ */
+#define WM2200_OUT1LMIX_VOL3_MASK               0x00FE  /* OUT1LMIX_VOL3 - [7:1] */
+#define WM2200_OUT1LMIX_VOL3_SHIFT                   1  /* OUT1LMIX_VOL3 - [7:1] */
+#define WM2200_OUT1LMIX_VOL3_WIDTH                   7  /* OUT1LMIX_VOL3 - [7:1] */
+
+/*
+ * R1542 (0x606) - OUT1LMIX Input 4 Source
+ */
+#define WM2200_OUT1LMIX_SRC4_MASK               0x007F  /* OUT1LMIX_SRC4 - [6:0] */
+#define WM2200_OUT1LMIX_SRC4_SHIFT                   0  /* OUT1LMIX_SRC4 - [6:0] */
+#define WM2200_OUT1LMIX_SRC4_WIDTH                   7  /* OUT1LMIX_SRC4 - [6:0] */
+
+/*
+ * R1543 (0x607) - OUT1LMIX Input 4 Volume
+ */
+#define WM2200_OUT1LMIX_VOL4_MASK               0x00FE  /* OUT1LMIX_VOL4 - [7:1] */
+#define WM2200_OUT1LMIX_VOL4_SHIFT                   1  /* OUT1LMIX_VOL4 - [7:1] */
+#define WM2200_OUT1LMIX_VOL4_WIDTH                   7  /* OUT1LMIX_VOL4 - [7:1] */
+
+/*
+ * R1544 (0x608) - OUT1RMIX Input 1 Source
+ */
+#define WM2200_OUT1RMIX_SRC1_MASK               0x007F  /* OUT1RMIX_SRC1 - [6:0] */
+#define WM2200_OUT1RMIX_SRC1_SHIFT                   0  /* OUT1RMIX_SRC1 - [6:0] */
+#define WM2200_OUT1RMIX_SRC1_WIDTH                   7  /* OUT1RMIX_SRC1 - [6:0] */
+
+/*
+ * R1545 (0x609) - OUT1RMIX Input 1 Volume
+ */
+#define WM2200_OUT1RMIX_VOL1_MASK               0x00FE  /* OUT1RMIX_VOL1 - [7:1] */
+#define WM2200_OUT1RMIX_VOL1_SHIFT                   1  /* OUT1RMIX_VOL1 - [7:1] */
+#define WM2200_OUT1RMIX_VOL1_WIDTH                   7  /* OUT1RMIX_VOL1 - [7:1] */
+
+/*
+ * R1546 (0x60A) - OUT1RMIX Input 2 Source
+ */
+#define WM2200_OUT1RMIX_SRC2_MASK               0x007F  /* OUT1RMIX_SRC2 - [6:0] */
+#define WM2200_OUT1RMIX_SRC2_SHIFT                   0  /* OUT1RMIX_SRC2 - [6:0] */
+#define WM2200_OUT1RMIX_SRC2_WIDTH                   7  /* OUT1RMIX_SRC2 - [6:0] */
+
+/*
+ * R1547 (0x60B) - OUT1RMIX Input 2 Volume
+ */
+#define WM2200_OUT1RMIX_VOL2_MASK               0x00FE  /* OUT1RMIX_VOL2 - [7:1] */
+#define WM2200_OUT1RMIX_VOL2_SHIFT                   1  /* OUT1RMIX_VOL2 - [7:1] */
+#define WM2200_OUT1RMIX_VOL2_WIDTH                   7  /* OUT1RMIX_VOL2 - [7:1] */
+
+/*
+ * R1548 (0x60C) - OUT1RMIX Input 3 Source
+ */
+#define WM2200_OUT1RMIX_SRC3_MASK               0x007F  /* OUT1RMIX_SRC3 - [6:0] */
+#define WM2200_OUT1RMIX_SRC3_SHIFT                   0  /* OUT1RMIX_SRC3 - [6:0] */
+#define WM2200_OUT1RMIX_SRC3_WIDTH                   7  /* OUT1RMIX_SRC3 - [6:0] */
+
+/*
+ * R1549 (0x60D) - OUT1RMIX Input 3 Volume
+ */
+#define WM2200_OUT1RMIX_VOL3_MASK               0x00FE  /* OUT1RMIX_VOL3 - [7:1] */
+#define WM2200_OUT1RMIX_VOL3_SHIFT                   1  /* OUT1RMIX_VOL3 - [7:1] */
+#define WM2200_OUT1RMIX_VOL3_WIDTH                   7  /* OUT1RMIX_VOL3 - [7:1] */
+
+/*
+ * R1550 (0x60E) - OUT1RMIX Input 4 Source
+ */
+#define WM2200_OUT1RMIX_SRC4_MASK               0x007F  /* OUT1RMIX_SRC4 - [6:0] */
+#define WM2200_OUT1RMIX_SRC4_SHIFT                   0  /* OUT1RMIX_SRC4 - [6:0] */
+#define WM2200_OUT1RMIX_SRC4_WIDTH                   7  /* OUT1RMIX_SRC4 - [6:0] */
+
+/*
+ * R1551 (0x60F) - OUT1RMIX Input 4 Volume
+ */
+#define WM2200_OUT1RMIX_VOL4_MASK               0x00FE  /* OUT1RMIX_VOL4 - [7:1] */
+#define WM2200_OUT1RMIX_VOL4_SHIFT                   1  /* OUT1RMIX_VOL4 - [7:1] */
+#define WM2200_OUT1RMIX_VOL4_WIDTH                   7  /* OUT1RMIX_VOL4 - [7:1] */
+
+/*
+ * R1552 (0x610) - OUT2LMIX Input 1 Source
+ */
+#define WM2200_OUT2LMIX_SRC1_MASK               0x007F  /* OUT2LMIX_SRC1 - [6:0] */
+#define WM2200_OUT2LMIX_SRC1_SHIFT                   0  /* OUT2LMIX_SRC1 - [6:0] */
+#define WM2200_OUT2LMIX_SRC1_WIDTH                   7  /* OUT2LMIX_SRC1 - [6:0] */
+
+/*
+ * R1553 (0x611) - OUT2LMIX Input 1 Volume
+ */
+#define WM2200_OUT2LMIX_VOL1_MASK               0x00FE  /* OUT2LMIX_VOL1 - [7:1] */
+#define WM2200_OUT2LMIX_VOL1_SHIFT                   1  /* OUT2LMIX_VOL1 - [7:1] */
+#define WM2200_OUT2LMIX_VOL1_WIDTH                   7  /* OUT2LMIX_VOL1 - [7:1] */
+
+/*
+ * R1554 (0x612) - OUT2LMIX Input 2 Source
+ */
+#define WM2200_OUT2LMIX_SRC2_MASK               0x007F  /* OUT2LMIX_SRC2 - [6:0] */
+#define WM2200_OUT2LMIX_SRC2_SHIFT                   0  /* OUT2LMIX_SRC2 - [6:0] */
+#define WM2200_OUT2LMIX_SRC2_WIDTH                   7  /* OUT2LMIX_SRC2 - [6:0] */
+
+/*
+ * R1555 (0x613) - OUT2LMIX Input 2 Volume
+ */
+#define WM2200_OUT2LMIX_VOL2_MASK               0x00FE  /* OUT2LMIX_VOL2 - [7:1] */
+#define WM2200_OUT2LMIX_VOL2_SHIFT                   1  /* OUT2LMIX_VOL2 - [7:1] */
+#define WM2200_OUT2LMIX_VOL2_WIDTH                   7  /* OUT2LMIX_VOL2 - [7:1] */
+
+/*
+ * R1556 (0x614) - OUT2LMIX Input 3 Source
+ */
+#define WM2200_OUT2LMIX_SRC3_MASK               0x007F  /* OUT2LMIX_SRC3 - [6:0] */
+#define WM2200_OUT2LMIX_SRC3_SHIFT                   0  /* OUT2LMIX_SRC3 - [6:0] */
+#define WM2200_OUT2LMIX_SRC3_WIDTH                   7  /* OUT2LMIX_SRC3 - [6:0] */
+
+/*
+ * R1557 (0x615) - OUT2LMIX Input 3 Volume
+ */
+#define WM2200_OUT2LMIX_VOL3_MASK               0x00FE  /* OUT2LMIX_VOL3 - [7:1] */
+#define WM2200_OUT2LMIX_VOL3_SHIFT                   1  /* OUT2LMIX_VOL3 - [7:1] */
+#define WM2200_OUT2LMIX_VOL3_WIDTH                   7  /* OUT2LMIX_VOL3 - [7:1] */
+
+/*
+ * R1558 (0x616) - OUT2LMIX Input 4 Source
+ */
+#define WM2200_OUT2LMIX_SRC4_MASK               0x007F  /* OUT2LMIX_SRC4 - [6:0] */
+#define WM2200_OUT2LMIX_SRC4_SHIFT                   0  /* OUT2LMIX_SRC4 - [6:0] */
+#define WM2200_OUT2LMIX_SRC4_WIDTH                   7  /* OUT2LMIX_SRC4 - [6:0] */
+
+/*
+ * R1559 (0x617) - OUT2LMIX Input 4 Volume
+ */
+#define WM2200_OUT2LMIX_VOL4_MASK               0x00FE  /* OUT2LMIX_VOL4 - [7:1] */
+#define WM2200_OUT2LMIX_VOL4_SHIFT                   1  /* OUT2LMIX_VOL4 - [7:1] */
+#define WM2200_OUT2LMIX_VOL4_WIDTH                   7  /* OUT2LMIX_VOL4 - [7:1] */
+
+/*
+ * R1560 (0x618) - OUT2RMIX Input 1 Source
+ */
+#define WM2200_OUT2RMIX_SRC1_MASK               0x007F  /* OUT2RMIX_SRC1 - [6:0] */
+#define WM2200_OUT2RMIX_SRC1_SHIFT                   0  /* OUT2RMIX_SRC1 - [6:0] */
+#define WM2200_OUT2RMIX_SRC1_WIDTH                   7  /* OUT2RMIX_SRC1 - [6:0] */
+
+/*
+ * R1561 (0x619) - OUT2RMIX Input 1 Volume
+ */
+#define WM2200_OUT2RMIX_VOL1_MASK               0x00FE  /* OUT2RMIX_VOL1 - [7:1] */
+#define WM2200_OUT2RMIX_VOL1_SHIFT                   1  /* OUT2RMIX_VOL1 - [7:1] */
+#define WM2200_OUT2RMIX_VOL1_WIDTH                   7  /* OUT2RMIX_VOL1 - [7:1] */
+
+/*
+ * R1562 (0x61A) - OUT2RMIX Input 2 Source
+ */
+#define WM2200_OUT2RMIX_SRC2_MASK               0x007F  /* OUT2RMIX_SRC2 - [6:0] */
+#define WM2200_OUT2RMIX_SRC2_SHIFT                   0  /* OUT2RMIX_SRC2 - [6:0] */
+#define WM2200_OUT2RMIX_SRC2_WIDTH                   7  /* OUT2RMIX_SRC2 - [6:0] */
+
+/*
+ * R1563 (0x61B) - OUT2RMIX Input 2 Volume
+ */
+#define WM2200_OUT2RMIX_VOL2_MASK               0x00FE  /* OUT2RMIX_VOL2 - [7:1] */
+#define WM2200_OUT2RMIX_VOL2_SHIFT                   1  /* OUT2RMIX_VOL2 - [7:1] */
+#define WM2200_OUT2RMIX_VOL2_WIDTH                   7  /* OUT2RMIX_VOL2 - [7:1] */
+
+/*
+ * R1564 (0x61C) - OUT2RMIX Input 3 Source
+ */
+#define WM2200_OUT2RMIX_SRC3_MASK               0x007F  /* OUT2RMIX_SRC3 - [6:0] */
+#define WM2200_OUT2RMIX_SRC3_SHIFT                   0  /* OUT2RMIX_SRC3 - [6:0] */
+#define WM2200_OUT2RMIX_SRC3_WIDTH                   7  /* OUT2RMIX_SRC3 - [6:0] */
+
+/*
+ * R1565 (0x61D) - OUT2RMIX Input 3 Volume
+ */
+#define WM2200_OUT2RMIX_VOL3_MASK               0x00FE  /* OUT2RMIX_VOL3 - [7:1] */
+#define WM2200_OUT2RMIX_VOL3_SHIFT                   1  /* OUT2RMIX_VOL3 - [7:1] */
+#define WM2200_OUT2RMIX_VOL3_WIDTH                   7  /* OUT2RMIX_VOL3 - [7:1] */
+
+/*
+ * R1566 (0x61E) - OUT2RMIX Input 4 Source
+ */
+#define WM2200_OUT2RMIX_SRC4_MASK               0x007F  /* OUT2RMIX_SRC4 - [6:0] */
+#define WM2200_OUT2RMIX_SRC4_SHIFT                   0  /* OUT2RMIX_SRC4 - [6:0] */
+#define WM2200_OUT2RMIX_SRC4_WIDTH                   7  /* OUT2RMIX_SRC4 - [6:0] */
+
+/*
+ * R1567 (0x61F) - OUT2RMIX Input 4 Volume
+ */
+#define WM2200_OUT2RMIX_VOL4_MASK               0x00FE  /* OUT2RMIX_VOL4 - [7:1] */
+#define WM2200_OUT2RMIX_VOL4_SHIFT                   1  /* OUT2RMIX_VOL4 - [7:1] */
+#define WM2200_OUT2RMIX_VOL4_WIDTH                   7  /* OUT2RMIX_VOL4 - [7:1] */
+
+/*
+ * R1568 (0x620) - AIF1TX1MIX Input 1 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC1_MASK             0x007F  /* AIF1TX1MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC1_SHIFT                 0  /* AIF1TX1MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC1_WIDTH                 7  /* AIF1TX1MIX_SRC1 - [6:0] */
+
+/*
+ * R1569 (0x621) - AIF1TX1MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL1_MASK             0x00FE  /* AIF1TX1MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL1_SHIFT                 1  /* AIF1TX1MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL1_WIDTH                 7  /* AIF1TX1MIX_VOL1 - [7:1] */
+
+/*
+ * R1570 (0x622) - AIF1TX1MIX Input 2 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC2_MASK             0x007F  /* AIF1TX1MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC2_SHIFT                 0  /* AIF1TX1MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC2_WIDTH                 7  /* AIF1TX1MIX_SRC2 - [6:0] */
+
+/*
+ * R1571 (0x623) - AIF1TX1MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL2_MASK             0x00FE  /* AIF1TX1MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL2_SHIFT                 1  /* AIF1TX1MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL2_WIDTH                 7  /* AIF1TX1MIX_VOL2 - [7:1] */
+
+/*
+ * R1572 (0x624) - AIF1TX1MIX Input 3 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC3_MASK             0x007F  /* AIF1TX1MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC3_SHIFT                 0  /* AIF1TX1MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC3_WIDTH                 7  /* AIF1TX1MIX_SRC3 - [6:0] */
+
+/*
+ * R1573 (0x625) - AIF1TX1MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL3_MASK             0x00FE  /* AIF1TX1MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL3_SHIFT                 1  /* AIF1TX1MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL3_WIDTH                 7  /* AIF1TX1MIX_VOL3 - [7:1] */
+
+/*
+ * R1574 (0x626) - AIF1TX1MIX Input 4 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC4_MASK             0x007F  /* AIF1TX1MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC4_SHIFT                 0  /* AIF1TX1MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC4_WIDTH                 7  /* AIF1TX1MIX_SRC4 - [6:0] */
+
+/*
+ * R1575 (0x627) - AIF1TX1MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL4_MASK             0x00FE  /* AIF1TX1MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL4_SHIFT                 1  /* AIF1TX1MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL4_WIDTH                 7  /* AIF1TX1MIX_VOL4 - [7:1] */
+
+/*
+ * R1576 (0x628) - AIF1TX2MIX Input 1 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC1_MASK             0x007F  /* AIF1TX2MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC1_SHIFT                 0  /* AIF1TX2MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC1_WIDTH                 7  /* AIF1TX2MIX_SRC1 - [6:0] */
+
+/*
+ * R1577 (0x629) - AIF1TX2MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL1_MASK             0x00FE  /* AIF1TX2MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL1_SHIFT                 1  /* AIF1TX2MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL1_WIDTH                 7  /* AIF1TX2MIX_VOL1 - [7:1] */
+
+/*
+ * R1578 (0x62A) - AIF1TX2MIX Input 2 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC2_MASK             0x007F  /* AIF1TX2MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC2_SHIFT                 0  /* AIF1TX2MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC2_WIDTH                 7  /* AIF1TX2MIX_SRC2 - [6:0] */
+
+/*
+ * R1579 (0x62B) - AIF1TX2MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL2_MASK             0x00FE  /* AIF1TX2MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL2_SHIFT                 1  /* AIF1TX2MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL2_WIDTH                 7  /* AIF1TX2MIX_VOL2 - [7:1] */
+
+/*
+ * R1580 (0x62C) - AIF1TX2MIX Input 3 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC3_MASK             0x007F  /* AIF1TX2MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC3_SHIFT                 0  /* AIF1TX2MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC3_WIDTH                 7  /* AIF1TX2MIX_SRC3 - [6:0] */
+
+/*
+ * R1581 (0x62D) - AIF1TX2MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL3_MASK             0x00FE  /* AIF1TX2MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL3_SHIFT                 1  /* AIF1TX2MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL3_WIDTH                 7  /* AIF1TX2MIX_VOL3 - [7:1] */
+
+/*
+ * R1582 (0x62E) - AIF1TX2MIX Input 4 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC4_MASK             0x007F  /* AIF1TX2MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC4_SHIFT                 0  /* AIF1TX2MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC4_WIDTH                 7  /* AIF1TX2MIX_SRC4 - [6:0] */
+
+/*
+ * R1583 (0x62F) - AIF1TX2MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL4_MASK             0x00FE  /* AIF1TX2MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL4_SHIFT                 1  /* AIF1TX2MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL4_WIDTH                 7  /* AIF1TX2MIX_VOL4 - [7:1] */
+
+/*
+ * R1584 (0x630) - AIF1TX3MIX Input 1 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC1_MASK             0x007F  /* AIF1TX3MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC1_SHIFT                 0  /* AIF1TX3MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC1_WIDTH                 7  /* AIF1TX3MIX_SRC1 - [6:0] */
+
+/*
+ * R1585 (0x631) - AIF1TX3MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL1_MASK             0x00FE  /* AIF1TX3MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL1_SHIFT                 1  /* AIF1TX3MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL1_WIDTH                 7  /* AIF1TX3MIX_VOL1 - [7:1] */
+
+/*
+ * R1586 (0x632) - AIF1TX3MIX Input 2 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC2_MASK             0x007F  /* AIF1TX3MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC2_SHIFT                 0  /* AIF1TX3MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC2_WIDTH                 7  /* AIF1TX3MIX_SRC2 - [6:0] */
+
+/*
+ * R1587 (0x633) - AIF1TX3MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL2_MASK             0x00FE  /* AIF1TX3MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL2_SHIFT                 1  /* AIF1TX3MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL2_WIDTH                 7  /* AIF1TX3MIX_VOL2 - [7:1] */
+
+/*
+ * R1588 (0x634) - AIF1TX3MIX Input 3 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC3_MASK             0x007F  /* AIF1TX3MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC3_SHIFT                 0  /* AIF1TX3MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC3_WIDTH                 7  /* AIF1TX3MIX_SRC3 - [6:0] */
+
+/*
+ * R1589 (0x635) - AIF1TX3MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL3_MASK             0x00FE  /* AIF1TX3MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL3_SHIFT                 1  /* AIF1TX3MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL3_WIDTH                 7  /* AIF1TX3MIX_VOL3 - [7:1] */
+
+/*
+ * R1590 (0x636) - AIF1TX3MIX Input 4 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC4_MASK             0x007F  /* AIF1TX3MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC4_SHIFT                 0  /* AIF1TX3MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC4_WIDTH                 7  /* AIF1TX3MIX_SRC4 - [6:0] */
+
+/*
+ * R1591 (0x637) - AIF1TX3MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL4_MASK             0x00FE  /* AIF1TX3MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL4_SHIFT                 1  /* AIF1TX3MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL4_WIDTH                 7  /* AIF1TX3MIX_VOL4 - [7:1] */
+
+/*
+ * R1592 (0x638) - AIF1TX4MIX Input 1 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC1_MASK             0x007F  /* AIF1TX4MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC1_SHIFT                 0  /* AIF1TX4MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC1_WIDTH                 7  /* AIF1TX4MIX_SRC1 - [6:0] */
+
+/*
+ * R1593 (0x639) - AIF1TX4MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL1_MASK             0x00FE  /* AIF1TX4MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL1_SHIFT                 1  /* AIF1TX4MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL1_WIDTH                 7  /* AIF1TX4MIX_VOL1 - [7:1] */
+
+/*
+ * R1594 (0x63A) - AIF1TX4MIX Input 2 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC2_MASK             0x007F  /* AIF1TX4MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC2_SHIFT                 0  /* AIF1TX4MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC2_WIDTH                 7  /* AIF1TX4MIX_SRC2 - [6:0] */
+
+/*
+ * R1595 (0x63B) - AIF1TX4MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL2_MASK             0x00FE  /* AIF1TX4MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL2_SHIFT                 1  /* AIF1TX4MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL2_WIDTH                 7  /* AIF1TX4MIX_VOL2 - [7:1] */
+
+/*
+ * R1596 (0x63C) - AIF1TX4MIX Input 3 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC3_MASK             0x007F  /* AIF1TX4MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC3_SHIFT                 0  /* AIF1TX4MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC3_WIDTH                 7  /* AIF1TX4MIX_SRC3 - [6:0] */
+
+/*
+ * R1597 (0x63D) - AIF1TX4MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL3_MASK             0x00FE  /* AIF1TX4MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL3_SHIFT                 1  /* AIF1TX4MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL3_WIDTH                 7  /* AIF1TX4MIX_VOL3 - [7:1] */
+
+/*
+ * R1598 (0x63E) - AIF1TX4MIX Input 4 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC4_MASK             0x007F  /* AIF1TX4MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC4_SHIFT                 0  /* AIF1TX4MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC4_WIDTH                 7  /* AIF1TX4MIX_SRC4 - [6:0] */
+
+/*
+ * R1599 (0x63F) - AIF1TX4MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL4_MASK             0x00FE  /* AIF1TX4MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL4_SHIFT                 1  /* AIF1TX4MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL4_WIDTH                 7  /* AIF1TX4MIX_VOL4 - [7:1] */
+
+/*
+ * R1600 (0x640) - AIF1TX5MIX Input 1 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC1_MASK             0x007F  /* AIF1TX5MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC1_SHIFT                 0  /* AIF1TX5MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC1_WIDTH                 7  /* AIF1TX5MIX_SRC1 - [6:0] */
+
+/*
+ * R1601 (0x641) - AIF1TX5MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL1_MASK             0x00FE  /* AIF1TX5MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL1_SHIFT                 1  /* AIF1TX5MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL1_WIDTH                 7  /* AIF1TX5MIX_VOL1 - [7:1] */
+
+/*
+ * R1602 (0x642) - AIF1TX5MIX Input 2 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC2_MASK             0x007F  /* AIF1TX5MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC2_SHIFT                 0  /* AIF1TX5MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC2_WIDTH                 7  /* AIF1TX5MIX_SRC2 - [6:0] */
+
+/*
+ * R1603 (0x643) - AIF1TX5MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL2_MASK             0x00FE  /* AIF1TX5MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL2_SHIFT                 1  /* AIF1TX5MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL2_WIDTH                 7  /* AIF1TX5MIX_VOL2 - [7:1] */
+
+/*
+ * R1604 (0x644) - AIF1TX5MIX Input 3 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC3_MASK             0x007F  /* AIF1TX5MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC3_SHIFT                 0  /* AIF1TX5MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC3_WIDTH                 7  /* AIF1TX5MIX_SRC3 - [6:0] */
+
+/*
+ * R1605 (0x645) - AIF1TX5MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL3_MASK             0x00FE  /* AIF1TX5MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL3_SHIFT                 1  /* AIF1TX5MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL3_WIDTH                 7  /* AIF1TX5MIX_VOL3 - [7:1] */
+
+/*
+ * R1606 (0x646) - AIF1TX5MIX Input 4 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC4_MASK             0x007F  /* AIF1TX5MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC4_SHIFT                 0  /* AIF1TX5MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC4_WIDTH                 7  /* AIF1TX5MIX_SRC4 - [6:0] */
+
+/*
+ * R1607 (0x647) - AIF1TX5MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL4_MASK             0x00FE  /* AIF1TX5MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL4_SHIFT                 1  /* AIF1TX5MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL4_WIDTH                 7  /* AIF1TX5MIX_VOL4 - [7:1] */
+
+/*
+ * R1608 (0x648) - AIF1TX6MIX Input 1 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC1_MASK             0x007F  /* AIF1TX6MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC1_SHIFT                 0  /* AIF1TX6MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC1_WIDTH                 7  /* AIF1TX6MIX_SRC1 - [6:0] */
+
+/*
+ * R1609 (0x649) - AIF1TX6MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL1_MASK             0x00FE  /* AIF1TX6MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL1_SHIFT                 1  /* AIF1TX6MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL1_WIDTH                 7  /* AIF1TX6MIX_VOL1 - [7:1] */
+
+/*
+ * R1610 (0x64A) - AIF1TX6MIX Input 2 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC2_MASK             0x007F  /* AIF1TX6MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC2_SHIFT                 0  /* AIF1TX6MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC2_WIDTH                 7  /* AIF1TX6MIX_SRC2 - [6:0] */
+
+/*
+ * R1611 (0x64B) - AIF1TX6MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL2_MASK             0x00FE  /* AIF1TX6MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL2_SHIFT                 1  /* AIF1TX6MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL2_WIDTH                 7  /* AIF1TX6MIX_VOL2 - [7:1] */
+
+/*
+ * R1612 (0x64C) - AIF1TX6MIX Input 3 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC3_MASK             0x007F  /* AIF1TX6MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC3_SHIFT                 0  /* AIF1TX6MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC3_WIDTH                 7  /* AIF1TX6MIX_SRC3 - [6:0] */
+
+/*
+ * R1613 (0x64D) - AIF1TX6MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL3_MASK             0x00FE  /* AIF1TX6MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL3_SHIFT                 1  /* AIF1TX6MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL3_WIDTH                 7  /* AIF1TX6MIX_VOL3 - [7:1] */
+
+/*
+ * R1614 (0x64E) - AIF1TX6MIX Input 4 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC4_MASK             0x007F  /* AIF1TX6MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC4_SHIFT                 0  /* AIF1TX6MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC4_WIDTH                 7  /* AIF1TX6MIX_SRC4 - [6:0] */
+
+/*
+ * R1615 (0x64F) - AIF1TX6MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL4_MASK             0x00FE  /* AIF1TX6MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL4_SHIFT                 1  /* AIF1TX6MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL4_WIDTH                 7  /* AIF1TX6MIX_VOL4 - [7:1] */
+
+/*
+ * R1616 (0x650) - EQLMIX Input 1 Source
+ */
+#define WM2200_EQLMIX_SRC1_MASK                 0x007F  /* EQLMIX_SRC1 - [6:0] */
+#define WM2200_EQLMIX_SRC1_SHIFT                     0  /* EQLMIX_SRC1 - [6:0] */
+#define WM2200_EQLMIX_SRC1_WIDTH                     7  /* EQLMIX_SRC1 - [6:0] */
+
+/*
+ * R1617 (0x651) - EQLMIX Input 1 Volume
+ */
+#define WM2200_EQLMIX_VOL1_MASK                 0x00FE  /* EQLMIX_VOL1 - [7:1] */
+#define WM2200_EQLMIX_VOL1_SHIFT                     1  /* EQLMIX_VOL1 - [7:1] */
+#define WM2200_EQLMIX_VOL1_WIDTH                     7  /* EQLMIX_VOL1 - [7:1] */
+
+/*
+ * R1618 (0x652) - EQLMIX Input 2 Source
+ */
+#define WM2200_EQLMIX_SRC2_MASK                 0x007F  /* EQLMIX_SRC2 - [6:0] */
+#define WM2200_EQLMIX_SRC2_SHIFT                     0  /* EQLMIX_SRC2 - [6:0] */
+#define WM2200_EQLMIX_SRC2_WIDTH                     7  /* EQLMIX_SRC2 - [6:0] */
+
+/*
+ * R1619 (0x653) - EQLMIX Input 2 Volume
+ */
+#define WM2200_EQLMIX_VOL2_MASK                 0x00FE  /* EQLMIX_VOL2 - [7:1] */
+#define WM2200_EQLMIX_VOL2_SHIFT                     1  /* EQLMIX_VOL2 - [7:1] */
+#define WM2200_EQLMIX_VOL2_WIDTH                     7  /* EQLMIX_VOL2 - [7:1] */
+
+/*
+ * R1620 (0x654) - EQLMIX Input 3 Source
+ */
+#define WM2200_EQLMIX_SRC3_MASK                 0x007F  /* EQLMIX_SRC3 - [6:0] */
+#define WM2200_EQLMIX_SRC3_SHIFT                     0  /* EQLMIX_SRC3 - [6:0] */
+#define WM2200_EQLMIX_SRC3_WIDTH                     7  /* EQLMIX_SRC3 - [6:0] */
+
+/*
+ * R1621 (0x655) - EQLMIX Input 3 Volume
+ */
+#define WM2200_EQLMIX_VOL3_MASK                 0x00FE  /* EQLMIX_VOL3 - [7:1] */
+#define WM2200_EQLMIX_VOL3_SHIFT                     1  /* EQLMIX_VOL3 - [7:1] */
+#define WM2200_EQLMIX_VOL3_WIDTH                     7  /* EQLMIX_VOL3 - [7:1] */
+
+/*
+ * R1622 (0x656) - EQLMIX Input 4 Source
+ */
+#define WM2200_EQLMIX_SRC4_MASK                 0x007F  /* EQLMIX_SRC4 - [6:0] */
+#define WM2200_EQLMIX_SRC4_SHIFT                     0  /* EQLMIX_SRC4 - [6:0] */
+#define WM2200_EQLMIX_SRC4_WIDTH                     7  /* EQLMIX_SRC4 - [6:0] */
+
+/*
+ * R1623 (0x657) - EQLMIX Input 4 Volume
+ */
+#define WM2200_EQLMIX_VOL4_MASK                 0x00FE  /* EQLMIX_VOL4 - [7:1] */
+#define WM2200_EQLMIX_VOL4_SHIFT                     1  /* EQLMIX_VOL4 - [7:1] */
+#define WM2200_EQLMIX_VOL4_WIDTH                     7  /* EQLMIX_VOL4 - [7:1] */
+
+/*
+ * R1624 (0x658) - EQRMIX Input 1 Source
+ */
+#define WM2200_EQRMIX_SRC1_MASK                 0x007F  /* EQRMIX_SRC1 - [6:0] */
+#define WM2200_EQRMIX_SRC1_SHIFT                     0  /* EQRMIX_SRC1 - [6:0] */
+#define WM2200_EQRMIX_SRC1_WIDTH                     7  /* EQRMIX_SRC1 - [6:0] */
+
+/*
+ * R1625 (0x659) - EQRMIX Input 1 Volume
+ */
+#define WM2200_EQRMIX_VOL1_MASK                 0x00FE  /* EQRMIX_VOL1 - [7:1] */
+#define WM2200_EQRMIX_VOL1_SHIFT                     1  /* EQRMIX_VOL1 - [7:1] */
+#define WM2200_EQRMIX_VOL1_WIDTH                     7  /* EQRMIX_VOL1 - [7:1] */
+
+/*
+ * R1626 (0x65A) - EQRMIX Input 2 Source
+ */
+#define WM2200_EQRMIX_SRC2_MASK                 0x007F  /* EQRMIX_SRC2 - [6:0] */
+#define WM2200_EQRMIX_SRC2_SHIFT                     0  /* EQRMIX_SRC2 - [6:0] */
+#define WM2200_EQRMIX_SRC2_WIDTH                     7  /* EQRMIX_SRC2 - [6:0] */
+
+/*
+ * R1627 (0x65B) - EQRMIX Input 2 Volume
+ */
+#define WM2200_EQRMIX_VOL2_MASK                 0x00FE  /* EQRMIX_VOL2 - [7:1] */
+#define WM2200_EQRMIX_VOL2_SHIFT                     1  /* EQRMIX_VOL2 - [7:1] */
+#define WM2200_EQRMIX_VOL2_WIDTH                     7  /* EQRMIX_VOL2 - [7:1] */
+
+/*
+ * R1628 (0x65C) - EQRMIX Input 3 Source
+ */
+#define WM2200_EQRMIX_SRC3_MASK                 0x007F  /* EQRMIX_SRC3 - [6:0] */
+#define WM2200_EQRMIX_SRC3_SHIFT                     0  /* EQRMIX_SRC3 - [6:0] */
+#define WM2200_EQRMIX_SRC3_WIDTH                     7  /* EQRMIX_SRC3 - [6:0] */
+
+/*
+ * R1629 (0x65D) - EQRMIX Input 3 Volume
+ */
+#define WM2200_EQRMIX_VOL3_MASK                 0x00FE  /* EQRMIX_VOL3 - [7:1] */
+#define WM2200_EQRMIX_VOL3_SHIFT                     1  /* EQRMIX_VOL3 - [7:1] */
+#define WM2200_EQRMIX_VOL3_WIDTH                     7  /* EQRMIX_VOL3 - [7:1] */
+
+/*
+ * R1630 (0x65E) - EQRMIX Input 4 Source
+ */
+#define WM2200_EQRMIX_SRC4_MASK                 0x007F  /* EQRMIX_SRC4 - [6:0] */
+#define WM2200_EQRMIX_SRC4_SHIFT                     0  /* EQRMIX_SRC4 - [6:0] */
+#define WM2200_EQRMIX_SRC4_WIDTH                     7  /* EQRMIX_SRC4 - [6:0] */
+
+/*
+ * R1631 (0x65F) - EQRMIX Input 4 Volume
+ */
+#define WM2200_EQRMIX_VOL4_MASK                 0x00FE  /* EQRMIX_VOL4 - [7:1] */
+#define WM2200_EQRMIX_VOL4_SHIFT                     1  /* EQRMIX_VOL4 - [7:1] */
+#define WM2200_EQRMIX_VOL4_WIDTH                     7  /* EQRMIX_VOL4 - [7:1] */
+
+/*
+ * R1632 (0x660) - LHPF1MIX Input 1 Source
+ */
+#define WM2200_LHPF1MIX_SRC1_MASK               0x007F  /* LHPF1MIX_SRC1 - [6:0] */
+#define WM2200_LHPF1MIX_SRC1_SHIFT                   0  /* LHPF1MIX_SRC1 - [6:0] */
+#define WM2200_LHPF1MIX_SRC1_WIDTH                   7  /* LHPF1MIX_SRC1 - [6:0] */
+
+/*
+ * R1633 (0x661) - LHPF1MIX Input 1 Volume
+ */
+#define WM2200_LHPF1MIX_VOL1_MASK               0x00FE  /* LHPF1MIX_VOL1 - [7:1] */
+#define WM2200_LHPF1MIX_VOL1_SHIFT                   1  /* LHPF1MIX_VOL1 - [7:1] */
+#define WM2200_LHPF1MIX_VOL1_WIDTH                   7  /* LHPF1MIX_VOL1 - [7:1] */
+
+/*
+ * R1634 (0x662) - LHPF1MIX Input 2 Source
+ */
+#define WM2200_LHPF1MIX_SRC2_MASK               0x007F  /* LHPF1MIX_SRC2 - [6:0] */
+#define WM2200_LHPF1MIX_SRC2_SHIFT                   0  /* LHPF1MIX_SRC2 - [6:0] */
+#define WM2200_LHPF1MIX_SRC2_WIDTH                   7  /* LHPF1MIX_SRC2 - [6:0] */
+
+/*
+ * R1635 (0x663) - LHPF1MIX Input 2 Volume
+ */
+#define WM2200_LHPF1MIX_VOL2_MASK               0x00FE  /* LHPF1MIX_VOL2 - [7:1] */
+#define WM2200_LHPF1MIX_VOL2_SHIFT                   1  /* LHPF1MIX_VOL2 - [7:1] */
+#define WM2200_LHPF1MIX_VOL2_WIDTH                   7  /* LHPF1MIX_VOL2 - [7:1] */
+
+/*
+ * R1636 (0x664) - LHPF1MIX Input 3 Source
+ */
+#define WM2200_LHPF1MIX_SRC3_MASK               0x007F  /* LHPF1MIX_SRC3 - [6:0] */
+#define WM2200_LHPF1MIX_SRC3_SHIFT                   0  /* LHPF1MIX_SRC3 - [6:0] */
+#define WM2200_LHPF1MIX_SRC3_WIDTH                   7  /* LHPF1MIX_SRC3 - [6:0] */
+
+/*
+ * R1637 (0x665) - LHPF1MIX Input 3 Volume
+ */
+#define WM2200_LHPF1MIX_VOL3_MASK               0x00FE  /* LHPF1MIX_VOL3 - [7:1] */
+#define WM2200_LHPF1MIX_VOL3_SHIFT                   1  /* LHPF1MIX_VOL3 - [7:1] */
+#define WM2200_LHPF1MIX_VOL3_WIDTH                   7  /* LHPF1MIX_VOL3 - [7:1] */
+
+/*
+ * R1638 (0x666) - LHPF1MIX Input 4 Source
+ */
+#define WM2200_LHPF1MIX_SRC4_MASK               0x007F  /* LHPF1MIX_SRC4 - [6:0] */
+#define WM2200_LHPF1MIX_SRC4_SHIFT                   0  /* LHPF1MIX_SRC4 - [6:0] */
+#define WM2200_LHPF1MIX_SRC4_WIDTH                   7  /* LHPF1MIX_SRC4 - [6:0] */
+
+/*
+ * R1639 (0x667) - LHPF1MIX Input 4 Volume
+ */
+#define WM2200_LHPF1MIX_VOL4_MASK               0x00FE  /* LHPF1MIX_VOL4 - [7:1] */
+#define WM2200_LHPF1MIX_VOL4_SHIFT                   1  /* LHPF1MIX_VOL4 - [7:1] */
+#define WM2200_LHPF1MIX_VOL4_WIDTH                   7  /* LHPF1MIX_VOL4 - [7:1] */
+
+/*
+ * R1640 (0x668) - LHPF2MIX Input 1 Source
+ */
+#define WM2200_LHPF2MIX_SRC1_MASK               0x007F  /* LHPF2MIX_SRC1 - [6:0] */
+#define WM2200_LHPF2MIX_SRC1_SHIFT                   0  /* LHPF2MIX_SRC1 - [6:0] */
+#define WM2200_LHPF2MIX_SRC1_WIDTH                   7  /* LHPF2MIX_SRC1 - [6:0] */
+
+/*
+ * R1641 (0x669) - LHPF2MIX Input 1 Volume
+ */
+#define WM2200_LHPF2MIX_VOL1_MASK               0x00FE  /* LHPF2MIX_VOL1 - [7:1] */
+#define WM2200_LHPF2MIX_VOL1_SHIFT                   1  /* LHPF2MIX_VOL1 - [7:1] */
+#define WM2200_LHPF2MIX_VOL1_WIDTH                   7  /* LHPF2MIX_VOL1 - [7:1] */
+
+/*
+ * R1642 (0x66A) - LHPF2MIX Input 2 Source
+ */
+#define WM2200_LHPF2MIX_SRC2_MASK               0x007F  /* LHPF2MIX_SRC2 - [6:0] */
+#define WM2200_LHPF2MIX_SRC2_SHIFT                   0  /* LHPF2MIX_SRC2 - [6:0] */
+#define WM2200_LHPF2MIX_SRC2_WIDTH                   7  /* LHPF2MIX_SRC2 - [6:0] */
+
+/*
+ * R1643 (0x66B) - LHPF2MIX Input 2 Volume
+ */
+#define WM2200_LHPF2MIX_VOL2_MASK               0x00FE  /* LHPF2MIX_VOL2 - [7:1] */
+#define WM2200_LHPF2MIX_VOL2_SHIFT                   1  /* LHPF2MIX_VOL2 - [7:1] */
+#define WM2200_LHPF2MIX_VOL2_WIDTH                   7  /* LHPF2MIX_VOL2 - [7:1] */
+
+/*
+ * R1644 (0x66C) - LHPF2MIX Input 3 Source
+ */
+#define WM2200_LHPF2MIX_SRC3_MASK               0x007F  /* LHPF2MIX_SRC3 - [6:0] */
+#define WM2200_LHPF2MIX_SRC3_SHIFT                   0  /* LHPF2MIX_SRC3 - [6:0] */
+#define WM2200_LHPF2MIX_SRC3_WIDTH                   7  /* LHPF2MIX_SRC3 - [6:0] */
+
+/*
+ * R1645 (0x66D) - LHPF2MIX Input 3 Volume
+ */
+#define WM2200_LHPF2MIX_VOL3_MASK               0x00FE  /* LHPF2MIX_VOL3 - [7:1] */
+#define WM2200_LHPF2MIX_VOL3_SHIFT                   1  /* LHPF2MIX_VOL3 - [7:1] */
+#define WM2200_LHPF2MIX_VOL3_WIDTH                   7  /* LHPF2MIX_VOL3 - [7:1] */
+
+/*
+ * R1646 (0x66E) - LHPF2MIX Input 4 Source
+ */
+#define WM2200_LHPF2MIX_SRC4_MASK               0x007F  /* LHPF2MIX_SRC4 - [6:0] */
+#define WM2200_LHPF2MIX_SRC4_SHIFT                   0  /* LHPF2MIX_SRC4 - [6:0] */
+#define WM2200_LHPF2MIX_SRC4_WIDTH                   7  /* LHPF2MIX_SRC4 - [6:0] */
+
+/*
+ * R1647 (0x66F) - LHPF2MIX Input 4 Volume
+ */
+#define WM2200_LHPF2MIX_VOL4_MASK               0x00FE  /* LHPF2MIX_VOL4 - [7:1] */
+#define WM2200_LHPF2MIX_VOL4_SHIFT                   1  /* LHPF2MIX_VOL4 - [7:1] */
+#define WM2200_LHPF2MIX_VOL4_WIDTH                   7  /* LHPF2MIX_VOL4 - [7:1] */
+
+/*
+ * R1648 (0x670) - DSP1LMIX Input 1 Source
+ */
+#define WM2200_DSP1LMIX_SRC1_MASK               0x007F  /* DSP1LMIX_SRC1 - [6:0] */
+#define WM2200_DSP1LMIX_SRC1_SHIFT                   0  /* DSP1LMIX_SRC1 - [6:0] */
+#define WM2200_DSP1LMIX_SRC1_WIDTH                   7  /* DSP1LMIX_SRC1 - [6:0] */
+
+/*
+ * R1649 (0x671) - DSP1LMIX Input 1 Volume
+ */
+#define WM2200_DSP1LMIX_VOL1_MASK               0x00FE  /* DSP1LMIX_VOL1 - [7:1] */
+#define WM2200_DSP1LMIX_VOL1_SHIFT                   1  /* DSP1LMIX_VOL1 - [7:1] */
+#define WM2200_DSP1LMIX_VOL1_WIDTH                   7  /* DSP1LMIX_VOL1 - [7:1] */
+
+/*
+ * R1650 (0x672) - DSP1LMIX Input 2 Source
+ */
+#define WM2200_DSP1LMIX_SRC2_MASK               0x007F  /* DSP1LMIX_SRC2 - [6:0] */
+#define WM2200_DSP1LMIX_SRC2_SHIFT                   0  /* DSP1LMIX_SRC2 - [6:0] */
+#define WM2200_DSP1LMIX_SRC2_WIDTH                   7  /* DSP1LMIX_SRC2 - [6:0] */
+
+/*
+ * R1651 (0x673) - DSP1LMIX Input 2 Volume
+ */
+#define WM2200_DSP1LMIX_VOL2_MASK               0x00FE  /* DSP1LMIX_VOL2 - [7:1] */
+#define WM2200_DSP1LMIX_VOL2_SHIFT                   1  /* DSP1LMIX_VOL2 - [7:1] */
+#define WM2200_DSP1LMIX_VOL2_WIDTH                   7  /* DSP1LMIX_VOL2 - [7:1] */
+
+/*
+ * R1652 (0x674) - DSP1LMIX Input 3 Source
+ */
+#define WM2200_DSP1LMIX_SRC3_MASK               0x007F  /* DSP1LMIX_SRC3 - [6:0] */
+#define WM2200_DSP1LMIX_SRC3_SHIFT                   0  /* DSP1LMIX_SRC3 - [6:0] */
+#define WM2200_DSP1LMIX_SRC3_WIDTH                   7  /* DSP1LMIX_SRC3 - [6:0] */
+
+/*
+ * R1653 (0x675) - DSP1LMIX Input 3 Volume
+ */
+#define WM2200_DSP1LMIX_VOL3_MASK               0x00FE  /* DSP1LMIX_VOL3 - [7:1] */
+#define WM2200_DSP1LMIX_VOL3_SHIFT                   1  /* DSP1LMIX_VOL3 - [7:1] */
+#define WM2200_DSP1LMIX_VOL3_WIDTH                   7  /* DSP1LMIX_VOL3 - [7:1] */
+
+/*
+ * R1654 (0x676) - DSP1LMIX Input 4 Source
+ */
+#define WM2200_DSP1LMIX_SRC4_MASK               0x007F  /* DSP1LMIX_SRC4 - [6:0] */
+#define WM2200_DSP1LMIX_SRC4_SHIFT                   0  /* DSP1LMIX_SRC4 - [6:0] */
+#define WM2200_DSP1LMIX_SRC4_WIDTH                   7  /* DSP1LMIX_SRC4 - [6:0] */
+
+/*
+ * R1655 (0x677) - DSP1LMIX Input 4 Volume
+ */
+#define WM2200_DSP1LMIX_VOL4_MASK               0x00FE  /* DSP1LMIX_VOL4 - [7:1] */
+#define WM2200_DSP1LMIX_VOL4_SHIFT                   1  /* DSP1LMIX_VOL4 - [7:1] */
+#define WM2200_DSP1LMIX_VOL4_WIDTH                   7  /* DSP1LMIX_VOL4 - [7:1] */
+
+/*
+ * R1656 (0x678) - DSP1RMIX Input 1 Source
+ */
+#define WM2200_DSP1RMIX_SRC1_MASK               0x007F  /* DSP1RMIX_SRC1 - [6:0] */
+#define WM2200_DSP1RMIX_SRC1_SHIFT                   0  /* DSP1RMIX_SRC1 - [6:0] */
+#define WM2200_DSP1RMIX_SRC1_WIDTH                   7  /* DSP1RMIX_SRC1 - [6:0] */
+
+/*
+ * R1657 (0x679) - DSP1RMIX Input 1 Volume
+ */
+#define WM2200_DSP1RMIX_VOL1_MASK               0x00FE  /* DSP1RMIX_VOL1 - [7:1] */
+#define WM2200_DSP1RMIX_VOL1_SHIFT                   1  /* DSP1RMIX_VOL1 - [7:1] */
+#define WM2200_DSP1RMIX_VOL1_WIDTH                   7  /* DSP1RMIX_VOL1 - [7:1] */
+
+/*
+ * R1658 (0x67A) - DSP1RMIX Input 2 Source
+ */
+#define WM2200_DSP1RMIX_SRC2_MASK               0x007F  /* DSP1RMIX_SRC2 - [6:0] */
+#define WM2200_DSP1RMIX_SRC2_SHIFT                   0  /* DSP1RMIX_SRC2 - [6:0] */
+#define WM2200_DSP1RMIX_SRC2_WIDTH                   7  /* DSP1RMIX_SRC2 - [6:0] */
+
+/*
+ * R1659 (0x67B) - DSP1RMIX Input 2 Volume
+ */
+#define WM2200_DSP1RMIX_VOL2_MASK               0x00FE  /* DSP1RMIX_VOL2 - [7:1] */
+#define WM2200_DSP1RMIX_VOL2_SHIFT                   1  /* DSP1RMIX_VOL2 - [7:1] */
+#define WM2200_DSP1RMIX_VOL2_WIDTH                   7  /* DSP1RMIX_VOL2 - [7:1] */
+
+/*
+ * R1660 (0x67C) - DSP1RMIX Input 3 Source
+ */
+#define WM2200_DSP1RMIX_SRC3_MASK               0x007F  /* DSP1RMIX_SRC3 - [6:0] */
+#define WM2200_DSP1RMIX_SRC3_SHIFT                   0  /* DSP1RMIX_SRC3 - [6:0] */
+#define WM2200_DSP1RMIX_SRC3_WIDTH                   7  /* DSP1RMIX_SRC3 - [6:0] */
+
+/*
+ * R1661 (0x67D) - DSP1RMIX Input 3 Volume
+ */
+#define WM2200_DSP1RMIX_VOL3_MASK               0x00FE  /* DSP1RMIX_VOL3 - [7:1] */
+#define WM2200_DSP1RMIX_VOL3_SHIFT                   1  /* DSP1RMIX_VOL3 - [7:1] */
+#define WM2200_DSP1RMIX_VOL3_WIDTH                   7  /* DSP1RMIX_VOL3 - [7:1] */
+
+/*
+ * R1662 (0x67E) - DSP1RMIX Input 4 Source
+ */
+#define WM2200_DSP1RMIX_SRC4_MASK               0x007F  /* DSP1RMIX_SRC4 - [6:0] */
+#define WM2200_DSP1RMIX_SRC4_SHIFT                   0  /* DSP1RMIX_SRC4 - [6:0] */
+#define WM2200_DSP1RMIX_SRC4_WIDTH                   7  /* DSP1RMIX_SRC4 - [6:0] */
+
+/*
+ * R1663 (0x67F) - DSP1RMIX Input 4 Volume
+ */
+#define WM2200_DSP1RMIX_VOL4_MASK               0x00FE  /* DSP1RMIX_VOL4 - [7:1] */
+#define WM2200_DSP1RMIX_VOL4_SHIFT                   1  /* DSP1RMIX_VOL4 - [7:1] */
+#define WM2200_DSP1RMIX_VOL4_WIDTH                   7  /* DSP1RMIX_VOL4 - [7:1] */
+
+/*
+ * R1664 (0x680) - DSP1AUX1MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX1MIX_SRC1_MASK            0x007F  /* DSP1AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX1MIX_SRC1_SHIFT                0  /* DSP1AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX1MIX_SRC1_WIDTH                7  /* DSP1AUX1MIX_SRC1 - [6:0] */
+
+/*
+ * R1665 (0x681) - DSP1AUX2MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX2MIX_SRC1_MASK            0x007F  /* DSP1AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX2MIX_SRC1_SHIFT                0  /* DSP1AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX2MIX_SRC1_WIDTH                7  /* DSP1AUX2MIX_SRC1 - [6:0] */
+
+/*
+ * R1666 (0x682) - DSP1AUX3MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX3MIX_SRC1_MASK            0x007F  /* DSP1AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX3MIX_SRC1_SHIFT                0  /* DSP1AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX3MIX_SRC1_WIDTH                7  /* DSP1AUX3MIX_SRC1 - [6:0] */
+
+/*
+ * R1667 (0x683) - DSP1AUX4MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX4MIX_SRC1_MASK            0x007F  /* DSP1AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX4MIX_SRC1_SHIFT                0  /* DSP1AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX4MIX_SRC1_WIDTH                7  /* DSP1AUX4MIX_SRC1 - [6:0] */
+
+/*
+ * R1668 (0x684) - DSP1AUX5MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX5MIX_SRC1_MASK            0x007F  /* DSP1AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX5MIX_SRC1_SHIFT                0  /* DSP1AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX5MIX_SRC1_WIDTH                7  /* DSP1AUX5MIX_SRC1 - [6:0] */
+
+/*
+ * R1669 (0x685) - DSP1AUX6MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX6MIX_SRC1_MASK            0x007F  /* DSP1AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX6MIX_SRC1_SHIFT                0  /* DSP1AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX6MIX_SRC1_WIDTH                7  /* DSP1AUX6MIX_SRC1 - [6:0] */
+
+/*
+ * R1670 (0x686) - DSP2LMIX Input 1 Source
+ */
+#define WM2200_DSP2LMIX_SRC1_MASK               0x007F  /* DSP2LMIX_SRC1 - [6:0] */
+#define WM2200_DSP2LMIX_SRC1_SHIFT                   0  /* DSP2LMIX_SRC1 - [6:0] */
+#define WM2200_DSP2LMIX_SRC1_WIDTH                   7  /* DSP2LMIX_SRC1 - [6:0] */
+
+/*
+ * R1671 (0x687) - DSP2LMIX Input 1 Volume
+ */
+#define WM2200_DSP2LMIX_VOL1_MASK               0x00FE  /* DSP2LMIX_VOL1 - [7:1] */
+#define WM2200_DSP2LMIX_VOL1_SHIFT                   1  /* DSP2LMIX_VOL1 - [7:1] */
+#define WM2200_DSP2LMIX_VOL1_WIDTH                   7  /* DSP2LMIX_VOL1 - [7:1] */
+
+/*
+ * R1672 (0x688) - DSP2LMIX Input 2 Source
+ */
+#define WM2200_DSP2LMIX_SRC2_MASK               0x007F  /* DSP2LMIX_SRC2 - [6:0] */
+#define WM2200_DSP2LMIX_SRC2_SHIFT                   0  /* DSP2LMIX_SRC2 - [6:0] */
+#define WM2200_DSP2LMIX_SRC2_WIDTH                   7  /* DSP2LMIX_SRC2 - [6:0] */
+
+/*
+ * R1673 (0x689) - DSP2LMIX Input 2 Volume
+ */
+#define WM2200_DSP2LMIX_VOL2_MASK               0x00FE  /* DSP2LMIX_VOL2 - [7:1] */
+#define WM2200_DSP2LMIX_VOL2_SHIFT                   1  /* DSP2LMIX_VOL2 - [7:1] */
+#define WM2200_DSP2LMIX_VOL2_WIDTH                   7  /* DSP2LMIX_VOL2 - [7:1] */
+
+/*
+ * R1674 (0x68A) - DSP2LMIX Input 3 Source
+ */
+#define WM2200_DSP2LMIX_SRC3_MASK               0x007F  /* DSP2LMIX_SRC3 - [6:0] */
+#define WM2200_DSP2LMIX_SRC3_SHIFT                   0  /* DSP2LMIX_SRC3 - [6:0] */
+#define WM2200_DSP2LMIX_SRC3_WIDTH                   7  /* DSP2LMIX_SRC3 - [6:0] */
+
+/*
+ * R1675 (0x68B) - DSP2LMIX Input 3 Volume
+ */
+#define WM2200_DSP2LMIX_VOL3_MASK               0x00FE  /* DSP2LMIX_VOL3 - [7:1] */
+#define WM2200_DSP2LMIX_VOL3_SHIFT                   1  /* DSP2LMIX_VOL3 - [7:1] */
+#define WM2200_DSP2LMIX_VOL3_WIDTH                   7  /* DSP2LMIX_VOL3 - [7:1] */
+
+/*
+ * R1676 (0x68C) - DSP2LMIX Input 4 Source
+ */
+#define WM2200_DSP2LMIX_SRC4_MASK               0x007F  /* DSP2LMIX_SRC4 - [6:0] */
+#define WM2200_DSP2LMIX_SRC4_SHIFT                   0  /* DSP2LMIX_SRC4 - [6:0] */
+#define WM2200_DSP2LMIX_SRC4_WIDTH                   7  /* DSP2LMIX_SRC4 - [6:0] */
+
+/*
+ * R1677 (0x68D) - DSP2LMIX Input 4 Volume
+ */
+#define WM2200_DSP2LMIX_VOL4_MASK               0x00FE  /* DSP2LMIX_VOL4 - [7:1] */
+#define WM2200_DSP2LMIX_VOL4_SHIFT                   1  /* DSP2LMIX_VOL4 - [7:1] */
+#define WM2200_DSP2LMIX_VOL4_WIDTH                   7  /* DSP2LMIX_VOL4 - [7:1] */
+
+/*
+ * R1678 (0x68E) - DSP2RMIX Input 1 Source
+ */
+#define WM2200_DSP2RMIX_SRC1_MASK               0x007F  /* DSP2RMIX_SRC1 - [6:0] */
+#define WM2200_DSP2RMIX_SRC1_SHIFT                   0  /* DSP2RMIX_SRC1 - [6:0] */
+#define WM2200_DSP2RMIX_SRC1_WIDTH                   7  /* DSP2RMIX_SRC1 - [6:0] */
+
+/*
+ * R1679 (0x68F) - DSP2RMIX Input 1 Volume
+ */
+#define WM2200_DSP2RMIX_VOL1_MASK               0x00FE  /* DSP2RMIX_VOL1 - [7:1] */
+#define WM2200_DSP2RMIX_VOL1_SHIFT                   1  /* DSP2RMIX_VOL1 - [7:1] */
+#define WM2200_DSP2RMIX_VOL1_WIDTH                   7  /* DSP2RMIX_VOL1 - [7:1] */
+
+/*
+ * R1680 (0x690) - DSP2RMIX Input 2 Source
+ */
+#define WM2200_DSP2RMIX_SRC2_MASK               0x007F  /* DSP2RMIX_SRC2 - [6:0] */
+#define WM2200_DSP2RMIX_SRC2_SHIFT                   0  /* DSP2RMIX_SRC2 - [6:0] */
+#define WM2200_DSP2RMIX_SRC2_WIDTH                   7  /* DSP2RMIX_SRC2 - [6:0] */
+
+/*
+ * R1681 (0x691) - DSP2RMIX Input 2 Volume
+ */
+#define WM2200_DSP2RMIX_VOL2_MASK               0x00FE  /* DSP2RMIX_VOL2 - [7:1] */
+#define WM2200_DSP2RMIX_VOL2_SHIFT                   1  /* DSP2RMIX_VOL2 - [7:1] */
+#define WM2200_DSP2RMIX_VOL2_WIDTH                   7  /* DSP2RMIX_VOL2 - [7:1] */
+
+/*
+ * R1682 (0x692) - DSP2RMIX Input 3 Source
+ */
+#define WM2200_DSP2RMIX_SRC3_MASK               0x007F  /* DSP2RMIX_SRC3 - [6:0] */
+#define WM2200_DSP2RMIX_SRC3_SHIFT                   0  /* DSP2RMIX_SRC3 - [6:0] */
+#define WM2200_DSP2RMIX_SRC3_WIDTH                   7  /* DSP2RMIX_SRC3 - [6:0] */
+
+/*
+ * R1683 (0x693) - DSP2RMIX Input 3 Volume
+ */
+#define WM2200_DSP2RMIX_VOL3_MASK               0x00FE  /* DSP2RMIX_VOL3 - [7:1] */
+#define WM2200_DSP2RMIX_VOL3_SHIFT                   1  /* DSP2RMIX_VOL3 - [7:1] */
+#define WM2200_DSP2RMIX_VOL3_WIDTH                   7  /* DSP2RMIX_VOL3 - [7:1] */
+
+/*
+ * R1684 (0x694) - DSP2RMIX Input 4 Source
+ */
+#define WM2200_DSP2RMIX_SRC4_MASK               0x007F  /* DSP2RMIX_SRC4 - [6:0] */
+#define WM2200_DSP2RMIX_SRC4_SHIFT                   0  /* DSP2RMIX_SRC4 - [6:0] */
+#define WM2200_DSP2RMIX_SRC4_WIDTH                   7  /* DSP2RMIX_SRC4 - [6:0] */
+
+/*
+ * R1685 (0x695) - DSP2RMIX Input 4 Volume
+ */
+#define WM2200_DSP2RMIX_VOL4_MASK               0x00FE  /* DSP2RMIX_VOL4 - [7:1] */
+#define WM2200_DSP2RMIX_VOL4_SHIFT                   1  /* DSP2RMIX_VOL4 - [7:1] */
+#define WM2200_DSP2RMIX_VOL4_WIDTH                   7  /* DSP2RMIX_VOL4 - [7:1] */
+
+/*
+ * R1686 (0x696) - DSP2AUX1MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX1MIX_SRC1_MASK            0x007F  /* DSP2AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX1MIX_SRC1_SHIFT                0  /* DSP2AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX1MIX_SRC1_WIDTH                7  /* DSP2AUX1MIX_SRC1 - [6:0] */
+
+/*
+ * R1687 (0x697) - DSP2AUX2MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX2MIX_SRC1_MASK            0x007F  /* DSP2AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX2MIX_SRC1_SHIFT                0  /* DSP2AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX2MIX_SRC1_WIDTH                7  /* DSP2AUX2MIX_SRC1 - [6:0] */
+
+/*
+ * R1688 (0x698) - DSP2AUX3MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX3MIX_SRC1_MASK            0x007F  /* DSP2AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX3MIX_SRC1_SHIFT                0  /* DSP2AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX3MIX_SRC1_WIDTH                7  /* DSP2AUX3MIX_SRC1 - [6:0] */
+
+/*
+ * R1689 (0x699) - DSP2AUX4MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX4MIX_SRC1_MASK            0x007F  /* DSP2AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX4MIX_SRC1_SHIFT                0  /* DSP2AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX4MIX_SRC1_WIDTH                7  /* DSP2AUX4MIX_SRC1 - [6:0] */
+
+/*
+ * R1690 (0x69A) - DSP2AUX5MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX5MIX_SRC1_MASK            0x007F  /* DSP2AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX5MIX_SRC1_SHIFT                0  /* DSP2AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX5MIX_SRC1_WIDTH                7  /* DSP2AUX5MIX_SRC1 - [6:0] */
+
+/*
+ * R1691 (0x69B) - DSP2AUX6MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX6MIX_SRC1_MASK            0x007F  /* DSP2AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX6MIX_SRC1_SHIFT                0  /* DSP2AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX6MIX_SRC1_WIDTH                7  /* DSP2AUX6MIX_SRC1 - [6:0] */
+
+/*
+ * R1792 (0x700) - GPIO CTRL 1
+ */
+#define WM2200_GP1_DIR                          0x8000  /* GP1_DIR */
+#define WM2200_GP1_DIR_MASK                     0x8000  /* GP1_DIR */
+#define WM2200_GP1_DIR_SHIFT                        15  /* GP1_DIR */
+#define WM2200_GP1_DIR_WIDTH                         1  /* GP1_DIR */
+#define WM2200_GP1_PU                           0x4000  /* GP1_PU */
+#define WM2200_GP1_PU_MASK                      0x4000  /* GP1_PU */
+#define WM2200_GP1_PU_SHIFT                         14  /* GP1_PU */
+#define WM2200_GP1_PU_WIDTH                          1  /* GP1_PU */
+#define WM2200_GP1_PD                           0x2000  /* GP1_PD */
+#define WM2200_GP1_PD_MASK                      0x2000  /* GP1_PD */
+#define WM2200_GP1_PD_SHIFT                         13  /* GP1_PD */
+#define WM2200_GP1_PD_WIDTH                          1  /* GP1_PD */
+#define WM2200_GP1_POL                          0x0400  /* GP1_POL */
+#define WM2200_GP1_POL_MASK                     0x0400  /* GP1_POL */
+#define WM2200_GP1_POL_SHIFT                        10  /* GP1_POL */
+#define WM2200_GP1_POL_WIDTH                         1  /* GP1_POL */
+#define WM2200_GP1_OP_CFG                       0x0200  /* GP1_OP_CFG */
+#define WM2200_GP1_OP_CFG_MASK                  0x0200  /* GP1_OP_CFG */
+#define WM2200_GP1_OP_CFG_SHIFT                      9  /* GP1_OP_CFG */
+#define WM2200_GP1_OP_CFG_WIDTH                      1  /* GP1_OP_CFG */
+#define WM2200_GP1_DB                           0x0100  /* GP1_DB */
+#define WM2200_GP1_DB_MASK                      0x0100  /* GP1_DB */
+#define WM2200_GP1_DB_SHIFT                          8  /* GP1_DB */
+#define WM2200_GP1_DB_WIDTH                          1  /* GP1_DB */
+#define WM2200_GP1_LVL                          0x0040  /* GP1_LVL */
+#define WM2200_GP1_LVL_MASK                     0x0040  /* GP1_LVL */
+#define WM2200_GP1_LVL_SHIFT                         6  /* GP1_LVL */
+#define WM2200_GP1_LVL_WIDTH                         1  /* GP1_LVL */
+#define WM2200_GP1_FN_MASK                      0x003F  /* GP1_FN - [5:0] */
+#define WM2200_GP1_FN_SHIFT                          0  /* GP1_FN - [5:0] */
+#define WM2200_GP1_FN_WIDTH                          6  /* GP1_FN - [5:0] */
+
+/*
+ * R1793 (0x701) - GPIO CTRL 2
+ */
+#define WM2200_GP2_DIR                          0x8000  /* GP2_DIR */
+#define WM2200_GP2_DIR_MASK                     0x8000  /* GP2_DIR */
+#define WM2200_GP2_DIR_SHIFT                        15  /* GP2_DIR */
+#define WM2200_GP2_DIR_WIDTH                         1  /* GP2_DIR */
+#define WM2200_GP2_PU                           0x4000  /* GP2_PU */
+#define WM2200_GP2_PU_MASK                      0x4000  /* GP2_PU */
+#define WM2200_GP2_PU_SHIFT                         14  /* GP2_PU */
+#define WM2200_GP2_PU_WIDTH                          1  /* GP2_PU */
+#define WM2200_GP2_PD                           0x2000  /* GP2_PD */
+#define WM2200_GP2_PD_MASK                      0x2000  /* GP2_PD */
+#define WM2200_GP2_PD_SHIFT                         13  /* GP2_PD */
+#define WM2200_GP2_PD_WIDTH                          1  /* GP2_PD */
+#define WM2200_GP2_POL                          0x0400  /* GP2_POL */
+#define WM2200_GP2_POL_MASK                     0x0400  /* GP2_POL */
+#define WM2200_GP2_POL_SHIFT                        10  /* GP2_POL */
+#define WM2200_GP2_POL_WIDTH                         1  /* GP2_POL */
+#define WM2200_GP2_OP_CFG                       0x0200  /* GP2_OP_CFG */
+#define WM2200_GP2_OP_CFG_MASK                  0x0200  /* GP2_OP_CFG */
+#define WM2200_GP2_OP_CFG_SHIFT                      9  /* GP2_OP_CFG */
+#define WM2200_GP2_OP_CFG_WIDTH                      1  /* GP2_OP_CFG */
+#define WM2200_GP2_DB                           0x0100  /* GP2_DB */
+#define WM2200_GP2_DB_MASK                      0x0100  /* GP2_DB */
+#define WM2200_GP2_DB_SHIFT                          8  /* GP2_DB */
+#define WM2200_GP2_DB_WIDTH                          1  /* GP2_DB */
+#define WM2200_GP2_LVL                          0x0040  /* GP2_LVL */
+#define WM2200_GP2_LVL_MASK                     0x0040  /* GP2_LVL */
+#define WM2200_GP2_LVL_SHIFT                         6  /* GP2_LVL */
+#define WM2200_GP2_LVL_WIDTH                         1  /* GP2_LVL */
+#define WM2200_GP2_FN_MASK                      0x003F  /* GP2_FN - [5:0] */
+#define WM2200_GP2_FN_SHIFT                          0  /* GP2_FN - [5:0] */
+#define WM2200_GP2_FN_WIDTH                          6  /* GP2_FN - [5:0] */
+
+/*
+ * R1794 (0x702) - GPIO CTRL 3
+ */
+#define WM2200_GP3_DIR                          0x8000  /* GP3_DIR */
+#define WM2200_GP3_DIR_MASK                     0x8000  /* GP3_DIR */
+#define WM2200_GP3_DIR_SHIFT                        15  /* GP3_DIR */
+#define WM2200_GP3_DIR_WIDTH                         1  /* GP3_DIR */
+#define WM2200_GP3_PU                           0x4000  /* GP3_PU */
+#define WM2200_GP3_PU_MASK                      0x4000  /* GP3_PU */
+#define WM2200_GP3_PU_SHIFT                         14  /* GP3_PU */
+#define WM2200_GP3_PU_WIDTH                          1  /* GP3_PU */
+#define WM2200_GP3_PD                           0x2000  /* GP3_PD */
+#define WM2200_GP3_PD_MASK                      0x2000  /* GP3_PD */
+#define WM2200_GP3_PD_SHIFT                         13  /* GP3_PD */
+#define WM2200_GP3_PD_WIDTH                          1  /* GP3_PD */
+#define WM2200_GP3_POL                          0x0400  /* GP3_POL */
+#define WM2200_GP3_POL_MASK                     0x0400  /* GP3_POL */
+#define WM2200_GP3_POL_SHIFT                        10  /* GP3_POL */
+#define WM2200_GP3_POL_WIDTH                         1  /* GP3_POL */
+#define WM2200_GP3_OP_CFG                       0x0200  /* GP3_OP_CFG */
+#define WM2200_GP3_OP_CFG_MASK                  0x0200  /* GP3_OP_CFG */
+#define WM2200_GP3_OP_CFG_SHIFT                      9  /* GP3_OP_CFG */
+#define WM2200_GP3_OP_CFG_WIDTH                      1  /* GP3_OP_CFG */
+#define WM2200_GP3_DB                           0x0100  /* GP3_DB */
+#define WM2200_GP3_DB_MASK                      0x0100  /* GP3_DB */
+#define WM2200_GP3_DB_SHIFT                          8  /* GP3_DB */
+#define WM2200_GP3_DB_WIDTH                          1  /* GP3_DB */
+#define WM2200_GP3_LVL                          0x0040  /* GP3_LVL */
+#define WM2200_GP3_LVL_MASK                     0x0040  /* GP3_LVL */
+#define WM2200_GP3_LVL_SHIFT                         6  /* GP3_LVL */
+#define WM2200_GP3_LVL_WIDTH                         1  /* GP3_LVL */
+#define WM2200_GP3_FN_MASK                      0x003F  /* GP3_FN - [5:0] */
+#define WM2200_GP3_FN_SHIFT                          0  /* GP3_FN - [5:0] */
+#define WM2200_GP3_FN_WIDTH                          6  /* GP3_FN - [5:0] */
+
+/*
+ * R1795 (0x703) - GPIO CTRL 4
+ */
+#define WM2200_GP4_DIR                          0x8000  /* GP4_DIR */
+#define WM2200_GP4_DIR_MASK                     0x8000  /* GP4_DIR */
+#define WM2200_GP4_DIR_SHIFT                        15  /* GP4_DIR */
+#define WM2200_GP4_DIR_WIDTH                         1  /* GP4_DIR */
+#define WM2200_GP4_PU                           0x4000  /* GP4_PU */
+#define WM2200_GP4_PU_MASK                      0x4000  /* GP4_PU */
+#define WM2200_GP4_PU_SHIFT                         14  /* GP4_PU */
+#define WM2200_GP4_PU_WIDTH                          1  /* GP4_PU */
+#define WM2200_GP4_PD                           0x2000  /* GP4_PD */
+#define WM2200_GP4_PD_MASK                      0x2000  /* GP4_PD */
+#define WM2200_GP4_PD_SHIFT                         13  /* GP4_PD */
+#define WM2200_GP4_PD_WIDTH                          1  /* GP4_PD */
+#define WM2200_GP4_POL                          0x0400  /* GP4_POL */
+#define WM2200_GP4_POL_MASK                     0x0400  /* GP4_POL */
+#define WM2200_GP4_POL_SHIFT                        10  /* GP4_POL */
+#define WM2200_GP4_POL_WIDTH                         1  /* GP4_POL */
+#define WM2200_GP4_OP_CFG                       0x0200  /* GP4_OP_CFG */
+#define WM2200_GP4_OP_CFG_MASK                  0x0200  /* GP4_OP_CFG */
+#define WM2200_GP4_OP_CFG_SHIFT                      9  /* GP4_OP_CFG */
+#define WM2200_GP4_OP_CFG_WIDTH                      1  /* GP4_OP_CFG */
+#define WM2200_GP4_DB                           0x0100  /* GP4_DB */
+#define WM2200_GP4_DB_MASK                      0x0100  /* GP4_DB */
+#define WM2200_GP4_DB_SHIFT                          8  /* GP4_DB */
+#define WM2200_GP4_DB_WIDTH                          1  /* GP4_DB */
+#define WM2200_GP4_LVL                          0x0040  /* GP4_LVL */
+#define WM2200_GP4_LVL_MASK                     0x0040  /* GP4_LVL */
+#define WM2200_GP4_LVL_SHIFT                         6  /* GP4_LVL */
+#define WM2200_GP4_LVL_WIDTH                         1  /* GP4_LVL */
+#define WM2200_GP4_FN_MASK                      0x003F  /* GP4_FN - [5:0] */
+#define WM2200_GP4_FN_SHIFT                          0  /* GP4_FN - [5:0] */
+#define WM2200_GP4_FN_WIDTH                          6  /* GP4_FN - [5:0] */
+
+/*
+ * R1799 (0x707) - ADPS1 IRQ0
+ */
+#define WM2200_DSP_IRQ1                         0x0002  /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ1_MASK                    0x0002  /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ1_SHIFT                        1  /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ1_WIDTH                        1  /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ0                         0x0001  /* DSP_IRQ0 */
+#define WM2200_DSP_IRQ0_MASK                    0x0001  /* DSP_IRQ0 */
+#define WM2200_DSP_IRQ0_SHIFT                        0  /* DSP_IRQ0 */
+#define WM2200_DSP_IRQ0_WIDTH                        1  /* DSP_IRQ0 */
+
+/*
+ * R1800 (0x708) - ADPS1 IRQ1
+ */
+#define WM2200_DSP_IRQ3                         0x0002  /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ3_MASK                    0x0002  /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ3_SHIFT                        1  /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ3_WIDTH                        1  /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ2                         0x0001  /* DSP_IRQ2 */
+#define WM2200_DSP_IRQ2_MASK                    0x0001  /* DSP_IRQ2 */
+#define WM2200_DSP_IRQ2_SHIFT                        0  /* DSP_IRQ2 */
+#define WM2200_DSP_IRQ2_WIDTH                        1  /* DSP_IRQ2 */
+
+/*
+ * R1801 (0x709) - Misc Pad Ctrl 1
+ */
+#define WM2200_LDO1ENA_PD                       0x8000  /* LDO1ENA_PD */
+#define WM2200_LDO1ENA_PD_MASK                  0x8000  /* LDO1ENA_PD */
+#define WM2200_LDO1ENA_PD_SHIFT                     15  /* LDO1ENA_PD */
+#define WM2200_LDO1ENA_PD_WIDTH                      1  /* LDO1ENA_PD */
+#define WM2200_MCLK2_PD                         0x2000  /* MCLK2_PD */
+#define WM2200_MCLK2_PD_MASK                    0x2000  /* MCLK2_PD */
+#define WM2200_MCLK2_PD_SHIFT                       13  /* MCLK2_PD */
+#define WM2200_MCLK2_PD_WIDTH                        1  /* MCLK2_PD */
+#define WM2200_MCLK1_PD                         0x1000  /* MCLK1_PD */
+#define WM2200_MCLK1_PD_MASK                    0x1000  /* MCLK1_PD */
+#define WM2200_MCLK1_PD_SHIFT                       12  /* MCLK1_PD */
+#define WM2200_MCLK1_PD_WIDTH                        1  /* MCLK1_PD */
+#define WM2200_DACLRCLK1_PU                     0x0400  /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PU_MASK                0x0400  /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PU_SHIFT                   10  /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PU_WIDTH                    1  /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PD                     0x0200  /* DACLRCLK1_PD */
+#define WM2200_DACLRCLK1_PD_MASK                0x0200  /* DACLRCLK1_PD */
+#define WM2200_DACLRCLK1_PD_SHIFT                    9  /* DACLRCLK1_PD */
+#define WM2200_DACLRCLK1_PD_WIDTH                    1  /* DACLRCLK1_PD */
+#define WM2200_BCLK1_PU                         0x0100  /* BCLK1_PU */
+#define WM2200_BCLK1_PU_MASK                    0x0100  /* BCLK1_PU */
+#define WM2200_BCLK1_PU_SHIFT                        8  /* BCLK1_PU */
+#define WM2200_BCLK1_PU_WIDTH                        1  /* BCLK1_PU */
+#define WM2200_BCLK1_PD                         0x0080  /* BCLK1_PD */
+#define WM2200_BCLK1_PD_MASK                    0x0080  /* BCLK1_PD */
+#define WM2200_BCLK1_PD_SHIFT                        7  /* BCLK1_PD */
+#define WM2200_BCLK1_PD_WIDTH                        1  /* BCLK1_PD */
+#define WM2200_DACDAT1_PU                       0x0040  /* DACDAT1_PU */
+#define WM2200_DACDAT1_PU_MASK                  0x0040  /* DACDAT1_PU */
+#define WM2200_DACDAT1_PU_SHIFT                      6  /* DACDAT1_PU */
+#define WM2200_DACDAT1_PU_WIDTH                      1  /* DACDAT1_PU */
+#define WM2200_DACDAT1_PD                       0x0020  /* DACDAT1_PD */
+#define WM2200_DACDAT1_PD_MASK                  0x0020  /* DACDAT1_PD */
+#define WM2200_DACDAT1_PD_SHIFT                      5  /* DACDAT1_PD */
+#define WM2200_DACDAT1_PD_WIDTH                      1  /* DACDAT1_PD */
+#define WM2200_DMICDAT3_PD                      0x0010  /* DMICDAT3_PD */
+#define WM2200_DMICDAT3_PD_MASK                 0x0010  /* DMICDAT3_PD */
+#define WM2200_DMICDAT3_PD_SHIFT                     4  /* DMICDAT3_PD */
+#define WM2200_DMICDAT3_PD_WIDTH                     1  /* DMICDAT3_PD */
+#define WM2200_DMICDAT2_PD                      0x0008  /* DMICDAT2_PD */
+#define WM2200_DMICDAT2_PD_MASK                 0x0008  /* DMICDAT2_PD */
+#define WM2200_DMICDAT2_PD_SHIFT                     3  /* DMICDAT2_PD */
+#define WM2200_DMICDAT2_PD_WIDTH                     1  /* DMICDAT2_PD */
+#define WM2200_DMICDAT1_PD                      0x0004  /* DMICDAT1_PD */
+#define WM2200_DMICDAT1_PD_MASK                 0x0004  /* DMICDAT1_PD */
+#define WM2200_DMICDAT1_PD_SHIFT                     2  /* DMICDAT1_PD */
+#define WM2200_DMICDAT1_PD_WIDTH                     1  /* DMICDAT1_PD */
+#define WM2200_RSTB_PU                          0x0002  /* RSTB_PU */
+#define WM2200_RSTB_PU_MASK                     0x0002  /* RSTB_PU */
+#define WM2200_RSTB_PU_SHIFT                         1  /* RSTB_PU */
+#define WM2200_RSTB_PU_WIDTH                         1  /* RSTB_PU */
+#define WM2200_ADDR_PD                          0x0001  /* ADDR_PD */
+#define WM2200_ADDR_PD_MASK                     0x0001  /* ADDR_PD */
+#define WM2200_ADDR_PD_SHIFT                         0  /* ADDR_PD */
+#define WM2200_ADDR_PD_WIDTH                         1  /* ADDR_PD */
+
+/*
+ * R2048 (0x800) - Interrupt Status 1
+ */
+#define WM2200_DSP_IRQ0_EINT                    0x0080  /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ0_EINT_MASK               0x0080  /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ0_EINT_SHIFT                   7  /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ0_EINT_WIDTH                   1  /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ1_EINT                    0x0040  /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ1_EINT_MASK               0x0040  /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ1_EINT_SHIFT                   6  /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ1_EINT_WIDTH                   1  /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ2_EINT                    0x0020  /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ2_EINT_MASK               0x0020  /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ2_EINT_SHIFT                   5  /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ2_EINT_WIDTH                   1  /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ3_EINT                    0x0010  /* DSP_IRQ3_EINT */
+#define WM2200_DSP_IRQ3_EINT_MASK               0x0010  /* DSP_IRQ3_EINT */
+#define WM2200_DSP_IRQ3_EINT_SHIFT                   4  /* DSP_IRQ3_EINT */
+#define WM2200_DSP_IRQ3_EINT_WIDTH                   1  /* DSP_IRQ3_EINT */
+#define WM2200_GP4_EINT                         0x0008  /* GP4_EINT */
+#define WM2200_GP4_EINT_MASK                    0x0008  /* GP4_EINT */
+#define WM2200_GP4_EINT_SHIFT                        3  /* GP4_EINT */
+#define WM2200_GP4_EINT_WIDTH                        1  /* GP4_EINT */
+#define WM2200_GP3_EINT                         0x0004  /* GP3_EINT */
+#define WM2200_GP3_EINT_MASK                    0x0004  /* GP3_EINT */
+#define WM2200_GP3_EINT_SHIFT                        2  /* GP3_EINT */
+#define WM2200_GP3_EINT_WIDTH                        1  /* GP3_EINT */
+#define WM2200_GP2_EINT                         0x0002  /* GP2_EINT */
+#define WM2200_GP2_EINT_MASK                    0x0002  /* GP2_EINT */
+#define WM2200_GP2_EINT_SHIFT                        1  /* GP2_EINT */
+#define WM2200_GP2_EINT_WIDTH                        1  /* GP2_EINT */
+#define WM2200_GP1_EINT                         0x0001  /* GP1_EINT */
+#define WM2200_GP1_EINT_MASK                    0x0001  /* GP1_EINT */
+#define WM2200_GP1_EINT_SHIFT                        0  /* GP1_EINT */
+#define WM2200_GP1_EINT_WIDTH                        1  /* GP1_EINT */
+
+/*
+ * R2049 (0x801) - Interrupt Status 1 Mask
+ */
+#define WM2200_IM_DSP_IRQ0_EINT                 0x0080  /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ0_EINT_MASK            0x0080  /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ0_EINT_SHIFT                7  /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ0_EINT_WIDTH                1  /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT                 0x0040  /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT_MASK            0x0040  /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT_SHIFT                6  /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT_WIDTH                1  /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT                 0x0020  /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT_MASK            0x0020  /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT_SHIFT                5  /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT_WIDTH                1  /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT                 0x0010  /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT_MASK            0x0010  /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT_SHIFT                4  /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT_WIDTH                1  /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_GP4_EINT                      0x0008  /* IM_GP4_EINT */
+#define WM2200_IM_GP4_EINT_MASK                 0x0008  /* IM_GP4_EINT */
+#define WM2200_IM_GP4_EINT_SHIFT                     3  /* IM_GP4_EINT */
+#define WM2200_IM_GP4_EINT_WIDTH                     1  /* IM_GP4_EINT */
+#define WM2200_IM_GP3_EINT                      0x0004  /* IM_GP3_EINT */
+#define WM2200_IM_GP3_EINT_MASK                 0x0004  /* IM_GP3_EINT */
+#define WM2200_IM_GP3_EINT_SHIFT                     2  /* IM_GP3_EINT */
+#define WM2200_IM_GP3_EINT_WIDTH                     1  /* IM_GP3_EINT */
+#define WM2200_IM_GP2_EINT                      0x0002  /* IM_GP2_EINT */
+#define WM2200_IM_GP2_EINT_MASK                 0x0002  /* IM_GP2_EINT */
+#define WM2200_IM_GP2_EINT_SHIFT                     1  /* IM_GP2_EINT */
+#define WM2200_IM_GP2_EINT_WIDTH                     1  /* IM_GP2_EINT */
+#define WM2200_IM_GP1_EINT                      0x0001  /* IM_GP1_EINT */
+#define WM2200_IM_GP1_EINT_MASK                 0x0001  /* IM_GP1_EINT */
+#define WM2200_IM_GP1_EINT_SHIFT                     0  /* IM_GP1_EINT */
+#define WM2200_IM_GP1_EINT_WIDTH                     1  /* IM_GP1_EINT */
+
+/*
+ * R2050 (0x802) - Interrupt Status 2
+ */
+#define WM2200_WSEQ_BUSY_EINT                   0x0100  /* WSEQ_BUSY_EINT */
+#define WM2200_WSEQ_BUSY_EINT_MASK              0x0100  /* WSEQ_BUSY_EINT */
+#define WM2200_WSEQ_BUSY_EINT_SHIFT                  8  /* WSEQ_BUSY_EINT */
+#define WM2200_WSEQ_BUSY_EINT_WIDTH                  1  /* WSEQ_BUSY_EINT */
+#define WM2200_FLL_LOCK_EINT                    0x0002  /* FLL_LOCK_EINT */
+#define WM2200_FLL_LOCK_EINT_MASK               0x0002  /* FLL_LOCK_EINT */
+#define WM2200_FLL_LOCK_EINT_SHIFT                   1  /* FLL_LOCK_EINT */
+#define WM2200_FLL_LOCK_EINT_WIDTH                   1  /* FLL_LOCK_EINT */
+#define WM2200_CLKGEN_EINT                      0x0001  /* CLKGEN_EINT */
+#define WM2200_CLKGEN_EINT_MASK                 0x0001  /* CLKGEN_EINT */
+#define WM2200_CLKGEN_EINT_SHIFT                     0  /* CLKGEN_EINT */
+#define WM2200_CLKGEN_EINT_WIDTH                     1  /* CLKGEN_EINT */
+
+/*
+ * R2051 (0x803) - Interrupt Raw Status 2
+ */
+#define WM2200_WSEQ_BUSY_STS                    0x0100  /* WSEQ_BUSY_STS */
+#define WM2200_WSEQ_BUSY_STS_MASK               0x0100  /* WSEQ_BUSY_STS */
+#define WM2200_WSEQ_BUSY_STS_SHIFT                   8  /* WSEQ_BUSY_STS */
+#define WM2200_WSEQ_BUSY_STS_WIDTH                   1  /* WSEQ_BUSY_STS */
+#define WM2200_FLL_LOCK_STS                     0x0002  /* FLL_LOCK_STS */
+#define WM2200_FLL_LOCK_STS_MASK                0x0002  /* FLL_LOCK_STS */
+#define WM2200_FLL_LOCK_STS_SHIFT                    1  /* FLL_LOCK_STS */
+#define WM2200_FLL_LOCK_STS_WIDTH                    1  /* FLL_LOCK_STS */
+#define WM2200_CLKGEN_STS                       0x0001  /* CLKGEN_STS */
+#define WM2200_CLKGEN_STS_MASK                  0x0001  /* CLKGEN_STS */
+#define WM2200_CLKGEN_STS_SHIFT                      0  /* CLKGEN_STS */
+#define WM2200_CLKGEN_STS_WIDTH                      1  /* CLKGEN_STS */
+
+/*
+ * R2052 (0x804) - Interrupt Status 2 Mask
+ */
+#define WM2200_IM_WSEQ_BUSY_EINT                0x0100  /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_WSEQ_BUSY_EINT_MASK           0x0100  /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_WSEQ_BUSY_EINT_SHIFT               8  /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_WSEQ_BUSY_EINT_WIDTH               1  /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_FLL_LOCK_EINT                 0x0002  /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_FLL_LOCK_EINT_MASK            0x0002  /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_FLL_LOCK_EINT_SHIFT                1  /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_FLL_LOCK_EINT_WIDTH                1  /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_CLKGEN_EINT                   0x0001  /* IM_CLKGEN_EINT */
+#define WM2200_IM_CLKGEN_EINT_MASK              0x0001  /* IM_CLKGEN_EINT */
+#define WM2200_IM_CLKGEN_EINT_SHIFT                  0  /* IM_CLKGEN_EINT */
+#define WM2200_IM_CLKGEN_EINT_WIDTH                  1  /* IM_CLKGEN_EINT */
+
+/*
+ * R2056 (0x808) - Interrupt Control
+ */
+#define WM2200_IM_IRQ                           0x0001  /* IM_IRQ */
+#define WM2200_IM_IRQ_MASK                      0x0001  /* IM_IRQ */
+#define WM2200_IM_IRQ_SHIFT                          0  /* IM_IRQ */
+#define WM2200_IM_IRQ_WIDTH                          1  /* IM_IRQ */
+
+/*
+ * R2304 (0x900) - EQL_1
+ */
+#define WM2200_EQL_B1_GAIN_MASK                 0xF800  /* EQL_B1_GAIN - [15:11] */
+#define WM2200_EQL_B1_GAIN_SHIFT                    11  /* EQL_B1_GAIN - [15:11] */
+#define WM2200_EQL_B1_GAIN_WIDTH                     5  /* EQL_B1_GAIN - [15:11] */
+#define WM2200_EQL_B2_GAIN_MASK                 0x07C0  /* EQL_B2_GAIN - [10:6] */
+#define WM2200_EQL_B2_GAIN_SHIFT                     6  /* EQL_B2_GAIN - [10:6] */
+#define WM2200_EQL_B2_GAIN_WIDTH                     5  /* EQL_B2_GAIN - [10:6] */
+#define WM2200_EQL_B3_GAIN_MASK                 0x003E  /* EQL_B3_GAIN - [5:1] */
+#define WM2200_EQL_B3_GAIN_SHIFT                     1  /* EQL_B3_GAIN - [5:1] */
+#define WM2200_EQL_B3_GAIN_WIDTH                     5  /* EQL_B3_GAIN - [5:1] */
+#define WM2200_EQL_ENA                          0x0001  /* EQL_ENA */
+#define WM2200_EQL_ENA_MASK                     0x0001  /* EQL_ENA */
+#define WM2200_EQL_ENA_SHIFT                         0  /* EQL_ENA */
+#define WM2200_EQL_ENA_WIDTH                         1  /* EQL_ENA */
+
+/*
+ * R2305 (0x901) - EQL_2
+ */
+#define WM2200_EQL_B4_GAIN_MASK                 0xF800  /* EQL_B4_GAIN - [15:11] */
+#define WM2200_EQL_B4_GAIN_SHIFT                    11  /* EQL_B4_GAIN - [15:11] */
+#define WM2200_EQL_B4_GAIN_WIDTH                     5  /* EQL_B4_GAIN - [15:11] */
+#define WM2200_EQL_B5_GAIN_MASK                 0x07C0  /* EQL_B5_GAIN - [10:6] */
+#define WM2200_EQL_B5_GAIN_SHIFT                     6  /* EQL_B5_GAIN - [10:6] */
+#define WM2200_EQL_B5_GAIN_WIDTH                     5  /* EQL_B5_GAIN - [10:6] */
+
+/*
+ * R2306 (0x902) - EQL_3
+ */
+#define WM2200_EQL_B1_A_MASK                    0xFFFF  /* EQL_B1_A - [15:0] */
+#define WM2200_EQL_B1_A_SHIFT                        0  /* EQL_B1_A - [15:0] */
+#define WM2200_EQL_B1_A_WIDTH                       16  /* EQL_B1_A - [15:0] */
+
+/*
+ * R2307 (0x903) - EQL_4
+ */
+#define WM2200_EQL_B1_B_MASK                    0xFFFF  /* EQL_B1_B - [15:0] */
+#define WM2200_EQL_B1_B_SHIFT                        0  /* EQL_B1_B - [15:0] */
+#define WM2200_EQL_B1_B_WIDTH                       16  /* EQL_B1_B - [15:0] */
+
+/*
+ * R2308 (0x904) - EQL_5
+ */
+#define WM2200_EQL_B1_PG_MASK                   0xFFFF  /* EQL_B1_PG - [15:0] */
+#define WM2200_EQL_B1_PG_SHIFT                       0  /* EQL_B1_PG - [15:0] */
+#define WM2200_EQL_B1_PG_WIDTH                      16  /* EQL_B1_PG - [15:0] */
+
+/*
+ * R2309 (0x905) - EQL_6
+ */
+#define WM2200_EQL_B2_A_MASK                    0xFFFF  /* EQL_B2_A - [15:0] */
+#define WM2200_EQL_B2_A_SHIFT                        0  /* EQL_B2_A - [15:0] */
+#define WM2200_EQL_B2_A_WIDTH                       16  /* EQL_B2_A - [15:0] */
+
+/*
+ * R2310 (0x906) - EQL_7
+ */
+#define WM2200_EQL_B2_B_MASK                    0xFFFF  /* EQL_B2_B - [15:0] */
+#define WM2200_EQL_B2_B_SHIFT                        0  /* EQL_B2_B - [15:0] */
+#define WM2200_EQL_B2_B_WIDTH                       16  /* EQL_B2_B - [15:0] */
+
+/*
+ * R2311 (0x907) - EQL_8
+ */
+#define WM2200_EQL_B2_C_MASK                    0xFFFF  /* EQL_B2_C - [15:0] */
+#define WM2200_EQL_B2_C_SHIFT                        0  /* EQL_B2_C - [15:0] */
+#define WM2200_EQL_B2_C_WIDTH                       16  /* EQL_B2_C - [15:0] */
+
+/*
+ * R2312 (0x908) - EQL_9
+ */
+#define WM2200_EQL_B2_PG_MASK                   0xFFFF  /* EQL_B2_PG - [15:0] */
+#define WM2200_EQL_B2_PG_SHIFT                       0  /* EQL_B2_PG - [15:0] */
+#define WM2200_EQL_B2_PG_WIDTH                      16  /* EQL_B2_PG - [15:0] */
+
+/*
+ * R2313 (0x909) - EQL_10
+ */
+#define WM2200_EQL_B3_A_MASK                    0xFFFF  /* EQL_B3_A - [15:0] */
+#define WM2200_EQL_B3_A_SHIFT                        0  /* EQL_B3_A - [15:0] */
+#define WM2200_EQL_B3_A_WIDTH                       16  /* EQL_B3_A - [15:0] */
+
+/*
+ * R2314 (0x90A) - EQL_11
+ */
+#define WM2200_EQL_B3_B_MASK                    0xFFFF  /* EQL_B3_B - [15:0] */
+#define WM2200_EQL_B3_B_SHIFT                        0  /* EQL_B3_B - [15:0] */
+#define WM2200_EQL_B3_B_WIDTH                       16  /* EQL_B3_B - [15:0] */
+
+/*
+ * R2315 (0x90B) - EQL_12
+ */
+#define WM2200_EQL_B3_C_MASK                    0xFFFF  /* EQL_B3_C - [15:0] */
+#define WM2200_EQL_B3_C_SHIFT                        0  /* EQL_B3_C - [15:0] */
+#define WM2200_EQL_B3_C_WIDTH                       16  /* EQL_B3_C - [15:0] */
+
+/*
+ * R2316 (0x90C) - EQL_13
+ */
+#define WM2200_EQL_B3_PG_MASK                   0xFFFF  /* EQL_B3_PG - [15:0] */
+#define WM2200_EQL_B3_PG_SHIFT                       0  /* EQL_B3_PG - [15:0] */
+#define WM2200_EQL_B3_PG_WIDTH                      16  /* EQL_B3_PG - [15:0] */
+
+/*
+ * R2317 (0x90D) - EQL_14
+ */
+#define WM2200_EQL_B4_A_MASK                    0xFFFF  /* EQL_B4_A - [15:0] */
+#define WM2200_EQL_B4_A_SHIFT                        0  /* EQL_B4_A - [15:0] */
+#define WM2200_EQL_B4_A_WIDTH                       16  /* EQL_B4_A - [15:0] */
+
+/*
+ * R2318 (0x90E) - EQL_15
+ */
+#define WM2200_EQL_B4_B_MASK                    0xFFFF  /* EQL_B4_B - [15:0] */
+#define WM2200_EQL_B4_B_SHIFT                        0  /* EQL_B4_B - [15:0] */
+#define WM2200_EQL_B4_B_WIDTH                       16  /* EQL_B4_B - [15:0] */
+
+/*
+ * R2319 (0x90F) - EQL_16
+ */
+#define WM2200_EQL_B4_C_MASK                    0xFFFF  /* EQL_B4_C - [15:0] */
+#define WM2200_EQL_B4_C_SHIFT                        0  /* EQL_B4_C - [15:0] */
+#define WM2200_EQL_B4_C_WIDTH                       16  /* EQL_B4_C - [15:0] */
+
+/*
+ * R2320 (0x910) - EQL_17
+ */
+#define WM2200_EQL_B4_PG_MASK                   0xFFFF  /* EQL_B4_PG - [15:0] */
+#define WM2200_EQL_B4_PG_SHIFT                       0  /* EQL_B4_PG - [15:0] */
+#define WM2200_EQL_B4_PG_WIDTH                      16  /* EQL_B4_PG - [15:0] */
+
+/*
+ * R2321 (0x911) - EQL_18
+ */
+#define WM2200_EQL_B5_A_MASK                    0xFFFF  /* EQL_B5_A - [15:0] */
+#define WM2200_EQL_B5_A_SHIFT                        0  /* EQL_B5_A - [15:0] */
+#define WM2200_EQL_B5_A_WIDTH                       16  /* EQL_B5_A - [15:0] */
+
+/*
+ * R2322 (0x912) - EQL_19
+ */
+#define WM2200_EQL_B5_B_MASK                    0xFFFF  /* EQL_B5_B - [15:0] */
+#define WM2200_EQL_B5_B_SHIFT                        0  /* EQL_B5_B - [15:0] */
+#define WM2200_EQL_B5_B_WIDTH                       16  /* EQL_B5_B - [15:0] */
+
+/*
+ * R2323 (0x913) - EQL_20
+ */
+#define WM2200_EQL_B5_PG_MASK                   0xFFFF  /* EQL_B5_PG - [15:0] */
+#define WM2200_EQL_B5_PG_SHIFT                       0  /* EQL_B5_PG - [15:0] */
+#define WM2200_EQL_B5_PG_WIDTH                      16  /* EQL_B5_PG - [15:0] */
+
+/*
+ * R2326 (0x916) - EQR_1
+ */
+#define WM2200_EQR_B1_GAIN_MASK                 0xF800  /* EQR_B1_GAIN - [15:11] */
+#define WM2200_EQR_B1_GAIN_SHIFT                    11  /* EQR_B1_GAIN - [15:11] */
+#define WM2200_EQR_B1_GAIN_WIDTH                     5  /* EQR_B1_GAIN - [15:11] */
+#define WM2200_EQR_B2_GAIN_MASK                 0x07C0  /* EQR_B2_GAIN - [10:6] */
+#define WM2200_EQR_B2_GAIN_SHIFT                     6  /* EQR_B2_GAIN - [10:6] */
+#define WM2200_EQR_B2_GAIN_WIDTH                     5  /* EQR_B2_GAIN - [10:6] */
+#define WM2200_EQR_B3_GAIN_MASK                 0x003E  /* EQR_B3_GAIN - [5:1] */
+#define WM2200_EQR_B3_GAIN_SHIFT                     1  /* EQR_B3_GAIN - [5:1] */
+#define WM2200_EQR_B3_GAIN_WIDTH                     5  /* EQR_B3_GAIN - [5:1] */
+#define WM2200_EQR_ENA                          0x0001  /* EQR_ENA */
+#define WM2200_EQR_ENA_MASK                     0x0001  /* EQR_ENA */
+#define WM2200_EQR_ENA_SHIFT                         0  /* EQR_ENA */
+#define WM2200_EQR_ENA_WIDTH                         1  /* EQR_ENA */
+
+/*
+ * R2327 (0x917) - EQR_2
+ */
+#define WM2200_EQR_B4_GAIN_MASK                 0xF800  /* EQR_B4_GAIN - [15:11] */
+#define WM2200_EQR_B4_GAIN_SHIFT                    11  /* EQR_B4_GAIN - [15:11] */
+#define WM2200_EQR_B4_GAIN_WIDTH                     5  /* EQR_B4_GAIN - [15:11] */
+#define WM2200_EQR_B5_GAIN_MASK                 0x07C0  /* EQR_B5_GAIN - [10:6] */
+#define WM2200_EQR_B5_GAIN_SHIFT                     6  /* EQR_B5_GAIN - [10:6] */
+#define WM2200_EQR_B5_GAIN_WIDTH                     5  /* EQR_B5_GAIN - [10:6] */
+
+/*
+ * R2328 (0x918) - EQR_3
+ */
+#define WM2200_EQR_B1_A_MASK                    0xFFFF  /* EQR_B1_A - [15:0] */
+#define WM2200_EQR_B1_A_SHIFT                        0  /* EQR_B1_A - [15:0] */
+#define WM2200_EQR_B1_A_WIDTH                       16  /* EQR_B1_A - [15:0] */
+
+/*
+ * R2329 (0x919) - EQR_4
+ */
+#define WM2200_EQR_B1_B_MASK                    0xFFFF  /* EQR_B1_B - [15:0] */
+#define WM2200_EQR_B1_B_SHIFT                        0  /* EQR_B1_B - [15:0] */
+#define WM2200_EQR_B1_B_WIDTH                       16  /* EQR_B1_B - [15:0] */
+
+/*
+ * R2330 (0x91A) - EQR_5
+ */
+#define WM2200_EQR_B1_PG_MASK                   0xFFFF  /* EQR_B1_PG - [15:0] */
+#define WM2200_EQR_B1_PG_SHIFT                       0  /* EQR_B1_PG - [15:0] */
+#define WM2200_EQR_B1_PG_WIDTH                      16  /* EQR_B1_PG - [15:0] */
+
+/*
+ * R2331 (0x91B) - EQR_6
+ */
+#define WM2200_EQR_B2_A_MASK                    0xFFFF  /* EQR_B2_A - [15:0] */
+#define WM2200_EQR_B2_A_SHIFT                        0  /* EQR_B2_A - [15:0] */
+#define WM2200_EQR_B2_A_WIDTH                       16  /* EQR_B2_A - [15:0] */
+
+/*
+ * R2332 (0x91C) - EQR_7
+ */
+#define WM2200_EQR_B2_B_MASK                    0xFFFF  /* EQR_B2_B - [15:0] */
+#define WM2200_EQR_B2_B_SHIFT                        0  /* EQR_B2_B - [15:0] */
+#define WM2200_EQR_B2_B_WIDTH                       16  /* EQR_B2_B - [15:0] */
+
+/*
+ * R2333 (0x91D) - EQR_8
+ */
+#define WM2200_EQR_B2_C_MASK                    0xFFFF  /* EQR_B2_C - [15:0] */
+#define WM2200_EQR_B2_C_SHIFT                        0  /* EQR_B2_C - [15:0] */
+#define WM2200_EQR_B2_C_WIDTH                       16  /* EQR_B2_C - [15:0] */
+
+/*
+ * R2334 (0x91E) - EQR_9
+ */
+#define WM2200_EQR_B2_PG_MASK                   0xFFFF  /* EQR_B2_PG - [15:0] */
+#define WM2200_EQR_B2_PG_SHIFT                       0  /* EQR_B2_PG - [15:0] */
+#define WM2200_EQR_B2_PG_WIDTH                      16  /* EQR_B2_PG - [15:0] */
+
+/*
+ * R2335 (0x91F) - EQR_10
+ */
+#define WM2200_EQR_B3_A_MASK                    0xFFFF  /* EQR_B3_A - [15:0] */
+#define WM2200_EQR_B3_A_SHIFT                        0  /* EQR_B3_A - [15:0] */
+#define WM2200_EQR_B3_A_WIDTH                       16  /* EQR_B3_A - [15:0] */
+
+/*
+ * R2336 (0x920) - EQR_11
+ */
+#define WM2200_EQR_B3_B_MASK                    0xFFFF  /* EQR_B3_B - [15:0] */
+#define WM2200_EQR_B3_B_SHIFT                        0  /* EQR_B3_B - [15:0] */
+#define WM2200_EQR_B3_B_WIDTH                       16  /* EQR_B3_B - [15:0] */
+
+/*
+ * R2337 (0x921) - EQR_12
+ */
+#define WM2200_EQR_B3_C_MASK                    0xFFFF  /* EQR_B3_C - [15:0] */
+#define WM2200_EQR_B3_C_SHIFT                        0  /* EQR_B3_C - [15:0] */
+#define WM2200_EQR_B3_C_WIDTH                       16  /* EQR_B3_C - [15:0] */
+
+/*
+ * R2338 (0x922) - EQR_13
+ */
+#define WM2200_EQR_B3_PG_MASK                   0xFFFF  /* EQR_B3_PG - [15:0] */
+#define WM2200_EQR_B3_PG_SHIFT                       0  /* EQR_B3_PG - [15:0] */
+#define WM2200_EQR_B3_PG_WIDTH                      16  /* EQR_B3_PG - [15:0] */
+
+/*
+ * R2339 (0x923) - EQR_14
+ */
+#define WM2200_EQR_B4_A_MASK                    0xFFFF  /* EQR_B4_A - [15:0] */
+#define WM2200_EQR_B4_A_SHIFT                        0  /* EQR_B4_A - [15:0] */
+#define WM2200_EQR_B4_A_WIDTH                       16  /* EQR_B4_A - [15:0] */
+
+/*
+ * R2340 (0x924) - EQR_15
+ */
+#define WM2200_EQR_B4_B_MASK                    0xFFFF  /* EQR_B4_B - [15:0] */
+#define WM2200_EQR_B4_B_SHIFT                        0  /* EQR_B4_B - [15:0] */
+#define WM2200_EQR_B4_B_WIDTH                       16  /* EQR_B4_B - [15:0] */
+
+/*
+ * R2341 (0x925) - EQR_16
+ */
+#define WM2200_EQR_B4_C_MASK                    0xFFFF  /* EQR_B4_C - [15:0] */
+#define WM2200_EQR_B4_C_SHIFT                        0  /* EQR_B4_C - [15:0] */
+#define WM2200_EQR_B4_C_WIDTH                       16  /* EQR_B4_C - [15:0] */
+
+/*
+ * R2342 (0x926) - EQR_17
+ */
+#define WM2200_EQR_B4_PG_MASK                   0xFFFF  /* EQR_B4_PG - [15:0] */
+#define WM2200_EQR_B4_PG_SHIFT                       0  /* EQR_B4_PG - [15:0] */
+#define WM2200_EQR_B4_PG_WIDTH                      16  /* EQR_B4_PG - [15:0] */
+
+/*
+ * R2343 (0x927) - EQR_18
+ */
+#define WM2200_EQR_B5_A_MASK                    0xFFFF  /* EQR_B5_A - [15:0] */
+#define WM2200_EQR_B5_A_SHIFT                        0  /* EQR_B5_A - [15:0] */
+#define WM2200_EQR_B5_A_WIDTH                       16  /* EQR_B5_A - [15:0] */
+
+/*
+ * R2344 (0x928) - EQR_19
+ */
+#define WM2200_EQR_B5_B_MASK                    0xFFFF  /* EQR_B5_B - [15:0] */
+#define WM2200_EQR_B5_B_SHIFT                        0  /* EQR_B5_B - [15:0] */
+#define WM2200_EQR_B5_B_WIDTH                       16  /* EQR_B5_B - [15:0] */
+
+/*
+ * R2345 (0x929) - EQR_20
+ */
+#define WM2200_EQR_B5_PG_MASK                   0xFFFF  /* EQR_B5_PG - [15:0] */
+#define WM2200_EQR_B5_PG_SHIFT                       0  /* EQR_B5_PG - [15:0] */
+#define WM2200_EQR_B5_PG_WIDTH                      16  /* EQR_B5_PG - [15:0] */
+
+/*
+ * R2366 (0x93E) - HPLPF1_1
+ */
+#define WM2200_LHPF1_MODE                       0x0002  /* LHPF1_MODE */
+#define WM2200_LHPF1_MODE_MASK                  0x0002  /* LHPF1_MODE */
+#define WM2200_LHPF1_MODE_SHIFT                      1  /* LHPF1_MODE */
+#define WM2200_LHPF1_MODE_WIDTH                      1  /* LHPF1_MODE */
+#define WM2200_LHPF1_ENA                        0x0001  /* LHPF1_ENA */
+#define WM2200_LHPF1_ENA_MASK                   0x0001  /* LHPF1_ENA */
+#define WM2200_LHPF1_ENA_SHIFT                       0  /* LHPF1_ENA */
+#define WM2200_LHPF1_ENA_WIDTH                       1  /* LHPF1_ENA */
+
+/*
+ * R2367 (0x93F) - HPLPF1_2
+ */
+#define WM2200_LHPF1_COEFF_MASK                 0xFFFF  /* LHPF1_COEFF - [15:0] */
+#define WM2200_LHPF1_COEFF_SHIFT                     0  /* LHPF1_COEFF - [15:0] */
+#define WM2200_LHPF1_COEFF_WIDTH                    16  /* LHPF1_COEFF - [15:0] */
+
+/*
+ * R2370 (0x942) - HPLPF2_1
+ */
+#define WM2200_LHPF2_MODE                       0x0002  /* LHPF2_MODE */
+#define WM2200_LHPF2_MODE_MASK                  0x0002  /* LHPF2_MODE */
+#define WM2200_LHPF2_MODE_SHIFT                      1  /* LHPF2_MODE */
+#define WM2200_LHPF2_MODE_WIDTH                      1  /* LHPF2_MODE */
+#define WM2200_LHPF2_ENA                        0x0001  /* LHPF2_ENA */
+#define WM2200_LHPF2_ENA_MASK                   0x0001  /* LHPF2_ENA */
+#define WM2200_LHPF2_ENA_SHIFT                       0  /* LHPF2_ENA */
+#define WM2200_LHPF2_ENA_WIDTH                       1  /* LHPF2_ENA */
+
+/*
+ * R2371 (0x943) - HPLPF2_2
+ */
+#define WM2200_LHPF2_COEFF_MASK                 0xFFFF  /* LHPF2_COEFF - [15:0] */
+#define WM2200_LHPF2_COEFF_SHIFT                     0  /* LHPF2_COEFF - [15:0] */
+#define WM2200_LHPF2_COEFF_WIDTH                    16  /* LHPF2_COEFF - [15:0] */
+
+/*
+ * R2560 (0xA00) - DSP1 Control 1
+ */
+#define WM2200_DSP1_RW_SEQUENCE_ENA             0x0001  /* DSP1_RW_SEQUENCE_ENA */
+#define WM2200_DSP1_RW_SEQUENCE_ENA_MASK        0x0001  /* DSP1_RW_SEQUENCE_ENA */
+#define WM2200_DSP1_RW_SEQUENCE_ENA_SHIFT            0  /* DSP1_RW_SEQUENCE_ENA */
+#define WM2200_DSP1_RW_SEQUENCE_ENA_WIDTH            1  /* DSP1_RW_SEQUENCE_ENA */
+
+/*
+ * R2562 (0xA02) - DSP1 Control 2
+ */
+#define WM2200_DSP1_PAGE_BASE_PM_0_MASK         0xFF00  /* DSP1_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_PM_0_SHIFT             8  /* DSP1_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_PM_0_WIDTH             8  /* DSP1_PAGE_BASE_PM - [15:8] */
+
+/*
+ * R2563 (0xA03) - DSP1 Control 3
+ */
+#define WM2200_DSP1_PAGE_BASE_DM_0_MASK         0xFF00  /* DSP1_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_DM_0_SHIFT             8  /* DSP1_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_DM_0_WIDTH             8  /* DSP1_PAGE_BASE_DM - [15:8] */
+
+/*
+ * R2564 (0xA04) - DSP1 Control 4
+ */
+#define WM2200_DSP1_PAGE_BASE_ZM_0_MASK         0xFF00  /* DSP1_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_ZM_0_SHIFT             8  /* DSP1_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_ZM_0_WIDTH             8  /* DSP1_PAGE_BASE_ZM - [15:8] */
+
+/*
+ * R2566 (0xA06) - DSP1 Control 5
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_MASK 0x3FFF  /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_SHIFT      0  /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_WIDTH     14  /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2567 (0xA07) - DSP1 Control 6
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_MASK 0x3FFF  /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_SHIFT      0  /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_WIDTH     14  /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2568 (0xA08) - DSP1 Control 7
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_MASK 0x3FFF  /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_SHIFT      0  /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_WIDTH     14  /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2569 (0xA09) - DSP1 Control 8
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_MASK 0x3FFF  /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_SHIFT      0  /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_WIDTH     14  /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2570 (0xA0A) - DSP1 Control 9
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_MASK 0x3FFF  /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_SHIFT      0  /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_WIDTH     14  /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2571 (0xA0B) - DSP1 Control 10
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_MASK 0x3FFF  /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_SHIFT      0  /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_WIDTH     14  /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2572 (0xA0C) - DSP1 Control 11
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_MASK 0x3FFF  /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_SHIFT      0  /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_WIDTH     14  /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+
+/*
+ * R2573 (0xA0D) - DSP1 Control 12
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_MASK 0x3FFF  /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_SHIFT      0  /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_WIDTH     14  /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+
+/*
+ * R2575 (0xA0F) - DSP1 Control 13
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_MASK 0x3FFF  /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_SHIFT      0  /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_WIDTH     14  /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2576 (0xA10) - DSP1 Control 14
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_MASK 0x3FFF  /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_SHIFT      0  /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_WIDTH     14  /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2577 (0xA11) - DSP1 Control 15
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_MASK 0x3FFF  /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_SHIFT      0  /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_WIDTH     14  /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2578 (0xA12) - DSP1 Control 16
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_MASK 0x3FFF  /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_SHIFT      0  /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_WIDTH     14  /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2579 (0xA13) - DSP1 Control 17
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_MASK 0x3FFF  /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_SHIFT      0  /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_WIDTH     14  /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2580 (0xA14) - DSP1 Control 18
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_MASK 0x3FFF  /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_SHIFT      0  /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_WIDTH     14  /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2582 (0xA16) - DSP1 Control 19
+ */
+#define WM2200_DSP1_WDMA_BUFFER_LENGTH_MASK     0x00FF  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP1_WDMA_BUFFER_LENGTH_SHIFT         0  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP1_WDMA_BUFFER_LENGTH_WIDTH         8  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+
+/*
+ * R2583 (0xA17) - DSP1 Control 20
+ */
+#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_MASK    0x00FF  /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_SHIFT        0  /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_WIDTH        8  /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */
+
+/*
+ * R2584 (0xA18) - DSP1 Control 21
+ */
+#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_MASK    0x003F  /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_SHIFT        0  /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_WIDTH        6  /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */
+
+/*
+ * R2586 (0xA1A) - DSP1 Control 22
+ */
+#define WM2200_DSP1_DM_SIZE_MASK                0xFFFF  /* DSP1_DM_SIZE - [15:0] */
+#define WM2200_DSP1_DM_SIZE_SHIFT                    0  /* DSP1_DM_SIZE - [15:0] */
+#define WM2200_DSP1_DM_SIZE_WIDTH                   16  /* DSP1_DM_SIZE - [15:0] */
+
+/*
+ * R2587 (0xA1B) - DSP1 Control 23
+ */
+#define WM2200_DSP1_PM_SIZE_MASK                0xFFFF  /* DSP1_PM_SIZE - [15:0] */
+#define WM2200_DSP1_PM_SIZE_SHIFT                    0  /* DSP1_PM_SIZE - [15:0] */
+#define WM2200_DSP1_PM_SIZE_WIDTH                   16  /* DSP1_PM_SIZE - [15:0] */
+
+/*
+ * R2588 (0xA1C) - DSP1 Control 24
+ */
+#define WM2200_DSP1_ZM_SIZE_MASK                0xFFFF  /* DSP1_ZM_SIZE - [15:0] */
+#define WM2200_DSP1_ZM_SIZE_SHIFT                    0  /* DSP1_ZM_SIZE - [15:0] */
+#define WM2200_DSP1_ZM_SIZE_WIDTH                   16  /* DSP1_ZM_SIZE - [15:0] */
+
+/*
+ * R2590 (0xA1E) - DSP1 Control 25
+ */
+#define WM2200_DSP1_PING_FULL                   0x8000  /* DSP1_PING_FULL */
+#define WM2200_DSP1_PING_FULL_MASK              0x8000  /* DSP1_PING_FULL */
+#define WM2200_DSP1_PING_FULL_SHIFT                 15  /* DSP1_PING_FULL */
+#define WM2200_DSP1_PING_FULL_WIDTH                  1  /* DSP1_PING_FULL */
+#define WM2200_DSP1_PONG_FULL                   0x4000  /* DSP1_PONG_FULL */
+#define WM2200_DSP1_PONG_FULL_MASK              0x4000  /* DSP1_PONG_FULL */
+#define WM2200_DSP1_PONG_FULL_SHIFT                 14  /* DSP1_PONG_FULL */
+#define WM2200_DSP1_PONG_FULL_WIDTH                  1  /* DSP1_PONG_FULL */
+#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_MASK   0x00FF  /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_SHIFT       0  /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_WIDTH       8  /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */
+
+/*
+ * R2592 (0xA20) - DSP1 Control 26
+ */
+#define WM2200_DSP1_SCRATCH_0_MASK              0xFFFF  /* DSP1_SCRATCH_0 - [15:0] */
+#define WM2200_DSP1_SCRATCH_0_SHIFT                  0  /* DSP1_SCRATCH_0 - [15:0] */
+#define WM2200_DSP1_SCRATCH_0_WIDTH                 16  /* DSP1_SCRATCH_0 - [15:0] */
+
+/*
+ * R2593 (0xA21) - DSP1 Control 27
+ */
+#define WM2200_DSP1_SCRATCH_1_MASK              0xFFFF  /* DSP1_SCRATCH_1 - [15:0] */
+#define WM2200_DSP1_SCRATCH_1_SHIFT                  0  /* DSP1_SCRATCH_1 - [15:0] */
+#define WM2200_DSP1_SCRATCH_1_WIDTH                 16  /* DSP1_SCRATCH_1 - [15:0] */
+
+/*
+ * R2594 (0xA22) - DSP1 Control 28
+ */
+#define WM2200_DSP1_SCRATCH_2_MASK              0xFFFF  /* DSP1_SCRATCH_2 - [15:0] */
+#define WM2200_DSP1_SCRATCH_2_SHIFT                  0  /* DSP1_SCRATCH_2 - [15:0] */
+#define WM2200_DSP1_SCRATCH_2_WIDTH                 16  /* DSP1_SCRATCH_2 - [15:0] */
+
+/*
+ * R2595 (0xA23) - DSP1 Control 29
+ */
+#define WM2200_DSP1_SCRATCH_3_MASK              0xFFFF  /* DSP1_SCRATCH_3 - [15:0] */
+#define WM2200_DSP1_SCRATCH_3_SHIFT                  0  /* DSP1_SCRATCH_3 - [15:0] */
+#define WM2200_DSP1_SCRATCH_3_WIDTH                 16  /* DSP1_SCRATCH_3 - [15:0] */
+
+/*
+ * R2596 (0xA24) - DSP1 Control 30
+ */
+#define WM2200_DSP1_DBG_CLK_ENA                 0x0008  /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_DBG_CLK_ENA_MASK            0x0008  /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_DBG_CLK_ENA_SHIFT                3  /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_DBG_CLK_ENA_WIDTH                1  /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
+#define WM2200_DSP1_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
+#define WM2200_DSP1_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
+#define WM2200_DSP1_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
+#define WM2200_DSP1_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
+#define WM2200_DSP1_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
+#define WM2200_DSP1_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
+#define WM2200_DSP1_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
+#define WM2200_DSP1_START                       0x0001  /* DSP1_START */
+#define WM2200_DSP1_START_MASK                  0x0001  /* DSP1_START */
+#define WM2200_DSP1_START_SHIFT                      0  /* DSP1_START */
+#define WM2200_DSP1_START_WIDTH                      1  /* DSP1_START */
+
+/*
+ * R2598 (0xA26) - DSP1 Control 31
+ */
+#define WM2200_DSP1_CLK_RATE_MASK               0x0018  /* DSP1_CLK_RATE - [4:3] */
+#define WM2200_DSP1_CLK_RATE_SHIFT                   3  /* DSP1_CLK_RATE - [4:3] */
+#define WM2200_DSP1_CLK_RATE_WIDTH                   2  /* DSP1_CLK_RATE - [4:3] */
+#define WM2200_DSP1_CLK_AVAIL                   0x0004  /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_AVAIL_MASK              0x0004  /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_AVAIL_SHIFT                  2  /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_AVAIL_WIDTH                  1  /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_REQ_MASK                0x0003  /* DSP1_CLK_REQ - [1:0] */
+#define WM2200_DSP1_CLK_REQ_SHIFT                    0  /* DSP1_CLK_REQ - [1:0] */
+#define WM2200_DSP1_CLK_REQ_WIDTH                    2  /* DSP1_CLK_REQ - [1:0] */
+
+/*
+ * R2816 (0xB00) - DSP2 Control 1
+ */
+#define WM2200_DSP2_RW_SEQUENCE_ENA             0x0001  /* DSP2_RW_SEQUENCE_ENA */
+#define WM2200_DSP2_RW_SEQUENCE_ENA_MASK        0x0001  /* DSP2_RW_SEQUENCE_ENA */
+#define WM2200_DSP2_RW_SEQUENCE_ENA_SHIFT            0  /* DSP2_RW_SEQUENCE_ENA */
+#define WM2200_DSP2_RW_SEQUENCE_ENA_WIDTH            1  /* DSP2_RW_SEQUENCE_ENA */
+
+/*
+ * R2818 (0xB02) - DSP2 Control 2
+ */
+#define WM2200_DSP2_PAGE_BASE_PM_0_MASK         0xFF00  /* DSP2_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_PM_0_SHIFT             8  /* DSP2_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_PM_0_WIDTH             8  /* DSP2_PAGE_BASE_PM - [15:8] */
+
+/*
+ * R2819 (0xB03) - DSP2 Control 3
+ */
+#define WM2200_DSP2_PAGE_BASE_DM_0_MASK         0xFF00  /* DSP2_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_DM_0_SHIFT             8  /* DSP2_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_DM_0_WIDTH             8  /* DSP2_PAGE_BASE_DM - [15:8] */
+
+/*
+ * R2820 (0xB04) - DSP2 Control 4
+ */
+#define WM2200_DSP2_PAGE_BASE_ZM_0_MASK         0xFF00  /* DSP2_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_ZM_0_SHIFT             8  /* DSP2_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_ZM_0_WIDTH             8  /* DSP2_PAGE_BASE_ZM - [15:8] */
+
+/*
+ * R2822 (0xB06) - DSP2 Control 5
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_MASK 0x3FFF  /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_SHIFT      0  /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_WIDTH     14  /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2823 (0xB07) - DSP2 Control 6
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_MASK 0x3FFF  /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_SHIFT      0  /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_WIDTH     14  /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2824 (0xB08) - DSP2 Control 7
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_MASK 0x3FFF  /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_SHIFT      0  /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_WIDTH     14  /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2825 (0xB09) - DSP2 Control 8
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_MASK 0x3FFF  /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_SHIFT      0  /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_WIDTH     14  /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2826 (0xB0A) - DSP2 Control 9
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_MASK 0x3FFF  /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_SHIFT      0  /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_WIDTH     14  /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2827 (0xB0B) - DSP2 Control 10
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_MASK 0x3FFF  /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_SHIFT      0  /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_WIDTH     14  /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2828 (0xB0C) - DSP2 Control 11
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_MASK 0x3FFF  /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_SHIFT      0  /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_WIDTH     14  /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+
+/*
+ * R2829 (0xB0D) - DSP2 Control 12
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_MASK 0x3FFF  /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_SHIFT      0  /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_WIDTH     14  /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+
+/*
+ * R2831 (0xB0F) - DSP2 Control 13
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_MASK 0x3FFF  /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_SHIFT      0  /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_WIDTH     14  /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2832 (0xB10) - DSP2 Control 14
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_MASK 0x3FFF  /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_SHIFT      0  /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_WIDTH     14  /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2833 (0xB11) - DSP2 Control 15
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_MASK 0x3FFF  /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_SHIFT      0  /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_WIDTH     14  /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2834 (0xB12) - DSP2 Control 16
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_MASK 0x3FFF  /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_SHIFT      0  /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_WIDTH     14  /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2835 (0xB13) - DSP2 Control 17
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_MASK 0x3FFF  /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_SHIFT      0  /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_WIDTH     14  /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2836 (0xB14) - DSP2 Control 18
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_MASK 0x3FFF  /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_SHIFT      0  /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_WIDTH     14  /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2838 (0xB16) - DSP2 Control 19
+ */
+#define WM2200_DSP2_WDMA_BUFFER_LENGTH_MASK     0x00FF  /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP2_WDMA_BUFFER_LENGTH_SHIFT         0  /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP2_WDMA_BUFFER_LENGTH_WIDTH         8  /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */
+
+/*
+ * R2839 (0xB17) - DSP2 Control 20
+ */
+#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_MASK    0x00FF  /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_SHIFT        0  /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_WIDTH        8  /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */
+
+/*
+ * R2840 (0xB18) - DSP2 Control 21
+ */
+#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_MASK    0x003F  /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_SHIFT        0  /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_WIDTH        6  /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */
+
+/*
+ * R2842 (0xB1A) - DSP2 Control 22
+ */
+#define WM2200_DSP2_DM_SIZE_MASK                0xFFFF  /* DSP2_DM_SIZE - [15:0] */
+#define WM2200_DSP2_DM_SIZE_SHIFT                    0  /* DSP2_DM_SIZE - [15:0] */
+#define WM2200_DSP2_DM_SIZE_WIDTH                   16  /* DSP2_DM_SIZE - [15:0] */
+
+/*
+ * R2843 (0xB1B) - DSP2 Control 23
+ */
+#define WM2200_DSP2_PM_SIZE_MASK                0xFFFF  /* DSP2_PM_SIZE - [15:0] */
+#define WM2200_DSP2_PM_SIZE_SHIFT                    0  /* DSP2_PM_SIZE - [15:0] */
+#define WM2200_DSP2_PM_SIZE_WIDTH                   16  /* DSP2_PM_SIZE - [15:0] */
+
+/*
+ * R2844 (0xB1C) - DSP2 Control 24
+ */
+#define WM2200_DSP2_ZM_SIZE_MASK                0xFFFF  /* DSP2_ZM_SIZE - [15:0] */
+#define WM2200_DSP2_ZM_SIZE_SHIFT                    0  /* DSP2_ZM_SIZE - [15:0] */
+#define WM2200_DSP2_ZM_SIZE_WIDTH                   16  /* DSP2_ZM_SIZE - [15:0] */
+
+/*
+ * R2846 (0xB1E) - DSP2 Control 25
+ */
+#define WM2200_DSP2_PING_FULL                   0x8000  /* DSP2_PING_FULL */
+#define WM2200_DSP2_PING_FULL_MASK              0x8000  /* DSP2_PING_FULL */
+#define WM2200_DSP2_PING_FULL_SHIFT                 15  /* DSP2_PING_FULL */
+#define WM2200_DSP2_PING_FULL_WIDTH                  1  /* DSP2_PING_FULL */
+#define WM2200_DSP2_PONG_FULL                   0x4000  /* DSP2_PONG_FULL */
+#define WM2200_DSP2_PONG_FULL_MASK              0x4000  /* DSP2_PONG_FULL */
+#define WM2200_DSP2_PONG_FULL_SHIFT                 14  /* DSP2_PONG_FULL */
+#define WM2200_DSP2_PONG_FULL_WIDTH                  1  /* DSP2_PONG_FULL */
+#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_MASK   0x00FF  /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_SHIFT       0  /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_WIDTH       8  /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */
+
+/*
+ * R2848 (0xB20) - DSP2 Control 26
+ */
+#define WM2200_DSP2_SCRATCH_0_MASK              0xFFFF  /* DSP2_SCRATCH_0 - [15:0] */
+#define WM2200_DSP2_SCRATCH_0_SHIFT                  0  /* DSP2_SCRATCH_0 - [15:0] */
+#define WM2200_DSP2_SCRATCH_0_WIDTH                 16  /* DSP2_SCRATCH_0 - [15:0] */
+
+/*
+ * R2849 (0xB21) - DSP2 Control 27
+ */
+#define WM2200_DSP2_SCRATCH_1_MASK              0xFFFF  /* DSP2_SCRATCH_1 - [15:0] */
+#define WM2200_DSP2_SCRATCH_1_SHIFT                  0  /* DSP2_SCRATCH_1 - [15:0] */
+#define WM2200_DSP2_SCRATCH_1_WIDTH                 16  /* DSP2_SCRATCH_1 - [15:0] */
+
+/*
+ * R2850 (0xB22) - DSP2 Control 28
+ */
+#define WM2200_DSP2_SCRATCH_2_MASK              0xFFFF  /* DSP2_SCRATCH_2 - [15:0] */
+#define WM2200_DSP2_SCRATCH_2_SHIFT                  0  /* DSP2_SCRATCH_2 - [15:0] */
+#define WM2200_DSP2_SCRATCH_2_WIDTH                 16  /* DSP2_SCRATCH_2 - [15:0] */
+
+/*
+ * R2851 (0xB23) - DSP2 Control 29
+ */
+#define WM2200_DSP2_SCRATCH_3_MASK              0xFFFF  /* DSP2_SCRATCH_3 - [15:0] */
+#define WM2200_DSP2_SCRATCH_3_SHIFT                  0  /* DSP2_SCRATCH_3 - [15:0] */
+#define WM2200_DSP2_SCRATCH_3_WIDTH                 16  /* DSP2_SCRATCH_3 - [15:0] */
+
+/*
+ * R2852 (0xB24) - DSP2 Control 30
+ */
+#define WM2200_DSP2_DBG_CLK_ENA                 0x0008  /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_DBG_CLK_ENA_MASK            0x0008  /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_DBG_CLK_ENA_SHIFT                3  /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_DBG_CLK_ENA_WIDTH                1  /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_SYS_ENA                     0x0004  /* DSP2_SYS_ENA */
+#define WM2200_DSP2_SYS_ENA_MASK                0x0004  /* DSP2_SYS_ENA */
+#define WM2200_DSP2_SYS_ENA_SHIFT                    2  /* DSP2_SYS_ENA */
+#define WM2200_DSP2_SYS_ENA_WIDTH                    1  /* DSP2_SYS_ENA */
+#define WM2200_DSP2_CORE_ENA                    0x0002  /* DSP2_CORE_ENA */
+#define WM2200_DSP2_CORE_ENA_MASK               0x0002  /* DSP2_CORE_ENA */
+#define WM2200_DSP2_CORE_ENA_SHIFT                   1  /* DSP2_CORE_ENA */
+#define WM2200_DSP2_CORE_ENA_WIDTH                   1  /* DSP2_CORE_ENA */
+#define WM2200_DSP2_START                       0x0001  /* DSP2_START */
+#define WM2200_DSP2_START_MASK                  0x0001  /* DSP2_START */
+#define WM2200_DSP2_START_SHIFT                      0  /* DSP2_START */
+#define WM2200_DSP2_START_WIDTH                      1  /* DSP2_START */
+
+/*
+ * R2854 (0xB26) - DSP2 Control 31
+ */
+#define WM2200_DSP2_CLK_RATE_MASK               0x0018  /* DSP2_CLK_RATE - [4:3] */
+#define WM2200_DSP2_CLK_RATE_SHIFT                   3  /* DSP2_CLK_RATE - [4:3] */
+#define WM2200_DSP2_CLK_RATE_WIDTH                   2  /* DSP2_CLK_RATE - [4:3] */
+#define WM2200_DSP2_CLK_AVAIL                   0x0004  /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_AVAIL_MASK              0x0004  /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_AVAIL_SHIFT                  2  /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_AVAIL_WIDTH                  1  /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_REQ_MASK                0x0003  /* DSP2_CLK_REQ - [1:0] */
+#define WM2200_DSP2_CLK_REQ_SHIFT                    0  /* DSP2_CLK_REQ - [1:0] */
+#define WM2200_DSP2_CLK_REQ_WIDTH                    2  /* DSP2_CLK_REQ - [1:0] */
+
+#endif
index 89f2af77b1c3983afaa407e6ff2740ec95e0c068..2339aa0e9453e5eadea52e541901b8292a333c26 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/gcd.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
+#include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/fixed.h>
 #include <linux/slab.h>
@@ -50,13 +51,11 @@ struct wm5100_fll {
 
 /* codec private data */
 struct wm5100_priv {
+       struct device *dev;
        struct regmap *regmap;
        struct snd_soc_codec *codec;
 
        struct regulator_bulk_data core_supplies[WM5100_NUM_CORE_SUPPLIES];
-       struct regulator *cpvdd;
-       struct regulator *dbvdd2;
-       struct regulator *dbvdd3;
 
        int rev;
 
@@ -73,6 +72,7 @@ struct wm5100_priv {
        bool jack_detecting;
        bool jack_mic;
        int jack_mode;
+       int jack_flips;
 
        struct wm5100_fll fll[2];
 
@@ -776,127 +776,48 @@ static int wm5100_out_ev(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
-static int wm5100_cp_ev(struct snd_soc_dapm_widget *w,
-                       struct snd_kcontrol *kcontrol,
-                       int event)
-{
-       struct snd_soc_codec *codec = w->codec;
-       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
-       int ret;
-
-       switch (event) {
-       case SND_SOC_DAPM_PRE_PMU:
-               ret = regulator_enable(wm5100->cpvdd);
-               if (ret != 0) {
-                       dev_err(codec->dev, "Failed to enable CPVDD: %d\n",
-                               ret);
-                       return ret;
-               }
-               return ret;
-
-       case SND_SOC_DAPM_POST_PMD:
-               ret = regulator_disable_deferred(wm5100->cpvdd, 20);
-               if (ret != 0) {
-                       dev_err(codec->dev, "Failed to disable CPVDD: %d\n",
-                               ret);
-                       return ret;
-               }
-               return ret;
-
-       default:
-               BUG();
-               return 0;
-       }
-}
-
-static int wm5100_dbvdd_ev(struct snd_soc_dapm_widget *w,
-                          struct snd_kcontrol *kcontrol,
-                          int event)
-{
-       struct snd_soc_codec *codec = w->codec;
-       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
-       struct regulator *regulator;
-       int ret;
-
-       switch (w->shift) {
-       case 2:
-               regulator = wm5100->dbvdd2;
-               break;
-       case 3:
-               regulator = wm5100->dbvdd3;
-               break;
-       default:
-               BUG();
-               return 0;
-       }
-
-       switch (event) {
-       case SND_SOC_DAPM_PRE_PMU:
-               ret = regulator_enable(regulator);
-               if (ret != 0) {
-                       dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n",
-                               w->shift, ret);
-                       return ret;
-               }
-               return ret;
-
-       case SND_SOC_DAPM_POST_PMD:
-               ret = regulator_disable(regulator);
-               if (ret != 0) {
-                       dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n",
-                               w->shift, ret);
-                       return ret;
-               }
-               return ret;
-
-       default:
-               BUG();
-               return 0;
-       }
-}
-
-static void wm5100_log_status3(struct snd_soc_codec *codec, int val)
+static void wm5100_log_status3(struct wm5100_priv *wm5100, int val)
 {
        if (val & WM5100_SPK_SHUTDOWN_WARN_EINT)
-               dev_crit(codec->dev, "Speaker shutdown warning\n");
+               dev_crit(wm5100->dev, "Speaker shutdown warning\n");
        if (val & WM5100_SPK_SHUTDOWN_EINT)
-               dev_crit(codec->dev, "Speaker shutdown\n");
+               dev_crit(wm5100->dev, "Speaker shutdown\n");
        if (val & WM5100_CLKGEN_ERR_EINT)
-               dev_crit(codec->dev, "SYSCLK underclocked\n");
+               dev_crit(wm5100->dev, "SYSCLK underclocked\n");
        if (val & WM5100_CLKGEN_ERR_ASYNC_EINT)
-               dev_crit(codec->dev, "ASYNCCLK underclocked\n");
+               dev_crit(wm5100->dev, "ASYNCCLK underclocked\n");
 }
 
-static void wm5100_log_status4(struct snd_soc_codec *codec, int val)
+static void wm5100_log_status4(struct wm5100_priv *wm5100, int val)
 {
        if (val & WM5100_AIF3_ERR_EINT)
-               dev_err(codec->dev, "AIF3 configuration error\n");
+               dev_err(wm5100->dev, "AIF3 configuration error\n");
        if (val & WM5100_AIF2_ERR_EINT)
-               dev_err(codec->dev, "AIF2 configuration error\n");
+               dev_err(wm5100->dev, "AIF2 configuration error\n");
        if (val & WM5100_AIF1_ERR_EINT)
-               dev_err(codec->dev, "AIF1 configuration error\n");
+               dev_err(wm5100->dev, "AIF1 configuration error\n");
        if (val & WM5100_CTRLIF_ERR_EINT)
-               dev_err(codec->dev, "Control interface error\n");
+               dev_err(wm5100->dev, "Control interface error\n");
        if (val & WM5100_ISRC2_UNDERCLOCKED_EINT)
-               dev_err(codec->dev, "ISRC2 underclocked\n");
+               dev_err(wm5100->dev, "ISRC2 underclocked\n");
        if (val & WM5100_ISRC1_UNDERCLOCKED_EINT)
-               dev_err(codec->dev, "ISRC1 underclocked\n");
+               dev_err(wm5100->dev, "ISRC1 underclocked\n");
        if (val & WM5100_FX_UNDERCLOCKED_EINT)
-               dev_err(codec->dev, "FX underclocked\n");
+               dev_err(wm5100->dev, "FX underclocked\n");
        if (val & WM5100_AIF3_UNDERCLOCKED_EINT)
-               dev_err(codec->dev, "AIF3 underclocked\n");
+               dev_err(wm5100->dev, "AIF3 underclocked\n");
        if (val & WM5100_AIF2_UNDERCLOCKED_EINT)
-               dev_err(codec->dev, "AIF2 underclocked\n");
+               dev_err(wm5100->dev, "AIF2 underclocked\n");
        if (val & WM5100_AIF1_UNDERCLOCKED_EINT)
-               dev_err(codec->dev, "AIF1 underclocked\n");
+               dev_err(wm5100->dev, "AIF1 underclocked\n");
        if (val & WM5100_ASRC_UNDERCLOCKED_EINT)
-               dev_err(codec->dev, "ASRC underclocked\n");
+               dev_err(wm5100->dev, "ASRC underclocked\n");
        if (val & WM5100_DAC_UNDERCLOCKED_EINT)
-               dev_err(codec->dev, "DAC underclocked\n");
+               dev_err(wm5100->dev, "DAC underclocked\n");
        if (val & WM5100_ADC_UNDERCLOCKED_EINT)
-               dev_err(codec->dev, "ADC underclocked\n");
+               dev_err(wm5100->dev, "ADC underclocked\n");
        if (val & WM5100_MIXER_UNDERCLOCKED_EINT)
-               dev_err(codec->dev, "Mixer underclocked\n");
+               dev_err(wm5100->dev, "Mixer underclocked\n");
 }
 
 static int wm5100_post_ev(struct snd_soc_dapm_widget *w,
@@ -904,16 +825,17 @@ static int wm5100_post_ev(struct snd_soc_dapm_widget *w,
                          int event)
 {
        struct snd_soc_codec *codec = w->codec;
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
        ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_3);
        ret &= WM5100_SPK_SHUTDOWN_WARN_STS |
                WM5100_SPK_SHUTDOWN_STS | WM5100_CLKGEN_ERR_STS |
                WM5100_CLKGEN_ERR_ASYNC_STS;
-       wm5100_log_status3(codec, ret);
+       wm5100_log_status3(wm5100, ret);
 
        ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_4);
-       wm5100_log_status4(codec, ret);
+       wm5100_log_status4(wm5100, ret);
 
        return 0;
 }
@@ -924,18 +846,16 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", WM5100_CLOCKING_3, WM5100_SYSCLK_ENA_SHIFT, 0,
 SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT,
                    0, NULL, 0),
 
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
+SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0),
+
 SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0,
-                   wm5100_cp_ev,
-                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+                   NULL, 0),
 SND_SOC_DAPM_SUPPLY("CP2", WM5100_MIC_CHARGE_PUMP_1, WM5100_CP2_ENA_SHIFT, 0,
                    NULL, 0),
 SND_SOC_DAPM_SUPPLY("CP2 Active", WM5100_MIC_CHARGE_PUMP_1,
-                   WM5100_CP2_BYPASS_SHIFT, 1, wm5100_cp_ev,
-                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-SND_SOC_DAPM_SUPPLY("DBVDD2", SND_SOC_NOPM, 2, 0, wm5100_dbvdd_ev,
-                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-SND_SOC_DAPM_SUPPLY("DBVDD3", SND_SOC_NOPM, 3, 0, wm5100_dbvdd_ev,
-                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+                   WM5100_CP2_BYPASS_SHIFT, 1, NULL, 0),
 
 SND_SOC_DAPM_SUPPLY("MICBIAS1", WM5100_MIC_BIAS_CTRL_1, WM5100_MICB1_ENA_SHIFT,
                    0, NULL, 0),
@@ -1146,6 +1066,9 @@ SND_SOC_DAPM_POST("Post", wm5100_post_ev),
 };
 
 static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
+       { "CP1", NULL, "CPVDD" },
+       { "CP2 Active", NULL, "CPVDD" },
+
        { "IN1L", NULL, "SYSCLK" },
        { "IN1R", NULL, "SYSCLK" },
        { "IN2L", NULL, "SYSCLK" },
@@ -1308,10 +1231,7 @@ static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
        { "PWM2", NULL, "PWM2 Driver" },
 };
 
-static struct {
-       int reg;
-       int val;
-} wm5100_reva_patches[] = {
+static const __devinitdata struct reg_default wm5100_reva_patches[] = {
        { WM5100_AUDIO_IF_1_10, 0 },
        { WM5100_AUDIO_IF_1_11, 1 },
        { WM5100_AUDIO_IF_1_12, 2 },
@@ -1343,80 +1263,6 @@ static struct {
        { WM5100_AUDIO_IF_3_19, 1 },
 };
 
-static int wm5100_set_bias_level(struct snd_soc_codec *codec,
-                                enum snd_soc_bias_level level)
-{
-       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
-       int ret, i;
-
-       switch (level) {
-       case SND_SOC_BIAS_ON:
-               break;
-
-       case SND_SOC_BIAS_PREPARE:
-               break;
-
-       case SND_SOC_BIAS_STANDBY:
-               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-                       ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
-                                                   wm5100->core_supplies);
-                       if (ret != 0) {
-                               dev_err(codec->dev,
-                                       "Failed to enable supplies: %d\n",
-                                       ret);
-                               return ret;
-                       }
-
-                       if (wm5100->pdata.ldo_ena) {
-                               gpio_set_value_cansleep(wm5100->pdata.ldo_ena,
-                                                       1);
-                               msleep(2);
-                       }
-
-                       regcache_cache_only(wm5100->regmap, false);
-
-                       switch (wm5100->rev) {
-                       case 0:
-                               regcache_cache_bypass(wm5100->regmap, true);
-                               snd_soc_write(codec, 0x11, 0x3);
-                               snd_soc_write(codec, 0x203, 0xc);
-                               snd_soc_write(codec, 0x206, 0);
-                               snd_soc_write(codec, 0x207, 0xf0);
-                               snd_soc_write(codec, 0x208, 0x3c);
-                               snd_soc_write(codec, 0x209, 0);
-                               snd_soc_write(codec, 0x211, 0x20d8);
-                               snd_soc_write(codec, 0x11, 0);
-
-                               for (i = 0;
-                                    i < ARRAY_SIZE(wm5100_reva_patches);
-                                    i++)
-                                       snd_soc_write(codec,
-                                                     wm5100_reva_patches[i].reg,
-                                                     wm5100_reva_patches[i].val);
-                               regcache_cache_bypass(wm5100->regmap, false);
-                               break;
-                       default:
-                               break;
-                       }
-
-                       regcache_sync(wm5100->regmap);
-               }
-               break;
-
-       case SND_SOC_BIAS_OFF:
-               regcache_cache_only(wm5100->regmap, true);
-               regcache_mark_dirty(wm5100->regmap);
-               if (wm5100->pdata.ldo_ena)
-                       gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
-               regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
-                                      wm5100->core_supplies);
-               break;
-       }
-       codec->dapm.bias_level = level;
-
-       return 0;
-}
-
 static int wm5100_dai_to_base(struct snd_soc_dai *dai)
 {
        switch (dai->id) {
@@ -1944,6 +1790,8 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 
        if (!Fout) {
                dev_dbg(codec->dev, "FLL%d disabled", fll_id);
+               if (fll->fout)
+                       pm_runtime_put(codec->dev);
                fll->fout = 0;
                snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0);
                return 0;
@@ -1988,6 +1836,8 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
        /* Clear any pending completions */
        try_wait_for_completion(&fll->lock);
 
+       pm_runtime_get_sync(codec->dev);
+
        snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, WM5100_FLL1_ENA);
 
        if (i2c->irq)
@@ -2022,6 +1872,7 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
        }
        if (i == timeout) {
                dev_err(codec->dev, "FLL%d lock timed out\n", fll_id);
+               pm_runtime_put(codec->dev);
                return -ETIMEDOUT;
        }
 
@@ -2124,55 +1975,73 @@ static int wm5100_dig_vu[] = {
        WM5100_DAC_DIGITAL_VOLUME_6R,
 };
 
-static void wm5100_set_detect_mode(struct snd_soc_codec *codec, int the_mode)
+static void wm5100_set_detect_mode(struct wm5100_priv *wm5100, int the_mode)
 {
-       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
        struct wm5100_jack_mode *mode = &wm5100->pdata.jack_modes[the_mode];
 
        BUG_ON(the_mode >= ARRAY_SIZE(wm5100->pdata.jack_modes));
 
        gpio_set_value_cansleep(wm5100->pdata.hp_pol, mode->hp_pol);
-       snd_soc_update_bits(codec, WM5100_ACCESSORY_DETECT_MODE_1,
-                           WM5100_ACCDET_BIAS_SRC_MASK |
-                           WM5100_ACCDET_SRC,
-                           (mode->bias << WM5100_ACCDET_BIAS_SRC_SHIFT) |
-                           mode->micd_src << WM5100_ACCDET_SRC_SHIFT);
-       snd_soc_update_bits(codec, WM5100_MISC_CONTROL,
-                           WM5100_HPCOM_SRC,
-                           mode->micd_src << WM5100_HPCOM_SRC_SHIFT);
+       regmap_update_bits(wm5100->regmap, WM5100_ACCESSORY_DETECT_MODE_1,
+                          WM5100_ACCDET_BIAS_SRC_MASK |
+                          WM5100_ACCDET_SRC,
+                          (mode->bias << WM5100_ACCDET_BIAS_SRC_SHIFT) |
+                          mode->micd_src << WM5100_ACCDET_SRC_SHIFT);
+       regmap_update_bits(wm5100->regmap, WM5100_MISC_CONTROL,
+                          WM5100_HPCOM_SRC,
+                          mode->micd_src << WM5100_HPCOM_SRC_SHIFT);
 
        wm5100->jack_mode = the_mode;
 
-       dev_dbg(codec->dev, "Set microphone polarity to %d\n",
+       dev_dbg(wm5100->dev, "Set microphone polarity to %d\n",
                wm5100->jack_mode);
 }
 
-static void wm5100_micd_irq(struct snd_soc_codec *codec)
+static void wm5100_report_headphone(struct wm5100_priv *wm5100)
 {
-       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
-       int val;
+       dev_dbg(wm5100->dev, "Headphone detected\n");
+       wm5100->jack_detecting = false;
+       snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,
+                           SND_JACK_HEADPHONE);
+
+       /* Increase the detection rate a bit for responsiveness. */
+       regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
+                          WM5100_ACCDET_RATE_MASK,
+                          7 << WM5100_ACCDET_RATE_SHIFT);
+}
 
-       val = snd_soc_read(codec, WM5100_MIC_DETECT_3);
+static void wm5100_micd_irq(struct wm5100_priv *wm5100)
+{
+       unsigned int val;
+       int ret;
 
-       dev_dbg(codec->dev, "Microphone event: %x\n", val);
+       ret = regmap_read(wm5100->regmap, WM5100_MIC_DETECT_3, &val);
+       if (ret != 0) {
+               dev_err(wm5100->dev, "Failed to read micropone status: %d\n",
+                       ret);
+               return;
+       }
+
+       dev_dbg(wm5100->dev, "Microphone event: %x\n", val);
 
        if (!(val & WM5100_ACCDET_VALID)) {
-               dev_warn(codec->dev, "Microphone detection state invalid\n");
+               dev_warn(wm5100->dev, "Microphone detection state invalid\n");
                return;
        }
 
        /* No accessory, reset everything and report removal */
        if (!(val & WM5100_ACCDET_STS)) {
-               dev_dbg(codec->dev, "Jack removal detected\n");
+               dev_dbg(wm5100->dev, "Jack removal detected\n");
                wm5100->jack_mic = false;
                wm5100->jack_detecting = true;
+               wm5100->jack_flips = 0;
                snd_soc_jack_report(wm5100->jack, 0,
                                    SND_JACK_LINEOUT | SND_JACK_HEADSET |
                                    SND_JACK_BTN_0);
 
-               snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
-                                   WM5100_ACCDET_RATE_MASK,
-                                   WM5100_ACCDET_RATE_MASK);
+               regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
+                                  WM5100_ACCDET_RATE_MASK,
+                                  WM5100_ACCDET_RATE_MASK);
                return;
        }
 
@@ -2182,7 +2051,7 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
         */
        if (val & 0x400) {
                if (wm5100->jack_detecting) {
-                       dev_dbg(codec->dev, "Microphone detected\n");
+                       dev_dbg(wm5100->dev, "Microphone detected\n");
                        wm5100->jack_mic = true;
                        wm5100->jack_detecting = false;
                        snd_soc_jack_report(wm5100->jack,
@@ -2191,11 +2060,11 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
 
                        /* Increase poll rate to give better responsiveness
                         * for buttons */
-                       snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
-                                           WM5100_ACCDET_RATE_MASK,
-                                           5 << WM5100_ACCDET_RATE_SHIFT);
+                       regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
+                                          WM5100_ACCDET_RATE_MASK,
+                                          5 << WM5100_ACCDET_RATE_SHIFT);
                } else {
-                       dev_dbg(codec->dev, "Mic button up\n");
+                       dev_dbg(wm5100->dev, "Mic button up\n");
                        snd_soc_jack_report(wm5100->jack, 0, SND_JACK_BTN_0);
                }
 
@@ -2205,10 +2074,16 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
        /* If we detected a lower impedence during initial startup
         * then we probably have the wrong polarity, flip it.  Don't
         * do this for the lowest impedences to speed up detection of
-        * plain headphones.
+        * plain headphones and give up if neither polarity looks
+        * sensible.
         */
        if (wm5100->jack_detecting && (val & 0x3f8)) {
-               wm5100_set_detect_mode(codec, !wm5100->jack_mode);
+               wm5100->jack_flips++;
+
+               if (wm5100->jack_flips > 1)
+                       wm5100_report_headphone(wm5100);
+               else
+                       wm5100_set_detect_mode(wm5100, !wm5100->jack_mode);
 
                return;
        }
@@ -2218,21 +2093,11 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)
         */
        if (val & 0x3fc) {
                if (wm5100->jack_mic) {
-                       dev_dbg(codec->dev, "Mic button detected\n");
+                       dev_dbg(wm5100->dev, "Mic button detected\n");
                        snd_soc_jack_report(wm5100->jack, SND_JACK_BTN_0,
                                            SND_JACK_BTN_0);
                } else if (wm5100->jack_detecting) {
-                       dev_dbg(codec->dev, "Headphone detected\n");
-                       wm5100->jack_detecting = false;
-                       snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,
-                                           SND_JACK_HEADPHONE);
-
-                       /* Increase the detection rate a bit for
-                        * responsiveness.
-                        */
-                       snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
-                                           WM5100_ACCDET_RATE_MASK,
-                                           7 << WM5100_ACCDET_RATE_SHIFT);
+                       wm5100_report_headphone(wm5100);
                }
        }
 }
@@ -2244,8 +2109,9 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
        if (jack) {
                wm5100->jack = jack;
                wm5100->jack_detecting = true;
+               wm5100->jack_flips = 0;
 
-               wm5100_set_detect_mode(codec, 0);
+               wm5100_set_detect_mode(wm5100, 0);
 
                /* Slowest detection rate, gives debounce for initial
                 * detection */
@@ -2284,52 +2150,70 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
 
 static irqreturn_t wm5100_irq(int irq, void *data)
 {
-       struct snd_soc_codec *codec = data;
-       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       struct wm5100_priv *wm5100 = data;
        irqreturn_t status = IRQ_NONE;
-       int irq_val;
+       unsigned int irq_val, mask_val;
+       int ret;
 
-       irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3);
-       if (irq_val < 0) {
-               dev_err(codec->dev, "Failed to read IRQ status 3: %d\n",
-                       irq_val);
+       ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_3, &irq_val);
+       if (ret < 0) {
+               dev_err(wm5100->dev, "Failed to read IRQ status 3: %d\n",
+                       ret);
                irq_val = 0;
        }
-       irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3_MASK);
 
-       snd_soc_write(codec, WM5100_INTERRUPT_STATUS_3, irq_val);
+       ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_3_MASK,
+                         &mask_val);
+       if (ret < 0) {
+               dev_err(wm5100->dev, "Failed to read IRQ mask 3: %d\n",
+                       ret);
+               mask_val = 0xffff;
+       }
+
+       irq_val &= ~mask_val;
+
+       regmap_write(wm5100->regmap, WM5100_INTERRUPT_STATUS_3, irq_val);
 
        if (irq_val)
                status = IRQ_HANDLED;
 
-       wm5100_log_status3(codec, irq_val);
+       wm5100_log_status3(wm5100, irq_val);
 
        if (irq_val & WM5100_FLL1_LOCK_EINT) {
-               dev_dbg(codec->dev, "FLL1 locked\n");
+               dev_dbg(wm5100->dev, "FLL1 locked\n");
                complete(&wm5100->fll[0].lock);
        }
        if (irq_val & WM5100_FLL2_LOCK_EINT) {
-               dev_dbg(codec->dev, "FLL2 locked\n");
+               dev_dbg(wm5100->dev, "FLL2 locked\n");
                complete(&wm5100->fll[1].lock);
        }
 
        if (irq_val & WM5100_ACCDET_EINT)
-               wm5100_micd_irq(codec);
+               wm5100_micd_irq(wm5100);
 
-       irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4);
-       if (irq_val < 0) {
-               dev_err(codec->dev, "Failed to read IRQ status 4: %d\n",
-                       irq_val);
+       ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_4, &irq_val);
+       if (ret < 0) {
+               dev_err(wm5100->dev, "Failed to read IRQ status 4: %d\n",
+                       ret);
                irq_val = 0;
        }
-       irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4_MASK);
+
+       ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_4_MASK,
+                         &mask_val);
+       if (ret < 0) {
+               dev_err(wm5100->dev, "Failed to read IRQ mask 4: %d\n",
+                       ret);
+               mask_val = 0xffff;
+       }
+
+       irq_val &= ~mask_val;
 
        if (irq_val)
                status = IRQ_HANDLED;
 
-       snd_soc_write(codec, WM5100_INTERRUPT_STATUS_4, irq_val);
+       regmap_write(wm5100->regmap, WM5100_INTERRUPT_STATUS_4, irq_val);
 
-       wm5100_log_status4(codec, irq_val);
+       wm5100_log_status4(wm5100, irq_val);
 
        return status;
 }
@@ -2454,7 +2338,7 @@ static int wm5100_probe(struct snd_soc_codec *codec)
 {
        struct i2c_client *i2c = to_i2c_client(codec->dev);
        struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
-       int ret, i, irq_flags;
+       int ret, i;
 
        wm5100->codec = codec;
        codec->control_data = wm5100->regmap;
@@ -2465,9 +2349,6 @@ static int wm5100_probe(struct snd_soc_codec *codec)
                return ret;
        }
 
-       regcache_cache_only(wm5100->regmap, true);
-
-
        for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++)
                snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU,
                                    WM5100_OUT_VU);
@@ -2478,60 +2359,10 @@ static int wm5100_probe(struct snd_soc_codec *codec)
 
        /* TODO: check if we're symmetric */
 
-       if (i2c->irq) {
-               if (wm5100->pdata.irq_flags)
-                       irq_flags = wm5100->pdata.irq_flags;
-               else
-                       irq_flags = IRQF_TRIGGER_LOW;
-
-               irq_flags |= IRQF_ONESHOT;
-
-               if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
-                       ret = request_threaded_irq(i2c->irq, NULL,
-                                                  wm5100_edge_irq,
-                                                  irq_flags, "wm5100", codec);
-               else
-                       ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq,
-                                                  irq_flags, "wm5100", codec);
-
-               if (ret != 0) {
-                       dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
-                               i2c->irq, ret);
-               } else {
-                       /* Enable default interrupts */
-                       snd_soc_update_bits(codec,
-                                           WM5100_INTERRUPT_STATUS_3_MASK,
-                                           WM5100_IM_SPK_SHUTDOWN_WARN_EINT |
-                                           WM5100_IM_SPK_SHUTDOWN_EINT |
-                                           WM5100_IM_ASRC2_LOCK_EINT |
-                                           WM5100_IM_ASRC1_LOCK_EINT |
-                                           WM5100_IM_FLL2_LOCK_EINT |
-                                           WM5100_IM_FLL1_LOCK_EINT |
-                                           WM5100_CLKGEN_ERR_EINT |
-                                           WM5100_CLKGEN_ERR_ASYNC_EINT, 0);
-
-                       snd_soc_update_bits(codec,
-                                           WM5100_INTERRUPT_STATUS_4_MASK,
-                                           WM5100_AIF3_ERR_EINT |
-                                           WM5100_AIF2_ERR_EINT |
-                                           WM5100_AIF1_ERR_EINT |
-                                           WM5100_CTRLIF_ERR_EINT |
-                                           WM5100_ISRC2_UNDERCLOCKED_EINT |
-                                           WM5100_ISRC1_UNDERCLOCKED_EINT |
-                                           WM5100_FX_UNDERCLOCKED_EINT |
-                                           WM5100_AIF3_UNDERCLOCKED_EINT |
-                                           WM5100_AIF2_UNDERCLOCKED_EINT |
-                                           WM5100_AIF1_UNDERCLOCKED_EINT |
-                                           WM5100_ASRC_UNDERCLOCKED_EINT |
-                                           WM5100_DAC_UNDERCLOCKED_EINT |
-                                           WM5100_ADC_UNDERCLOCKED_EINT |
-                                           WM5100_MIXER_UNDERCLOCKED_EINT, 0);
-               }
-       } else {
+       if (i2c->irq)
                snd_soc_dapm_new_controls(&codec->dapm,
                                          wm5100_dapm_widgets_noirq,
                                          ARRAY_SIZE(wm5100_dapm_widgets_noirq));
-       }
 
        if (wm5100->pdata.hp_pol) {
                ret = gpio_request_one(wm5100->pdata.hp_pol,
@@ -2543,19 +2374,9 @@ static int wm5100_probe(struct snd_soc_codec *codec)
                }
        }
 
-       /* We'll get woken up again when the system has something useful
-        * for us to do.
-        */
-       if (wm5100->pdata.ldo_ena)
-               gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
-       regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
-                              wm5100->core_supplies);
-
        return 0;
 
 err_gpio:
-       if (i2c->irq)
-               free_irq(i2c->irq, codec);
 
        return ret;
 }
@@ -2563,14 +2384,11 @@ err_gpio:
 static int wm5100_remove(struct snd_soc_codec *codec)
 {
        struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
-       struct i2c_client *i2c = to_i2c_client(codec->dev);
 
-       wm5100_set_bias_level(codec, SND_SOC_BIAS_OFF);
        if (wm5100->pdata.hp_pol) {
                gpio_free(wm5100->pdata.hp_pol);
        }
-       if (i2c->irq)
-               free_irq(i2c->irq, codec);
+
        return 0;
 }
 
@@ -2587,7 +2405,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5100 = {
 
        .set_sysclk = wm5100_set_sysclk,
        .set_pll = wm5100_set_fll,
-       .set_bias_level = wm5100_set_bias_level,
        .idle_bias_off = 1,
        .reg_cache_size = WM5100_MAX_REGISTER,
        .volatile_register = wm5100_soc_volatile,
@@ -2626,13 +2443,15 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
        struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev);
        struct wm5100_priv *wm5100;
        unsigned int reg;
-       int ret, i;
+       int ret, i, irq_flags;
 
        wm5100 = devm_kzalloc(&i2c->dev, sizeof(struct wm5100_priv),
                              GFP_KERNEL);
        if (wm5100 == NULL)
                return -ENOMEM;
 
+       wm5100->dev = &i2c->dev;
+
        wm5100->regmap = regmap_init_i2c(i2c, &wm5100_regmap);
        if (IS_ERR(wm5100->regmap)) {
                ret = PTR_ERR(wm5100->regmap);
@@ -2652,41 +2471,21 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
        for (i = 0; i < ARRAY_SIZE(wm5100->core_supplies); i++)
                wm5100->core_supplies[i].supply = wm5100_core_supply_names[i];
 
-       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm5100->core_supplies),
-                                wm5100->core_supplies);
+       ret = devm_regulator_bulk_get(&i2c->dev,
+                                     ARRAY_SIZE(wm5100->core_supplies),
+                                     wm5100->core_supplies);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
                        ret);
                goto err_regmap;
        }
 
-       wm5100->cpvdd = regulator_get(&i2c->dev, "CPVDD");
-       if (IS_ERR(wm5100->cpvdd)) {
-               ret = PTR_ERR(wm5100->cpvdd);
-               dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret);
-               goto err_core;
-       }
-
-       wm5100->dbvdd2 = regulator_get(&i2c->dev, "DBVDD2");
-       if (IS_ERR(wm5100->dbvdd2)) {
-               ret = PTR_ERR(wm5100->dbvdd2);
-               dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret);
-               goto err_cpvdd;
-       }
-
-       wm5100->dbvdd3 = regulator_get(&i2c->dev, "DBVDD3");
-       if (IS_ERR(wm5100->dbvdd3)) {
-               ret = PTR_ERR(wm5100->dbvdd3);
-               dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret);
-               goto err_dbvdd2;
-       }
-
        ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
                                    wm5100->core_supplies);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
                        ret);
-               goto err_dbvdd3;
+               goto err_regmap;
        }
 
        if (wm5100->pdata.ldo_ena) {
@@ -2712,7 +2511,7 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
 
        ret = regmap_read(wm5100->regmap, WM5100_SOFTWARE_RESET, &reg);
        if (ret < 0) {
-               dev_err(&i2c->dev, "Failed to read ID register\n");
+               dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
                goto err_reset;
        }
        switch (reg) {
@@ -2741,6 +2540,22 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
                goto err_reset;
        }
 
+       switch (wm5100->rev) {
+       case 0:
+               ret = regmap_register_patch(wm5100->regmap,
+                                           wm5100_reva_patches,
+                                           ARRAY_SIZE(wm5100_reva_patches));
+               if (ret != 0) {
+                       dev_err(&i2c->dev, "Failed to register patches: %d\n",
+                               ret);
+                       goto err_reset;
+               }
+               break;
+       default:
+               break;
+       }
+
+
        wm5100_init_gpio(i2c);
 
        for (i = 0; i < ARRAY_SIZE(wm5100->pdata.gpio_defaults); i++) {
@@ -2761,6 +2576,62 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
                                    WM5100_IN1_DMIC_SUP_SHIFT));
        }
 
+       if (i2c->irq) {
+               if (wm5100->pdata.irq_flags)
+                       irq_flags = wm5100->pdata.irq_flags;
+               else
+                       irq_flags = IRQF_TRIGGER_LOW;
+
+               irq_flags |= IRQF_ONESHOT;
+
+               if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
+                       ret = request_threaded_irq(i2c->irq, NULL,
+                                                  wm5100_edge_irq, irq_flags,
+                                                  "wm5100", wm5100);
+               else
+                       ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq,
+                                                  irq_flags, "wm5100",
+                                                  wm5100);
+
+               if (ret != 0) {
+                       dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
+                               i2c->irq, ret);
+               } else {
+                       /* Enable default interrupts */
+                       regmap_update_bits(wm5100->regmap,
+                                          WM5100_INTERRUPT_STATUS_3_MASK,
+                                          WM5100_IM_SPK_SHUTDOWN_WARN_EINT |
+                                          WM5100_IM_SPK_SHUTDOWN_EINT |
+                                          WM5100_IM_ASRC2_LOCK_EINT |
+                                          WM5100_IM_ASRC1_LOCK_EINT |
+                                          WM5100_IM_FLL2_LOCK_EINT |
+                                          WM5100_IM_FLL1_LOCK_EINT |
+                                          WM5100_CLKGEN_ERR_EINT |
+                                          WM5100_CLKGEN_ERR_ASYNC_EINT, 0);
+
+                       regmap_update_bits(wm5100->regmap,
+                                          WM5100_INTERRUPT_STATUS_4_MASK,
+                                          WM5100_AIF3_ERR_EINT |
+                                          WM5100_AIF2_ERR_EINT |
+                                          WM5100_AIF1_ERR_EINT |
+                                          WM5100_CTRLIF_ERR_EINT |
+                                          WM5100_ISRC2_UNDERCLOCKED_EINT |
+                                          WM5100_ISRC1_UNDERCLOCKED_EINT |
+                                          WM5100_FX_UNDERCLOCKED_EINT |
+                                          WM5100_AIF3_UNDERCLOCKED_EINT |
+                                          WM5100_AIF2_UNDERCLOCKED_EINT |
+                                          WM5100_AIF1_UNDERCLOCKED_EINT |
+                                          WM5100_ASRC_UNDERCLOCKED_EINT |
+                                          WM5100_DAC_UNDERCLOCKED_EINT |
+                                          WM5100_ADC_UNDERCLOCKED_EINT |
+                                          WM5100_MIXER_UNDERCLOCKED_EINT, 0);
+               }
+       }
+
+       pm_runtime_set_active(&i2c->dev);
+       pm_runtime_enable(&i2c->dev);
+       pm_request_idle(&i2c->dev);
+
        ret = snd_soc_register_codec(&i2c->dev,
                                     &soc_codec_dev_wm5100, wm5100_dai,
                                     ARRAY_SIZE(wm5100_dai));
@@ -2772,9 +2643,11 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
        return ret;
 
 err_reset:
+       if (i2c->irq)
+               free_irq(i2c->irq, wm5100);
        wm5100_free_gpio(i2c);
        if (wm5100->pdata.reset) {
-               gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+               gpio_set_value_cansleep(wm5100->pdata.reset, 0);
                gpio_free(wm5100->pdata.reset);
        }
 err_ldo:
@@ -2785,45 +2658,78 @@ err_ldo:
 err_enable:
        regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
                               wm5100->core_supplies);
-err_dbvdd3:
-       regulator_put(wm5100->dbvdd3);
-err_dbvdd2:
-       regulator_put(wm5100->dbvdd2);
-err_cpvdd:
-       regulator_put(wm5100->cpvdd);
-err_core:
-       regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
-                           wm5100->core_supplies);
 err_regmap:
        regmap_exit(wm5100->regmap);
 err:
        return ret;
 }
 
-static __devexit int wm5100_i2c_remove(struct i2c_client *client)
+static __devexit int wm5100_i2c_remove(struct i2c_client *i2c)
 {
-       struct wm5100_priv *wm5100 = i2c_get_clientdata(client);
+       struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
 
-       snd_soc_unregister_codec(&client->dev);
-       wm5100_free_gpio(client);
+       snd_soc_unregister_codec(&i2c->dev);
+       if (i2c->irq)
+               free_irq(i2c->irq, wm5100);
+       wm5100_free_gpio(i2c);
        if (wm5100->pdata.reset) {
-               gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+               gpio_set_value_cansleep(wm5100->pdata.reset, 0);
                gpio_free(wm5100->pdata.reset);
        }
        if (wm5100->pdata.ldo_ena) {
                gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
                gpio_free(wm5100->pdata.ldo_ena);
        }
-       regulator_put(wm5100->dbvdd3);
-       regulator_put(wm5100->dbvdd2);
-       regulator_put(wm5100->cpvdd);
-       regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
-                           wm5100->core_supplies);
        regmap_exit(wm5100->regmap);
 
        return 0;
 }
 
+#ifdef CONFIG_PM_RUNTIME
+static int wm5100_runtime_suspend(struct device *dev)
+{
+       struct wm5100_priv *wm5100 = dev_get_drvdata(dev);
+
+       regcache_cache_only(wm5100->regmap, true);
+       regcache_mark_dirty(wm5100->regmap);
+       if (wm5100->pdata.ldo_ena)
+               gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+       regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
+                              wm5100->core_supplies);
+
+       return 0;
+}
+
+static int wm5100_runtime_resume(struct device *dev)
+{
+       struct wm5100_priv *wm5100 = dev_get_drvdata(dev);
+       int ret;
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
+                                   wm5100->core_supplies);
+       if (ret != 0) {
+               dev_err(dev, "Failed to enable supplies: %d\n",
+                       ret);
+               return ret;
+       }
+
+       if (wm5100->pdata.ldo_ena) {
+               gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 1);
+               msleep(2);
+       }
+
+       regcache_cache_only(wm5100->regmap, false);
+       regcache_sync(wm5100->regmap);
+
+       return 0;
+}
+#endif
+
+static struct dev_pm_ops wm5100_pm = {
+       SET_RUNTIME_PM_OPS(wm5100_runtime_suspend, wm5100_runtime_resume,
+                          NULL)
+};
+
 static const struct i2c_device_id wm5100_i2c_id[] = {
        { "wm5100", 0 },
        { }
@@ -2834,6 +2740,7 @@ static struct i2c_driver wm5100_i2c_driver = {
        .driver = {
                .name = "wm5100",
                .owner = THIS_MODULE,
+               .pm = &wm5100_pm,
        },
        .probe =    wm5100_i2c_probe,
        .remove =   __devexit_p(wm5100_i2c_remove),
index 8821af70e660b354e4672a5aa7c32fa5fd7fd3f9..a32caa72bd7d727e4e94737e50650d647da1e2db 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 #include <linux/of_device.h>
@@ -41,7 +42,7 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
 
 /* codec private data */
 struct wm8731_priv {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
        struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
        unsigned int sysclk;
        int sysclk_type;
@@ -52,16 +53,30 @@ struct wm8731_priv {
 
 /*
  * wm8731 register cache
- * We can't read the WM8731 register space when we are
- * using 2 wire for device control, so we cache them instead.
- * There is no point in caching the reset register
  */
-static const u16 wm8731_reg[WM8731_CACHEREGNUM] = {
-       0x0097, 0x0097, 0x0079, 0x0079,
-       0x000a, 0x0008, 0x009f, 0x000a,
-       0x0000, 0x0000
+static const struct reg_default wm8731_reg_defaults[] = {
+       { 0, 0x0097 },
+       { 1, 0x0097 },
+       { 2, 0x0079 },
+       { 3, 0x0079 },
+       { 4, 0x000a },
+       { 5, 0x0008 },
+       { 6, 0x009f },
+       { 7, 0x000a },
+       { 8, 0x0000 },
+       { 9, 0x0000 },
 };
 
+static bool wm8731_volatile(struct device *dev, unsigned int reg)
+{
+       return reg == WM8731_RESET;
+}
+
+static bool wm8731_writeable(struct device *dev, unsigned int reg)
+{
+       return reg <= WM8731_RESET;
+}
+
 #define wm8731_reset(c)        snd_soc_write(c, WM8731_RESET, 0)
 
 static const char *wm8731_input_select[] = {"Line In", "Mic"};
@@ -441,7 +456,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
                        if (ret != 0)
                                return ret;
 
-                       snd_soc_cache_sync(codec);
+                       regcache_sync(wm8731->regmap);
                }
 
                /* Clear PWROFF, gate CLKOUT, everything else as-is */
@@ -452,7 +467,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
                snd_soc_write(codec, WM8731_PWR, 0xffff);
                regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
                                       wm8731->supplies);
-               codec->cache_sync = 1;
+               regcache_mark_dirty(wm8731->regmap);
                break;
        }
        codec->dapm.bias_level = level;
@@ -513,7 +528,8 @@ static int wm8731_probe(struct snd_soc_codec *codec)
        struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
        int ret = 0, i;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8731->control_type);
+       codec->control_data = wm8731->regmap;
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
@@ -585,9 +601,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8731 = {
        .suspend =      wm8731_suspend,
        .resume =       wm8731_resume,
        .set_bias_level = wm8731_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8731_reg),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8731_reg,
        .dapm_widgets = wm8731_dapm_widgets,
        .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets),
        .dapm_routes = wm8731_intercon,
@@ -603,6 +616,19 @@ static const struct of_device_id wm8731_of_match[] = {
 
 MODULE_DEVICE_TABLE(of, wm8731_of_match);
 
+static const struct regmap_config wm8731_regmap = {
+       .reg_bits = 7,
+       .val_bits = 9,
+
+       .max_register = WM8731_RESET,
+       .volatile_reg = wm8731_volatile,
+       .writeable_reg = wm8731_writeable,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = wm8731_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8731_reg_defaults),
+};
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8731_spi_probe(struct spi_device *spi)
 {
@@ -613,20 +639,39 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi)
        if (wm8731 == NULL)
                return -ENOMEM;
 
-       wm8731->control_type = SND_SOC_SPI;
+       wm8731->regmap = regmap_init_spi(spi, &wm8731_regmap);
+       if (IS_ERR(wm8731->regmap)) {
+               ret = PTR_ERR(wm8731->regmap);
+               dev_err(&spi->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               goto err;
+       }
+
        spi_set_drvdata(spi, wm8731);
 
        ret = snd_soc_register_codec(&spi->dev,
                        &soc_codec_dev_wm8731, &wm8731_dai, 1);
-       if (ret < 0)
-               kfree(wm8731);
+       if (ret != 0) {
+               dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret);
+               goto err_regmap;
+       }
+
+       return 0;
+
+err_regmap:
+       regmap_exit(wm8731->regmap);
+err:
+       kfree(wm8731);
        return ret;
 }
 
 static int __devexit wm8731_spi_remove(struct spi_device *spi)
 {
+       struct wm8731_priv *wm8731 = spi_get_drvdata(spi);
+
        snd_soc_unregister_codec(&spi->dev);
-       kfree(spi_get_drvdata(spi));
+       regmap_exit(wm8731->regmap);
+       kfree(wm8731);
        return 0;
 }
 
@@ -652,20 +697,38 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
        if (wm8731 == NULL)
                return -ENOMEM;
 
+       wm8731->regmap = regmap_init_i2c(i2c, &wm8731_regmap);
+       if (IS_ERR(wm8731->regmap)) {
+               ret = PTR_ERR(wm8731->regmap);
+               dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               goto err;
+       }
+
        i2c_set_clientdata(i2c, wm8731);
-       wm8731->control_type = SND_SOC_I2C;
 
-       ret =  snd_soc_register_codec(&i2c->dev,
+       ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8731, &wm8731_dai, 1);
-       if (ret < 0)
-               kfree(wm8731);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+               goto err_regmap;
+       }
+
+       return 0;
+
+err_regmap:
+       regmap_exit(wm8731->regmap);
+err:
+       kfree(wm8731);
        return ret;
 }
 
 static __devexit int wm8731_i2c_remove(struct i2c_client *client)
 {
+       struct wm8731_priv *wm8731 = i2c_get_clientdata(client);
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+       regmap_exit(wm8731->regmap);
+       kfree(wm8731);
        return 0;
 }
 
index ff95e62c56b9a7ae211c3f2d508d9cff94132931..4fe9d191e2774ab7fad2e00a5ba7542b51580669 100644 (file)
@@ -599,7 +599,7 @@ static int wm8737_probe(struct snd_soc_codec *codec)
        /* Bias level configuration will have done an extra enable */
        regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies);
 
-       snd_soc_add_controls(codec, wm8737_snd_controls,
+       snd_soc_add_codec_controls(codec, wm8737_snd_controls,
                             ARRAY_SIZE(wm8737_snd_controls));
        wm8737_add_widgets(codec);
 
index b114c19f530ab89c30ea9daa24cc2a0eef143f85..21ed75de41f31ed9384aa904b6473add464eddcd 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/of_device.h>
+#include <linux/regmap.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -65,28 +66,86 @@ static int wm8753_voice_write_dai_fmt(struct snd_soc_codec *codec,
  * We can't read the WM8753 register space when we
  * are using 2 wire for device control, so we cache them instead.
  */
-static const u16 wm8753_reg[] = {
-       0x0000, 0x0008, 0x0000, 0x000a,
-       0x000a, 0x0033, 0x0000, 0x0007,
-       0x00ff, 0x00ff, 0x000f, 0x000f,
-       0x007b, 0x0000, 0x0032, 0x0000,
-       0x00c3, 0x00c3, 0x00c0, 0x0000,
-       0x0000, 0x0000, 0x0000, 0x0000,
-       0x0000, 0x0000, 0x0000, 0x0000,
-       0x0000, 0x0000, 0x0000, 0x0000,
-       0x0055, 0x0005, 0x0050, 0x0055,
-       0x0050, 0x0055, 0x0050, 0x0055,
-       0x0079, 0x0079, 0x0079, 0x0079,
-       0x0079, 0x0000, 0x0000, 0x0000,
-       0x0000, 0x0097, 0x0097, 0x0000,
-       0x0004, 0x0000, 0x0083, 0x0024,
-       0x01ba, 0x0000, 0x0083, 0x0024,
-       0x01ba, 0x0000, 0x0000, 0x0000
+static const struct reg_default wm8753_reg_defaults[] = {
+       { 0x00, 0x0000 },
+       { 0x01, 0x0008 },
+       { 0x02, 0x0000 },
+       { 0x03, 0x000a },
+       { 0x04, 0x000a },
+       { 0x05, 0x0033 },
+       { 0x06, 0x0000 },
+       { 0x07, 0x0007 },
+       { 0x08, 0x00ff },
+       { 0x09, 0x00ff },
+       { 0x0a, 0x000f },
+       { 0x0b, 0x000f },
+       { 0x0c, 0x007b },
+       { 0x0d, 0x0000 },
+       { 0x0e, 0x0032 },
+       { 0x0f, 0x0000 },
+       { 0x10, 0x00c3 },
+       { 0x11, 0x00c3 },
+       { 0x12, 0x00c0 },
+       { 0x13, 0x0000 },
+       { 0x14, 0x0000 },
+       { 0x15, 0x0000 },
+       { 0x16, 0x0000 },
+       { 0x17, 0x0000 },
+       { 0x18, 0x0000 },
+       { 0x19, 0x0000 },
+       { 0x1a, 0x0000 },
+       { 0x1b, 0x0000 },
+       { 0x1c, 0x0000 },
+       { 0x1d, 0x0000 },
+       { 0x1e, 0x0000 },
+       { 0x1f, 0x0000 },
+       { 0x20, 0x0055 },
+       { 0x21, 0x0005 },
+       { 0x22, 0x0050 },
+       { 0x23, 0x0055 },
+       { 0x24, 0x0050 },
+       { 0x25, 0x0055 },
+       { 0x26, 0x0050 },
+       { 0x27, 0x0055 },
+       { 0x28, 0x0079 },
+       { 0x29, 0x0079 },
+       { 0x2a, 0x0079 },
+       { 0x2b, 0x0079 },
+       { 0x2c, 0x0079 },
+       { 0x2d, 0x0000 },
+       { 0x2e, 0x0000 },
+       { 0x2f, 0x0000 },
+       { 0x30, 0x0000 },
+       { 0x31, 0x0097 },
+       { 0x32, 0x0097 },
+       { 0x33, 0x0000 },
+       { 0x34, 0x0004 },
+       { 0x35, 0x0000 },
+       { 0x36, 0x0083 },
+       { 0x37, 0x0024 },
+       { 0x38, 0x01ba },
+       { 0x39, 0x0000 },
+       { 0x3a, 0x0083 },
+       { 0x3b, 0x0024 },
+       { 0x3c, 0x01ba },
+       { 0x3d, 0x0000 },
+       { 0x3e, 0x0000 },
+       { 0x3f, 0x0000 },
 };
 
+static bool wm8753_volatile(struct device *dev, unsigned int reg)
+{
+       return reg == WM8753_RESET;
+}
+
+static bool wm8753_writeable(struct device *dev, unsigned int reg)
+{
+       return reg <= WM8753_ADCTL2;
+}
+
 /* codec private data */
 struct wm8753_priv {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
        unsigned int sysclk;
        unsigned int pcmclk;
 
@@ -1383,25 +1442,15 @@ static void wm8753_work(struct work_struct *work)
 static int wm8753_suspend(struct snd_soc_codec *codec)
 {
        wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       codec->cache_sync = 1;
        return 0;
 }
 
 static int wm8753_resume(struct snd_soc_codec *codec)
 {
-       u16 *reg_cache = codec->reg_cache;
-       int i;
-
-       /* Sync reg_cache with the hardware */
-       for (i = 1; i < ARRAY_SIZE(wm8753_reg); i++) {
-               if (i == WM8753_RESET)
-                       continue;
-
-               /* No point in writing hardware default values back */
-               if (reg_cache[i] == wm8753_reg[i])
-                       continue;
+       struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
 
-               snd_soc_write(codec, i, reg_cache[i]);
-       }
+       regcache_sync(wm8753->regmap);
 
        wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
@@ -1423,7 +1472,8 @@ static int wm8753_probe(struct snd_soc_codec *codec)
 
        INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work);
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8753->control_type);
+       codec->control_data = wm8753->regmap;
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
@@ -1473,9 +1523,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8753 = {
        .suspend =      wm8753_suspend,
        .resume =       wm8753_resume,
        .set_bias_level = wm8753_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8753_reg),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8753_reg,
 
        .controls = wm8753_snd_controls,
        .num_controls = ARRAY_SIZE(wm8753_snd_controls),
@@ -1491,6 +1538,19 @@ static const struct of_device_id wm8753_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, wm8753_of_match);
 
+static const struct regmap_config wm8753_regmap = {
+       .reg_bits = 7,
+       .val_bits = 9,
+
+       .max_register = WM8753_ADCTL2,
+       .writeable_reg = wm8753_writeable,
+       .volatile_reg = wm8753_volatile,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = wm8753_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8753_reg_defaults),
+};
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8753_spi_probe(struct spi_device *spi)
 {
@@ -1501,20 +1561,36 @@ static int __devinit wm8753_spi_probe(struct spi_device *spi)
        if (wm8753 == NULL)
                return -ENOMEM;
 
-       wm8753->control_type = SND_SOC_SPI;
        spi_set_drvdata(spi, wm8753);
 
-       ret = snd_soc_register_codec(&spi->dev,
-                       &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai));
-       if (ret < 0)
-               kfree(wm8753);
+       wm8753->regmap = regmap_init_spi(spi, &wm8753_regmap);
+       if (IS_ERR(wm8753->regmap)) {
+               ret = PTR_ERR(wm8753->regmap);
+               dev_err(&spi->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               goto err;
+       }
+
+       ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8753,
+                                    wm8753_dai, ARRAY_SIZE(wm8753_dai));
+       if (ret != 0) {
+               dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret);
+               goto err_regmap;
+       }
+err_regmap:
+       regmap_exit(wm8753->regmap);
+err:
+       kfree(wm8753);
        return ret;
 }
 
 static int __devexit wm8753_spi_remove(struct spi_device *spi)
 {
+       struct wm8753_priv *wm8753 = spi_get_drvdata(spi);
+
        snd_soc_unregister_codec(&spi->dev);
-       kfree(spi_get_drvdata(spi));
+       regmap_exit(wm8753->regmap);
+       kfree(wm8753);
        return 0;
 }
 
@@ -1541,19 +1617,35 @@ static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm8753);
-       wm8753->control_type = SND_SOC_I2C;
 
-       ret =  snd_soc_register_codec(&i2c->dev,
-                       &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai));
-       if (ret < 0)
-               kfree(wm8753);
+       wm8753->regmap = regmap_init_i2c(i2c, &wm8753_regmap);
+       if (IS_ERR(wm8753->regmap)) {
+               ret = PTR_ERR(wm8753->regmap);
+               dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               goto err;
+       }
+
+       ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8753,
+                                    wm8753_dai, ARRAY_SIZE(wm8753_dai));
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+               goto err_regmap;
+       }
+err_regmap:
+       regmap_exit(wm8753->regmap);
+err:
+       kfree(wm8753);
        return ret;
 }
 
 static __devexit int wm8753_i2c_remove(struct i2c_client *client)
 {
+       struct wm8753_priv *wm8753 = i2c_get_clientdata(client);
+
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+       regmap_exit(wm8753->regmap);
+       kfree(wm8753);
        return 0;
 }
 
index 19374a9e5ba6ce06fc721e768255fcdb1ea2d97b..a5127b4ff9e1881dd49b5d588d3cd354d33cc746 100644 (file)
@@ -580,8 +580,6 @@ static int wm8770_probe(struct snd_soc_codec *codec)
        wm8770 = snd_soc_codec_get_drvdata(codec);
        wm8770->codec = codec;
 
-       codec->dapm.idle_bias_off = 1;
-
        ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8770->control_type);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -643,7 +641,7 @@ static int wm8770_probe(struct snd_soc_codec *codec)
        /* mute all DACs */
        snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10);
 
-       snd_soc_add_controls(codec, wm8770_snd_controls,
+       snd_soc_add_codec_controls(codec, wm8770_snd_controls,
                             ARRAY_SIZE(wm8770_snd_controls));
        snd_soc_dapm_new_controls(&codec->dapm, wm8770_dapm_widgets,
                                  ARRAY_SIZE(wm8770_dapm_widgets));
@@ -679,6 +677,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8770 = {
        .suspend = wm8770_suspend,
        .resume = wm8770_resume,
        .set_bias_level = wm8770_set_bias_level,
+       .idle_bias_off = true,
        .reg_cache_size = ARRAY_SIZE(wm8770_reg_defs),
        .reg_word_size = sizeof (u16),
        .reg_cache_default = wm8770_reg_defs
index d54a3ca5e19ee3c72550f464e0032d1caeca0bc3..7ee8dcf1fe32c7e7848cf3d2f4fde78f7f668c7e 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/i2c.h>
 #include <linux/of_device.h>
 #include <linux/spi/spi.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -35,45 +36,33 @@ static const char *wm8804_supply_names[WM8804_NUM_SUPPLIES] = {
        "DVDD"
 };
 
-static const u8 wm8804_reg_defs[] = {
-       0x05,     /* R0  - RST/DEVID1 */
-       0x88,     /* R1  - DEVID2 */
-       0x04,     /* R2  - DEVREV */
-       0x21,     /* R3  - PLL1 */
-       0xFD,     /* R4  - PLL2 */
-       0x36,     /* R5  - PLL3 */
-       0x07,     /* R6  - PLL4 */
-       0x16,     /* R7  - PLL5 */
-       0x18,     /* R8  - PLL6 */
-       0xFF,     /* R9  - SPDMODE */
-       0x00,     /* R10 - INTMASK */
-       0x00,     /* R11 - INTSTAT */
-       0x00,     /* R12 - SPDSTAT */
-       0x00,     /* R13 - RXCHAN1 */
-       0x00,     /* R14 - RXCHAN2 */
-       0x00,     /* R15 - RXCHAN3 */
-       0x00,     /* R16 - RXCHAN4 */
-       0x00,     /* R17 - RXCHAN5 */
-       0x00,     /* R18 - SPDTX1 */
-       0x00,     /* R19 - SPDTX2 */
-       0x00,     /* R20 - SPDTX3 */
-       0x71,     /* R21 - SPDTX4 */
-       0x0B,     /* R22 - SPDTX5 */
-       0x70,     /* R23 - GPO0 */
-       0x57,     /* R24 - GPO1 */
-       0x00,     /* R25 */
-       0x42,     /* R26 - GPO2 */
-       0x06,     /* R27 - AIFTX */
-       0x06,     /* R28 - AIFRX */
-       0x80,     /* R29 - SPDRX1 */
-       0x07,     /* R30 - PWRDN */
+static const struct reg_default wm8804_reg_defaults[] = {
+       { 3,  0x21 },     /* R3  - PLL1 */
+       { 4,  0xFD },     /* R4  - PLL2 */
+       { 5,  0x36 },     /* R5  - PLL3 */
+       { 6,  0x07 },     /* R6  - PLL4 */
+       { 7,  0x16 },     /* R7  - PLL5 */
+       { 8,  0x18 },     /* R8  - PLL6 */
+       { 9,  0xFF },     /* R9  - SPDMODE */
+       { 10, 0x00 },     /* R10 - INTMASK */
+       { 18, 0x00 },     /* R18 - SPDTX1 */
+       { 19, 0x00 },     /* R19 - SPDTX2 */
+       { 20, 0x00 },     /* R20 - SPDTX3 */
+       { 21, 0x71 },     /* R21 - SPDTX4 */
+       { 22, 0x0B },     /* R22 - SPDTX5 */
+       { 23, 0x70 },     /* R23 - GPO0 */
+       { 24, 0x57 },     /* R24 - GPO1 */
+       { 26, 0x42 },     /* R26 - GPO2 */
+       { 27, 0x06 },     /* R27 - AIFTX */
+       { 28, 0x06 },     /* R28 - AIFRX */
+       { 29, 0x80 },     /* R29 - SPDRX1 */
+       { 30, 0x07 },     /* R30 - PWRDN */
 };
 
 struct wm8804_priv {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
        struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES];
        struct notifier_block disable_nb[WM8804_NUM_SUPPLIES];
-       struct snd_soc_codec *codec;
 };
 
 static int txsrc_get(struct snd_kcontrol *kcontrol,
@@ -94,7 +83,7 @@ static int wm8804_regulator_event_##n(struct notifier_block *nb, \
        struct wm8804_priv *wm8804 = container_of(nb, struct wm8804_priv, \
                                                  disable_nb[n]); \
        if (event & REGULATOR_EVENT_DISABLE) { \
-               wm8804->codec->cache_sync = 1; \
+               regcache_mark_dirty(wm8804->regmap);    \
        } \
        return 0; \
 }
@@ -176,7 +165,7 @@ static int txsrc_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static int wm8804_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8804_volatile(struct device *dev, unsigned int reg)
 {
        switch (reg) {
        case WM8804_RST_DEVID1:
@@ -189,12 +178,10 @@ static int wm8804_volatile(struct snd_soc_codec *codec, unsigned int reg)
        case WM8804_RXCHAN3:
        case WM8804_RXCHAN4:
        case WM8804_RXCHAN5:
-               return 1;
+               return true;
        default:
-               break;
+               return false;
        }
-
-       return 0;
 }
 
 static int wm8804_reset(struct snd_soc_codec *codec)
@@ -482,24 +469,6 @@ static int wm8804_set_clkdiv(struct snd_soc_dai *dai,
        return 0;
 }
 
-static void wm8804_sync_cache(struct snd_soc_codec *codec)
-{
-       short i;
-       u8 *cache;
-
-       if (!codec->cache_sync)
-               return;
-
-       codec->cache_only = 0;
-       cache = codec->reg_cache;
-       for (i = 0; i < codec->driver->reg_cache_size; i++) {
-               if (i == WM8804_RST_DEVID1 || cache[i] == wm8804_reg_defs[i])
-                       continue;
-               snd_soc_write(codec, i, cache[i]);
-       }
-       codec->cache_sync = 0;
-}
-
 static int wm8804_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
@@ -524,7 +493,7 @@ static int wm8804_set_bias_level(struct snd_soc_codec *codec,
                                        ret);
                                return ret;
                        }
-                       wm8804_sync_cache(codec);
+                       regcache_sync(wm8804->regmap);
                }
                /* power down the OSC and the PLL */
                snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0x9);
@@ -579,11 +548,10 @@ static int wm8804_probe(struct snd_soc_codec *codec)
        int i, id1, id2, ret;
 
        wm8804 = snd_soc_codec_get_drvdata(codec);
-       wm8804->codec = codec;
 
-       codec->dapm.idle_bias_off = 1;
+       codec->control_data = wm8804->regmap;
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 8, wm8804->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
                return ret;
@@ -636,8 +604,7 @@ static int wm8804_probe(struct snd_soc_codec *codec)
 
        id2 = (id2 << 8) | id1;
 
-       if (id2 != ((wm8804_reg_defs[WM8804_DEVID2] << 8)
-                       | wm8804_reg_defs[WM8804_RST_DEVID1])) {
+       if (id2 != 0x8805) {
                dev_err(codec->dev, "Invalid device ID: %#x\n", id2);
                ret = -EINVAL;
                goto err_reg_enable;
@@ -710,10 +677,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
        .suspend = wm8804_suspend,
        .resume = wm8804_resume,
        .set_bias_level = wm8804_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8804_reg_defs),
-       .reg_word_size = sizeof(u8),
-       .reg_cache_default = wm8804_reg_defs,
-       .volatile_register = wm8804_volatile,
+       .idle_bias_off = true,
 
        .controls = wm8804_snd_controls,
        .num_controls = ARRAY_SIZE(wm8804_snd_controls),
@@ -725,30 +689,47 @@ static const struct of_device_id wm8804_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, wm8804_of_match);
 
+static struct regmap_config wm8804_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+
+       .max_register = WM8804_MAX_REGISTER,
+       .volatile_reg = wm8804_volatile,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = wm8804_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8804_reg_defaults),
+};
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8804_spi_probe(struct spi_device *spi)
 {
        struct wm8804_priv *wm8804;
        int ret;
 
-       wm8804 = kzalloc(sizeof *wm8804, GFP_KERNEL);
+       wm8804 = devm_kzalloc(&spi->dev, sizeof *wm8804, GFP_KERNEL);
        if (!wm8804)
                return -ENOMEM;
 
-       wm8804->control_type = SND_SOC_SPI;
+       wm8804->regmap = regmap_init_spi(spi, &wm8804_regmap_config);
+       if (IS_ERR(wm8804->regmap)) {
+               ret = PTR_ERR(wm8804->regmap);
+               return ret;
+       }
+
        spi_set_drvdata(spi, wm8804);
 
        ret = snd_soc_register_codec(&spi->dev,
                                     &soc_codec_dev_wm8804, &wm8804_dai, 1);
-       if (ret < 0)
-               kfree(wm8804);
+
        return ret;
 }
 
 static int __devexit wm8804_spi_remove(struct spi_device *spi)
 {
+       struct wm8804_priv *wm8804 = spi_get_drvdata(spi);
        snd_soc_unregister_codec(&spi->dev);
-       kfree(spi_get_drvdata(spi));
+       regmap_exit(wm8804->regmap);
        return 0;
 }
 
@@ -770,24 +751,31 @@ static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
        struct wm8804_priv *wm8804;
        int ret;
 
-       wm8804 = kzalloc(sizeof *wm8804, GFP_KERNEL);
+       wm8804 = devm_kzalloc(&i2c->dev, sizeof *wm8804, GFP_KERNEL);
        if (!wm8804)
                return -ENOMEM;
 
-       wm8804->control_type = SND_SOC_I2C;
        i2c_set_clientdata(i2c, wm8804);
 
        ret = snd_soc_register_codec(&i2c->dev,
                                     &soc_codec_dev_wm8804, &wm8804_dai, 1);
-       if (ret < 0)
-               kfree(wm8804);
+       if (ret != 0)
+               goto err;
+
+       return 0;
+
+err:
+       regmap_exit(wm8804->regmap);
        return ret;
 }
 
-static __devexit int wm8804_i2c_remove(struct i2c_client *client)
+static __devexit int wm8804_i2c_remove(struct i2c_client *i2c)
 {
-       snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+       struct wm8804_priv *wm8804 = i2c_get_clientdata(i2c);
+
+       snd_soc_unregister_codec(&i2c->dev);
+       regmap_exit(wm8804->regmap);
+
        return 0;
 }
 
index f31c754c8865abd5b21ee61c3e47b810f73721a6..65d525d74c549ee9d83bbb1f1ca0a982a103a567 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -47,6 +48,7 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
 
 /* codec private data */
 struct wm8904_priv {
+       struct regmap *regmap;
 
        enum wm8904_type devtype;
 
@@ -86,517 +88,230 @@ struct wm8904_priv {
        int dcs_state[WM8904_NUM_DCS_CHANNELS];
 };
 
-static const u16 wm8904_reg[WM8904_MAX_REGISTER + 1] = {
-       0x8904,     /* R0   - SW Reset and ID */
-       0x0000,     /* R1   - Revision */
-       0x0000,     /* R2 */
-       0x0000,     /* R3 */
-       0x0018,     /* R4   - Bias Control 0 */
-       0x0000,     /* R5   - VMID Control 0 */
-       0x0000,     /* R6   - Mic Bias Control 0 */
-       0x0000,     /* R7   - Mic Bias Control 1 */
-       0x0001,     /* R8   - Analogue DAC 0 */
-       0x9696,     /* R9   - mic Filter Control */
-       0x0001,     /* R10  - Analogue ADC 0 */
-       0x0000,     /* R11 */
-       0x0000,     /* R12  - Power Management 0 */
-       0x0000,     /* R13 */
-       0x0000,     /* R14  - Power Management 2 */
-       0x0000,     /* R15  - Power Management 3 */
-       0x0000,     /* R16 */
-       0x0000,     /* R17 */
-       0x0000,     /* R18  - Power Management 6 */
-       0x0000,     /* R19 */
-       0x945E,     /* R20  - Clock Rates 0 */
-       0x0C05,     /* R21  - Clock Rates 1 */
-       0x0006,     /* R22  - Clock Rates 2 */
-       0x0000,     /* R23 */
-       0x0050,     /* R24  - Audio Interface 0 */
-       0x000A,     /* R25  - Audio Interface 1 */
-       0x00E4,     /* R26  - Audio Interface 2 */
-       0x0040,     /* R27  - Audio Interface 3 */
-       0x0000,     /* R28 */
-       0x0000,     /* R29 */
-       0x00C0,     /* R30  - DAC Digital Volume Left */
-       0x00C0,     /* R31  - DAC Digital Volume Right */
-       0x0000,     /* R32  - DAC Digital 0 */
-       0x0008,     /* R33  - DAC Digital 1 */
-       0x0000,     /* R34 */
-       0x0000,     /* R35 */
-       0x00C0,     /* R36  - ADC Digital Volume Left */
-       0x00C0,     /* R37  - ADC Digital Volume Right */
-       0x0010,     /* R38  - ADC Digital 0 */
-       0x0000,     /* R39  - Digital Microphone 0 */
-       0x01AF,     /* R40  - DRC 0 */
-       0x3248,     /* R41  - DRC 1 */
-       0x0000,     /* R42  - DRC 2 */
-       0x0000,     /* R43  - DRC 3 */
-       0x0085,     /* R44  - Analogue Left Input 0 */
-       0x0085,     /* R45  - Analogue Right Input 0 */
-       0x0044,     /* R46  - Analogue Left Input 1 */
-       0x0044,     /* R47  - Analogue Right Input 1 */
-       0x0000,     /* R48 */
-       0x0000,     /* R49 */
-       0x0000,     /* R50 */
-       0x0000,     /* R51 */
-       0x0000,     /* R52 */
-       0x0000,     /* R53 */
-       0x0000,     /* R54 */
-       0x0000,     /* R55 */
-       0x0000,     /* R56 */
-       0x002D,     /* R57  - Analogue OUT1 Left */
-       0x002D,     /* R58  - Analogue OUT1 Right */
-       0x0039,     /* R59  - Analogue OUT2 Left */
-       0x0039,     /* R60  - Analogue OUT2 Right */
-       0x0000,     /* R61  - Analogue OUT12 ZC */
-       0x0000,     /* R62 */
-       0x0000,     /* R63 */
-       0x0000,     /* R64 */
-       0x0000,     /* R65 */
-       0x0000,     /* R66 */
-       0x0000,     /* R67  - DC Servo 0 */
-       0x0000,     /* R68  - DC Servo 1 */
-       0xAAAA,     /* R69  - DC Servo 2 */
-       0x0000,     /* R70 */
-       0xAAAA,     /* R71  - DC Servo 4 */
-       0xAAAA,     /* R72  - DC Servo 5 */
-       0x0000,     /* R73  - DC Servo 6 */
-       0x0000,     /* R74  - DC Servo 7 */
-       0x0000,     /* R75  - DC Servo 8 */
-       0x0000,     /* R76  - DC Servo 9 */
-       0x0000,     /* R77  - DC Servo Readback 0 */
-       0x0000,     /* R78 */
-       0x0000,     /* R79 */
-       0x0000,     /* R80 */
-       0x0000,     /* R81 */
-       0x0000,     /* R82 */
-       0x0000,     /* R83 */
-       0x0000,     /* R84 */
-       0x0000,     /* R85 */
-       0x0000,     /* R86 */
-       0x0000,     /* R87 */
-       0x0000,     /* R88 */
-       0x0000,     /* R89 */
-       0x0000,     /* R90  - Analogue HP 0 */
-       0x0000,     /* R91 */
-       0x0000,     /* R92 */
-       0x0000,     /* R93 */
-       0x0000,     /* R94  - Analogue Lineout 0 */
-       0x0000,     /* R95 */
-       0x0000,     /* R96 */
-       0x0000,     /* R97 */
-       0x0000,     /* R98  - Charge Pump 0 */
-       0x0000,     /* R99 */
-       0x0000,     /* R100 */
-       0x0000,     /* R101 */
-       0x0000,     /* R102 */
-       0x0000,     /* R103 */
-       0x0004,     /* R104 - Class W 0 */
-       0x0000,     /* R105 */
-       0x0000,     /* R106 */
-       0x0000,     /* R107 */
-       0x0000,     /* R108 - Write Sequencer 0 */
-       0x0000,     /* R109 - Write Sequencer 1 */
-       0x0000,     /* R110 - Write Sequencer 2 */
-       0x0000,     /* R111 - Write Sequencer 3 */
-       0x0000,     /* R112 - Write Sequencer 4 */
-       0x0000,     /* R113 */
-       0x0000,     /* R114 */
-       0x0000,     /* R115 */
-       0x0000,     /* R116 - FLL Control 1 */
-       0x0007,     /* R117 - FLL Control 2 */
-       0x0000,     /* R118 - FLL Control 3 */
-       0x2EE0,     /* R119 - FLL Control 4 */
-       0x0004,     /* R120 - FLL Control 5 */
-       0x0014,     /* R121 - GPIO Control 1 */
-       0x0010,     /* R122 - GPIO Control 2 */
-       0x0010,     /* R123 - GPIO Control 3 */
-       0x0000,     /* R124 - GPIO Control 4 */
-       0x0000,     /* R125 */
-       0x0000,     /* R126 - Digital Pulls */
-       0x0000,     /* R127 - Interrupt Status */
-       0xFFFF,     /* R128 - Interrupt Status Mask */
-       0x0000,     /* R129 - Interrupt Polarity */
-       0x0000,     /* R130 - Interrupt Debounce */
-       0x0000,     /* R131 */
-       0x0000,     /* R132 */
-       0x0000,     /* R133 */
-       0x0000,     /* R134 - EQ1 */
-       0x000C,     /* R135 - EQ2 */
-       0x000C,     /* R136 - EQ3 */
-       0x000C,     /* R137 - EQ4 */
-       0x000C,     /* R138 - EQ5 */
-       0x000C,     /* R139 - EQ6 */
-       0x0FCA,     /* R140 - EQ7 */
-       0x0400,     /* R141 - EQ8 */
-       0x00D8,     /* R142 - EQ9 */
-       0x1EB5,     /* R143 - EQ10 */
-       0xF145,     /* R144 - EQ11 */
-       0x0B75,     /* R145 - EQ12 */
-       0x01C5,     /* R146 - EQ13 */
-       0x1C58,     /* R147 - EQ14 */
-       0xF373,     /* R148 - EQ15 */
-       0x0A54,     /* R149 - EQ16 */
-       0x0558,     /* R150 - EQ17 */
-       0x168E,     /* R151 - EQ18 */
-       0xF829,     /* R152 - EQ19 */
-       0x07AD,     /* R153 - EQ20 */
-       0x1103,     /* R154 - EQ21 */
-       0x0564,     /* R155 - EQ22 */
-       0x0559,     /* R156 - EQ23 */
-       0x4000,     /* R157 - EQ24 */
-       0x0000,     /* R158 */
-       0x0000,     /* R159 */
-       0x0000,     /* R160 */
-       0x0000,     /* R161 - Control Interface Test 1 */
-       0x0000,     /* R162 */
-       0x0000,     /* R163 */
-       0x0000,     /* R164 */
-       0x0000,     /* R165 */
-       0x0000,     /* R166 */
-       0x0000,     /* R167 */
-       0x0000,     /* R168 */
-       0x0000,     /* R169 */
-       0x0000,     /* R170 */
-       0x0000,     /* R171 */
-       0x0000,     /* R172 */
-       0x0000,     /* R173 */
-       0x0000,     /* R174 */
-       0x0000,     /* R175 */
-       0x0000,     /* R176 */
-       0x0000,     /* R177 */
-       0x0000,     /* R178 */
-       0x0000,     /* R179 */
-       0x0000,     /* R180 */
-       0x0000,     /* R181 */
-       0x0000,     /* R182 */
-       0x0000,     /* R183 */
-       0x0000,     /* R184 */
-       0x0000,     /* R185 */
-       0x0000,     /* R186 */
-       0x0000,     /* R187 */
-       0x0000,     /* R188 */
-       0x0000,     /* R189 */
-       0x0000,     /* R190 */
-       0x0000,     /* R191 */
-       0x0000,     /* R192 */
-       0x0000,     /* R193 */
-       0x0000,     /* R194 */
-       0x0000,     /* R195 */
-       0x0000,     /* R196 */
-       0x0000,     /* R197 */
-       0x0000,     /* R198 */
-       0x0000,     /* R199 */
-       0x0000,     /* R200 */
-       0x0000,     /* R201 */
-       0x0000,     /* R202 */
-       0x0000,     /* R203 */
-       0x0000,     /* R204 - Analogue Output Bias 0 */
-       0x0000,     /* R205 */
-       0x0000,     /* R206 */
-       0x0000,     /* R207 */
-       0x0000,     /* R208 */
-       0x0000,     /* R209 */
-       0x0000,     /* R210 */
-       0x0000,     /* R211 */
-       0x0000,     /* R212 */
-       0x0000,     /* R213 */
-       0x0000,     /* R214 */
-       0x0000,     /* R215 */
-       0x0000,     /* R216 */
-       0x0000,     /* R217 */
-       0x0000,     /* R218 */
-       0x0000,     /* R219 */
-       0x0000,     /* R220 */
-       0x0000,     /* R221 */
-       0x0000,     /* R222 */
-       0x0000,     /* R223 */
-       0x0000,     /* R224 */
-       0x0000,     /* R225 */
-       0x0000,     /* R226 */
-       0x0000,     /* R227 */
-       0x0000,     /* R228 */
-       0x0000,     /* R229 */
-       0x0000,     /* R230 */
-       0x0000,     /* R231 */
-       0x0000,     /* R232 */
-       0x0000,     /* R233 */
-       0x0000,     /* R234 */
-       0x0000,     /* R235 */
-       0x0000,     /* R236 */
-       0x0000,     /* R237 */
-       0x0000,     /* R238 */
-       0x0000,     /* R239 */
-       0x0000,     /* R240 */
-       0x0000,     /* R241 */
-       0x0000,     /* R242 */
-       0x0000,     /* R243 */
-       0x0000,     /* R244 */
-       0x0000,     /* R245 */
-       0x0000,     /* R246 */
-       0x0000,     /* R247 - FLL NCO Test 0 */
-       0x0019,     /* R248 - FLL NCO Test 1 */
+static const struct reg_default wm8904_reg_defaults[] = {
+       { 4,   0x0018 },     /* R4   - Bias Control 0 */
+       { 5,   0x0000 },     /* R5   - VMID Control 0 */
+       { 6,   0x0000 },     /* R6   - Mic Bias Control 0 */
+       { 7,   0x0000 },     /* R7   - Mic Bias Control 1 */
+       { 8,   0x0001 },     /* R8   - Analogue DAC 0 */
+       { 9,   0x9696 },     /* R9   - mic Filter Control */
+       { 10,  0x0001 },     /* R10  - Analogue ADC 0 */
+       { 12,  0x0000 },     /* R12  - Power Management 0 */
+       { 14,  0x0000 },     /* R14  - Power Management 2 */
+       { 15,  0x0000 },     /* R15  - Power Management 3 */
+       { 18,  0x0000 },     /* R18  - Power Management 6 */
+       { 19,  0x945E },     /* R20  - Clock Rates 0 */
+       { 21,  0x0C05 },     /* R21  - Clock Rates 1 */
+       { 22,  0x0006 },     /* R22  - Clock Rates 2 */
+       { 24,  0x0050 },     /* R24  - Audio Interface 0 */
+       { 25,  0x000A },     /* R25  - Audio Interface 1 */
+       { 26,  0x00E4 },     /* R26  - Audio Interface 2 */
+       { 27,  0x0040 },     /* R27  - Audio Interface 3 */
+       { 30,  0x00C0 },     /* R30  - DAC Digital Volume Left */
+       { 31,  0x00C0 },     /* R31  - DAC Digital Volume Right */
+       { 32,  0x0000 },     /* R32  - DAC Digital 0 */
+       { 33,  0x0008 },     /* R33  - DAC Digital 1 */
+       { 36,  0x00C0 },     /* R36  - ADC Digital Volume Left */
+       { 37,  0x00C0 },     /* R37  - ADC Digital Volume Right */
+       { 38,  0x0010 },     /* R38  - ADC Digital 0 */
+       { 39,  0x0000 },     /* R39  - Digital Microphone 0 */
+       { 40,  0x01AF },     /* R40  - DRC 0 */
+       { 41,  0x3248 },     /* R41  - DRC 1 */
+       { 42,  0x0000 },     /* R42  - DRC 2 */
+       { 43,  0x0000 },     /* R43  - DRC 3 */
+       { 44,  0x0085 },     /* R44  - Analogue Left Input 0 */
+       { 45,  0x0085 },     /* R45  - Analogue Right Input 0 */
+       { 46,  0x0044 },     /* R46  - Analogue Left Input 1 */
+       { 47,  0x0044 },     /* R47  - Analogue Right Input 1 */
+       { 57,  0x002D },     /* R57  - Analogue OUT1 Left */
+       { 58,  0x002D },     /* R58  - Analogue OUT1 Right */
+       { 59,  0x0039 },     /* R59  - Analogue OUT2 Left */
+       { 60,  0x0039 },     /* R60  - Analogue OUT2 Right */
+       { 61,  0x0000 },     /* R61  - Analogue OUT12 ZC */
+       { 67,  0x0000 },     /* R67  - DC Servo 0 */
+       { 69,  0xAAAA },     /* R69  - DC Servo 2 */
+       { 71,  0xAAAA },     /* R71  - DC Servo 4 */
+       { 72,  0xAAAA },     /* R72  - DC Servo 5 */
+       { 90,  0x0000 },     /* R90  - Analogue HP 0 */
+       { 94,  0x0000 },     /* R94  - Analogue Lineout 0 */
+       { 98,  0x0000 },     /* R98  - Charge Pump 0 */
+       { 104, 0x0004 },     /* R104 - Class W 0 */
+       { 108, 0x0000 },     /* R108 - Write Sequencer 0 */
+       { 109, 0x0000 },     /* R109 - Write Sequencer 1 */
+       { 110, 0x0000 },     /* R110 - Write Sequencer 2 */
+       { 111, 0x0000 },     /* R111 - Write Sequencer 3 */
+       { 112, 0x0000 },     /* R112 - Write Sequencer 4 */
+       { 116, 0x0000 },     /* R116 - FLL Control 1 */
+       { 117, 0x0007 },     /* R117 - FLL Control 2 */
+       { 118, 0x0000 },     /* R118 - FLL Control 3 */
+       { 119, 0x2EE0 },     /* R119 - FLL Control 4 */
+       { 120, 0x0004 },     /* R120 - FLL Control 5 */
+       { 121, 0x0014 },     /* R121 - GPIO Control 1 */
+       { 122, 0x0010 },     /* R122 - GPIO Control 2 */
+       { 123, 0x0010 },     /* R123 - GPIO Control 3 */
+       { 124, 0x0000 },     /* R124 - GPIO Control 4 */
+       { 126, 0x0000 },     /* R126 - Digital Pulls */
+       { 128, 0xFFFF },     /* R128 - Interrupt Status Mask */
+       { 129, 0x0000 },     /* R129 - Interrupt Polarity */
+       { 130, 0x0000 },     /* R130 - Interrupt Debounce */
+       { 134, 0x0000 },     /* R134 - EQ1 */
+       { 135, 0x000C },     /* R135 - EQ2 */
+       { 136, 0x000C },     /* R136 - EQ3 */
+       { 137, 0x000C },     /* R137 - EQ4 */
+       { 138, 0x000C },     /* R138 - EQ5 */
+       { 139, 0x000C },     /* R139 - EQ6 */
+       { 140, 0x0FCA },     /* R140 - EQ7 */
+       { 141, 0x0400 },     /* R141 - EQ8 */
+       { 142, 0x00D8 },     /* R142 - EQ9 */
+       { 143, 0x1EB5 },     /* R143 - EQ10 */
+       { 144, 0xF145 },     /* R144 - EQ11 */
+       { 145, 0x0B75 },     /* R145 - EQ12 */
+       { 146, 0x01C5 },     /* R146 - EQ13 */
+       { 147, 0x1C58 },     /* R147 - EQ14 */
+       { 148, 0xF373 },     /* R148 - EQ15 */
+       { 149, 0x0A54 },     /* R149 - EQ16 */
+       { 150, 0x0558 },     /* R150 - EQ17 */
+       { 151, 0x168E },     /* R151 - EQ18 */
+       { 152, 0xF829 },     /* R152 - EQ19 */
+       { 153, 0x07AD },     /* R153 - EQ20 */
+       { 154, 0x1103 },     /* R154 - EQ21 */
+       { 155, 0x0564 },     /* R155 - EQ22 */
+       { 156, 0x0559 },     /* R156 - EQ23 */
+       { 157, 0x4000 },     /* R157 - EQ24 */
+       { 161, 0x0000 },     /* R161 - Control Interface Test 1 */
+       { 204, 0x0000 },     /* R204 - Analogue Output Bias 0 */
+       { 247, 0x0000 },     /* R247 - FLL NCO Test 0 */
+       { 248, 0x0019 },     /* R248 - FLL NCO Test 1 */
 };
 
-static struct {
-       int readable;
-       int writable;
-       int vol;
-} wm8904_access[] = {
-       { 0xFFFF, 0xFFFF, 1 }, /* R0   - SW Reset and ID */
-       { 0x0000, 0x0000, 0 }, /* R1   - Revision */
-       { 0x0000, 0x0000, 0 }, /* R2 */
-       { 0x0000, 0x0000, 0 }, /* R3 */
-       { 0x001F, 0x001F, 0 }, /* R4   - Bias Control 0 */
-       { 0x0047, 0x0047, 0 }, /* R5   - VMID Control 0 */
-       { 0x007F, 0x007F, 0 }, /* R6   - Mic Bias Control 0 */
-       { 0xC007, 0xC007, 0 }, /* R7   - Mic Bias Control 1 */
-       { 0x001E, 0x001E, 0 }, /* R8   - Analogue DAC 0 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R9   - mic Filter Control */
-       { 0x0001, 0x0001, 0 }, /* R10  - Analogue ADC 0 */
-       { 0x0000, 0x0000, 0 }, /* R11 */
-       { 0x0003, 0x0003, 0 }, /* R12  - Power Management 0 */
-       { 0x0000, 0x0000, 0 }, /* R13 */
-       { 0x0003, 0x0003, 0 }, /* R14  - Power Management 2 */
-       { 0x0003, 0x0003, 0 }, /* R15  - Power Management 3 */
-       { 0x0000, 0x0000, 0 }, /* R16 */
-       { 0x0000, 0x0000, 0 }, /* R17 */
-       { 0x000F, 0x000F, 0 }, /* R18  - Power Management 6 */
-       { 0x0000, 0x0000, 0 }, /* R19 */
-       { 0x7001, 0x7001, 0 }, /* R20  - Clock Rates 0 */
-       { 0x3C07, 0x3C07, 0 }, /* R21  - Clock Rates 1 */
-       { 0xD00F, 0xD00F, 0 }, /* R22  - Clock Rates 2 */
-       { 0x0000, 0x0000, 0 }, /* R23 */
-       { 0x1FFF, 0x1FFF, 0 }, /* R24  - Audio Interface 0 */
-       { 0x3DDF, 0x3DDF, 0 }, /* R25  - Audio Interface 1 */
-       { 0x0F1F, 0x0F1F, 0 }, /* R26  - Audio Interface 2 */
-       { 0x0FFF, 0x0FFF, 0 }, /* R27  - Audio Interface 3 */
-       { 0x0000, 0x0000, 0 }, /* R28 */
-       { 0x0000, 0x0000, 0 }, /* R29 */
-       { 0x00FF, 0x01FF, 0 }, /* R30  - DAC Digital Volume Left */
-       { 0x00FF, 0x01FF, 0 }, /* R31  - DAC Digital Volume Right */
-       { 0x0FFF, 0x0FFF, 0 }, /* R32  - DAC Digital 0 */
-       { 0x1E4E, 0x1E4E, 0 }, /* R33  - DAC Digital 1 */
-       { 0x0000, 0x0000, 0 }, /* R34 */
-       { 0x0000, 0x0000, 0 }, /* R35 */
-       { 0x00FF, 0x01FF, 0 }, /* R36  - ADC Digital Volume Left */
-       { 0x00FF, 0x01FF, 0 }, /* R37  - ADC Digital Volume Right */
-       { 0x0073, 0x0073, 0 }, /* R38  - ADC Digital 0 */
-       { 0x1800, 0x1800, 0 }, /* R39  - Digital Microphone 0 */
-       { 0xDFEF, 0xDFEF, 0 }, /* R40  - DRC 0 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R41  - DRC 1 */
-       { 0x003F, 0x003F, 0 }, /* R42  - DRC 2 */
-       { 0x07FF, 0x07FF, 0 }, /* R43  - DRC 3 */
-       { 0x009F, 0x009F, 0 }, /* R44  - Analogue Left Input 0 */
-       { 0x009F, 0x009F, 0 }, /* R45  - Analogue Right Input 0 */
-       { 0x007F, 0x007F, 0 }, /* R46  - Analogue Left Input 1 */
-       { 0x007F, 0x007F, 0 }, /* R47  - Analogue Right Input 1 */
-       { 0x0000, 0x0000, 0 }, /* R48 */
-       { 0x0000, 0x0000, 0 }, /* R49 */
-       { 0x0000, 0x0000, 0 }, /* R50 */
-       { 0x0000, 0x0000, 0 }, /* R51 */
-       { 0x0000, 0x0000, 0 }, /* R52 */
-       { 0x0000, 0x0000, 0 }, /* R53 */
-       { 0x0000, 0x0000, 0 }, /* R54 */
-       { 0x0000, 0x0000, 0 }, /* R55 */
-       { 0x0000, 0x0000, 0 }, /* R56 */
-       { 0x017F, 0x01FF, 0 }, /* R57  - Analogue OUT1 Left */
-       { 0x017F, 0x01FF, 0 }, /* R58  - Analogue OUT1 Right */
-       { 0x017F, 0x01FF, 0 }, /* R59  - Analogue OUT2 Left */
-       { 0x017F, 0x01FF, 0 }, /* R60  - Analogue OUT2 Right */
-       { 0x000F, 0x000F, 0 }, /* R61  - Analogue OUT12 ZC */
-       { 0x0000, 0x0000, 0 }, /* R62 */
-       { 0x0000, 0x0000, 0 }, /* R63 */
-       { 0x0000, 0x0000, 0 }, /* R64 */
-       { 0x0000, 0x0000, 0 }, /* R65 */
-       { 0x0000, 0x0000, 0 }, /* R66 */
-       { 0x000F, 0x000F, 0 }, /* R67  - DC Servo 0 */
-       { 0xFFFF, 0xFFFF, 1 }, /* R68  - DC Servo 1 */
-       { 0x0F0F, 0x0F0F, 0 }, /* R69  - DC Servo 2 */
-       { 0x0000, 0x0000, 0 }, /* R70 */
-       { 0x007F, 0x007F, 0 }, /* R71  - DC Servo 4 */
-       { 0x007F, 0x007F, 0 }, /* R72  - DC Servo 5 */
-       { 0x00FF, 0x00FF, 1 }, /* R73  - DC Servo 6 */
-       { 0x00FF, 0x00FF, 1 }, /* R74  - DC Servo 7 */
-       { 0x00FF, 0x00FF, 1 }, /* R75  - DC Servo 8 */
-       { 0x00FF, 0x00FF, 1 }, /* R76  - DC Servo 9 */
-       { 0x0FFF, 0x0000, 1 }, /* R77  - DC Servo Readback 0 */
-       { 0x0000, 0x0000, 0 }, /* R78 */
-       { 0x0000, 0x0000, 0 }, /* R79 */
-       { 0x0000, 0x0000, 0 }, /* R80 */
-       { 0x0000, 0x0000, 0 }, /* R81 */
-       { 0x0000, 0x0000, 0 }, /* R82 */
-       { 0x0000, 0x0000, 0 }, /* R83 */
-       { 0x0000, 0x0000, 0 }, /* R84 */
-       { 0x0000, 0x0000, 0 }, /* R85 */
-       { 0x0000, 0x0000, 0 }, /* R86 */
-       { 0x0000, 0x0000, 0 }, /* R87 */
-       { 0x0000, 0x0000, 0 }, /* R88 */
-       { 0x0000, 0x0000, 0 }, /* R89 */
-       { 0x00FF, 0x00FF, 0 }, /* R90  - Analogue HP 0 */
-       { 0x0000, 0x0000, 0 }, /* R91 */
-       { 0x0000, 0x0000, 0 }, /* R92 */
-       { 0x0000, 0x0000, 0 }, /* R93 */
-       { 0x00FF, 0x00FF, 0 }, /* R94  - Analogue Lineout 0 */
-       { 0x0000, 0x0000, 0 }, /* R95 */
-       { 0x0000, 0x0000, 0 }, /* R96 */
-       { 0x0000, 0x0000, 0 }, /* R97 */
-       { 0x0001, 0x0001, 0 }, /* R98  - Charge Pump 0 */
-       { 0x0000, 0x0000, 0 }, /* R99 */
-       { 0x0000, 0x0000, 0 }, /* R100 */
-       { 0x0000, 0x0000, 0 }, /* R101 */
-       { 0x0000, 0x0000, 0 }, /* R102 */
-       { 0x0000, 0x0000, 0 }, /* R103 */
-       { 0x0001, 0x0001, 0 }, /* R104 - Class W 0 */
-       { 0x0000, 0x0000, 0 }, /* R105 */
-       { 0x0000, 0x0000, 0 }, /* R106 */
-       { 0x0000, 0x0000, 0 }, /* R107 */
-       { 0x011F, 0x011F, 0 }, /* R108 - Write Sequencer 0 */
-       { 0x7FFF, 0x7FFF, 0 }, /* R109 - Write Sequencer 1 */
-       { 0x4FFF, 0x4FFF, 0 }, /* R110 - Write Sequencer 2 */
-       { 0x003F, 0x033F, 0 }, /* R111 - Write Sequencer 3 */
-       { 0x03F1, 0x0000, 0 }, /* R112 - Write Sequencer 4 */
-       { 0x0000, 0x0000, 0 }, /* R113 */
-       { 0x0000, 0x0000, 0 }, /* R114 */
-       { 0x0000, 0x0000, 0 }, /* R115 */
-       { 0x0007, 0x0007, 0 }, /* R116 - FLL Control 1 */
-       { 0x3F77, 0x3F77, 0 }, /* R117 - FLL Control 2 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R118 - FLL Control 3 */
-       { 0x7FEF, 0x7FEF, 0 }, /* R119 - FLL Control 4 */
-       { 0x001B, 0x001B, 0 }, /* R120 - FLL Control 5 */
-       { 0x003F, 0x003F, 0 }, /* R121 - GPIO Control 1 */
-       { 0x003F, 0x003F, 0 }, /* R122 - GPIO Control 2 */
-       { 0x003F, 0x003F, 0 }, /* R123 - GPIO Control 3 */
-       { 0x038F, 0x038F, 0 }, /* R124 - GPIO Control 4 */
-       { 0x0000, 0x0000, 0 }, /* R125 */
-       { 0x00FF, 0x00FF, 0 }, /* R126 - Digital Pulls */
-       { 0x07FF, 0x03FF, 1 }, /* R127 - Interrupt Status */
-       { 0x03FF, 0x03FF, 0 }, /* R128 - Interrupt Status Mask */
-       { 0x03FF, 0x03FF, 0 }, /* R129 - Interrupt Polarity */
-       { 0x03FF, 0x03FF, 0 }, /* R130 - Interrupt Debounce */
-       { 0x0000, 0x0000, 0 }, /* R131 */
-       { 0x0000, 0x0000, 0 }, /* R132 */
-       { 0x0000, 0x0000, 0 }, /* R133 */
-       { 0x0001, 0x0001, 0 }, /* R134 - EQ1 */
-       { 0x001F, 0x001F, 0 }, /* R135 - EQ2 */
-       { 0x001F, 0x001F, 0 }, /* R136 - EQ3 */
-       { 0x001F, 0x001F, 0 }, /* R137 - EQ4 */
-       { 0x001F, 0x001F, 0 }, /* R138 - EQ5 */
-       { 0x001F, 0x001F, 0 }, /* R139 - EQ6 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R140 - EQ7 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R141 - EQ8 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R142 - EQ9 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R143 - EQ10 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R144 - EQ11 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R145 - EQ12 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R146 - EQ13 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R147 - EQ14 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R148 - EQ15 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R149 - EQ16 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R150 - EQ17 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R151wm8523_dai - EQ18 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R152 - EQ19 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R153 - EQ20 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R154 - EQ21 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R155 - EQ22 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R156 - EQ23 */
-       { 0xFFFF, 0xFFFF, 0 }, /* R157 - EQ24 */
-       { 0x0000, 0x0000, 0 }, /* R158 */
-       { 0x0000, 0x0000, 0 }, /* R159 */
-       { 0x0000, 0x0000, 0 }, /* R160 */
-       { 0x0002, 0x0002, 0 }, /* R161 - Control Interface Test 1 */
-       { 0x0000, 0x0000, 0 }, /* R162 */
-       { 0x0000, 0x0000, 0 }, /* R163 */
-       { 0x0000, 0x0000, 0 }, /* R164 */
-       { 0x0000, 0x0000, 0 }, /* R165 */
-       { 0x0000, 0x0000, 0 }, /* R166 */
-       { 0x0000, 0x0000, 0 }, /* R167 */
-       { 0x0000, 0x0000, 0 }, /* R168 */
-       { 0x0000, 0x0000, 0 }, /* R169 */
-       { 0x0000, 0x0000, 0 }, /* R170 */
-       { 0x0000, 0x0000, 0 }, /* R171 */
-       { 0x0000, 0x0000, 0 }, /* R172 */
-       { 0x0000, 0x0000, 0 }, /* R173 */
-       { 0x0000, 0x0000, 0 }, /* R174 */
-       { 0x0000, 0x0000, 0 }, /* R175 */
-       { 0x0000, 0x0000, 0 }, /* R176 */
-       { 0x0000, 0x0000, 0 }, /* R177 */
-       { 0x0000, 0x0000, 0 }, /* R178 */
-       { 0x0000, 0x0000, 0 }, /* R179 */
-       { 0x0000, 0x0000, 0 }, /* R180 */
-       { 0x0000, 0x0000, 0 }, /* R181 */
-       { 0x0000, 0x0000, 0 }, /* R182 */
-       { 0x0000, 0x0000, 0 }, /* R183 */
-       { 0x0000, 0x0000, 0 }, /* R184 */
-       { 0x0000, 0x0000, 0 }, /* R185 */
-       { 0x0000, 0x0000, 0 }, /* R186 */
-       { 0x0000, 0x0000, 0 }, /* R187 */
-       { 0x0000, 0x0000, 0 }, /* R188 */
-       { 0x0000, 0x0000, 0 }, /* R189 */
-       { 0x0000, 0x0000, 0 }, /* R190 */
-       { 0x0000, 0x0000, 0 }, /* R191 */
-       { 0x0000, 0x0000, 0 }, /* R192 */
-       { 0x0000, 0x0000, 0 }, /* R193 */
-       { 0x0000, 0x0000, 0 }, /* R194 */
-       { 0x0000, 0x0000, 0 }, /* R195 */
-       { 0x0000, 0x0000, 0 }, /* R196 */
-       { 0x0000, 0x0000, 0 }, /* R197 */
-       { 0x0000, 0x0000, 0 }, /* R198 */
-       { 0x0000, 0x0000, 0 }, /* R199 */
-       { 0x0000, 0x0000, 0 }, /* R200 */
-       { 0x0000, 0x0000, 0 }, /* R201 */
-       { 0x0000, 0x0000, 0 }, /* R202 */
-       { 0x0000, 0x0000, 0 }, /* R203 */
-       { 0x0070, 0x0070, 0 }, /* R204 - Analogue Output Bias 0 */
-       { 0x0000, 0x0000, 0 }, /* R205 */
-       { 0x0000, 0x0000, 0 }, /* R206 */
-       { 0x0000, 0x0000, 0 }, /* R207 */
-       { 0x0000, 0x0000, 0 }, /* R208 */
-       { 0x0000, 0x0000, 0 }, /* R209 */
-       { 0x0000, 0x0000, 0 }, /* R210 */
-       { 0x0000, 0x0000, 0 }, /* R211 */
-       { 0x0000, 0x0000, 0 }, /* R212 */
-       { 0x0000, 0x0000, 0 }, /* R213 */
-       { 0x0000, 0x0000, 0 }, /* R214 */
-       { 0x0000, 0x0000, 0 }, /* R215 */
-       { 0x0000, 0x0000, 0 }, /* R216 */
-       { 0x0000, 0x0000, 0 }, /* R217 */
-       { 0x0000, 0x0000, 0 }, /* R218 */
-       { 0x0000, 0x0000, 0 }, /* R219 */
-       { 0x0000, 0x0000, 0 }, /* R220 */
-       { 0x0000, 0x0000, 0 }, /* R221 */
-       { 0x0000, 0x0000, 0 }, /* R222 */
-       { 0x0000, 0x0000, 0 }, /* R223 */
-       { 0x0000, 0x0000, 0 }, /* R224 */
-       { 0x0000, 0x0000, 0 }, /* R225 */
-       { 0x0000, 0x0000, 0 }, /* R226 */
-       { 0x0000, 0x0000, 0 }, /* R227 */
-       { 0x0000, 0x0000, 0 }, /* R228 */
-       { 0x0000, 0x0000, 0 }, /* R229 */
-       { 0x0000, 0x0000, 0 }, /* R230 */
-       { 0x0000, 0x0000, 0 }, /* R231 */
-       { 0x0000, 0x0000, 0 }, /* R232 */
-       { 0x0000, 0x0000, 0 }, /* R233 */
-       { 0x0000, 0x0000, 0 }, /* R234 */
-       { 0x0000, 0x0000, 0 }, /* R235 */
-       { 0x0000, 0x0000, 0 }, /* R236 */
-       { 0x0000, 0x0000, 0 }, /* R237 */
-       { 0x0000, 0x0000, 0 }, /* R238 */
-       { 0x0000, 0x0000, 0 }, /* R239 */
-       { 0x0000, 0x0000, 0 }, /* R240 */
-       { 0x0000, 0x0000, 0 }, /* R241 */
-       { 0x0000, 0x0000, 0 }, /* R242 */
-       { 0x0000, 0x0000, 0 }, /* R243 */
-       { 0x0000, 0x0000, 0 }, /* R244 */
-       { 0x0000, 0x0000, 0 }, /* R245 */
-       { 0x0000, 0x0000, 0 }, /* R246 */
-       { 0x0001, 0x0001, 0 }, /* R247 - FLL NCO Test 0 */
-       { 0x003F, 0x003F, 0 }, /* R248 - FLL NCO Test 1 */
-};
+static bool wm8904_volatile_register(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM8904_SW_RESET_AND_ID:
+       case WM8904_REVISION:
+       case WM8904_DC_SERVO_1:
+       case WM8904_DC_SERVO_6:
+       case WM8904_DC_SERVO_7:
+       case WM8904_DC_SERVO_8:
+       case WM8904_DC_SERVO_9:
+       case WM8904_DC_SERVO_READBACK_0:
+       case WM8904_INTERRUPT_STATUS:
+               return true;
+       default:
+               return false;
+       }
+}
 
-static int wm8904_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8904_readable_register(struct device *dev, unsigned int reg)
 {
-       return wm8904_access[reg].vol;
+       switch (reg) {
+       case WM8904_SW_RESET_AND_ID:
+       case WM8904_REVISION:
+       case WM8904_BIAS_CONTROL_0:
+       case WM8904_VMID_CONTROL_0:
+       case WM8904_MIC_BIAS_CONTROL_0:
+       case WM8904_MIC_BIAS_CONTROL_1:
+       case WM8904_ANALOGUE_DAC_0:
+       case WM8904_MIC_FILTER_CONTROL:
+       case WM8904_ANALOGUE_ADC_0:
+       case WM8904_POWER_MANAGEMENT_0:
+       case WM8904_POWER_MANAGEMENT_2:
+       case WM8904_POWER_MANAGEMENT_3:
+       case WM8904_POWER_MANAGEMENT_6:
+       case WM8904_CLOCK_RATES_0:
+       case WM8904_CLOCK_RATES_1:
+       case WM8904_CLOCK_RATES_2:
+       case WM8904_AUDIO_INTERFACE_0:
+       case WM8904_AUDIO_INTERFACE_1:
+       case WM8904_AUDIO_INTERFACE_2:
+       case WM8904_AUDIO_INTERFACE_3:
+       case WM8904_DAC_DIGITAL_VOLUME_LEFT:
+       case WM8904_DAC_DIGITAL_VOLUME_RIGHT:
+       case WM8904_DAC_DIGITAL_0:
+       case WM8904_DAC_DIGITAL_1:
+       case WM8904_ADC_DIGITAL_VOLUME_LEFT:
+       case WM8904_ADC_DIGITAL_VOLUME_RIGHT:
+       case WM8904_ADC_DIGITAL_0:
+       case WM8904_DIGITAL_MICROPHONE_0:
+       case WM8904_DRC_0:
+       case WM8904_DRC_1:
+       case WM8904_DRC_2:
+       case WM8904_DRC_3:
+       case WM8904_ANALOGUE_LEFT_INPUT_0:
+       case WM8904_ANALOGUE_RIGHT_INPUT_0:
+       case WM8904_ANALOGUE_LEFT_INPUT_1:
+       case WM8904_ANALOGUE_RIGHT_INPUT_1:
+       case WM8904_ANALOGUE_OUT1_LEFT:
+       case WM8904_ANALOGUE_OUT1_RIGHT:
+       case WM8904_ANALOGUE_OUT2_LEFT:
+       case WM8904_ANALOGUE_OUT2_RIGHT:
+       case WM8904_ANALOGUE_OUT12_ZC:
+       case WM8904_DC_SERVO_0:
+       case WM8904_DC_SERVO_1:
+       case WM8904_DC_SERVO_2:
+       case WM8904_DC_SERVO_4:
+       case WM8904_DC_SERVO_5:
+       case WM8904_DC_SERVO_6:
+       case WM8904_DC_SERVO_7:
+       case WM8904_DC_SERVO_8:
+       case WM8904_DC_SERVO_9:
+       case WM8904_DC_SERVO_READBACK_0:
+       case WM8904_ANALOGUE_HP_0:
+       case WM8904_ANALOGUE_LINEOUT_0:
+       case WM8904_CHARGE_PUMP_0:
+       case WM8904_CLASS_W_0:
+       case WM8904_WRITE_SEQUENCER_0:
+       case WM8904_WRITE_SEQUENCER_1:
+       case WM8904_WRITE_SEQUENCER_2:
+       case WM8904_WRITE_SEQUENCER_3:
+       case WM8904_WRITE_SEQUENCER_4:
+       case WM8904_FLL_CONTROL_1:
+       case WM8904_FLL_CONTROL_2:
+       case WM8904_FLL_CONTROL_3:
+       case WM8904_FLL_CONTROL_4:
+       case WM8904_FLL_CONTROL_5:
+       case WM8904_GPIO_CONTROL_1:
+       case WM8904_GPIO_CONTROL_2:
+       case WM8904_GPIO_CONTROL_3:
+       case WM8904_GPIO_CONTROL_4:
+       case WM8904_DIGITAL_PULLS:
+       case WM8904_INTERRUPT_STATUS:
+       case WM8904_INTERRUPT_STATUS_MASK:
+       case WM8904_INTERRUPT_POLARITY:
+       case WM8904_INTERRUPT_DEBOUNCE:
+       case WM8904_EQ1:
+       case WM8904_EQ2:
+       case WM8904_EQ3:
+       case WM8904_EQ4:
+       case WM8904_EQ5:
+       case WM8904_EQ6:
+       case WM8904_EQ7:
+       case WM8904_EQ8:
+       case WM8904_EQ9:
+       case WM8904_EQ10:
+       case WM8904_EQ11:
+       case WM8904_EQ12:
+       case WM8904_EQ13:
+       case WM8904_EQ14:
+       case WM8904_EQ15:
+       case WM8904_EQ16:
+       case WM8904_EQ17:
+       case WM8904_EQ18:
+       case WM8904_EQ19:
+       case WM8904_EQ20:
+       case WM8904_EQ21:
+       case WM8904_EQ22:
+       case WM8904_EQ23:
+       case WM8904_EQ24:
+       case WM8904_CONTROL_INTERFACE_TEST_1:
+       case WM8904_ADC_TEST_0:
+       case WM8904_ANALOGUE_OUTPUT_BIAS_0:
+       case WM8904_FLL_NCO_TEST_0:
+       case WM8904_FLL_NCO_TEST_1:
+               return true;
+       default:
+               return true;
+       }
 }
 
 static int wm8904_reset(struct snd_soc_codec *codec)
@@ -855,6 +570,29 @@ static const char *hpf_mode_text[] = {
 static const struct soc_enum hpf_mode =
        SOC_ENUM_SINGLE(WM8904_ADC_DIGITAL_0, 5, 4, hpf_mode_text);
 
+static int wm8904_adc_osr_put(struct snd_kcontrol *kcontrol,
+                             struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       unsigned int val;
+       int ret;
+
+       ret = snd_soc_put_volsw(kcontrol, ucontrol);
+       if (ret < 0)
+               return ret;
+
+       if (ucontrol->value.integer.value[0])
+               val = 0;
+       else
+               val = WM8904_ADC_128_OSR_TST_MODE | WM8904_ADC_BIASX1P5;
+
+       snd_soc_update_bits(codec, WM8904_ADC_TEST_0,
+                           WM8904_ADC_128_OSR_TST_MODE | WM8904_ADC_BIASX1P5,
+                           val);
+
+       return ret;
+}
+
 static const struct snd_kcontrol_new wm8904_adc_snd_controls[] = {
 SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8904_ADC_DIGITAL_VOLUME_LEFT,
                 WM8904_ADC_DIGITAL_VOLUME_RIGHT, 1, 119, 0, digital_tlv),
@@ -871,7 +609,12 @@ SOC_DOUBLE_R("Capture Switch", WM8904_ANALOGUE_LEFT_INPUT_0,
 SOC_SINGLE("High Pass Filter Switch", WM8904_ADC_DIGITAL_0, 4, 1, 0),
 SOC_ENUM("High Pass Filter Mode", hpf_mode),
 
-SOC_SINGLE("ADC 128x OSR Switch", WM8904_ANALOGUE_ADC_0, 0, 1, 0),
+{       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "ADC 128x OSR Switch",
+       .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,
+       .put = wm8904_adc_osr_put,
+       .private_value = SOC_SINGLE_VALUE(WM8904_ANALOGUE_ADC_0, 0, 1, 0),
+},
 };
 
 static const char *drc_path_text[] = {
@@ -1433,11 +1176,11 @@ static int wm8904_add_widgets(struct snd_soc_codec *codec)
 
        switch (wm8904->devtype) {
        case WM8904:
-               snd_soc_add_controls(codec, wm8904_adc_snd_controls,
+               snd_soc_add_codec_controls(codec, wm8904_adc_snd_controls,
                                     ARRAY_SIZE(wm8904_adc_snd_controls));
-               snd_soc_add_controls(codec, wm8904_dac_snd_controls,
+               snd_soc_add_codec_controls(codec, wm8904_dac_snd_controls,
                                     ARRAY_SIZE(wm8904_dac_snd_controls));
-               snd_soc_add_controls(codec, wm8904_snd_controls,
+               snd_soc_add_codec_controls(codec, wm8904_snd_controls,
                                     ARRAY_SIZE(wm8904_snd_controls));
 
                snd_soc_dapm_new_controls(dapm, wm8904_adc_dapm_widgets,
@@ -1458,7 +1201,7 @@ static int wm8904_add_widgets(struct snd_soc_codec *codec)
                break;
 
        case WM8912:
-               snd_soc_add_controls(codec, wm8904_dac_snd_controls,
+               snd_soc_add_codec_controls(codec, wm8904_dac_snd_controls,
                                     ARRAY_SIZE(wm8904_dac_snd_controls));
 
                snd_soc_dapm_new_controls(dapm, wm8904_dac_dapm_widgets,
@@ -2088,32 +1831,6 @@ static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute)
        return 0;
 }
 
-static void wm8904_sync_cache(struct snd_soc_codec *codec)
-{
-       u16 *reg_cache = codec->reg_cache;
-       int i;
-
-       if (!codec->cache_sync)
-               return;
-
-       codec->cache_only = 0;
-
-       /* Sync back cached values if they're different from the
-        * hardware default.
-        */
-       for (i = 1; i < codec->driver->reg_cache_size; i++) {
-               if (!wm8904_access[i].writable)
-                       continue;
-
-               if (reg_cache[i] == wm8904_reg[i])
-                       continue;
-
-               snd_soc_write(codec, i, reg_cache[i]);
-       }
-
-       codec->cache_sync = 0;
-}
-
 static int wm8904_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
@@ -2146,7 +1863,7 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec,
                                return ret;
                        }
 
-                       wm8904_sync_cache(codec);
+                       regcache_sync(wm8904->regmap);
 
                        /* Enable bias */
                        snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0,
@@ -2303,7 +2020,7 @@ static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec)
        wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts;
        wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts;
 
-       ret = snd_soc_add_controls(codec, &control, 1);
+       ret = snd_soc_add_codec_controls(codec, &control, 1);
        if (ret != 0)
                dev_err(codec->dev,
                        "Failed to add ReTune Mobile control: %d\n", ret);
@@ -2316,7 +2033,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
        int ret, i;
 
        if (!pdata) {
-               snd_soc_add_controls(codec, wm8904_eq_controls,
+               snd_soc_add_codec_controls(codec, wm8904_eq_controls,
                                     ARRAY_SIZE(wm8904_eq_controls));
                return;
        }
@@ -2344,7 +2061,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
                wm8904->drc_enum.max = pdata->num_drc_cfgs;
                wm8904->drc_enum.texts = wm8904->drc_texts;
 
-               ret = snd_soc_add_controls(codec, &control, 1);
+               ret = snd_soc_add_codec_controls(codec, &control, 1);
                if (ret != 0)
                        dev_err(codec->dev,
                                "Failed to add DRC mode control: %d\n", ret);
@@ -2358,7 +2075,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
        if (pdata->num_retune_mobile_cfgs)
                wm8904_handle_retune_mobile_pdata(codec);
        else
-               snd_soc_add_controls(codec, wm8904_eq_controls,
+               snd_soc_add_codec_controls(codec, wm8904_eq_controls,
                                     ARRAY_SIZE(wm8904_eq_controls));
 }
 
@@ -2371,7 +2088,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)
        int ret, i;
 
        codec->cache_sync = 1;
-       codec->dapm.idle_bias_off = 1;
+       codec->control_data = wm8904->regmap;
 
        switch (wm8904->devtype) {
        case WM8904:
@@ -2385,7 +2102,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)
                return -EINVAL;
        }
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
@@ -2413,7 +2130,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)
                dev_err(codec->dev, "Failed to read ID register\n");
                goto err_enable;
        }
-       if (ret != wm8904_reg[WM8904_SW_RESET_AND_ID]) {
+       if (ret != 0x8904) {
                dev_err(codec->dev, "Device is not a WM8904, ID is %x\n", ret);
                ret = -EINVAL;
                goto err_enable;
@@ -2519,38 +2236,62 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8904 = {
        .suspend =      wm8904_suspend,
        .resume =       wm8904_resume,
        .set_bias_level = wm8904_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8904_reg),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8904_reg,
-       .volatile_register = wm8904_volatile_register,
+       .idle_bias_off = true,
+};
+
+static const struct regmap_config wm8904_regmap = {
+       .reg_bits = 8,
+       .val_bits = 16,
+
+       .max_register = WM8904_MAX_REGISTER,
+       .volatile_reg = wm8904_volatile_register,
+       .readable_reg = wm8904_readable_register,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = wm8904_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8904_reg_defaults),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm8904_priv *wm8904;
        int ret;
 
-       wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL);
+       wm8904 = devm_kzalloc(&i2c->dev, sizeof(struct wm8904_priv),
+                             GFP_KERNEL);
        if (wm8904 == NULL)
                return -ENOMEM;
 
+       wm8904->regmap = regmap_init_i2c(i2c, &wm8904_regmap);
+       if (IS_ERR(wm8904->regmap)) {
+               ret = PTR_ERR(wm8904->regmap);
+               dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               return ret;
+       }
+
        wm8904->devtype = id->driver_data;
        i2c_set_clientdata(i2c, wm8904);
        wm8904->pdata = i2c->dev.platform_data;
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8904, &wm8904_dai, 1);
-       if (ret < 0)
-               kfree(wm8904);
+       if (ret != 0)
+               goto err;
+
+       return 0;
+
+err:
+       regmap_exit(wm8904->regmap);
        return ret;
 }
 
 static __devexit int wm8904_i2c_remove(struct i2c_client *client)
 {
+       struct wm8904_priv *wm8904 = i2c_get_clientdata(client);
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+       regmap_exit(wm8904->regmap);
        return 0;
 }
 
@@ -2571,27 +2312,22 @@ static struct i2c_driver wm8904_i2c_driver = {
        .remove =   __devexit_p(wm8904_i2c_remove),
        .id_table = wm8904_i2c_id,
 };
-#endif
 
 static int __init wm8904_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8904_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n",
                       ret);
        }
-#endif
        return ret;
 }
 module_init(wm8904_modinit);
 
 static void __exit wm8904_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8904_i2c_driver);
-#endif
 }
 module_exit(wm8904_exit);
 
index 9e8c84188ba761bb0eb606029e7c80f8d34e8219..c29a0e8131ca97e2d87cffcb9ad4105a87a437b9 100644 (file)
 #define WM8904_EQ23                             0x9C
 #define WM8904_EQ24                             0x9D
 #define WM8904_CONTROL_INTERFACE_TEST_1         0xA1
+#define WM8904_ADC_TEST_0                      0xC6
 #define WM8904_ANALOGUE_OUTPUT_BIAS_0           0xCC
 #define WM8904_FLL_NCO_TEST_0                   0xF7
 #define WM8904_FLL_NCO_TEST_1                   0xF8
 #define WM8904_USER_KEY_SHIFT                        1  /* USER_KEY */
 #define WM8904_USER_KEY_WIDTH                        1  /* USER_KEY */
 
+/*
+ * R198 (0xC6) - ADC Test 0
+ */
+#define WM8904_ADC_128_OSR_TST_MODE             0x0004  /* ADC_128_OSR_TST_MODE */
+#define WM8904_ADC_128_OSR_TST_MODE_SHIFT            2  /* ADC_128_OSR_TST_MODE */
+#define WM8904_ADC_128_OSR_TST_MODE_WIDTH            1  /* ADC_128_OSR_TST_MODE */
+#define WM8904_ADC_BIASX1P5                     0x0001  /* ADC_BIASX1P5 */
+#define WM8904_ADC_BIASX1P5_SHIFT                    0  /* ADC_BIASX1P5 */
+#define WM8904_ADC_BIASX1P5_WIDTH                    1  /* ADC_BIASX1P5 */
+
 /*
  * R204 (0xCC) - Analogue Output Bias 0
  */
index 14039ea2f3e4a13d9e882fefe3c2dd4f387bb670..d2883affea3b2421508c474732d3fdf92192bdb2 100644 (file)
@@ -717,7 +717,7 @@ static int wm8940_probe(struct snd_soc_codec *codec)
                        return ret;
        }
 
-       ret = snd_soc_add_controls(codec, wm8940_snd_controls,
+       ret = snd_soc_add_codec_controls(codec, wm8940_snd_controls,
                             ARRAY_SIZE(wm8940_snd_controls));
        if (ret)
                return ret;
@@ -743,14 +743,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
        .volatile_register = wm8940_volatile_register,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm8940_priv *wm8940;
        int ret;
 
-       wm8940 = kzalloc(sizeof(struct wm8940_priv), GFP_KERNEL);
+       wm8940 = devm_kzalloc(&i2c->dev, sizeof(struct wm8940_priv),
+                             GFP_KERNEL);
        if (wm8940 == NULL)
                return -ENOMEM;
 
@@ -759,15 +759,14 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8940, &wm8940_dai, 1);
-       if (ret < 0)
-               kfree(wm8940);
+
        return ret;
 }
 
 static __devexit int wm8940_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+
        return 0;
 }
 
@@ -786,27 +785,22 @@ static struct i2c_driver wm8940_i2c_driver = {
        .remove =   __devexit_p(wm8940_i2c_remove),
        .id_table = wm8940_i2c_id,
 };
-#endif
 
 static int __init wm8940_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8940_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register wm8940 I2C driver: %d\n",
                       ret);
        }
-#endif
        return ret;
 }
 module_init(wm8940_modinit);
 
 static void __exit wm8940_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8940_i2c_driver);
-#endif
 }
 module_exit(wm8940_exit);
 
index 924548182d58f86257e1a4a2d9fde8125e67a8af..61fe97433e738eb43c486115a985fc1bd0ad68f5 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -38,7 +39,7 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
 
 /* codec private data */
 struct wm8955_priv {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
 
        unsigned int mclk_rate;
 
@@ -48,69 +49,85 @@ struct wm8955_priv {
        struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES];
 };
 
-static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = {
-       0x0000,     /* R0 */
-       0x0000,     /* R1 */
-       0x0079,     /* R2  - LOUT1 volume */
-       0x0079,     /* R3  - ROUT1 volume */
-       0x0000,     /* R4 */
-       0x0008,     /* R5  - DAC Control */
-       0x0000,     /* R6 */
-       0x000A,     /* R7  - Audio Interface */
-       0x0000,     /* R8  - Sample Rate */
-       0x0000,     /* R9 */
-       0x00FF,     /* R10 - Left DAC volume */
-       0x00FF,     /* R11 - Right DAC volume */
-       0x000F,     /* R12 - Bass control */
-       0x000F,     /* R13 - Treble control */
-       0x0000,     /* R14 */
-       0x0000,     /* R15 - Reset */
-       0x0000,     /* R16 */
-       0x0000,     /* R17 */
-       0x0000,     /* R18 */
-       0x0000,     /* R19 */
-       0x0000,     /* R20 */
-       0x0000,     /* R21 */
-       0x0000,     /* R22 */
-       0x00C1,     /* R23 - Additional control (1) */
-       0x0000,     /* R24 - Additional control (2) */
-       0x0000,     /* R25 - Power Management (1) */
-       0x0000,     /* R26 - Power Management (2) */
-       0x0000,     /* R27 - Additional Control (3) */
-       0x0000,     /* R28 */
-       0x0000,     /* R29 */
-       0x0000,     /* R30 */
-       0x0000,     /* R31 */
-       0x0000,     /* R32 */
-       0x0000,     /* R33 */
-       0x0050,     /* R34 - Left out Mix (1) */
-       0x0050,     /* R35 - Left out Mix (2) */
-       0x0050,     /* R36 - Right out Mix (1) */
-       0x0050,     /* R37 - Right Out Mix (2) */
-       0x0050,     /* R38 - Mono out Mix (1) */
-       0x0050,     /* R39 - Mono out Mix (2) */
-       0x0079,     /* R40 - LOUT2 volume */
-       0x0079,     /* R41 - ROUT2 volume */
-       0x0079,     /* R42 - MONOOUT volume */
-       0x0000,     /* R43 - Clocking / PLL */
-       0x0103,     /* R44 - PLL Control 1 */
-       0x0024,     /* R45 - PLL Control 2 */
-       0x01BA,     /* R46 - PLL Control 3 */
-       0x0000,     /* R47 */
-       0x0000,     /* R48 */
-       0x0000,     /* R49 */
-       0x0000,     /* R50 */
-       0x0000,     /* R51 */
-       0x0000,     /* R52 */
-       0x0000,     /* R53 */
-       0x0000,     /* R54 */
-       0x0000,     /* R55 */
-       0x0000,     /* R56 */
-       0x0000,     /* R57 */
-       0x0000,     /* R58 */
-       0x0000,     /* R59 - PLL Control 4 */
+static const struct reg_default wm8955_reg_defaults[] = {
+       { 2,  0x0079 },     /* R2  - LOUT1 volume */
+       { 3,  0x0079 },     /* R3  - ROUT1 volume */
+       { 5,  0x0008 },     /* R5  - DAC Control */
+       { 7,  0x000A },     /* R7  - Audio Interface */
+       { 8,  0x0000 },     /* R8  - Sample Rate */
+       { 10, 0x00FF },     /* R10 - Left DAC volume */
+       { 11, 0x00FF },     /* R11 - Right DAC volume */
+       { 12, 0x000F },     /* R12 - Bass control */
+       { 13, 0x000F },     /* R13 - Treble control */
+       { 23, 0x00C1 },     /* R23 - Additional control (1) */
+       { 24, 0x0000 },     /* R24 - Additional control (2) */
+       { 25, 0x0000 },     /* R25 - Power Management (1) */
+       { 26, 0x0000 },     /* R26 - Power Management (2) */
+       { 27, 0x0000 },     /* R27 - Additional Control (3) */
+       { 34, 0x0050 },     /* R34 - Left out Mix (1) */
+       { 35, 0x0050 },     /* R35 - Left out Mix (2) */
+       { 36, 0x0050 },     /* R36 - Right out Mix (1) */
+       { 37, 0x0050 },     /* R37 - Right Out Mix (2) */
+       { 38, 0x0050 },     /* R38 - Mono out Mix (1) */
+       { 39, 0x0050 },     /* R39 - Mono out Mix (2) */
+       { 40, 0x0079 },     /* R40 - LOUT2 volume */
+       { 41, 0x0079 },     /* R41 - ROUT2 volume */
+       { 42, 0x0079 },     /* R42 - MONOOUT volume */
+       { 43, 0x0000 },     /* R43 - Clocking / PLL */
+       { 44, 0x0103 },     /* R44 - PLL Control 1 */
+       { 45, 0x0024 },     /* R45 - PLL Control 2 */
+       { 46, 0x01BA },     /* R46 - PLL Control 3 */
+       { 59, 0x0000 },     /* R59 - PLL Control 4 */
 };
 
+static bool wm8955_writeable(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM8955_LOUT1_VOLUME:
+       case WM8955_ROUT1_VOLUME:
+       case WM8955_DAC_CONTROL:
+       case WM8955_AUDIO_INTERFACE:
+       case WM8955_SAMPLE_RATE:
+       case WM8955_LEFT_DAC_VOLUME:
+       case WM8955_RIGHT_DAC_VOLUME:
+       case WM8955_BASS_CONTROL:
+       case WM8955_TREBLE_CONTROL:
+       case WM8955_RESET:
+       case WM8955_ADDITIONAL_CONTROL_1:
+       case WM8955_ADDITIONAL_CONTROL_2:
+       case WM8955_POWER_MANAGEMENT_1:
+       case WM8955_POWER_MANAGEMENT_2:
+       case WM8955_ADDITIONAL_CONTROL_3:
+       case WM8955_LEFT_OUT_MIX_1:
+       case WM8955_LEFT_OUT_MIX_2:
+       case WM8955_RIGHT_OUT_MIX_1:
+       case WM8955_RIGHT_OUT_MIX_2:
+       case WM8955_MONO_OUT_MIX_1:
+       case WM8955_MONO_OUT_MIX_2:
+       case WM8955_LOUT2_VOLUME:
+       case WM8955_ROUT2_VOLUME:
+       case WM8955_MONOOUT_VOLUME:
+       case WM8955_CLOCKING_PLL:
+       case WM8955_PLL_CONTROL_1:
+       case WM8955_PLL_CONTROL_2:
+       case WM8955_PLL_CONTROL_3:
+       case WM8955_PLL_CONTROL_4:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool wm8955_volatile(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM8955_RESET:
+               return true;
+       default:
+               return false;
+       }
+}
+
 static int wm8955_reset(struct snd_soc_codec *codec)
 {
        return snd_soc_write(codec, WM8955_RESET, 0);
@@ -527,7 +544,7 @@ SND_SOC_DAPM_OUTPUT("MONOOUT"),
 SND_SOC_DAPM_OUTPUT("OUT3"),
 };
 
-static const struct snd_soc_dapm_route wm8955_intercon[] = {
+static const struct snd_soc_dapm_route wm8955_dapm_routes[] = {
        { "DACL", NULL, "SYSCLK" },
        { "DACR", NULL, "SYSCLK" },
 
@@ -572,21 +589,6 @@ static const struct snd_soc_dapm_route wm8955_intercon[] = {
        { "OUT3", NULL, "OUT3 PGA" },
 };
 
-static int wm8955_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_add_controls(codec, wm8955_snd_controls,
-                            ARRAY_SIZE(wm8955_snd_controls));
-
-       snd_soc_dapm_new_controls(dapm, wm8955_dapm_widgets,
-                                 ARRAY_SIZE(wm8955_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, wm8955_intercon,
-                               ARRAY_SIZE(wm8955_intercon));
-
-       return 0;
-}
-
 static int wm8955_hw_params(struct snd_pcm_substream *substream,
                            struct snd_pcm_hw_params *params,
                            struct snd_soc_dai *dai)
@@ -765,8 +767,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
        struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
-       u16 *reg_cache = codec->reg_cache;
-       int ret, i;
+       int ret;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
@@ -795,18 +796,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
                                return ret;
                        }
 
-                       /* Sync back cached values if they're
-                        * different from the hardware default.
-                        */
-                       for (i = 0; i < codec->driver->reg_cache_size; i++) {
-                               if (i == WM8955_RESET)
-                                       continue;
-
-                               if (reg_cache[i] == wm8955_reg[i])
-                                       continue;
-
-                               snd_soc_write(codec, i, reg_cache[i]);
-                       }
+                       regcache_sync(wm8955->regmap);
 
                        /* Enable VREF and VMID */
                        snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1,
@@ -880,8 +870,12 @@ static struct snd_soc_dai_driver wm8955_dai = {
 #ifdef CONFIG_PM
 static int wm8955_suspend(struct snd_soc_codec *codec)
 {
+       struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
+
        wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
+       regcache_mark_dirty(wm8955->regmap);
+
        return 0;
 }
 
@@ -900,10 +894,11 @@ static int wm8955_probe(struct snd_soc_codec *codec)
 {
        struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
        struct wm8955_pdata *pdata = dev_get_platdata(codec->dev);
-       u16 *reg_cache = codec->reg_cache;
        int ret, i;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type);
+       codec->control_data = wm8955->regmap;
+
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
@@ -958,12 +953,12 @@ static int wm8955_probe(struct snd_soc_codec *codec)
        /* Set platform data values */
        if (pdata) {
                if (pdata->out2_speaker)
-                       reg_cache[WM8955_ADDITIONAL_CONTROL_2]
-                               |= WM8955_ROUT2INV;
+                       snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_2,
+                                           WM8955_ROUT2INV, WM8955_ROUT2INV);
 
                if (pdata->monoin_diff)
-                       reg_cache[WM8955_MONO_OUT_MIX_1]
-                               |= WM8955_DMEN;
+                       snd_soc_update_bits(codec, WM8955_MONO_OUT_MIX_1,
+                                           WM8955_DMEN, WM8955_DMEN);
        }
 
        wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -971,7 +966,6 @@ static int wm8955_probe(struct snd_soc_codec *codec)
        /* Bias level configuration will have done an extra enable */
        regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
 
-       wm8955_add_widgets(codec);
        return 0;
 
 err_enable:
@@ -996,36 +990,68 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8955 = {
        .suspend =      wm8955_suspend,
        .resume =       wm8955_resume,
        .set_bias_level = wm8955_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8955_reg),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8955_reg,
+
+       .controls =     wm8955_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8955_snd_controls),
+       .dapm_widgets = wm8955_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8955_dapm_widgets),
+       .dapm_routes =  wm8955_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8955_dapm_routes),
+};
+
+static const struct regmap_config wm8955_regmap = {
+       .reg_bits = 7,
+       .val_bits = 9,
+
+       .max_register = WM8955_MAX_REGISTER,
+       .volatile_reg = wm8955_volatile,
+       .writeable_reg = wm8955_writeable,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = wm8955_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8955_reg_defaults),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm8955_priv *wm8955;
        int ret;
 
-       wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL);
+       wm8955 = devm_kzalloc(&i2c->dev, sizeof(struct wm8955_priv),
+                             GFP_KERNEL);
        if (wm8955 == NULL)
                return -ENOMEM;
 
+       wm8955->regmap = regmap_init_i2c(i2c, &wm8955_regmap);
+       if (IS_ERR(wm8955->regmap)) {
+               ret = PTR_ERR(wm8955->regmap);
+               dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               return ret;
+       }
+
        i2c_set_clientdata(i2c, wm8955);
-       wm8955->control_type = SND_SOC_I2C;
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8955, &wm8955_dai, 1);
-       if (ret < 0)
-               kfree(wm8955);
+       if (ret != 0)
+               goto err;
+
+       return ret;
+
+err:
+       regmap_exit(wm8955->regmap);
        return ret;
 }
 
 static __devexit int wm8955_i2c_remove(struct i2c_client *client)
 {
+       struct wm8955_priv *wm8955 = i2c_get_clientdata(client);
+
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+       regmap_exit(wm8955->regmap);
+
        return 0;
 }
 
@@ -1044,27 +1070,22 @@ static struct i2c_driver wm8955_i2c_driver = {
        .remove =   __devexit_p(wm8955_i2c_remove),
        .id_table = wm8955_i2c_id,
 };
-#endif
 
 static int __init wm8955_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8955_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register WM8955 I2C driver: %d\n",
                       ret);
        }
-#endif
        return ret;
 }
 module_init(wm8955_modinit);
 
 static void __exit wm8955_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8955_i2c_driver);
-#endif
 }
 module_exit(wm8955_exit);
 
index 40ac888faf3d7633f433257ab96e2f190d6f4174..1332692ef81bc9628e8cad04ccf65cd972c7fb8c 100644 (file)
@@ -920,11 +920,11 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
 
        wm8994->dsp_active = -1;
 
-       snd_soc_add_controls(codec, wm8958_mbc_snd_controls,
+       snd_soc_add_codec_controls(codec, wm8958_mbc_snd_controls,
                             ARRAY_SIZE(wm8958_mbc_snd_controls));
-       snd_soc_add_controls(codec, wm8958_vss_snd_controls,
+       snd_soc_add_codec_controls(codec, wm8958_vss_snd_controls,
                             ARRAY_SIZE(wm8958_vss_snd_controls));
-       snd_soc_add_controls(codec, wm8958_enh_eq_snd_controls,
+       snd_soc_add_codec_controls(codec, wm8958_enh_eq_snd_controls,
                             ARRAY_SIZE(wm8958_enh_eq_snd_controls));
 
 
@@ -958,7 +958,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
                wm8994->mbc_enum.max = pdata->num_mbc_cfgs;
                wm8994->mbc_enum.texts = wm8994->mbc_texts;
 
-               ret = snd_soc_add_controls(wm8994->codec, control, 1);
+               ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
                if (ret != 0)
                        dev_err(wm8994->codec->dev,
                                "Failed to add MBC mode controls: %d\n", ret);
@@ -986,7 +986,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
                wm8994->vss_enum.max = pdata->num_vss_cfgs;
                wm8994->vss_enum.texts = wm8994->vss_texts;
 
-               ret = snd_soc_add_controls(wm8994->codec, control, 1);
+               ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
                if (ret != 0)
                        dev_err(wm8994->codec->dev,
                                "Failed to add VSS mode controls: %d\n", ret);
@@ -1015,7 +1015,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
                wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs;
                wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts;
 
-               ret = snd_soc_add_controls(wm8994->codec, control, 1);
+               ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
                if (ret != 0)
                        dev_err(wm8994->codec->dev,
                                "Failed to add VSS HPFmode controls: %d\n",
@@ -1045,7 +1045,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
                wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs;
                wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts;
 
-               ret = snd_soc_add_controls(wm8994->codec, control, 1);
+               ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
                if (ret != 0)
                        dev_err(wm8994->codec->dev,
                                "Failed to add enhanced EQ controls: %d\n",
index e5caae32e5419a695f0533b833fb3d719ccbbf4c..840d72086d04c7c3cf8dcf7d813c9a4f8ee149d7 100644 (file)
@@ -940,7 +940,7 @@ static int wm8960_probe(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, WM8960_LOUT2, 0x100, 0x100);
        snd_soc_update_bits(codec, WM8960_ROUT2, 0x100, 0x100);
 
-       snd_soc_add_controls(codec, wm8960_snd_controls,
+       snd_soc_add_codec_controls(codec, wm8960_snd_controls,
                                     ARRAY_SIZE(wm8960_snd_controls));
        wm8960_add_widgets(codec);
 
index 4f20c72a0f1d329a824ee2255f6003ef741c07da..05ea7c2740933b0ff4b2cbfedc3be54515670fa8 100644 (file)
@@ -1022,7 +1022,7 @@ static int wm8961_probe(struct snd_soc_codec *codec)
 
        wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       snd_soc_add_controls(codec, wm8961_snd_controls,
+       snd_soc_add_codec_controls(codec, wm8961_snd_controls,
                                ARRAY_SIZE(wm8961_snd_controls));
        snd_soc_dapm_new_controls(dapm, wm8961_dapm_widgets,
                                  ARRAY_SIZE(wm8961_dapm_widgets));
index 29c4b02c4790681743ba82e6e3c3d6d87c558b8e..2dd710f58b858d72485dd91604200a6173f2a599 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
@@ -797,1167 +798,660 @@ static struct reg_default wm8962_reg[] = {
        { 21139, 0x8580 },   /* R21139 - VSS_XTS32_0 */
 };
 
-static const struct wm8962_reg_access {
-       u16 read;
-       u16 write;
-       u16 vol;
-} wm8962_reg_access[WM8962_MAX_REGISTER + 1] = {
-       [0] = { 0x00FF, 0x01FF, 0x0000 }, /* R0     - Left Input volume */
-       [1] = { 0xFEFF, 0x01FF, 0x0000 }, /* R1     - Right Input volume */
-       [2] = { 0x00FF, 0x01FF, 0x0000 }, /* R2     - HPOUTL volume */
-       [3] = { 0x00FF, 0x01FF, 0x0000 }, /* R3     - HPOUTR volume */
-       [4] = { 0x07FE, 0x07FE, 0xFFFF }, /* R4     - Clocking1 */
-       [5] = { 0x007F, 0x007F, 0x0000 }, /* R5     - ADC & DAC Control 1 */
-       [6] = { 0x37ED, 0x37ED, 0x0000 }, /* R6     - ADC & DAC Control 2 */
-       [7] = { 0x1FFF, 0x1FFF, 0x0000 }, /* R7     - Audio Interface 0 */
-       [8] = { 0x0FEF, 0x0FEF, 0xFFFF }, /* R8     - Clocking2 */
-       [9] = { 0x0B9F, 0x039F, 0x0000 }, /* R9     - Audio Interface 1 */
-       [10] = { 0x00FF, 0x01FF, 0x0000 }, /* R10    - Left DAC volume */
-       [11] = { 0x00FF, 0x01FF, 0x0000 }, /* R11    - Right DAC volume */
-       [14] = { 0x07FF, 0x07FF, 0x0000 }, /* R14    - Audio Interface 2 */
-       [15] = { 0xFFFF, 0xFFFF, 0xFFFF }, /* R15    - Software Reset */
-       [17] = { 0x07FF, 0x07FF, 0x0000 }, /* R17    - ALC1 */
-       [18] = { 0xF8FF, 0x00FF, 0xFFFF }, /* R18    - ALC2 */
-       [19] = { 0x1DFF, 0x1DFF, 0x0000 }, /* R19    - ALC3 */
-       [20] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20    - Noise Gate */
-       [21] = { 0x00FF, 0x01FF, 0x0000 }, /* R21    - Left ADC volume */
-       [22] = { 0x00FF, 0x01FF, 0x0000 }, /* R22    - Right ADC volume */
-       [23] = { 0x0161, 0x0161, 0x0000 }, /* R23    - Additional control(1) */
-       [24] = { 0x0008, 0x0008, 0x0000 }, /* R24    - Additional control(2) */
-       [25] = { 0x07FE, 0x07FE, 0x0000 }, /* R25    - Pwr Mgmt (1) */
-       [26] = { 0x01FB, 0x01FB, 0x0000 }, /* R26    - Pwr Mgmt (2) */
-       [27] = { 0x0017, 0x0017, 0x0000 }, /* R27    - Additional Control (3) */
-       [28] = { 0x001C, 0x001C, 0x0000 }, /* R28    - Anti-pop */
-
-       [30] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R30    - Clocking 3 */
-       [31] = { 0x000F, 0x000F, 0x0000 }, /* R31    - Input mixer control (1) */
-       [32] = { 0x01FF, 0x01FF, 0x0000 }, /* R32    - Left input mixer volume */
-       [33] = { 0x01FF, 0x01FF, 0x0000 }, /* R33    - Right input mixer volume */
-       [34] = { 0x003F, 0x003F, 0x0000 }, /* R34    - Input mixer control (2) */
-       [35] = { 0x003F, 0x003F, 0x0000 }, /* R35    - Input bias control */
-       [37] = { 0x001F, 0x001F, 0x0000 }, /* R37    - Left input PGA control */
-       [38] = { 0x001F, 0x001F, 0x0000 }, /* R38    - Right input PGA control */
-       [40] = { 0x00FF, 0x01FF, 0x0000 }, /* R40    - SPKOUTL volume */
-       [41] = { 0x00FF, 0x01FF, 0x0000 }, /* R41    - SPKOUTR volume */
-
-       [47] = { 0x000F, 0x0000, 0xFFFF }, /* R47    - Thermal Shutdown Status */
-       [48] = { 0x7EC7, 0x7E07, 0xFFFF }, /* R48    - Additional Control (4) */
-       [49] = { 0x00D3, 0x00D7, 0xFFFF }, /* R49    - Class D Control 1 */
-       [51] = { 0x0047, 0x0047, 0x0000 }, /* R51    - Class D Control 2 */
-       [56] = { 0x001E, 0x001E, 0x0000 }, /* R56    - Clocking 4 */
-       [57] = { 0x02FC, 0x02FC, 0x0000 }, /* R57    - DAC DSP Mixing (1) */
-       [58] = { 0x00FC, 0x00FC, 0x0000 }, /* R58    - DAC DSP Mixing (2) */
-       [60] = { 0x00CC, 0x00CC, 0x0000 }, /* R60    - DC Servo 0 */
-       [61] = { 0x00DD, 0x00DD, 0x0000 }, /* R61    - DC Servo 1 */
-       [64] = { 0x3F80, 0x3F80, 0x0000 }, /* R64    - DC Servo 4 */
-       [66] = { 0x0780, 0x0000, 0xFFFF }, /* R66    - DC Servo 6 */
-       [68] = { 0x0007, 0x0007, 0x0000 }, /* R68    - Analogue PGA Bias */
-       [69] = { 0x00FF, 0x00FF, 0x0000 }, /* R69    - Analogue HP 0 */
-       [71] = { 0x01FF, 0x01FF, 0x0000 }, /* R71    - Analogue HP 2 */
-       [72] = { 0x0001, 0x0001, 0x0000 }, /* R72    - Charge Pump 1 */
-       [82] = { 0x0001, 0x0001, 0x0000 }, /* R82    - Charge Pump B */
-       [87] = { 0x00A0, 0x00A0, 0x0000 }, /* R87    - Write Sequencer Control 1 */
-       [90] = { 0x007F, 0x01FF, 0x0000 }, /* R90    - Write Sequencer Control 2 */
-       [93] = { 0x03F9, 0x0000, 0x0000 }, /* R93    - Write Sequencer Control 3 */
-       [94] = { 0x0070, 0x0070, 0x0000 }, /* R94    - Control Interface */
-       [99] = { 0x000F, 0x000F, 0x0000 }, /* R99    - Mixer Enables */
-       [100] = { 0x00BF, 0x00BF, 0x0000 }, /* R100   - Headphone Mixer (1) */
-       [101] = { 0x00BF, 0x00BF, 0x0000 }, /* R101   - Headphone Mixer (2) */
-       [102] = { 0x01FF, 0x01FF, 0x0000 }, /* R102   - Headphone Mixer (3) */
-       [103] = { 0x01FF, 0x01FF, 0x0000 }, /* R103   - Headphone Mixer (4) */
-       [105] = { 0x00BF, 0x00BF, 0x0000 }, /* R105   - Speaker Mixer (1) */
-       [106] = { 0x00BF, 0x00BF, 0x0000 }, /* R106   - Speaker Mixer (2) */
-       [107] = { 0x01FF, 0x01FF, 0x0000 }, /* R107   - Speaker Mixer (3) */
-       [108] = { 0x01FF, 0x01FF, 0x0000 }, /* R108   - Speaker Mixer (4) */
-       [109] = { 0x00F0, 0x00F0, 0x0000 }, /* R109   - Speaker Mixer (5) */
-       [110] = { 0x00F7, 0x00F7, 0x0000 }, /* R110   - Beep Generator (1) */
-       [115] = { 0x001F, 0x001F, 0x0000 }, /* R115   - Oscillator Trim (3) */
-       [116] = { 0x001F, 0x001F, 0x0000 }, /* R116   - Oscillator Trim (4) */
-       [119] = { 0x00FF, 0x00FF, 0x0000 }, /* R119   - Oscillator Trim (7) */
-       [124] = { 0x0079, 0x0079, 0x0000 }, /* R124   - Analogue Clocking1 */
-       [125] = { 0x00DF, 0x00DF, 0x0000 }, /* R125   - Analogue Clocking2 */
-       [126] = { 0x000D, 0x000D, 0x0000 }, /* R126   - Analogue Clocking3 */
-       [127] = { 0x0000, 0xFFFF, 0x0000 }, /* R127   - PLL Software Reset */
-       [129] = { 0x00B0, 0x00B0, 0x0000 }, /* R129   - PLL2 */
-       [131] = { 0x0003, 0x0003, 0x0000 }, /* R131   - PLL 4 */
-       [136] = { 0x005F, 0x005F, 0x0000 }, /* R136   - PLL 9 */
-       [137] = { 0x00FF, 0x00FF, 0x0000 }, /* R137   - PLL 10 */
-       [138] = { 0x00FF, 0x00FF, 0x0000 }, /* R138   - PLL 11 */
-       [139] = { 0x00FF, 0x00FF, 0x0000 }, /* R139   - PLL 12 */
-       [140] = { 0x005F, 0x005F, 0x0000 }, /* R140   - PLL 13 */
-       [141] = { 0x00FF, 0x00FF, 0x0000 }, /* R141   - PLL 14 */
-       [142] = { 0x00FF, 0x00FF, 0x0000 }, /* R142   - PLL 15 */
-       [143] = { 0x00FF, 0x00FF, 0x0000 }, /* R143   - PLL 16 */
-       [155] = { 0x0067, 0x0067, 0x0000 }, /* R155   - FLL Control (1) */
-       [156] = { 0x01FB, 0x01FB, 0x0000 }, /* R156   - FLL Control (2) */
-       [157] = { 0x0007, 0x0007, 0x0000 }, /* R157   - FLL Control (3) */
-       [159] = { 0x007F, 0x007F, 0x0000 }, /* R159   - FLL Control (5) */
-       [160] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R160   - FLL Control (6) */
-       [161] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R161   - FLL Control (7) */
-       [162] = { 0x03FF, 0x03FF, 0x0000 }, /* R162   - FLL Control (8) */
-       [252] = { 0x0005, 0x0005, 0x0000 }, /* R252   - General test 1 */
-       [256] = { 0x000F, 0x000F, 0x0000 }, /* R256   - DF1 */
-       [257] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R257   - DF2 */
-       [258] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R258   - DF3 */
-       [259] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R259   - DF4 */
-       [260] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R260   - DF5 */
-       [261] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R261   - DF6 */
-       [262] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R262   - DF7 */
-       [264] = { 0x0003, 0x0003, 0x0000 }, /* R264   - LHPF1 */
-       [265] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R265   - LHPF2 */
-       [268] = { 0x0077, 0x0077, 0x0000 }, /* R268   - THREED1 */
-       [269] = { 0xFFFC, 0xFFFC, 0x0000 }, /* R269   - THREED2 */
-       [270] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R270   - THREED3 */
-       [271] = { 0xFFFC, 0xFFFC, 0x0000 }, /* R271   - THREED4 */
-       [276] = { 0x7FFF, 0x7FFF, 0x0000 }, /* R276   - DRC 1 */
-       [277] = { 0x1FFF, 0x1FFF, 0x0000 }, /* R277   - DRC 2 */
-       [278] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R278   - DRC 3 */
-       [279] = { 0x07FF, 0x07FF, 0x0000 }, /* R279   - DRC 4 */
-       [280] = { 0x03FF, 0x03FF, 0x0000 }, /* R280   - DRC 5 */
-       [285] = { 0x0003, 0x0003, 0x0000 }, /* R285   - Tloopback */
-       [335] = { 0x0007, 0x0007, 0x0000 }, /* R335   - EQ1 */
-       [336] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R336   - EQ2 */
-       [337] = { 0xFFC0, 0xFFC0, 0x0000 }, /* R337   - EQ3 */
-       [338] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R338   - EQ4 */
-       [339] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R339   - EQ5 */
-       [340] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R340   - EQ6 */
-       [341] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R341   - EQ7 */
-       [342] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R342   - EQ8 */
-       [343] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R343   - EQ9 */
-       [344] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R344   - EQ10 */
-       [345] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R345   - EQ11 */
-       [346] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R346   - EQ12 */
-       [347] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R347   - EQ13 */
-       [348] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R348   - EQ14 */
-       [349] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R349   - EQ15 */
-       [350] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R350   - EQ16 */
-       [351] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R351   - EQ17 */
-       [352] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R352   - EQ18 */
-       [353] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R353   - EQ19 */
-       [354] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R354   - EQ20 */
-       [355] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R355   - EQ21 */
-       [356] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R356   - EQ22 */
-       [357] = { 0xFFC0, 0xFFC0, 0x0000 }, /* R357   - EQ23 */
-       [358] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R358   - EQ24 */
-       [359] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R359   - EQ25 */
-       [360] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R360   - EQ26 */
-       [361] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R361   - EQ27 */
-       [362] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R362   - EQ28 */
-       [363] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R363   - EQ29 */
-       [364] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R364   - EQ30 */
-       [365] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R365   - EQ31 */
-       [366] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R366   - EQ32 */
-       [367] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R367   - EQ33 */
-       [368] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R368   - EQ34 */
-       [369] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R369   - EQ35 */
-       [370] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R370   - EQ36 */
-       [371] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R371   - EQ37 */
-       [372] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R372   - EQ38 */
-       [373] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R373   - EQ39 */
-       [374] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R374   - EQ40 */
-       [375] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R375   - EQ41 */
-       [513] = { 0x045F, 0x045F, 0x0000 }, /* R513   - GPIO 2 */
-       [514] = { 0x045F, 0x045F, 0x0000 }, /* R514   - GPIO 3 */
-       [516] = { 0xE75F, 0xE75F, 0x0000 }, /* R516   - GPIO 5 */
-       [517] = { 0xE75F, 0xE75F, 0x0000 }, /* R517   - GPIO 6 */
-       [560] = { 0x0030, 0x0030, 0xFFFF }, /* R560   - Interrupt Status 1 */
-       [561] = { 0xFFED, 0xFFED, 0xFFFF }, /* R561   - Interrupt Status 2 */
-       [568] = { 0x0030, 0x0030, 0x0000 }, /* R568   - Interrupt Status 1 Mask */
-       [569] = { 0xFFED, 0xFFED, 0x0000 }, /* R569   - Interrupt Status 2 Mask */
-       [576] = { 0x0001, 0x0001, 0x0000 }, /* R576   - Interrupt Control */
-       [584] = { 0x002D, 0x002D, 0x0000 }, /* R584   - IRQ Debounce */
-       [586] = { 0xC000, 0xC000, 0x0000 }, /* R586   -  MICINT Source Pol */
-       [768] = { 0x0001, 0x0001, 0x0000 }, /* R768   - DSP2 Power Management */
-       [1037] = { 0x0000, 0x003F, 0xFFFF }, /* R1037  - DSP2_ExecControl */
-       [4096] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4096  - Write Sequencer 0 */
-       [4097] = { 0x00FF, 0x00FF, 0x0000 }, /* R4097  - Write Sequencer 1 */
-       [4098] = { 0x070F, 0x070F, 0x0000 }, /* R4098  - Write Sequencer 2 */
-       [4099] = { 0x010F, 0x010F, 0x0000 }, /* R4099  - Write Sequencer 3 */
-       [4100] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4100  - Write Sequencer 4 */
-       [4101] = { 0x00FF, 0x00FF, 0x0000 }, /* R4101  - Write Sequencer 5 */
-       [4102] = { 0x070F, 0x070F, 0x0000 }, /* R4102  - Write Sequencer 6 */
-       [4103] = { 0x010F, 0x010F, 0x0000 }, /* R4103  - Write Sequencer 7 */
-       [4104] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4104  - Write Sequencer 8 */
-       [4105] = { 0x00FF, 0x00FF, 0x0000 }, /* R4105  - Write Sequencer 9 */
-       [4106] = { 0x070F, 0x070F, 0x0000 }, /* R4106  - Write Sequencer 10 */
-       [4107] = { 0x010F, 0x010F, 0x0000 }, /* R4107  - Write Sequencer 11 */
-       [4108] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4108  - Write Sequencer 12 */
-       [4109] = { 0x00FF, 0x00FF, 0x0000 }, /* R4109  - Write Sequencer 13 */
-       [4110] = { 0x070F, 0x070F, 0x0000 }, /* R4110  - Write Sequencer 14 */
-       [4111] = { 0x010F, 0x010F, 0x0000 }, /* R4111  - Write Sequencer 15 */
-       [4112] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4112  - Write Sequencer 16 */
-       [4113] = { 0x00FF, 0x00FF, 0x0000 }, /* R4113  - Write Sequencer 17 */
-       [4114] = { 0x070F, 0x070F, 0x0000 }, /* R4114  - Write Sequencer 18 */
-       [4115] = { 0x010F, 0x010F, 0x0000 }, /* R4115  - Write Sequencer 19 */
-       [4116] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4116  - Write Sequencer 20 */
-       [4117] = { 0x00FF, 0x00FF, 0x0000 }, /* R4117  - Write Sequencer 21 */
-       [4118] = { 0x070F, 0x070F, 0x0000 }, /* R4118  - Write Sequencer 22 */
-       [4119] = { 0x010F, 0x010F, 0x0000 }, /* R4119  - Write Sequencer 23 */
-       [4120] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4120  - Write Sequencer 24 */
-       [4121] = { 0x00FF, 0x00FF, 0x0000 }, /* R4121  - Write Sequencer 25 */
-       [4122] = { 0x070F, 0x070F, 0x0000 }, /* R4122  - Write Sequencer 26 */
-       [4123] = { 0x010F, 0x010F, 0x0000 }, /* R4123  - Write Sequencer 27 */
-       [4124] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4124  - Write Sequencer 28 */
-       [4125] = { 0x00FF, 0x00FF, 0x0000 }, /* R4125  - Write Sequencer 29 */
-       [4126] = { 0x070F, 0x070F, 0x0000 }, /* R4126  - Write Sequencer 30 */
-       [4127] = { 0x010F, 0x010F, 0x0000 }, /* R4127  - Write Sequencer 31 */
-       [4128] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4128  - Write Sequencer 32 */
-       [4129] = { 0x00FF, 0x00FF, 0x0000 }, /* R4129  - Write Sequencer 33 */
-       [4130] = { 0x070F, 0x070F, 0x0000 }, /* R4130  - Write Sequencer 34 */
-       [4131] = { 0x010F, 0x010F, 0x0000 }, /* R4131  - Write Sequencer 35 */
-       [4132] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4132  - Write Sequencer 36 */
-       [4133] = { 0x00FF, 0x00FF, 0x0000 }, /* R4133  - Write Sequencer 37 */
-       [4134] = { 0x070F, 0x070F, 0x0000 }, /* R4134  - Write Sequencer 38 */
-       [4135] = { 0x010F, 0x010F, 0x0000 }, /* R4135  - Write Sequencer 39 */
-       [4136] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4136  - Write Sequencer 40 */
-       [4137] = { 0x00FF, 0x00FF, 0x0000 }, /* R4137  - Write Sequencer 41 */
-       [4138] = { 0x070F, 0x070F, 0x0000 }, /* R4138  - Write Sequencer 42 */
-       [4139] = { 0x010F, 0x010F, 0x0000 }, /* R4139  - Write Sequencer 43 */
-       [4140] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4140  - Write Sequencer 44 */
-       [4141] = { 0x00FF, 0x00FF, 0x0000 }, /* R4141  - Write Sequencer 45 */
-       [4142] = { 0x070F, 0x070F, 0x0000 }, /* R4142  - Write Sequencer 46 */
-       [4143] = { 0x010F, 0x010F, 0x0000 }, /* R4143  - Write Sequencer 47 */
-       [4144] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4144  - Write Sequencer 48 */
-       [4145] = { 0x00FF, 0x00FF, 0x0000 }, /* R4145  - Write Sequencer 49 */
-       [4146] = { 0x070F, 0x070F, 0x0000 }, /* R4146  - Write Sequencer 50 */
-       [4147] = { 0x010F, 0x010F, 0x0000 }, /* R4147  - Write Sequencer 51 */
-       [4148] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4148  - Write Sequencer 52 */
-       [4149] = { 0x00FF, 0x00FF, 0x0000 }, /* R4149  - Write Sequencer 53 */
-       [4150] = { 0x070F, 0x070F, 0x0000 }, /* R4150  - Write Sequencer 54 */
-       [4151] = { 0x010F, 0x010F, 0x0000 }, /* R4151  - Write Sequencer 55 */
-       [4152] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4152  - Write Sequencer 56 */
-       [4153] = { 0x00FF, 0x00FF, 0x0000 }, /* R4153  - Write Sequencer 57 */
-       [4154] = { 0x070F, 0x070F, 0x0000 }, /* R4154  - Write Sequencer 58 */
-       [4155] = { 0x010F, 0x010F, 0x0000 }, /* R4155  - Write Sequencer 59 */
-       [4156] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4156  - Write Sequencer 60 */
-       [4157] = { 0x00FF, 0x00FF, 0x0000 }, /* R4157  - Write Sequencer 61 */
-       [4158] = { 0x070F, 0x070F, 0x0000 }, /* R4158  - Write Sequencer 62 */
-       [4159] = { 0x010F, 0x010F, 0x0000 }, /* R4159  - Write Sequencer 63 */
-       [4160] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4160  - Write Sequencer 64 */
-       [4161] = { 0x00FF, 0x00FF, 0x0000 }, /* R4161  - Write Sequencer 65 */
-       [4162] = { 0x070F, 0x070F, 0x0000 }, /* R4162  - Write Sequencer 66 */
-       [4163] = { 0x010F, 0x010F, 0x0000 }, /* R4163  - Write Sequencer 67 */
-       [4164] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4164  - Write Sequencer 68 */
-       [4165] = { 0x00FF, 0x00FF, 0x0000 }, /* R4165  - Write Sequencer 69 */
-       [4166] = { 0x070F, 0x070F, 0x0000 }, /* R4166  - Write Sequencer 70 */
-       [4167] = { 0x010F, 0x010F, 0x0000 }, /* R4167  - Write Sequencer 71 */
-       [4168] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4168  - Write Sequencer 72 */
-       [4169] = { 0x00FF, 0x00FF, 0x0000 }, /* R4169  - Write Sequencer 73 */
-       [4170] = { 0x070F, 0x070F, 0x0000 }, /* R4170  - Write Sequencer 74 */
-       [4171] = { 0x010F, 0x010F, 0x0000 }, /* R4171  - Write Sequencer 75 */
-       [4172] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4172  - Write Sequencer 76 */
-       [4173] = { 0x00FF, 0x00FF, 0x0000 }, /* R4173  - Write Sequencer 77 */
-       [4174] = { 0x070F, 0x070F, 0x0000 }, /* R4174  - Write Sequencer 78 */
-       [4175] = { 0x010F, 0x010F, 0x0000 }, /* R4175  - Write Sequencer 79 */
-       [4176] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4176  - Write Sequencer 80 */
-       [4177] = { 0x00FF, 0x00FF, 0x0000 }, /* R4177  - Write Sequencer 81 */
-       [4178] = { 0x070F, 0x070F, 0x0000 }, /* R4178  - Write Sequencer 82 */
-       [4179] = { 0x010F, 0x010F, 0x0000 }, /* R4179  - Write Sequencer 83 */
-       [4180] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4180  - Write Sequencer 84 */
-       [4181] = { 0x00FF, 0x00FF, 0x0000 }, /* R4181  - Write Sequencer 85 */
-       [4182] = { 0x070F, 0x070F, 0x0000 }, /* R4182  - Write Sequencer 86 */
-       [4183] = { 0x010F, 0x010F, 0x0000 }, /* R4183  - Write Sequencer 87 */
-       [4184] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4184  - Write Sequencer 88 */
-       [4185] = { 0x00FF, 0x00FF, 0x0000 }, /* R4185  - Write Sequencer 89 */
-       [4186] = { 0x070F, 0x070F, 0x0000 }, /* R4186  - Write Sequencer 90 */
-       [4187] = { 0x010F, 0x010F, 0x0000 }, /* R4187  - Write Sequencer 91 */
-       [4188] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4188  - Write Sequencer 92 */
-       [4189] = { 0x00FF, 0x00FF, 0x0000 }, /* R4189  - Write Sequencer 93 */
-       [4190] = { 0x070F, 0x070F, 0x0000 }, /* R4190  - Write Sequencer 94 */
-       [4191] = { 0x010F, 0x010F, 0x0000 }, /* R4191  - Write Sequencer 95 */
-       [4192] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4192  - Write Sequencer 96 */
-       [4193] = { 0x00FF, 0x00FF, 0x0000 }, /* R4193  - Write Sequencer 97 */
-       [4194] = { 0x070F, 0x070F, 0x0000 }, /* R4194  - Write Sequencer 98 */
-       [4195] = { 0x010F, 0x010F, 0x0000 }, /* R4195  - Write Sequencer 99 */
-       [4196] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4196  - Write Sequencer 100 */
-       [4197] = { 0x00FF, 0x00FF, 0x0000 }, /* R4197  - Write Sequencer 101 */
-       [4198] = { 0x070F, 0x070F, 0x0000 }, /* R4198  - Write Sequencer 102 */
-       [4199] = { 0x010F, 0x010F, 0x0000 }, /* R4199  - Write Sequencer 103 */
-       [4200] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4200  - Write Sequencer 104 */
-       [4201] = { 0x00FF, 0x00FF, 0x0000 }, /* R4201  - Write Sequencer 105 */
-       [4202] = { 0x070F, 0x070F, 0x0000 }, /* R4202  - Write Sequencer 106 */
-       [4203] = { 0x010F, 0x010F, 0x0000 }, /* R4203  - Write Sequencer 107 */
-       [4204] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4204  - Write Sequencer 108 */
-       [4205] = { 0x00FF, 0x00FF, 0x0000 }, /* R4205  - Write Sequencer 109 */
-       [4206] = { 0x070F, 0x070F, 0x0000 }, /* R4206  - Write Sequencer 110 */
-       [4207] = { 0x010F, 0x010F, 0x0000 }, /* R4207  - Write Sequencer 111 */
-       [4208] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4208  - Write Sequencer 112 */
-       [4209] = { 0x00FF, 0x00FF, 0x0000 }, /* R4209  - Write Sequencer 113 */
-       [4210] = { 0x070F, 0x070F, 0x0000 }, /* R4210  - Write Sequencer 114 */
-       [4211] = { 0x010F, 0x010F, 0x0000 }, /* R4211  - Write Sequencer 115 */
-       [4212] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4212  - Write Sequencer 116 */
-       [4213] = { 0x00FF, 0x00FF, 0x0000 }, /* R4213  - Write Sequencer 117 */
-       [4214] = { 0x070F, 0x070F, 0x0000 }, /* R4214  - Write Sequencer 118 */
-       [4215] = { 0x010F, 0x010F, 0x0000 }, /* R4215  - Write Sequencer 119 */
-       [4216] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4216  - Write Sequencer 120 */
-       [4217] = { 0x00FF, 0x00FF, 0x0000 }, /* R4217  - Write Sequencer 121 */
-       [4218] = { 0x070F, 0x070F, 0x0000 }, /* R4218  - Write Sequencer 122 */
-       [4219] = { 0x010F, 0x010F, 0x0000 }, /* R4219  - Write Sequencer 123 */
-       [4220] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4220  - Write Sequencer 124 */
-       [4221] = { 0x00FF, 0x00FF, 0x0000 }, /* R4221  - Write Sequencer 125 */
-       [4222] = { 0x070F, 0x070F, 0x0000 }, /* R4222  - Write Sequencer 126 */
-       [4223] = { 0x010F, 0x010F, 0x0000 }, /* R4223  - Write Sequencer 127 */
-       [4224] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4224  - Write Sequencer 128 */
-       [4225] = { 0x00FF, 0x00FF, 0x0000 }, /* R4225  - Write Sequencer 129 */
-       [4226] = { 0x070F, 0x070F, 0x0000 }, /* R4226  - Write Sequencer 130 */
-       [4227] = { 0x010F, 0x010F, 0x0000 }, /* R4227  - Write Sequencer 131 */
-       [4228] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4228  - Write Sequencer 132 */
-       [4229] = { 0x00FF, 0x00FF, 0x0000 }, /* R4229  - Write Sequencer 133 */
-       [4230] = { 0x070F, 0x070F, 0x0000 }, /* R4230  - Write Sequencer 134 */
-       [4231] = { 0x010F, 0x010F, 0x0000 }, /* R4231  - Write Sequencer 135 */
-       [4232] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4232  - Write Sequencer 136 */
-       [4233] = { 0x00FF, 0x00FF, 0x0000 }, /* R4233  - Write Sequencer 137 */
-       [4234] = { 0x070F, 0x070F, 0x0000 }, /* R4234  - Write Sequencer 138 */
-       [4235] = { 0x010F, 0x010F, 0x0000 }, /* R4235  - Write Sequencer 139 */
-       [4236] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4236  - Write Sequencer 140 */
-       [4237] = { 0x00FF, 0x00FF, 0x0000 }, /* R4237  - Write Sequencer 141 */
-       [4238] = { 0x070F, 0x070F, 0x0000 }, /* R4238  - Write Sequencer 142 */
-       [4239] = { 0x010F, 0x010F, 0x0000 }, /* R4239  - Write Sequencer 143 */
-       [4240] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4240  - Write Sequencer 144 */
-       [4241] = { 0x00FF, 0x00FF, 0x0000 }, /* R4241  - Write Sequencer 145 */
-       [4242] = { 0x070F, 0x070F, 0x0000 }, /* R4242  - Write Sequencer 146 */
-       [4243] = { 0x010F, 0x010F, 0x0000 }, /* R4243  - Write Sequencer 147 */
-       [4244] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4244  - Write Sequencer 148 */
-       [4245] = { 0x00FF, 0x00FF, 0x0000 }, /* R4245  - Write Sequencer 149 */
-       [4246] = { 0x070F, 0x070F, 0x0000 }, /* R4246  - Write Sequencer 150 */
-       [4247] = { 0x010F, 0x010F, 0x0000 }, /* R4247  - Write Sequencer 151 */
-       [4248] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4248  - Write Sequencer 152 */
-       [4249] = { 0x00FF, 0x00FF, 0x0000 }, /* R4249  - Write Sequencer 153 */
-       [4250] = { 0x070F, 0x070F, 0x0000 }, /* R4250  - Write Sequencer 154 */
-       [4251] = { 0x010F, 0x010F, 0x0000 }, /* R4251  - Write Sequencer 155 */
-       [4252] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4252  - Write Sequencer 156 */
-       [4253] = { 0x00FF, 0x00FF, 0x0000 }, /* R4253  - Write Sequencer 157 */
-       [4254] = { 0x070F, 0x070F, 0x0000 }, /* R4254  - Write Sequencer 158 */
-       [4255] = { 0x010F, 0x010F, 0x0000 }, /* R4255  - Write Sequencer 159 */
-       [4256] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4256  - Write Sequencer 160 */
-       [4257] = { 0x00FF, 0x00FF, 0x0000 }, /* R4257  - Write Sequencer 161 */
-       [4258] = { 0x070F, 0x070F, 0x0000 }, /* R4258  - Write Sequencer 162 */
-       [4259] = { 0x010F, 0x010F, 0x0000 }, /* R4259  - Write Sequencer 163 */
-       [4260] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4260  - Write Sequencer 164 */
-       [4261] = { 0x00FF, 0x00FF, 0x0000 }, /* R4261  - Write Sequencer 165 */
-       [4262] = { 0x070F, 0x070F, 0x0000 }, /* R4262  - Write Sequencer 166 */
-       [4263] = { 0x010F, 0x010F, 0x0000 }, /* R4263  - Write Sequencer 167 */
-       [4264] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4264  - Write Sequencer 168 */
-       [4265] = { 0x00FF, 0x00FF, 0x0000 }, /* R4265  - Write Sequencer 169 */
-       [4266] = { 0x070F, 0x070F, 0x0000 }, /* R4266  - Write Sequencer 170 */
-       [4267] = { 0x010F, 0x010F, 0x0000 }, /* R4267  - Write Sequencer 171 */
-       [4268] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4268  - Write Sequencer 172 */
-       [4269] = { 0x00FF, 0x00FF, 0x0000 }, /* R4269  - Write Sequencer 173 */
-       [4270] = { 0x070F, 0x070F, 0x0000 }, /* R4270  - Write Sequencer 174 */
-       [4271] = { 0x010F, 0x010F, 0x0000 }, /* R4271  - Write Sequencer 175 */
-       [4272] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4272  - Write Sequencer 176 */
-       [4273] = { 0x00FF, 0x00FF, 0x0000 }, /* R4273  - Write Sequencer 177 */
-       [4274] = { 0x070F, 0x070F, 0x0000 }, /* R4274  - Write Sequencer 178 */
-       [4275] = { 0x010F, 0x010F, 0x0000 }, /* R4275  - Write Sequencer 179 */
-       [4276] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4276  - Write Sequencer 180 */
-       [4277] = { 0x00FF, 0x00FF, 0x0000 }, /* R4277  - Write Sequencer 181 */
-       [4278] = { 0x070F, 0x070F, 0x0000 }, /* R4278  - Write Sequencer 182 */
-       [4279] = { 0x010F, 0x010F, 0x0000 }, /* R4279  - Write Sequencer 183 */
-       [4280] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4280  - Write Sequencer 184 */
-       [4281] = { 0x00FF, 0x00FF, 0x0000 }, /* R4281  - Write Sequencer 185 */
-       [4282] = { 0x070F, 0x070F, 0x0000 }, /* R4282  - Write Sequencer 186 */
-       [4283] = { 0x010F, 0x010F, 0x0000 }, /* R4283  - Write Sequencer 187 */
-       [4284] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4284  - Write Sequencer 188 */
-       [4285] = { 0x00FF, 0x00FF, 0x0000 }, /* R4285  - Write Sequencer 189 */
-       [4286] = { 0x070F, 0x070F, 0x0000 }, /* R4286  - Write Sequencer 190 */
-       [4287] = { 0x010F, 0x010F, 0x0000 }, /* R4287  - Write Sequencer 191 */
-       [4288] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4288  - Write Sequencer 192 */
-       [4289] = { 0x00FF, 0x00FF, 0x0000 }, /* R4289  - Write Sequencer 193 */
-       [4290] = { 0x070F, 0x070F, 0x0000 }, /* R4290  - Write Sequencer 194 */
-       [4291] = { 0x010F, 0x010F, 0x0000 }, /* R4291  - Write Sequencer 195 */
-       [4292] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4292  - Write Sequencer 196 */
-       [4293] = { 0x00FF, 0x00FF, 0x0000 }, /* R4293  - Write Sequencer 197 */
-       [4294] = { 0x070F, 0x070F, 0x0000 }, /* R4294  - Write Sequencer 198 */
-       [4295] = { 0x010F, 0x010F, 0x0000 }, /* R4295  - Write Sequencer 199 */
-       [4296] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4296  - Write Sequencer 200 */
-       [4297] = { 0x00FF, 0x00FF, 0x0000 }, /* R4297  - Write Sequencer 201 */
-       [4298] = { 0x070F, 0x070F, 0x0000 }, /* R4298  - Write Sequencer 202 */
-       [4299] = { 0x010F, 0x010F, 0x0000 }, /* R4299  - Write Sequencer 203 */
-       [4300] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4300  - Write Sequencer 204 */
-       [4301] = { 0x00FF, 0x00FF, 0x0000 }, /* R4301  - Write Sequencer 205 */
-       [4302] = { 0x070F, 0x070F, 0x0000 }, /* R4302  - Write Sequencer 206 */
-       [4303] = { 0x010F, 0x010F, 0x0000 }, /* R4303  - Write Sequencer 207 */
-       [4304] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4304  - Write Sequencer 208 */
-       [4305] = { 0x00FF, 0x00FF, 0x0000 }, /* R4305  - Write Sequencer 209 */
-       [4306] = { 0x070F, 0x070F, 0x0000 }, /* R4306  - Write Sequencer 210 */
-       [4307] = { 0x010F, 0x010F, 0x0000 }, /* R4307  - Write Sequencer 211 */
-       [4308] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4308  - Write Sequencer 212 */
-       [4309] = { 0x00FF, 0x00FF, 0x0000 }, /* R4309  - Write Sequencer 213 */
-       [4310] = { 0x070F, 0x070F, 0x0000 }, /* R4310  - Write Sequencer 214 */
-       [4311] = { 0x010F, 0x010F, 0x0000 }, /* R4311  - Write Sequencer 215 */
-       [4312] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4312  - Write Sequencer 216 */
-       [4313] = { 0x00FF, 0x00FF, 0x0000 }, /* R4313  - Write Sequencer 217 */
-       [4314] = { 0x070F, 0x070F, 0x0000 }, /* R4314  - Write Sequencer 218 */
-       [4315] = { 0x010F, 0x010F, 0x0000 }, /* R4315  - Write Sequencer 219 */
-       [4316] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4316  - Write Sequencer 220 */
-       [4317] = { 0x00FF, 0x00FF, 0x0000 }, /* R4317  - Write Sequencer 221 */
-       [4318] = { 0x070F, 0x070F, 0x0000 }, /* R4318  - Write Sequencer 222 */
-       [4319] = { 0x010F, 0x010F, 0x0000 }, /* R4319  - Write Sequencer 223 */
-       [4320] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4320  - Write Sequencer 224 */
-       [4321] = { 0x00FF, 0x00FF, 0x0000 }, /* R4321  - Write Sequencer 225 */
-       [4322] = { 0x070F, 0x070F, 0x0000 }, /* R4322  - Write Sequencer 226 */
-       [4323] = { 0x010F, 0x010F, 0x0000 }, /* R4323  - Write Sequencer 227 */
-       [4324] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4324  - Write Sequencer 228 */
-       [4325] = { 0x00FF, 0x00FF, 0x0000 }, /* R4325  - Write Sequencer 229 */
-       [4326] = { 0x070F, 0x070F, 0x0000 }, /* R4326  - Write Sequencer 230 */
-       [4327] = { 0x010F, 0x010F, 0x0000 }, /* R4327  - Write Sequencer 231 */
-       [4328] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4328  - Write Sequencer 232 */
-       [4329] = { 0x00FF, 0x00FF, 0x0000 }, /* R4329  - Write Sequencer 233 */
-       [4330] = { 0x070F, 0x070F, 0x0000 }, /* R4330  - Write Sequencer 234 */
-       [4331] = { 0x010F, 0x010F, 0x0000 }, /* R4331  - Write Sequencer 235 */
-       [4332] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4332  - Write Sequencer 236 */
-       [4333] = { 0x00FF, 0x00FF, 0x0000 }, /* R4333  - Write Sequencer 237 */
-       [4334] = { 0x070F, 0x070F, 0x0000 }, /* R4334  - Write Sequencer 238 */
-       [4335] = { 0x010F, 0x010F, 0x0000 }, /* R4335  - Write Sequencer 239 */
-       [4336] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4336  - Write Sequencer 240 */
-       [4337] = { 0x00FF, 0x00FF, 0x0000 }, /* R4337  - Write Sequencer 241 */
-       [4338] = { 0x070F, 0x070F, 0x0000 }, /* R4338  - Write Sequencer 242 */
-       [4339] = { 0x010F, 0x010F, 0x0000 }, /* R4339  - Write Sequencer 243 */
-       [4340] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4340  - Write Sequencer 244 */
-       [4341] = { 0x00FF, 0x00FF, 0x0000 }, /* R4341  - Write Sequencer 245 */
-       [4342] = { 0x070F, 0x070F, 0x0000 }, /* R4342  - Write Sequencer 246 */
-       [4343] = { 0x010F, 0x010F, 0x0000 }, /* R4343  - Write Sequencer 247 */
-       [4344] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4344  - Write Sequencer 248 */
-       [4345] = { 0x00FF, 0x00FF, 0x0000 }, /* R4345  - Write Sequencer 249 */
-       [4346] = { 0x070F, 0x070F, 0x0000 }, /* R4346  - Write Sequencer 250 */
-       [4347] = { 0x010F, 0x010F, 0x0000 }, /* R4347  - Write Sequencer 251 */
-       [4348] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4348  - Write Sequencer 252 */
-       [4349] = { 0x00FF, 0x00FF, 0x0000 }, /* R4349  - Write Sequencer 253 */
-       [4350] = { 0x070F, 0x070F, 0x0000 }, /* R4350  - Write Sequencer 254 */
-       [4351] = { 0x010F, 0x010F, 0x0000 }, /* R4351  - Write Sequencer 255 */
-       [4352] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4352  - Write Sequencer 256 */
-       [4353] = { 0x00FF, 0x00FF, 0x0000 }, /* R4353  - Write Sequencer 257 */
-       [4354] = { 0x070F, 0x070F, 0x0000 }, /* R4354  - Write Sequencer 258 */
-       [4355] = { 0x010F, 0x010F, 0x0000 }, /* R4355  - Write Sequencer 259 */
-       [4356] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4356  - Write Sequencer 260 */
-       [4357] = { 0x00FF, 0x00FF, 0x0000 }, /* R4357  - Write Sequencer 261 */
-       [4358] = { 0x070F, 0x070F, 0x0000 }, /* R4358  - Write Sequencer 262 */
-       [4359] = { 0x010F, 0x010F, 0x0000 }, /* R4359  - Write Sequencer 263 */
-       [4360] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4360  - Write Sequencer 264 */
-       [4361] = { 0x00FF, 0x00FF, 0x0000 }, /* R4361  - Write Sequencer 265 */
-       [4362] = { 0x070F, 0x070F, 0x0000 }, /* R4362  - Write Sequencer 266 */
-       [4363] = { 0x010F, 0x010F, 0x0000 }, /* R4363  - Write Sequencer 267 */
-       [4364] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4364  - Write Sequencer 268 */
-       [4365] = { 0x00FF, 0x00FF, 0x0000 }, /* R4365  - Write Sequencer 269 */
-       [4366] = { 0x070F, 0x070F, 0x0000 }, /* R4366  - Write Sequencer 270 */
-       [4367] = { 0x010F, 0x010F, 0x0000 }, /* R4367  - Write Sequencer 271 */
-       [4368] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4368  - Write Sequencer 272 */
-       [4369] = { 0x00FF, 0x00FF, 0x0000 }, /* R4369  - Write Sequencer 273 */
-       [4370] = { 0x070F, 0x070F, 0x0000 }, /* R4370  - Write Sequencer 274 */
-       [4371] = { 0x010F, 0x010F, 0x0000 }, /* R4371  - Write Sequencer 275 */
-       [4372] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4372  - Write Sequencer 276 */
-       [4373] = { 0x00FF, 0x00FF, 0x0000 }, /* R4373  - Write Sequencer 277 */
-       [4374] = { 0x070F, 0x070F, 0x0000 }, /* R4374  - Write Sequencer 278 */
-       [4375] = { 0x010F, 0x010F, 0x0000 }, /* R4375  - Write Sequencer 279 */
-       [4376] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4376  - Write Sequencer 280 */
-       [4377] = { 0x00FF, 0x00FF, 0x0000 }, /* R4377  - Write Sequencer 281 */
-       [4378] = { 0x070F, 0x070F, 0x0000 }, /* R4378  - Write Sequencer 282 */
-       [4379] = { 0x010F, 0x010F, 0x0000 }, /* R4379  - Write Sequencer 283 */
-       [4380] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4380  - Write Sequencer 284 */
-       [4381] = { 0x00FF, 0x00FF, 0x0000 }, /* R4381  - Write Sequencer 285 */
-       [4382] = { 0x070F, 0x070F, 0x0000 }, /* R4382  - Write Sequencer 286 */
-       [4383] = { 0x010F, 0x010F, 0x0000 }, /* R4383  - Write Sequencer 287 */
-       [4384] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4384  - Write Sequencer 288 */
-       [4385] = { 0x00FF, 0x00FF, 0x0000 }, /* R4385  - Write Sequencer 289 */
-       [4386] = { 0x070F, 0x070F, 0x0000 }, /* R4386  - Write Sequencer 290 */
-       [4387] = { 0x010F, 0x010F, 0x0000 }, /* R4387  - Write Sequencer 291 */
-       [4388] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4388  - Write Sequencer 292 */
-       [4389] = { 0x00FF, 0x00FF, 0x0000 }, /* R4389  - Write Sequencer 293 */
-       [4390] = { 0x070F, 0x070F, 0x0000 }, /* R4390  - Write Sequencer 294 */
-       [4391] = { 0x010F, 0x010F, 0x0000 }, /* R4391  - Write Sequencer 295 */
-       [4392] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4392  - Write Sequencer 296 */
-       [4393] = { 0x00FF, 0x00FF, 0x0000 }, /* R4393  - Write Sequencer 297 */
-       [4394] = { 0x070F, 0x070F, 0x0000 }, /* R4394  - Write Sequencer 298 */
-       [4395] = { 0x010F, 0x010F, 0x0000 }, /* R4395  - Write Sequencer 299 */
-       [4396] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4396  - Write Sequencer 300 */
-       [4397] = { 0x00FF, 0x00FF, 0x0000 }, /* R4397  - Write Sequencer 301 */
-       [4398] = { 0x070F, 0x070F, 0x0000 }, /* R4398  - Write Sequencer 302 */
-       [4399] = { 0x010F, 0x010F, 0x0000 }, /* R4399  - Write Sequencer 303 */
-       [4400] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4400  - Write Sequencer 304 */
-       [4401] = { 0x00FF, 0x00FF, 0x0000 }, /* R4401  - Write Sequencer 305 */
-       [4402] = { 0x070F, 0x070F, 0x0000 }, /* R4402  - Write Sequencer 306 */
-       [4403] = { 0x010F, 0x010F, 0x0000 }, /* R4403  - Write Sequencer 307 */
-       [4404] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4404  - Write Sequencer 308 */
-       [4405] = { 0x00FF, 0x00FF, 0x0000 }, /* R4405  - Write Sequencer 309 */
-       [4406] = { 0x070F, 0x070F, 0x0000 }, /* R4406  - Write Sequencer 310 */
-       [4407] = { 0x010F, 0x010F, 0x0000 }, /* R4407  - Write Sequencer 311 */
-       [4408] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4408  - Write Sequencer 312 */
-       [4409] = { 0x00FF, 0x00FF, 0x0000 }, /* R4409  - Write Sequencer 313 */
-       [4410] = { 0x070F, 0x070F, 0x0000 }, /* R4410  - Write Sequencer 314 */
-       [4411] = { 0x010F, 0x010F, 0x0000 }, /* R4411  - Write Sequencer 315 */
-       [4412] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4412  - Write Sequencer 316 */
-       [4413] = { 0x00FF, 0x00FF, 0x0000 }, /* R4413  - Write Sequencer 317 */
-       [4414] = { 0x070F, 0x070F, 0x0000 }, /* R4414  - Write Sequencer 318 */
-       [4415] = { 0x010F, 0x010F, 0x0000 }, /* R4415  - Write Sequencer 319 */
-       [4416] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4416  - Write Sequencer 320 */
-       [4417] = { 0x00FF, 0x00FF, 0x0000 }, /* R4417  - Write Sequencer 321 */
-       [4418] = { 0x070F, 0x070F, 0x0000 }, /* R4418  - Write Sequencer 322 */
-       [4419] = { 0x010F, 0x010F, 0x0000 }, /* R4419  - Write Sequencer 323 */
-       [4420] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4420  - Write Sequencer 324 */
-       [4421] = { 0x00FF, 0x00FF, 0x0000 }, /* R4421  - Write Sequencer 325 */
-       [4422] = { 0x070F, 0x070F, 0x0000 }, /* R4422  - Write Sequencer 326 */
-       [4423] = { 0x010F, 0x010F, 0x0000 }, /* R4423  - Write Sequencer 327 */
-       [4424] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4424  - Write Sequencer 328 */
-       [4425] = { 0x00FF, 0x00FF, 0x0000 }, /* R4425  - Write Sequencer 329 */
-       [4426] = { 0x070F, 0x070F, 0x0000 }, /* R4426  - Write Sequencer 330 */
-       [4427] = { 0x010F, 0x010F, 0x0000 }, /* R4427  - Write Sequencer 331 */
-       [4428] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4428  - Write Sequencer 332 */
-       [4429] = { 0x00FF, 0x00FF, 0x0000 }, /* R4429  - Write Sequencer 333 */
-       [4430] = { 0x070F, 0x070F, 0x0000 }, /* R4430  - Write Sequencer 334 */
-       [4431] = { 0x010F, 0x010F, 0x0000 }, /* R4431  - Write Sequencer 335 */
-       [4432] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4432  - Write Sequencer 336 */
-       [4433] = { 0x00FF, 0x00FF, 0x0000 }, /* R4433  - Write Sequencer 337 */
-       [4434] = { 0x070F, 0x070F, 0x0000 }, /* R4434  - Write Sequencer 338 */
-       [4435] = { 0x010F, 0x010F, 0x0000 }, /* R4435  - Write Sequencer 339 */
-       [4436] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4436  - Write Sequencer 340 */
-       [4437] = { 0x00FF, 0x00FF, 0x0000 }, /* R4437  - Write Sequencer 341 */
-       [4438] = { 0x070F, 0x070F, 0x0000 }, /* R4438  - Write Sequencer 342 */
-       [4439] = { 0x010F, 0x010F, 0x0000 }, /* R4439  - Write Sequencer 343 */
-       [4440] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4440  - Write Sequencer 344 */
-       [4441] = { 0x00FF, 0x00FF, 0x0000 }, /* R4441  - Write Sequencer 345 */
-       [4442] = { 0x070F, 0x070F, 0x0000 }, /* R4442  - Write Sequencer 346 */
-       [4443] = { 0x010F, 0x010F, 0x0000 }, /* R4443  - Write Sequencer 347 */
-       [4444] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4444  - Write Sequencer 348 */
-       [4445] = { 0x00FF, 0x00FF, 0x0000 }, /* R4445  - Write Sequencer 349 */
-       [4446] = { 0x070F, 0x070F, 0x0000 }, /* R4446  - Write Sequencer 350 */
-       [4447] = { 0x010F, 0x010F, 0x0000 }, /* R4447  - Write Sequencer 351 */
-       [4448] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4448  - Write Sequencer 352 */
-       [4449] = { 0x00FF, 0x00FF, 0x0000 }, /* R4449  - Write Sequencer 353 */
-       [4450] = { 0x070F, 0x070F, 0x0000 }, /* R4450  - Write Sequencer 354 */
-       [4451] = { 0x010F, 0x010F, 0x0000 }, /* R4451  - Write Sequencer 355 */
-       [4452] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4452  - Write Sequencer 356 */
-       [4453] = { 0x00FF, 0x00FF, 0x0000 }, /* R4453  - Write Sequencer 357 */
-       [4454] = { 0x070F, 0x070F, 0x0000 }, /* R4454  - Write Sequencer 358 */
-       [4455] = { 0x010F, 0x010F, 0x0000 }, /* R4455  - Write Sequencer 359 */
-       [4456] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4456  - Write Sequencer 360 */
-       [4457] = { 0x00FF, 0x00FF, 0x0000 }, /* R4457  - Write Sequencer 361 */
-       [4458] = { 0x070F, 0x070F, 0x0000 }, /* R4458  - Write Sequencer 362 */
-       [4459] = { 0x010F, 0x010F, 0x0000 }, /* R4459  - Write Sequencer 363 */
-       [4460] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4460  - Write Sequencer 364 */
-       [4461] = { 0x00FF, 0x00FF, 0x0000 }, /* R4461  - Write Sequencer 365 */
-       [4462] = { 0x070F, 0x070F, 0x0000 }, /* R4462  - Write Sequencer 366 */
-       [4463] = { 0x010F, 0x010F, 0x0000 }, /* R4463  - Write Sequencer 367 */
-       [4464] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4464  - Write Sequencer 368 */
-       [4465] = { 0x00FF, 0x00FF, 0x0000 }, /* R4465  - Write Sequencer 369 */
-       [4466] = { 0x070F, 0x070F, 0x0000 }, /* R4466  - Write Sequencer 370 */
-       [4467] = { 0x010F, 0x010F, 0x0000 }, /* R4467  - Write Sequencer 371 */
-       [4468] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4468  - Write Sequencer 372 */
-       [4469] = { 0x00FF, 0x00FF, 0x0000 }, /* R4469  - Write Sequencer 373 */
-       [4470] = { 0x070F, 0x070F, 0x0000 }, /* R4470  - Write Sequencer 374 */
-       [4471] = { 0x010F, 0x010F, 0x0000 }, /* R4471  - Write Sequencer 375 */
-       [4472] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4472  - Write Sequencer 376 */
-       [4473] = { 0x00FF, 0x00FF, 0x0000 }, /* R4473  - Write Sequencer 377 */
-       [4474] = { 0x070F, 0x070F, 0x0000 }, /* R4474  - Write Sequencer 378 */
-       [4475] = { 0x010F, 0x010F, 0x0000 }, /* R4475  - Write Sequencer 379 */
-       [4476] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4476  - Write Sequencer 380 */
-       [4477] = { 0x00FF, 0x00FF, 0x0000 }, /* R4477  - Write Sequencer 381 */
-       [4478] = { 0x070F, 0x070F, 0x0000 }, /* R4478  - Write Sequencer 382 */
-       [4479] = { 0x010F, 0x010F, 0x0000 }, /* R4479  - Write Sequencer 383 */
-       [4480] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4480  - Write Sequencer 384 */
-       [4481] = { 0x00FF, 0x00FF, 0x0000 }, /* R4481  - Write Sequencer 385 */
-       [4482] = { 0x070F, 0x070F, 0x0000 }, /* R4482  - Write Sequencer 386 */
-       [4483] = { 0x010F, 0x010F, 0x0000 }, /* R4483  - Write Sequencer 387 */
-       [4484] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4484  - Write Sequencer 388 */
-       [4485] = { 0x00FF, 0x00FF, 0x0000 }, /* R4485  - Write Sequencer 389 */
-       [4486] = { 0x070F, 0x070F, 0x0000 }, /* R4486  - Write Sequencer 390 */
-       [4487] = { 0x010F, 0x010F, 0x0000 }, /* R4487  - Write Sequencer 391 */
-       [4488] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4488  - Write Sequencer 392 */
-       [4489] = { 0x00FF, 0x00FF, 0x0000 }, /* R4489  - Write Sequencer 393 */
-       [4490] = { 0x070F, 0x070F, 0x0000 }, /* R4490  - Write Sequencer 394 */
-       [4491] = { 0x010F, 0x010F, 0x0000 }, /* R4491  - Write Sequencer 395 */
-       [4492] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4492  - Write Sequencer 396 */
-       [4493] = { 0x00FF, 0x00FF, 0x0000 }, /* R4493  - Write Sequencer 397 */
-       [4494] = { 0x070F, 0x070F, 0x0000 }, /* R4494  - Write Sequencer 398 */
-       [4495] = { 0x010F, 0x010F, 0x0000 }, /* R4495  - Write Sequencer 399 */
-       [4496] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4496  - Write Sequencer 400 */
-       [4497] = { 0x00FF, 0x00FF, 0x0000 }, /* R4497  - Write Sequencer 401 */
-       [4498] = { 0x070F, 0x070F, 0x0000 }, /* R4498  - Write Sequencer 402 */
-       [4499] = { 0x010F, 0x010F, 0x0000 }, /* R4499  - Write Sequencer 403 */
-       [4500] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4500  - Write Sequencer 404 */
-       [4501] = { 0x00FF, 0x00FF, 0x0000 }, /* R4501  - Write Sequencer 405 */
-       [4502] = { 0x070F, 0x070F, 0x0000 }, /* R4502  - Write Sequencer 406 */
-       [4503] = { 0x010F, 0x010F, 0x0000 }, /* R4503  - Write Sequencer 407 */
-       [4504] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4504  - Write Sequencer 408 */
-       [4505] = { 0x00FF, 0x00FF, 0x0000 }, /* R4505  - Write Sequencer 409 */
-       [4506] = { 0x070F, 0x070F, 0x0000 }, /* R4506  - Write Sequencer 410 */
-       [4507] = { 0x010F, 0x010F, 0x0000 }, /* R4507  - Write Sequencer 411 */
-       [4508] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4508  - Write Sequencer 412 */
-       [4509] = { 0x00FF, 0x00FF, 0x0000 }, /* R4509  - Write Sequencer 413 */
-       [4510] = { 0x070F, 0x070F, 0x0000 }, /* R4510  - Write Sequencer 414 */
-       [4511] = { 0x010F, 0x010F, 0x0000 }, /* R4511  - Write Sequencer 415 */
-       [4512] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4512  - Write Sequencer 416 */
-       [4513] = { 0x00FF, 0x00FF, 0x0000 }, /* R4513  - Write Sequencer 417 */
-       [4514] = { 0x070F, 0x070F, 0x0000 }, /* R4514  - Write Sequencer 418 */
-       [4515] = { 0x010F, 0x010F, 0x0000 }, /* R4515  - Write Sequencer 419 */
-       [4516] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4516  - Write Sequencer 420 */
-       [4517] = { 0x00FF, 0x00FF, 0x0000 }, /* R4517  - Write Sequencer 421 */
-       [4518] = { 0x070F, 0x070F, 0x0000 }, /* R4518  - Write Sequencer 422 */
-       [4519] = { 0x010F, 0x010F, 0x0000 }, /* R4519  - Write Sequencer 423 */
-       [4520] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4520  - Write Sequencer 424 */
-       [4521] = { 0x00FF, 0x00FF, 0x0000 }, /* R4521  - Write Sequencer 425 */
-       [4522] = { 0x070F, 0x070F, 0x0000 }, /* R4522  - Write Sequencer 426 */
-       [4523] = { 0x010F, 0x010F, 0x0000 }, /* R4523  - Write Sequencer 427 */
-       [4524] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4524  - Write Sequencer 428 */
-       [4525] = { 0x00FF, 0x00FF, 0x0000 }, /* R4525  - Write Sequencer 429 */
-       [4526] = { 0x070F, 0x070F, 0x0000 }, /* R4526  - Write Sequencer 430 */
-       [4527] = { 0x010F, 0x010F, 0x0000 }, /* R4527  - Write Sequencer 431 */
-       [4528] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4528  - Write Sequencer 432 */
-       [4529] = { 0x00FF, 0x00FF, 0x0000 }, /* R4529  - Write Sequencer 433 */
-       [4530] = { 0x070F, 0x070F, 0x0000 }, /* R4530  - Write Sequencer 434 */
-       [4531] = { 0x010F, 0x010F, 0x0000 }, /* R4531  - Write Sequencer 435 */
-       [4532] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4532  - Write Sequencer 436 */
-       [4533] = { 0x00FF, 0x00FF, 0x0000 }, /* R4533  - Write Sequencer 437 */
-       [4534] = { 0x070F, 0x070F, 0x0000 }, /* R4534  - Write Sequencer 438 */
-       [4535] = { 0x010F, 0x010F, 0x0000 }, /* R4535  - Write Sequencer 439 */
-       [4536] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4536  - Write Sequencer 440 */
-       [4537] = { 0x00FF, 0x00FF, 0x0000 }, /* R4537  - Write Sequencer 441 */
-       [4538] = { 0x070F, 0x070F, 0x0000 }, /* R4538  - Write Sequencer 442 */
-       [4539] = { 0x010F, 0x010F, 0x0000 }, /* R4539  - Write Sequencer 443 */
-       [4540] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4540  - Write Sequencer 444 */
-       [4541] = { 0x00FF, 0x00FF, 0x0000 }, /* R4541  - Write Sequencer 445 */
-       [4542] = { 0x070F, 0x070F, 0x0000 }, /* R4542  - Write Sequencer 446 */
-       [4543] = { 0x010F, 0x010F, 0x0000 }, /* R4543  - Write Sequencer 447 */
-       [4544] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4544  - Write Sequencer 448 */
-       [4545] = { 0x00FF, 0x00FF, 0x0000 }, /* R4545  - Write Sequencer 449 */
-       [4546] = { 0x070F, 0x070F, 0x0000 }, /* R4546  - Write Sequencer 450 */
-       [4547] = { 0x010F, 0x010F, 0x0000 }, /* R4547  - Write Sequencer 451 */
-       [4548] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4548  - Write Sequencer 452 */
-       [4549] = { 0x00FF, 0x00FF, 0x0000 }, /* R4549  - Write Sequencer 453 */
-       [4550] = { 0x070F, 0x070F, 0x0000 }, /* R4550  - Write Sequencer 454 */
-       [4551] = { 0x010F, 0x010F, 0x0000 }, /* R4551  - Write Sequencer 455 */
-       [4552] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4552  - Write Sequencer 456 */
-       [4553] = { 0x00FF, 0x00FF, 0x0000 }, /* R4553  - Write Sequencer 457 */
-       [4554] = { 0x070F, 0x070F, 0x0000 }, /* R4554  - Write Sequencer 458 */
-       [4555] = { 0x010F, 0x010F, 0x0000 }, /* R4555  - Write Sequencer 459 */
-       [4556] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4556  - Write Sequencer 460 */
-       [4557] = { 0x00FF, 0x00FF, 0x0000 }, /* R4557  - Write Sequencer 461 */
-       [4558] = { 0x070F, 0x070F, 0x0000 }, /* R4558  - Write Sequencer 462 */
-       [4559] = { 0x010F, 0x010F, 0x0000 }, /* R4559  - Write Sequencer 463 */
-       [4560] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4560  - Write Sequencer 464 */
-       [4561] = { 0x00FF, 0x00FF, 0x0000 }, /* R4561  - Write Sequencer 465 */
-       [4562] = { 0x070F, 0x070F, 0x0000 }, /* R4562  - Write Sequencer 466 */
-       [4563] = { 0x010F, 0x010F, 0x0000 }, /* R4563  - Write Sequencer 467 */
-       [4564] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4564  - Write Sequencer 468 */
-       [4565] = { 0x00FF, 0x00FF, 0x0000 }, /* R4565  - Write Sequencer 469 */
-       [4566] = { 0x070F, 0x070F, 0x0000 }, /* R4566  - Write Sequencer 470 */
-       [4567] = { 0x010F, 0x010F, 0x0000 }, /* R4567  - Write Sequencer 471 */
-       [4568] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4568  - Write Sequencer 472 */
-       [4569] = { 0x00FF, 0x00FF, 0x0000 }, /* R4569  - Write Sequencer 473 */
-       [4570] = { 0x070F, 0x070F, 0x0000 }, /* R4570  - Write Sequencer 474 */
-       [4571] = { 0x010F, 0x010F, 0x0000 }, /* R4571  - Write Sequencer 475 */
-       [4572] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4572  - Write Sequencer 476 */
-       [4573] = { 0x00FF, 0x00FF, 0x0000 }, /* R4573  - Write Sequencer 477 */
-       [4574] = { 0x070F, 0x070F, 0x0000 }, /* R4574  - Write Sequencer 478 */
-       [4575] = { 0x010F, 0x010F, 0x0000 }, /* R4575  - Write Sequencer 479 */
-       [4576] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4576  - Write Sequencer 480 */
-       [4577] = { 0x00FF, 0x00FF, 0x0000 }, /* R4577  - Write Sequencer 481 */
-       [4578] = { 0x070F, 0x070F, 0x0000 }, /* R4578  - Write Sequencer 482 */
-       [4579] = { 0x010F, 0x010F, 0x0000 }, /* R4579  - Write Sequencer 483 */
-       [4580] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4580  - Write Sequencer 484 */
-       [4581] = { 0x00FF, 0x00FF, 0x0000 }, /* R4581  - Write Sequencer 485 */
-       [4582] = { 0x070F, 0x070F, 0x0000 }, /* R4582  - Write Sequencer 486 */
-       [4583] = { 0x010F, 0x010F, 0x0000 }, /* R4583  - Write Sequencer 487 */
-       [4584] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4584  - Write Sequencer 488 */
-       [4585] = { 0x00FF, 0x00FF, 0x0000 }, /* R4585  - Write Sequencer 489 */
-       [4586] = { 0x070F, 0x070F, 0x0000 }, /* R4586  - Write Sequencer 490 */
-       [4587] = { 0x010F, 0x010F, 0x0000 }, /* R4587  - Write Sequencer 491 */
-       [4588] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4588  - Write Sequencer 492 */
-       [4589] = { 0x00FF, 0x00FF, 0x0000 }, /* R4589  - Write Sequencer 493 */
-       [4590] = { 0x070F, 0x070F, 0x0000 }, /* R4590  - Write Sequencer 494 */
-       [4591] = { 0x010F, 0x010F, 0x0000 }, /* R4591  - Write Sequencer 495 */
-       [4592] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4592  - Write Sequencer 496 */
-       [4593] = { 0x00FF, 0x00FF, 0x0000 }, /* R4593  - Write Sequencer 497 */
-       [4594] = { 0x070F, 0x070F, 0x0000 }, /* R4594  - Write Sequencer 498 */
-       [4595] = { 0x010F, 0x010F, 0x0000 }, /* R4595  - Write Sequencer 499 */
-       [4596] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4596  - Write Sequencer 500 */
-       [4597] = { 0x00FF, 0x00FF, 0x0000 }, /* R4597  - Write Sequencer 501 */
-       [4598] = { 0x070F, 0x070F, 0x0000 }, /* R4598  - Write Sequencer 502 */
-       [4599] = { 0x010F, 0x010F, 0x0000 }, /* R4599  - Write Sequencer 503 */
-       [4600] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4600  - Write Sequencer 504 */
-       [4601] = { 0x00FF, 0x00FF, 0x0000 }, /* R4601  - Write Sequencer 505 */
-       [4602] = { 0x070F, 0x070F, 0x0000 }, /* R4602  - Write Sequencer 506 */
-       [4603] = { 0x010F, 0x010F, 0x0000 }, /* R4603  - Write Sequencer 507 */
-       [4604] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4604  - Write Sequencer 508 */
-       [4605] = { 0x00FF, 0x00FF, 0x0000 }, /* R4605  - Write Sequencer 509 */
-       [4606] = { 0x070F, 0x070F, 0x0000 }, /* R4606  - Write Sequencer 510 */
-       [4607] = { 0x010F, 0x010F, 0x0000 }, /* R4607  - Write Sequencer 511 */
-       [8192] = { 0x03FF, 0x03FF, 0x0000 }, /* R8192  - DSP2 Instruction RAM 0 */
-       [9216] = { 0x003F, 0x003F, 0x0000 }, /* R9216  - DSP2 Address RAM 2 */
-       [9217] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R9217  - DSP2 Address RAM 1 */
-       [9218] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R9218  - DSP2 Address RAM 0 */
-       [12288] = { 0x00FF, 0x00FF, 0x0000 }, /* R12288 - DSP2 Data1 RAM 1 */
-       [12289] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R12289 - DSP2 Data1 RAM 0 */
-       [13312] = { 0x00FF, 0x00FF, 0x0000 }, /* R13312 - DSP2 Data2 RAM 1 */
-       [13313] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R13313 - DSP2 Data2 RAM 0 */
-       [14336] = { 0x00FF, 0x00FF, 0x0000 }, /* R14336 - DSP2 Data3 RAM 1 */
-       [14337] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R14337 - DSP2 Data3 RAM 0 */
-       [15360] = { 0x07FF, 0x07FF, 0x0000 }, /* R15360 - DSP2 Coeff RAM 0 */
-       [16384] = { 0x00FF, 0x00FF, 0x0000 }, /* R16384 - RETUNEADC_SHARED_COEFF_1 */
-       [16385] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16385 - RETUNEADC_SHARED_COEFF_0 */
-       [16386] = { 0x00FF, 0x00FF, 0x0000 }, /* R16386 - RETUNEDAC_SHARED_COEFF_1 */
-       [16387] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16387 - RETUNEDAC_SHARED_COEFF_0 */
-       [16388] = { 0x00FF, 0x00FF, 0x0000 }, /* R16388 - SOUNDSTAGE_ENABLES_1 */
-       [16389] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16389 - SOUNDSTAGE_ENABLES_0 */
-       [16896] = { 0x00FF, 0x00FF, 0x0000 }, /* R16896 - HDBASS_AI_1 */
-       [16897] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16897 - HDBASS_AI_0 */
-       [16898] = { 0x00FF, 0x00FF, 0x0000 }, /* R16898 - HDBASS_AR_1 */
-       [16899] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16899 - HDBASS_AR_0 */
-       [16900] = { 0x00FF, 0x00FF, 0x0000 }, /* R16900 - HDBASS_B_1 */
-       [16901] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16901 - HDBASS_B_0 */
-       [16902] = { 0x00FF, 0x00FF, 0x0000 }, /* R16902 - HDBASS_K_1 */
-       [16903] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16903 - HDBASS_K_0 */
-       [16904] = { 0x00FF, 0x00FF, 0x0000 }, /* R16904 - HDBASS_N1_1 */
-       [16905] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16905 - HDBASS_N1_0 */
-       [16906] = { 0x00FF, 0x00FF, 0x0000 }, /* R16906 - HDBASS_N2_1 */
-       [16907] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16907 - HDBASS_N2_0 */
-       [16908] = { 0x00FF, 0x00FF, 0x0000 }, /* R16908 - HDBASS_N3_1 */
-       [16909] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16909 - HDBASS_N3_0 */
-       [16910] = { 0x00FF, 0x00FF, 0x0000 }, /* R16910 - HDBASS_N4_1 */
-       [16911] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16911 - HDBASS_N4_0 */
-       [16912] = { 0x00FF, 0x00FF, 0x0000 }, /* R16912 - HDBASS_N5_1 */
-       [16913] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16913 - HDBASS_N5_0 */
-       [16914] = { 0x00FF, 0x00FF, 0x0000 }, /* R16914 - HDBASS_X1_1 */
-       [16915] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16915 - HDBASS_X1_0 */
-       [16916] = { 0x00FF, 0x00FF, 0x0000 }, /* R16916 - HDBASS_X2_1 */
-       [16917] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16917 - HDBASS_X2_0 */
-       [16918] = { 0x00FF, 0x00FF, 0x0000 }, /* R16918 - HDBASS_X3_1 */
-       [16919] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16919 - HDBASS_X3_0 */
-       [16920] = { 0x00FF, 0x00FF, 0x0000 }, /* R16920 - HDBASS_ATK_1 */
-       [16921] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16921 - HDBASS_ATK_0 */
-       [16922] = { 0x00FF, 0x00FF, 0x0000 }, /* R16922 - HDBASS_DCY_1 */
-       [16923] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16923 - HDBASS_DCY_0 */
-       [16924] = { 0x00FF, 0x00FF, 0x0000 }, /* R16924 - HDBASS_PG_1 */
-       [16925] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16925 - HDBASS_PG_0 */
-       [17408] = { 0x00FF, 0x00FF, 0x0000 }, /* R17408 - HPF_C_1 */
-       [17409] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17409 - HPF_C_0 */
-       [17920] = { 0x00FF, 0x00FF, 0x0000 }, /* R17920 - ADCL_RETUNE_C1_1 */
-       [17921] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17921 - ADCL_RETUNE_C1_0 */
-       [17922] = { 0x00FF, 0x00FF, 0x0000 }, /* R17922 - ADCL_RETUNE_C2_1 */
-       [17923] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17923 - ADCL_RETUNE_C2_0 */
-       [17924] = { 0x00FF, 0x00FF, 0x0000 }, /* R17924 - ADCL_RETUNE_C3_1 */
-       [17925] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17925 - ADCL_RETUNE_C3_0 */
-       [17926] = { 0x00FF, 0x00FF, 0x0000 }, /* R17926 - ADCL_RETUNE_C4_1 */
-       [17927] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17927 - ADCL_RETUNE_C4_0 */
-       [17928] = { 0x00FF, 0x00FF, 0x0000 }, /* R17928 - ADCL_RETUNE_C5_1 */
-       [17929] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17929 - ADCL_RETUNE_C5_0 */
-       [17930] = { 0x00FF, 0x00FF, 0x0000 }, /* R17930 - ADCL_RETUNE_C6_1 */
-       [17931] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17931 - ADCL_RETUNE_C6_0 */
-       [17932] = { 0x00FF, 0x00FF, 0x0000 }, /* R17932 - ADCL_RETUNE_C7_1 */
-       [17933] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17933 - ADCL_RETUNE_C7_0 */
-       [17934] = { 0x00FF, 0x00FF, 0x0000 }, /* R17934 - ADCL_RETUNE_C8_1 */
-       [17935] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17935 - ADCL_RETUNE_C8_0 */
-       [17936] = { 0x00FF, 0x00FF, 0x0000 }, /* R17936 - ADCL_RETUNE_C9_1 */
-       [17937] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17937 - ADCL_RETUNE_C9_0 */
-       [17938] = { 0x00FF, 0x00FF, 0x0000 }, /* R17938 - ADCL_RETUNE_C10_1 */
-       [17939] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17939 - ADCL_RETUNE_C10_0 */
-       [17940] = { 0x00FF, 0x00FF, 0x0000 }, /* R17940 - ADCL_RETUNE_C11_1 */
-       [17941] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17941 - ADCL_RETUNE_C11_0 */
-       [17942] = { 0x00FF, 0x00FF, 0x0000 }, /* R17942 - ADCL_RETUNE_C12_1 */
-       [17943] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17943 - ADCL_RETUNE_C12_0 */
-       [17944] = { 0x00FF, 0x00FF, 0x0000 }, /* R17944 - ADCL_RETUNE_C13_1 */
-       [17945] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17945 - ADCL_RETUNE_C13_0 */
-       [17946] = { 0x00FF, 0x00FF, 0x0000 }, /* R17946 - ADCL_RETUNE_C14_1 */
-       [17947] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17947 - ADCL_RETUNE_C14_0 */
-       [17948] = { 0x00FF, 0x00FF, 0x0000 }, /* R17948 - ADCL_RETUNE_C15_1 */
-       [17949] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17949 - ADCL_RETUNE_C15_0 */
-       [17950] = { 0x00FF, 0x00FF, 0x0000 }, /* R17950 - ADCL_RETUNE_C16_1 */
-       [17951] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17951 - ADCL_RETUNE_C16_0 */
-       [17952] = { 0x00FF, 0x00FF, 0x0000 }, /* R17952 - ADCL_RETUNE_C17_1 */
-       [17953] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17953 - ADCL_RETUNE_C17_0 */
-       [17954] = { 0x00FF, 0x00FF, 0x0000 }, /* R17954 - ADCL_RETUNE_C18_1 */
-       [17955] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17955 - ADCL_RETUNE_C18_0 */
-       [17956] = { 0x00FF, 0x00FF, 0x0000 }, /* R17956 - ADCL_RETUNE_C19_1 */
-       [17957] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17957 - ADCL_RETUNE_C19_0 */
-       [17958] = { 0x00FF, 0x00FF, 0x0000 }, /* R17958 - ADCL_RETUNE_C20_1 */
-       [17959] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17959 - ADCL_RETUNE_C20_0 */
-       [17960] = { 0x00FF, 0x00FF, 0x0000 }, /* R17960 - ADCL_RETUNE_C21_1 */
-       [17961] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17961 - ADCL_RETUNE_C21_0 */
-       [17962] = { 0x00FF, 0x00FF, 0x0000 }, /* R17962 - ADCL_RETUNE_C22_1 */
-       [17963] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17963 - ADCL_RETUNE_C22_0 */
-       [17964] = { 0x00FF, 0x00FF, 0x0000 }, /* R17964 - ADCL_RETUNE_C23_1 */
-       [17965] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17965 - ADCL_RETUNE_C23_0 */
-       [17966] = { 0x00FF, 0x00FF, 0x0000 }, /* R17966 - ADCL_RETUNE_C24_1 */
-       [17967] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17967 - ADCL_RETUNE_C24_0 */
-       [17968] = { 0x00FF, 0x00FF, 0x0000 }, /* R17968 - ADCL_RETUNE_C25_1 */
-       [17969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17969 - ADCL_RETUNE_C25_0 */
-       [17970] = { 0x00FF, 0x00FF, 0x0000 }, /* R17970 - ADCL_RETUNE_C26_1 */
-       [17971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17971 - ADCL_RETUNE_C26_0 */
-       [17972] = { 0x00FF, 0x00FF, 0x0000 }, /* R17972 - ADCL_RETUNE_C27_1 */
-       [17973] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17973 - ADCL_RETUNE_C27_0 */
-       [17974] = { 0x00FF, 0x00FF, 0x0000 }, /* R17974 - ADCL_RETUNE_C28_1 */
-       [17975] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17975 - ADCL_RETUNE_C28_0 */
-       [17976] = { 0x00FF, 0x00FF, 0x0000 }, /* R17976 - ADCL_RETUNE_C29_1 */
-       [17977] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17977 - ADCL_RETUNE_C29_0 */
-       [17978] = { 0x00FF, 0x00FF, 0x0000 }, /* R17978 - ADCL_RETUNE_C30_1 */
-       [17979] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17979 - ADCL_RETUNE_C30_0 */
-       [17980] = { 0x00FF, 0x00FF, 0x0000 }, /* R17980 - ADCL_RETUNE_C31_1 */
-       [17981] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17981 - ADCL_RETUNE_C31_0 */
-       [17982] = { 0x00FF, 0x00FF, 0x0000 }, /* R17982 - ADCL_RETUNE_C32_1 */
-       [17983] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17983 - ADCL_RETUNE_C32_0 */
-       [18432] = { 0x00FF, 0x00FF, 0x0000 }, /* R18432 - RETUNEADC_PG2_1 */
-       [18433] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18433 - RETUNEADC_PG2_0 */
-       [18434] = { 0x00FF, 0x00FF, 0x0000 }, /* R18434 - RETUNEADC_PG_1 */
-       [18435] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18435 - RETUNEADC_PG_0 */
-       [18944] = { 0x00FF, 0x00FF, 0x0000 }, /* R18944 - ADCR_RETUNE_C1_1 */
-       [18945] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18945 - ADCR_RETUNE_C1_0 */
-       [18946] = { 0x00FF, 0x00FF, 0x0000 }, /* R18946 - ADCR_RETUNE_C2_1 */
-       [18947] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18947 - ADCR_RETUNE_C2_0 */
-       [18948] = { 0x00FF, 0x00FF, 0x0000 }, /* R18948 - ADCR_RETUNE_C3_1 */
-       [18949] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18949 - ADCR_RETUNE_C3_0 */
-       [18950] = { 0x00FF, 0x00FF, 0x0000 }, /* R18950 - ADCR_RETUNE_C4_1 */
-       [18951] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18951 - ADCR_RETUNE_C4_0 */
-       [18952] = { 0x00FF, 0x00FF, 0x0000 }, /* R18952 - ADCR_RETUNE_C5_1 */
-       [18953] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18953 - ADCR_RETUNE_C5_0 */
-       [18954] = { 0x00FF, 0x00FF, 0x0000 }, /* R18954 - ADCR_RETUNE_C6_1 */
-       [18955] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18955 - ADCR_RETUNE_C6_0 */
-       [18956] = { 0x00FF, 0x00FF, 0x0000 }, /* R18956 - ADCR_RETUNE_C7_1 */
-       [18957] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18957 - ADCR_RETUNE_C7_0 */
-       [18958] = { 0x00FF, 0x00FF, 0x0000 }, /* R18958 - ADCR_RETUNE_C8_1 */
-       [18959] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18959 - ADCR_RETUNE_C8_0 */
-       [18960] = { 0x00FF, 0x00FF, 0x0000 }, /* R18960 - ADCR_RETUNE_C9_1 */
-       [18961] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18961 - ADCR_RETUNE_C9_0 */
-       [18962] = { 0x00FF, 0x00FF, 0x0000 }, /* R18962 - ADCR_RETUNE_C10_1 */
-       [18963] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18963 - ADCR_RETUNE_C10_0 */
-       [18964] = { 0x00FF, 0x00FF, 0x0000 }, /* R18964 - ADCR_RETUNE_C11_1 */
-       [18965] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18965 - ADCR_RETUNE_C11_0 */
-       [18966] = { 0x00FF, 0x00FF, 0x0000 }, /* R18966 - ADCR_RETUNE_C12_1 */
-       [18967] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18967 - ADCR_RETUNE_C12_0 */
-       [18968] = { 0x00FF, 0x00FF, 0x0000 }, /* R18968 - ADCR_RETUNE_C13_1 */
-       [18969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18969 - ADCR_RETUNE_C13_0 */
-       [18970] = { 0x00FF, 0x00FF, 0x0000 }, /* R18970 - ADCR_RETUNE_C14_1 */
-       [18971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18971 - ADCR_RETUNE_C14_0 */
-       [18972] = { 0x00FF, 0x00FF, 0x0000 }, /* R18972 - ADCR_RETUNE_C15_1 */
-       [18973] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18973 - ADCR_RETUNE_C15_0 */
-       [18974] = { 0x00FF, 0x00FF, 0x0000 }, /* R18974 - ADCR_RETUNE_C16_1 */
-       [18975] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18975 - ADCR_RETUNE_C16_0 */
-       [18976] = { 0x00FF, 0x00FF, 0x0000 }, /* R18976 - ADCR_RETUNE_C17_1 */
-       [18977] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18977 - ADCR_RETUNE_C17_0 */
-       [18978] = { 0x00FF, 0x00FF, 0x0000 }, /* R18978 - ADCR_RETUNE_C18_1 */
-       [18979] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18979 - ADCR_RETUNE_C18_0 */
-       [18980] = { 0x00FF, 0x00FF, 0x0000 }, /* R18980 - ADCR_RETUNE_C19_1 */
-       [18981] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18981 - ADCR_RETUNE_C19_0 */
-       [18982] = { 0x00FF, 0x00FF, 0x0000 }, /* R18982 - ADCR_RETUNE_C20_1 */
-       [18983] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18983 - ADCR_RETUNE_C20_0 */
-       [18984] = { 0x00FF, 0x00FF, 0x0000 }, /* R18984 - ADCR_RETUNE_C21_1 */
-       [18985] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18985 - ADCR_RETUNE_C21_0 */
-       [18986] = { 0x00FF, 0x00FF, 0x0000 }, /* R18986 - ADCR_RETUNE_C22_1 */
-       [18987] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18987 - ADCR_RETUNE_C22_0 */
-       [18988] = { 0x00FF, 0x00FF, 0x0000 }, /* R18988 - ADCR_RETUNE_C23_1 */
-       [18989] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18989 - ADCR_RETUNE_C23_0 */
-       [18990] = { 0x00FF, 0x00FF, 0x0000 }, /* R18990 - ADCR_RETUNE_C24_1 */
-       [18991] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18991 - ADCR_RETUNE_C24_0 */
-       [18992] = { 0x00FF, 0x00FF, 0x0000 }, /* R18992 - ADCR_RETUNE_C25_1 */
-       [18993] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18993 - ADCR_RETUNE_C25_0 */
-       [18994] = { 0x00FF, 0x00FF, 0x0000 }, /* R18994 - ADCR_RETUNE_C26_1 */
-       [18995] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18995 - ADCR_RETUNE_C26_0 */
-       [18996] = { 0x00FF, 0x00FF, 0x0000 }, /* R18996 - ADCR_RETUNE_C27_1 */
-       [18997] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18997 - ADCR_RETUNE_C27_0 */
-       [18998] = { 0x00FF, 0x00FF, 0x0000 }, /* R18998 - ADCR_RETUNE_C28_1 */
-       [18999] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18999 - ADCR_RETUNE_C28_0 */
-       [19000] = { 0x00FF, 0x00FF, 0x0000 }, /* R19000 - ADCR_RETUNE_C29_1 */
-       [19001] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19001 - ADCR_RETUNE_C29_0 */
-       [19002] = { 0x00FF, 0x00FF, 0x0000 }, /* R19002 - ADCR_RETUNE_C30_1 */
-       [19003] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19003 - ADCR_RETUNE_C30_0 */
-       [19004] = { 0x00FF, 0x00FF, 0x0000 }, /* R19004 - ADCR_RETUNE_C31_1 */
-       [19005] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19005 - ADCR_RETUNE_C31_0 */
-       [19006] = { 0x00FF, 0x00FF, 0x0000 }, /* R19006 - ADCR_RETUNE_C32_1 */
-       [19007] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19007 - ADCR_RETUNE_C32_0 */
-       [19456] = { 0x00FF, 0x00FF, 0x0000 }, /* R19456 - DACL_RETUNE_C1_1 */
-       [19457] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19457 - DACL_RETUNE_C1_0 */
-       [19458] = { 0x00FF, 0x00FF, 0x0000 }, /* R19458 - DACL_RETUNE_C2_1 */
-       [19459] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19459 - DACL_RETUNE_C2_0 */
-       [19460] = { 0x00FF, 0x00FF, 0x0000 }, /* R19460 - DACL_RETUNE_C3_1 */
-       [19461] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19461 - DACL_RETUNE_C3_0 */
-       [19462] = { 0x00FF, 0x00FF, 0x0000 }, /* R19462 - DACL_RETUNE_C4_1 */
-       [19463] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19463 - DACL_RETUNE_C4_0 */
-       [19464] = { 0x00FF, 0x00FF, 0x0000 }, /* R19464 - DACL_RETUNE_C5_1 */
-       [19465] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19465 - DACL_RETUNE_C5_0 */
-       [19466] = { 0x00FF, 0x00FF, 0x0000 }, /* R19466 - DACL_RETUNE_C6_1 */
-       [19467] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19467 - DACL_RETUNE_C6_0 */
-       [19468] = { 0x00FF, 0x00FF, 0x0000 }, /* R19468 - DACL_RETUNE_C7_1 */
-       [19469] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19469 - DACL_RETUNE_C7_0 */
-       [19470] = { 0x00FF, 0x00FF, 0x0000 }, /* R19470 - DACL_RETUNE_C8_1 */
-       [19471] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19471 - DACL_RETUNE_C8_0 */
-       [19472] = { 0x00FF, 0x00FF, 0x0000 }, /* R19472 - DACL_RETUNE_C9_1 */
-       [19473] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19473 - DACL_RETUNE_C9_0 */
-       [19474] = { 0x00FF, 0x00FF, 0x0000 }, /* R19474 - DACL_RETUNE_C10_1 */
-       [19475] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19475 - DACL_RETUNE_C10_0 */
-       [19476] = { 0x00FF, 0x00FF, 0x0000 }, /* R19476 - DACL_RETUNE_C11_1 */
-       [19477] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19477 - DACL_RETUNE_C11_0 */
-       [19478] = { 0x00FF, 0x00FF, 0x0000 }, /* R19478 - DACL_RETUNE_C12_1 */
-       [19479] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19479 - DACL_RETUNE_C12_0 */
-       [19480] = { 0x00FF, 0x00FF, 0x0000 }, /* R19480 - DACL_RETUNE_C13_1 */
-       [19481] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19481 - DACL_RETUNE_C13_0 */
-       [19482] = { 0x00FF, 0x00FF, 0x0000 }, /* R19482 - DACL_RETUNE_C14_1 */
-       [19483] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19483 - DACL_RETUNE_C14_0 */
-       [19484] = { 0x00FF, 0x00FF, 0x0000 }, /* R19484 - DACL_RETUNE_C15_1 */
-       [19485] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19485 - DACL_RETUNE_C15_0 */
-       [19486] = { 0x00FF, 0x00FF, 0x0000 }, /* R19486 - DACL_RETUNE_C16_1 */
-       [19487] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19487 - DACL_RETUNE_C16_0 */
-       [19488] = { 0x00FF, 0x00FF, 0x0000 }, /* R19488 - DACL_RETUNE_C17_1 */
-       [19489] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19489 - DACL_RETUNE_C17_0 */
-       [19490] = { 0x00FF, 0x00FF, 0x0000 }, /* R19490 - DACL_RETUNE_C18_1 */
-       [19491] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19491 - DACL_RETUNE_C18_0 */
-       [19492] = { 0x00FF, 0x00FF, 0x0000 }, /* R19492 - DACL_RETUNE_C19_1 */
-       [19493] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19493 - DACL_RETUNE_C19_0 */
-       [19494] = { 0x00FF, 0x00FF, 0x0000 }, /* R19494 - DACL_RETUNE_C20_1 */
-       [19495] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19495 - DACL_RETUNE_C20_0 */
-       [19496] = { 0x00FF, 0x00FF, 0x0000 }, /* R19496 - DACL_RETUNE_C21_1 */
-       [19497] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19497 - DACL_RETUNE_C21_0 */
-       [19498] = { 0x00FF, 0x00FF, 0x0000 }, /* R19498 - DACL_RETUNE_C22_1 */
-       [19499] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19499 - DACL_RETUNE_C22_0 */
-       [19500] = { 0x00FF, 0x00FF, 0x0000 }, /* R19500 - DACL_RETUNE_C23_1 */
-       [19501] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19501 - DACL_RETUNE_C23_0 */
-       [19502] = { 0x00FF, 0x00FF, 0x0000 }, /* R19502 - DACL_RETUNE_C24_1 */
-       [19503] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19503 - DACL_RETUNE_C24_0 */
-       [19504] = { 0x00FF, 0x00FF, 0x0000 }, /* R19504 - DACL_RETUNE_C25_1 */
-       [19505] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19505 - DACL_RETUNE_C25_0 */
-       [19506] = { 0x00FF, 0x00FF, 0x0000 }, /* R19506 - DACL_RETUNE_C26_1 */
-       [19507] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19507 - DACL_RETUNE_C26_0 */
-       [19508] = { 0x00FF, 0x00FF, 0x0000 }, /* R19508 - DACL_RETUNE_C27_1 */
-       [19509] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19509 - DACL_RETUNE_C27_0 */
-       [19510] = { 0x00FF, 0x00FF, 0x0000 }, /* R19510 - DACL_RETUNE_C28_1 */
-       [19511] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19511 - DACL_RETUNE_C28_0 */
-       [19512] = { 0x00FF, 0x00FF, 0x0000 }, /* R19512 - DACL_RETUNE_C29_1 */
-       [19513] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19513 - DACL_RETUNE_C29_0 */
-       [19514] = { 0x00FF, 0x00FF, 0x0000 }, /* R19514 - DACL_RETUNE_C30_1 */
-       [19515] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19515 - DACL_RETUNE_C30_0 */
-       [19516] = { 0x00FF, 0x00FF, 0x0000 }, /* R19516 - DACL_RETUNE_C31_1 */
-       [19517] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19517 - DACL_RETUNE_C31_0 */
-       [19518] = { 0x00FF, 0x00FF, 0x0000 }, /* R19518 - DACL_RETUNE_C32_1 */
-       [19519] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19519 - DACL_RETUNE_C32_0 */
-       [19968] = { 0x00FF, 0x00FF, 0x0000 }, /* R19968 - RETUNEDAC_PG2_1 */
-       [19969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19969 - RETUNEDAC_PG2_0 */
-       [19970] = { 0x00FF, 0x00FF, 0x0000 }, /* R19970 - RETUNEDAC_PG_1 */
-       [19971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19971 - RETUNEDAC_PG_0 */
-       [20480] = { 0x00FF, 0x00FF, 0x0000 }, /* R20480 - DACR_RETUNE_C1_1 */
-       [20481] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20481 - DACR_RETUNE_C1_0 */
-       [20482] = { 0x00FF, 0x00FF, 0x0000 }, /* R20482 - DACR_RETUNE_C2_1 */
-       [20483] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20483 - DACR_RETUNE_C2_0 */
-       [20484] = { 0x00FF, 0x00FF, 0x0000 }, /* R20484 - DACR_RETUNE_C3_1 */
-       [20485] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20485 - DACR_RETUNE_C3_0 */
-       [20486] = { 0x00FF, 0x00FF, 0x0000 }, /* R20486 - DACR_RETUNE_C4_1 */
-       [20487] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20487 - DACR_RETUNE_C4_0 */
-       [20488] = { 0x00FF, 0x00FF, 0x0000 }, /* R20488 - DACR_RETUNE_C5_1 */
-       [20489] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20489 - DACR_RETUNE_C5_0 */
-       [20490] = { 0x00FF, 0x00FF, 0x0000 }, /* R20490 - DACR_RETUNE_C6_1 */
-       [20491] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20491 - DACR_RETUNE_C6_0 */
-       [20492] = { 0x00FF, 0x00FF, 0x0000 }, /* R20492 - DACR_RETUNE_C7_1 */
-       [20493] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20493 - DACR_RETUNE_C7_0 */
-       [20494] = { 0x00FF, 0x00FF, 0x0000 }, /* R20494 - DACR_RETUNE_C8_1 */
-       [20495] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20495 - DACR_RETUNE_C8_0 */
-       [20496] = { 0x00FF, 0x00FF, 0x0000 }, /* R20496 - DACR_RETUNE_C9_1 */
-       [20497] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20497 - DACR_RETUNE_C9_0 */
-       [20498] = { 0x00FF, 0x00FF, 0x0000 }, /* R20498 - DACR_RETUNE_C10_1 */
-       [20499] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20499 - DACR_RETUNE_C10_0 */
-       [20500] = { 0x00FF, 0x00FF, 0x0000 }, /* R20500 - DACR_RETUNE_C11_1 */
-       [20501] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20501 - DACR_RETUNE_C11_0 */
-       [20502] = { 0x00FF, 0x00FF, 0x0000 }, /* R20502 - DACR_RETUNE_C12_1 */
-       [20503] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20503 - DACR_RETUNE_C12_0 */
-       [20504] = { 0x00FF, 0x00FF, 0x0000 }, /* R20504 - DACR_RETUNE_C13_1 */
-       [20505] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20505 - DACR_RETUNE_C13_0 */
-       [20506] = { 0x00FF, 0x00FF, 0x0000 }, /* R20506 - DACR_RETUNE_C14_1 */
-       [20507] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20507 - DACR_RETUNE_C14_0 */
-       [20508] = { 0x00FF, 0x00FF, 0x0000 }, /* R20508 - DACR_RETUNE_C15_1 */
-       [20509] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20509 - DACR_RETUNE_C15_0 */
-       [20510] = { 0x00FF, 0x00FF, 0x0000 }, /* R20510 - DACR_RETUNE_C16_1 */
-       [20511] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20511 - DACR_RETUNE_C16_0 */
-       [20512] = { 0x00FF, 0x00FF, 0x0000 }, /* R20512 - DACR_RETUNE_C17_1 */
-       [20513] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20513 - DACR_RETUNE_C17_0 */
-       [20514] = { 0x00FF, 0x00FF, 0x0000 }, /* R20514 - DACR_RETUNE_C18_1 */
-       [20515] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20515 - DACR_RETUNE_C18_0 */
-       [20516] = { 0x00FF, 0x00FF, 0x0000 }, /* R20516 - DACR_RETUNE_C19_1 */
-       [20517] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20517 - DACR_RETUNE_C19_0 */
-       [20518] = { 0x00FF, 0x00FF, 0x0000 }, /* R20518 - DACR_RETUNE_C20_1 */
-       [20519] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20519 - DACR_RETUNE_C20_0 */
-       [20520] = { 0x00FF, 0x00FF, 0x0000 }, /* R20520 - DACR_RETUNE_C21_1 */
-       [20521] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20521 - DACR_RETUNE_C21_0 */
-       [20522] = { 0x00FF, 0x00FF, 0x0000 }, /* R20522 - DACR_RETUNE_C22_1 */
-       [20523] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20523 - DACR_RETUNE_C22_0 */
-       [20524] = { 0x00FF, 0x00FF, 0x0000 }, /* R20524 - DACR_RETUNE_C23_1 */
-       [20525] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20525 - DACR_RETUNE_C23_0 */
-       [20526] = { 0x00FF, 0x00FF, 0x0000 }, /* R20526 - DACR_RETUNE_C24_1 */
-       [20527] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20527 - DACR_RETUNE_C24_0 */
-       [20528] = { 0x00FF, 0x00FF, 0x0000 }, /* R20528 - DACR_RETUNE_C25_1 */
-       [20529] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20529 - DACR_RETUNE_C25_0 */
-       [20530] = { 0x00FF, 0x00FF, 0x0000 }, /* R20530 - DACR_RETUNE_C26_1 */
-       [20531] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20531 - DACR_RETUNE_C26_0 */
-       [20532] = { 0x00FF, 0x00FF, 0x0000 }, /* R20532 - DACR_RETUNE_C27_1 */
-       [20533] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20533 - DACR_RETUNE_C27_0 */
-       [20534] = { 0x00FF, 0x00FF, 0x0000 }, /* R20534 - DACR_RETUNE_C28_1 */
-       [20535] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20535 - DACR_RETUNE_C28_0 */
-       [20536] = { 0x00FF, 0x00FF, 0x0000 }, /* R20536 - DACR_RETUNE_C29_1 */
-       [20537] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20537 - DACR_RETUNE_C29_0 */
-       [20538] = { 0x00FF, 0x00FF, 0x0000 }, /* R20538 - DACR_RETUNE_C30_1 */
-       [20539] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20539 - DACR_RETUNE_C30_0 */
-       [20540] = { 0x00FF, 0x00FF, 0x0000 }, /* R20540 - DACR_RETUNE_C31_1 */
-       [20541] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20541 - DACR_RETUNE_C31_0 */
-       [20542] = { 0x00FF, 0x00FF, 0x0000 }, /* R20542 - DACR_RETUNE_C32_1 */
-       [20543] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20543 - DACR_RETUNE_C32_0 */
-       [20992] = { 0x00FF, 0x00FF, 0x0000 }, /* R20992 - VSS_XHD2_1 */
-       [20993] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20993 - VSS_XHD2_0 */
-       [20994] = { 0x00FF, 0x00FF, 0x0000 }, /* R20994 - VSS_XHD3_1 */
-       [20995] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20995 - VSS_XHD3_0 */
-       [20996] = { 0x00FF, 0x00FF, 0x0000 }, /* R20996 - VSS_XHN1_1 */
-       [20997] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20997 - VSS_XHN1_0 */
-       [20998] = { 0x00FF, 0x00FF, 0x0000 }, /* R20998 - VSS_XHN2_1 */
-       [20999] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20999 - VSS_XHN2_0 */
-       [21000] = { 0x00FF, 0x00FF, 0x0000 }, /* R21000 - VSS_XHN3_1 */
-       [21001] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21001 - VSS_XHN3_0 */
-       [21002] = { 0x00FF, 0x00FF, 0x0000 }, /* R21002 - VSS_XLA_1 */
-       [21003] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21003 - VSS_XLA_0 */
-       [21004] = { 0x00FF, 0x00FF, 0x0000 }, /* R21004 - VSS_XLB_1 */
-       [21005] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21005 - VSS_XLB_0 */
-       [21006] = { 0x00FF, 0x00FF, 0x0000 }, /* R21006 - VSS_XLG_1 */
-       [21007] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21007 - VSS_XLG_0 */
-       [21008] = { 0x00FF, 0x00FF, 0x0000 }, /* R21008 - VSS_PG2_1 */
-       [21009] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21009 - VSS_PG2_0 */
-       [21010] = { 0x00FF, 0x00FF, 0x0000 }, /* R21010 - VSS_PG_1 */
-       [21011] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21011 - VSS_PG_0 */
-       [21012] = { 0x00FF, 0x00FF, 0x0000 }, /* R21012 - VSS_XTD1_1 */
-       [21013] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21013 - VSS_XTD1_0 */
-       [21014] = { 0x00FF, 0x00FF, 0x0000 }, /* R21014 - VSS_XTD2_1 */
-       [21015] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21015 - VSS_XTD2_0 */
-       [21016] = { 0x00FF, 0x00FF, 0x0000 }, /* R21016 - VSS_XTD3_1 */
-       [21017] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21017 - VSS_XTD3_0 */
-       [21018] = { 0x00FF, 0x00FF, 0x0000 }, /* R21018 - VSS_XTD4_1 */
-       [21019] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21019 - VSS_XTD4_0 */
-       [21020] = { 0x00FF, 0x00FF, 0x0000 }, /* R21020 - VSS_XTD5_1 */
-       [21021] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21021 - VSS_XTD5_0 */
-       [21022] = { 0x00FF, 0x00FF, 0x0000 }, /* R21022 - VSS_XTD6_1 */
-       [21023] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21023 - VSS_XTD6_0 */
-       [21024] = { 0x00FF, 0x00FF, 0x0000 }, /* R21024 - VSS_XTD7_1 */
-       [21025] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21025 - VSS_XTD7_0 */
-       [21026] = { 0x00FF, 0x00FF, 0x0000 }, /* R21026 - VSS_XTD8_1 */
-       [21027] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21027 - VSS_XTD8_0 */
-       [21028] = { 0x00FF, 0x00FF, 0x0000 }, /* R21028 - VSS_XTD9_1 */
-       [21029] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21029 - VSS_XTD9_0 */
-       [21030] = { 0x00FF, 0x00FF, 0x0000 }, /* R21030 - VSS_XTD10_1 */
-       [21031] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21031 - VSS_XTD10_0 */
-       [21032] = { 0x00FF, 0x00FF, 0x0000 }, /* R21032 - VSS_XTD11_1 */
-       [21033] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21033 - VSS_XTD11_0 */
-       [21034] = { 0x00FF, 0x00FF, 0x0000 }, /* R21034 - VSS_XTD12_1 */
-       [21035] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21035 - VSS_XTD12_0 */
-       [21036] = { 0x00FF, 0x00FF, 0x0000 }, /* R21036 - VSS_XTD13_1 */
-       [21037] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21037 - VSS_XTD13_0 */
-       [21038] = { 0x00FF, 0x00FF, 0x0000 }, /* R21038 - VSS_XTD14_1 */
-       [21039] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21039 - VSS_XTD14_0 */
-       [21040] = { 0x00FF, 0x00FF, 0x0000 }, /* R21040 - VSS_XTD15_1 */
-       [21041] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21041 - VSS_XTD15_0 */
-       [21042] = { 0x00FF, 0x00FF, 0x0000 }, /* R21042 - VSS_XTD16_1 */
-       [21043] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21043 - VSS_XTD16_0 */
-       [21044] = { 0x00FF, 0x00FF, 0x0000 }, /* R21044 - VSS_XTD17_1 */
-       [21045] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21045 - VSS_XTD17_0 */
-       [21046] = { 0x00FF, 0x00FF, 0x0000 }, /* R21046 - VSS_XTD18_1 */
-       [21047] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21047 - VSS_XTD18_0 */
-       [21048] = { 0x00FF, 0x00FF, 0x0000 }, /* R21048 - VSS_XTD19_1 */
-       [21049] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21049 - VSS_XTD19_0 */
-       [21050] = { 0x00FF, 0x00FF, 0x0000 }, /* R21050 - VSS_XTD20_1 */
-       [21051] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21051 - VSS_XTD20_0 */
-       [21052] = { 0x00FF, 0x00FF, 0x0000 }, /* R21052 - VSS_XTD21_1 */
-       [21053] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21053 - VSS_XTD21_0 */
-       [21054] = { 0x00FF, 0x00FF, 0x0000 }, /* R21054 - VSS_XTD22_1 */
-       [21055] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21055 - VSS_XTD22_0 */
-       [21056] = { 0x00FF, 0x00FF, 0x0000 }, /* R21056 - VSS_XTD23_1 */
-       [21057] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21057 - VSS_XTD23_0 */
-       [21058] = { 0x00FF, 0x00FF, 0x0000 }, /* R21058 - VSS_XTD24_1 */
-       [21059] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21059 - VSS_XTD24_0 */
-       [21060] = { 0x00FF, 0x00FF, 0x0000 }, /* R21060 - VSS_XTD25_1 */
-       [21061] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21061 - VSS_XTD25_0 */
-       [21062] = { 0x00FF, 0x00FF, 0x0000 }, /* R21062 - VSS_XTD26_1 */
-       [21063] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21063 - VSS_XTD26_0 */
-       [21064] = { 0x00FF, 0x00FF, 0x0000 }, /* R21064 - VSS_XTD27_1 */
-       [21065] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21065 - VSS_XTD27_0 */
-       [21066] = { 0x00FF, 0x00FF, 0x0000 }, /* R21066 - VSS_XTD28_1 */
-       [21067] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21067 - VSS_XTD28_0 */
-       [21068] = { 0x00FF, 0x00FF, 0x0000 }, /* R21068 - VSS_XTD29_1 */
-       [21069] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21069 - VSS_XTD29_0 */
-       [21070] = { 0x00FF, 0x00FF, 0x0000 }, /* R21070 - VSS_XTD30_1 */
-       [21071] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21071 - VSS_XTD30_0 */
-       [21072] = { 0x00FF, 0x00FF, 0x0000 }, /* R21072 - VSS_XTD31_1 */
-       [21073] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21073 - VSS_XTD31_0 */
-       [21074] = { 0x00FF, 0x00FF, 0x0000 }, /* R21074 - VSS_XTD32_1 */
-       [21075] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21075 - VSS_XTD32_0 */
-       [21076] = { 0x00FF, 0x00FF, 0x0000 }, /* R21076 - VSS_XTS1_1 */
-       [21077] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21077 - VSS_XTS1_0 */
-       [21078] = { 0x00FF, 0x00FF, 0x0000 }, /* R21078 - VSS_XTS2_1 */
-       [21079] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21079 - VSS_XTS2_0 */
-       [21080] = { 0x00FF, 0x00FF, 0x0000 }, /* R21080 - VSS_XTS3_1 */
-       [21081] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21081 - VSS_XTS3_0 */
-       [21082] = { 0x00FF, 0x00FF, 0x0000 }, /* R21082 - VSS_XTS4_1 */
-       [21083] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21083 - VSS_XTS4_0 */
-       [21084] = { 0x00FF, 0x00FF, 0x0000 }, /* R21084 - VSS_XTS5_1 */
-       [21085] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21085 - VSS_XTS5_0 */
-       [21086] = { 0x00FF, 0x00FF, 0x0000 }, /* R21086 - VSS_XTS6_1 */
-       [21087] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21087 - VSS_XTS6_0 */
-       [21088] = { 0x00FF, 0x00FF, 0x0000 }, /* R21088 - VSS_XTS7_1 */
-       [21089] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21089 - VSS_XTS7_0 */
-       [21090] = { 0x00FF, 0x00FF, 0x0000 }, /* R21090 - VSS_XTS8_1 */
-       [21091] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21091 - VSS_XTS8_0 */
-       [21092] = { 0x00FF, 0x00FF, 0x0000 }, /* R21092 - VSS_XTS9_1 */
-       [21093] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21093 - VSS_XTS9_0 */
-       [21094] = { 0x00FF, 0x00FF, 0x0000 }, /* R21094 - VSS_XTS10_1 */
-       [21095] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21095 - VSS_XTS10_0 */
-       [21096] = { 0x00FF, 0x00FF, 0x0000 }, /* R21096 - VSS_XTS11_1 */
-       [21097] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21097 - VSS_XTS11_0 */
-       [21098] = { 0x00FF, 0x00FF, 0x0000 }, /* R21098 - VSS_XTS12_1 */
-       [21099] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21099 - VSS_XTS12_0 */
-       [21100] = { 0x00FF, 0x00FF, 0x0000 }, /* R21100 - VSS_XTS13_1 */
-       [21101] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21101 - VSS_XTS13_0 */
-       [21102] = { 0x00FF, 0x00FF, 0x0000 }, /* R21102 - VSS_XTS14_1 */
-       [21103] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21103 - VSS_XTS14_0 */
-       [21104] = { 0x00FF, 0x00FF, 0x0000 }, /* R21104 - VSS_XTS15_1 */
-       [21105] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21105 - VSS_XTS15_0 */
-       [21106] = { 0x00FF, 0x00FF, 0x0000 }, /* R21106 - VSS_XTS16_1 */
-       [21107] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21107 - VSS_XTS16_0 */
-       [21108] = { 0x00FF, 0x00FF, 0x0000 }, /* R21108 - VSS_XTS17_1 */
-       [21109] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21109 - VSS_XTS17_0 */
-       [21110] = { 0x00FF, 0x00FF, 0x0000 }, /* R21110 - VSS_XTS18_1 */
-       [21111] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21111 - VSS_XTS18_0 */
-       [21112] = { 0x00FF, 0x00FF, 0x0000 }, /* R21112 - VSS_XTS19_1 */
-       [21113] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21113 - VSS_XTS19_0 */
-       [21114] = { 0x00FF, 0x00FF, 0x0000 }, /* R21114 - VSS_XTS20_1 */
-       [21115] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21115 - VSS_XTS20_0 */
-       [21116] = { 0x00FF, 0x00FF, 0x0000 }, /* R21116 - VSS_XTS21_1 */
-       [21117] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21117 - VSS_XTS21_0 */
-       [21118] = { 0x00FF, 0x00FF, 0x0000 }, /* R21118 - VSS_XTS22_1 */
-       [21119] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21119 - VSS_XTS22_0 */
-       [21120] = { 0x00FF, 0x00FF, 0x0000 }, /* R21120 - VSS_XTS23_1 */
-       [21121] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21121 - VSS_XTS23_0 */
-       [21122] = { 0x00FF, 0x00FF, 0x0000 }, /* R21122 - VSS_XTS24_1 */
-       [21123] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21123 - VSS_XTS24_0 */
-       [21124] = { 0x00FF, 0x00FF, 0x0000 }, /* R21124 - VSS_XTS25_1 */
-       [21125] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21125 - VSS_XTS25_0 */
-       [21126] = { 0x00FF, 0x00FF, 0x0000 }, /* R21126 - VSS_XTS26_1 */
-       [21127] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21127 - VSS_XTS26_0 */
-       [21128] = { 0x00FF, 0x00FF, 0x0000 }, /* R21128 - VSS_XTS27_1 */
-       [21129] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21129 - VSS_XTS27_0 */
-       [21130] = { 0x00FF, 0x00FF, 0x0000 }, /* R21130 - VSS_XTS28_1 */
-       [21131] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21131 - VSS_XTS28_0 */
-       [21132] = { 0x00FF, 0x00FF, 0x0000 }, /* R21132 - VSS_XTS29_1 */
-       [21133] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21133 - VSS_XTS29_0 */
-       [21134] = { 0x00FF, 0x00FF, 0x0000 }, /* R21134 - VSS_XTS30_1 */
-       [21135] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21135 - VSS_XTS30_0 */
-       [21136] = { 0x00FF, 0x00FF, 0x0000 }, /* R21136 - VSS_XTS31_1 */
-       [21137] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21137 - VSS_XTS31_0 */
-       [21138] = { 0x00FF, 0x00FF, 0x0000 }, /* R21138 - VSS_XTS32_1 */
-       [21139] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21139 - VSS_XTS32_0 */
-};
-
 static bool wm8962_volatile_register(struct device *dev, unsigned int reg)
 {
-       if (wm8962_reg_access[reg].vol)
-               return 1;
-       else
-               return 0;
+       switch (reg) {
+       case WM8962_CLOCKING1:
+       case WM8962_CLOCKING2:
+       case WM8962_SOFTWARE_RESET:
+       case WM8962_ALC2:
+       case WM8962_THERMAL_SHUTDOWN_STATUS:
+       case WM8962_ADDITIONAL_CONTROL_4:
+       case WM8962_CLASS_D_CONTROL_1:
+       case WM8962_DC_SERVO_6:
+       case WM8962_INTERRUPT_STATUS_1:
+       case WM8962_INTERRUPT_STATUS_2:
+       case WM8962_DSP2_EXECCONTROL:
+               return true;
+       default:
+               return false;
+       }
 }
 
 static bool wm8962_readable_register(struct device *dev, unsigned int reg)
 {
-       if (wm8962_reg_access[reg].read)
-               return 1;
-       else
-               return 0;
+       switch (reg) {
+       case WM8962_LEFT_INPUT_VOLUME:
+       case WM8962_RIGHT_INPUT_VOLUME:
+       case WM8962_HPOUTL_VOLUME:
+       case WM8962_HPOUTR_VOLUME:
+       case WM8962_CLOCKING1:
+       case WM8962_ADC_DAC_CONTROL_1:
+       case WM8962_ADC_DAC_CONTROL_2:
+       case WM8962_AUDIO_INTERFACE_0:
+       case WM8962_CLOCKING2:
+       case WM8962_AUDIO_INTERFACE_1:
+       case WM8962_LEFT_DAC_VOLUME:
+       case WM8962_RIGHT_DAC_VOLUME:
+       case WM8962_AUDIO_INTERFACE_2:
+       case WM8962_SOFTWARE_RESET:
+       case WM8962_ALC1:
+       case WM8962_ALC2:
+       case WM8962_ALC3:
+       case WM8962_NOISE_GATE:
+       case WM8962_LEFT_ADC_VOLUME:
+       case WM8962_RIGHT_ADC_VOLUME:
+       case WM8962_ADDITIONAL_CONTROL_1:
+       case WM8962_ADDITIONAL_CONTROL_2:
+       case WM8962_PWR_MGMT_1:
+       case WM8962_PWR_MGMT_2:
+       case WM8962_ADDITIONAL_CONTROL_3:
+       case WM8962_ANTI_POP:
+       case WM8962_CLOCKING_3:
+       case WM8962_INPUT_MIXER_CONTROL_1:
+       case WM8962_LEFT_INPUT_MIXER_VOLUME:
+       case WM8962_RIGHT_INPUT_MIXER_VOLUME:
+       case WM8962_INPUT_MIXER_CONTROL_2:
+       case WM8962_INPUT_BIAS_CONTROL:
+       case WM8962_LEFT_INPUT_PGA_CONTROL:
+       case WM8962_RIGHT_INPUT_PGA_CONTROL:
+       case WM8962_SPKOUTL_VOLUME:
+       case WM8962_SPKOUTR_VOLUME:
+       case WM8962_THERMAL_SHUTDOWN_STATUS:
+       case WM8962_ADDITIONAL_CONTROL_4:
+       case WM8962_CLASS_D_CONTROL_1:
+       case WM8962_CLASS_D_CONTROL_2:
+       case WM8962_CLOCKING_4:
+       case WM8962_DAC_DSP_MIXING_1:
+       case WM8962_DAC_DSP_MIXING_2:
+       case WM8962_DC_SERVO_0:
+       case WM8962_DC_SERVO_1:
+       case WM8962_DC_SERVO_4:
+       case WM8962_DC_SERVO_6:
+       case WM8962_ANALOGUE_PGA_BIAS:
+       case WM8962_ANALOGUE_HP_0:
+       case WM8962_ANALOGUE_HP_2:
+       case WM8962_CHARGE_PUMP_1:
+       case WM8962_CHARGE_PUMP_B:
+       case WM8962_WRITE_SEQUENCER_CONTROL_1:
+       case WM8962_WRITE_SEQUENCER_CONTROL_2:
+       case WM8962_WRITE_SEQUENCER_CONTROL_3:
+       case WM8962_CONTROL_INTERFACE:
+       case WM8962_MIXER_ENABLES:
+       case WM8962_HEADPHONE_MIXER_1:
+       case WM8962_HEADPHONE_MIXER_2:
+       case WM8962_HEADPHONE_MIXER_3:
+       case WM8962_HEADPHONE_MIXER_4:
+       case WM8962_SPEAKER_MIXER_1:
+       case WM8962_SPEAKER_MIXER_2:
+       case WM8962_SPEAKER_MIXER_3:
+       case WM8962_SPEAKER_MIXER_4:
+       case WM8962_SPEAKER_MIXER_5:
+       case WM8962_BEEP_GENERATOR_1:
+       case WM8962_OSCILLATOR_TRIM_3:
+       case WM8962_OSCILLATOR_TRIM_4:
+       case WM8962_OSCILLATOR_TRIM_7:
+       case WM8962_ANALOGUE_CLOCKING1:
+       case WM8962_ANALOGUE_CLOCKING2:
+       case WM8962_ANALOGUE_CLOCKING3:
+       case WM8962_PLL_SOFTWARE_RESET:
+       case WM8962_PLL2:
+       case WM8962_PLL_4:
+       case WM8962_PLL_9:
+       case WM8962_PLL_10:
+       case WM8962_PLL_11:
+       case WM8962_PLL_12:
+       case WM8962_PLL_13:
+       case WM8962_PLL_14:
+       case WM8962_PLL_15:
+       case WM8962_PLL_16:
+       case WM8962_FLL_CONTROL_1:
+       case WM8962_FLL_CONTROL_2:
+       case WM8962_FLL_CONTROL_3:
+       case WM8962_FLL_CONTROL_5:
+       case WM8962_FLL_CONTROL_6:
+       case WM8962_FLL_CONTROL_7:
+       case WM8962_FLL_CONTROL_8:
+       case WM8962_GENERAL_TEST_1:
+       case WM8962_DF1:
+       case WM8962_DF2:
+       case WM8962_DF3:
+       case WM8962_DF4:
+       case WM8962_DF5:
+       case WM8962_DF6:
+       case WM8962_DF7:
+       case WM8962_LHPF1:
+       case WM8962_LHPF2:
+       case WM8962_THREED1:
+       case WM8962_THREED2:
+       case WM8962_THREED3:
+       case WM8962_THREED4:
+       case WM8962_DRC_1:
+       case WM8962_DRC_2:
+       case WM8962_DRC_3:
+       case WM8962_DRC_4:
+       case WM8962_DRC_5:
+       case WM8962_TLOOPBACK:
+       case WM8962_EQ1:
+       case WM8962_EQ2:
+       case WM8962_EQ3:
+       case WM8962_EQ4:
+       case WM8962_EQ5:
+       case WM8962_EQ6:
+       case WM8962_EQ7:
+       case WM8962_EQ8:
+       case WM8962_EQ9:
+       case WM8962_EQ10:
+       case WM8962_EQ11:
+       case WM8962_EQ12:
+       case WM8962_EQ13:
+       case WM8962_EQ14:
+       case WM8962_EQ15:
+       case WM8962_EQ16:
+       case WM8962_EQ17:
+       case WM8962_EQ18:
+       case WM8962_EQ19:
+       case WM8962_EQ20:
+       case WM8962_EQ21:
+       case WM8962_EQ22:
+       case WM8962_EQ23:
+       case WM8962_EQ24:
+       case WM8962_EQ25:
+       case WM8962_EQ26:
+       case WM8962_EQ27:
+       case WM8962_EQ28:
+       case WM8962_EQ29:
+       case WM8962_EQ30:
+       case WM8962_EQ31:
+       case WM8962_EQ32:
+       case WM8962_EQ33:
+       case WM8962_EQ34:
+       case WM8962_EQ35:
+       case WM8962_EQ36:
+       case WM8962_EQ37:
+       case WM8962_EQ38:
+       case WM8962_EQ39:
+       case WM8962_EQ40:
+       case WM8962_EQ41:
+       case WM8962_GPIO_BASE:
+       case WM8962_GPIO_2:
+       case WM8962_GPIO_3:
+       case WM8962_GPIO_5:
+       case WM8962_GPIO_6:
+       case WM8962_INTERRUPT_STATUS_1:
+       case WM8962_INTERRUPT_STATUS_2:
+       case WM8962_INTERRUPT_STATUS_1_MASK:
+       case WM8962_INTERRUPT_STATUS_2_MASK:
+       case WM8962_INTERRUPT_CONTROL:
+       case WM8962_IRQ_DEBOUNCE:
+       case WM8962_MICINT_SOURCE_POL:
+       case WM8962_DSP2_POWER_MANAGEMENT:
+       case WM8962_DSP2_EXECCONTROL:
+       case WM8962_DSP2_INSTRUCTION_RAM_0:
+       case WM8962_DSP2_ADDRESS_RAM_2:
+       case WM8962_DSP2_ADDRESS_RAM_1:
+       case WM8962_DSP2_ADDRESS_RAM_0:
+       case WM8962_DSP2_DATA1_RAM_1:
+       case WM8962_DSP2_DATA1_RAM_0:
+       case WM8962_DSP2_DATA2_RAM_1:
+       case WM8962_DSP2_DATA2_RAM_0:
+       case WM8962_DSP2_DATA3_RAM_1:
+       case WM8962_DSP2_DATA3_RAM_0:
+       case WM8962_DSP2_COEFF_RAM_0:
+       case WM8962_RETUNEADC_SHARED_COEFF_1:
+       case WM8962_RETUNEADC_SHARED_COEFF_0:
+       case WM8962_RETUNEDAC_SHARED_COEFF_1:
+       case WM8962_RETUNEDAC_SHARED_COEFF_0:
+       case WM8962_SOUNDSTAGE_ENABLES_1:
+       case WM8962_SOUNDSTAGE_ENABLES_0:
+       case WM8962_HDBASS_AI_1:
+       case WM8962_HDBASS_AI_0:
+       case WM8962_HDBASS_AR_1:
+       case WM8962_HDBASS_AR_0:
+       case WM8962_HDBASS_B_1:
+       case WM8962_HDBASS_B_0:
+       case WM8962_HDBASS_K_1:
+       case WM8962_HDBASS_K_0:
+       case WM8962_HDBASS_N1_1:
+       case WM8962_HDBASS_N1_0:
+       case WM8962_HDBASS_N2_1:
+       case WM8962_HDBASS_N2_0:
+       case WM8962_HDBASS_N3_1:
+       case WM8962_HDBASS_N3_0:
+       case WM8962_HDBASS_N4_1:
+       case WM8962_HDBASS_N4_0:
+       case WM8962_HDBASS_N5_1:
+       case WM8962_HDBASS_N5_0:
+       case WM8962_HDBASS_X1_1:
+       case WM8962_HDBASS_X1_0:
+       case WM8962_HDBASS_X2_1:
+       case WM8962_HDBASS_X2_0:
+       case WM8962_HDBASS_X3_1:
+       case WM8962_HDBASS_X3_0:
+       case WM8962_HDBASS_ATK_1:
+       case WM8962_HDBASS_ATK_0:
+       case WM8962_HDBASS_DCY_1:
+       case WM8962_HDBASS_DCY_0:
+       case WM8962_HDBASS_PG_1:
+       case WM8962_HDBASS_PG_0:
+       case WM8962_HPF_C_1:
+       case WM8962_HPF_C_0:
+       case WM8962_ADCL_RETUNE_C1_1:
+       case WM8962_ADCL_RETUNE_C1_0:
+       case WM8962_ADCL_RETUNE_C2_1:
+       case WM8962_ADCL_RETUNE_C2_0:
+       case WM8962_ADCL_RETUNE_C3_1:
+       case WM8962_ADCL_RETUNE_C3_0:
+       case WM8962_ADCL_RETUNE_C4_1:
+       case WM8962_ADCL_RETUNE_C4_0:
+       case WM8962_ADCL_RETUNE_C5_1:
+       case WM8962_ADCL_RETUNE_C5_0:
+       case WM8962_ADCL_RETUNE_C6_1:
+       case WM8962_ADCL_RETUNE_C6_0:
+       case WM8962_ADCL_RETUNE_C7_1:
+       case WM8962_ADCL_RETUNE_C7_0:
+       case WM8962_ADCL_RETUNE_C8_1:
+       case WM8962_ADCL_RETUNE_C8_0:
+       case WM8962_ADCL_RETUNE_C9_1:
+       case WM8962_ADCL_RETUNE_C9_0:
+       case WM8962_ADCL_RETUNE_C10_1:
+       case WM8962_ADCL_RETUNE_C10_0:
+       case WM8962_ADCL_RETUNE_C11_1:
+       case WM8962_ADCL_RETUNE_C11_0:
+       case WM8962_ADCL_RETUNE_C12_1:
+       case WM8962_ADCL_RETUNE_C12_0:
+       case WM8962_ADCL_RETUNE_C13_1:
+       case WM8962_ADCL_RETUNE_C13_0:
+       case WM8962_ADCL_RETUNE_C14_1:
+       case WM8962_ADCL_RETUNE_C14_0:
+       case WM8962_ADCL_RETUNE_C15_1:
+       case WM8962_ADCL_RETUNE_C15_0:
+       case WM8962_ADCL_RETUNE_C16_1:
+       case WM8962_ADCL_RETUNE_C16_0:
+       case WM8962_ADCL_RETUNE_C17_1:
+       case WM8962_ADCL_RETUNE_C17_0:
+       case WM8962_ADCL_RETUNE_C18_1:
+       case WM8962_ADCL_RETUNE_C18_0:
+       case WM8962_ADCL_RETUNE_C19_1:
+       case WM8962_ADCL_RETUNE_C19_0:
+       case WM8962_ADCL_RETUNE_C20_1:
+       case WM8962_ADCL_RETUNE_C20_0:
+       case WM8962_ADCL_RETUNE_C21_1:
+       case WM8962_ADCL_RETUNE_C21_0:
+       case WM8962_ADCL_RETUNE_C22_1:
+       case WM8962_ADCL_RETUNE_C22_0:
+       case WM8962_ADCL_RETUNE_C23_1:
+       case WM8962_ADCL_RETUNE_C23_0:
+       case WM8962_ADCL_RETUNE_C24_1:
+       case WM8962_ADCL_RETUNE_C24_0:
+       case WM8962_ADCL_RETUNE_C25_1:
+       case WM8962_ADCL_RETUNE_C25_0:
+       case WM8962_ADCL_RETUNE_C26_1:
+       case WM8962_ADCL_RETUNE_C26_0:
+       case WM8962_ADCL_RETUNE_C27_1:
+       case WM8962_ADCL_RETUNE_C27_0:
+       case WM8962_ADCL_RETUNE_C28_1:
+       case WM8962_ADCL_RETUNE_C28_0:
+       case WM8962_ADCL_RETUNE_C29_1:
+       case WM8962_ADCL_RETUNE_C29_0:
+       case WM8962_ADCL_RETUNE_C30_1:
+       case WM8962_ADCL_RETUNE_C30_0:
+       case WM8962_ADCL_RETUNE_C31_1:
+       case WM8962_ADCL_RETUNE_C31_0:
+       case WM8962_ADCL_RETUNE_C32_1:
+       case WM8962_ADCL_RETUNE_C32_0:
+       case WM8962_RETUNEADC_PG2_1:
+       case WM8962_RETUNEADC_PG2_0:
+       case WM8962_RETUNEADC_PG_1:
+       case WM8962_RETUNEADC_PG_0:
+       case WM8962_ADCR_RETUNE_C1_1:
+       case WM8962_ADCR_RETUNE_C1_0:
+       case WM8962_ADCR_RETUNE_C2_1:
+       case WM8962_ADCR_RETUNE_C2_0:
+       case WM8962_ADCR_RETUNE_C3_1:
+       case WM8962_ADCR_RETUNE_C3_0:
+       case WM8962_ADCR_RETUNE_C4_1:
+       case WM8962_ADCR_RETUNE_C4_0:
+       case WM8962_ADCR_RETUNE_C5_1:
+       case WM8962_ADCR_RETUNE_C5_0:
+       case WM8962_ADCR_RETUNE_C6_1:
+       case WM8962_ADCR_RETUNE_C6_0:
+       case WM8962_ADCR_RETUNE_C7_1:
+       case WM8962_ADCR_RETUNE_C7_0:
+       case WM8962_ADCR_RETUNE_C8_1:
+       case WM8962_ADCR_RETUNE_C8_0:
+       case WM8962_ADCR_RETUNE_C9_1:
+       case WM8962_ADCR_RETUNE_C9_0:
+       case WM8962_ADCR_RETUNE_C10_1:
+       case WM8962_ADCR_RETUNE_C10_0:
+       case WM8962_ADCR_RETUNE_C11_1:
+       case WM8962_ADCR_RETUNE_C11_0:
+       case WM8962_ADCR_RETUNE_C12_1:
+       case WM8962_ADCR_RETUNE_C12_0:
+       case WM8962_ADCR_RETUNE_C13_1:
+       case WM8962_ADCR_RETUNE_C13_0:
+       case WM8962_ADCR_RETUNE_C14_1:
+       case WM8962_ADCR_RETUNE_C14_0:
+       case WM8962_ADCR_RETUNE_C15_1:
+       case WM8962_ADCR_RETUNE_C15_0:
+       case WM8962_ADCR_RETUNE_C16_1:
+       case WM8962_ADCR_RETUNE_C16_0:
+       case WM8962_ADCR_RETUNE_C17_1:
+       case WM8962_ADCR_RETUNE_C17_0:
+       case WM8962_ADCR_RETUNE_C18_1:
+       case WM8962_ADCR_RETUNE_C18_0:
+       case WM8962_ADCR_RETUNE_C19_1:
+       case WM8962_ADCR_RETUNE_C19_0:
+       case WM8962_ADCR_RETUNE_C20_1:
+       case WM8962_ADCR_RETUNE_C20_0:
+       case WM8962_ADCR_RETUNE_C21_1:
+       case WM8962_ADCR_RETUNE_C21_0:
+       case WM8962_ADCR_RETUNE_C22_1:
+       case WM8962_ADCR_RETUNE_C22_0:
+       case WM8962_ADCR_RETUNE_C23_1:
+       case WM8962_ADCR_RETUNE_C23_0:
+       case WM8962_ADCR_RETUNE_C24_1:
+       case WM8962_ADCR_RETUNE_C24_0:
+       case WM8962_ADCR_RETUNE_C25_1:
+       case WM8962_ADCR_RETUNE_C25_0:
+       case WM8962_ADCR_RETUNE_C26_1:
+       case WM8962_ADCR_RETUNE_C26_0:
+       case WM8962_ADCR_RETUNE_C27_1:
+       case WM8962_ADCR_RETUNE_C27_0:
+       case WM8962_ADCR_RETUNE_C28_1:
+       case WM8962_ADCR_RETUNE_C28_0:
+       case WM8962_ADCR_RETUNE_C29_1:
+       case WM8962_ADCR_RETUNE_C29_0:
+       case WM8962_ADCR_RETUNE_C30_1:
+       case WM8962_ADCR_RETUNE_C30_0:
+       case WM8962_ADCR_RETUNE_C31_1:
+       case WM8962_ADCR_RETUNE_C31_0:
+       case WM8962_ADCR_RETUNE_C32_1:
+       case WM8962_ADCR_RETUNE_C32_0:
+       case WM8962_DACL_RETUNE_C1_1:
+       case WM8962_DACL_RETUNE_C1_0:
+       case WM8962_DACL_RETUNE_C2_1:
+       case WM8962_DACL_RETUNE_C2_0:
+       case WM8962_DACL_RETUNE_C3_1:
+       case WM8962_DACL_RETUNE_C3_0:
+       case WM8962_DACL_RETUNE_C4_1:
+       case WM8962_DACL_RETUNE_C4_0:
+       case WM8962_DACL_RETUNE_C5_1:
+       case WM8962_DACL_RETUNE_C5_0:
+       case WM8962_DACL_RETUNE_C6_1:
+       case WM8962_DACL_RETUNE_C6_0:
+       case WM8962_DACL_RETUNE_C7_1:
+       case WM8962_DACL_RETUNE_C7_0:
+       case WM8962_DACL_RETUNE_C8_1:
+       case WM8962_DACL_RETUNE_C8_0:
+       case WM8962_DACL_RETUNE_C9_1:
+       case WM8962_DACL_RETUNE_C9_0:
+       case WM8962_DACL_RETUNE_C10_1:
+       case WM8962_DACL_RETUNE_C10_0:
+       case WM8962_DACL_RETUNE_C11_1:
+       case WM8962_DACL_RETUNE_C11_0:
+       case WM8962_DACL_RETUNE_C12_1:
+       case WM8962_DACL_RETUNE_C12_0:
+       case WM8962_DACL_RETUNE_C13_1:
+       case WM8962_DACL_RETUNE_C13_0:
+       case WM8962_DACL_RETUNE_C14_1:
+       case WM8962_DACL_RETUNE_C14_0:
+       case WM8962_DACL_RETUNE_C15_1:
+       case WM8962_DACL_RETUNE_C15_0:
+       case WM8962_DACL_RETUNE_C16_1:
+       case WM8962_DACL_RETUNE_C16_0:
+       case WM8962_DACL_RETUNE_C17_1:
+       case WM8962_DACL_RETUNE_C17_0:
+       case WM8962_DACL_RETUNE_C18_1:
+       case WM8962_DACL_RETUNE_C18_0:
+       case WM8962_DACL_RETUNE_C19_1:
+       case WM8962_DACL_RETUNE_C19_0:
+       case WM8962_DACL_RETUNE_C20_1:
+       case WM8962_DACL_RETUNE_C20_0:
+       case WM8962_DACL_RETUNE_C21_1:
+       case WM8962_DACL_RETUNE_C21_0:
+       case WM8962_DACL_RETUNE_C22_1:
+       case WM8962_DACL_RETUNE_C22_0:
+       case WM8962_DACL_RETUNE_C23_1:
+       case WM8962_DACL_RETUNE_C23_0:
+       case WM8962_DACL_RETUNE_C24_1:
+       case WM8962_DACL_RETUNE_C24_0:
+       case WM8962_DACL_RETUNE_C25_1:
+       case WM8962_DACL_RETUNE_C25_0:
+       case WM8962_DACL_RETUNE_C26_1:
+       case WM8962_DACL_RETUNE_C26_0:
+       case WM8962_DACL_RETUNE_C27_1:
+       case WM8962_DACL_RETUNE_C27_0:
+       case WM8962_DACL_RETUNE_C28_1:
+       case WM8962_DACL_RETUNE_C28_0:
+       case WM8962_DACL_RETUNE_C29_1:
+       case WM8962_DACL_RETUNE_C29_0:
+       case WM8962_DACL_RETUNE_C30_1:
+       case WM8962_DACL_RETUNE_C30_0:
+       case WM8962_DACL_RETUNE_C31_1:
+       case WM8962_DACL_RETUNE_C31_0:
+       case WM8962_DACL_RETUNE_C32_1:
+       case WM8962_DACL_RETUNE_C32_0:
+       case WM8962_RETUNEDAC_PG2_1:
+       case WM8962_RETUNEDAC_PG2_0:
+       case WM8962_RETUNEDAC_PG_1:
+       case WM8962_RETUNEDAC_PG_0:
+       case WM8962_DACR_RETUNE_C1_1:
+       case WM8962_DACR_RETUNE_C1_0:
+       case WM8962_DACR_RETUNE_C2_1:
+       case WM8962_DACR_RETUNE_C2_0:
+       case WM8962_DACR_RETUNE_C3_1:
+       case WM8962_DACR_RETUNE_C3_0:
+       case WM8962_DACR_RETUNE_C4_1:
+       case WM8962_DACR_RETUNE_C4_0:
+       case WM8962_DACR_RETUNE_C5_1:
+       case WM8962_DACR_RETUNE_C5_0:
+       case WM8962_DACR_RETUNE_C6_1:
+       case WM8962_DACR_RETUNE_C6_0:
+       case WM8962_DACR_RETUNE_C7_1:
+       case WM8962_DACR_RETUNE_C7_0:
+       case WM8962_DACR_RETUNE_C8_1:
+       case WM8962_DACR_RETUNE_C8_0:
+       case WM8962_DACR_RETUNE_C9_1:
+       case WM8962_DACR_RETUNE_C9_0:
+       case WM8962_DACR_RETUNE_C10_1:
+       case WM8962_DACR_RETUNE_C10_0:
+       case WM8962_DACR_RETUNE_C11_1:
+       case WM8962_DACR_RETUNE_C11_0:
+       case WM8962_DACR_RETUNE_C12_1:
+       case WM8962_DACR_RETUNE_C12_0:
+       case WM8962_DACR_RETUNE_C13_1:
+       case WM8962_DACR_RETUNE_C13_0:
+       case WM8962_DACR_RETUNE_C14_1:
+       case WM8962_DACR_RETUNE_C14_0:
+       case WM8962_DACR_RETUNE_C15_1:
+       case WM8962_DACR_RETUNE_C15_0:
+       case WM8962_DACR_RETUNE_C16_1:
+       case WM8962_DACR_RETUNE_C16_0:
+       case WM8962_DACR_RETUNE_C17_1:
+       case WM8962_DACR_RETUNE_C17_0:
+       case WM8962_DACR_RETUNE_C18_1:
+       case WM8962_DACR_RETUNE_C18_0:
+       case WM8962_DACR_RETUNE_C19_1:
+       case WM8962_DACR_RETUNE_C19_0:
+       case WM8962_DACR_RETUNE_C20_1:
+       case WM8962_DACR_RETUNE_C20_0:
+       case WM8962_DACR_RETUNE_C21_1:
+       case WM8962_DACR_RETUNE_C21_0:
+       case WM8962_DACR_RETUNE_C22_1:
+       case WM8962_DACR_RETUNE_C22_0:
+       case WM8962_DACR_RETUNE_C23_1:
+       case WM8962_DACR_RETUNE_C23_0:
+       case WM8962_DACR_RETUNE_C24_1:
+       case WM8962_DACR_RETUNE_C24_0:
+       case WM8962_DACR_RETUNE_C25_1:
+       case WM8962_DACR_RETUNE_C25_0:
+       case WM8962_DACR_RETUNE_C26_1:
+       case WM8962_DACR_RETUNE_C26_0:
+       case WM8962_DACR_RETUNE_C27_1:
+       case WM8962_DACR_RETUNE_C27_0:
+       case WM8962_DACR_RETUNE_C28_1:
+       case WM8962_DACR_RETUNE_C28_0:
+       case WM8962_DACR_RETUNE_C29_1:
+       case WM8962_DACR_RETUNE_C29_0:
+       case WM8962_DACR_RETUNE_C30_1:
+       case WM8962_DACR_RETUNE_C30_0:
+       case WM8962_DACR_RETUNE_C31_1:
+       case WM8962_DACR_RETUNE_C31_0:
+       case WM8962_DACR_RETUNE_C32_1:
+       case WM8962_DACR_RETUNE_C32_0:
+       case WM8962_VSS_XHD2_1:
+       case WM8962_VSS_XHD2_0:
+       case WM8962_VSS_XHD3_1:
+       case WM8962_VSS_XHD3_0:
+       case WM8962_VSS_XHN1_1:
+       case WM8962_VSS_XHN1_0:
+       case WM8962_VSS_XHN2_1:
+       case WM8962_VSS_XHN2_0:
+       case WM8962_VSS_XHN3_1:
+       case WM8962_VSS_XHN3_0:
+       case WM8962_VSS_XLA_1:
+       case WM8962_VSS_XLA_0:
+       case WM8962_VSS_XLB_1:
+       case WM8962_VSS_XLB_0:
+       case WM8962_VSS_XLG_1:
+       case WM8962_VSS_XLG_0:
+       case WM8962_VSS_PG2_1:
+       case WM8962_VSS_PG2_0:
+       case WM8962_VSS_PG_1:
+       case WM8962_VSS_PG_0:
+       case WM8962_VSS_XTD1_1:
+       case WM8962_VSS_XTD1_0:
+       case WM8962_VSS_XTD2_1:
+       case WM8962_VSS_XTD2_0:
+       case WM8962_VSS_XTD3_1:
+       case WM8962_VSS_XTD3_0:
+       case WM8962_VSS_XTD4_1:
+       case WM8962_VSS_XTD4_0:
+       case WM8962_VSS_XTD5_1:
+       case WM8962_VSS_XTD5_0:
+       case WM8962_VSS_XTD6_1:
+       case WM8962_VSS_XTD6_0:
+       case WM8962_VSS_XTD7_1:
+       case WM8962_VSS_XTD7_0:
+       case WM8962_VSS_XTD8_1:
+       case WM8962_VSS_XTD8_0:
+       case WM8962_VSS_XTD9_1:
+       case WM8962_VSS_XTD9_0:
+       case WM8962_VSS_XTD10_1:
+       case WM8962_VSS_XTD10_0:
+       case WM8962_VSS_XTD11_1:
+       case WM8962_VSS_XTD11_0:
+       case WM8962_VSS_XTD12_1:
+       case WM8962_VSS_XTD12_0:
+       case WM8962_VSS_XTD13_1:
+       case WM8962_VSS_XTD13_0:
+       case WM8962_VSS_XTD14_1:
+       case WM8962_VSS_XTD14_0:
+       case WM8962_VSS_XTD15_1:
+       case WM8962_VSS_XTD15_0:
+       case WM8962_VSS_XTD16_1:
+       case WM8962_VSS_XTD16_0:
+       case WM8962_VSS_XTD17_1:
+       case WM8962_VSS_XTD17_0:
+       case WM8962_VSS_XTD18_1:
+       case WM8962_VSS_XTD18_0:
+       case WM8962_VSS_XTD19_1:
+       case WM8962_VSS_XTD19_0:
+       case WM8962_VSS_XTD20_1:
+       case WM8962_VSS_XTD20_0:
+       case WM8962_VSS_XTD21_1:
+       case WM8962_VSS_XTD21_0:
+       case WM8962_VSS_XTD22_1:
+       case WM8962_VSS_XTD22_0:
+       case WM8962_VSS_XTD23_1:
+       case WM8962_VSS_XTD23_0:
+       case WM8962_VSS_XTD24_1:
+       case WM8962_VSS_XTD24_0:
+       case WM8962_VSS_XTD25_1:
+       case WM8962_VSS_XTD25_0:
+       case WM8962_VSS_XTD26_1:
+       case WM8962_VSS_XTD26_0:
+       case WM8962_VSS_XTD27_1:
+       case WM8962_VSS_XTD27_0:
+       case WM8962_VSS_XTD28_1:
+       case WM8962_VSS_XTD28_0:
+       case WM8962_VSS_XTD29_1:
+       case WM8962_VSS_XTD29_0:
+       case WM8962_VSS_XTD30_1:
+       case WM8962_VSS_XTD30_0:
+       case WM8962_VSS_XTD31_1:
+       case WM8962_VSS_XTD31_0:
+       case WM8962_VSS_XTD32_1:
+       case WM8962_VSS_XTD32_0:
+       case WM8962_VSS_XTS1_1:
+       case WM8962_VSS_XTS1_0:
+       case WM8962_VSS_XTS2_1:
+       case WM8962_VSS_XTS2_0:
+       case WM8962_VSS_XTS3_1:
+       case WM8962_VSS_XTS3_0:
+       case WM8962_VSS_XTS4_1:
+       case WM8962_VSS_XTS4_0:
+       case WM8962_VSS_XTS5_1:
+       case WM8962_VSS_XTS5_0:
+       case WM8962_VSS_XTS6_1:
+       case WM8962_VSS_XTS6_0:
+       case WM8962_VSS_XTS7_1:
+       case WM8962_VSS_XTS7_0:
+       case WM8962_VSS_XTS8_1:
+       case WM8962_VSS_XTS8_0:
+       case WM8962_VSS_XTS9_1:
+       case WM8962_VSS_XTS9_0:
+       case WM8962_VSS_XTS10_1:
+       case WM8962_VSS_XTS10_0:
+       case WM8962_VSS_XTS11_1:
+       case WM8962_VSS_XTS11_0:
+       case WM8962_VSS_XTS12_1:
+       case WM8962_VSS_XTS12_0:
+       case WM8962_VSS_XTS13_1:
+       case WM8962_VSS_XTS13_0:
+       case WM8962_VSS_XTS14_1:
+       case WM8962_VSS_XTS14_0:
+       case WM8962_VSS_XTS15_1:
+       case WM8962_VSS_XTS15_0:
+       case WM8962_VSS_XTS16_1:
+       case WM8962_VSS_XTS16_0:
+       case WM8962_VSS_XTS17_1:
+       case WM8962_VSS_XTS17_0:
+       case WM8962_VSS_XTS18_1:
+       case WM8962_VSS_XTS18_0:
+       case WM8962_VSS_XTS19_1:
+       case WM8962_VSS_XTS19_0:
+       case WM8962_VSS_XTS20_1:
+       case WM8962_VSS_XTS20_0:
+       case WM8962_VSS_XTS21_1:
+       case WM8962_VSS_XTS21_0:
+       case WM8962_VSS_XTS22_1:
+       case WM8962_VSS_XTS22_0:
+       case WM8962_VSS_XTS23_1:
+       case WM8962_VSS_XTS23_0:
+       case WM8962_VSS_XTS24_1:
+       case WM8962_VSS_XTS24_0:
+       case WM8962_VSS_XTS25_1:
+       case WM8962_VSS_XTS25_0:
+       case WM8962_VSS_XTS26_1:
+       case WM8962_VSS_XTS26_0:
+       case WM8962_VSS_XTS27_1:
+       case WM8962_VSS_XTS27_0:
+       case WM8962_VSS_XTS28_1:
+       case WM8962_VSS_XTS28_0:
+       case WM8962_VSS_XTS29_1:
+       case WM8962_VSS_XTS29_0:
+       case WM8962_VSS_XTS30_1:
+       case WM8962_VSS_XTS30_0:
+       case WM8962_VSS_XTS31_1:
+       case WM8962_VSS_XTS31_0:
+       case WM8962_VSS_XTS32_1:
+       case WM8962_VSS_XTS32_0:
+               return true;
+       default:
+               return false;
+       }
 }
 
 static int wm8962_reset(struct wm8962_priv *wm8962)
@@ -2221,6 +1715,8 @@ SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1,
 SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8962_LEFT_DAC_VOLUME,
                 WM8962_RIGHT_DAC_VOLUME, 1, 127, 0, digital_tlv),
 SOC_SINGLE("DAC High Performance Switch", WM8962_ADC_DAC_CONTROL_2, 0, 1, 0),
+SOC_SINGLE("DAC L/R Swap Switch", WM8962_AUDIO_INTERFACE_0, 5, 1, 0),
+SOC_SINGLE("ADC L/R Swap Switch", WM8962_AUDIO_INTERFACE_0, 8, 1, 0),
 
 SOC_SINGLE("ADC High Performance Switch", WM8962_ADDITIONAL_CONTROL_1,
           5, 1, 0),
@@ -2337,65 +1833,6 @@ SOC_SINGLE_TLV("SPKOUTR Mixer DACR Volume", WM8962_SPEAKER_MIXER_5,
               4, 1, 0, inmix_tlv),
 };
 
-static int sysclk_event(struct snd_soc_dapm_widget *w,
-                       struct snd_kcontrol *kcontrol, int event)
-{
-       struct snd_soc_codec *codec = w->codec;
-       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
-       unsigned long timeout;
-       int src;
-       int fll;
-
-       /* Ignore attempts to run the event during startup */
-       if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
-               return 0;
-
-       src = snd_soc_read(codec, WM8962_CLOCKING2) & WM8962_SYSCLK_SRC_MASK;
-
-       switch (src) {
-       case 0:      /* MCLK */
-               fll = 0;
-               break;
-       case 0x200:  /* FLL */
-               fll = 1;
-               break;
-       default:
-               dev_err(codec->dev, "Unknown SYSCLK source %x\n", src);
-               return -EINVAL;
-       }
-
-       switch (event) {
-       case SND_SOC_DAPM_PRE_PMU:
-               if (fll) {
-                       try_wait_for_completion(&wm8962->fll_lock);
-
-                       snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
-                                           WM8962_FLL_ENA, WM8962_FLL_ENA);
-
-                       timeout = msecs_to_jiffies(5);
-                       timeout = wait_for_completion_timeout(&wm8962->fll_lock,
-                                                             timeout);
-
-                       if (wm8962->irq && timeout == 0)
-                               dev_err(codec->dev,
-                                       "Timed out starting FLL\n");
-               }
-               break;
-
-       case SND_SOC_DAPM_POST_PMD:
-               if (fll)
-                       snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
-                                           WM8962_FLL_ENA, 0);
-               break;
-
-       default:
-               BUG();
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 static int cp_event(struct snd_soc_dapm_widget *w,
                    struct snd_kcontrol *kcontrol, int event)
 {
@@ -2681,8 +2118,7 @@ SND_SOC_DAPM_INPUT("DMICDAT"),
 SND_SOC_DAPM_SUPPLY("MICBIAS", WM8962_PWR_MGMT_1, 1, 0, NULL, 0),
 
 SND_SOC_DAPM_SUPPLY("Class G", WM8962_CHARGE_PUMP_B, 0, 1, NULL, 0),
-SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event,
-                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event,
                    SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0),
@@ -2910,13 +2346,13 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec)
        struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
        struct snd_soc_dapm_context *dapm = &codec->dapm;
 
-       snd_soc_add_controls(codec, wm8962_snd_controls,
+       snd_soc_add_codec_controls(codec, wm8962_snd_controls,
                             ARRAY_SIZE(wm8962_snd_controls));
        if (pdata && pdata->spk_mono)
-               snd_soc_add_controls(codec, wm8962_spk_mono_controls,
+               snd_soc_add_codec_controls(codec, wm8962_spk_mono_controls,
                                     ARRAY_SIZE(wm8962_spk_mono_controls));
        else
-               snd_soc_add_controls(codec, wm8962_spk_stereo_controls,
+               snd_soc_add_codec_controls(codec, wm8962_spk_stereo_controls,
                                     ARRAY_SIZE(wm8962_spk_stereo_controls));
 
 
@@ -2950,7 +2386,7 @@ static const int bclk_divs[] = {
 };
 
 static const int sysclk_rates[] = {
-       64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536,
+       64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536, 3072, 6144
 };
 
 static void wm8962_configure_bclk(struct snd_soc_codec *codec)
@@ -2984,6 +2420,8 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
                return;
        }
 
+       dev_dbg(codec->dev, "Selected sysclk ratio %d\n", sysclk_rates[i]);
+
        snd_soc_update_bits(codec, WM8962_CLOCKING_4,
                            WM8962_SYSCLK_RATE_MASK, clocking4);
 
@@ -3042,9 +2480,6 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
 static int wm8962_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
-       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
-       int ret;
-
        if (level == codec->dapm.bias_level)
                return 0;
 
@@ -3061,51 +2496,15 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec,
                break;
 
        case SND_SOC_BIAS_STANDBY:
-               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-                       ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
-                                                   wm8962->supplies);
-                       if (ret != 0) {
-                               dev_err(codec->dev,
-                                       "Failed to enable supplies: %d\n",
-                                       ret);
-                               return ret;
-                       }
-
-                       regcache_cache_only(wm8962->regmap, false);
-                       regcache_sync(wm8962->regmap);
-
-                       snd_soc_update_bits(codec, WM8962_ANTI_POP,
-                                           WM8962_STARTUP_BIAS_ENA |
-                                           WM8962_VMID_BUF_ENA,
-                                           WM8962_STARTUP_BIAS_ENA |
-                                           WM8962_VMID_BUF_ENA);
-
-                       /* Bias enable at 2*50k for ramp */
-                       snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
-                                           WM8962_VMID_SEL_MASK |
-                                           WM8962_BIAS_ENA,
-                                           WM8962_BIAS_ENA | 0x180);
-
-                       msleep(5);
-               }
-
                /* VMID 2*250k */
                snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
                                    WM8962_VMID_SEL_MASK, 0x100);
                break;
 
        case SND_SOC_BIAS_OFF:
-               snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
-                                   WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, 0);
-
-               snd_soc_update_bits(codec, WM8962_ANTI_POP,
-                                   WM8962_STARTUP_BIAS_ENA |
-                                   WM8962_VMID_BUF_ENA, 0);
-
-               regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies),
-                                      wm8962->supplies);
                break;
        }
+
        codec->dapm.bias_level = level;
        return 0;
 }
@@ -3139,6 +2538,9 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
        int adctl3 = 0;
 
        wm8962->bclk = snd_soc_params_to_bclk(params);
+       if (params_channels(params) == 1)
+               wm8962->bclk *= 2;
+
        wm8962->lrclk = params_rate(params);
 
        for (i = 0; i < ARRAY_SIZE(sr_vals); i++) {
@@ -3177,7 +2579,8 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
                            WM8962_SAMPLE_RATE_INT_MODE |
                            WM8962_SAMPLE_RATE_MASK, adctl3);
 
-       wm8962_configure_bclk(codec);
+       if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
+               wm8962_configure_bclk(codec);
 
        return 0;
 }
@@ -3207,6 +2610,8 @@ static int wm8962_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
 
        wm8962->sysclk_rate = freq;
 
+       wm8962_configure_bclk(codec);
+
        return 0;
 }
 
@@ -3385,8 +2790,7 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
        struct _fll_div fll_div;
        unsigned long timeout;
        int ret;
-       int fll1 = snd_soc_read(codec, WM8962_FLL_CONTROL_1) & WM8962_FLL_ENA;
-       int sysclk = snd_soc_read(codec, WM8962_CLOCKING2) & WM8962_SYSCLK_ENA;
+       int fll1 = 0;
 
        /* Any change? */
        if (source == wm8962->fll_src && Fref == wm8962->fll_fref &&
@@ -3402,6 +2806,8 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
                snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
                                    WM8962_FLL_ENA, 0);
 
+               pm_runtime_put(codec->dev);
+
                return 0;
        }
 
@@ -3409,6 +2815,9 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
        if (ret != 0)
                return ret;
 
+       /* Parameters good, disable so we can reprogram */
+       snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_ENA, 0);
+
        switch (fll_id) {
        case WM8962_FLL_MCLK:
        case WM8962_FLL_BCLK:
@@ -3447,12 +2856,11 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 
        try_wait_for_completion(&wm8962->fll_lock);
 
-       if (sysclk)
-               fll1 |= WM8962_FLL_ENA;
+       pm_runtime_get_sync(codec->dev);
 
        snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
                            WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK |
-                           WM8962_FLL_ENA, fll1);
+                           WM8962_FLL_ENA, fll1 | WM8962_FLL_ENA);
 
        dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
 
@@ -3513,14 +2921,14 @@ static struct snd_soc_dai_driver wm8962_dai = {
        .name = "wm8962",
        .playback = {
                .stream_name = "Playback",
-               .channels_min = 2,
+               .channels_min = 1,
                .channels_max = 2,
                .rates = WM8962_RATES,
                .formats = WM8962_FORMATS,
        },
        .capture = {
                .stream_name = "Capture",
-               .channels_min = 2,
+               .channels_min = 1,
                .channels_max = 2,
                .rates = WM8962_RATES,
                .formats = WM8962_FORMATS,
@@ -4127,20 +3535,19 @@ static int wm8962_remove(struct snd_soc_codec *codec)
        return 0;
 }
 
-static int wm8962_soc_volatile(struct snd_soc_codec *codec,
-                              unsigned int reg)
-{
-       return true;
-}
-
-
 static struct snd_soc_codec_driver soc_codec_dev_wm8962 = {
        .probe =        wm8962_probe,
        .remove =       wm8962_remove,
        .set_bias_level = wm8962_set_bias_level,
        .set_pll = wm8962_set_fll,
-       .reg_cache_size = WM8962_MAX_REGISTER,
-       .volatile_register = wm8962_soc_volatile,
+       .idle_bias_off = true,
+};
+
+/* Improve power consumption for IN4 DC measurement mode */
+static const struct reg_default wm8962_dc_measure[] = {
+       { 0xfd, 0x1 },
+       { 0xcc, 0x40 },
+       { 0xfd, 0 },
 };
 
 static const struct regmap_config wm8962_regmap = {
@@ -4155,10 +3562,10 @@ static const struct regmap_config wm8962_regmap = {
        .cache_type = REGCACHE_RBTREE,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
+       struct wm8962_pdata *pdata = dev_get_platdata(&i2c->dev);
        struct wm8962_priv *wm8962;
        unsigned int reg;
        int ret, i;
@@ -4212,7 +3619,7 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
        }
        if (reg != 0x6243) {
                dev_err(&i2c->dev,
-                       "Device is not a WM8962, ID %x != 0x6243\n", ret);
+                       "Device is not a WM8962, ID %x != 0x6243\n", reg);
                ret = -EINVAL;
                goto err_regmap;
        }
@@ -4237,7 +3644,19 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
                goto err_regmap;
        }
 
-       regcache_cache_only(wm8962->regmap, true);
+       if (pdata && pdata->in4_dc_measure) {
+               ret = regmap_register_patch(wm8962->regmap,
+                                           wm8962_dc_measure,
+                                           ARRAY_SIZE(wm8962_dc_measure));
+               if (ret != 0)
+                       dev_err(&i2c->dev,
+                               "Failed to configure for DC mesurement: %d\n",
+                               ret);
+       }
+
+       pm_runtime_set_active(&i2c->dev);
+       pm_runtime_enable(&i2c->dev);
+       pm_request_idle(&i2c->dev);
 
        ret = snd_soc_register_codec(&i2c->dev,
                                     &soc_codec_dev_wm8962, &wm8962_dai, 1);
@@ -4269,6 +3688,69 @@ static __devexit int wm8962_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM_RUNTIME
+static int wm8962_runtime_resume(struct device *dev)
+{
+       struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+       int ret;
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
+                                   wm8962->supplies);
+       if (ret != 0) {
+               dev_err(dev,
+                       "Failed to enable supplies: %d\n", ret);
+               return ret;
+       }
+
+       regcache_cache_only(wm8962->regmap, false);
+       regcache_sync(wm8962->regmap);
+
+       regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP,
+                          WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA,
+                          WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA);
+
+       /* Bias enable at 2*50k for ramp */
+       regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
+                          WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA,
+                          WM8962_BIAS_ENA | 0x180);
+
+       msleep(5);
+
+       /* VMID back to 2x250k for standby */
+       regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
+                          WM8962_VMID_SEL_MASK, 0x100);
+
+       dev_crit(dev, "RESUME\n");
+
+       return 0;
+}
+
+static int wm8962_runtime_suspend(struct device *dev)
+{
+       struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+
+       dev_crit(dev, "SUSPEND\n");
+
+       regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
+                          WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, 0);
+
+       regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP,
+                          WM8962_STARTUP_BIAS_ENA |
+                          WM8962_VMID_BUF_ENA, 0);
+
+       regcache_cache_only(wm8962->regmap, true);
+
+       regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies),
+                              wm8962->supplies);
+
+       return 0;
+}
+#endif
+
+static struct dev_pm_ops wm8962_pm = {
+       SET_RUNTIME_PM_OPS(wm8962_runtime_suspend, wm8962_runtime_resume, NULL)
+};
+
 static const struct i2c_device_id wm8962_i2c_id[] = {
        { "wm8962", 0 },
        { }
@@ -4279,34 +3761,14 @@ static struct i2c_driver wm8962_i2c_driver = {
        .driver = {
                .name = "wm8962",
                .owner = THIS_MODULE,
+               .pm = &wm8962_pm,
        },
        .probe =    wm8962_i2c_probe,
        .remove =   __devexit_p(wm8962_i2c_remove),
        .id_table = wm8962_i2c_id,
 };
-#endif
 
-static int __init wm8962_modinit(void)
-{
-       int ret;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       ret = i2c_add_driver(&wm8962_i2c_driver);
-       if (ret != 0) {
-               printk(KERN_ERR "Failed to register WM8962 I2C driver: %d\n",
-                      ret);
-       }
-#endif
-       return 0;
-}
-module_init(wm8962_modinit);
-
-static void __exit wm8962_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       i2c_del_driver(&wm8962_i2c_driver);
-#endif
-}
-module_exit(wm8962_exit);
+module_i2c_driver(wm8962_i2c_driver);
 
 MODULE_DESCRIPTION("ASoC WM8962 driver");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
index 4af893601f00e2da9c33101de59ed42ff949904b..28fe59e3ce011c4d96eac242276214b91d3d9c86 100644 (file)
@@ -252,7 +252,7 @@ static const struct snd_soc_dapm_widget wm8971_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("MIC"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8971_dapm_routes[] = {
        /* left mixer */
        {"Left Mixer", "Playback Switch", "Left DAC"},
        {"Left Mixer", "Left Bypass Switch", "Left Line Mux"},
@@ -329,17 +329,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Right ADC", NULL, "Right ADC Mux"},
 };
 
-static int wm8971_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_new_controls(dapm, wm8971_dapm_widgets,
-                                 ARRAY_SIZE(wm8971_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-       return 0;
-}
-
 struct _coeff_div {
        u32 mclk;
        u32 rate;
@@ -659,10 +648,6 @@ static int wm8971_probe(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, WM8971_LINVOL, 0x0100, 0x0100);
        snd_soc_update_bits(codec, WM8971_RINVOL, 0x0100, 0x0100);
 
-       snd_soc_add_controls(codec, wm8971_snd_controls,
-                               ARRAY_SIZE(wm8971_snd_controls));
-       wm8971_add_widgets(codec);
-
        return ret;
 }
 
@@ -686,16 +671,23 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
        .reg_cache_size = ARRAY_SIZE(wm8971_reg),
        .reg_word_size = sizeof(u16),
        .reg_cache_default = wm8971_reg,
+
+       .controls = wm8971_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8971_snd_controls),
+       .dapm_widgets = wm8971_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8971_dapm_widgets),
+       .dapm_routes = wm8971_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8971_dapm_routes),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm8971_priv *wm8971;
        int ret;
 
-       wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL);
+       wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv),
+                             GFP_KERNEL);
        if (wm8971 == NULL)
                return -ENOMEM;
 
@@ -704,15 +696,13 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8971, &wm8971_dai, 1);
-       if (ret < 0)
-               kfree(wm8971);
+
        return ret;
 }
 
 static __devexit int wm8971_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -731,27 +721,22 @@ static struct i2c_driver wm8971_i2c_driver = {
        .remove =   __devexit_p(wm8971_i2c_remove),
        .id_table = wm8971_i2c_id,
 };
-#endif
 
 static int __init wm8971_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8971_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n",
                       ret);
        }
-#endif
        return ret;
 }
 module_init(wm8971_modinit);
 
 static void __exit wm8971_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8971_i2c_driver);
-#endif
 }
 module_exit(wm8971_exit);
 
index 4a6a7b5a61ba442583cce6d1d6e6338836130f70..d93c03f820c9e802f87d2cfcd0fb7357d7b9fa15 100644 (file)
@@ -48,10 +48,6 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = {
 #define WM8974_POWER1_BIASEN  0x08
 #define WM8974_POWER1_BUFIOEN 0x04
 
-struct wm8974_priv {
-       enum snd_soc_control_type control_type;
-};
-
 #define wm8974_reset(c)        snd_soc_write(c, WM8974_RESET, 0)
 
 static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" };
@@ -235,7 +231,7 @@ SND_SOC_DAPM_OUTPUT("SPKOUTP"),
 SND_SOC_DAPM_OUTPUT("SPKOUTN"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8974_dapm_routes[] = {
        /* Mono output mixer */
        {"Mono Mixer", "PCM Playback Switch", "DAC"},
        {"Mono Mixer", "Aux Playback Switch", "Aux Input"},
@@ -269,17 +265,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Aux Input", NULL, "AUX"},
 };
 
-static int wm8974_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_new_controls(dapm, wm8974_dapm_widgets,
-                                 ARRAY_SIZE(wm8974_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-       return 0;
-}
-
 struct pll_ {
        unsigned int pre_div:1;
        unsigned int n:4;
@@ -611,9 +596,6 @@ static int wm8974_probe(struct snd_soc_codec *codec)
        }
 
        wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-       snd_soc_add_controls(codec, wm8974_snd_controls,
-                            ARRAY_SIZE(wm8974_snd_controls));
-       wm8974_add_widgets(codec);
 
        return ret;
 }
@@ -634,32 +616,30 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {
        .reg_cache_size = ARRAY_SIZE(wm8974_reg),
        .reg_word_size = sizeof(u16),
        .reg_cache_default = wm8974_reg,
+
+       .controls = wm8974_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8974_snd_controls),
+       .dapm_widgets = wm8974_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8974_dapm_widgets),
+       .dapm_routes = wm8974_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8974_dapm_routes),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8974_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
-       struct wm8974_priv *wm8974;
        int ret;
 
-       wm8974 = kzalloc(sizeof(struct wm8974_priv), GFP_KERNEL);
-       if (wm8974 == NULL)
-               return -ENOMEM;
-
-       i2c_set_clientdata(i2c, wm8974);
-
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8974, &wm8974_dai, 1);
-       if (ret < 0)
-               kfree(wm8974);
+
        return ret;
 }
 
 static __devexit int wm8974_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+
        return 0;
 }
 
@@ -678,27 +658,22 @@ static struct i2c_driver wm8974_i2c_driver = {
        .remove =   __devexit_p(wm8974_i2c_remove),
        .id_table = wm8974_i2c_id,
 };
-#endif
 
 static int __init wm8974_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8974_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register wm8974 I2C driver: %d\n",
                       ret);
        }
-#endif
        return ret;
 }
 module_init(wm8974_modinit);
 
 static void __exit wm8974_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8974_i2c_driver);
-#endif
 }
 module_exit(wm8974_exit);
 
index 85d514d63a4c8862e9be6f7c4a751f1aa749a6ab..72d5fdcd3cc2b8b1eb6453f847eea219cb920b35 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 
 #include "wm8978.h"
 
-/* wm8978 register cache. Note that register 0 is not included in the cache. */
-static const u16 wm8978_reg[WM8978_CACHEREGNUM] = {
-       0x0000, 0x0000, 0x0000, 0x0000, /* 0x00...0x03 */
-       0x0050, 0x0000, 0x0140, 0x0000, /* 0x04...0x07 */
-       0x0000, 0x0000, 0x0000, 0x00ff, /* 0x08...0x0b */
-       0x00ff, 0x0000, 0x0100, 0x00ff, /* 0x0c...0x0f */
-       0x00ff, 0x0000, 0x012c, 0x002c, /* 0x10...0x13 */
-       0x002c, 0x002c, 0x002c, 0x0000, /* 0x14...0x17 */
-       0x0032, 0x0000, 0x0000, 0x0000, /* 0x18...0x1b */
-       0x0000, 0x0000, 0x0000, 0x0000, /* 0x1c...0x1f */
-       0x0038, 0x000b, 0x0032, 0x0000, /* 0x20...0x23 */
-       0x0008, 0x000c, 0x0093, 0x00e9, /* 0x24...0x27 */
-       0x0000, 0x0000, 0x0000, 0x0000, /* 0x28...0x2b */
-       0x0033, 0x0010, 0x0010, 0x0100, /* 0x2c...0x2f */
-       0x0100, 0x0002, 0x0001, 0x0001, /* 0x30...0x33 */
-       0x0039, 0x0039, 0x0039, 0x0039, /* 0x34...0x37 */
-       0x0001, 0x0001,                 /* 0x38...0x3b */
+static const struct reg_default wm8978_reg_defaults[] = {
+       { 1, 0x0000 },
+       { 2, 0x0000 },
+       { 3, 0x0000 },
+       { 4, 0x0050 },
+       { 5, 0x0000 },
+       { 6, 0x0140 },
+       { 7, 0x0000 },
+       { 8, 0x0000 },
+       { 9, 0x0000 },
+       { 10, 0x0000 },
+       { 11, 0x00ff },
+       { 12, 0x00ff },
+       { 13, 0x0000 },
+       { 14, 0x0100 },
+       { 15, 0x00ff },
+       { 16, 0x00ff },
+       { 17, 0x0000 },
+       { 18, 0x012c },
+       { 19, 0x002c },
+       { 20, 0x002c },
+       { 21, 0x002c },
+       { 22, 0x002c },
+       { 23, 0x0000 },
+       { 24, 0x0032 },
+       { 25, 0x0000 },
+       { 26, 0x0000 },
+       { 27, 0x0000 },
+       { 28, 0x0000 },
+       { 29, 0x0000 },
+       { 30, 0x0000 },
+       { 31, 0x0000 },
+       { 32, 0x0038 },
+       { 33, 0x000b },
+       { 34, 0x0032 },
+       { 35, 0x0000 },
+       { 36, 0x0008 },
+       { 37, 0x000c },
+       { 38, 0x0093 },
+       { 39, 0x00e9 },
+       { 40, 0x0000 },
+       { 41, 0x0000 },
+       { 42, 0x0000 },
+       { 43, 0x0000 },
+       { 44, 0x0033 },
+       { 45, 0x0010 },
+       { 46, 0x0010 },
+       { 47, 0x0100 },
+       { 48, 0x0100 },
+       { 49, 0x0002 },
+       { 50, 0x0001 },
+       { 51, 0x0001 },
+       { 52, 0x0039 },
+       { 53, 0x0039 },
+       { 54, 0x0039 },
+       { 55, 0x0039 },
+       { 56, 0x0001 },
+       { 57, 0x0001 },
 };
 
+static bool wm8978_volatile(struct device *dev, unsigned int reg)
+{
+       return reg == WM8978_RESET;
+}
+
 /* codec private data */
 struct wm8978_priv {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
        unsigned int f_pllout;
        unsigned int f_mclk;
        unsigned int f_256fs;
@@ -303,7 +350,7 @@ static const struct snd_soc_dapm_widget wm8978_dapm_widgets[] = {
        SND_SOC_DAPM_OUTPUT("RSPK"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8978_dapm_routes[] = {
        /* Output mixer */
        {"Right Output Mixer", "PCM Playback Switch", "Right DAC"},
        {"Right Output Mixer", "Aux Playback Switch", "RAUX"},
@@ -352,18 +399,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Left Input Mixer", "MicP Switch", "LMICP"},
 };
 
-static int wm8978_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_new_controls(dapm, wm8978_dapm_widgets,
-                                 ARRAY_SIZE(wm8978_dapm_widgets));
-       /* set up the WM8978 audio map */
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-       return 0;
-}
-
 /* PLL divisors */
 struct wm8978_pll_div {
        u32 k;
@@ -894,26 +929,23 @@ static struct snd_soc_dai_driver wm8978_dai = {
 
 static int wm8978_suspend(struct snd_soc_codec *codec)
 {
+       struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
+
        wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF);
        /* Also switch PLL off */
        snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0);
 
+       regcache_mark_dirty(wm8978->regmap);
+
        return 0;
 }
 
 static int wm8978_resume(struct snd_soc_codec *codec)
 {
        struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
-       int i;
-       u16 *cache = codec->reg_cache;
 
        /* Sync reg_cache with the hardware */
-       for (i = 0; i < ARRAY_SIZE(wm8978_reg); i++) {
-               if (i == WM8978_RESET)
-                       continue;
-               if (cache[i] != wm8978_reg[i])
-                       snd_soc_write(codec, i, cache[i]);
-       }
+       regcache_sync(wm8978->regmap);
 
        wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
@@ -953,7 +985,8 @@ static int wm8978_probe(struct snd_soc_codec *codec)
         * default hardware setting
         */
        wm8978->sysclk = WM8978_PLL;
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
+       codec->control_data = wm8978->regmap;
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
@@ -967,19 +1000,8 @@ static int wm8978_probe(struct snd_soc_codec *codec)
        for (i = 0; i < ARRAY_SIZE(update_reg); i++)
                snd_soc_update_bits(codec, update_reg[i], 0x100, 0x100);
 
-       /* Reset the codec */
-       ret = snd_soc_write(codec, WM8978_RESET, 0);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to issue reset\n");
-               return ret;
-       }
-
        wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       snd_soc_add_controls(codec, wm8978_snd_controls,
-                            ARRAY_SIZE(wm8978_snd_controls));
-       wm8978_add_widgets(codec);
-
        return 0;
 }
 
@@ -996,35 +1018,75 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8978 = {
        .suspend =      wm8978_suspend,
        .resume =       wm8978_resume,
        .set_bias_level = wm8978_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8978_reg),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8978_reg,
+
+       .controls = wm8978_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8978_snd_controls),
+       .dapm_widgets = wm8978_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8978_dapm_widgets),
+       .dapm_routes = wm8978_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8978_dapm_routes),
+};
+
+static const struct regmap_config wm8978_regmap_config = {
+       .reg_bits = 7,
+       .val_bits = 9,
+
+       .max_register = WM8978_MAX_REGISTER,
+       .volatile_reg = wm8978_volatile,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = wm8978_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8978_reg_defaults),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm8978_priv *wm8978;
        int ret;
 
-       wm8978 = kzalloc(sizeof(struct wm8978_priv), GFP_KERNEL);
+       wm8978 = devm_kzalloc(&i2c->dev, sizeof(struct wm8978_priv),
+                             GFP_KERNEL);
        if (wm8978 == NULL)
                return -ENOMEM;
 
+       wm8978->regmap = regmap_init_i2c(i2c, &wm8978_regmap_config);
+       if (IS_ERR(wm8978->regmap)) {
+               ret = PTR_ERR(wm8978->regmap);
+               dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+               return ret;
+       }
+
        i2c_set_clientdata(i2c, wm8978);
 
+       /* Reset the codec */
+       ret = regmap_write(wm8978->regmap, WM8978_RESET, 0);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret);
+               goto err;
+       }
+
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8978, &wm8978_dai, 1);
-       if (ret < 0)
-               kfree(wm8978);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+               goto err;
+       }
+
+       return 0;
+
+err:
+       regmap_exit(wm8978->regmap);
        return ret;
 }
 
 static __devexit int wm8978_i2c_remove(struct i2c_client *client)
 {
+       struct wm8978_priv *wm8978 = i2c_get_clientdata(client);
+
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+       regmap_exit(wm8978->regmap);
+
        return 0;
 }
 
@@ -1043,27 +1105,22 @@ static struct i2c_driver wm8978_i2c_driver = {
        .remove =   __devexit_p(wm8978_i2c_remove),
        .id_table = wm8978_i2c_id,
 };
-#endif
 
 static int __init wm8978_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8978_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register WM8978 I2C driver: %d\n",
                       ret);
        }
-#endif
        return ret;
 }
 module_init(wm8978_modinit);
 
 static void __exit wm8978_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8978_i2c_driver);
-#endif
 }
 module_exit(wm8978_exit);
 
index c75525b7f154c9fe25e88a91cb55e99d7e0b37c2..6ae43495b7cf922f171b4afc77b83c3b78ad5754 100644 (file)
@@ -67,6 +67,8 @@
 #define WM8978_OUT3_MIXER_CONTROL              0x38
 #define WM8978_OUT4_MIXER_CONTROL              0x39
 
+#define WM8978_MAX_REGISTER                    0x39
+
 #define WM8978_CACHEREGNUM                     58
 
 /* Clock divider Id's */
index cebde568d1919a0e961601b1e308be8ebb1accc8..367388fdc486484202e4bb550420bdcda31a8fdf 100644 (file)
@@ -249,9 +249,6 @@ static const char *eq5_cutoff_text[] = {
 static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5,
                                  eq5_cutoff_text);
 
-static const char *speaker_mode_text[] = { "Class A/B", "Class D" };
-static const SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text);
-
 static const char *depth_3d_text[] = {
        "Off",
        "6.67%",
@@ -369,8 +366,6 @@ static const struct snd_kcontrol_new wm8983_snd_controls[] = {
        SOC_SINGLE_TLV("EQ5 Volume", WM8983_EQ5_HIGH_SHELF, 0, 24, 1, eq_tlv),
 
        SOC_ENUM("3D Depth", depth_3d),
-
-       SOC_ENUM("Speaker Mode", speaker_mode)
 };
 
 static const struct snd_kcontrol_new left_out_mixer[] = {
index c0c86b3c6adf69076be221308d0fe0fcc48a1c08..14f666398d0c9a0bb7677fa6a1bdbac43125c0fe 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
@@ -39,73 +40,127 @@ static const char *wm8985_supply_names[WM8985_NUM_SUPPLIES] = {
        "AVDD2"
 };
 
-static const u16 wm8985_reg_defs[] = {
-       0x0000,     /* R0  - Software Reset */
-       0x0000,     /* R1  - Power management 1 */
-       0x0000,     /* R2  - Power management 2 */
-       0x0000,     /* R3  - Power management 3 */
-       0x0050,     /* R4  - Audio Interface */
-       0x0000,     /* R5  - Companding control */
-       0x0140,     /* R6  - Clock Gen control */
-       0x0000,     /* R7  - Additional control */
-       0x0000,     /* R8  - GPIO Control */
-       0x0000,     /* R9  - Jack Detect Control 1 */
-       0x0000,     /* R10 - DAC Control */
-       0x00FF,     /* R11 - Left DAC digital Vol */
-       0x00FF,     /* R12 - Right DAC digital vol */
-       0x0000,     /* R13 - Jack Detect Control 2 */
-       0x0100,     /* R14 - ADC Control */
-       0x00FF,     /* R15 - Left ADC Digital Vol */
-       0x00FF,     /* R16 - Right ADC Digital Vol */
-       0x0000,     /* R17 */
-       0x012C,     /* R18 - EQ1 - low shelf */
-       0x002C,     /* R19 - EQ2 - peak 1 */
-       0x002C,     /* R20 - EQ3 - peak 2 */
-       0x002C,     /* R21 - EQ4 - peak 3 */
-       0x002C,     /* R22 - EQ5 - high shelf */
-       0x0000,     /* R23 */
-       0x0032,     /* R24 - DAC Limiter 1 */
-       0x0000,     /* R25 - DAC Limiter 2 */
-       0x0000,     /* R26 */
-       0x0000,     /* R27 - Notch Filter 1 */
-       0x0000,     /* R28 - Notch Filter 2 */
-       0x0000,     /* R29 - Notch Filter 3 */
-       0x0000,     /* R30 - Notch Filter 4 */
-       0x0000,     /* R31 */
-       0x0038,     /* R32 - ALC control 1 */
-       0x000B,     /* R33 - ALC control 2 */
-       0x0032,     /* R34 - ALC control 3 */
-       0x0000,     /* R35 - Noise Gate */
-       0x0008,     /* R36 - PLL N */
-       0x000C,     /* R37 - PLL K 1 */
-       0x0093,     /* R38 - PLL K 2 */
-       0x00E9,     /* R39 - PLL K 3 */
-       0x0000,     /* R40 */
-       0x0000,     /* R41 - 3D control */
-       0x0000,     /* R42 - OUT4 to ADC */
-       0x0000,     /* R43 - Beep control */
-       0x0033,     /* R44 - Input ctrl */
-       0x0010,     /* R45 - Left INP PGA gain ctrl */
-       0x0010,     /* R46 - Right INP PGA gain ctrl */
-       0x0100,     /* R47 - Left ADC BOOST ctrl */
-       0x0100,     /* R48 - Right ADC BOOST ctrl */
-       0x0002,     /* R49 - Output ctrl */
-       0x0001,     /* R50 - Left mixer ctrl */
-       0x0001,     /* R51 - Right mixer ctrl */
-       0x0039,     /* R52 - LOUT1 (HP) volume ctrl */
-       0x0039,     /* R53 - ROUT1 (HP) volume ctrl */
-       0x0039,     /* R54 - LOUT2 (SPK) volume ctrl */
-       0x0039,     /* R55 - ROUT2 (SPK) volume ctrl */
-       0x0001,     /* R56 - OUT3 mixer ctrl */
-       0x0001,     /* R57 - OUT4 (MONO) mix ctrl */
-       0x0001,     /* R58 */
-       0x0000,     /* R59 */
-       0x0004,     /* R60 - OUTPUT ctrl */
-       0x0000,     /* R61 - BIAS CTRL */
-       0x0180,     /* R62 */
-       0x0000      /* R63 */
+static const struct reg_default wm8985_reg_defaults[] = {
+       { 1,  0x0000 },     /* R1  - Power management 1 */
+       { 2,  0x0000 },     /* R2  - Power management 2 */
+       { 3,  0x0000 },     /* R3  - Power management 3 */
+       { 4,  0x0050 },     /* R4  - Audio Interface */
+       { 5,  0x0000 },     /* R5  - Companding control */
+       { 6,  0x0140 },     /* R6  - Clock Gen control */
+       { 7,  0x0000 },     /* R7  - Additional control */
+       { 8,  0x0000 },     /* R8  - GPIO Control */
+       { 9,  0x0000 },     /* R9  - Jack Detect Control 1 */
+       { 10, 0x0000 },     /* R10 - DAC Control */
+       { 11, 0x00FF },     /* R11 - Left DAC digital Vol */
+       { 12, 0x00FF },     /* R12 - Right DAC digital vol */
+       { 13, 0x0000 },     /* R13 - Jack Detect Control 2 */
+       { 14, 0x0100 },     /* R14 - ADC Control */
+       { 15, 0x00FF },     /* R15 - Left ADC Digital Vol */
+       { 16, 0x00FF },     /* R16 - Right ADC Digital Vol */
+       { 18, 0x012C },     /* R18 - EQ1 - low shelf */
+       { 19, 0x002C },     /* R19 - EQ2 - peak 1 */
+       { 20, 0x002C },     /* R20 - EQ3 - peak 2 */
+       { 21, 0x002C },     /* R21 - EQ4 - peak 3 */
+       { 22, 0x002C },     /* R22 - EQ5 - high shelf */
+       { 24, 0x0032 },     /* R24 - DAC Limiter 1 */
+       { 25, 0x0000 },     /* R25 - DAC Limiter 2 */
+       { 27, 0x0000 },     /* R27 - Notch Filter 1 */
+       { 28, 0x0000 },     /* R28 - Notch Filter 2 */
+       { 29, 0x0000 },     /* R29 - Notch Filter 3 */
+       { 30, 0x0000 },     /* R30 - Notch Filter 4 */
+       { 32, 0x0038 },     /* R32 - ALC control 1 */
+       { 33, 0x000B },     /* R33 - ALC control 2 */
+       { 34, 0x0032 },     /* R34 - ALC control 3 */
+       { 35, 0x0000 },     /* R35 - Noise Gate */
+       { 36, 0x0008 },     /* R36 - PLL N */
+       { 37, 0x000C },     /* R37 - PLL K 1 */
+       { 38, 0x0093 },     /* R38 - PLL K 2 */
+       { 39, 0x00E9 },     /* R39 - PLL K 3 */
+       { 41, 0x0000 },     /* R41 - 3D control */
+       { 42, 0x0000 },     /* R42 - OUT4 to ADC */
+       { 43, 0x0000 },     /* R43 - Beep control */
+       { 44, 0x0033 },     /* R44 - Input ctrl */
+       { 45, 0x0010 },     /* R45 - Left INP PGA gain ctrl */
+       { 46, 0x0010 },     /* R46 - Right INP PGA gain ctrl */
+       { 47, 0x0100 },     /* R47 - Left ADC BOOST ctrl */
+       { 48, 0x0100 },     /* R48 - Right ADC BOOST ctrl */
+       { 49, 0x0002 },     /* R49 - Output ctrl */
+       { 50, 0x0001 },     /* R50 - Left mixer ctrl */
+       { 51, 0x0001 },     /* R51 - Right mixer ctrl */
+       { 52, 0x0039 },     /* R52 - LOUT1 (HP) volume ctrl */
+       { 53, 0x0039 },     /* R53 - ROUT1 (HP) volume ctrl */
+       { 54, 0x0039 },     /* R54 - LOUT2 (SPK) volume ctrl */
+       { 55, 0x0039 },     /* R55 - ROUT2 (SPK) volume ctrl */
+       { 56, 0x0001 },     /* R56 - OUT3 mixer ctrl */
+       { 57, 0x0001 },     /* R57 - OUT4 (MONO) mix ctrl */
+       { 60, 0x0004 },     /* R60 - OUTPUT ctrl */
+       { 61, 0x0000 },     /* R61 - BIAS CTRL */
 };
 
+static bool wm8985_writeable(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM8985_SOFTWARE_RESET:
+       case WM8985_POWER_MANAGEMENT_1:
+       case WM8985_POWER_MANAGEMENT_2:
+       case WM8985_POWER_MANAGEMENT_3:
+       case WM8985_AUDIO_INTERFACE:
+       case WM8985_COMPANDING_CONTROL:
+       case WM8985_CLOCK_GEN_CONTROL:
+       case WM8985_ADDITIONAL_CONTROL:
+       case WM8985_GPIO_CONTROL:
+       case WM8985_JACK_DETECT_CONTROL_1:
+       case WM8985_DAC_CONTROL:
+       case WM8985_LEFT_DAC_DIGITAL_VOL:
+       case WM8985_RIGHT_DAC_DIGITAL_VOL:
+       case WM8985_JACK_DETECT_CONTROL_2:
+       case WM8985_ADC_CONTROL:
+       case WM8985_LEFT_ADC_DIGITAL_VOL:
+       case WM8985_RIGHT_ADC_DIGITAL_VOL:
+       case WM8985_EQ1_LOW_SHELF:
+       case WM8985_EQ2_PEAK_1:
+       case WM8985_EQ3_PEAK_2:
+       case WM8985_EQ4_PEAK_3:
+       case WM8985_EQ5_HIGH_SHELF:
+       case WM8985_DAC_LIMITER_1:
+       case WM8985_DAC_LIMITER_2:
+       case WM8985_NOTCH_FILTER_1:
+       case WM8985_NOTCH_FILTER_2:
+       case WM8985_NOTCH_FILTER_3:
+       case WM8985_NOTCH_FILTER_4:
+       case WM8985_ALC_CONTROL_1:
+       case WM8985_ALC_CONTROL_2:
+       case WM8985_ALC_CONTROL_3:
+       case WM8985_NOISE_GATE:
+       case WM8985_PLL_N:
+       case WM8985_PLL_K_1:
+       case WM8985_PLL_K_2:
+       case WM8985_PLL_K_3:
+       case WM8985_3D_CONTROL:
+       case WM8985_OUT4_TO_ADC:
+       case WM8985_BEEP_CONTROL:
+       case WM8985_INPUT_CTRL:
+       case WM8985_LEFT_INP_PGA_GAIN_CTRL:
+       case WM8985_RIGHT_INP_PGA_GAIN_CTRL:
+       case WM8985_LEFT_ADC_BOOST_CTRL:
+       case WM8985_RIGHT_ADC_BOOST_CTRL:
+       case WM8985_OUTPUT_CTRL0:
+       case WM8985_LEFT_MIXER_CTRL:
+       case WM8985_RIGHT_MIXER_CTRL:
+       case WM8985_LOUT1_HP_VOLUME_CTRL:
+       case WM8985_ROUT1_HP_VOLUME_CTRL:
+       case WM8985_LOUT2_SPK_VOLUME_CTRL:
+       case WM8985_ROUT2_SPK_VOLUME_CTRL:
+       case WM8985_OUT3_MIXER_CTRL:
+       case WM8985_OUT4_MONO_MIX_CTRL:
+       case WM8985_OUTPUT_CTRL1:
+       case WM8985_BIAS_CTRL:
+               return true;
+       default:
+               return false;
+       }
+}
+
 /*
  * latch bit 8 of these registers to ensure instant
  * volume updates
@@ -124,7 +179,7 @@ static const int volume_update_regs[] = {
 };
 
 struct wm8985_priv {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
        struct regulator_bulk_data supplies[WM8985_NUM_SUPPLIES];
        unsigned int sysclk;
        unsigned int bclk;
@@ -428,7 +483,7 @@ static const struct snd_soc_dapm_widget wm8985_dapm_widgets[] = {
        SND_SOC_DAPM_OUTPUT("SPKR")
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8985_dapm_routes[] = {
        { "Right Output Mixer", "PCM Switch", "Right DAC" },
        { "Right Output Mixer", "Aux Switch", "AUXR" },
        { "Right Output Mixer", "Line Switch", "Right Boost Mixer" },
@@ -531,17 +586,6 @@ static int eqmode_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static int wm8985_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_new_controls(dapm, wm8985_dapm_widgets,
-                                 ARRAY_SIZE(wm8985_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, audio_map,
-                               ARRAY_SIZE(audio_map));
-       return 0;
-}
-
 static int wm8985_reset(struct snd_soc_codec *codec)
 {
        return snd_soc_write(codec, WM8985_SOFTWARE_RESET, 0x0);
@@ -845,25 +889,6 @@ static int wm8985_set_sysclk(struct snd_soc_dai *dai,
        return 0;
 }
 
-static void wm8985_sync_cache(struct snd_soc_codec *codec)
-{
-       short i;
-       u16 *cache;
-
-       if (!codec->cache_sync)
-               return;
-       codec->cache_only = 0;
-       /* restore cache */
-       cache = codec->reg_cache;
-       for (i = 0; i < codec->driver->reg_cache_size; i++) {
-               if (i == WM8985_SOFTWARE_RESET
-                               || cache[i] == wm8985_reg_defs[i])
-                       continue;
-               snd_soc_write(codec, i, cache[i]);
-       }
-       codec->cache_sync = 0;
-}
-
 static int wm8985_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
@@ -890,7 +915,7 @@ static int wm8985_set_bias_level(struct snd_soc_codec *codec,
                                return ret;
                        }
 
-                       wm8985_sync_cache(codec);
+                       regcache_sync(wm8985->regmap);
 
                        /* enable anti-pop features */
                        snd_soc_update_bits(codec, WM8985_OUT4_TO_ADC,
@@ -933,7 +958,7 @@ static int wm8985_set_bias_level(struct snd_soc_codec *codec,
                snd_soc_write(codec, WM8985_POWER_MANAGEMENT_2, 0);
                snd_soc_write(codec, WM8985_POWER_MANAGEMENT_3, 0);
 
-               codec->cache_sync = 1;
+               regcache_mark_dirty(wm8985->regmap);
 
                regulator_bulk_disable(ARRAY_SIZE(wm8985->supplies),
                                       wm8985->supplies);
@@ -976,11 +1001,11 @@ static int wm8985_probe(struct snd_soc_codec *codec)
        size_t i;
        struct wm8985_priv *wm8985;
        int ret;
-       u16 *cache;
 
        wm8985 = snd_soc_codec_get_drvdata(codec);
+       codec->control_data = wm8985->regmap;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8985->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
                return ret;
@@ -1009,17 +1034,13 @@ static int wm8985_probe(struct snd_soc_codec *codec)
                goto err_reg_enable;
        }
 
-       cache = codec->reg_cache;
        /* latch volume update bits */
        for (i = 0; i < ARRAY_SIZE(volume_update_regs); ++i)
-               cache[volume_update_regs[i]] |= 0x100;
+               snd_soc_update_bits(codec, volume_update_regs[i],
+                                   0x100, 0x100);
        /* enable BIASCUT */
-       cache[WM8985_BIAS_CTRL] |= WM8985_BIASCUT;
-       codec->cache_sync = 1;
-
-       snd_soc_add_controls(codec, wm8985_snd_controls,
-                            ARRAY_SIZE(wm8985_snd_controls));
-       wm8985_add_widgets(codec);
+       snd_soc_update_bits(codec, WM8985_BIAS_CTRL, WM8985_BIASCUT,
+                           WM8985_BIASCUT);
 
        wm8985_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        return 0;
@@ -1068,9 +1089,25 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8985 = {
        .suspend = wm8985_suspend,
        .resume = wm8985_resume,
        .set_bias_level = wm8985_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8985_reg_defs),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8985_reg_defs
+
+       .controls = wm8985_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8985_snd_controls),
+       .dapm_widgets = wm8985_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8985_dapm_widgets),
+       .dapm_routes = wm8985_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8985_dapm_routes),
+};
+
+static const struct regmap_config wm8985_regmap = {
+       .reg_bits = 7,
+       .val_bits = 9,
+
+       .max_register = WM8985_MAX_REGISTER,
+       .writeable_reg = wm8985_writeable,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = wm8985_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8985_reg_defaults),
 };
 
 #if defined(CONFIG_SPI_MASTER)
@@ -1079,24 +1116,39 @@ static int __devinit wm8985_spi_probe(struct spi_device *spi)
        struct wm8985_priv *wm8985;
        int ret;
 
-       wm8985 = kzalloc(sizeof *wm8985, GFP_KERNEL);
+       wm8985 = devm_kzalloc(&spi->dev, sizeof *wm8985, GFP_KERNEL);
        if (!wm8985)
                return -ENOMEM;
 
-       wm8985->control_type = SND_SOC_SPI;
        spi_set_drvdata(spi, wm8985);
 
+       wm8985->regmap = regmap_init_spi(spi, &wm8985_regmap);
+       if (IS_ERR(wm8985->regmap)) {
+               ret = PTR_ERR(wm8985->regmap);
+               dev_err(&spi->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               goto err;
+       }
+
        ret = snd_soc_register_codec(&spi->dev,
                                     &soc_codec_dev_wm8985, &wm8985_dai, 1);
-       if (ret < 0)
-               kfree(wm8985);
+       if (ret != 0)
+               goto err;
+
+       return 0;
+
+err:
+       regmap_exit(wm8985->regmap);
        return ret;
 }
 
 static int __devexit wm8985_spi_remove(struct spi_device *spi)
 {
+       struct wm8985_priv *wm8985 = spi_get_drvdata(spi);
+
        snd_soc_unregister_codec(&spi->dev);
-       kfree(spi_get_drvdata(spi));
+       regmap_exit(wm8985->regmap);
+
        return 0;
 }
 
@@ -1117,24 +1169,39 @@ static __devinit int wm8985_i2c_probe(struct i2c_client *i2c,
        struct wm8985_priv *wm8985;
        int ret;
 
-       wm8985 = kzalloc(sizeof *wm8985, GFP_KERNEL);
+       wm8985 = devm_kzalloc(&i2c->dev, sizeof *wm8985, GFP_KERNEL);
        if (!wm8985)
                return -ENOMEM;
 
-       wm8985->control_type = SND_SOC_I2C;
        i2c_set_clientdata(i2c, wm8985);
 
+       wm8985->regmap = regmap_init_i2c(i2c, &wm8985_regmap);
+       if (IS_ERR(wm8985->regmap)) {
+               ret = PTR_ERR(wm8985->regmap);
+               dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               goto err;
+       }
+
        ret = snd_soc_register_codec(&i2c->dev,
                                     &soc_codec_dev_wm8985, &wm8985_dai, 1);
-       if (ret < 0)
-               kfree(wm8985);
+       if (ret != 0)
+               goto err;
+
+       return 0;
+
+err:
+       regmap_exit(wm8985->regmap);
        return ret;
 }
 
-static __devexit int wm8985_i2c_remove(struct i2c_client *client)
+static __devexit int wm8985_i2c_remove(struct i2c_client *i2c)
 {
-       snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+       struct wm8985_priv *wm8985 = i2c_get_clientdata(i2c);
+
+       snd_soc_unregister_codec(&i2c->dev);
+       regmap_exit(wm8985->regmap);
+
        return 0;
 }
 
index ab52963dd04c976a21fab1badfffb6f775f30de7..6cdf6a2bc28304db51b59128584689bfcc29139c 100644 (file)
  * We can't read the WM8988 register space when we
  * are using 2 wire for device control, so we cache them instead.
  */
-static const u16 wm8988_reg[] = {
-       0x0097, 0x0097, 0x0079, 0x0079,  /*  0 */
-       0x0000, 0x0008, 0x0000, 0x000a,  /*  4 */
-       0x0000, 0x0000, 0x00ff, 0x00ff,  /*  8 */
-       0x000f, 0x000f, 0x0000, 0x0000,  /* 12 */
-       0x0000, 0x007b, 0x0000, 0x0032,  /* 16 */
-       0x0000, 0x00c3, 0x00c3, 0x00c0,  /* 20 */
-       0x0000, 0x0000, 0x0000, 0x0000,  /* 24 */
-       0x0000, 0x0000, 0x0000, 0x0000,  /* 28 */
-       0x0000, 0x0000, 0x0050, 0x0050,  /* 32 */
-       0x0050, 0x0050, 0x0050, 0x0050,  /* 36 */
-       0x0079, 0x0079, 0x0079,          /* 40 */
+static const struct reg_default wm8988_reg_defaults[] = {
+       { 0, 0x0097 },
+       { 1, 0x0097 },
+       { 2, 0x0079 },
+       { 3, 0x0079 },
+       { 5, 0x0008 },
+       { 7, 0x000a },
+       { 8, 0x0000 },
+       { 10, 0x00ff },
+       { 11, 0x00ff },
+       { 12, 0x000f },
+       { 13, 0x000f },
+       { 16, 0x0000 },
+       { 17, 0x007b },
+       { 18, 0x0000 },
+       { 19, 0x0032 },
+       { 20, 0x0000 },
+       { 21, 0x00c3 },
+       { 22, 0x00c3 },
+       { 23, 0x00c0 },
+       { 24, 0x0000 },
+       { 25, 0x0000 },
+       { 26, 0x0000 },
+       { 27, 0x0000 },
+       { 31, 0x0000 },
+       { 32, 0x0000 },
+       { 33, 0x0000 },
+       { 34, 0x0050 },
+       { 35, 0x0050 },
+       { 36, 0x0050 },
+       { 37, 0x0050 },
+       { 40, 0x0079 },
+       { 41, 0x0079 },
+       { 42, 0x0079 },
 };
 
+static bool wm8988_writeable(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM8988_LINVOL:
+       case WM8988_RINVOL:
+       case WM8988_LOUT1V:
+       case WM8988_ROUT1V:
+       case WM8988_ADCDAC:
+       case WM8988_IFACE:
+       case WM8988_SRATE:
+       case WM8988_LDAC:
+       case WM8988_RDAC:
+       case WM8988_BASS:
+       case WM8988_TREBLE:
+       case WM8988_RESET:
+       case WM8988_3D:
+       case WM8988_ALC1:
+       case WM8988_ALC2:
+       case WM8988_ALC3:
+       case WM8988_NGATE:
+       case WM8988_LADC:
+       case WM8988_RADC:
+       case WM8988_ADCTL1:
+       case WM8988_ADCTL2:
+       case WM8988_PWR1:
+       case WM8988_PWR2:
+       case WM8988_ADCTL3:
+       case WM8988_ADCIN:
+       case WM8988_LADCIN:
+       case WM8988_RADCIN:
+       case WM8988_LOUTM1:
+       case WM8988_LOUTM2:
+       case WM8988_ROUTM1:
+       case WM8988_ROUTM2:
+       case WM8988_LOUT2V:
+       case WM8988_ROUT2V:
+       case WM8988_LPPB:
+               return true;
+       default:
+               return false;
+       }
+}
+
 /* codec private data */
 struct wm8988_priv {
+       struct regmap *regmap;
        unsigned int sysclk;
-       enum snd_soc_control_type control_type;
        struct snd_pcm_hw_constraint_list *sysclk_constraints;
 };
 
@@ -317,7 +382,7 @@ static const struct snd_soc_dapm_widget wm8988_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("RINPUT2"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8988_dapm_routes[] = {
 
        { "Left Line Mux", "Line 1", "LINPUT1" },
        { "Left Line Mux", "Line 2", "LINPUT2" },
@@ -661,6 +726,7 @@ static int wm8988_mute(struct snd_soc_dai *dai, int mute)
 static int wm8988_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
+       struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
        u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1;
 
        switch (level) {
@@ -674,7 +740,7 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
 
        case SND_SOC_BIAS_STANDBY:
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-                       snd_soc_cache_sync(codec);
+                       regcache_sync(wm8988->regmap);
 
                        /* VREF, VMID=2x5k */
                        snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
@@ -730,7 +796,10 @@ static struct snd_soc_dai_driver wm8988_dai = {
 
 static int wm8988_suspend(struct snd_soc_codec *codec)
 {
+       struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
+
        wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       regcache_mark_dirty(wm8988->regmap);
        return 0;
 }
 
@@ -743,10 +812,10 @@ static int wm8988_resume(struct snd_soc_codec *codec)
 static int wm8988_probe(struct snd_soc_codec *codec)
 {
        struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
        int ret = 0;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type);
+       codec->control_data = wm8988->regmap;
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
@@ -767,12 +836,6 @@ static int wm8988_probe(struct snd_soc_codec *codec)
 
        wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       snd_soc_add_controls(codec, wm8988_snd_controls,
-                               ARRAY_SIZE(wm8988_snd_controls));
-       snd_soc_dapm_new_controls(dapm, wm8988_dapm_widgets,
-                                 ARRAY_SIZE(wm8988_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
        return 0;
 }
 
@@ -788,9 +851,25 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8988 = {
        .suspend =      wm8988_suspend,
        .resume =       wm8988_resume,
        .set_bias_level = wm8988_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8988_reg),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8988_reg,
+
+       .controls = wm8988_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8988_snd_controls),
+       .dapm_widgets = wm8988_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8988_dapm_widgets),
+       .dapm_routes = wm8988_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes),
+};
+
+static struct regmap_config wm8988_regmap = {
+       .reg_bits = 7,
+       .val_bits = 9,
+
+       .max_register = WM8988_LPPB,
+       .writeable_reg = wm8988_writeable,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = wm8988_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8988_reg_defaults),
 };
 
 #if defined(CONFIG_SPI_MASTER)
@@ -799,24 +878,33 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
        struct wm8988_priv *wm8988;
        int ret;
 
-       wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
+       wm8988 = devm_kzalloc(&spi->dev, sizeof(struct wm8988_priv),
+                             GFP_KERNEL);
        if (wm8988 == NULL)
                return -ENOMEM;
 
-       wm8988->control_type = SND_SOC_SPI;
+       wm8988->regmap = regmap_init_spi(spi, &wm8988_regmap);
+       if (IS_ERR(wm8988->regmap)) {
+               ret = PTR_ERR(wm8988->regmap);
+               dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);
+               return ret;
+       }
+
        spi_set_drvdata(spi, wm8988);
 
        ret = snd_soc_register_codec(&spi->dev,
                        &soc_codec_dev_wm8988, &wm8988_dai, 1);
-       if (ret < 0)
-               kfree(wm8988);
+       if (ret != 0)
+               regmap_exit(wm8988->regmap);
+
        return ret;
 }
 
 static int __devexit wm8988_spi_remove(struct spi_device *spi)
 {
+       struct wm8988_priv *wm8988 = spi_get_drvdata(spi);
        snd_soc_unregister_codec(&spi->dev);
-       kfree(spi_get_drvdata(spi));
+       regmap_exit(wm8988->regmap);
        return 0;
 }
 
@@ -837,24 +925,33 @@ static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
        struct wm8988_priv *wm8988;
        int ret;
 
-       wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
+       wm8988 = devm_kzalloc(&i2c->dev, sizeof(struct wm8988_priv),
+                             GFP_KERNEL);
        if (wm8988 == NULL)
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm8988);
-       wm8988->control_type = SND_SOC_I2C;
+
+       wm8988->regmap = regmap_init_i2c(i2c, &wm8988_regmap);
+       if (IS_ERR(wm8988->regmap)) {
+               ret = PTR_ERR(wm8988->regmap);
+               dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
+               return ret;
+       }
 
        ret =  snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8988, &wm8988_dai, 1);
-       if (ret < 0)
-               kfree(wm8988);
+       if (ret != 0)
+               regmap_exit(wm8988->regmap);
+
        return ret;
 }
 
 static __devexit int wm8988_i2c_remove(struct i2c_client *client)
 {
+       struct wm8988_priv *wm8988 = i2c_get_clientdata(client);
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+       regmap_exit(wm8988->regmap);
        return 0;
 }
 
@@ -866,7 +963,7 @@ MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
 
 static struct i2c_driver wm8988_i2c_driver = {
        .driver = {
-               .name = "wm8988-codec",
+               .name = "wm8988",
                .owner = THIS_MODULE,
        },
        .probe =    wm8988_i2c_probe,
index e538edaae1f0dbd6d9cdd82f34bb8bc232b7b549..9d242351e6e837211c70ffb37033874830ccb8b3 100644 (file)
@@ -1356,7 +1356,7 @@ static int wm8990_probe(struct snd_soc_codec *codec)
        snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
        snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
 
-       snd_soc_add_controls(codec, wm8990_snd_controls,
+       snd_soc_add_codec_controls(codec, wm8990_snd_controls,
                                ARRAY_SIZE(wm8990_snd_controls));
        wm8990_add_widgets(codec);
 
index 7ee40da8dbb52021db9427ec84f7b2751236b7d5..9ac31ba9b82e1ad635167baa38563da16d1e6ee2 100644 (file)
@@ -1297,7 +1297,7 @@ static int wm8991_probe(struct snd_soc_codec *codec)
        snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
        snd_soc_write(codec, WM8991_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
 
-       snd_soc_add_controls(codec, wm8991_snd_controls,
+       snd_soc_add_codec_controls(codec, wm8991_snd_controls,
                             ARRAY_SIZE(wm8991_snd_controls));
 
        snd_soc_dapm_new_controls(&codec->dapm, wm8991_dapm_widgets,
index 7c7fd925db8da78c1ad6bb08bdde66eb60d7210b..d256a934064490abb621b738020463e30490610b 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
@@ -40,134 +41,113 @@ static const char *wm8993_supply_names[WM8993_NUM_SUPPLIES] = {
        "SPKVDD",
 };
 
-static u16 wm8993_reg_defaults[WM8993_REGISTER_COUNT] = {
-       0x8993,     /* R0   - Software Reset */
-       0x0000,     /* R1   - Power Management (1) */
-       0x6000,     /* R2   - Power Management (2) */
-       0x0000,     /* R3   - Power Management (3) */
-       0x4050,     /* R4   - Audio Interface (1) */
-       0x4000,     /* R5   - Audio Interface (2) */
-       0x01C8,     /* R6   - Clocking 1 */
-       0x0000,     /* R7   - Clocking 2 */
-       0x0000,     /* R8   - Audio Interface (3) */
-       0x0040,     /* R9   - Audio Interface (4) */
-       0x0004,     /* R10  - DAC CTRL */
-       0x00C0,     /* R11  - Left DAC Digital Volume */
-       0x00C0,     /* R12  - Right DAC Digital Volume */
-       0x0000,     /* R13  - Digital Side Tone */
-       0x0300,     /* R14  - ADC CTRL */
-       0x00C0,     /* R15  - Left ADC Digital Volume */
-       0x00C0,     /* R16  - Right ADC Digital Volume */
-       0x0000,     /* R17 */
-       0x0000,     /* R18  - GPIO CTRL 1 */
-       0x0010,     /* R19  - GPIO1 */
-       0x0000,     /* R20  - IRQ_DEBOUNCE */
-       0x0000,     /* R21 */
-       0x8000,     /* R22  - GPIOCTRL 2 */
-       0x0800,     /* R23  - GPIO_POL */
-       0x008B,     /* R24  - Left Line Input 1&2 Volume */
-       0x008B,     /* R25  - Left Line Input 3&4 Volume */
-       0x008B,     /* R26  - Right Line Input 1&2 Volume */
-       0x008B,     /* R27  - Right Line Input 3&4 Volume */
-       0x006D,     /* R28  - Left Output Volume */
-       0x006D,     /* R29  - Right Output Volume */
-       0x0066,     /* R30  - Line Outputs Volume */
-       0x0020,     /* R31  - HPOUT2 Volume */
-       0x0079,     /* R32  - Left OPGA Volume */
-       0x0079,     /* R33  - Right OPGA Volume */
-       0x0003,     /* R34  - SPKMIXL Attenuation */
-       0x0003,     /* R35  - SPKMIXR Attenuation */
-       0x0011,     /* R36  - SPKOUT Mixers */
-       0x0100,     /* R37  - SPKOUT Boost */
-       0x0079,     /* R38  - Speaker Volume Left */
-       0x0079,     /* R39  - Speaker Volume Right */
-       0x0000,     /* R40  - Input Mixer2 */
-       0x0000,     /* R41  - Input Mixer3 */
-       0x0000,     /* R42  - Input Mixer4 */
-       0x0000,     /* R43  - Input Mixer5 */
-       0x0000,     /* R44  - Input Mixer6 */
-       0x0000,     /* R45  - Output Mixer1 */
-       0x0000,     /* R46  - Output Mixer2 */
-       0x0000,     /* R47  - Output Mixer3 */
-       0x0000,     /* R48  - Output Mixer4 */
-       0x0000,     /* R49  - Output Mixer5 */
-       0x0000,     /* R50  - Output Mixer6 */
-       0x0000,     /* R51  - HPOUT2 Mixer */
-       0x0000,     /* R52  - Line Mixer1 */
-       0x0000,     /* R53  - Line Mixer2 */
-       0x0000,     /* R54  - Speaker Mixer */
-       0x0000,     /* R55  - Additional Control */
-       0x0000,     /* R56  - AntiPOP1 */
-       0x0000,     /* R57  - AntiPOP2 */
-       0x0000,     /* R58  - MICBIAS */
-       0x0000,     /* R59 */
-       0x0000,     /* R60  - FLL Control 1 */
-       0x0000,     /* R61  - FLL Control 2 */
-       0x0000,     /* R62  - FLL Control 3 */
-       0x2EE0,     /* R63  - FLL Control 4 */
-       0x0002,     /* R64  - FLL Control 5 */
-       0x2287,     /* R65  - Clocking 3 */
-       0x025F,     /* R66  - Clocking 4 */
-       0x0000,     /* R67  - MW Slave Control */
-       0x0000,     /* R68 */
-       0x0002,     /* R69  - Bus Control 1 */
-       0x0000,     /* R70  - Write Sequencer 0 */
-       0x0000,     /* R71  - Write Sequencer 1 */
-       0x0000,     /* R72  - Write Sequencer 2 */
-       0x0000,     /* R73  - Write Sequencer 3 */
-       0x0000,     /* R74  - Write Sequencer 4 */
-       0x0000,     /* R75  - Write Sequencer 5 */
-       0x1F25,     /* R76  - Charge Pump 1 */
-       0x0000,     /* R77 */
-       0x0000,     /* R78 */
-       0x0000,     /* R79 */
-       0x0000,     /* R80 */
-       0x0000,     /* R81  - Class W 0 */
-       0x0000,     /* R82 */
-       0x0000,     /* R83 */
-       0x0000,     /* R84  - DC Servo 0 */
-       0x054A,     /* R85  - DC Servo 1 */
-       0x0000,     /* R86 */
-       0x0000,     /* R87  - DC Servo 3 */
-       0x0000,     /* R88  - DC Servo Readback 0 */
-       0x0000,     /* R89  - DC Servo Readback 1 */
-       0x0000,     /* R90  - DC Servo Readback 2 */
-       0x0000,     /* R91 */
-       0x0000,     /* R92 */
-       0x0000,     /* R93 */
-       0x0000,     /* R94 */
-       0x0000,     /* R95 */
-       0x0100,     /* R96  - Analogue HP 0 */
-       0x0000,     /* R97 */
-       0x0000,     /* R98  - EQ1 */
-       0x000C,     /* R99  - EQ2 */
-       0x000C,     /* R100 - EQ3 */
-       0x000C,     /* R101 - EQ4 */
-       0x000C,     /* R102 - EQ5 */
-       0x000C,     /* R103 - EQ6 */
-       0x0FCA,     /* R104 - EQ7 */
-       0x0400,     /* R105 - EQ8 */
-       0x00D8,     /* R106 - EQ9 */
-       0x1EB5,     /* R107 - EQ10 */
-       0xF145,     /* R108 - EQ11 */
-       0x0B75,     /* R109 - EQ12 */
-       0x01C5,     /* R110 - EQ13 */
-       0x1C58,     /* R111 - EQ14 */
-       0xF373,     /* R112 - EQ15 */
-       0x0A54,     /* R113 - EQ16 */
-       0x0558,     /* R114 - EQ17 */
-       0x168E,     /* R115 - EQ18 */
-       0xF829,     /* R116 - EQ19 */
-       0x07AD,     /* R117 - EQ20 */
-       0x1103,     /* R118 - EQ21 */
-       0x0564,     /* R119 - EQ22 */
-       0x0559,     /* R120 - EQ23 */
-       0x4000,     /* R121 - EQ24 */
-       0x0000,     /* R122 - Digital Pulls */
-       0x0F08,     /* R123 - DRC Control 1 */
-       0x0000,     /* R124 - DRC Control 2 */
-       0x0080,     /* R125 - DRC Control 3 */
-       0x0000,     /* R126 - DRC Control 4 */
+static struct reg_default wm8993_reg_defaults[] = {
+       { 1,   0x0000 },     /* R1   - Power Management (1) */
+       { 2,   0x6000 },     /* R2   - Power Management (2) */
+       { 3,   0x0000 },     /* R3   - Power Management (3) */
+       { 4,   0x4050 },     /* R4   - Audio Interface (1) */
+       { 5,   0x4000 },     /* R5   - Audio Interface (2) */
+       { 6,   0x01C8 },     /* R6   - Clocking 1 */
+       { 7,   0x0000 },     /* R7   - Clocking 2 */
+       { 8,   0x0000 },     /* R8   - Audio Interface (3) */
+       { 9,   0x0040 },     /* R9   - Audio Interface (4) */
+       { 10,  0x0004 },     /* R10  - DAC CTRL */
+       { 11,  0x00C0 },     /* R11  - Left DAC Digital Volume */
+       { 12,  0x00C0 },     /* R12  - Right DAC Digital Volume */
+       { 13,  0x0000 },     /* R13  - Digital Side Tone */
+       { 14,  0x0300 },     /* R14  - ADC CTRL */
+       { 15,  0x00C0 },     /* R15  - Left ADC Digital Volume */
+       { 16,  0x00C0 },     /* R16  - Right ADC Digital Volume */
+       { 18,  0x0000 },     /* R18  - GPIO CTRL 1 */
+       { 19,  0x0010 },     /* R19  - GPIO1 */
+       { 20,  0x0000 },     /* R20  - IRQ_DEBOUNCE */
+       { 21,  0x0000 },     /* R21  - Inputs Clamp */
+       { 22,  0x8000 },     /* R22  - GPIOCTRL 2 */
+       { 23,  0x0800 },     /* R23  - GPIO_POL */
+       { 24,  0x008B },     /* R24  - Left Line Input 1&2 Volume */
+       { 25,  0x008B },     /* R25  - Left Line Input 3&4 Volume */
+       { 26,  0x008B },     /* R26  - Right Line Input 1&2 Volume */
+       { 27,  0x008B },     /* R27  - Right Line Input 3&4 Volume */
+       { 28,  0x006D },     /* R28  - Left Output Volume */
+       { 29,  0x006D },     /* R29  - Right Output Volume */
+       { 30,  0x0066 },     /* R30  - Line Outputs Volume */
+       { 31,  0x0020 },     /* R31  - HPOUT2 Volume */
+       { 32,  0x0079 },     /* R32  - Left OPGA Volume */
+       { 33,  0x0079 },     /* R33  - Right OPGA Volume */
+       { 34,  0x0003 },     /* R34  - SPKMIXL Attenuation */
+       { 35,  0x0003 },     /* R35  - SPKMIXR Attenuation */
+       { 36,  0x0011 },     /* R36  - SPKOUT Mixers */
+       { 37,  0x0100 },     /* R37  - SPKOUT Boost */
+       { 38,  0x0079 },     /* R38  - Speaker Volume Left */
+       { 39,  0x0079 },     /* R39  - Speaker Volume Right */
+       { 40,  0x0000 },     /* R40  - Input Mixer2 */
+       { 41,  0x0000 },     /* R41  - Input Mixer3 */
+       { 42,  0x0000 },     /* R42  - Input Mixer4 */
+       { 43,  0x0000 },     /* R43  - Input Mixer5 */
+       { 44,  0x0000 },     /* R44  - Input Mixer6 */
+       { 45,  0x0000 },     /* R45  - Output Mixer1 */
+       { 46,  0x0000 },     /* R46  - Output Mixer2 */
+       { 47,  0x0000 },     /* R47  - Output Mixer3 */
+       { 48,  0x0000 },     /* R48  - Output Mixer4 */
+       { 49,  0x0000 },     /* R49  - Output Mixer5 */
+       { 50,  0x0000 },     /* R50  - Output Mixer6 */
+       { 51,  0x0000 },     /* R51  - HPOUT2 Mixer */
+       { 52,  0x0000 },     /* R52  - Line Mixer1 */
+       { 53,  0x0000 },     /* R53  - Line Mixer2 */
+       { 54,  0x0000 },     /* R54  - Speaker Mixer */
+       { 55,  0x0000 },     /* R55  - Additional Control */
+       { 56,  0x0000 },     /* R56  - AntiPOP1 */
+       { 57,  0x0000 },     /* R57  - AntiPOP2 */
+       { 58,  0x0000 },     /* R58  - MICBIAS */
+       { 60,  0x0000 },     /* R60  - FLL Control 1 */
+       { 61,  0x0000 },     /* R61  - FLL Control 2 */
+       { 62,  0x0000 },     /* R62  - FLL Control 3 */
+       { 63,  0x2EE0 },     /* R63  - FLL Control 4 */
+       { 64,  0x0002 },     /* R64  - FLL Control 5 */
+       { 65,  0x2287 },     /* R65  - Clocking 3 */
+       { 66,  0x025F },     /* R66  - Clocking 4 */
+       { 67,  0x0000 },     /* R67  - MW Slave Control */
+       { 69,  0x0002 },     /* R69  - Bus Control 1 */
+       { 70,  0x0000 },     /* R70  - Write Sequencer 0 */
+       { 71,  0x0000 },     /* R71  - Write Sequencer 1 */
+       { 72,  0x0000 },     /* R72  - Write Sequencer 2 */
+       { 73,  0x0000 },     /* R73  - Write Sequencer 3 */
+       { 74,  0x0000 },     /* R74  - Write Sequencer 4 */
+       { 75,  0x0000 },     /* R75  - Write Sequencer 5 */
+       { 76,  0x1F25 },     /* R76  - Charge Pump 1 */
+       { 81,  0x0000 },     /* R81  - Class W 0 */
+       { 85,  0x054A },     /* R85  - DC Servo 1 */
+       { 87,  0x0000 },     /* R87  - DC Servo 3 */
+       { 96,  0x0100 },     /* R96  - Analogue HP 0 */
+       { 98,  0x0000 },     /* R98  - EQ1 */
+       { 99,  0x000C },     /* R99  - EQ2 */
+       { 100, 0x000C },     /* R100 - EQ3 */
+       { 101, 0x000C },     /* R101 - EQ4 */
+       { 102, 0x000C },     /* R102 - EQ5 */
+       { 103, 0x000C },     /* R103 - EQ6 */
+       { 104, 0x0FCA },     /* R104 - EQ7 */
+       { 105, 0x0400 },     /* R105 - EQ8 */
+       { 106, 0x00D8 },     /* R106 - EQ9 */
+       { 107, 0x1EB5 },     /* R107 - EQ10 */
+       { 108, 0xF145 },     /* R108 - EQ11 */
+       { 109, 0x0B75 },     /* R109 - EQ12 */
+       { 110, 0x01C5 },     /* R110 - EQ13 */
+       { 111, 0x1C58 },     /* R111 - EQ14 */
+       { 112, 0xF373 },     /* R112 - EQ15 */
+       { 113, 0x0A54 },     /* R113 - EQ16 */
+       { 114, 0x0558 },     /* R114 - EQ17 */
+       { 115, 0x168E },     /* R115 - EQ18 */
+       { 116, 0xF829 },     /* R116 - EQ19 */
+       { 117, 0x07AD },     /* R117 - EQ20 */
+       { 118, 0x1103 },     /* R118 - EQ21 */
+       { 119, 0x0564 },     /* R119 - EQ22 */
+       { 120, 0x0559 },     /* R120 - EQ23 */
+       { 121, 0x4000 },     /* R121 - EQ24 */
+       { 122, 0x0000 },     /* R122 - Digital Pulls */
+       { 123, 0x0F08 },     /* R123 - DRC Control 1 */
+       { 124, 0x0000 },     /* R124 - DRC Control 2 */
+       { 125, 0x0080 },     /* R125 - DRC Control 3 */
+       { 126, 0x0000 },     /* R126 - DRC Control 4 */
 };
 
 static struct {
@@ -225,9 +205,11 @@ static struct {
 
 struct wm8993_priv {
        struct wm_hubs_data hubs_data;
+       struct device *dev;
+       struct regmap *regmap;
        struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES];
        struct wm8993_platform_data pdata;
-       enum snd_soc_control_type control_type;
+       struct completion fll_lock;
        int master;
        int sysclk_source;
        int tdm_slots;
@@ -242,17 +224,137 @@ struct wm8993_priv {
        int fll_src;
 };
 
-static int wm8993_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8993_volatile(struct device *dev, unsigned int reg)
 {
        switch (reg) {
        case WM8993_SOFTWARE_RESET:
+       case WM8993_GPIO_CTRL_1:
        case WM8993_DC_SERVO_0:
        case WM8993_DC_SERVO_READBACK_0:
        case WM8993_DC_SERVO_READBACK_1:
        case WM8993_DC_SERVO_READBACK_2:
-               return 1;
+               return true;
        default:
-               return 0;
+               return false;
+       }
+}
+
+static bool wm8993_readable(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM8993_SOFTWARE_RESET:
+       case WM8993_POWER_MANAGEMENT_1:
+       case WM8993_POWER_MANAGEMENT_2:
+       case WM8993_POWER_MANAGEMENT_3:
+       case WM8993_AUDIO_INTERFACE_1:
+       case WM8993_AUDIO_INTERFACE_2:
+       case WM8993_CLOCKING_1:
+       case WM8993_CLOCKING_2:
+       case WM8993_AUDIO_INTERFACE_3:
+       case WM8993_AUDIO_INTERFACE_4:
+       case WM8993_DAC_CTRL:
+       case WM8993_LEFT_DAC_DIGITAL_VOLUME:
+       case WM8993_RIGHT_DAC_DIGITAL_VOLUME:
+       case WM8993_DIGITAL_SIDE_TONE:
+       case WM8993_ADC_CTRL:
+       case WM8993_LEFT_ADC_DIGITAL_VOLUME:
+       case WM8993_RIGHT_ADC_DIGITAL_VOLUME:
+       case WM8993_GPIO_CTRL_1:
+       case WM8993_GPIO1:
+       case WM8993_IRQ_DEBOUNCE:
+       case WM8993_GPIOCTRL_2:
+       case WM8993_GPIO_POL:
+       case WM8993_LEFT_LINE_INPUT_1_2_VOLUME:
+       case WM8993_LEFT_LINE_INPUT_3_4_VOLUME:
+       case WM8993_RIGHT_LINE_INPUT_1_2_VOLUME:
+       case WM8993_RIGHT_LINE_INPUT_3_4_VOLUME:
+       case WM8993_LEFT_OUTPUT_VOLUME:
+       case WM8993_RIGHT_OUTPUT_VOLUME:
+       case WM8993_LINE_OUTPUTS_VOLUME:
+       case WM8993_HPOUT2_VOLUME:
+       case WM8993_LEFT_OPGA_VOLUME:
+       case WM8993_RIGHT_OPGA_VOLUME:
+       case WM8993_SPKMIXL_ATTENUATION:
+       case WM8993_SPKMIXR_ATTENUATION:
+       case WM8993_SPKOUT_MIXERS:
+       case WM8993_SPKOUT_BOOST:
+       case WM8993_SPEAKER_VOLUME_LEFT:
+       case WM8993_SPEAKER_VOLUME_RIGHT:
+       case WM8993_INPUT_MIXER2:
+       case WM8993_INPUT_MIXER3:
+       case WM8993_INPUT_MIXER4:
+       case WM8993_INPUT_MIXER5:
+       case WM8993_INPUT_MIXER6:
+       case WM8993_OUTPUT_MIXER1:
+       case WM8993_OUTPUT_MIXER2:
+       case WM8993_OUTPUT_MIXER3:
+       case WM8993_OUTPUT_MIXER4:
+       case WM8993_OUTPUT_MIXER5:
+       case WM8993_OUTPUT_MIXER6:
+       case WM8993_HPOUT2_MIXER:
+       case WM8993_LINE_MIXER1:
+       case WM8993_LINE_MIXER2:
+       case WM8993_SPEAKER_MIXER:
+       case WM8993_ADDITIONAL_CONTROL:
+       case WM8993_ANTIPOP1:
+       case WM8993_ANTIPOP2:
+       case WM8993_MICBIAS:
+       case WM8993_FLL_CONTROL_1:
+       case WM8993_FLL_CONTROL_2:
+       case WM8993_FLL_CONTROL_3:
+       case WM8993_FLL_CONTROL_4:
+       case WM8993_FLL_CONTROL_5:
+       case WM8993_CLOCKING_3:
+       case WM8993_CLOCKING_4:
+       case WM8993_MW_SLAVE_CONTROL:
+       case WM8993_BUS_CONTROL_1:
+       case WM8993_WRITE_SEQUENCER_0:
+       case WM8993_WRITE_SEQUENCER_1:
+       case WM8993_WRITE_SEQUENCER_2:
+       case WM8993_WRITE_SEQUENCER_3:
+       case WM8993_WRITE_SEQUENCER_4:
+       case WM8993_WRITE_SEQUENCER_5:
+       case WM8993_CHARGE_PUMP_1:
+       case WM8993_CLASS_W_0:
+       case WM8993_DC_SERVO_0:
+       case WM8993_DC_SERVO_1:
+       case WM8993_DC_SERVO_3:
+       case WM8993_DC_SERVO_READBACK_0:
+       case WM8993_DC_SERVO_READBACK_1:
+       case WM8993_DC_SERVO_READBACK_2:
+       case WM8993_ANALOGUE_HP_0:
+       case WM8993_EQ1:
+       case WM8993_EQ2:
+       case WM8993_EQ3:
+       case WM8993_EQ4:
+       case WM8993_EQ5:
+       case WM8993_EQ6:
+       case WM8993_EQ7:
+       case WM8993_EQ8:
+       case WM8993_EQ9:
+       case WM8993_EQ10:
+       case WM8993_EQ11:
+       case WM8993_EQ12:
+       case WM8993_EQ13:
+       case WM8993_EQ14:
+       case WM8993_EQ15:
+       case WM8993_EQ16:
+       case WM8993_EQ17:
+       case WM8993_EQ18:
+       case WM8993_EQ19:
+       case WM8993_EQ20:
+       case WM8993_EQ21:
+       case WM8993_EQ22:
+       case WM8993_EQ23:
+       case WM8993_EQ24:
+       case WM8993_DIGITAL_PULLS:
+       case WM8993_DRC_CONTROL_1:
+       case WM8993_DRC_CONTROL_2:
+       case WM8993_DRC_CONTROL_3:
+       case WM8993_DRC_CONTROL_4:
+               return true;
+       default:
+               return false;
        }
 }
 
@@ -369,8 +471,10 @@ static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
                          unsigned int Fref, unsigned int Fout)
 {
        struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
+       struct i2c_client *i2c = to_i2c_client(codec->dev);
        u16 reg1, reg4, reg5;
        struct _fll_div fll_div;
+       unsigned int timeout;
        int ret;
 
        /* Any change? */
@@ -441,14 +545,22 @@ static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
        reg5 |= fll_div.fll_clk_ref_div << WM8993_FLL_CLK_REF_DIV_SHIFT;
        snd_soc_write(codec, WM8993_FLL_CONTROL_5, reg5);
 
+       /* If we've got an interrupt wired up make sure we get it */
+       if (i2c->irq)
+               timeout = msecs_to_jiffies(20);
+       else if (Fref < 1000000)
+               timeout = msecs_to_jiffies(3);
+       else
+               timeout = msecs_to_jiffies(1);
+
+       try_wait_for_completion(&wm8993->fll_lock);
+
        /* Enable the FLL */
        snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA);
 
-       /* Both overestimates */
-       if (Fref < 1000000)
-               msleep(3);
-       else
-               msleep(1);
+       timeout = wait_for_completion_timeout(&wm8993->fll_lock, timeout);
+       if (i2c->irq && !timeout)
+               dev_warn(codec->dev, "Timed out waiting for FLL\n");
 
        dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout);
 
@@ -946,6 +1058,8 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
        struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
+       wm_hubs_set_bias_level(codec, level);
+
        switch (level) {
        case SND_SOC_BIAS_ON:
        case SND_SOC_BIAS_PREPARE:
@@ -963,12 +1077,10 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
                        if (ret != 0)
                                return ret;
 
-                       snd_soc_cache_sync(codec);
+                       regcache_cache_only(wm8993->regmap, false);
+                       regcache_sync(wm8993->regmap);
 
-                       /* Tune DC servo configuration */
-                       snd_soc_write(codec, 0x44, 3);
-                       snd_soc_write(codec, 0x56, 3);
-                       snd_soc_write(codec, 0x44, 0);
+                       wm_hubs_vmid_ena(codec);
 
                        /* Bring up VMID with fast soft start */
                        snd_soc_update_bits(codec, WM8993_ANTIPOP2,
@@ -1024,14 +1136,8 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
                                    WM8993_VMID_RAMP_MASK |
                                    WM8993_BIAS_SRC, 0);
 
-#ifdef CONFIG_REGULATOR
-               /* Post 2.6.34 we will be able to get a callback when
-                * the regulators are disabled which we can use but
-               * for now just assume that the power will be cut if
-               * the regulator API is in use.
-               */
-               codec->cache_sync = 1;
-#endif
+               regcache_cache_only(wm8993->regmap, true);
+               regcache_mark_dirty(wm8993->regmap);
 
                regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies),
                                       wm8993->supplies);
@@ -1378,6 +1484,45 @@ out:
        return 0;
 }
 
+static irqreturn_t wm8993_irq(int irq, void *data)
+{
+       struct wm8993_priv *wm8993 = data;
+       int mask, val, ret;
+
+       ret = regmap_read(wm8993->regmap, WM8993_GPIO_CTRL_1, &val);
+       if (ret != 0) {
+               dev_err(wm8993->dev, "Failed to read interrupt status: %d\n",
+                       ret);
+               return IRQ_NONE;
+       }
+
+       ret = regmap_read(wm8993->regmap, WM8993_GPIOCTRL_2, &mask);
+       if (ret != 0) {
+               dev_err(wm8993->dev, "Failed to read interrupt mask: %d\n",
+                       ret);
+               return IRQ_NONE;
+       }
+
+       /* The IRQ pin status is visible in the register too */
+       val &= ~(mask | WM8993_IRQ);
+       if (!val)
+               return IRQ_NONE;
+
+       if (val & WM8993_TEMPOK_EINT)
+               dev_crit(wm8993->dev, "Thermal warning\n");
+
+       if (val & WM8993_FLL_LOCK_EINT) {
+               dev_dbg(wm8993->dev, "FLL locked\n");
+               complete(&wm8993->fll_lock);
+       }
+
+       ret = regmap_write(wm8993->regmap, WM8993_GPIO_CTRL_1, val);
+       if (ret != 0)
+               dev_err(wm8993->dev, "Failed to ack interrupt: %d\n", ret);
+
+       return IRQ_HANDLED;
+}
+
 static const struct snd_soc_dai_ops wm8993_ops = {
        .set_sysclk = wm8993_set_sysclk,
        .set_fmt = wm8993_set_dai_fmt,
@@ -1402,6 +1547,7 @@ static struct snd_soc_dai_driver wm8993_dai = {
                .channels_max = 2,
                .rates = WM8993_RATES,
                .formats = WM8993_FORMATS,
+               .sig_bits = 24,
        },
        .capture = {
                 .stream_name = "Capture",
@@ -1409,6 +1555,7 @@ static struct snd_soc_dai_driver wm8993_dai = {
                 .channels_max = 2,
                 .rates = WM8993_RATES,
                 .formats = WM8993_FORMATS,
+                .sig_bits = 24,
         },
        .ops = &wm8993_ops,
        .symmetric_rates = 1,
@@ -1418,49 +1565,20 @@ static int wm8993_probe(struct snd_soc_codec *codec)
 {
        struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
        struct snd_soc_dapm_context *dapm = &codec->dapm;
-       int ret, i, val;
+       int ret;
 
        wm8993->hubs_data.hp_startup_mode = 1;
        wm8993->hubs_data.dcs_codes_l = -2;
        wm8993->hubs_data.dcs_codes_r = -2;
        wm8993->hubs_data.series_startup = 1;
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+       codec->control_data = wm8993->regmap;
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
        }
 
-       for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
-               wm8993->supplies[i].supply = wm8993_supply_names[i];
-
-       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies),
-                                wm8993->supplies);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-               return ret;
-       }
-
-       ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
-                                   wm8993->supplies);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
-               goto err_get;
-       }
-
-       val = snd_soc_read(codec, WM8993_SOFTWARE_RESET);
-       if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) {
-               dev_err(codec->dev, "Invalid ID register value %x\n", val);
-               ret = -EINVAL;
-               goto err_enable;
-       }
-
-       ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff);
-       if (ret != 0)
-               goto err_enable;
-
-       codec->cache_only = 1;
-
        /* By default we're using the output mixers */
        wm8993->class_w_users = 2;
 
@@ -1489,15 +1607,15 @@ static int wm8993_probe(struct snd_soc_codec *codec)
 
        ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        if (ret != 0)
-               goto err_enable;
+               return ret;
 
-       snd_soc_add_controls(codec, wm8993_snd_controls,
+       snd_soc_add_codec_controls(codec, wm8993_snd_controls,
                             ARRAY_SIZE(wm8993_snd_controls));
        if (wm8993->pdata.num_retune_configs != 0) {
                dev_dbg(codec->dev, "Using ReTune Mobile\n");
        } else {
                dev_dbg(codec->dev, "No ReTune Mobile, using normal EQ\n");
-               snd_soc_add_controls(codec, wm8993_eq_controls,
+               snd_soc_add_codec_controls(codec, wm8993_eq_controls,
                                     ARRAY_SIZE(wm8993_eq_controls));
        }
 
@@ -1509,13 +1627,14 @@ static int wm8993_probe(struct snd_soc_codec *codec)
        wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff,
                                    wm8993->pdata.lineout2_diff);
 
+       /* If the line outputs are differential then we aren't presenting
+        * VMID as an output and can disable it.
+        */
+       if (wm8993->pdata.lineout1_diff && wm8993->pdata.lineout2_diff)
+               codec->dapm.idle_bias_off = 1;
+
        return 0;
 
-err_enable:
-       regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-err_get:
-       regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-       return ret;
 }
 
 static int wm8993_remove(struct snd_soc_codec *codec)
@@ -1578,41 +1697,149 @@ static int wm8993_resume(struct snd_soc_codec *codec)
 #define wm8993_resume NULL
 #endif
 
+/* Tune DC servo configuration */
+static struct reg_default wm8993_regmap_patch[] = {
+       { 0x44, 3 },
+       { 0x56, 3 },
+       { 0x44, 0 },
+};
+
+static const struct regmap_config wm8993_regmap = {
+       .reg_bits = 8,
+       .val_bits = 16,
+
+       .max_register = WM8993_MAX_REGISTER,
+       .volatile_reg = wm8993_volatile,
+       .readable_reg = wm8993_readable,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = wm8993_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8993_reg_defaults),
+};
+
 static struct snd_soc_codec_driver soc_codec_dev_wm8993 = {
        .probe =        wm8993_probe,
        .remove =       wm8993_remove,
        .suspend =      wm8993_suspend,
        .resume =       wm8993_resume,
        .set_bias_level = wm8993_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8993_reg_defaults),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8993_reg_defaults,
-       .volatile_register = wm8993_volatile,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm8993_priv *wm8993;
-       int ret;
+       unsigned int reg;
+       int ret, i;
 
        wm8993 = devm_kzalloc(&i2c->dev, sizeof(struct wm8993_priv),
                              GFP_KERNEL);
        if (wm8993 == NULL)
                return -ENOMEM;
 
+       wm8993->dev = &i2c->dev;
+       init_completion(&wm8993->fll_lock);
+
+       wm8993->regmap = regmap_init_i2c(i2c, &wm8993_regmap);
+       if (IS_ERR(wm8993->regmap)) {
+               ret = PTR_ERR(wm8993->regmap);
+               dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+               return ret;
+       }
+
        i2c_set_clientdata(i2c, wm8993);
 
+       for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
+               wm8993->supplies[i].supply = wm8993_supply_names[i];
+
+       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8993->supplies),
+                                wm8993->supplies);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
+               goto err;
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
+                                   wm8993->supplies);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
+               goto err_get;
+       }
+
+       ret = regmap_read(wm8993->regmap, WM8993_SOFTWARE_RESET, &reg);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
+               goto err_enable;
+       }
+
+       if (reg != 0x8993) {
+               dev_err(&i2c->dev, "Invalid ID register value %x\n", reg);
+               ret = -EINVAL;
+               goto err_enable;
+       }
+
+       ret = regmap_write(wm8993->regmap, WM8993_SOFTWARE_RESET, 0xffff);
+       if (ret != 0)
+               goto err_enable;
+
+       ret = regmap_register_patch(wm8993->regmap, wm8993_regmap_patch,
+                                   ARRAY_SIZE(wm8993_regmap_patch));
+       if (ret != 0)
+               dev_warn(wm8993->dev, "Failed to apply regmap patch: %d\n",
+                        ret);
+
+       if (i2c->irq) {
+               /* Put GPIO1 into interrupt mode (only GPIO1 can output IRQ) */
+               ret = regmap_update_bits(wm8993->regmap, WM8993_GPIO1,
+                                        WM8993_GPIO1_PD |
+                                        WM8993_GPIO1_SEL_MASK, 7);
+               if (ret != 0)
+                       goto err_enable;
+
+               ret = request_threaded_irq(i2c->irq, NULL, wm8993_irq,
+                                          IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                                          "wm8993", wm8993);
+               if (ret != 0)
+                       goto err_enable;
+
+       }
+
+       regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+
+       regcache_cache_only(wm8993->regmap, true);
+
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8993, &wm8993_dai, 1);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+               goto err_irq;
+       }
+
+       return 0;
+
+err_irq:
+       if (i2c->irq)
+               free_irq(i2c->irq, wm8993);
+err_enable:
+       regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+err_get:
+       regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+err:
+       regmap_exit(wm8993->regmap);
        return ret;
 }
 
-static __devexit int wm8993_i2c_remove(struct i2c_client *client)
+static __devexit int wm8993_i2c_remove(struct i2c_client *i2c)
 {
-       snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+       struct wm8993_priv *wm8993 = i2c_get_clientdata(i2c);
+
+       snd_soc_unregister_codec(&i2c->dev);
+       if (i2c->irq)
+               free_irq(i2c->irq, wm8993);
+       regmap_exit(wm8993->regmap);
+       regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+       regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+
        return 0;
 }
 
@@ -1631,30 +1858,8 @@ static struct i2c_driver wm8993_i2c_driver = {
        .remove =   __devexit_p(wm8993_i2c_remove),
        .id_table = wm8993_i2c_id,
 };
-#endif
-
-static int __init wm8993_modinit(void)
-{
-       int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       ret = i2c_add_driver(&wm8993_i2c_driver);
-       if (ret != 0) {
-               pr_err("WM8993: Unable to register I2C driver: %d\n",
-                      ret);
-       }
-#endif
-       return ret;
-}
-module_init(wm8993_modinit);
-
-static void __exit wm8993_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       i2c_del_driver(&wm8993_i2c_driver);
-#endif
-}
-module_exit(wm8993_exit);
 
+module_i2c_driver(wm8993_i2c_driver);
 
 MODULE_DESCRIPTION("ASoC WM8993 driver");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
index 2184617b96117bfabac14cc7411eb24d2dadb317..4478b40c86e3191ccdad133c33b2d0b1f17272b7 100644 (file)
@@ -31,6 +31,7 @@
 #define WM8993_GPIO_CTRL_1                      0x12
 #define WM8993_GPIO1                            0x13
 #define WM8993_IRQ_DEBOUNCE                     0x14
+#define WM8993_INPUTS_CLAMP_REG                        0x15
 #define WM8993_GPIOCTRL_2                       0x16
 #define WM8993_GPIO_POL                         0x17
 #define WM8993_LEFT_LINE_INPUT_1_2_VOLUME       0x18
 #define WM8993_GPIO1_DB_SHIFT                        0  /* GPIO1_DB */
 #define WM8993_GPIO1_DB_WIDTH                        1  /* GPIO1_DB */
 
+/*
+ * R21 (0x15) - Inputs Clamp
+ */
+#define WM8993_INPUTS_CLAMP                     0x0040  /* INPUTS_CLAMP */
+#define WM8993_INPUTS_CLAMP_MASK                0x0040  /* INPUTS_CLAMP */
+#define WM8993_INPUTS_CLAMP_SHIFT                    7  /* INPUTS_CLAMP */
+#define WM8993_INPUTS_CLAMP_WIDTH                    1  /* INPUTS_CLAMP */
+
 /*
  * R22 (0x16) - GPIOCTRL 2
  */
index ec69a6c152fea9a8b55a7c16c1f3935fb3dc305d..18c99cda7cc9cad1c571bf71ebc273a566174328 100644 (file)
@@ -778,19 +778,25 @@ static void vmid_reference(struct snd_soc_codec *codec)
                wm8994->vmid_refcount);
 
        if (wm8994->vmid_refcount == 1) {
+               snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
+                                   WM8994_LINEOUT_VMID_BUF_ENA |
+                                   WM8994_LINEOUT1_DISCH |
+                                   WM8994_LINEOUT2_DISCH,
+                                   WM8994_LINEOUT_VMID_BUF_ENA);
+
                /* Startup bias, VMID ramp & buffer */
                snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+                                   WM8994_BIAS_SRC |
+                                   WM8994_VMID_DISCH |
                                    WM8994_STARTUP_BIAS_ENA |
                                    WM8994_VMID_BUF_ENA |
                                    WM8994_VMID_RAMP_MASK,
+                                   WM8994_BIAS_SRC |
                                    WM8994_STARTUP_BIAS_ENA |
                                    WM8994_VMID_BUF_ENA |
-                                   (0x3 << WM8994_VMID_RAMP_SHIFT));
+                                   (0x2 << WM8994_VMID_RAMP_SHIFT));
 
-               /* Remove discharge for line out */
-               snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
-                                   WM8994_LINEOUT1_DISCH |
-                                   WM8994_LINEOUT2_DISCH, 0);
+               wm_hubs_vmid_ena(codec);
 
                /* Main bias enable, VMID=2x40k */
                snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
@@ -798,7 +804,11 @@ static void vmid_reference(struct snd_soc_codec *codec)
                                    WM8994_VMID_SEL_MASK,
                                    WM8994_BIAS_ENA | 0x2);
 
-               msleep(20);
+               msleep(50);
+
+               snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+                                   WM8994_VMID_RAMP_MASK | WM8994_BIAS_SRC,
+                                   0);
        }
 }
 
@@ -828,6 +838,10 @@ static void vmid_dereference(struct snd_soc_codec *codec)
                                    WM8994_BIAS_ENA |
                                    WM8994_VMID_SEL_MASK, 0);
 
+               /* Discharge VMID */
+               snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+                                   WM8994_VMID_DISCH, WM8994_VMID_DISCH);
+
                /* Discharge line */
                snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
                                    WM8994_LINEOUT1_DISCH |
@@ -1459,17 +1473,17 @@ SND_SOC_DAPM_AIF_IN_E("AIF2DACR", NULL, 0,
                      WM8994_POWER_MANAGEMENT_5, 12, 0, wm8958_aif_ev,
                      SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 
-SND_SOC_DAPM_AIF_IN("AIF1DACDAT", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_IN("AIF2DACDAT", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1ADCDAT", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("AIF2ADCDAT", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF1DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF2DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1ADCDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2ADCDAT",  NULL, 0, SND_SOC_NOPM, 0, 0),
 
 SND_SOC_DAPM_MUX("AIF1DAC Mux", SND_SOC_NOPM, 0, 0, &aif1dac_mux),
 SND_SOC_DAPM_MUX("AIF2DAC Mux", SND_SOC_NOPM, 0, 0, &aif2dac_mux),
 SND_SOC_DAPM_MUX("AIF2ADC Mux", SND_SOC_NOPM, 0, 0, &aif2adc_mux),
 
-SND_SOC_DAPM_AIF_IN("AIF3DACDAT", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF3DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
 
 SND_SOC_DAPM_SUPPLY("TOCLK", WM8994_CLOCKING_1, 4, 0, NULL, 0),
 
@@ -1584,6 +1598,14 @@ static const struct snd_soc_dapm_route intercon[] = {
 
        { "TOCLK", NULL, "CLK_SYS" },
 
+       { "AIF1DACDAT", NULL, "AIF1 Playback" },
+       { "AIF2DACDAT", NULL, "AIF2 Playback" },
+       { "AIF3DACDAT", NULL, "AIF3 Playback" },
+
+       { "AIF1 Capture", NULL, "AIF1ADCDAT" },
+       { "AIF2 Capture", NULL, "AIF2ADCDAT" },
+       { "AIF3 Capture", NULL, "AIF3ADCDAT" },
+
        /* AIF1 outputs */
        { "AIF1ADC1L", NULL, "AIF1ADC1L Mixer" },
        { "AIF1ADC1L Mixer", "ADC/DMIC Switch", "ADCL Mux" },
@@ -2074,6 +2096,8 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = wm8994->wm8994;
 
+       wm_hubs_set_bias_level(codec, level);
+
        switch (level) {
        case SND_SOC_BIAS_ON:
                break;
@@ -2168,6 +2192,7 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
                        wm8994->cur_fw = NULL;
                break;
        }
+
        codec->dapm.bias_level = level;
 
        return 0;
@@ -2654,6 +2679,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
                        .channels_max = 2,
                        .rates = WM8994_RATES,
                        .formats = WM8994_FORMATS,
+                       .sig_bits = 24,
                },
                .capture = {
                        .stream_name = "AIF1 Capture",
@@ -2661,6 +2687,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
                        .channels_max = 2,
                        .rates = WM8994_RATES,
                        .formats = WM8994_FORMATS,
+                       .sig_bits = 24,
                 },
                .ops = &wm8994_aif1_dai_ops,
        },
@@ -2673,6 +2700,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
                        .channels_max = 2,
                        .rates = WM8994_RATES,
                        .formats = WM8994_FORMATS,
+                       .sig_bits = 24,
                },
                .capture = {
                        .stream_name = "AIF2 Capture",
@@ -2680,6 +2708,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
                        .channels_max = 2,
                        .rates = WM8994_RATES,
                        .formats = WM8994_FORMATS,
+                       .sig_bits = 24,
                },
                .probe = wm8994_aif2_probe,
                .ops = &wm8994_aif2_dai_ops,
@@ -2693,6 +2722,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
                        .channels_max = 2,
                        .rates = WM8994_RATES,
                        .formats = WM8994_FORMATS,
+                       .sig_bits = 24,
                },
                .capture = {
                        .stream_name = "AIF3 Capture",
@@ -2700,7 +2730,8 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
                        .channels_max = 2,
                        .rates = WM8994_RATES,
                        .formats = WM8994_FORMATS,
-               },
+                       .sig_bits = 24,
+                },
                .ops = &wm8994_aif3_dai_ops,
        }
 };
@@ -2762,8 +2793,6 @@ static int wm8994_resume(struct snd_soc_codec *codec)
                codec->cache_only = 0;
        }
 
-       wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
        for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
                if (!wm8994->fll_suspend[i].out)
                        continue;
@@ -2865,7 +2894,7 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
        wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts;
        wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts;
 
-       ret = snd_soc_add_controls(wm8994->codec, controls,
+       ret = snd_soc_add_codec_controls(wm8994->codec, controls,
                                   ARRAY_SIZE(controls));
        if (ret != 0)
                dev_err(wm8994->codec->dev,
@@ -2918,7 +2947,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
                wm8994->drc_enum.max = pdata->num_drc_cfgs;
                wm8994->drc_enum.texts = wm8994->drc_texts;
 
-               ret = snd_soc_add_controls(wm8994->codec, controls,
+               ret = snd_soc_add_codec_controls(wm8994->codec, controls,
                                           ARRAY_SIZE(controls));
                if (ret != 0)
                        dev_err(wm8994->codec->dev,
@@ -2934,7 +2963,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
        if (pdata->num_retune_mobile_cfgs)
                wm8994_handle_retune_mobile_pdata(wm8994);
        else
-               snd_soc_add_controls(wm8994->codec, wm8994_eq_controls,
+               snd_soc_add_codec_controls(wm8994->codec, wm8994_eq_controls,
                                     ARRAY_SIZE(wm8994_eq_controls));
 
        for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) {
@@ -2951,8 +2980,6 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
  * @codec:   WM8994 codec
  * @jack:    jack to report detection events on
  * @micbias: microphone bias to detect on
- * @det:     value to report for presence detection
- * @shrt:    value to report for short detection
  *
  * Enable microphone detection via IRQ on the WM8994.  If GPIOs are
  * being used to bring out signals to the processor then only platform
@@ -2963,43 +2990,63 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
  * and micbias2_lvl platform data members.
  */
 int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
-                     int micbias, int det, int shrt)
+                     int micbias)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994_micdet *micdet;
        struct wm8994 *control = wm8994->wm8994;
-       int reg;
+       int reg, ret;
 
-       if (control->type != WM8994)
+       if (control->type != WM8994) {
+               dev_warn(codec->dev, "Not a WM8994\n");
                return -EINVAL;
+       }
 
        switch (micbias) {
        case 1:
                micdet = &wm8994->micdet[0];
+               if (jack)
+                       ret = snd_soc_dapm_force_enable_pin(&codec->dapm,
+                                                           "MICBIAS1");
+               else
+                       ret = snd_soc_dapm_disable_pin(&codec->dapm,
+                                                      "MICBIAS1");
                break;
        case 2:
                micdet = &wm8994->micdet[1];
+               if (jack)
+                       ret = snd_soc_dapm_force_enable_pin(&codec->dapm,
+                                                           "MICBIAS1");
+               else
+                       ret = snd_soc_dapm_disable_pin(&codec->dapm,
+                                                      "MICBIAS1");
                break;
        default:
+               dev_warn(codec->dev, "Invalid MICBIAS %d\n", micbias);
                return -EINVAL;
-       }       
+       }
+
+       if (ret != 0)
+               dev_warn(codec->dev, "Failed to configure MICBIAS%d: %d\n",
+                        micbias, ret);
 
-       dev_dbg(codec->dev, "Configuring microphone detection on %d: %x %x\n",
-               micbias, det, shrt);
+       dev_dbg(codec->dev, "Configuring microphone detection on %d %p\n",
+               micbias, jack);
 
        /* Store the configuration */
        micdet->jack = jack;
-       micdet->det = det;
-       micdet->shrt = shrt;
+       micdet->detecting = true;
 
        /* If either of the jacks is set up then enable detection */
        if (wm8994->micdet[0].jack || wm8994->micdet[1].jack)
                reg = WM8994_MICD_ENA;
-       else 
+       else
                reg = 0;
 
        snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg);
 
+       snd_soc_dapm_sync(&codec->dapm);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(wm8994_mic_detect);
@@ -3025,20 +3072,42 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
        dev_dbg(codec->dev, "Microphone status: %x\n", reg);
 
        report = 0;
-       if (reg & WM8994_MIC1_DET_STS)
-               report |= priv->micdet[0].det;
-       if (reg & WM8994_MIC1_SHRT_STS)
-               report |= priv->micdet[0].shrt;
+       if (reg & WM8994_MIC1_DET_STS) {
+               if (priv->micdet[0].detecting)
+                       report = SND_JACK_HEADSET;
+       }
+       if (reg & WM8994_MIC1_SHRT_STS) {
+               if (priv->micdet[0].detecting)
+                       report = SND_JACK_HEADPHONE;
+               else
+                       report |= SND_JACK_BTN_0;
+       }
+       if (report)
+               priv->micdet[0].detecting = false;
+       else
+               priv->micdet[0].detecting = true;
+
        snd_soc_jack_report(priv->micdet[0].jack, report,
-                           priv->micdet[0].det | priv->micdet[0].shrt);
+                           SND_JACK_HEADSET | SND_JACK_BTN_0);
 
        report = 0;
-       if (reg & WM8994_MIC2_DET_STS)
-               report |= priv->micdet[1].det;
-       if (reg & WM8994_MIC2_SHRT_STS)
-               report |= priv->micdet[1].shrt;
+       if (reg & WM8994_MIC2_DET_STS) {
+               if (priv->micdet[1].detecting)
+                       report = SND_JACK_HEADSET;
+       }
+       if (reg & WM8994_MIC2_SHRT_STS) {
+               if (priv->micdet[1].detecting)
+                       report = SND_JACK_HEADPHONE;
+               else
+                       report |= SND_JACK_BTN_0;
+       }
+       if (report)
+               priv->micdet[1].detecting = false;
+       else
+               priv->micdet[1].detecting = true;
+
        snd_soc_jack_report(priv->micdet[1].jack, report,
-                           priv->micdet[1].det | priv->micdet[1].shrt);
+                           SND_JACK_HEADSET | SND_JACK_BTN_0);
 
        return IRQ_HANDLED;
 }
@@ -3087,7 +3156,7 @@ static void wm8958_default_micdet(u16 status, void *data)
        }
 
 
-       if (wm8994->mic_detecting && status & 0x4) {
+       if (wm8994->mic_detecting && status & 0xfc) {
                dev_dbg(codec->dev, "Detected headphone\n");
                wm8994->mic_detecting = false;
 
@@ -3392,12 +3461,20 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                                     WM8994_IRQ_MIC1_DET;
 
        pm_runtime_enable(codec->dev);
-       pm_runtime_resume(codec->dev);
+       pm_runtime_idle(codec->dev);
+
+       /* By default use idle_bias_off, will override for WM8994 */
+       codec->dapm.idle_bias_off = 1;
 
        /* Set revision-specific configuration */
        wm8994->revision = snd_soc_read(codec, WM8994_CHIP_REVISION);
        switch (control->type) {
        case WM8994:
+               /* Single ended line outputs should have VMID on. */
+               if (!wm8994->pdata->lineout1_diff ||
+                   !wm8994->pdata->lineout2_diff)
+                       codec->dapm.idle_bias_off = 0;
+
                switch (wm8994->revision) {
                case 2:
                case 3:
@@ -3536,6 +3613,9 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                        wm8994->fll_locked_irq = false;
        }
 
+       /* Make sure we can read from the GPIOs if they're inputs */
+       pm_runtime_get_sync(codec->dev);
+
        /* Remember if AIFnLRCLK is configured as a GPIO.  This should be
         * configured on init - if a system wants to do this dynamically
         * at runtime we can deal with that then.
@@ -3564,7 +3644,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                wm8994->lrclk_shared[1] = 0;
        }
 
-       wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       pm_runtime_put(codec->dev);
 
        /* Latch volume updates (right only; we always do left then right). */
        snd_soc_update_bits(codec, WM8994_AIF1_DAC1_LEFT_VOLUME,
@@ -3642,7 +3722,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
        wm8994_handle_pdata(wm8994);
 
        wm_hubs_add_analogue_controls(codec);
-       snd_soc_add_controls(codec, wm8994_snd_controls,
+       snd_soc_add_codec_controls(codec, wm8994_snd_controls,
                             ARRAY_SIZE(wm8994_snd_controls));
        snd_soc_dapm_new_controls(dapm, wm8994_dapm_widgets,
                                  ARRAY_SIZE(wm8994_dapm_widgets));
@@ -3668,7 +3748,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                }
                break;
        case WM8958:
-               snd_soc_add_controls(codec, wm8958_snd_controls,
+               snd_soc_add_codec_controls(codec, wm8958_snd_controls,
                                     ARRAY_SIZE(wm8958_snd_controls));
                snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
                                          ARRAY_SIZE(wm8958_dapm_widgets));
@@ -3690,7 +3770,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                break;
 
        case WM1811:
-               snd_soc_add_controls(codec, wm8958_snd_controls,
+               snd_soc_add_codec_controls(codec, wm8958_snd_controls,
                                     ARRAY_SIZE(wm8958_snd_controls));
                snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
                                          ARRAY_SIZE(wm8958_dapm_widgets));
index c3a42474ab19a6656fdd8549c3068559318b1a05..f996d14766d9dafda74cebd88ad02154133061b5 100644 (file)
@@ -35,7 +35,7 @@
 typedef void (*wm8958_micdet_cb)(u16 status, void *data);
 
 int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
-                     int micbias, int det, int shrt);
+                     int micbias);
 int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
                      wm8958_micdet_cb cb, void *cb_data);
 
@@ -46,8 +46,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec);
 
 struct wm8994_micdet {
        struct snd_soc_jack *jack;
-       int det;
-       int shrt;
+       bool detecting;
 };
 
 /* codec private data */
index c8aada597d7049cfc756cf887a886bd9f30cd54b..28c89b094c6ee6a5af57bab43a4a7f1c7d84f1f7 100644 (file)
@@ -2047,7 +2047,6 @@ static int wm8995_probe(struct snd_soc_codec *codec)
        int i;
        int ret;
 
-       codec->dapm.idle_bias_off = 1;
        wm8995 = snd_soc_codec_get_drvdata(codec);
        wm8995->codec = codec;
 
@@ -2137,7 +2136,7 @@ static int wm8995_probe(struct snd_soc_codec *codec)
 
        wm8995_update_class_w(codec);
 
-       snd_soc_add_controls(codec, wm8995_snd_controls,
+       snd_soc_add_codec_controls(codec, wm8995_snd_controls,
                             ARRAY_SIZE(wm8995_snd_controls));
        snd_soc_dapm_new_controls(&codec->dapm, wm8995_dapm_widgets,
                                  ARRAY_SIZE(wm8995_dapm_widgets));
@@ -2241,6 +2240,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8995 = {
        .suspend = wm8995_suspend,
        .resume = wm8995_resume,
        .set_bias_level = wm8995_set_bias_level,
+       .idle_bias_off = true,
 };
 
 static struct regmap_config wm8995_regmap = {
index 61f7daa4d0e681571222fce0910ab148e8b0f18a..aba144f69946e12eb0f99230102c9a0da0cef9e1 100644 (file)
@@ -73,7 +73,6 @@ struct wm8996_priv {
 
        struct regulator_bulk_data supplies[WM8996_NUM_SUPPLIES];
        struct notifier_block disable_nb[WM8996_NUM_SUPPLIES];
-       struct regulator *cpvdd;
        int bg_ena;
 
        struct wm8996_pdata pdata;
@@ -90,6 +89,7 @@ struct wm8996_priv {
        struct snd_soc_jack *jack;
        bool detecting;
        bool jack_mic;
+       int jack_flips;
        wm8996_polarity_fn polarity_cb;
 
 #ifdef CONFIG_GPIOLIB
@@ -792,29 +792,18 @@ static int bg_event(struct snd_soc_dapm_widget *w,
 static int cp_event(struct snd_soc_dapm_widget *w,
                    struct snd_kcontrol *kcontrol, int event)
 {
-       struct snd_soc_codec *codec = w->codec;
-       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
        int ret = 0;
 
        switch (event) {
-       case SND_SOC_DAPM_PRE_PMU:
-               ret = regulator_enable(wm8996->cpvdd);
-               if (ret != 0)
-                       dev_err(codec->dev, "Failed to enable CPVDD: %d\n",
-                               ret);
-               break;
        case SND_SOC_DAPM_POST_PMU:
                msleep(5);
                break;
-       case SND_SOC_DAPM_POST_PMD:
-               regulator_disable_deferred(wm8996->cpvdd, 20);
-               break;
        default:
                BUG();
                ret = -EINVAL;
        }
 
-       return ret;
+       return 0;
 }
 
 static int rmv_short_event(struct snd_soc_dapm_widget *w,
@@ -1116,12 +1105,12 @@ SND_SOC_DAPM_INPUT("IN2RP"),
 SND_SOC_DAPM_INPUT("DMIC1DAT"),
 SND_SOC_DAPM_INPUT("DMIC2DAT"),
 
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
 SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event,
-                     SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
-                     SND_SOC_DAPM_POST_PMD),
+                     SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event,
                    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0),
@@ -1280,6 +1269,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
        { "AIFCLK", NULL, "SYSCLK" },
        { "SYSDSPCLK", NULL, "SYSCLK" },
        { "Charge Pump", NULL, "SYSCLK" },
+       { "Charge Pump", NULL, "CPVDD" },
 
        { "MICB1", NULL, "LDO2" },
        { "MICB1", NULL, "MICB1 Audio" },
@@ -1719,6 +1709,7 @@ static bool wm8996_volatile_register(struct device *dev, unsigned int reg)
 static int wm8996_reset(struct wm8996_priv *wm8996)
 {
        if (wm8996->pdata.ldo_ena > 0) {
+               gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1);
                gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
                return 0;
        } else {
@@ -2438,6 +2429,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
        wm8996->jack = jack;
        wm8996->detecting = true;
        wm8996->polarity_cb = polarity_cb;
+       wm8996->jack_flips = 0;
 
        if (wm8996->polarity_cb)
                wm8996->polarity_cb(codec, 0);
@@ -2553,6 +2545,19 @@ static void wm8996_hpdet_start(struct snd_soc_codec *codec)
                            WM8996_HP_POLL, WM8996_HP_POLL);
 }
 
+static void wm8996_report_headphone(struct snd_soc_codec *codec)
+{
+       dev_dbg(codec->dev, "Headphone detected\n");
+       wm8996_hpdet_start(codec);
+
+       /* Increase the detection rate a bit for responsiveness. */
+       snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
+                           WM8996_MICD_RATE_MASK |
+                           WM8996_MICD_BIAS_STARTTIME_MASK,
+                           7 << WM8996_MICD_RATE_SHIFT |
+                           7 << WM8996_MICD_BIAS_STARTTIME_SHIFT);
+}
+
 static void wm8996_micd(struct snd_soc_codec *codec)
 {
        struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
@@ -2572,6 +2577,7 @@ static void wm8996_micd(struct snd_soc_codec *codec)
                dev_dbg(codec->dev, "Jack removal detected\n");
                wm8996->jack_mic = false;
                wm8996->detecting = true;
+               wm8996->jack_flips = 0;
                snd_soc_jack_report(wm8996->jack, 0,
                                    SND_JACK_LINEOUT | SND_JACK_HEADSET |
                                    SND_JACK_BTN_0);
@@ -2612,9 +2618,17 @@ static void wm8996_micd(struct snd_soc_codec *codec)
        /* If we detected a lower impedence during initial startup
         * then we probably have the wrong polarity, flip it.  Don't
         * do this for the lowest impedences to speed up detection of
-        * plain headphones.
+        * plain headphones.  If both polarities report a low
+        * impedence then give up and report headphones.
         */
        if (wm8996->detecting && (val & 0x3f0)) {
+               wm8996->jack_flips++;
+
+               if (wm8996->jack_flips > 1) {
+                       wm8996_report_headphone(codec);
+                       return;
+               }
+
                reg = snd_soc_read(codec, WM8996_ACCESSORY_DETECT_MODE_2);
                reg ^= WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC |
                        WM8996_MICD_BIAS_SRC;
@@ -2641,17 +2655,7 @@ static void wm8996_micd(struct snd_soc_codec *codec)
                        snd_soc_jack_report(wm8996->jack, SND_JACK_BTN_0,
                                            SND_JACK_BTN_0);
                } else if (wm8996->detecting) {
-                       dev_dbg(codec->dev, "Headphone detected\n");
-                       wm8996_hpdet_start(codec);
-
-                       /* Increase the detection rate a bit for
-                        * responsiveness.
-                        */
-                       snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
-                                           WM8996_MICD_RATE_MASK |
-                                           WM8996_MICD_BIAS_STARTTIME_MASK,
-                                           7 << WM8996_MICD_RATE_SHIFT |
-                                           7 << WM8996_MICD_BIAS_STARTTIME_SHIFT);
+                       wm8996_report_headphone(codec);
                }
        }
 }
@@ -2768,7 +2772,7 @@ static void wm8996_retune_mobile_pdata(struct snd_soc_codec *codec)
        wm8996->retune_mobile_enum.max = wm8996->num_retune_mobile_texts;
        wm8996->retune_mobile_enum.texts = wm8996->retune_mobile_texts;
 
-       ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+       ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
        if (ret != 0)
                dev_err(codec->dev,
                        "Failed to add ReTune Mobile controls: %d\n", ret);
@@ -2791,7 +2795,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
        int ret;
        struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
        struct i2c_client *i2c = to_i2c_client(codec->dev);
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
        int i, irq_flags;
 
        wm8996->codec = codec;
@@ -2799,8 +2802,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
        init_completion(&wm8996->dcs_done);
        init_completion(&wm8996->fll_lock);
 
-       dapm->idle_bias_off = true;
-
        codec->control_data = wm8996->regmap;
 
        ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
@@ -2966,7 +2967,7 @@ static int wm8996_probe(struct snd_soc_codec *codec)
        if (wm8996->pdata.num_retune_mobile_cfgs)
                wm8996_retune_mobile_pdata(codec);
        else
-               snd_soc_add_controls(codec, wm8996_eq_controls,
+               snd_soc_add_codec_controls(codec, wm8996_eq_controls,
                                     ARRAY_SIZE(wm8996_eq_controls));
 
        /* If the TX LRCLK pins are not in LRCLK mode configure the
@@ -3038,7 +3039,6 @@ 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;
@@ -3054,6 +3054,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8996 = {
        .probe =        wm8996_probe,
        .remove =       wm8996_remove,
        .set_bias_level = wm8996_set_bias_level,
+       .idle_bias_off  = true,
        .seq_notifier = wm8996_seq_notifier,
        .controls = wm8996_snd_controls,
        .num_controls = ARRAY_SIZE(wm8996_snd_controls),
@@ -3087,6 +3088,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
                        .channels_max = 6,
                        .rates = WM8996_RATES,
                        .formats = WM8996_FORMATS,
+                       .sig_bits = 24,
                },
                .capture = {
                         .stream_name = "AIF1 Capture",
@@ -3094,6 +3096,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
                         .channels_max = 6,
                         .rates = WM8996_RATES,
                         .formats = WM8996_FORMATS,
+                        .sig_bits = 24,
                 },
                .ops = &wm8996_dai_ops,
        },
@@ -3105,6 +3108,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
                        .channels_max = 2,
                        .rates = WM8996_RATES,
                        .formats = WM8996_FORMATS,
+                       .sig_bits = 24,
                },
                .capture = {
                         .stream_name = "AIF2 Capture",
@@ -3112,6 +3116,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
                         .channels_max = 2,
                         .rates = WM8996_RATES,
                         .formats = WM8996_FORMATS,
+                       .sig_bits = 24,
                 },
                .ops = &wm8996_dai_ops,
        },
@@ -3149,25 +3154,18 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
        for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
                wm8996->supplies[i].supply = wm8996_supply_names[i];
 
-       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8996->supplies),
-                                wm8996->supplies);
+       ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8996->supplies),
+                                     wm8996->supplies);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
                goto err_gpio;
        }
 
-       wm8996->cpvdd = regulator_get(&i2c->dev, "CPVDD");
-       if (IS_ERR(wm8996->cpvdd)) {
-               ret = PTR_ERR(wm8996->cpvdd);
-               dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret);
-               goto err_get;
-       }
-
        ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies),
                                    wm8996->supplies);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
-               goto err_cpvdd;
+               goto err_gpio;
        }
 
        if (wm8996->pdata.ldo_ena > 0) {
@@ -3188,7 +3186,7 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
                goto err_regmap;
        }
        if (reg != 0x8915) {
-               dev_err(&i2c->dev, "Device is not a WM8996, ID %x\n", ret);
+               dev_err(&i2c->dev, "Device is not a WM8996, ID %x\n", reg);
                ret = -EINVAL;
                goto err_regmap;
        }
@@ -3229,10 +3227,6 @@ err_enable:
        if (wm8996->pdata.ldo_ena > 0)
                gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
        regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
-err_cpvdd:
-       regulator_put(wm8996->cpvdd);
-err_get:
-       regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
 err_gpio:
        if (wm8996->pdata.ldo_ena > 0)
                gpio_free(wm8996->pdata.ldo_ena);
@@ -3247,8 +3241,6 @@ static __devexit int wm8996_i2c_remove(struct i2c_client *client)
 
        snd_soc_unregister_codec(&client->dev);
        wm8996_free_gpio(wm8996);
-       regulator_put(wm8996->cpvdd);
-       regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
        regmap_exit(wm8996->regmap);
        if (wm8996->pdata.ldo_ena > 0) {
                gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
@@ -3273,25 +3265,7 @@ static struct i2c_driver wm8996_i2c_driver = {
        .id_table = wm8996_i2c_id,
 };
 
-static int __init wm8996_modinit(void)
-{
-       int ret;
-
-       ret = i2c_add_driver(&wm8996_i2c_driver);
-       if (ret != 0) {
-               printk(KERN_ERR "Failed to register WM8996 I2C driver: %d\n",
-                      ret);
-       }
-
-       return ret;
-}
-module_init(wm8996_modinit);
-
-static void __exit wm8996_exit(void)
-{
-       i2c_del_driver(&wm8996_i2c_driver);
-}
-module_exit(wm8996_exit);
+module_i2c_driver(wm8996_i2c_driver);
 
 MODULE_DESCRIPTION("ASoC WM8996 driver");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
index a6bab392700e94bfe138e8ae2322f1df47d3a70d..076c126ed9b1812b63cc186138859a43832a8b9e 100644 (file)
@@ -824,6 +824,8 @@ static const struct snd_soc_dapm_route wm9081_audio_paths[] = {
 static int wm9081_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
+       struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
+
        switch (level) {
        case SND_SOC_BIAS_ON:
                break;
@@ -841,6 +843,9 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec,
        case SND_SOC_BIAS_STANDBY:
                /* Initial cold start */
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       regcache_cache_only(wm9081->regmap, false);
+                       regcache_sync(wm9081->regmap);
+
                        /* Disable LINEOUT discharge */
                        snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL,
                                            WM9081_LINEOUT_DISCH, 0);
@@ -892,6 +897,8 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec,
                snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL,
                                    WM9081_LINEOUT_DISCH,
                                    WM9081_LINEOUT_DISCH);
+
+               regcache_cache_only(wm9081->regmap, true);
                break;
        }
 
@@ -1258,7 +1265,6 @@ static int wm9081_probe(struct snd_soc_codec *codec)
 {
        struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
        int ret;
-       u16 reg;
 
        codec->control_data = wm9081->regmap;
 
@@ -1268,16 +1274,6 @@ static int wm9081_probe(struct snd_soc_codec *codec)
                return ret;
        }
 
-       reg = 0;
-       if (wm9081->pdata.irq_high)
-               reg |= WM9081_IRQ_POL;
-       if (!wm9081->pdata.irq_cmos)
-               reg |= WM9081_IRQ_OP_CTRL;
-       snd_soc_update_bits(codec, WM9081_INTERRUPT_CONTROL,
-                           WM9081_IRQ_POL | WM9081_IRQ_OP_CTRL, reg);
-
-       wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
        /* Enable zero cross by default */
        snd_soc_update_bits(codec, WM9081_ANALOGUE_LINEOUT,
                            WM9081_LINEOUTZC, WM9081_LINEOUTZC);
@@ -1287,7 +1283,7 @@ static int wm9081_probe(struct snd_soc_codec *codec)
        if (!wm9081->pdata.num_retune_configs) {
                dev_dbg(codec->dev,
                        "No ReTune Mobile data, using normal EQ\n");
-               snd_soc_add_controls(codec, wm9081_eq_controls,
+               snd_soc_add_codec_controls(codec, wm9081_eq_controls,
                                     ARRAY_SIZE(wm9081_eq_controls));
        }
 
@@ -1300,38 +1296,15 @@ static int wm9081_remove(struct snd_soc_codec *codec)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int wm9081_suspend(struct snd_soc_codec *codec)
-{
-       wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
-       return 0;
-}
-
-static int wm9081_resume(struct snd_soc_codec *codec)
-{
-       struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
-
-       regcache_sync(wm9081->regmap);
-
-       wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
-       return 0;
-}
-#else
-#define wm9081_suspend NULL
-#define wm9081_resume NULL
-#endif
-
 static struct snd_soc_codec_driver soc_codec_dev_wm9081 = {
        .probe =        wm9081_probe,
        .remove =       wm9081_remove,
-       .suspend =      wm9081_suspend,
-       .resume =       wm9081_resume,
 
        .set_sysclk = wm9081_set_sysclk,
        .set_bias_level = wm9081_set_bias_level,
 
+       .idle_bias_off = true,
+
        .controls         = wm9081_snd_controls,
        .num_controls     = ARRAY_SIZE(wm9081_snd_controls),
        .dapm_widgets     = wm9081_dapm_widgets,
@@ -1395,6 +1368,16 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
                memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev),
                       sizeof(wm9081->pdata));
 
+       reg = 0;
+       if (wm9081->pdata.irq_high)
+               reg |= WM9081_IRQ_POL;
+       if (!wm9081->pdata.irq_cmos)
+               reg |= WM9081_IRQ_OP_CTRL;
+       regmap_update_bits(wm9081->regmap, WM9081_INTERRUPT_CONTROL,
+                          WM9081_IRQ_POL | WM9081_IRQ_OP_CTRL, reg);
+
+       regcache_cache_only(wm9081->regmap, true);
+
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm9081, &wm9081_dai, 1);
        if (ret < 0)
@@ -1435,28 +1418,7 @@ static struct i2c_driver wm9081_i2c_driver = {
 };
 #endif
 
-static int __init wm9081_modinit(void)
-{
-       int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       ret = i2c_add_driver(&wm9081_i2c_driver);
-       if (ret != 0) {
-               printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n",
-                      ret);
-       }
-#endif
-       return ret;
-}
-module_init(wm9081_modinit);
-
-static void __exit wm9081_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       i2c_del_driver(&wm9081_i2c_driver);
-#endif
-}
-module_exit(wm9081_exit);
-
+module_i2c_driver(wm9081_i2c_driver);
 
 MODULE_DESCRIPTION("ASoC WM9081 driver");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
index 41ebe0dce772c908bcbcf53fdaff8264ac497e55..4b263b6edf13793908d3d1ab11c2630e5bee9054 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/device.h>
 #include <linux/i2c.h>
 #include <linux/delay.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/initval.h>
 #include <sound/soc.h>
 
 #include "wm9090.h"
 
-static const u16 wm9090_reg_defaults[] = {
-       0x9093,     /* R0   - Software Reset */
-       0x0006,     /* R1   - Power Management (1) */
-       0x6000,     /* R2   - Power Management (2) */
-       0x0000,     /* R3   - Power Management (3) */
-       0x0000,     /* R4 */
-       0x0000,     /* R5 */
-       0x01C0,     /* R6   - Clocking 1 */
-       0x0000,     /* R7 */
-       0x0000,     /* R8 */
-       0x0000,     /* R9 */
-       0x0000,     /* R10 */
-       0x0000,     /* R11 */
-       0x0000,     /* R12 */
-       0x0000,     /* R13 */
-       0x0000,     /* R14 */
-       0x0000,     /* R15 */
-       0x0000,     /* R16 */
-       0x0000,     /* R17 */
-       0x0000,     /* R18 */
-       0x0000,     /* R19 */
-       0x0000,     /* R20 */
-       0x0000,     /* R21 */
-       0x0003,     /* R22  - IN1 Line Control */
-       0x0003,     /* R23  - IN2 Line Control */
-       0x0083,     /* R24  - IN1 Line Input A Volume */
-       0x0083,     /* R25  - IN1  Line Input B Volume */
-       0x0083,     /* R26  - IN2 Line Input A Volume */
-       0x0083,     /* R27  - IN2 Line Input B Volume */
-       0x002D,     /* R28  - Left Output Volume */
-       0x002D,     /* R29  - Right Output Volume */
-       0x0000,     /* R30 */
-       0x0000,     /* R31 */
-       0x0000,     /* R32 */
-       0x0000,     /* R33 */
-       0x0100,     /* R34  - SPKMIXL Attenuation */
-       0x0000,     /* R35 */
-       0x0010,     /* R36  - SPKOUT Mixers */
-       0x0140,     /* R37  - ClassD3 */
-       0x0039,     /* R38  - Speaker Volume Left */
-       0x0000,     /* R39 */
-       0x0000,     /* R40 */
-       0x0000,     /* R41 */
-       0x0000,     /* R42 */
-       0x0000,     /* R43 */
-       0x0000,     /* R44 */
-       0x0000,     /* R45  - Output Mixer1 */
-       0x0000,     /* R46  - Output Mixer2 */
-       0x0100,     /* R47  - Output Mixer3 */
-       0x0100,     /* R48  - Output Mixer4 */
-       0x0000,     /* R49 */
-       0x0000,     /* R50 */
-       0x0000,     /* R51 */
-       0x0000,     /* R52 */
-       0x0000,     /* R53 */
-       0x0000,     /* R54  - Speaker Mixer */
-       0x0000,     /* R55 */
-       0x0000,     /* R56 */
-       0x000D,     /* R57  - AntiPOP2 */
-       0x0000,     /* R58 */
-       0x0000,     /* R59 */
-       0x0000,     /* R60 */
-       0x0000,     /* R61 */
-       0x0000,     /* R62 */
-       0x0000,     /* R63 */
-       0x0000,     /* R64 */
-       0x0000,     /* R65 */
-       0x0000,     /* R66 */
-       0x0000,     /* R67 */
-       0x0000,     /* R68 */
-       0x0000,     /* R69 */
-       0x0000,     /* R70  - Write Sequencer 0 */
-       0x0000,     /* R71  - Write Sequencer 1 */
-       0x0000,     /* R72  - Write Sequencer 2 */
-       0x0000,     /* R73  - Write Sequencer 3 */
-       0x0000,     /* R74  - Write Sequencer 4 */
-       0x0000,     /* R75  - Write Sequencer 5 */
-       0x1F25,     /* R76  - Charge Pump 1 */
-       0x0000,     /* R77 */
-       0x0000,     /* R78 */
-       0x0000,     /* R79 */
-       0x0000,     /* R80 */
-       0x0000,     /* R81 */
-       0x0000,     /* R82 */
-       0x0000,     /* R83 */
-       0x0000,     /* R84  - DC Servo 0 */
-       0x054A,     /* R85  - DC Servo 1 */
-       0x0000,     /* R86 */
-       0x0000,     /* R87  - DC Servo 3 */
-       0x0000,     /* R88  - DC Servo Readback 0 */
-       0x0000,     /* R89  - DC Servo Readback 1 */
-       0x0000,     /* R90  - DC Servo Readback 2 */
-       0x0000,     /* R91 */
-       0x0000,     /* R92 */
-       0x0000,     /* R93 */
-       0x0000,     /* R94 */
-       0x0000,     /* R95 */
-       0x0100,     /* R96  - Analogue HP 0 */
-       0x0000,     /* R97 */
-       0x8640,     /* R98  - AGC Control 0 */
-       0xC000,     /* R99  - AGC Control 1 */
-       0x0200,     /* R100 - AGC Control 2 */
+static const struct reg_default wm9090_reg_defaults[] = {
+       { 1,  0x0006 },     /* R1   - Power Management (1) */
+       { 2,  0x6000 },     /* R2   - Power Management (2) */
+       { 3,  0x0000 },     /* R3   - Power Management (3) */
+       { 6,  0x01C0 },     /* R6   - Clocking 1 */
+       { 22, 0x0003 },     /* R22  - IN1 Line Control */
+       { 23, 0x0003 },     /* R23  - IN2 Line Control */
+       { 24, 0x0083 },     /* R24  - IN1 Line Input A Volume */
+       { 25, 0x0083 },     /* R25  - IN1  Line Input B Volume */
+       { 26, 0x0083 },     /* R26  - IN2 Line Input A Volume */
+       { 27, 0x0083 },     /* R27  - IN2 Line Input B Volume */
+       { 28, 0x002D },     /* R28  - Left Output Volume */
+       { 29, 0x002D },     /* R29  - Right Output Volume */
+       { 34, 0x0100 },     /* R34  - SPKMIXL Attenuation */
+       { 35, 0x0010 },     /* R36  - SPKOUT Mixers */
+       { 37, 0x0140 },     /* R37  - ClassD3 */
+       { 38, 0x0039 },     /* R38  - Speaker Volume Left */
+       { 45, 0x0000 },     /* R45  - Output Mixer1 */
+       { 46, 0x0000 },     /* R46  - Output Mixer2 */
+       { 47, 0x0100 },     /* R47  - Output Mixer3 */
+       { 48, 0x0100 },     /* R48  - Output Mixer4 */
+       { 54, 0x0000 },     /* R54  - Speaker Mixer */
+       { 57, 0x000D },     /* R57  - AntiPOP2 */
+       { 70, 0x0000 },     /* R70  - Write Sequencer 0 */
+       { 71, 0x0000 },     /* R71  - Write Sequencer 1 */
+       { 72, 0x0000 },     /* R72  - Write Sequencer 2 */
+       { 73, 0x0000 },     /* R73  - Write Sequencer 3 */
+       { 74, 0x0000 },     /* R74  - Write Sequencer 4 */
+       { 75, 0x0000 },     /* R75  - Write Sequencer 5 */
+       { 76, 0x1F25 },     /* R76  - Charge Pump 1 */
+       { 85, 0x054A },     /* R85  - DC Servo 1 */
+       { 87, 0x0000 },     /* R87  - DC Servo 3 */
+       { 96, 0x0100 },     /* R96  - Analogue HP 0 */
+       { 98, 0x8640 },     /* R98  - AGC Control 0 */
+       { 99, 0xC000 },     /* R99  - AGC Control 1 */
+       { 100, 0x0200 },     /* R100 - AGC Control 2 */
 };
 
 /* This struct is used to save the context */
 struct wm9090_priv {
        struct wm9090_platform_data pdata;
+       struct regmap *regmap;
 };
 
-static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm9090_volatile(struct device *dev, unsigned int reg)
 {
        switch (reg) {
        case WM9090_SOFTWARE_RESET:
@@ -150,10 +86,60 @@ static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg)
        case WM9090_DC_SERVO_READBACK_0:
        case WM9090_DC_SERVO_READBACK_1:
        case WM9090_DC_SERVO_READBACK_2:
-               return 1;
+               return true;
 
        default:
-               return 0;
+               return false;
+       }
+}
+
+static bool wm9090_readable(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM9090_SOFTWARE_RESET:
+       case WM9090_POWER_MANAGEMENT_1:
+       case WM9090_POWER_MANAGEMENT_2:
+       case WM9090_POWER_MANAGEMENT_3:
+       case WM9090_CLOCKING_1:
+       case WM9090_IN1_LINE_CONTROL:
+       case WM9090_IN2_LINE_CONTROL:
+       case WM9090_IN1_LINE_INPUT_A_VOLUME:
+       case WM9090_IN1_LINE_INPUT_B_VOLUME:
+       case WM9090_IN2_LINE_INPUT_A_VOLUME:
+       case WM9090_IN2_LINE_INPUT_B_VOLUME:
+       case WM9090_LEFT_OUTPUT_VOLUME:
+       case WM9090_RIGHT_OUTPUT_VOLUME:
+       case WM9090_SPKMIXL_ATTENUATION:
+       case WM9090_SPKOUT_MIXERS:
+       case WM9090_CLASSD3:
+       case WM9090_SPEAKER_VOLUME_LEFT:
+       case WM9090_OUTPUT_MIXER1:
+       case WM9090_OUTPUT_MIXER2:
+       case WM9090_OUTPUT_MIXER3:
+       case WM9090_OUTPUT_MIXER4:
+       case WM9090_SPEAKER_MIXER:
+       case WM9090_ANTIPOP2:
+       case WM9090_WRITE_SEQUENCER_0:
+       case WM9090_WRITE_SEQUENCER_1:
+       case WM9090_WRITE_SEQUENCER_2:
+       case WM9090_WRITE_SEQUENCER_3:
+       case WM9090_WRITE_SEQUENCER_4:
+       case WM9090_WRITE_SEQUENCER_5:
+       case WM9090_CHARGE_PUMP_1:
+       case WM9090_DC_SERVO_0:
+       case WM9090_DC_SERVO_1:
+       case WM9090_DC_SERVO_3:
+       case WM9090_DC_SERVO_READBACK_0:
+       case WM9090_DC_SERVO_READBACK_1:
+       case WM9090_DC_SERVO_READBACK_2:
+       case WM9090_ANALOGUE_HP_0:
+       case WM9090_AGC_CONTROL_0:
+       case WM9090_AGC_CONTROL_1:
+       case WM9090_AGC_CONTROL_2:
+               return true;
+
+       default:
+               return false;
        }
 }
 
@@ -447,7 +433,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
 
        snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-       snd_soc_add_controls(codec, wm9090_controls,
+       snd_soc_add_codec_controls(codec, wm9090_controls,
                             ARRAY_SIZE(wm9090_controls));
 
        if (wm9090->pdata.lin1_diff) {
@@ -456,7 +442,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
        } else {
                snd_soc_dapm_add_routes(dapm, audio_map_in1_se,
                                        ARRAY_SIZE(audio_map_in1_se));
-               snd_soc_add_controls(codec, wm9090_in1_se_controls,
+               snd_soc_add_codec_controls(codec, wm9090_in1_se_controls,
                                     ARRAY_SIZE(wm9090_in1_se_controls));
        }
 
@@ -466,7 +452,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
        } else {
                snd_soc_dapm_add_routes(dapm, audio_map_in2_se,
                                        ARRAY_SIZE(audio_map_in2_se));
-               snd_soc_add_controls(codec, wm9090_in2_se_controls,
+               snd_soc_add_codec_controls(codec, wm9090_in2_se_controls,
                                     ARRAY_SIZE(wm9090_in2_se_controls));
        }
 
@@ -492,8 +478,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
 static int wm9090_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
-       u16 *reg_cache = codec->reg_cache;
-       int i, ret;
+       struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
 
        switch (level) {
        case SND_SOC_BIAS_ON:
@@ -513,7 +498,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
        case SND_SOC_BIAS_STANDBY:
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
                        /* Restore the register cache */
-                       snd_soc_cache_sync(codec);
+                       regcache_sync(wm9090->regmap);
                }
 
                /* We keep VMID off during standby since the combination of
@@ -537,26 +522,16 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
 
 static int wm9090_probe(struct snd_soc_codec *codec)
 {
+       struct wm9090_priv *wm9090 = dev_get_drvdata(codec->dev);
        int ret;
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+       codec->control_data = wm9090->regmap;
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
        }
 
-       ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET);
-       if (ret < 0)
-               return ret;
-       if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) {
-               dev_err(codec->dev, "Device is not a WM9090, ID=%x\n", ret);
-               return -EINVAL;
-       }
-
-       ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0);
-       if (ret < 0)
-               return ret;
-
        /* Configure some defaults; they will be written out when we
         * bring the bias up.
         */
@@ -624,16 +599,27 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9090 = {
        .suspend =      wm9090_suspend,
        .resume =       wm9090_resume,
        .set_bias_level = wm9090_set_bias_level,
-       .reg_cache_size = (WM9090_MAX_REGISTER + 1),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm9090_reg_defaults,
-       .volatile_register = wm9090_volatile,
 };
 
+static const struct regmap_config wm9090_regmap = {
+       .reg_bits = 8,
+       .val_bits = 16,
+
+       .max_register = WM9090_MAX_REGISTER,
+       .volatile_reg = wm9090_volatile,
+       .readable_reg = wm9090_readable,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = wm9090_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm9090_reg_defaults),
+};
+
+
 static int wm9090_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct wm9090_priv *wm9090;
+       unsigned int reg;
        int ret;
 
        wm9090 = devm_kzalloc(&i2c->dev, sizeof(*wm9090), GFP_KERNEL);
@@ -642,6 +628,26 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
        }
 
+       wm9090->regmap = regmap_init_i2c(i2c, &wm9090_regmap);
+       if (IS_ERR(wm9090->regmap)) {
+               ret = PTR_ERR(wm9090->regmap);
+               dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+               return ret;
+       }
+
+       ret = regmap_read(wm9090->regmap, WM9090_SOFTWARE_RESET, &reg);
+       if (ret < 0)
+               goto err;
+       if (reg != 0x9093) {
+               dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", reg);
+               ret = -ENODEV;
+               goto err;
+       }
+
+       ret = regmap_write(wm9090->regmap, WM9090_SOFTWARE_RESET, 0);
+       if (ret < 0)
+               goto err;
+
        if (i2c->dev.platform_data)
                memcpy(&wm9090->pdata, i2c->dev.platform_data,
                       sizeof(wm9090->pdata));
@@ -650,6 +656,15 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
 
        ret =  snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm9090,  NULL, 0);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+               goto err;
+       }
+
+       return 0;
+
+err:
+       regmap_exit(wm9090->regmap);
        return ret;
 }
 
@@ -658,6 +673,7 @@ static int __devexit wm9090_i2c_remove(struct i2c_client *i2c)
        struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c);
 
        snd_soc_unregister_codec(&i2c->dev);
+       regmap_exit(wm9090->regmap);
 
        return 0;
 }
index 40c92ead85a34526e4ce5d49c09e43595b8ae6c1..cacc6a86b46f05b1fd5ea54b08fae3d4ad7eb4be 100644 (file)
@@ -351,7 +351,7 @@ static int wm9705_soc_probe(struct snd_soc_codec *codec)
        if (ret)
                goto reset_err;
 
-       snd_soc_add_controls(codec, wm9705_snd_ac97_controls,
+       snd_soc_add_codec_controls(codec, wm9705_snd_ac97_controls,
                                ARRAY_SIZE(wm9705_snd_ac97_controls));
 
        return 0;
index b7b31f84c10b579432591d7d7caff670b1b6d9b7..b342ae50bcd6e294b5fe017f2bb7cdb77f4440ab 100644 (file)
 #include <sound/ac97_codec.h>
 #include <sound/initval.h>
 #include <sound/soc.h>
+#include <sound/tlv.h>
 #include "wm9712.h"
 
-#define WM9712_VERSION "0.4"
-
 static unsigned int ac97_read(struct snd_soc_codec *codec,
        unsigned int reg);
 static int ac97_write(struct snd_soc_codec *codec,
@@ -71,6 +70,9 @@ static const char *wm9712_rec_sel[] = {"Mic", "NC", "NC", "Speaker Mixer",
 static const char *wm9712_ng_type[] = {"Constant Gain", "Mute"};
 static const char *wm9712_diff_sel[] = {"Mic", "Line"};
 
+static const DECLARE_TLV_DB_SCALE(main_tlv, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 2000, 0);
+
 static const struct soc_enum wm9712_enum[] = {
 SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9712_alc_select),
 SOC_ENUM_SINGLE(AC97_VIDEO, 12, 4, wm9712_alc_mux),
@@ -149,9 +151,9 @@ SOC_ENUM("Capture Volume Steps", wm9712_enum[6]),
 SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
 SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
 
-SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
-SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
-SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
+SOC_SINGLE_TLV("Mic 1 Volume", AC97_MIC, 8, 31, 1, main_tlv),
+SOC_SINGLE_TLV("Mic 2 Volume", AC97_MIC, 0, 31, 1, main_tlv),
+SOC_SINGLE_TLV("Mic Boost Volume", AC97_MIC, 7, 1, 0, boost_tlv),
 };
 
 /* We have to create a fake left and right HP mixers because
@@ -619,8 +621,6 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)
 {
        int ret = 0;
 
-       printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION);
-
        ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
        if (ret < 0) {
                printk(KERN_ERR "wm9712: failed to register AC97 codec\n");
@@ -637,7 +637,7 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)
        ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
 
        wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-       snd_soc_add_controls(codec, wm9712_snd_ac97_controls,
+       snd_soc_add_codec_controls(codec, wm9712_snd_ac97_controls,
                                ARRAY_SIZE(wm9712_snd_ac97_controls));
 
        return 0;
index 2b8479bfcd93b822c48daa1f4e6797cf679d8cec..2d22cc70d5362d72c2372710597318e1cae61e6b 100644 (file)
@@ -1216,7 +1216,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)
        reg = ac97_read(codec, AC97_CD) & 0x7fff;
        ac97_write(codec, AC97_CD, reg);
 
-       snd_soc_add_controls(codec, wm9713_snd_ac97_controls,
+       snd_soc_add_codec_controls(codec, wm9713_snd_ac97_controls,
                                ARRAY_SIZE(wm9713_snd_ac97_controls));
 
        return 0;
index 8a68cea4a3ee6af7860ae65f4ccab119b10cc425..9742c666cd0ad89b8474715bbb2f1092055464b6 100644 (file)
@@ -500,6 +500,36 @@ static int earpiece_event(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
+static int lineout_event(struct snd_soc_dapm_widget *w,
+                        struct snd_kcontrol *control, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+       bool *flag;
+
+       switch (w->shift) {
+       case WM8993_LINEOUT1N_ENA_SHIFT:
+               flag = &hubs->lineout1n_ena;
+               break;
+       case WM8993_LINEOUT1P_ENA_SHIFT:
+               flag = &hubs->lineout1p_ena;
+               break;
+       case WM8993_LINEOUT2N_ENA_SHIFT:
+               flag = &hubs->lineout2n_ena;
+               break;
+       case WM8993_LINEOUT2P_ENA_SHIFT:
+               flag = &hubs->lineout2p_ena;
+               break;
+       default:
+               WARN(1, "Unknown line output");
+               return -EINVAL;
+       }
+
+       *flag = SND_SOC_DAPM_EVENT_ON(event);
+
+       return 0;
+}
+
 static const struct snd_kcontrol_new in1l_pga[] = {
 SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0),
 SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0),
@@ -656,10 +686,10 @@ SND_SOC_DAPM_MIXER("SPKR Boost", SND_SOC_NOPM, 0, 0,
                   right_speaker_boost, ARRAY_SIZE(right_speaker_boost)),
 
 SND_SOC_DAPM_SUPPLY("TSHUT", WM8993_POWER_MANAGEMENT_2, 14, 0, NULL, 0),
-SND_SOC_DAPM_PGA("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
-                NULL, 0),
-SND_SOC_DAPM_PGA("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
-                NULL, 0),
+SND_SOC_DAPM_OUT_DRV("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
+                    NULL, 0),
+SND_SOC_DAPM_OUT_DRV("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
+                    NULL, 0),
 
 SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0,
                   line1_mix, ARRAY_SIZE(line1_mix)),
@@ -675,14 +705,18 @@ SND_SOC_DAPM_MIXER("LINEOUT2N Mixer", SND_SOC_NOPM, 0, 0,
 SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0,
                   line2p_mix, ARRAY_SIZE(line2p_mix)),
 
-SND_SOC_DAPM_PGA("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
-                NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
-                NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
-                NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
-                NULL, 0),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
+                      NULL, 0, lineout_event,
+                    SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
+                      NULL, 0, lineout_event,
+                      SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
+                      NULL, 0, lineout_event,
+                      SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
+                      NULL, 0, lineout_event,
+                      SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 
 SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
 SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
@@ -901,7 +935,7 @@ int wm_hubs_add_analogue_controls(struct snd_soc_codec *codec)
                            WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU,
                            WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU);
 
-       snd_soc_add_controls(codec, analogue_snd_controls,
+       snd_soc_add_codec_controls(codec, analogue_snd_controls,
                             ARRAY_SIZE(analogue_snd_controls));
 
        snd_soc_dapm_new_controls(dapm, analogue_dapm_widgets,
@@ -949,6 +983,11 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
                                  int jd_scthr, int jd_thr, int micbias1_lvl,
                                  int micbias2_lvl)
 {
+       struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+
+       hubs->lineout1_se = !lineout1_diff;
+       hubs->lineout2_se = !lineout2_diff;
+
        if (!lineout1_diff)
                snd_soc_update_bits(codec, WM8993_LINE_MIXER1,
                                    WM8993_LINEOUT1_MODE,
@@ -958,12 +997,6 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
                                    WM8993_LINEOUT2_MODE,
                                    WM8993_LINEOUT2_MODE);
 
-       /* If the line outputs are differential then we aren't presenting
-        * VMID as an output and can disable it.
-        */
-       if (lineout1_diff && lineout2_diff)
-               codec->dapm.idle_bias_off = 1;
-
        if (lineout1fb)
                snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
                                    WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB);
@@ -984,6 +1017,74 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
 }
 EXPORT_SYMBOL_GPL(wm_hubs_handle_analogue_pdata);
 
+void wm_hubs_vmid_ena(struct snd_soc_codec *codec)
+{
+       struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+       int val = 0;
+
+       if (hubs->lineout1_se)
+               val |= WM8993_LINEOUT1N_ENA | WM8993_LINEOUT1P_ENA;
+
+       if (hubs->lineout2_se)
+               val |= WM8993_LINEOUT2N_ENA | WM8993_LINEOUT2P_ENA;
+
+       /* Enable the line outputs while we power up */
+       snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_3, val, val);
+}
+EXPORT_SYMBOL_GPL(wm_hubs_vmid_ena);
+
+void wm_hubs_set_bias_level(struct snd_soc_codec *codec,
+                           enum snd_soc_bias_level level)
+{
+       struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+       int val;
+
+       switch (level) {
+       case SND_SOC_BIAS_STANDBY:
+               /* Clamp the inputs to VMID while we ramp to charge caps */
+               snd_soc_update_bits(codec, WM8993_INPUTS_CLAMP_REG,
+                                   WM8993_INPUTS_CLAMP, WM8993_INPUTS_CLAMP);
+               break;
+
+       case SND_SOC_BIAS_ON:
+               /* Turn off any unneded single ended outputs */
+               val = 0;
+
+               if (hubs->lineout1_se && hubs->lineout1n_ena)
+                       val |= WM8993_LINEOUT1N_ENA;
+
+               if (hubs->lineout1_se && hubs->lineout1p_ena)
+                       val |= WM8993_LINEOUT1P_ENA;
+
+               if (hubs->lineout2_se && hubs->lineout2n_ena)
+                       val |= WM8993_LINEOUT2N_ENA;
+
+               if (hubs->lineout2_se && hubs->lineout2p_ena)
+                       val |= WM8993_LINEOUT2P_ENA;
+
+               snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_3,
+                                   WM8993_LINEOUT1N_ENA |
+                                   WM8993_LINEOUT1P_ENA |
+                                   WM8993_LINEOUT2N_ENA |
+                                   WM8993_LINEOUT2P_ENA,
+                                   val);
+
+               if (!hubs->lineout1n_ena && !hubs->lineout1p_ena &&
+                   !hubs->lineout2n_ena && !hubs->lineout2p_ena)
+                       snd_soc_update_bits(codec, WM8993_ANTIPOP1,
+                                           WM8993_LINEOUT_VMID_BUF_ENA, 0);
+
+               /* Remove the input clamps */
+               snd_soc_update_bits(codec, WM8993_INPUTS_CLAMP_REG,
+                                   WM8993_INPUTS_CLAMP, 0);
+               break;
+
+       default:
+               break;
+       }
+}
+EXPORT_SYMBOL_GPL(wm_hubs_set_bias_level);
+
 MODULE_DESCRIPTION("Shared support for Wolfson hubs products");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_LICENSE("GPL");
index c674c7a502a64e1d02889edfa839522686afdf9b..4140905c738144f0330904881ea92885ac5fb480 100644 (file)
@@ -33,6 +33,14 @@ struct wm_hubs_data {
        bool class_w;
        u16 class_w_dcs;
 
+       bool lineout1_se;
+       bool lineout1n_ena;
+       bool lineout1p_ena;
+
+       bool lineout2_se;
+       bool lineout2n_ena;
+       bool lineout2p_ena;
+
        bool dcs_done_irq;
        struct completion dcs_done;
 };
@@ -46,5 +54,8 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *,
                                         int micbias1_lvl, int micbias2_lvl);
 
 extern irqreturn_t wm_hubs_dcs_done(int irq, void *data);
+extern void wm_hubs_vmid_ena(struct snd_soc_codec *codec);
+extern void wm_hubs_set_bias_level(struct snd_soc_codec *codec,
+                                  enum snd_soc_bias_level level);
 
 #endif
index b26401f87b8509ea23eea61e1530f77eeb082377..97d77b298968fc714c4125fb48392afcd4bc60fe 100644 (file)
@@ -826,7 +826,7 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
        }
 }
 
-static u64 davinci_pcm_dmamask = 0xffffffff;
+static u64 davinci_pcm_dmamask = DMA_BIT_MASK(32);
 
 static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
@@ -837,7 +837,7 @@ static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd)
        if (!card->dev->dma_mask)
                card->dev->dma_mask = &davinci_pcm_dmamask;
        if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = 0xffffffff;
+               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = davinci_pcm_preallocate_dma_buffer(pcm,
index bae5cbbbd2b2d28c817c954f25e6dfc08faed22c..e01cb02abd3a91e17cfc9b3e22ee1df563feb22b 100644 (file)
@@ -85,9 +85,7 @@ static int __devinit edb93xx_probe(struct platform_device *pdev)
        struct snd_soc_card *card = &snd_soc_edb93xx;
        int ret;
 
-       ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97,
-                                EP93XX_SYSCON_I2SCLKDIV_ORIDE |
-                                EP93XX_SYSCON_I2SCLKDIV_SPOL);
+       ret = ep93xx_i2s_acquire();
        if (ret)
                return ret;
 
index de83904498730dbf43447cdcc4ef42cd34a9d0d7..32adca38b48b321900e1852e3dcc2abed92a16f0 100644 (file)
@@ -281,7 +281,7 @@ static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
        }
 }
 
-static u64 ep93xx_pcm_dmamask = 0xffffffff;
+static u64 ep93xx_pcm_dmamask = DMA_BIT_MASK(32);
 
 static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
@@ -292,7 +292,7 @@ static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd)
        if (!card->dev->dma_mask)
                card->dev->dma_mask = &ep93xx_pcm_dmamask;
        if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = 0xffffffff;
+               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
index ccae34a3f280dc08d8e33942389f46b27215ec87..a193cea3cf3cc73406a201db9e5aeb10b7772cc6 100644 (file)
@@ -103,9 +103,7 @@ static int __devinit snappercl15_probe(struct platform_device *pdev)
        struct snd_soc_card *card = &snd_soc_snappercl15;
        int ret;
 
-       ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97,
-                                EP93XX_SYSCON_I2SCLKDIV_ORIDE |
-                                EP93XX_SYSCON_I2SCLKDIV_SPOL);
+       ret = ep93xx_i2s_acquire();
        if (ret)
                return ret;
 
index 4f59bbaba48f4fcb8ae70e0ced615f19ab71404e..96bb92dd174c0ae14c0b262ae4f55fd6df2d3f70 100644 (file)
@@ -311,23 +311,23 @@ static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd)
         * should allocate a DMA buffer only for the streams that are valid.
         */
 
-       if (pcm->streams[0].substream) {
+       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
                        fsl_dma_hardware.buffer_bytes_max,
-                       &pcm->streams[0].substream->dma_buffer);
+                       &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
                if (ret) {
                        dev_err(card->dev, "can't alloc playback dma buffer\n");
                        return ret;
                }
        }
 
-       if (pcm->streams[1].substream) {
+       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
                ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
                        fsl_dma_hardware.buffer_bytes_max,
-                       &pcm->streams[1].substream->dma_buffer);
+                       &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer);
                if (ret) {
                        dev_err(card->dev, "can't alloc capture dma buffer\n");
-                       snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
+                       snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
                        return ret;
                }
        }
index e7803d34c425a35a8be366ccd5b9324b8eb41cad..33adbf1e40d644f3603555d0c62b55431de28c82 100644 (file)
@@ -298,7 +298,7 @@ static struct snd_pcm_ops psc_dma_ops = {
        .hw_params      = psc_dma_hw_params,
 };
 
-static u64 psc_dma_dmamask = 0xffffffff;
+static u64 psc_dma_dmamask = DMA_BIT_MASK(32);
 static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
@@ -314,18 +314,18 @@ static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
        if (!card->dev->dma_mask)
                card->dev->dma_mask = &psc_dma_dmamask;
        if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = 0xffffffff;
+               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
-       if (pcm->streams[0].substream) {
+       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
-                               size, &pcm->streams[0].substream->dma_buffer);
+                               size, &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
                if (rc)
                        goto playback_alloc_err;
        }
 
-       if (pcm->streams[1].substream) {
+       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
                rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
-                               size, &pcm->streams[1].substream->dma_buffer);
+                               size, &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer);
                if (rc)
                        goto capture_alloc_err;
        }
@@ -336,8 +336,8 @@ static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
        return 0;
 
  capture_alloc_err:
-       if (pcm->streams[0].substream)
-               snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
+       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
+               snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
 
  playback_alloc_err:
        dev_err(card->dev, "Cannot allocate buffer(s)\n");
index 3c2eed9094d57b135594ae3cd444c498cf19459a..155899c08c0c4c15ddcdf5fe3e6874463c6cb578 100644 (file)
 #include <linux/moduleparam.h>
 #include <linux/device.h>
 #include <linux/i2c.h>
+#include <linux/gpio.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
+#include <sound/tlv.h>
 #include <asm/mach-types.h>
 #include <mach/audmux.h>
+#include <mach/iomux-mx27.h>
 
 #include "../codecs/tlv320aic32x4.h"
 #include "imx-ssi.h"
 
+#define MX27VIS_AMP_GAIN       0
+#define MX27VIS_AMP_MUTE       1
+
+#define MX27VIS_PIN_G0         (GPIO_PORTF + 9)
+#define MX27VIS_PIN_G1         (GPIO_PORTF + 8)
+#define MX27VIS_PIN_SDL                (GPIO_PORTE + 5)
+#define MX27VIS_PIN_SDR                (GPIO_PORTF + 7)
+
+static int mx27vis_amp_gain;
+static int mx27vis_amp_mute;
+
+static const int mx27vis_amp_pins[] = {
+       MX27VIS_PIN_G0 | GPIO_GPIO | GPIO_OUT,
+       MX27VIS_PIN_G1 | GPIO_GPIO | GPIO_OUT,
+       MX27VIS_PIN_SDL | GPIO_GPIO | GPIO_OUT,
+       MX27VIS_PIN_SDR | GPIO_GPIO | GPIO_OUT,
+};
+
 static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream,
                            struct snd_pcm_hw_params *params)
 {
@@ -74,6 +95,76 @@ static struct snd_soc_ops mx27vis_aic32x4_snd_ops = {
        .hw_params      = mx27vis_aic32x4_hw_params,
 };
 
+static int mx27vis_amp_set(struct snd_kcontrol *kcontrol,
+                           struct snd_ctl_elem_value *ucontrol)
+{
+       struct soc_mixer_control *mc =
+               (struct soc_mixer_control *)kcontrol->private_value;
+       int value = ucontrol->value.integer.value[0];
+       unsigned int reg = mc->reg;
+       int max = mc->max;
+
+       if (value > max)
+               return -EINVAL;
+
+       switch (reg) {
+       case MX27VIS_AMP_GAIN:
+               gpio_set_value(MX27VIS_PIN_G0, value & 1);
+               gpio_set_value(MX27VIS_PIN_G1, value >> 1);
+               mx27vis_amp_gain = value;
+               break;
+       case MX27VIS_AMP_MUTE:
+               gpio_set_value(MX27VIS_PIN_SDL, value & 1);
+               gpio_set_value(MX27VIS_PIN_SDR, value >> 1);
+               mx27vis_amp_mute = value;
+               break;
+       }
+       return 0;
+}
+
+static int mx27vis_amp_get(struct snd_kcontrol *kcontrol,
+                           struct snd_ctl_elem_value *ucontrol)
+{
+       struct soc_mixer_control *mc =
+               (struct soc_mixer_control *)kcontrol->private_value;
+       unsigned int reg = mc->reg;
+
+       switch (reg) {
+       case MX27VIS_AMP_GAIN:
+               ucontrol->value.integer.value[0] = mx27vis_amp_gain;
+               break;
+       case MX27VIS_AMP_MUTE:
+               ucontrol->value.integer.value[0] = mx27vis_amp_mute;
+               break;
+       }
+       return 0;
+}
+
+/* From 6dB to 24dB in steps of 6dB */
+static const DECLARE_TLV_DB_SCALE(mx27vis_amp_tlv, 600, 600, 0);
+
+static const struct snd_kcontrol_new mx27vis_aic32x4_controls[] = {
+       SOC_DAPM_PIN_SWITCH("External Mic"),
+       SOC_SINGLE_EXT_TLV("LO Ext Boost", MX27VIS_AMP_GAIN, 0, 3, 0,
+                      mx27vis_amp_get, mx27vis_amp_set, mx27vis_amp_tlv),
+       SOC_DOUBLE_EXT("LO Ext Mute Switch", MX27VIS_AMP_MUTE, 0, 1, 1, 0,
+                      mx27vis_amp_get, mx27vis_amp_set),
+};
+
+static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = {
+       SND_SOC_DAPM_MIC("External Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = {
+       {"Mic Bias", NULL, "External Mic"},
+       {"IN1_R", NULL, "Mic Bias"},
+       {"IN2_R", NULL, "Mic Bias"},
+       {"IN3_R", NULL, "Mic Bias"},
+       {"IN1_L", NULL, "Mic Bias"},
+       {"IN2_L", NULL, "Mic Bias"},
+       {"IN3_L", NULL, "Mic Bias"},
+};
+
 static struct snd_soc_dai_link mx27vis_aic32x4_dai = {
        .name           = "tlv320aic32x4",
        .stream_name    = "TLV320AIC32X4",
@@ -89,6 +180,12 @@ static struct snd_soc_card mx27vis_aic32x4 = {
        .owner          = THIS_MODULE,
        .dai_link       = &mx27vis_aic32x4_dai,
        .num_links      = 1,
+       .controls       = mx27vis_aic32x4_controls,
+       .num_controls   = ARRAY_SIZE(mx27vis_aic32x4_controls),
+       .dapm_widgets   = aic32x4_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(aic32x4_dapm_widgets),
+       .dapm_routes    = aic32x4_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes),
 };
 
 static struct platform_device *mx27vis_aic32x4_snd_device;
@@ -122,6 +219,13 @@ static int __init mx27vis_aic32x4_init(void)
                        MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
        );
 
+       ret = mxc_gpio_setup_multiple_pins(mx27vis_amp_pins,
+                       ARRAY_SIZE(mx27vis_amp_pins), "MX27VIS_AMP");
+       if (ret) {
+               printk(KERN_ERR "ASoC: unable to setup gpios\n");
+               platform_device_put(mx27vis_aic32x4_snd_device);
+       }
+
        return ret;
 }
 
index 0097c3b13a1a31a1e1d48c99d71d62d3db72281d..e8aaff18d7cc4c9b18ed2d178cc69c2ddc77a6cb 100644 (file)
@@ -91,56 +91,52 @@ static struct snd_soc_card qi_lb60 = {
        .num_dapm_routes = ARRAY_SIZE(qi_lb60_routes),
 };
 
-static struct platform_device *qi_lb60_snd_device;
-
 static const struct gpio qi_lb60_gpios[] = {
        { QI_LB60_SND_GPIO, GPIOF_OUT_INIT_LOW, "SND" },
        { QI_LB60_AMP_GPIO, GPIOF_OUT_INIT_LOW, "AMP" },
 };
 
-static int __init qi_lb60_init(void)
+static int __devinit qi_lb60_probe(struct platform_device *pdev)
 {
+       struct snd_soc_card *card = &qi_lb60;
        int ret;
 
-       qi_lb60_snd_device = platform_device_alloc("soc-audio", -1);
-
-       if (!qi_lb60_snd_device)
-               return -ENOMEM;
-
        ret = gpio_request_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
-       if (ret) {
-               pr_err("qi_lb60 snd: Failed to request gpios: %d\n", ret);
-               goto err_device_put;
-       }
+       if (ret)
+               return ret;
 
-       platform_set_drvdata(qi_lb60_snd_device, &qi_lb60);
+       card->dev = &pdev->dev;
 
-       ret = platform_device_add(qi_lb60_snd_device);
+       ret = snd_soc_register_card(card);
        if (ret) {
-               pr_err("qi_lb60 snd: Failed to add snd soc device: %d\n", ret);
-               goto err_unset_pdata;
+               dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+                       ret);
+               gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
        }
-
-        return 0;
-
-err_unset_pdata:
-       platform_set_drvdata(qi_lb60_snd_device, NULL);
-/*err_gpio_free_array:*/
-       gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
-err_device_put:
-       platform_device_put(qi_lb60_snd_device);
-
        return ret;
 }
-module_init(qi_lb60_init);
 
-static void __exit qi_lb60_exit(void)
+static int __devexit qi_lb60_remove(struct platform_device *pdev)
 {
-       platform_device_unregister(qi_lb60_snd_device);
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_card(card);
        gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
+       return 0;
 }
-module_exit(qi_lb60_exit);
+
+static struct platform_driver qi_lb60_driver = {
+       .driver         = {
+               .name   = "qi-lb60-audio",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = qi_lb60_probe,
+       .remove         = __devexit_p(qi_lb60_remove),
+};
+
+module_platform_driver(qi_lb60_driver);
 
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("ALSA SoC QI LB60 Audio support");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qi-lb60-audio");
index d038540271285f90b8d093643fcfeb7de07cc8b6..b9f16598324c9b4b85373b6f55d785011c4d8b68 100644 (file)
@@ -55,7 +55,7 @@ static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
        .fifo_size              = 0,
 };
 
-static u64 kirkwood_dma_dmamask = 0xFFFFFFFFUL;
+static u64 kirkwood_dma_dmamask = DMA_BIT_MASK(32);
 
 static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
 {
@@ -324,7 +324,7 @@ static int kirkwood_dma_new(struct snd_soc_pcm_runtime *rtd)
        if (!card->dev->dma_mask)
                card->dev->dma_mask = &kirkwood_dma_dmamask;
        if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = 0xffffffff;
+               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = kirkwood_dma_preallocate_dma_buffer(pcm,
index 55d2ed3df30d6296dfaad03857e64ddde5505775..80bd59c33be4cb2d87297f5a47be17da014ea4e1 100644 (file)
@@ -71,41 +71,41 @@ static struct snd_soc_card openrd_client = {
        .num_links = ARRAY_SIZE(openrd_client_dai),
 };
 
-static struct platform_device *openrd_client_snd_device;
-
-static int __init openrd_client_init(void)
+static int __devinit openrd_probe(struct platform_device *pdev)
 {
+       struct snd_soc_card *card = &openrd_client;
        int ret;
 
-       if (!machine_is_openrd_client() && !machine_is_openrd_ultimate())
-               return 0;
-
-       openrd_client_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!openrd_client_snd_device)
-               return -ENOMEM;
-
-       platform_set_drvdata(openrd_client_snd_device,
-                       &openrd_client);
-
-       ret = platform_device_add(openrd_client_snd_device);
-       if (ret) {
-               printk(KERN_ERR "%s: platform_device_add failed\n", __func__);
-               platform_device_put(openrd_client_snd_device);
-       }
+       card->dev = &pdev->dev;
 
+       ret = snd_soc_register_card(card);
+       if (ret)
+               dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+                       ret);
        return ret;
 }
 
-static void __exit openrd_client_exit(void)
+static int __devexit openrd_remove(struct platform_device *pdev)
 {
-       platform_device_unregister(openrd_client_snd_device);
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_card(card);
+       return 0;
 }
 
-module_init(openrd_client_init);
-module_exit(openrd_client_exit);
+static struct platform_driver openrd_driver = {
+       .driver         = {
+               .name   = "openrd-client-audio",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = openrd_probe,
+       .remove         = __devexit_p(openrd_remove),
+};
+
+module_platform_driver(openrd_driver);
 
 /* Module information */
 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("ALSA SoC OpenRD Client");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:soc-audio");
+MODULE_ALIAS("platform:openrd-client-audio");
index b47cc4e9b746a39dc7d91e86244d430c03b0fde3..f8983635f7efc21c3f69544c5329900745dbe2a4 100644 (file)
@@ -80,7 +80,6 @@ static struct snd_soc_dai_link t5325_dai[] = {
 },
 };
 
-
 static struct snd_soc_card t5325 = {
        .name = "t5325",
        .owner = THIS_MODULE,
@@ -93,38 +92,40 @@ static struct snd_soc_card t5325 = {
        .num_dapm_routes = ARRAY_SIZE(t5325_route),
 };
 
-static struct platform_device *t5325_snd_device;
-
-static int __init t5325_init(void)
+static int __devinit t5325_probe(struct platform_device *pdev)
 {
+       struct snd_soc_card *card = &t5325;
        int ret;
 
-       if (!machine_is_t5325())
-               return 0;
-
-       t5325_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!t5325_snd_device)
-               return -ENOMEM;
-
-       platform_set_drvdata(t5325_snd_device,
-                       &t5325);
-
-       ret = platform_device_add(t5325_snd_device);
-       if (ret) {
-               printk(KERN_ERR "%s: platform_device_add failed\n", __func__);
-               platform_device_put(t5325_snd_device);
-       }
+       card->dev = &pdev->dev;
 
+       ret = snd_soc_register_card(card);
+       if (ret)
+               dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+                       ret);
        return ret;
 }
-module_init(t5325_init);
 
-static void __exit t5325_exit(void)
+static int __devexit t5325_remove(struct platform_device *pdev)
 {
-       platform_device_unregister(t5325_snd_device);
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_card(card);
+       return 0;
 }
-module_exit(t5325_exit);
+
+static struct platform_driver t5325_driver = {
+       .driver         = {
+               .name   = "t5325-audio",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = t5325_probe,
+       .remove         = __devexit_p(t5325_remove),
+};
+
+module_platform_driver(t5325_driver);
 
 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("ALSA SoC t5325 audio client");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:t5325-audio");
index 6f77eef0f13164b08507c15a1c554e9a1f35c9dc..2937e54da49ef596f52243cbce586a4cbba8712b 100644 (file)
@@ -235,7 +235,7 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
        snd_soc_dapm_enable_pin(dapm, "Headphones");
        snd_soc_dapm_enable_pin(dapm, "Mic");
 
-       ret_val = snd_soc_add_controls(codec, mfld_snd_controls,
+       ret_val = snd_soc_add_codec_controls(codec, mfld_snd_controls,
                                ARRAY_SIZE(mfld_snd_controls));
        if (ret_val) {
                pr_err("soc_add_controls failed %d", ret_val);
index f204dbac11d4e044edf12501b51238adcd069c28..12be05b16880aacc05d896d15564fd548686bb55 100644 (file)
@@ -630,7 +630,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
        if (pdev->id >= ARRAY_SIZE(mxs_saif))
                return -EINVAL;
 
-       saif = kzalloc(sizeof(*saif), GFP_KERNEL);
+       saif = devm_kzalloc(&pdev->dev, sizeof(*saif), GFP_KERNEL);
        if (!saif)
                return -ENOMEM;
 
@@ -655,29 +655,16 @@ static int mxs_saif_probe(struct platform_device *pdev)
                ret = PTR_ERR(saif->clk);
                dev_err(&pdev->dev, "Cannot get the clock: %d\n",
                        ret);
-               goto failed_clk;
+               return ret;
        }
 
        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!iores) {
-               ret = -ENODEV;
-               dev_err(&pdev->dev, "failed to get io resource: %d\n",
-                       ret);
-               goto failed_get_resource;
-       }
 
-       if (!request_mem_region(iores->start, resource_size(iores),
-                               "mxs-saif")) {
-               dev_err(&pdev->dev, "request_mem_region failed\n");
-               ret = -EBUSY;
-               goto failed_get_resource;
-       }
-
-       saif->base = ioremap(iores->start, resource_size(iores));
+       saif->base = devm_request_and_ioremap(&pdev->dev, iores);
        if (!saif->base) {
                dev_err(&pdev->dev, "ioremap failed\n");
                ret = -ENODEV;
-               goto failed_ioremap;
+               goto failed_get_resource;
        }
 
        dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -685,7 +672,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
                ret = -ENODEV;
                dev_err(&pdev->dev, "failed to get dma resource: %d\n",
                        ret);
-               goto failed_ioremap;
+               goto failed_get_resource;
        }
        saif->dma_param.chan_num = dmares->start;
 
@@ -694,14 +681,15 @@ static int mxs_saif_probe(struct platform_device *pdev)
                ret = saif->irq;
                dev_err(&pdev->dev, "failed to get irq resource: %d\n",
                        ret);
-               goto failed_get_irq1;
+               goto failed_get_resource;
        }
 
        saif->dev = &pdev->dev;
-       ret = request_irq(saif->irq, mxs_saif_irq, 0, "mxs-saif", saif);
+       ret = devm_request_irq(&pdev->dev, saif->irq, mxs_saif_irq, 0,
+                              "mxs-saif", saif);
        if (ret) {
                dev_err(&pdev->dev, "failed to request irq\n");
-               goto failed_get_irq1;
+               goto failed_get_resource;
        }
 
        saif->dma_param.chan_irq = platform_get_irq(pdev, 1);
@@ -709,7 +697,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
                ret = saif->dma_param.chan_irq;
                dev_err(&pdev->dev, "failed to get dma irq resource: %d\n",
                        ret);
-               goto failed_get_irq2;
+               goto failed_get_resource;
        }
 
        platform_set_drvdata(pdev, saif);
@@ -717,7 +705,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
        ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai);
        if (ret) {
                dev_err(&pdev->dev, "register DAI failed\n");
-               goto failed_register;
+               goto failed_get_resource;
        }
 
        saif->soc_platform_pdev = platform_device_alloc(
@@ -740,36 +728,19 @@ 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(iores->start, resource_size(iores));
 failed_get_resource:
        clk_put(saif->clk);
-failed_clk:
-       kfree(saif);
 
        return ret;
 }
 
 static int __devexit mxs_saif_remove(struct platform_device *pdev)
 {
-       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        struct mxs_saif *saif = platform_get_drvdata(pdev);
 
        platform_device_unregister(saif->soc_platform_pdev);
-
        snd_soc_unregister_dai(&pdev->dev);
-
-       iounmap(saif->base);
-       release_mem_region(res->start, resource_size(res));
-       free_irq(saif->irq, saif);
-
        clk_put(saif->clk);
-       kfree(saif);
 
        return 0;
 }
index a67f4370bc9f8fc0096e92abb8ba6cbc3771c220..78563bbbbf018078fefa0744ec27b1d6277ac0a0 100644 (file)
@@ -570,7 +570,7 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_disable_pin(dapm, "AGCOUT");
 
        /* Add virtual switch */
-       ret = snd_soc_add_controls(codec, ams_delta_audio_controls,
+       ret = snd_soc_add_codec_controls(codec, ams_delta_audio_controls,
                                        ARRAY_SIZE(ams_delta_audio_controls));
        if (ret)
                dev_warn(card->dev,
index 597be412f1e40080336be9604940cbfab72012fd..c292bf0fd19ce1184a49466818575f3c9a9604f1 100644 (file)
@@ -55,9 +55,8 @@ static int n810_spk_func;
 static int n810_jack_func;
 static int n810_dmic_func;
 
-static void n810_ext_control(struct snd_soc_codec *codec)
+static void n810_ext_control(struct snd_soc_dapm_context *dapm)
 {
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
        int hp = 0, line1l = 0;
 
        switch (n810_jack_func) {
@@ -102,7 +101,7 @@ static int n810_startup(struct snd_pcm_substream *substream)
        snd_pcm_hw_constraint_minmax(runtime,
                                     SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
 
-       n810_ext_control(codec);
+       n810_ext_control(&codec->dapm);
        return clk_enable(sys_clkout2);
 }
 
@@ -142,13 +141,13 @@ static int n810_get_spk(struct snd_kcontrol *kcontrol,
 static int n810_set_spk(struct snd_kcontrol *kcontrol,
                        struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+       struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
        if (n810_spk_func == ucontrol->value.integer.value[0])
                return 0;
 
        n810_spk_func = ucontrol->value.integer.value[0];
-       n810_ext_control(codec);
+       n810_ext_control(&card->dapm);
 
        return 1;
 }
@@ -164,13 +163,13 @@ static int n810_get_jack(struct snd_kcontrol *kcontrol,
 static int n810_set_jack(struct snd_kcontrol *kcontrol,
                         struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+       struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
        if (n810_jack_func == ucontrol->value.integer.value[0])
                return 0;
 
        n810_jack_func = ucontrol->value.integer.value[0];
-       n810_ext_control(codec);
+       n810_ext_control(&card->dapm);
 
        return 1;
 }
@@ -186,13 +185,13 @@ static int n810_get_input(struct snd_kcontrol *kcontrol,
 static int n810_set_input(struct snd_kcontrol *kcontrol,
                          struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+       struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
        if (n810_dmic_func == ucontrol->value.integer.value[0])
                return 0;
 
        n810_dmic_func = ucontrol->value.integer.value[0];
-       n810_ext_control(codec);
+       n810_ext_control(&card->dapm);
 
        return 1;
 }
index 0855c1cfa7fd84df5d66d3ab190682a250438b17..4dcb5a7e40e874c37440cbcf82073844ebf6d4d7 100644 (file)
@@ -113,12 +113,10 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream,
 
        mutex_lock(&dmic->mutex);
 
-       if (!dai->active) {
-               snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
+       if (!dai->active)
                dmic->active = 1;
-       } else {
+       else
                ret = -EBUSY;
-       }
 
        mutex_unlock(&dmic->mutex);
 
@@ -445,6 +443,7 @@ static struct snd_soc_dai_driver omap_dmic_dai = {
                .channels_max = 6,
                .rates = SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
                .formats = SNDRV_PCM_FMTBIT_S32_LE,
+               .sig_bits = 24,
        },
        .ops = &omap_dmic_dai_ops,
 };
index 017371913ec3cf0629acbdc549d8bbe99d5f7ea7..1287b870f2212f348ac5115e9c447a093dceee82 100644 (file)
@@ -744,17 +744,17 @@ static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = {
                                      omap_mcbsp3_set_st_ch1_volume),
 };
 
-int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id)
+int omap_mcbsp_st_add_controls(struct snd_soc_dai *dai)
 {
        if (!cpu_is_omap34xx())
                return -ENODEV;
 
-       switch (mcbsp_id) {
+       switch (dai->id) {
        case 1: /* McBSP 2 */
-               return snd_soc_add_controls(codec, omap_mcbsp2_st_controls,
+               return snd_soc_add_dai_controls(dai, omap_mcbsp2_st_controls,
                                        ARRAY_SIZE(omap_mcbsp2_st_controls));
        case 2: /* McBSP 3 */
-               return snd_soc_add_controls(codec, omap_mcbsp3_st_controls,
+               return snd_soc_add_dai_controls(dai, omap_mcbsp3_st_controls,
                                        ARRAY_SIZE(omap_mcbsp3_st_controls));
        default:
                break;
index 65cde9d3807b5ffc11c4072dcd8fb606c3e1fb12..476fe2add703611ccc677c05c3346e2553f5e017 100644 (file)
@@ -59,6 +59,6 @@ enum omap_mcbsp_div {
 #define NUM_LINKS      5
 #endif
 
-int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id);
+int omap_mcbsp_st_add_controls(struct snd_soc_dai *dai);
 
 #endif
index 0e25df4fa9e5cf20e380582a36082e23596d2f0b..39705561131a6c10f4a62a486a31208ccbe075a4 100644 (file)
@@ -419,12 +419,14 @@ static struct snd_soc_dai_driver omap_mcpdm_dai = {
                .channels_max = 5,
                .rates = OMAP_MCPDM_RATES,
                .formats = OMAP_MCPDM_FORMATS,
+               .sig_bits = 24,
        },
        .capture = {
                .channels_min = 1,
                .channels_max = 3,
                .rates = OMAP_MCPDM_RATES,
                .formats = OMAP_MCPDM_FORMATS,
+               .sig_bits = 24,
        },
        .ops = &omap_mcpdm_dai_ops,
 };
index fada6ef43eeae736750ef60de289efb0fa48af1d..58936c730a877a22ee3cb5767c1e5a35d6d525f7 100644 (file)
@@ -59,9 +59,8 @@ static int rx51_spk_func;
 static int rx51_dmic_func;
 static int rx51_jack_func;
 
-static void rx51_ext_control(struct snd_soc_codec *codec)
+static void rx51_ext_control(struct snd_soc_dapm_context *dapm)
 {
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
        int hp = 0, hs = 0, tvout = 0;
 
        switch (rx51_jack_func) {
@@ -102,11 +101,11 @@ static int rx51_startup(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec *codec = rtd->codec;
+       struct snd_soc_card *card = rtd->card;
 
        snd_pcm_hw_constraint_minmax(runtime,
                                     SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
-       rx51_ext_control(codec);
+       rx51_ext_control(&card->dapm);
 
        return 0;
 }
@@ -138,13 +137,13 @@ static int rx51_get_spk(struct snd_kcontrol *kcontrol,
 static int rx51_set_spk(struct snd_kcontrol *kcontrol,
                        struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
        if (rx51_spk_func == ucontrol->value.integer.value[0])
                return 0;
 
        rx51_spk_func = ucontrol->value.integer.value[0];
-       rx51_ext_control(codec);
+       rx51_ext_control(&card->dapm);
 
        return 1;
 }
@@ -184,13 +183,13 @@ static int rx51_get_input(struct snd_kcontrol *kcontrol,
 static int rx51_set_input(struct snd_kcontrol *kcontrol,
                          struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
        if (rx51_dmic_func == ucontrol->value.integer.value[0])
                return 0;
 
        rx51_dmic_func = ucontrol->value.integer.value[0];
-       rx51_ext_control(codec);
+       rx51_ext_control(&card->dapm);
 
        return 1;
 }
@@ -206,13 +205,13 @@ static int rx51_get_jack(struct snd_kcontrol *kcontrol,
 static int rx51_set_jack(struct snd_kcontrol *kcontrol,
                         struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
        if (rx51_jack_func == ucontrol->value.integer.value[0])
                return 0;
 
        rx51_jack_func = ucontrol->value.integer.value[0];
-       rx51_ext_control(codec);
+       rx51_ext_control(&card->dapm);
 
        return 1;
 }
@@ -297,7 +296,7 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_nc_pin(dapm, "LINE1R");
 
        /* Add RX-51 specific controls */
-       err = snd_soc_add_controls(codec, aic34_rx51_controls,
+       err = snd_soc_add_card_controls(rtd->card, aic34_rx51_controls,
                                   ARRAY_SIZE(aic34_rx51_controls));
        if (err < 0)
                return err;
@@ -314,7 +313,7 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
                return err;
        snd_soc_limit_volume(codec, "TPA6130A2 Headphone Playback Volume", 42);
 
-       err = omap_mcbsp_st_add_controls(codec, 1);
+       err = omap_mcbsp_st_add_controls(rtd->cpu_dai);
        if (err < 0)
                return err;
 
@@ -335,7 +334,7 @@ static int rx51_aic34b_init(struct snd_soc_dapm_context *dapm)
 {
        int err;
 
-       err = snd_soc_add_controls(dapm->codec, aic34_rx51_controlsb,
+       err = snd_soc_add_card_controls(dapm->card, aic34_rx51_controlsb,
                                   ARRAY_SIZE(aic34_rx51_controlsb));
        if (err < 0)
                return err;
index bc21944851c4c69f274fc4df418dd499e45a0bdd..863367ad89ce6aa1b173914f8c2541903d4f9846 100644 (file)
 static int corgi_jack_func;
 static int corgi_spk_func;
 
-static void corgi_ext_control(struct snd_soc_codec *codec)
+static void corgi_ext_control(struct snd_soc_dapm_context *dapm)
 {
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
        /* set up jack connection */
        switch (corgi_jack_func) {
        case CORGI_HP:
@@ -104,7 +102,7 @@ static int corgi_startup(struct snd_pcm_substream *substream)
        mutex_lock(&codec->mutex);
 
        /* check the jack status at stream startup */
-       corgi_ext_control(codec);
+       corgi_ext_control(&codec->dapm);
 
        mutex_unlock(&codec->mutex);
 
@@ -173,13 +171,13 @@ static int corgi_get_jack(struct snd_kcontrol *kcontrol,
 static int corgi_set_jack(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
        if (corgi_jack_func == ucontrol->value.integer.value[0])
                return 0;
 
        corgi_jack_func = ucontrol->value.integer.value[0];
-       corgi_ext_control(codec);
+       corgi_ext_control(&card->dapm);
        return 1;
 }
 
@@ -193,13 +191,13 @@ static int corgi_get_spk(struct snd_kcontrol *kcontrol,
 static int corgi_set_spk(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+       struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
        if (corgi_spk_func == ucontrol->value.integer.value[0])
                return 0;
 
        corgi_spk_func = ucontrol->value.integer.value[0];
-       corgi_ext_control(codec);
+       corgi_ext_control(&card->dapm);
        return 1;
 }
 
index 3f7a8ecb97206b875469d5de5a2bf21410dd9034..aace19e0fe2c217f734dbd0164b4d242a93be1d1 100644 (file)
@@ -411,7 +411,7 @@ static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_nc_pin(dapm, "VINR");
 
        /* Add magician specific controls */
-       err = snd_soc_add_controls(codec, uda1380_magician_controls,
+       err = snd_soc_add_codec_controls(codec, uda1380_magician_controls,
                                ARRAY_SIZE(uda1380_magician_controls));
        if (err < 0)
                return err;
index fd0ed10c6fe7346065ee18c65d0cb02f4cee6724..d2cc81735036ea8dd6a1aff7f61465caa29fd2fd 100644 (file)
 static int poodle_jack_func;
 static int poodle_spk_func;
 
-static void poodle_ext_control(struct snd_soc_codec *codec)
+static void poodle_ext_control(struct snd_soc_dapm_context *dapm)
 {
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
        /* set up jack connection */
        if (poodle_jack_func == POODLE_HP) {
                /* set = unmute headphone */
@@ -81,7 +79,7 @@ static int poodle_startup(struct snd_pcm_substream *substream)
        mutex_lock(&codec->mutex);
 
        /* check the jack status at stream startup */
-       poodle_ext_control(codec);
+       poodle_ext_control(&codec->dapm);
 
        mutex_unlock(&codec->mutex);
 
@@ -152,13 +150,13 @@ static int poodle_get_jack(struct snd_kcontrol *kcontrol,
 static int poodle_set_jack(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+       struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
        if (poodle_jack_func == ucontrol->value.integer.value[0])
                return 0;
 
        poodle_jack_func = ucontrol->value.integer.value[0];
-       poodle_ext_control(codec);
+       poodle_ext_control(&card->dapm);
        return 1;
 }
 
@@ -172,13 +170,13 @@ static int poodle_get_spk(struct snd_kcontrol *kcontrol,
 static int poodle_set_spk(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+       struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
        if (poodle_spk_func == ucontrol->value.integer.value[0])
                return 0;
 
        poodle_spk_func = ucontrol->value.integer.value[0];
-       poodle_ext_control(codec);
+       poodle_ext_control(&card->dapm);
        return 1;
 }
 
index 837ff341fd6dda45954f2ec34fd263f24a54d62e..4800d5fe568dcdd38adbbe424a1c0e595139775b 100644 (file)
@@ -103,7 +103,7 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
 #define pxa2xx_ac97_resume     NULL
 #endif
 
-static int pxa2xx_ac97_probe(struct snd_soc_dai *dai)
+static int __devinit pxa2xx_ac97_probe(struct snd_soc_dai *dai)
 {
        return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev));
 }
@@ -179,7 +179,7 @@ static const struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = {
  * There is only 1 physical AC97 interface for pxa2xx, but it
  * has extra fifo's that can be used for aux DACs and ADCs.
  */
-static struct snd_soc_dai_driver pxa_ac97_dai[] = {
+static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = {
 {
        .name = "pxa2xx-ac97",
        .ac97_control = 1,
@@ -244,13 +244,13 @@ static __devinit int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
         * driver to do interesting things with the clocking to get us up
         * and running.
         */
-       return snd_soc_register_dais(&pdev->dev, pxa_ac97_dai,
-                       ARRAY_SIZE(pxa_ac97_dai));
+       return snd_soc_register_dais(&pdev->dev, pxa_ac97_dai_driver,
+                       ARRAY_SIZE(pxa_ac97_dai_driver));
 }
 
 static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai));
+       snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai_driver));
        return 0;
 }
 
index 90c5245c4742493bc7406d27d5d7bf11d2a74423..fc052d8247ff245aa6b5baead314ac893e77930c 100644 (file)
@@ -44,10 +44,8 @@ static int spitz_jack_func;
 static int spitz_spk_func;
 static int spitz_mic_gpio;
 
-static void spitz_ext_control(struct snd_soc_codec *codec)
+static void spitz_ext_control(struct snd_soc_dapm_context *dapm)
 {
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
        if (spitz_spk_func == SPITZ_SPK_ON)
                snd_soc_dapm_enable_pin(dapm, "Ext Spk");
        else
@@ -113,7 +111,7 @@ static int spitz_startup(struct snd_pcm_substream *substream)
        mutex_lock(&codec->mutex);
 
        /* check the jack status at stream startup */
-       spitz_ext_control(codec);
+       spitz_ext_control(&codec->dapm);
 
        mutex_unlock(&codec->mutex);
 
@@ -173,13 +171,13 @@ static int spitz_get_jack(struct snd_kcontrol *kcontrol,
 static int spitz_set_jack(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
        if (spitz_jack_func == ucontrol->value.integer.value[0])
                return 0;
 
        spitz_jack_func = ucontrol->value.integer.value[0];
-       spitz_ext_control(codec);
+       spitz_ext_control(&card->dapm);
        return 1;
 }
 
@@ -193,13 +191,13 @@ static int spitz_get_spk(struct snd_kcontrol *kcontrol,
 static int spitz_set_spk(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
        if (spitz_spk_func == ucontrol->value.integer.value[0])
                return 0;
 
        spitz_spk_func = ucontrol->value.integer.value[0];
-       spitz_ext_control(codec);
+       spitz_ext_control(&card->dapm);
        return 1;
 }
 
index 564ef08a89f2d410efae0d45dcdc1691d9e32b5d..2aec63f3706acf826f8f9424fa496a1a479814ab 100644 (file)
@@ -197,7 +197,7 @@ static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_nc_pin(dapm, "MONOOUT");
 
        /* add tosa specific controls */
-       err = snd_soc_add_controls(codec, tosa_controls,
+       err = snd_soc_add_codec_controls(codec, tosa_controls,
                                ARRAY_SIZE(tosa_controls));
        if (err < 0)
                return err;
index 43c014f362f60643a9f5f4d798a2c651b6c0af1b..716da861c629399de5e5322b1556c4e7ae46d08e 100644 (file)
@@ -435,7 +435,8 @@ static void s6000_pcm_free(struct snd_pcm *pcm)
 {
        struct snd_soc_pcm_runtime *runtime = pcm->private_data;
        struct s6000_pcm_dma_params *params =
-               snd_soc_dai_get_dma_data(runtime->cpu_dai, pcm->streams[0].substream);
+               snd_soc_dai_get_dma_data(runtime->cpu_dai,
+                       pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
 
        free_irq(params->irq, pcm);
        snd_pcm_lib_preallocate_free_for_all(pcm);
@@ -451,7 +452,7 @@ static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime)
        int res;
 
        params = snd_soc_dai_get_dma_data(runtime->cpu_dai,
-                       pcm->streams[0].substream);
+                       pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
 
        if (!card->dev->dma_mask)
                card->dev->dma_mask = &s6000_pcm_dmamask;
index e4ba17ce6b32cf3c8d3d3a0762d70c7b7c969b3c..ddc6cde14e2a588763531d94f22b0dab2b1d9a49 100644 (file)
@@ -411,7 +411,7 @@ static int dma_new(struct snd_soc_pcm_runtime *rtd)
        if (!card->dev->dma_mask)
                card->dev->dma_mask = &dma_mask;
        if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = 0xffffffff;
+               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = preallocate_dma_buffer(pcm,
index 9dd818bde06fb6347d9a6e2f79717ae9766123d8..e7416851bf7d0237e97f33fd58b60886ab3ec4f0 100644 (file)
@@ -189,6 +189,9 @@ static int littlemill_late_probe(struct snd_soc_card *card)
        /* This will check device compatibility itself */
        wm8958_mic_detect(codec, &littlemill_headset, NULL, NULL);
 
+       /* As will this */
+       wm8994_mic_detect(codec, &littlemill_headset, 1);
+
        return 0;
 }
 
index c6012ff5bd3ea977cd18f5bb98e4e7e6ded82d1e..24bdb321269af92de0a417990bd5fe0bcacfe656 100644 (file)
@@ -296,7 +296,7 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
        if (ret)
                return ret;
 
-       ret = snd_soc_add_controls(codec, neo1973_gta02_wm8753_controls,
+       ret = snd_soc_add_card_controls(codec->card, neo1973_gta02_wm8753_controls,
                        ARRAY_SIZE(neo1973_gta02_wm8753_controls));
        if (ret)
                return ret;
@@ -328,7 +328,7 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
                return ret;
 
        /* add neo1973 specific controls */
-       ret = snd_soc_add_controls(codec, neo1973_wm8753_controls,
+       ret = snd_soc_add_card_controls(rtd->card, neo1973_wm8753_controls,
                        ARRAY_SIZE(neo1973_wm8753_controls));
        if (ret)
                return ret;
index a253bcc1646aabee42c7b4844bcf960578f49b1b..656d5afe4ca945a944b2d7efdca3e7a78c197228 100644 (file)
@@ -134,18 +134,18 @@ static const struct snd_kcontrol_new amp_unmute_controls[] = {
 
 void simtec_audio_init(struct snd_soc_pcm_runtime *rtd)
 {
-       struct snd_soc_codec *codec = rtd->codec;
+       struct snd_soc_card *card = rtd->card;
 
        if (pdata->amp_gpio > 0) {
                pr_debug("%s: adding amp routes\n", __func__);
 
-               snd_soc_add_controls(codec, amp_unmute_controls,
+               snd_soc_add_card_controls(card, amp_unmute_controls,
                                     ARRAY_SIZE(amp_unmute_controls));
        }
 
        if (pdata->amp_gain[0] > 0) {
                pr_debug("%s: adding amp controls\n", __func__);
-               snd_soc_add_controls(codec, amp_gain_controls,
+               snd_soc_add_card_controls(card, amp_gain_controls,
                                     ARRAY_SIZE(amp_gain_controls));
        }
 }
index ea4a82d01160f5657e19a4f1f4df4ca928d1737a..13746809c27dcf52b19c4546115d58fdef1941d4 100644 (file)
 
 #define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
 
-typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int enable);
+typedef int (*set_rate_func)(struct device *dev, int rate, int enable);
 
 /*
  * FSI driver use below type name for variable
@@ -159,22 +159,33 @@ typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int ena
  *             struct
  */
 
+struct fsi_stream_handler;
 struct fsi_stream {
-       struct snd_pcm_substream *substream;
 
+       /*
+        * these are initialized by fsi_stream_init()
+        */
+       struct snd_pcm_substream *substream;
        int fifo_sample_capa;   /* sample capacity of FSI FIFO */
        int buff_sample_capa;   /* sample capacity of ALSA buffer */
        int buff_sample_pos;    /* sample position of ALSA buffer */
        int period_samples;     /* sample number / 1 period */
        int period_pos;         /* current period position */
-
+       int sample_width;       /* sample width */
        int uerr_num;
        int oerr_num;
+
+       /*
+        * thse are initialized by fsi_handler_init()
+        */
+       struct fsi_stream_handler *handler;
+       struct fsi_priv         *priv;
 };
 
 struct fsi_priv {
        void __iomem *base;
        struct fsi_master *master;
+       struct sh_fsi_port_info *info;
 
        struct fsi_stream playback;
        struct fsi_stream capture;
@@ -189,6 +200,20 @@ struct fsi_priv {
        long rate;
 };
 
+struct fsi_stream_handler {
+       int (*init)(struct fsi_priv *fsi, struct fsi_stream *io);
+       int (*quit)(struct fsi_priv *fsi, struct fsi_stream *io);
+       int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io);
+       int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io);
+       int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io);
+       void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io,
+                          int enable);
+};
+#define fsi_stream_handler_call(io, func, args...)     \
+       (!(io) ? -ENODEV :                              \
+        !((io)->handler->func) ? 0 :                   \
+        (io)->handler->func(args))
+
 struct fsi_core {
        int ver;
 
@@ -205,10 +230,11 @@ struct fsi_master {
        struct fsi_priv fsia;
        struct fsi_priv fsib;
        struct fsi_core *core;
-       struct sh_fsi_platform_info *info;
        spinlock_t lock;
 };
 
+static int fsi_stream_is_play(struct fsi_priv *fsi, struct fsi_stream *io);
+
 /*
  *             basic read write function
  */
@@ -295,6 +321,11 @@ static int fsi_is_spdif(struct fsi_priv *fsi)
        return fsi->spdif;
 }
 
+static int fsi_is_play(struct snd_pcm_substream *substream)
+{
+       return substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+}
+
 static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -317,44 +348,25 @@ static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream)
        return fsi_get_priv_frm_dai(fsi_get_dai(substream));
 }
 
-static set_rate_func fsi_get_info_set_rate(struct fsi_master *master)
+static set_rate_func fsi_get_info_set_rate(struct fsi_priv *fsi)
 {
-       if (!master->info)
+       if (!fsi->info)
                return NULL;
 
-       return master->info->set_rate;
+       return fsi->info->set_rate;
 }
 
 static u32 fsi_get_info_flags(struct fsi_priv *fsi)
 {
-       int is_porta = fsi_is_port_a(fsi);
-       struct fsi_master *master = fsi_get_master(fsi);
-
-       if (!master->info)
+       if (!fsi->info)
                return 0;
 
-       return is_porta ? master->info->porta_flags :
-               master->info->portb_flags;
-}
-
-static inline int fsi_stream_is_play(int stream)
-{
-       return stream == SNDRV_PCM_STREAM_PLAYBACK;
+       return fsi->info->flags;
 }
 
-static inline int fsi_is_play(struct snd_pcm_substream *substream)
-{
-       return fsi_stream_is_play(substream->stream);
-}
-
-static inline struct fsi_stream *fsi_get_stream(struct fsi_priv *fsi,
-                                               int is_play)
-{
-       return is_play ? &fsi->playback : &fsi->capture;
-}
-
-static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play)
+static u32 fsi_get_port_shift(struct fsi_priv *fsi, struct fsi_stream *io)
 {
+       int is_play = fsi_stream_is_play(fsi, io);
        int is_porta = fsi_is_port_a(fsi);
        u32 shift;
 
@@ -376,26 +388,81 @@ static int fsi_sample2frame(struct fsi_priv *fsi, int samples)
        return samples / fsi->chan_num;
 }
 
+static int fsi_get_current_fifo_samples(struct fsi_priv *fsi,
+                                       struct fsi_stream *io)
+{
+       int is_play = fsi_stream_is_play(fsi, io);
+       u32 status;
+       int frames;
+
+       status = is_play ?
+               fsi_reg_read(fsi, DOFF_ST) :
+               fsi_reg_read(fsi, DIFF_ST);
+
+       frames = 0x1ff & (status >> 8);
+
+       return fsi_frame2sample(fsi, frames);
+}
+
+static void fsi_count_fifo_err(struct fsi_priv *fsi)
+{
+       u32 ostatus = fsi_reg_read(fsi, DOFF_ST);
+       u32 istatus = fsi_reg_read(fsi, DIFF_ST);
+
+       if (ostatus & ERR_OVER)
+               fsi->playback.oerr_num++;
+
+       if (ostatus & ERR_UNDER)
+               fsi->playback.uerr_num++;
+
+       if (istatus & ERR_OVER)
+               fsi->capture.oerr_num++;
+
+       if (istatus & ERR_UNDER)
+               fsi->capture.uerr_num++;
+
+       fsi_reg_write(fsi, DOFF_ST, 0);
+       fsi_reg_write(fsi, DIFF_ST, 0);
+}
+
+/*
+ *             fsi_stream_xx() function
+ */
+static inline int fsi_stream_is_play(struct fsi_priv *fsi,
+                                    struct fsi_stream *io)
+{
+       return &fsi->playback == io;
+}
+
+static inline struct fsi_stream *fsi_stream_get(struct fsi_priv *fsi,
+                                       struct snd_pcm_substream *substream)
+{
+       return fsi_is_play(substream) ? &fsi->playback : &fsi->capture;
+}
+
 static int fsi_stream_is_working(struct fsi_priv *fsi,
-                                 int is_play)
+                                struct fsi_stream *io)
 {
-       struct fsi_stream *io = fsi_get_stream(fsi, is_play);
        struct fsi_master *master = fsi_get_master(fsi);
        unsigned long flags;
        int ret;
 
        spin_lock_irqsave(&master->lock, flags);
-       ret = !!io->substream;
+       ret = !!(io->substream && io->substream->runtime);
        spin_unlock_irqrestore(&master->lock, flags);
 
        return ret;
 }
 
-static void fsi_stream_push(struct fsi_priv *fsi,
-                           int is_play,
+static struct fsi_priv *fsi_stream_to_priv(struct fsi_stream *io)
+{
+       return io->priv;
+}
+
+static void fsi_stream_init(struct fsi_priv *fsi,
+                           struct fsi_stream *io,
                            struct snd_pcm_substream *substream)
 {
-       struct fsi_stream *io = fsi_get_stream(fsi, is_play);
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct fsi_master *master = fsi_get_master(fsi);
        unsigned long flags;
@@ -406,14 +473,15 @@ static void fsi_stream_push(struct fsi_priv *fsi,
        io->buff_sample_pos     = 0;
        io->period_samples      = fsi_frame2sample(fsi, runtime->period_size);
        io->period_pos          = 0;
+       io->sample_width        = samples_to_bytes(runtime, 1);
        io->oerr_num    = -1; /* ignore 1st err */
        io->uerr_num    = -1; /* ignore 1st err */
+       fsi_stream_handler_call(io, init, fsi, io);
        spin_unlock_irqrestore(&master->lock, flags);
 }
 
-static void fsi_stream_pop(struct fsi_priv *fsi, int is_play)
+static void fsi_stream_quit(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-       struct fsi_stream *io = fsi_get_stream(fsi, is_play);
        struct snd_soc_dai *dai = fsi_get_dai(io->substream);
        struct fsi_master *master = fsi_get_master(fsi);
        unsigned long flags;
@@ -426,127 +494,87 @@ static void fsi_stream_pop(struct fsi_priv *fsi, int is_play)
        if (io->uerr_num > 0)
                dev_err(dai->dev, "under_run = %d\n", io->uerr_num);
 
+       fsi_stream_handler_call(io, quit, fsi, io);
        io->substream   = NULL;
        io->buff_sample_capa    = 0;
        io->buff_sample_pos     = 0;
        io->period_samples      = 0;
        io->period_pos          = 0;
+       io->sample_width        = 0;
        io->oerr_num    = 0;
        io->uerr_num    = 0;
        spin_unlock_irqrestore(&master->lock, flags);
 }
 
-static int fsi_get_current_fifo_samples(struct fsi_priv *fsi, int is_play)
+static int fsi_stream_transfer(struct fsi_stream *io)
 {
-       u32 status;
-       int frames;
-
-       status = is_play ?
-               fsi_reg_read(fsi, DOFF_ST) :
-               fsi_reg_read(fsi, DIFF_ST);
+       struct fsi_priv *fsi = fsi_stream_to_priv(io);
+       if (!fsi)
+               return -EIO;
 
-       frames = 0x1ff & (status >> 8);
-
-       return fsi_frame2sample(fsi, frames);
-}
-
-static void fsi_count_fifo_err(struct fsi_priv *fsi)
-{
-       u32 ostatus = fsi_reg_read(fsi, DOFF_ST);
-       u32 istatus = fsi_reg_read(fsi, DIFF_ST);
-
-       if (ostatus & ERR_OVER)
-               fsi->playback.oerr_num++;
-
-       if (ostatus & ERR_UNDER)
-               fsi->playback.uerr_num++;
-
-       if (istatus & ERR_OVER)
-               fsi->capture.oerr_num++;
-
-       if (istatus & ERR_UNDER)
-               fsi->capture.uerr_num++;
-
-       fsi_reg_write(fsi, DOFF_ST, 0);
-       fsi_reg_write(fsi, DIFF_ST, 0);
+       return fsi_stream_handler_call(io, transfer, fsi, io);
 }
 
-/*
- *             dma function
- */
+#define fsi_stream_start(fsi, io)\
+       fsi_stream_handler_call(io, start_stop, fsi, io, 1)
 
-static u8 *fsi_dma_get_area(struct fsi_priv *fsi, int stream)
-{
-       int is_play = fsi_stream_is_play(stream);
-       struct fsi_stream *io = fsi_get_stream(fsi, is_play);
-       struct snd_pcm_runtime *runtime = io->substream->runtime;
+#define fsi_stream_stop(fsi, io)\
+       fsi_stream_handler_call(io, start_stop, fsi, io, 0)
 
-       return runtime->dma_area +
-               samples_to_bytes(runtime, io->buff_sample_pos);
-}
-
-static void fsi_dma_soft_push16(struct fsi_priv *fsi, int num)
+static int fsi_stream_probe(struct fsi_priv *fsi)
 {
-       u16 *start;
-       int i;
-
-       start  = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK);
+       struct fsi_stream *io;
+       int ret1, ret2;
 
-       for (i = 0; i < num; i++)
-               fsi_reg_write(fsi, DODT, ((u32)*(start + i) << 8));
-}
-
-static void fsi_dma_soft_pop16(struct fsi_priv *fsi, int num)
-{
-       u16 *start;
-       int i;
+       io = &fsi->playback;
+       ret1 = fsi_stream_handler_call(io, probe, fsi, io);
 
-       start  = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE);
+       io = &fsi->capture;
+       ret2 = fsi_stream_handler_call(io, probe, fsi, io);
 
+       if (ret1 < 0)
+               return ret1;
+       if (ret2 < 0)
+               return ret2;
 
-       for (i = 0; i < num; i++)
-               *(start + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8);
+       return 0;
 }
 
-static void fsi_dma_soft_push32(struct fsi_priv *fsi, int num)
+static int fsi_stream_remove(struct fsi_priv *fsi)
 {
-       u32 *start;
-       int i;
-
-       start  = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK);
+       struct fsi_stream *io;
+       int ret1, ret2;
 
+       io = &fsi->playback;
+       ret1 = fsi_stream_handler_call(io, remove, fsi, io);
 
-       for (i = 0; i < num; i++)
-               fsi_reg_write(fsi, DODT, *(start + i));
-}
-
-static void fsi_dma_soft_pop32(struct fsi_priv *fsi, int num)
-{
-       u32 *start;
-       int i;
+       io = &fsi->capture;
+       ret2 = fsi_stream_handler_call(io, remove, fsi, io);
 
-       start  = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE);
+       if (ret1 < 0)
+               return ret1;
+       if (ret2 < 0)
+               return ret2;
 
-       for (i = 0; i < num; i++)
-               *(start + i) = fsi_reg_read(fsi, DIDT);
+       return 0;
 }
 
 /*
  *             irq function
  */
 
-static void fsi_irq_enable(struct fsi_priv *fsi, int is_play)
+static void fsi_irq_enable(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-       u32 data = AB_IO(1, fsi_get_port_shift(fsi, is_play));
+       u32 data = AB_IO(1, fsi_get_port_shift(fsi, io));
        struct fsi_master *master = fsi_get_master(fsi);
 
        fsi_core_mask_set(master, imsk,  data, data);
        fsi_core_mask_set(master, iemsk, data, data);
 }
 
-static void fsi_irq_disable(struct fsi_priv *fsi, int is_play)
+static void fsi_irq_disable(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-       u32 data = AB_IO(1, fsi_get_port_shift(fsi, is_play));
+       u32 data = AB_IO(1, fsi_get_port_shift(fsi, io));
        struct fsi_master *master = fsi_get_master(fsi);
 
        fsi_core_mask_set(master, imsk,  data, 0);
@@ -563,8 +591,8 @@ static void fsi_irq_clear_status(struct fsi_priv *fsi)
        u32 data = 0;
        struct fsi_master *master = fsi_get_master(fsi);
 
-       data |= AB_IO(1, fsi_get_port_shift(fsi, 0));
-       data |= AB_IO(1, fsi_get_port_shift(fsi, 1));
+       data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->playback));
+       data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->capture));
 
        /* clear interrupt factor */
        fsi_core_mask_set(master, int_st, data, 0);
@@ -600,11 +628,14 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
                              long rate, int enable)
 {
        struct fsi_master *master = fsi_get_master(fsi);
-       set_rate_func set_rate = fsi_get_info_set_rate(master);
+       set_rate_func set_rate = fsi_get_info_set_rate(fsi);
        int fsi_ver = master->core->ver;
        int ret;
 
-       ret = set_rate(dev, fsi_is_port_a(fsi), rate, enable);
+       if (!set_rate)
+               return 0;
+
+       ret = set_rate(dev, rate, enable);
        if (ret < 0) /* error */
                return ret;
 
@@ -671,96 +702,64 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
        return ret;
 }
 
-#define fsi_port_start(f, i)   __fsi_port_clk_ctrl(f, i, 1)
-#define fsi_port_stop(f, i)    __fsi_port_clk_ctrl(f, i, 0)
-static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int is_play, int enable)
+/*
+ *             pio data transfer handler
+ */
+static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples)
 {
-       struct fsi_master *master = fsi_get_master(fsi);
-       u32 clk  = fsi_is_port_a(fsi) ? CRA  : CRB;
+       u16 *buf = (u16 *)_buf;
+       int i;
 
-       if (enable)
-               fsi_irq_enable(fsi, is_play);
-       else
-               fsi_irq_disable(fsi, is_play);
+       for (i = 0; i < samples; i++)
+               fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8));
+}
 
-       if (fsi_is_clk_master(fsi))
-               fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
+static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int samples)
+{
+       u16 *buf = (u16 *)_buf;
+       int i;
+
+       for (i = 0; i < samples; i++)
+               *(buf + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8);
 }
 
-/*
- *             ctrl function
- */
-static void fsi_fifo_init(struct fsi_priv *fsi,
-                         int is_play,
-                         struct device *dev)
+static void fsi_pio_push32(struct fsi_priv *fsi, u8 *_buf, int samples)
 {
-       struct fsi_master *master = fsi_get_master(fsi);
-       struct fsi_stream *io = fsi_get_stream(fsi, is_play);
-       u32 shift, i;
-       int frame_capa;
+       u32 *buf = (u32 *)_buf;
+       int i;
 
-       /* get on-chip RAM capacity */
-       shift = fsi_master_read(master, FIFO_SZ);
-       shift >>= fsi_get_port_shift(fsi, is_play);
-       shift &= FIFO_SZ_MASK;
-       frame_capa = 256 << shift;
-       dev_dbg(dev, "fifo = %d words\n", frame_capa);
+       for (i = 0; i < samples; i++)
+               fsi_reg_write(fsi, DODT, *(buf + i));
+}
 
-       /*
-        * The maximum number of sample data varies depending
-        * on the number of channels selected for the format.
-        *
-        * FIFOs are used in 4-channel units in 3-channel mode
-        * and in 8-channel units in 5- to 7-channel mode
-        * meaning that more FIFOs than the required size of DPRAM
-        * are used.
-        *
-        * ex) if 256 words of DP-RAM is connected
-        * 1 channel:  256 (256 x 1 = 256)
-        * 2 channels: 128 (128 x 2 = 256)
-        * 3 channels:  64 ( 64 x 3 = 192)
-        * 4 channels:  64 ( 64 x 4 = 256)
-        * 5 channels:  32 ( 32 x 5 = 160)
-        * 6 channels:  32 ( 32 x 6 = 192)
-        * 7 channels:  32 ( 32 x 7 = 224)
-        * 8 channels:  32 ( 32 x 8 = 256)
-        */
-       for (i = 1; i < fsi->chan_num; i <<= 1)
-               frame_capa >>= 1;
-       dev_dbg(dev, "%d channel %d store\n",
-               fsi->chan_num, frame_capa);
+static void fsi_pio_pop32(struct fsi_priv *fsi, u8 *_buf, int samples)
+{
+       u32 *buf = (u32 *)_buf;
+       int i;
 
-       io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa);
+       for (i = 0; i < samples; i++)
+               *(buf + i) = fsi_reg_read(fsi, DIDT);
+}
 
-       /*
-        * set interrupt generation factor
-        * clear FIFO
-        */
-       if (is_play) {
-               fsi_reg_write(fsi,      DOFF_CTL, IRQ_HALF);
-               fsi_reg_mask_set(fsi,   DOFF_CTL, FIFO_CLR, FIFO_CLR);
-       } else {
-               fsi_reg_write(fsi,      DIFF_CTL, IRQ_HALF);
-               fsi_reg_mask_set(fsi,   DIFF_CTL, FIFO_CLR, FIFO_CLR);
-       }
+static u8 *fsi_pio_get_area(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+       struct snd_pcm_runtime *runtime = io->substream->runtime;
+
+       return runtime->dma_area +
+               samples_to_bytes(runtime, io->buff_sample_pos);
 }
 
-static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
+static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io,
+               void (*run16)(struct fsi_priv *fsi, u8 *buf, int samples),
+               void (*run32)(struct fsi_priv *fsi, u8 *buf, int samples),
+               int samples)
 {
        struct snd_pcm_runtime *runtime;
-       struct snd_pcm_substream *substream = NULL;
-       int is_play = fsi_stream_is_play(stream);
-       struct fsi_stream *io = fsi_get_stream(fsi, is_play);
-       int sample_residues;
-       int sample_width;
-       int samples;
-       int samples_max;
+       struct snd_pcm_substream *substream;
+       u8 *buf;
        int over_period;
-       void (*fn)(struct fsi_priv *fsi, int size);
 
-       if (!fsi                        ||
-           !io->substream              ||
-           !io->substream->runtime)
+       if (!fsi_stream_is_working(fsi, io))
                return -EINVAL;
 
        over_period     = 0;
@@ -780,60 +779,19 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
                        io->buff_sample_pos = 0;
        }
 
-       /* get 1 sample data width */
-       sample_width = samples_to_bytes(runtime, 1);
-
-       /* get number of residue samples */
-       sample_residues = io->buff_sample_capa - io->buff_sample_pos;
+       buf = fsi_pio_get_area(fsi, io);
 
-       if (is_play) {
-               /*
-                * for play-back
-                *
-                * samples_max  : number of FSI fifo free samples space
-                * samples      : number of ALSA residue samples
-                */
-               samples_max  = io->fifo_sample_capa;
-               samples_max -= fsi_get_current_fifo_samples(fsi, is_play);
-
-               samples = sample_residues;
-
-               switch (sample_width) {
-               case 2:
-                       fn = fsi_dma_soft_push16;
-                       break;
-               case 4:
-                       fn = fsi_dma_soft_push32;
-                       break;
-               default:
-                       return -EINVAL;
-               }
-       } else {
-               /*
-                * for capture
-                *
-                * samples_max  : number of ALSA free samples space
-                * samples      : number of samples in FSI fifo
-                */
-               samples_max = sample_residues;
-               samples     = fsi_get_current_fifo_samples(fsi, is_play);
-
-               switch (sample_width) {
-               case 2:
-                       fn = fsi_dma_soft_pop16;
-                       break;
-               case 4:
-                       fn = fsi_dma_soft_pop32;
-                       break;
-               default:
-                       return -EINVAL;
-               }
+       switch (io->sample_width) {
+       case 2:
+               run16(fsi, buf, samples);
+               break;
+       case 4:
+               run32(fsi, buf, samples);
+               break;
+       default:
+               return -EINVAL;
        }
 
-       samples = min(samples, samples_max);
-
-       fn(fsi, samples);
-
        /* update buff_sample_pos */
        io->buff_sample_pos += samples;
 
@@ -843,16 +801,66 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
        return 0;
 }
 
-static int fsi_data_pop(struct fsi_priv *fsi)
+static int fsi_pio_pop(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-       return fsi_fifo_data_ctrl(fsi, SNDRV_PCM_STREAM_CAPTURE);
+       int sample_residues;    /* samples in FSI fifo */
+       int sample_space;       /* ALSA free samples space */
+       int samples;
+
+       sample_residues = fsi_get_current_fifo_samples(fsi, io);
+       sample_space    = io->buff_sample_capa - io->buff_sample_pos;
+
+       samples = min(sample_residues, sample_space);
+
+       return fsi_pio_transfer(fsi, io,
+                                 fsi_pio_pop16,
+                                 fsi_pio_pop32,
+                                 samples);
 }
 
-static int fsi_data_push(struct fsi_priv *fsi)
+static int fsi_pio_push(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-       return fsi_fifo_data_ctrl(fsi, SNDRV_PCM_STREAM_PLAYBACK);
+       int sample_residues;    /* ALSA residue samples */
+       int sample_space;       /* FSI fifo free samples space */
+       int samples;
+
+       sample_residues = io->buff_sample_capa - io->buff_sample_pos;
+       sample_space    = io->fifo_sample_capa -
+               fsi_get_current_fifo_samples(fsi, io);
+
+       samples = min(sample_residues, sample_space);
+
+       return fsi_pio_transfer(fsi, io,
+                                 fsi_pio_push16,
+                                 fsi_pio_push32,
+                                 samples);
+}
+
+static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
+                              int enable)
+{
+       struct fsi_master *master = fsi_get_master(fsi);
+       u32 clk  = fsi_is_port_a(fsi) ? CRA  : CRB;
+
+       if (enable)
+               fsi_irq_enable(fsi, io);
+       else
+               fsi_irq_disable(fsi, io);
+
+       if (fsi_is_clk_master(fsi))
+               fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
 }
 
+static struct fsi_stream_handler fsi_pio_push_handler = {
+       .transfer       = fsi_pio_push,
+       .start_stop     = fsi_pio_start_stop,
+};
+
+static struct fsi_stream_handler fsi_pio_pop_handler = {
+       .transfer       = fsi_pio_pop,
+       .start_stop     = fsi_pio_start_stop,
+};
+
 static irqreturn_t fsi_interrupt(int irq, void *data)
 {
        struct fsi_master *master = data;
@@ -863,13 +871,13 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
        fsi_master_mask_set(master, SOFT_RST, IR, IR);
 
        if (int_st & AB_IO(1, AO_SHIFT))
-               fsi_data_push(&master->fsia);
+               fsi_stream_transfer(&master->fsia.playback);
        if (int_st & AB_IO(1, BO_SHIFT))
-               fsi_data_push(&master->fsib);
+               fsi_stream_transfer(&master->fsib.playback);
        if (int_st & AB_IO(1, AI_SHIFT))
-               fsi_data_pop(&master->fsia);
+               fsi_stream_transfer(&master->fsia.capture);
        if (int_st & AB_IO(1, BI_SHIFT))
-               fsi_data_pop(&master->fsib);
+               fsi_stream_transfer(&master->fsib.capture);
 
        fsi_count_fifo_err(&master->fsia);
        fsi_count_fifo_err(&master->fsib);
@@ -883,9 +891,63 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
 /*
  *             dai ops
  */
+static void fsi_fifo_init(struct fsi_priv *fsi,
+                         struct fsi_stream *io,
+                         struct device *dev)
+{
+       struct fsi_master *master = fsi_get_master(fsi);
+       int is_play = fsi_stream_is_play(fsi, io);
+       u32 shift, i;
+       int frame_capa;
+
+       /* get on-chip RAM capacity */
+       shift = fsi_master_read(master, FIFO_SZ);
+       shift >>= fsi_get_port_shift(fsi, io);
+       shift &= FIFO_SZ_MASK;
+       frame_capa = 256 << shift;
+       dev_dbg(dev, "fifo = %d words\n", frame_capa);
+
+       /*
+        * The maximum number of sample data varies depending
+        * on the number of channels selected for the format.
+        *
+        * FIFOs are used in 4-channel units in 3-channel mode
+        * and in 8-channel units in 5- to 7-channel mode
+        * meaning that more FIFOs than the required size of DPRAM
+        * are used.
+        *
+        * ex) if 256 words of DP-RAM is connected
+        * 1 channel:  256 (256 x 1 = 256)
+        * 2 channels: 128 (128 x 2 = 256)
+        * 3 channels:  64 ( 64 x 3 = 192)
+        * 4 channels:  64 ( 64 x 4 = 256)
+        * 5 channels:  32 ( 32 x 5 = 160)
+        * 6 channels:  32 ( 32 x 6 = 192)
+        * 7 channels:  32 ( 32 x 7 = 224)
+        * 8 channels:  32 ( 32 x 8 = 256)
+        */
+       for (i = 1; i < fsi->chan_num; i <<= 1)
+               frame_capa >>= 1;
+       dev_dbg(dev, "%d channel %d store\n",
+               fsi->chan_num, frame_capa);
+
+       io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa);
+
+       /*
+        * set interrupt generation factor
+        * clear FIFO
+        */
+       if (is_play) {
+               fsi_reg_write(fsi,      DOFF_CTL, IRQ_HALF);
+               fsi_reg_mask_set(fsi,   DOFF_CTL, FIFO_CLR, FIFO_CLR);
+       } else {
+               fsi_reg_write(fsi,      DIFF_CTL, IRQ_HALF);
+               fsi_reg_mask_set(fsi,   DIFF_CTL, FIFO_CLR, FIFO_CLR);
+       }
+}
 
 static int fsi_hw_startup(struct fsi_priv *fsi,
-                         int is_play,
+                         struct fsi_stream *io,
                          struct device *dev)
 {
        struct fsi_master *master = fsi_get_master(fsi);
@@ -934,17 +996,16 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
        }
 
        /* irq clear */
-       fsi_irq_disable(fsi, is_play);
+       fsi_irq_disable(fsi, io);
        fsi_irq_clear_status(fsi);
 
        /* fifo init */
-       fsi_fifo_init(fsi, is_play, dev);
+       fsi_fifo_init(fsi, io, dev);
 
        return 0;
 }
 
 static void fsi_hw_shutdown(struct fsi_priv *fsi,
-                           int is_play,
                            struct device *dev)
 {
        if (fsi_is_clk_master(fsi))
@@ -955,18 +1016,16 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
                           struct snd_soc_dai *dai)
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
-       int is_play = fsi_is_play(substream);
 
-       return fsi_hw_startup(fsi, is_play, dai->dev);
+       return fsi_hw_startup(fsi, fsi_stream_get(fsi, substream), dai->dev);
 }
 
 static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
                             struct snd_soc_dai *dai)
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
-       int is_play = fsi_is_play(substream);
 
-       fsi_hw_shutdown(fsi, is_play, dai->dev);
+       fsi_hw_shutdown(fsi, dai->dev);
        fsi->rate = 0;
 }
 
@@ -974,18 +1033,19 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
                           struct snd_soc_dai *dai)
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
-       int is_play = fsi_is_play(substream);
+       struct fsi_stream *io = fsi_stream_get(fsi, substream);
        int ret = 0;
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               fsi_stream_push(fsi, is_play, substream);
-               ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi);
-               fsi_port_start(fsi, is_play);
+               fsi_stream_init(fsi, io, substream);
+               ret = fsi_stream_transfer(io);
+               if (0 == ret)
+                       fsi_stream_start(fsi, io);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
-               fsi_port_stop(fsi, is_play);
-               fsi_stream_pop(fsi, is_play);
+               fsi_stream_stop(fsi, io);
+               fsi_stream_quit(fsi, io);
                break;
        }
 
@@ -1036,8 +1096,7 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
 static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
        struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai);
-       struct fsi_master *master = fsi_get_master(fsi);
-       set_rate_func set_rate = fsi_get_info_set_rate(master);
+       set_rate_func set_rate = fsi_get_info_set_rate(fsi);
        u32 flags = fsi_get_info_flags(fsi);
        int ret;
 
@@ -1151,7 +1210,7 @@ static int fsi_hw_free(struct snd_pcm_substream *substream)
 static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
-       struct fsi_stream *io = fsi_get_stream(fsi, fsi_is_play(substream));
+       struct fsi_stream *io = fsi_stream_get(fsi, substream);
 
        return fsi_sample2frame(fsi, io->buff_sample_pos);
 }
@@ -1239,11 +1298,19 @@ static struct snd_soc_platform_driver fsi_soc_platform = {
 /*
  *             platform function
  */
+static void fsi_handler_init(struct fsi_priv *fsi)
+{
+       fsi->playback.handler   = &fsi_pio_push_handler; /* default PIO */
+       fsi->playback.priv      = fsi;
+       fsi->capture.handler    = &fsi_pio_pop_handler;  /* default PIO */
+       fsi->capture.priv       = fsi;
+}
 
 static int fsi_probe(struct platform_device *pdev)
 {
        struct fsi_master *master;
        const struct platform_device_id *id_entry;
+       struct sh_fsi_platform_info *info = pdev->dev.platform_data;
        struct resource *res;
        unsigned int irq;
        int ret;
@@ -1278,17 +1345,30 @@ static int fsi_probe(struct platform_device *pdev)
 
        /* master setting */
        master->irq             = irq;
-       master->info            = pdev->dev.platform_data;
        master->core            = (struct fsi_core *)id_entry->driver_data;
        spin_lock_init(&master->lock);
 
        /* FSI A setting */
        master->fsia.base       = master->base;
        master->fsia.master     = master;
+       master->fsia.info       = &info->port_a;
+       fsi_handler_init(&master->fsia);
+       ret = fsi_stream_probe(&master->fsia);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "FSIA stream probe failed\n");
+               goto exit_iounmap;
+       }
 
        /* FSI B setting */
        master->fsib.base       = master->base + 0x40;
        master->fsib.master     = master;
+       master->fsib.info       = &info->port_b;
+       fsi_handler_init(&master->fsib);
+       ret = fsi_stream_probe(&master->fsib);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "FSIB stream probe failed\n");
+               goto exit_fsia;
+       }
 
        pm_runtime_enable(&pdev->dev);
        dev_set_drvdata(&pdev->dev, master);
@@ -1297,7 +1377,7 @@ static int fsi_probe(struct platform_device *pdev)
                          id_entry->name, master);
        if (ret) {
                dev_err(&pdev->dev, "irq request err\n");
-               goto exit_iounmap;
+               goto exit_fsib;
        }
 
        ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform);
@@ -1319,6 +1399,10 @@ exit_snd_soc:
        snd_soc_unregister_platform(&pdev->dev);
 exit_free_irq:
        free_irq(irq, master);
+exit_fsib:
+       fsi_stream_remove(&master->fsib);
+exit_fsia:
+       fsi_stream_remove(&master->fsia);
 exit_iounmap:
        iounmap(master->base);
        pm_runtime_disable(&pdev->dev);
@@ -1341,6 +1425,9 @@ static int fsi_remove(struct platform_device *pdev)
        snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
        snd_soc_unregister_platform(&pdev->dev);
 
+       fsi_stream_remove(&master->fsia);
+       fsi_stream_remove(&master->fsib);
+
        iounmap(master->base);
        kfree(master);
 
@@ -1348,30 +1435,29 @@ static int fsi_remove(struct platform_device *pdev)
 }
 
 static void __fsi_suspend(struct fsi_priv *fsi,
-                         int is_play,
+                         struct fsi_stream *io,
                          struct device *dev)
 {
-       if (!fsi_stream_is_working(fsi, is_play))
+       if (!fsi_stream_is_working(fsi, io))
                return;
 
-       fsi_port_stop(fsi, is_play);
-       fsi_hw_shutdown(fsi, is_play, dev);
+       fsi_stream_stop(fsi, io);
+       fsi_hw_shutdown(fsi, dev);
 }
 
 static void __fsi_resume(struct fsi_priv *fsi,
-                        int is_play,
+                        struct fsi_stream *io,
                         struct device *dev)
 {
-       if (!fsi_stream_is_working(fsi, is_play))
+       if (!fsi_stream_is_working(fsi, io))
                return;
 
-       fsi_hw_startup(fsi, is_play, dev);
+       fsi_hw_startup(fsi, io, dev);
 
        if (fsi_is_clk_master(fsi) && fsi->rate)
                fsi_set_master_clk(dev, fsi, fsi->rate, 1);
 
-       fsi_port_start(fsi, is_play);
-
+       fsi_stream_start(fsi, io);
 }
 
 static int fsi_suspend(struct device *dev)
@@ -1380,11 +1466,11 @@ static int fsi_suspend(struct device *dev)
        struct fsi_priv *fsia = &master->fsia;
        struct fsi_priv *fsib = &master->fsib;
 
-       __fsi_suspend(fsia, 1, dev);
-       __fsi_suspend(fsia, 0, dev);
+       __fsi_suspend(fsia, &fsia->playback, dev);
+       __fsi_suspend(fsia, &fsia->capture, dev);
 
-       __fsi_suspend(fsib, 1, dev);
-       __fsi_suspend(fsib, 0, dev);
+       __fsi_suspend(fsib, &fsib->playback, dev);
+       __fsi_suspend(fsib, &fsib->capture, dev);
 
        return 0;
 }
@@ -1395,32 +1481,18 @@ static int fsi_resume(struct device *dev)
        struct fsi_priv *fsia = &master->fsia;
        struct fsi_priv *fsib = &master->fsib;
 
-       __fsi_resume(fsia, 1, dev);
-       __fsi_resume(fsia, 0, dev);
+       __fsi_resume(fsia, &fsia->playback, dev);
+       __fsi_resume(fsia, &fsia->capture, dev);
 
-       __fsi_resume(fsib, 1, dev);
-       __fsi_resume(fsib, 0, dev);
+       __fsi_resume(fsib, &fsib->playback, dev);
+       __fsi_resume(fsib, &fsib->capture, dev);
 
        return 0;
 }
 
-static int fsi_runtime_nop(struct device *dev)
-{
-       /* Runtime PM callback shared between ->runtime_suspend()
-        * and ->runtime_resume(). Simply returns success.
-        *
-        * This driver re-initializes all registers after
-        * pm_runtime_get_sync() anyway so there is no need
-        * to save and restore registers here.
-        */
-       return 0;
-}
-
 static struct dev_pm_ops fsi_pm_ops = {
        .suspend                = fsi_suspend,
        .resume                 = fsi_resume,
-       .runtime_suspend        = fsi_runtime_nop,
-       .runtime_resume         = fsi_runtime_nop,
 };
 
 static struct fsi_core fsi1_core = {
index 92cee24ed2dcce7eb7b7e8de3a87f09d0ffe5138..3ca70594e2423e2121160bf2f9fbb6b1b6432798 100644 (file)
@@ -277,8 +277,7 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
        codec->debugfs_codec_root = debugfs_create_dir(codec->name,
                                                       debugfs_card_root);
        if (!codec->debugfs_codec_root) {
-               printk(KERN_WARNING
-                      "ASoC: Failed to create codec debugfs directory\n");
+               dev_warn(codec->dev, "Failed to create codec debugfs directory\n");
                return;
        }
 
@@ -291,8 +290,7 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
                                                 codec->debugfs_codec_root,
                                                 codec, &codec_reg_fops);
        if (!codec->debugfs_reg)
-               printk(KERN_WARNING
-                      "ASoC: Failed to create codec register debugfs file\n");
+               dev_warn(codec->dev, "Failed to create codec register debugfs file\n");
 
        snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root);
 }
@@ -302,6 +300,27 @@ static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
        debugfs_remove_recursive(codec->debugfs_codec_root);
 }
 
+static void soc_init_platform_debugfs(struct snd_soc_platform *platform)
+{
+       struct dentry *debugfs_card_root = platform->card->debugfs_card_root;
+
+       platform->debugfs_platform_root = debugfs_create_dir(platform->name,
+                                                      debugfs_card_root);
+       if (!platform->debugfs_platform_root) {
+               dev_warn(platform->dev,
+                       "Failed to create platform debugfs directory\n");
+               return;
+       }
+
+       snd_soc_dapm_debugfs_init(&platform->dapm,
+               platform->debugfs_platform_root);
+}
+
+static void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform)
+{
+       debugfs_remove_recursive(platform->debugfs_platform_root);
+}
+
 static ssize_t codec_list_read_file(struct file *file, char __user *user_buf,
                                    size_t count, loff_t *ppos)
 {
@@ -435,6 +454,14 @@ static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
 {
 }
 
+static inline void soc_init_platform_debugfs(struct snd_soc_platform *platform)
+{
+}
+
+static inline void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform)
+{
+}
+
 static inline void soc_init_card_debugfs(struct snd_soc_card *card)
 {
 }
@@ -546,18 +573,20 @@ int snd_soc_suspend(struct device *dev)
        }
 
        for (i = 0; i < card->num_rtd; i++) {
-               struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
+               struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
 
                if (card->rtd[i].dai_link->ignore_suspend)
                        continue;
 
-               if (driver->playback.stream_name != NULL)
-                       snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
-                               SND_SOC_DAPM_STREAM_SUSPEND);
+               snd_soc_dapm_stream_event(&card->rtd[i],
+                                         SNDRV_PCM_STREAM_PLAYBACK,
+                                         codec_dai,
+                                         SND_SOC_DAPM_STREAM_SUSPEND);
 
-               if (driver->capture.stream_name != NULL)
-                       snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
-                               SND_SOC_DAPM_STREAM_SUSPEND);
+               snd_soc_dapm_stream_event(&card->rtd[i],
+                                         SNDRV_PCM_STREAM_CAPTURE,
+                                         codec_dai,
+                                         SND_SOC_DAPM_STREAM_SUSPEND);
        }
 
        /* suspend all CODECs */
@@ -660,18 +689,18 @@ static void soc_resume_deferred(struct work_struct *work)
        }
 
        for (i = 0; i < card->num_rtd; i++) {
-               struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
+               struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
 
                if (card->rtd[i].dai_link->ignore_suspend)
                        continue;
 
-               if (driver->playback.stream_name != NULL)
-                       snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
-                               SND_SOC_DAPM_STREAM_RESUME);
+               snd_soc_dapm_stream_event(&card->rtd[i],
+                                         SNDRV_PCM_STREAM_PLAYBACK, codec_dai,
+                                         SND_SOC_DAPM_STREAM_RESUME);
 
-               if (driver->capture.stream_name != NULL)
-                       snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
-                               SND_SOC_DAPM_STREAM_RESUME);
+               snd_soc_dapm_stream_event(&card->rtd[i],
+                                         SNDRV_PCM_STREAM_CAPTURE, codec_dai,
+                                         SND_SOC_DAPM_STREAM_RESUME);
        }
 
        /* unmute any active DACs */
@@ -904,7 +933,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
                if (codec_dai->driver->remove) {
                        err = codec_dai->driver->remove(codec_dai);
                        if (err < 0)
-                               printk(KERN_ERR "asoc: failed to remove %s\n", codec_dai->name);
+                               pr_err("asoc: failed to remove %s: %d\n",
+                                                       codec_dai->name, err);
                }
                codec_dai->probed = 0;
                list_del(&codec_dai->card_list);
@@ -916,12 +946,14 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
                if (platform->driver->remove) {
                        err = platform->driver->remove(platform);
                        if (err < 0)
-                               printk(KERN_ERR "asoc: failed to remove %s\n", platform->name);
+                               pr_err("asoc: failed to remove %s: %d\n",
+                                                       platform->name, err);
                }
 
                /* Make sure all DAPM widgets are freed */
                snd_soc_dapm_free(&platform->dapm);
 
+               soc_cleanup_platform_debugfs(platform);
                platform->probed = 0;
                list_del(&platform->card_list);
                module_put(platform->dev->driver->owner);
@@ -938,7 +970,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
                if (cpu_dai->driver->remove) {
                        err = cpu_dai->driver->remove(cpu_dai);
                        if (err < 0)
-                               printk(KERN_ERR "asoc: failed to remove %s\n", cpu_dai->name);
+                               pr_err("asoc: failed to remove %s: %d\n",
+                                                       cpu_dai->name, err);
                }
                cpu_dai->probed = 0;
                list_del(&cpu_dai->card_list);
@@ -980,6 +1013,7 @@ static int soc_probe_codec(struct snd_soc_card *card,
 {
        int ret = 0;
        const struct snd_soc_codec_driver *driver = codec->driver;
+       struct snd_soc_dai *dai;
 
        codec->card = card;
        codec->dapm.card = card;
@@ -994,6 +1028,14 @@ static int soc_probe_codec(struct snd_soc_card *card,
                snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets,
                                          driver->num_dapm_widgets);
 
+       /* Create DAPM widgets for each DAI stream */
+       list_for_each_entry(dai, &dai_list, list) {
+               if (dai->dev != codec->dev)
+                       continue;
+
+               snd_soc_dapm_new_dai_widgets(&codec->dapm, dai);
+       }
+
        codec->dapm.idle_bias_off = driver->idle_bias_off;
 
        if (driver->probe) {
@@ -1007,7 +1049,7 @@ static int soc_probe_codec(struct snd_soc_card *card,
        }
 
        if (driver->controls)
-               snd_soc_add_controls(codec, driver->controls,
+               snd_soc_add_codec_controls(codec, driver->controls,
                                     driver->num_controls);
        if (driver->dapm_routes)
                snd_soc_dapm_add_routes(&codec->dapm, driver->dapm_routes,
@@ -1039,6 +1081,8 @@ static int soc_probe_platform(struct snd_soc_card *card,
        if (!try_module_get(platform->dev->driver->owner))
                return -ENODEV;
 
+       soc_init_platform_debugfs(platform);
+
        if (driver->dapm_widgets)
                snd_soc_dapm_new_controls(&platform->dapm,
                        driver->dapm_widgets, driver->num_dapm_widgets);
@@ -1183,8 +1227,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
                if (cpu_dai->driver->probe) {
                        ret = cpu_dai->driver->probe(cpu_dai);
                        if (ret < 0) {
-                               printk(KERN_ERR "asoc: failed to probe CPU DAI %s\n",
-                                               cpu_dai->name);
+                               pr_err("asoc: failed to probe CPU DAI %s: %d\n",
+                                                       cpu_dai->name, ret);
                                module_put(cpu_dai->dev->driver->owner);
                                return ret;
                        }
@@ -1215,8 +1259,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
                if (codec_dai->driver->probe) {
                        ret = codec_dai->driver->probe(codec_dai);
                        if (ret < 0) {
-                               printk(KERN_ERR "asoc: failed to probe CODEC DAI %s\n",
-                                               codec_dai->name);
+                               pr_err("asoc: failed to probe CODEC DAI %s: %d\n",
+                                                       codec_dai->name, ret);
                                return ret;
                        }
                }
@@ -1236,12 +1280,13 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
 
        ret = device_create_file(rtd->dev, &dev_attr_pmdown_time);
        if (ret < 0)
-               printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n");
+               pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret);
 
        /* create the pcm */
        ret = soc_new_pcm(rtd, num);
        if (ret < 0) {
-               printk(KERN_ERR "asoc: can't create pcm %s\n", dai_link->stream_name);
+               pr_err("asoc: can't create pcm %s :%d\n",
+                               dai_link->stream_name, ret);
                return ret;
        }
 
@@ -1274,7 +1319,7 @@ static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
 
                ret = soc_ac97_dev_register(rtd->codec);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: AC97 device register failed\n");
+                       pr_err("asoc: AC97 device register failed:%d\n", ret);
                        return ret;
                }
 
@@ -1414,8 +1459,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
        ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
                        card->owner, 0, &card->snd_card);
        if (ret < 0) {
-               printk(KERN_ERR "asoc: can't create sound card for card %s\n",
-                       card->name);
+               pr_err("asoc: can't create sound card for card %s: %d\n",
+                       card->name, ret);
                mutex_unlock(&card->mutex);
                return;
        }
@@ -1468,13 +1513,10 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
                }
        }
 
-       /* We should have a non-codec control add function but we don't */
+       snd_soc_dapm_link_dai_widgets(card);
+
        if (card->controls)
-               snd_soc_add_controls(list_first_entry(&card->codec_dev_list,
-                                                     struct snd_soc_codec,
-                                                     card_list),
-                                    card->controls,
-                                    card->num_controls);
+               snd_soc_add_card_controls(card, card->controls, card->num_controls);
 
        if (card->dapm_routes)
                snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes,
@@ -1538,7 +1580,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 
        ret = snd_card_register(card->snd_card);
        if (ret < 0) {
-               printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name);
+               pr_err("asoc: failed to register soundcard for %s: %d\n",
+                                                       card->name, ret);
                goto probe_aux_dev_err;
        }
 
@@ -1547,7 +1590,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
        for (i = 0; i < card->num_rtd; i++) {
                ret = soc_register_ac97_dai_link(&card->rtd[i]);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
+                       pr_err("asoc: failed to register AC97 %s: %d\n",
+                                                       card->name, ret);
                        while (--i >= 0)
                                soc_unregister_ac97_dai_link(card->rtd[i].codec);
                        goto probe_aux_dev_err;
@@ -1674,8 +1718,7 @@ int snd_soc_poweroff(struct device *dev)
 EXPORT_SYMBOL_GPL(snd_soc_poweroff);
 
 const struct dev_pm_ops snd_soc_pm_ops = {
-       .suspend = snd_soc_suspend,
-       .resume = snd_soc_resume,
+       SET_SYSTEM_SLEEP_PM_OPS(snd_soc_suspend, snd_soc_resume)
        .poweroff = snd_soc_poweroff,
 };
 EXPORT_SYMBOL_GPL(snd_soc_pm_ops);
@@ -1880,23 +1923,28 @@ EXPORT_SYMBOL_GPL(snd_soc_bulk_write_raw);
 int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
                                unsigned int mask, unsigned int value)
 {
-       int change;
+       bool change;
        unsigned int old, new;
        int ret;
 
-       ret = snd_soc_read(codec, reg);
-       if (ret < 0)
-               return ret;
-
-       old = ret;
-       new = (old & ~mask) | (value & mask);
-       change = old != new;
-       if (change) {
-               ret = snd_soc_write(codec, reg, new);
+       if (codec->using_regmap) {
+               ret = regmap_update_bits_check(codec->control_data, reg,
+                                              mask, value, &change);
+       } else {
+               ret = snd_soc_read(codec, reg);
                if (ret < 0)
                        return ret;
+
+               old = ret;
+               new = (old & ~mask) | (value & mask);
+               change = old != new;
+               if (change)
+                       ret = snd_soc_write(codec, reg, new);
        }
 
+       if (ret < 0)
+               return ret;
+
        return change;
 }
 EXPORT_SYMBOL_GPL(snd_soc_update_bits);
@@ -1987,7 +2035,7 @@ EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
  * Returns 0 for success, else error.
  */
 struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
-                                 void *data, char *long_name,
+                                 void *data, const char *long_name,
                                  const char *prefix)
 {
        struct snd_kcontrol_new template;
@@ -2022,9 +2070,28 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
 }
 EXPORT_SYMBOL_GPL(snd_soc_cnew);
 
+static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
+       const struct snd_kcontrol_new *controls, int num_controls,
+       const char *prefix, void *data)
+{
+       int err, i;
+
+       for (i = 0; i < num_controls; i++) {
+               const struct snd_kcontrol_new *control = &controls[i];
+               err = snd_ctl_add(card, snd_soc_cnew(control, data,
+                                                    control->name, prefix));
+               if (err < 0) {
+                       dev_err(dev, "Failed to add %s: %d\n", control->name, err);
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
 /**
- * snd_soc_add_controls - add an array of controls to a codec.
- * Convienience function to add a list of controls. Many codecs were
+ * snd_soc_add_codec_controls - add an array of controls to a codec.
+ * Convenience function to add a list of controls. Many codecs were
  * duplicating this code.
  *
  * @codec: codec to add controls to
@@ -2033,31 +2100,19 @@ EXPORT_SYMBOL_GPL(snd_soc_cnew);
  *
  * Return 0 for success, else error.
  */
-int snd_soc_add_controls(struct snd_soc_codec *codec,
+int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
        const struct snd_kcontrol_new *controls, int num_controls)
 {
        struct snd_card *card = codec->card->snd_card;
-       int err, i;
-
-       for (i = 0; i < num_controls; i++) {
-               const struct snd_kcontrol_new *control = &controls[i];
-               err = snd_ctl_add(card, snd_soc_cnew(control, codec,
-                                                    control->name,
-                                                    codec->name_prefix));
-               if (err < 0) {
-                       dev_err(codec->dev, "%s: Failed to add %s: %d\n",
-                               codec->name, control->name, err);
-                       return err;
-               }
-       }
 
-       return 0;
+       return snd_soc_add_controls(card, codec->dev, controls, num_controls,
+                       codec->name_prefix, codec);
 }
-EXPORT_SYMBOL_GPL(snd_soc_add_controls);
+EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls);
 
 /**
  * snd_soc_add_platform_controls - add an array of controls to a platform.
- * Convienience function to add a list of controls.
+ * Convenience function to add a list of controls.
  *
  * @platform: platform to add controls to
  * @controls: array of controls to add
@@ -2069,22 +2124,52 @@ int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
        const struct snd_kcontrol_new *controls, int num_controls)
 {
        struct snd_card *card = platform->card->snd_card;
-       int err, i;
 
-       for (i = 0; i < num_controls; i++) {
-               const struct snd_kcontrol_new *control = &controls[i];
-               err = snd_ctl_add(card, snd_soc_cnew(control, platform,
-                               control->name, NULL));
-               if (err < 0) {
-                       dev_err(platform->dev, "Failed to add %s %d\n",control->name, err);
-                       return err;
-               }
-       }
-
-       return 0;
+       return snd_soc_add_controls(card, platform->dev, controls, num_controls,
+                       NULL, platform);
 }
 EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls);
 
+/**
+ * snd_soc_add_card_controls - add an array of controls to a SoC card.
+ * Convenience function to add a list of controls.
+ *
+ * @soc_card: SoC card to add controls to
+ * @controls: array of controls to add
+ * @num_controls: number of elements in the array
+ *
+ * Return 0 for success, else error.
+ */
+int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
+       const struct snd_kcontrol_new *controls, int num_controls)
+{
+       struct snd_card *card = soc_card->snd_card;
+
+       return snd_soc_add_controls(card, soc_card->dev, controls, num_controls,
+                       NULL, soc_card);
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_card_controls);
+
+/**
+ * snd_soc_add_dai_controls - add an array of controls to a DAI.
+ * Convienience function to add a list of controls.
+ *
+ * @dai: DAI to add controls to
+ * @controls: array of controls to add
+ * @num_controls: number of elements in the array
+ *
+ * Return 0 for success, else error.
+ */
+int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
+       const struct snd_kcontrol_new *controls, int num_controls)
+{
+       struct snd_card *card = dai->card->snd_card;
+
+       return snd_soc_add_controls(card, dai->dev, controls, num_controls,
+                       NULL, dai);
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls);
+
 /**
  * snd_soc_info_enum_double - enumerated double mixer info callback
  * @kcontrol: mixer control
@@ -2875,7 +2960,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
                 */
                if (!!link->codec_name == !!link->codec_of_node) {
                        dev_err(card->dev,
-                               "Neither/both codec name/of_node are set\n");
+                               "Neither/both codec name/of_node are set for %s\n",
+                               link->name);
                        return -EINVAL;
                }
 
@@ -2885,7 +2971,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
                 */
                if (link->platform_name && link->platform_of_node) {
                        dev_err(card->dev,
-                               "Both platform name/of_node are set\n");
+                               "Both platform name/of_node are set for %s\n", link->name);
                        return -EINVAL;
                }
 
@@ -2895,7 +2981,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
                 */
                if (!!link->cpu_dai_name == !!link->cpu_dai_of_node) {
                        dev_err(card->dev,
-                               "Neither/both cpu_dai name/of_node are set\n");
+                               "Neither/both cpu_dai name/of_node are set for %s\n",
+                               link->name);
                        return -EINVAL;
                }
        }
@@ -3002,7 +3089,7 @@ static inline char *fmt_multiple_name(struct device *dev,
                struct snd_soc_dai_driver *dai_drv)
 {
        if (dai_drv->name == NULL) {
-               printk(KERN_ERR "asoc: error - multiple DAI %s registered with no name\n",
+               pr_err("asoc: error - multiple DAI %s registered with no name\n",
                                dev_name(dev));
                return NULL;
        }
@@ -3285,6 +3372,7 @@ int snd_soc_register_codec(struct device *dev,
        codec->volatile_register = codec_drv->volatile_register;
        codec->readable_register = codec_drv->readable_register;
        codec->writable_register = codec_drv->writable_register;
+       codec->ignore_pmdown_time = codec_drv->ignore_pmdown_time;
        codec->dapm.bias_level = SND_SOC_BIAS_OFF;
        codec->dapm.dev = dev;
        codec->dapm.codec = codec;
@@ -3473,8 +3561,7 @@ static int __init snd_soc_init(void)
 #ifdef CONFIG_DEBUG_FS
        snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL);
        if (IS_ERR(snd_soc_debugfs_root) || !snd_soc_debugfs_root) {
-               printk(KERN_WARNING
-                      "ASoC: Failed to create debugfs directory\n");
+               pr_warn("ASoC: Failed to create debugfs directory\n");
                snd_soc_debugfs_root = NULL;
        }
 
index 1f55ded4047f03b9a538af971c01018f0fb5df10..c9b088dab1cf4cad72d0ef2248deff11391b203b 100644 (file)
  *      dynamic configuration of codec internal audio paths and active
  *      DACs/ADCs.
  *    o Platform power domain - can support external components i.e. amps and
- *      mic/meadphone insertion events.
+ *      mic/headphone insertion events.
  *    o Automatic Mic Bias support
  *    o Jack insertion power event initiation - e.g. hp insertion will enable
  *      sinks, dacs, etc
- *    o Delayed powerdown of audio susbsystem to reduce pops between a quick
+ *    o Delayed power down of audio subsystem to reduce pops between a quick
  *      device reopen.
  *
- *  Todo:
- *    o DAPM power change sequencing - allow for configurable per
- *      codec sequences.
- *    o Support for analogue bias optimisation.
- *    o Support for reduced codec oversampling rates.
- *    o Support for reduced codec bias currents.
  */
 
 #include <linux/module.h>
@@ -40,6 +34,7 @@
 #include <linux/jiffies.h>
 #include <linux/debugfs.h>
 #include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -55,7 +50,9 @@
 static int dapm_up_seq[] = {
        [snd_soc_dapm_pre] = 0,
        [snd_soc_dapm_supply] = 1,
+       [snd_soc_dapm_regulator_supply] = 1,
        [snd_soc_dapm_micbias] = 2,
+       [snd_soc_dapm_dai] = 3,
        [snd_soc_dapm_aif_in] = 3,
        [snd_soc_dapm_aif_out] = 3,
        [snd_soc_dapm_mic] = 4,
@@ -90,6 +87,8 @@ static int dapm_down_seq[] = {
        [snd_soc_dapm_value_mux] = 9,
        [snd_soc_dapm_aif_in] = 10,
        [snd_soc_dapm_aif_out] = 10,
+       [snd_soc_dapm_dai] = 10,
+       [snd_soc_dapm_regulator_supply] = 11,
        [snd_soc_dapm_supply] = 11,
        [snd_soc_dapm_post] = 12,
 };
@@ -172,6 +171,19 @@ static inline struct snd_soc_card *dapm_get_soc_card(
        return NULL;
 }
 
+static void dapm_reset(struct snd_soc_card *card)
+{
+       struct snd_soc_dapm_widget *w;
+
+       memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
+
+       list_for_each_entry(w, &card->widgets, list) {
+               w->power_checked = false;
+               w->inputs = -1;
+               w->outputs = -1;
+       }
+}
+
 static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg)
 {
        if (w->codec)
@@ -197,21 +209,28 @@ static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
 static int soc_widget_update_bits(struct snd_soc_dapm_widget *w,
        unsigned short reg, unsigned int mask, unsigned int value)
 {
-       int change;
+       bool change;
        unsigned int old, new;
        int ret;
 
-       ret = soc_widget_read(w, reg);
-       if (ret < 0)
-               return ret;
-
-       old = ret;
-       new = (old & ~mask) | (value & mask);
-       change = old != new;
-       if (change) {
-               ret = soc_widget_write(w, reg, new);
+       if (w->codec && w->codec->using_regmap) {
+               ret = regmap_update_bits_check(w->codec->control_data,
+                                              reg, mask, value, &change);
+               if (ret != 0)
+                       return ret;
+       } else {
+               ret = soc_widget_read(w, reg);
                if (ret < 0)
                        return ret;
+
+               old = ret;
+               new = (old & ~mask) | (value & mask);
+               change = old != new;
+               if (change) {
+                       ret = soc_widget_write(w, reg, new);
+                       if (ret < 0)
+                               return ret;
+               }
        }
 
        return change;
@@ -345,8 +364,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
        case snd_soc_dapm_micbias:
        case snd_soc_dapm_vmid:
        case snd_soc_dapm_supply:
+       case snd_soc_dapm_regulator_supply:
        case snd_soc_dapm_aif_in:
        case snd_soc_dapm_aif_out:
+       case snd_soc_dapm_dai:
        case snd_soc_dapm_hp:
        case snd_soc_dapm_mic:
        case snd_soc_dapm_spk:
@@ -504,17 +525,17 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
                                 * for widgets so cut the prefix off
                                 * the front of the widget name.
                                 */
-                               snprintf(path->long_name, name_len, "%s %s",
-                                        w->name + prefix_len,
+                               snprintf((char *)path->long_name, name_len,
+                                        "%s %s", w->name + prefix_len,
                                         w->kcontrol_news[i].name);
                                break;
                        case snd_soc_dapm_mixer_named_ctl:
-                               snprintf(path->long_name, name_len, "%s",
-                                        w->kcontrol_news[i].name);
+                               snprintf((char *)path->long_name, name_len,
+                                        "%s", w->kcontrol_news[i].name);
                                break;
                        }
 
-                       path->long_name[name_len - 1] = '\0';
+                       ((char *)path->long_name)[name_len - 1] = '\0';
 
                        path->kcontrol = snd_soc_cnew(&w->kcontrol_news[i],
                                                      wlist, path->long_name,
@@ -548,7 +569,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
        struct snd_soc_dapm_widget_list *wlist;
        int shared, wlistentries;
        size_t wlistsize;
-       char *name;
+       const char *name;
 
        if (w->num_kcontrols != 1) {
                dev_err(dapm->dev,
@@ -673,12 +694,18 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
 
        DAPM_UPDATE_STAT(widget, path_checks);
 
-       if (widget->id == snd_soc_dapm_supply)
+       switch (widget->id) {
+       case snd_soc_dapm_supply:
+       case snd_soc_dapm_regulator_supply:
                return 0;
+       default:
+               break;
+       }
 
        switch (widget->id) {
        case snd_soc_dapm_adc:
        case snd_soc_dapm_aif_out:
+       case snd_soc_dapm_dai:
                if (widget->active) {
                        widget->outputs = snd_soc_dapm_suspend_check(widget);
                        return widget->outputs;
@@ -738,13 +765,19 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
 
        DAPM_UPDATE_STAT(widget, path_checks);
 
-       if (widget->id == snd_soc_dapm_supply)
+       switch (widget->id) {
+       case snd_soc_dapm_supply:
+       case snd_soc_dapm_regulator_supply:
                return 0;
+       default:
+               break;
+       }
 
        /* active stream ? */
        switch (widget->id) {
        case snd_soc_dapm_dac:
        case snd_soc_dapm_aif_in:
+       case snd_soc_dapm_dai:
                if (widget->active) {
                        widget->inputs = snd_soc_dapm_suspend_check(widget);
                        return widget->inputs;
@@ -821,6 +854,19 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
 }
 EXPORT_SYMBOL_GPL(dapm_reg_event);
 
+/*
+ * Handler for regulator supply widget.
+ */
+int dapm_regulator_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol, int event)
+{
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               return regulator_enable(w->priv);
+       else
+               return regulator_disable_deferred(w->priv, w->shift);
+}
+EXPORT_SYMBOL_GPL(dapm_regulator_event);
+
 static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
 {
        if (w->power_checked)
@@ -851,6 +897,13 @@ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
        return out != 0 && in != 0;
 }
 
+static int dapm_dai_check_power(struct snd_soc_dapm_widget *w)
+{
+       DAPM_UPDATE_STAT(w, power_checks);
+
+       return w->active;
+}
+
 /* Check to see if an ADC has power */
 static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
 {
@@ -1251,7 +1304,7 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
                        dev_err(d->dev, "Failed to turn off bias: %d\n", ret);
 
                if (d->dev)
-                       pm_runtime_put_sync(d->dev);
+                       pm_runtime_put(d->dev);
        }
 
        /* If we just powered up then move to active bias */
@@ -1301,6 +1354,7 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
        }
        switch (w->id) {
        case snd_soc_dapm_supply:
+       case snd_soc_dapm_regulator_supply:
                /* Supplies can't affect their outputs, only their inputs */
                break;
        default:
@@ -1373,13 +1427,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
                }
        }
 
-       memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
-
-       list_for_each_entry(w, &card->widgets, list) {
-               w->power_checked = false;
-               w->inputs = -1;
-               w->outputs = -1;
-       }
+       dapm_reset(card);
 
        /* Check which widgets we need to power and store them in
         * lists indicating if they should be powered up or down.  We
@@ -1400,10 +1448,15 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
                        /* Supplies and micbiases only bring the
                         * context up to STANDBY as unless something
                         * else is active and passing audio they
-                        * generally don't require full power.
+                        * generally don't require full power.  Signal
+                        * generators are virtual pins and have no
+                        * power impact themselves.
                         */
                        switch (w->id) {
+                       case snd_soc_dapm_siggen:
+                               break;
                        case snd_soc_dapm_supply:
+                       case snd_soc_dapm_regulator_supply:
                        case snd_soc_dapm_micbias:
                                if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
                                        d->target_bias_level = SND_SOC_BIAS_STANDBY;
@@ -1475,6 +1528,12 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
                                        &async_domain);
        async_synchronize_full_domain(&async_domain);
 
+       /* do we need to notify any clients that DAPM event is complete */
+       list_for_each_entry(d, &card->dapm_list, list) {
+               if (d->stream_event)
+                       d->stream_event(d, event);
+       }
+
        pop_dbg(dapm->dev, card->pop_time,
                "DAPM sequencing finished, waiting %dms\n", card->pop_time);
        pop_wait(card->pop_time);
@@ -1659,9 +1718,8 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
 #endif
 
 /* test and update the power status of a mux widget */
-static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
-                                struct snd_kcontrol *kcontrol, int change,
-                                int mux, struct soc_enum *e)
+int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
+                                struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
 {
        struct snd_soc_dapm_path *path;
        int found = 0;
@@ -1671,9 +1729,6 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
            widget->id != snd_soc_dapm_value_mux)
                return -ENODEV;
 
-       if (!change)
-               return 0;
-
        /* find dapm widget path assoc with kcontrol */
        list_for_each_entry(path, &widget->dapm->card->paths, list) {
                if (path->kcontrol != kcontrol)
@@ -1702,9 +1757,10 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
 
 /* test and update the power status of a mixer or switch widget */
-static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
+int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
                                   struct snd_kcontrol *kcontrol, int connect)
 {
        struct snd_soc_dapm_path *path;
@@ -1733,6 +1789,7 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
 
 /* show dapm widget status in sys fs */
 static ssize_t dapm_widget_show(struct device *dev,
@@ -1762,6 +1819,7 @@ static ssize_t dapm_widget_show(struct device *dev,
                case snd_soc_dapm_mixer:
                case snd_soc_dapm_mixer_named_ctl:
                case snd_soc_dapm_supply:
+               case snd_soc_dapm_regulator_supply:
                        if (w->name)
                                count += sprintf(buf + count, "%s: %s\n",
                                        w->name, w->power ? "On":"Off");
@@ -1869,10 +1927,12 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
                return -EINVAL;
        }
 
+       if (w->connected != status)
+               dapm_mark_dirty(w, "pin configuration");
+
        w->connected = status;
        if (status == 0)
                w->force = 0;
-       dapm_mark_dirty(w, "pin configuration");
 
        return 0;
 }
@@ -2000,8 +2060,10 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
        case snd_soc_dapm_pre:
        case snd_soc_dapm_post:
        case snd_soc_dapm_supply:
+       case snd_soc_dapm_regulator_supply:
        case snd_soc_dapm_aif_in:
        case snd_soc_dapm_aif_out:
+       case snd_soc_dapm_dai:
                list_add(&path->list, &dapm->card->paths);
                list_add(&path->list_sink, &wsink->sources);
                list_add(&path->list_source, &wsource->sinks);
@@ -2315,7 +2377,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
                        update.val = val;
                        widget->dapm->update = &update;
 
-                       dapm_mixer_update_power(widget, kcontrol, connect);
+                       snd_soc_dapm_mixer_update_power(widget, kcontrol, connect);
 
                        widget->dapm->update = NULL;
                }
@@ -2406,7 +2468,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
                        update.val = val;
                        widget->dapm->update = &update;
 
-                       dapm_mux_update_power(widget, kcontrol, change, mux, e);
+                       snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
 
                        widget->dapm->update = NULL;
                }
@@ -2467,8 +2529,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
 
                        widget->value = ucontrol->value.enumerated.item[0];
 
-                       dapm_mux_update_power(widget, kcontrol, change,
-                                             widget->value, e);
+                       snd_soc_dapm_mux_update_power(widget, kcontrol, widget->value, e);
                }
        }
 
@@ -2571,7 +2632,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
                        update.val = val;
                        widget->dapm->update = &update;
 
-                       dapm_mux_update_power(widget, kcontrol, change, mux, e);
+                       snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
 
                        widget->dapm->update = NULL;
                }
@@ -2611,15 +2672,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch);
 int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
                                struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
        const char *pin = (const char *)kcontrol->private_value;
 
-       mutex_lock(&codec->mutex);
+       mutex_lock(&card->mutex);
 
        ucontrol->value.integer.value[0] =
-               snd_soc_dapm_get_pin_status(&codec->dapm, pin);
+               snd_soc_dapm_get_pin_status(&card->dapm, pin);
 
-       mutex_unlock(&codec->mutex);
+       mutex_unlock(&card->mutex);
 
        return 0;
 }
@@ -2634,41 +2695,48 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch);
 int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
                                struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
        const char *pin = (const char *)kcontrol->private_value;
 
-       mutex_lock(&codec->mutex);
+       mutex_lock(&card->mutex);
 
        if (ucontrol->value.integer.value[0])
-               snd_soc_dapm_enable_pin(&codec->dapm, pin);
+               snd_soc_dapm_enable_pin(&card->dapm, pin);
        else
-               snd_soc_dapm_disable_pin(&codec->dapm, pin);
+               snd_soc_dapm_disable_pin(&card->dapm, pin);
 
-       snd_soc_dapm_sync(&codec->dapm);
+       snd_soc_dapm_sync(&card->dapm);
 
-       mutex_unlock(&codec->mutex);
+       mutex_unlock(&card->mutex);
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
 
-/**
- * snd_soc_dapm_new_control - create new dapm control
- * @dapm: DAPM context
- * @widget: widget template
- *
- * Creates a new dapm control based upon the template.
- *
- * Returns 0 for success else error.
- */
-int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
-       const struct snd_soc_dapm_widget *widget)
+static struct snd_soc_dapm_widget *
+snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
+                        const struct snd_soc_dapm_widget *widget)
 {
        struct snd_soc_dapm_widget *w;
        size_t name_len;
+       int ret;
 
        if ((w = dapm_cnew_widget(widget)) == NULL)
-               return -ENOMEM;
+               return NULL;
+
+       switch (w->id) {
+       case snd_soc_dapm_regulator_supply:
+               w->priv = devm_regulator_get(dapm->dev, w->name);
+               if (IS_ERR(w->priv)) {
+                       ret = PTR_ERR(w->priv);
+                       dev_err(dapm->dev, "Failed to request %s: %d\n",
+                               w->name, ret);
+                       return NULL;
+               }
+               break;
+       default:
+               break;
+       }
 
        name_len = strlen(widget->name) + 1;
        if (dapm->codec && dapm->codec->name_prefix)
@@ -2676,13 +2744,13 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
        w->name = kmalloc(name_len, GFP_KERNEL);
        if (w->name == NULL) {
                kfree(w);
-               return -ENOMEM;
+               return NULL;
        }
        if (dapm->codec && dapm->codec->name_prefix)
-               snprintf(w->name, name_len, "%s %s",
+               snprintf((char *)w->name, name_len, "%s %s",
                        dapm->codec->name_prefix, widget->name);
        else
-               snprintf(w->name, name_len, "%s", widget->name);
+               snprintf((char *)w->name, name_len, "%s", widget->name);
 
        switch (w->id) {
        case snd_soc_dapm_switch:
@@ -2715,8 +2783,12 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
                w->power_check = dapm_generic_check_power;
                break;
        case snd_soc_dapm_supply:
+       case snd_soc_dapm_regulator_supply:
                w->power_check = dapm_supply_check_power;
                break;
+       case snd_soc_dapm_dai:
+               w->power_check = dapm_dai_check_power;
+               break;
        default:
                w->power_check = dapm_always_on_check_power;
                break;
@@ -2734,9 +2806,8 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 
        /* machine layer set ups unconnected pins and insertions */
        w->connected = 1;
-       return 0;
+       return w;
 }
-EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
 
 /**
  * snd_soc_dapm_new_controls - create new dapm controls
@@ -2752,15 +2823,16 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
        const struct snd_soc_dapm_widget *widget,
        int num)
 {
-       int i, ret;
+       struct snd_soc_dapm_widget *w;
+       int i;
 
        for (i = 0; i < num; i++) {
-               ret = snd_soc_dapm_new_control(dapm, widget);
-               if (ret < 0) {
+               w = snd_soc_dapm_new_control(dapm, widget);
+               if (!w) {
                        dev_err(dapm->dev,
-                               "ASoC: Failed to create DAPM control %s: %d\n",
-                               widget->name, ret);
-                       return ret;
+                               "ASoC: Failed to create DAPM control %s\n",
+                               widget->name);
+                       return -ENOMEM;
                }
                widget++;
        }
@@ -2768,40 +2840,140 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
 
-static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
-       const char *stream, int event)
+int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
+                                struct snd_soc_dai *dai)
 {
+       struct snd_soc_dapm_widget template;
        struct snd_soc_dapm_widget *w;
 
-       list_for_each_entry(w, &dapm->card->widgets, list)
-       {
-               if (!w->sname || w->dapm != dapm)
+       WARN_ON(dapm->dev != dai->dev);
+
+       memset(&template, 0, sizeof(template));
+       template.reg = SND_SOC_NOPM;
+
+       if (dai->driver->playback.stream_name) {
+               template.id = snd_soc_dapm_dai;
+               template.name = dai->driver->playback.stream_name;
+               template.sname = dai->driver->playback.stream_name;
+
+               dev_dbg(dai->dev, "adding %s widget\n",
+                       template.name);
+
+               w = snd_soc_dapm_new_control(dapm, &template);
+               if (!w) {
+                       dev_err(dapm->dev, "Failed to create %s widget\n",
+                               dai->driver->playback.stream_name);
+               }
+
+               w->priv = dai;
+               dai->playback_widget = w;
+       }
+
+       if (dai->driver->capture.stream_name) {
+               template.id = snd_soc_dapm_dai;
+               template.name = dai->driver->capture.stream_name;
+               template.sname = dai->driver->capture.stream_name;
+
+               dev_dbg(dai->dev, "adding %s widget\n",
+                       template.name);
+
+               w = snd_soc_dapm_new_control(dapm, &template);
+               if (!w) {
+                       dev_err(dapm->dev, "Failed to create %s widget\n",
+                               dai->driver->capture.stream_name);
+               }
+
+               w->priv = dai;
+               dai->capture_widget = w;
+       }
+
+       return 0;
+}
+
+int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
+{
+       struct snd_soc_dapm_widget *dai_w, *w;
+       struct snd_soc_dai *dai;
+       struct snd_soc_dapm_route r;
+
+       memset(&r, 0, sizeof(r));
+
+       /* For each DAI widget... */
+       list_for_each_entry(dai_w, &card->widgets, list) {
+               if (dai_w->id != snd_soc_dapm_dai)
                        continue;
-               dev_vdbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n",
-                       w->name, w->sname, stream, event);
-               if (strstr(w->sname, stream)) {
-                       dapm_mark_dirty(w, "stream event");
-                       switch(event) {
-                       case SND_SOC_DAPM_STREAM_START:
-                               w->active = 1;
-                               break;
-                       case SND_SOC_DAPM_STREAM_STOP:
-                               w->active = 0;
-                               break;
-                       case SND_SOC_DAPM_STREAM_SUSPEND:
-                       case SND_SOC_DAPM_STREAM_RESUME:
-                       case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
-                       case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
-                               break;
+
+               dai = dai_w->priv;
+
+               /* ...find all widgets with the same stream and link them */
+               list_for_each_entry(w, &card->widgets, list) {
+                       if (w->dapm != dai_w->dapm)
+                               continue;
+
+                       if (w->id == snd_soc_dapm_dai)
+                               continue;
+
+                       if (!w->sname)
+                               continue;
+
+                       if (dai->driver->playback.stream_name &&
+                           strstr(w->sname,
+                                  dai->driver->playback.stream_name)) {
+                               r.source = dai->playback_widget->name;
+                               r.sink = w->name;
+                               dev_dbg(dai->dev, "%s -> %s\n",
+                                        r.source, r.sink);
+
+                               snd_soc_dapm_add_route(w->dapm, &r);
+                       }
+
+                       if (dai->driver->capture.stream_name &&
+                           strstr(w->sname,
+                                  dai->driver->capture.stream_name)) {
+                               r.source = w->name;
+                               r.sink = dai->capture_widget->name;
+                               dev_dbg(dai->dev, "%s -> %s\n",
+                                       r.source, r.sink);
+
+                               snd_soc_dapm_add_route(w->dapm, &r);
                        }
                }
        }
 
-       dapm_power_widgets(dapm, event);
+       return 0;
+}
 
-       /* do we need to notify any clients that DAPM stream is complete */
-       if (dapm->stream_event)
-               dapm->stream_event(dapm, event);
+static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
+                                 int stream, struct snd_soc_dai *dai,
+                                 int event)
+{
+       struct snd_soc_dapm_widget *w;
+
+       if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+               w = dai->playback_widget;
+       else
+               w = dai->capture_widget;
+
+       if (!w)
+               return;
+
+       dapm_mark_dirty(w, "stream event");
+
+       switch (event) {
+       case SND_SOC_DAPM_STREAM_START:
+               w->active = 1;
+               break;
+       case SND_SOC_DAPM_STREAM_STOP:
+               w->active = 0;
+               break;
+       case SND_SOC_DAPM_STREAM_SUSPEND:
+       case SND_SOC_DAPM_STREAM_RESUME:
+       case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
+       case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
+               break;
+       }
+
+       dapm_power_widgets(dapm, event);
 }
 
 /**
@@ -2815,16 +2987,13 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
  *
  * Returns 0 for success else error.
  */
-int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
-       const char *stream, int event)
+int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
+                             struct snd_soc_dai *dai, int event)
 {
        struct snd_soc_codec *codec = rtd->codec;
 
-       if (stream == NULL)
-               return 0;
-
        mutex_lock(&codec->mutex);
-       soc_dapm_stream_event(&codec->dapm, stream, event);
+       soc_dapm_stream_event(&codec->dapm, stream, dai, event);
        mutex_unlock(&codec->mutex);
        return 0;
 }
index c8610cbf34a51cf9f2e856cc847a730f64a1d016..39ba5070ff92609d45f2e5223221d2b040ecc027 100644 (file)
@@ -140,6 +140,7 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
 
        case SND_SOC_REGMAP:
                /* Device has made its own regmap arrangements */
+               codec->using_regmap = true;
                break;
 
        default:
index cdc860a5ff37ca0fe070bdc9f6f4532e1cd6a7c3..0ad8dcacd2f39eefbdc434ac8bed0a4a56e3ea6f 100644 (file)
@@ -62,6 +62,41 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
        return 0;
 }
 
+/*
+ * List of sample sizes that might go over the bus for parameter
+ * application.  There ought to be a wildcard sample size for things
+ * like the DAC/ADC resolution to use but there isn't right now.
+ */
+static int sample_sizes[] = {
+       24, 32,
+};
+
+static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
+                             struct snd_soc_dai *dai)
+{
+       int ret, i, bits;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               bits = dai->driver->playback.sig_bits;
+       else
+               bits = dai->driver->capture.sig_bits;
+
+       if (!bits)
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(sample_sizes); i++) {
+               if (bits >= sample_sizes[i])
+                       continue;
+
+               ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0,
+                                                  sample_sizes[i], bits);
+               if (ret != 0)
+                       dev_warn(dai->dev,
+                                "Failed to set MSB %d/%d: %d\n",
+                                bits, sample_sizes[i], ret);
+       }
+}
+
 /*
  * Called by ALSA when a PCM substream is opened, the runtime->hw record is
  * then initialized and any private data can be allocated. This also calls
@@ -88,8 +123,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        if (cpu_dai->driver->ops->startup) {
                ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: can't open interface %s\n",
-                               cpu_dai->name);
+                       dev_err(cpu_dai->dev, "can't open interface %s: %d\n",
+                               cpu_dai->name, ret);
                        goto out;
                }
        }
@@ -97,7 +132,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        if (platform->driver->ops && platform->driver->ops->open) {
                ret = platform->driver->ops->open(substream);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
+                       dev_err(platform->dev, "can't open platform %s: %d\n",
+                               platform->name, ret);
                        goto platform_err;
                }
        }
@@ -105,8 +141,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        if (codec_dai->driver->ops->startup) {
                ret = codec_dai->driver->ops->startup(substream, codec_dai);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: can't open codec %s\n",
-                               codec_dai->name);
+                       dev_err(codec_dai->dev, "can't open codec %s: %d\n",
+                               codec_dai->name, ret);
                        goto codec_dai_err;
                }
        }
@@ -114,7 +150,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
                ret = rtd->dai_link->ops->startup(substream);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name);
+                       pr_err("asoc: %s startup failed: %d\n",
+                              rtd->dai_link->name, ret);
                        goto machine_err;
                }
        }
@@ -187,6 +224,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
                goto config_err;
        }
 
+       soc_pcm_apply_msb(substream, codec_dai);
+       soc_pcm_apply_msb(substream, cpu_dai);
+
        /* Symmetry only applies if we've already got an active stream. */
        if (cpu_dai->active) {
                ret = soc_pcm_apply_symmetry(substream, cpu_dai);
@@ -267,9 +307,8 @@ static void close_delayed_work(struct work_struct *work)
        /* are we waiting on this codec DAI stream */
        if (codec_dai->pop_wait == 1) {
                codec_dai->pop_wait = 0;
-               snd_soc_dapm_stream_event(rtd,
-                       codec_dai->driver->playback.stream_name,
-                       SND_SOC_DAPM_STREAM_STOP);
+               snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
+                                         codec_dai, SND_SOC_DAPM_STREAM_STOP);
        }
 
        mutex_unlock(&rtd->pcm_mutex);
@@ -329,12 +368,13 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
        cpu_dai->runtime = NULL;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               if (codec->ignore_pmdown_time ||
+               if (!rtd->pmdown_time || codec->ignore_pmdown_time ||
                    rtd->dai_link->ignore_pmdown_time) {
                        /* powered down playback stream now */
                        snd_soc_dapm_stream_event(rtd,
-                               codec_dai->driver->playback.stream_name,
-                               SND_SOC_DAPM_STREAM_STOP);
+                                                 SNDRV_PCM_STREAM_PLAYBACK,
+                                                 codec_dai,
+                                                 SND_SOC_DAPM_STREAM_STOP);
                } else {
                        /* start delayed pop wq here for playback streams */
                        codec_dai->pop_wait = 1;
@@ -343,9 +383,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
                }
        } else {
                /* capture streams can be powered down now */
-               snd_soc_dapm_stream_event(rtd,
-                       codec_dai->driver->capture.stream_name,
-                       SND_SOC_DAPM_STREAM_STOP);
+               snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
+                                         codec_dai, SND_SOC_DAPM_STREAM_STOP);
        }
 
        mutex_unlock(&rtd->pcm_mutex);
@@ -375,7 +414,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
        if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
                ret = rtd->dai_link->ops->prepare(substream);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: machine prepare error\n");
+                       pr_err("asoc: machine prepare error: %d\n", ret);
                        goto out;
                }
        }
@@ -383,7 +422,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
        if (platform->driver->ops && platform->driver->ops->prepare) {
                ret = platform->driver->ops->prepare(substream);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: platform prepare error\n");
+                       dev_err(platform->dev, "platform prepare error: %d\n",
+                               ret);
                        goto out;
                }
        }
@@ -391,7 +431,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
        if (codec_dai->driver->ops->prepare) {
                ret = codec_dai->driver->ops->prepare(substream, codec_dai);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: codec DAI prepare error\n");
+                       dev_err(codec_dai->dev, "DAI prepare error: %d\n",
+                               ret);
                        goto out;
                }
        }
@@ -399,7 +440,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
        if (cpu_dai->driver->ops->prepare) {
                ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: cpu DAI prepare error\n");
+                       dev_err(cpu_dai->dev, "DAI prepare error: %d\n",
+                               ret);
                        goto out;
                }
        }
@@ -411,14 +453,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
                cancel_delayed_work(&rtd->delayed_work);
        }
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               snd_soc_dapm_stream_event(rtd,
-                                         codec_dai->driver->playback.stream_name,
-                                         SND_SOC_DAPM_STREAM_START);
-       else
-               snd_soc_dapm_stream_event(rtd,
-                                         codec_dai->driver->capture.stream_name,
-                                         SND_SOC_DAPM_STREAM_START);
+       snd_soc_dapm_stream_event(rtd, substream->stream, codec_dai,
+                                 SND_SOC_DAPM_STREAM_START);
 
        snd_soc_dai_digital_mute(codec_dai, 0);
 
@@ -446,7 +482,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
        if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
                ret = rtd->dai_link->ops->hw_params(substream, params);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: machine hw_params failed\n");
+                       pr_err("asoc: machine hw_params failed: %d\n", ret);
                        goto out;
                }
        }
@@ -454,8 +490,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
        if (codec_dai->driver->ops->hw_params) {
                ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: can't set codec %s hw params\n",
-                               codec_dai->name);
+                       dev_err(codec_dai->dev, "can't set %s hw params: %d\n",
+                               codec_dai->name, ret);
                        goto codec_err;
                }
        }
@@ -463,8 +499,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
        if (cpu_dai->driver->ops->hw_params) {
                ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: interface %s hw params failed\n",
-                               cpu_dai->name);
+                       dev_err(cpu_dai->dev, "%s hw params failed: %d\n",
+                               cpu_dai->name, ret);
                        goto interface_err;
                }
        }
@@ -472,8 +508,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
        if (platform->driver->ops && platform->driver->ops->hw_params) {
                ret = platform->driver->ops->hw_params(substream, params);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: platform %s hw params failed\n",
-                               platform->name);
+                       dev_err(platform->dev, "%s hw params failed: %d\n",
+                              platform->name, ret);
                        goto platform_err;
                }
        }
index 4220bb0f27301aa962964b9eb645fd0f5e51e17c..60053709e417b0bdcecc81d13ac676fc885021e7 100644 (file)
@@ -89,14 +89,32 @@ static struct snd_soc_platform_driver dummy_platform = {
        .ops = &dummy_dma_ops,
 };
 
+static struct snd_soc_codec_driver dummy_codec;
+static struct snd_soc_dai_driver dummy_dai = {
+       .name = "snd-soc-dummy-dai",
+};
+
 static __devinit int snd_soc_dummy_probe(struct platform_device *pdev)
 {
-       return snd_soc_register_platform(&pdev->dev, &dummy_platform);
+       int ret;
+
+       ret = snd_soc_register_codec(&pdev->dev, &dummy_codec, &dummy_dai, 1);
+       if (ret < 0)
+               return ret;
+
+       ret = snd_soc_register_platform(&pdev->dev, &dummy_platform);
+       if (ret < 0) {
+               snd_soc_unregister_codec(&pdev->dev);
+               return ret;
+       }
+
+       return ret;
 }
 
 static __devexit int snd_soc_dummy_remove(struct platform_device *pdev)
 {
        snd_soc_unregister_platform(&pdev->dev);
+       snd_soc_unregister_codec(&pdev->dev);
 
        return 0;
 }
index 4a0e805c4edd1b770cf84c85369be81d94375d2f..2a27725cc9b1687a9a7ee4d8f40d953c9eb3e7ec 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
+#include <linux/of_gpio.h>
 
 #include <sound/core.h>
 #include <sound/jack.h>
 
 #define DRV_NAME "tegra-alc5632"
 
+#define GPIO_HP_DET     BIT(0)
+
 struct tegra_alc5632 {
        struct tegra_asoc_utils_data util_data;
+       struct platform_device *pcm_dev;
+       int gpio_requested;
+       int gpio_hp_det;
 };
 
 static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream,
@@ -85,24 +91,18 @@ static struct snd_soc_jack_pin tegra_alc5632_hs_jack_pins[] = {
        },
 };
 
+static struct snd_soc_jack_gpio tegra_alc5632_hp_jack_gpio = {
+       .name = "Headset detection",
+       .report = SND_JACK_HEADSET,
+       .debounce_time = 150,
+       .invert = 1,
+};
+
 static const struct snd_soc_dapm_widget tegra_alc5632_dapm_widgets[] = {
        SND_SOC_DAPM_SPK("Int Spk", NULL),
        SND_SOC_DAPM_HP("Headset Stereophone", NULL),
        SND_SOC_DAPM_MIC("Headset Mic", NULL),
-};
-
-static const struct snd_soc_dapm_route tegra_alc5632_audio_map[] = {
-       /* Internal Speaker */
-       {"Int Spk", NULL, "SPKOUT"},
-       {"Int Spk", NULL, "SPKOUTN"},
-
-       /* Headset Mic */
-       {"MIC1", NULL, "MICBIAS1"},
-       {"MICBIAS1", NULL, "Headset Mic"},
-
-       /* Headset Stereophone */
-       {"Headset Stereophone", NULL, "HPR"},
-       {"Headset Stereophone", NULL, "HPL"},
+       SND_SOC_DAPM_MIC("Digital Mic", NULL),
 };
 
 static const struct snd_kcontrol_new tegra_alc5632_controls[] = {
@@ -113,6 +113,9 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_codec *codec = rtd->codec;
        struct snd_soc_dapm_context *dapm = &codec->dapm;
+       struct device_node *np = codec->card->dev->of_node;
+       struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card);
+       int ret;
 
        snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
                         &tegra_alc5632_hs_jack);
@@ -120,6 +123,16 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
                        ARRAY_SIZE(tegra_alc5632_hs_jack_pins),
                        tegra_alc5632_hs_jack_pins);
 
+       machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
+
+       if (gpio_is_valid(machine->gpio_hp_det)) {
+               tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det;
+               snd_soc_jack_add_gpios(&tegra_alc5632_hs_jack,
+                                               1,
+                                               &tegra_alc5632_hp_jack_gpio);
+               machine->gpio_requested |= GPIO_HP_DET;
+       }
+
        snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1");
 
        return 0;
@@ -128,9 +141,7 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
 static struct snd_soc_dai_link tegra_alc5632_dai = {
        .name = "ALC5632",
        .stream_name = "ALC5632 PCM",
-       .codec_name = "alc5632.0-001e",
        .platform_name = "tegra-pcm-audio",
-       .cpu_dai_name = "tegra-i2s.0",
        .codec_dai_name = "alc5632-hifi",
        .init = tegra_alc5632_asoc_init,
        .ops = &tegra_alc5632_asoc_ops,
@@ -148,8 +159,6 @@ static struct snd_soc_card snd_soc_tegra_alc5632 = {
        .num_controls = ARRAY_SIZE(tegra_alc5632_controls),
        .dapm_widgets = tegra_alc5632_dapm_widgets,
        .num_dapm_widgets = ARRAY_SIZE(tegra_alc5632_dapm_widgets),
-       .dapm_routes = tegra_alc5632_audio_map,
-       .num_dapm_routes = ARRAY_SIZE(tegra_alc5632_audio_map),
        .fully_routed = true,
 };
 
@@ -163,45 +172,111 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
                        sizeof(struct tegra_alc5632), GFP_KERNEL);
        if (!alc5632) {
                dev_err(&pdev->dev, "Can't allocate tegra_alc5632\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto err;
        }
 
-       ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev);
-       if (ret)
-               return ret;
-
        card->dev = &pdev->dev;
        platform_set_drvdata(pdev, card);
        snd_soc_card_set_drvdata(card, alc5632);
 
+       alc5632->pcm_dev = ERR_PTR(-EINVAL);
+
+       if (!(pdev->dev.of_node)) {
+               dev_err(&pdev->dev, "Must be instantiated using device tree\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       ret = snd_soc_of_parse_card_name(card, "nvidia,model");
+       if (ret)
+               goto err;
+
+       ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
+       if (ret)
+               goto err;
+
+       tegra_alc5632_dai.codec_of_node = of_parse_phandle(
+                       pdev->dev.of_node, "nvidia,audio-codec", 0);
+
+       if (!tegra_alc5632_dai.codec_of_node) {
+               dev_err(&pdev->dev,
+                       "Property 'nvidia,audio-codec' missing or invalid\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       tegra_alc5632_dai.cpu_dai_of_node = of_parse_phandle(
+                       pdev->dev.of_node, "nvidia,i2s-controller", 0);
+       if (!tegra_alc5632_dai.cpu_dai_of_node) {
+               dev_err(&pdev->dev,
+               "Property 'nvidia,i2s-controller' missing or invalid\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       alc5632->pcm_dev = platform_device_register_simple(
+               "tegra-pcm-audio", -1, NULL, 0);
+       if (IS_ERR(alc5632->pcm_dev)) {
+               dev_err(&pdev->dev,
+                       "Can't instantiate tegra-pcm-audio\n");
+               ret = PTR_ERR(alc5632->pcm_dev);
+               goto err;
+       }
+
+       ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev);
+       if (ret)
+               goto err_unregister;
+
        ret = snd_soc_register_card(card);
        if (ret) {
                dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
                        ret);
-               tegra_asoc_utils_fini(&alc5632->util_data);
-               return ret;
+               goto err_fini_utils;
        }
 
        return 0;
+
+err_fini_utils:
+       tegra_asoc_utils_fini(&alc5632->util_data);
+err_unregister:
+       if (!IS_ERR(alc5632->pcm_dev))
+               platform_device_unregister(alc5632->pcm_dev);
+err:
+       return ret;
 }
 
 static int __devexit tegra_alc5632_remove(struct platform_device *pdev)
 {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
-       struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card);
+       struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card);
+
+       if (machine->gpio_requested & GPIO_HP_DET)
+               snd_soc_jack_free_gpios(&tegra_alc5632_hs_jack,
+                                       1,
+                                       &tegra_alc5632_hp_jack_gpio);
+       machine->gpio_requested = 0;
 
        snd_soc_unregister_card(card);
 
-       tegra_asoc_utils_fini(&alc5632->util_data);
+       tegra_asoc_utils_fini(&machine->util_data);
+       if (!IS_ERR(machine->pcm_dev))
+               platform_device_unregister(machine->pcm_dev);
 
        return 0;
 }
 
+static const struct of_device_id tegra_alc5632_of_match[] __devinitconst = {
+       { .compatible = "nvidia,tegra-audio-alc5632", },
+       {},
+};
+
 static struct platform_driver tegra_alc5632_driver = {
        .driver = {
                .name = DRV_NAME,
                .owner = THIS_MODULE,
                .pm = &snd_soc_pm_ops,
+               .of_match_table = tegra_alc5632_of_match,
        },
        .probe = tegra_alc5632_probe,
        .remove = __devexit_p(tegra_alc5632_remove),
@@ -212,3 +287,4 @@ MODULE_AUTHOR("Leon Romanovsky <leon@leon.nu>");
 MODULE_DESCRIPTION("Tegra+ALC5632 machine ASoC driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_alc5632_of_match);
index c22431516ab200ebcdc9b2b1b86894afb8cf5a3a..8b4457137c7ca7a451cad16e41fb274010a2d380 100644 (file)
@@ -336,7 +336,7 @@ static int tegra_pcm_new(struct snd_soc_pcm_runtime *rtd)
        if (!card->dev->dma_mask)
                card->dev->dma_mask = &tegra_dma_mask;
        if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = 0xffffffff;
+               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = tegra_pcm_preallocate_dma_buffer(pcm,