Merge branch 'topic/asoc' into for-linus
authorTakashi Iwai <tiwai@suse.de>
Thu, 27 Oct 2011 08:43:40 +0000 (10:43 +0200)
committerTakashi Iwai <tiwai@suse.de>
Thu, 27 Oct 2011 08:43:40 +0000 (10:43 +0200)
186 files changed:
MAINTAINERS
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/plat-omap/devices.c
drivers/input/misc/twl6040-vibra.c
drivers/mfd/twl6040-core.c
drivers/mfd/wm8994-core.c
drivers/regulator/core.c
drivers/regulator/wm8994-regulator.c
include/linux/mfd/twl6040.h
include/linux/mfd/wm8994/core.h
include/linux/mfd/wm8994/registers.h
include/sound/soc-dai.h
include/sound/soc-dapm.h
include/sound/soc.h
include/sound/tpa6130a2-plat.h
include/sound/wm1250-ev1.h [new file with mode: 0644]
include/sound/wm5100.h [new file with mode: 0644]
include/trace/events/asoc.h
sound/soc/atmel/playpaq_wm8510.c
sound/soc/atmel/sam9g20_wm8731.c
sound/soc/atmel/snd-soc-afeb9260.c
sound/soc/au1x/ac97c.c
sound/soc/au1x/i2sc.c
sound/soc/au1x/psc-ac97.c
sound/soc/au1x/psc-i2s.c
sound/soc/blackfin/bf5xx-ac97-pcm.c
sound/soc/blackfin/bf5xx-i2s-pcm.c
sound/soc/codecs/88pm860x-codec.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ad193x.c
sound/soc/codecs/ad193x.h
sound/soc/codecs/ad1980.c
sound/soc/codecs/adau1373.c
sound/soc/codecs/adau1701.c
sound/soc/codecs/ads117x.h [deleted file]
sound/soc/codecs/ak4104.c
sound/soc/codecs/ak4535.c
sound/soc/codecs/ak4641.c
sound/soc/codecs/ak4642.c
sound/soc/codecs/ak4671.c
sound/soc/codecs/alc5623.c
sound/soc/codecs/cs4270.c
sound/soc/codecs/cs4271.c
sound/soc/codecs/cs42l51.c
sound/soc/codecs/da7210.c
sound/soc/codecs/lm4857.c
sound/soc/codecs/max98088.c
sound/soc/codecs/max98095.c
sound/soc/codecs/rt5631.c [new file with mode: 0644]
sound/soc/codecs/rt5631.h [new file with mode: 0644]
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/sgtl5000.h
sound/soc/codecs/sn95031.c
sound/soc/codecs/ssm2602.c
sound/soc/codecs/ssm2602.h
sound/soc/codecs/sta32x.c
sound/soc/codecs/tlv320aic23.c
sound/soc/codecs/tlv320aic32x4.c
sound/soc/codecs/tlv320aic3x.c
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/wl1273.c
sound/soc/codecs/wm1250-ev1.c
sound/soc/codecs/wm5100-tables.c [new file with mode: 0644]
sound/soc/codecs/wm5100.c [new file with mode: 0644]
sound/soc/codecs/wm5100.h [new file with mode: 0644]
sound/soc/codecs/wm8350.c
sound/soc/codecs/wm8400.c
sound/soc/codecs/wm8510.c
sound/soc/codecs/wm8523.c
sound/soc/codecs/wm8580.c
sound/soc/codecs/wm8711.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8741.c
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8776.c
sound/soc/codecs/wm8782.c
sound/soc/codecs/wm8900.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8940.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/wm8983.c
sound/soc/codecs/wm8988.c
sound/soc/codecs/wm8990.c
sound/soc/codecs/wm8991.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8995.c
sound/soc/codecs/wm8996.c
sound/soc/codecs/wm9081.c
sound/soc/codecs/wm9090.c
sound/soc/codecs/wm_hubs.c
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-i2s.c
sound/soc/ep93xx/ep93xx-ac97.c
sound/soc/imx/Kconfig
sound/soc/imx/imx-pcm-fiq.c
sound/soc/imx/imx-ssi.c
sound/soc/imx/imx-ssi.h
sound/soc/jz4740/jz4740-pcm.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/kirkwood/kirkwood-t5325.c
sound/soc/mid-x86/mfld_machine.c
sound/soc/mid-x86/sst_platform.c
sound/soc/mxs/mxs-saif.c
sound/soc/nuc900/nuc900-pcm.c
sound/soc/omap/Makefile
sound/soc/omap/am3517evm.c
sound/soc/omap/ams-delta.c
sound/soc/omap/igep0020.c
sound/soc/omap/mcpdm.c [deleted file]
sound/soc/omap/mcpdm.h [deleted file]
sound/soc/omap/n810.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcpdm.c
sound/soc/omap/omap-mcpdm.h [new file with mode: 0644]
sound/soc/omap/omap-pcm.c
sound/soc/omap/omap3evm.c
sound/soc/omap/omap3pandora.c
sound/soc/omap/osk5912.c
sound/soc/omap/overo.c
sound/soc/omap/rx51.c
sound/soc/omap/sdp3430.c
sound/soc/omap/sdp4430.c
sound/soc/omap/zoom2.c
sound/soc/pxa/Kconfig
sound/soc/pxa/corgi.c
sound/soc/pxa/e740_wm9705.c
sound/soc/pxa/e750_wm9705.c
sound/soc/pxa/e800_wm9712.c
sound/soc/pxa/magician.c
sound/soc/pxa/mioa701_wm9713.c
sound/soc/pxa/palm27x.c
sound/soc/pxa/poodle.c
sound/soc/pxa/saarb.c
sound/soc/pxa/spitz.c
sound/soc/pxa/tavorevb3.c
sound/soc/pxa/tosa.c
sound/soc/pxa/z2.c
sound/soc/pxa/zylonite.c
sound/soc/samsung/Kconfig
sound/soc/samsung/ac97.c
sound/soc/samsung/goni_wm8994.c
sound/soc/samsung/h1940_uda1380.c
sound/soc/samsung/i2s.c
sound/soc/samsung/jive_wm8750.c
sound/soc/samsung/neo1973_wm8753.c
sound/soc/samsung/pcm.c
sound/soc/samsung/rx1950_uda1380.c
sound/soc/samsung/s3c-i2s-v2.c
sound/soc/samsung/s3c2412-i2s.c
sound/soc/samsung/s3c24xx-i2s.c
sound/soc/samsung/s3c24xx_simtec.c
sound/soc/samsung/s3c24xx_simtec_hermes.c
sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
sound/soc/samsung/smartq_wm8987.c
sound/soc/samsung/smdk_wm8580.c
sound/soc/samsung/smdk_wm8994.c
sound/soc/samsung/spdif.c
sound/soc/samsung/speyside_wm8962.c
sound/soc/sh/fsi.c
sound/soc/sh/sh7760-ac97.c
sound/soc/sh/ssi.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-io.c
sound/soc/soc-jack.c
sound/soc/soc-pcm.c
sound/soc/tegra/tegra_das.c
sound/soc/tegra/tegra_i2s.c
sound/soc/tegra/tegra_pcm.c
sound/soc/tegra/tegra_spdif.c
sound/soc/tegra/tegra_wm8903.c
sound/soc/tegra/trimslice.c
sound/soc/txx9/txx9aclc-generic.c

index a676343..1dbbb27 100644 (file)
@@ -530,6 +530,7 @@ S:  Maintained
 F:     drivers/infiniband/hw/amso1100/
 
 ANALOG DEVICES INC ASOC CODEC DRIVERS
+M:     Lars-Peter Clausen <lars@metafoo.de>
 L:     device-drivers-devel@blackfin.uclinux.org
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 W:     http://wiki.analog.com/
@@ -7199,6 +7200,7 @@ T:        git git://opensource.wolfsonmicro.com/linux-2.6-audioplus
 W:     http://opensource.wolfsonmicro.com/content/linux-drivers-wolfson-devices
 S:     Supported
 F:     Documentation/hwmon/wm83??
+F:     arch/arm/mach-s3c64xx/mach-crag6410*
 F:     drivers/leds/leds-wm83*.c
 F:     drivers/input/misc/wm831x-on.c
 F:     drivers/input/touchscreen/wm831x-ts.c
index 5a886cd..ba1aa07 100644 (file)
@@ -900,7 +900,6 @@ static struct twl4030_platform_data rx51_twldata __initdata = {
 };
 
 static struct tpa6130a2_platform_data rx51_tpa6130a2_data __initdata_or_module = {
-       .id                     = TPA6130A2,
        .power_gpio             = 98,
 };
 
index 1077ad6..3f0b143 100644 (file)
@@ -330,6 +330,38 @@ static void omap_init_audio(void)
 static inline void omap_init_audio(void) {}
 #endif
 
+#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \
+               defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE)
+
+static struct omap_device_pm_latency omap_mcpdm_latency[] = {
+       {
+               .deactivate_func = omap_device_idle_hwmods,
+               .activate_func = omap_device_enable_hwmods,
+               .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+       },
+};
+
+static void omap_init_mcpdm(void)
+{
+       struct omap_hwmod *oh;
+       struct omap_device *od;
+
+       oh = omap_hwmod_lookup("mcpdm");
+       if (!oh) {
+               printk(KERN_ERR "Could not look up mcpdm hw_mod\n");
+               return;
+       }
+
+       od = omap_device_build("omap-mcpdm", -1, oh, NULL, 0,
+                               omap_mcpdm_latency,
+                               ARRAY_SIZE(omap_mcpdm_latency), 0);
+       if (IS_ERR(od))
+               printk(KERN_ERR "Could not build omap_device for omap-mcpdm-dai\n");
+}
+#else
+static inline void omap_init_mcpdm(void) {}
+#endif
+
 #if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
 
 #include <plat/mcspi.h>
@@ -683,6 +715,7 @@ static int __init omap2_init_devices(void)
         * in alphabetical order so they're easier to sort through.
         */
        omap_init_audio();
+       omap_init_mcpdm();
        omap_init_camera();
        omap_init_mbox();
        omap_init_mcspi();
index 6201422..79325c6 100644 (file)
@@ -5430,7 +5430,7 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
        &omap44xx_mcbsp4_hwmod,
 
        /* mcpdm class */
-/*     &omap44xx_mcpdm_hwmod, */
+       &omap44xx_mcpdm_hwmod,
 
        /* mcspi class */
        &omap44xx_mcspi1_hwmod,
index ea28f98..40eca9b 100644 (file)
@@ -74,41 +74,6 @@ void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
 
 /*-------------------------------------------------------------------------*/
 
-#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \
-               defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE)
-
-static struct resource mcpdm_resources[] = {
-       {
-               .name           = "mcpdm_mem",
-               .start          = OMAP44XX_MCPDM_BASE,
-               .end            = OMAP44XX_MCPDM_BASE + SZ_4K,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .name           = "mcpdm_irq",
-               .start          = OMAP44XX_IRQ_MCPDM,
-               .end            = OMAP44XX_IRQ_MCPDM,
-               .flags          = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device omap_mcpdm_device = {
-       .name           = "omap-mcpdm",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(mcpdm_resources),
-       .resource       = mcpdm_resources,
-};
-
-static void omap_init_mcpdm(void)
-{
-       (void) platform_device_register(&omap_mcpdm_device);
-}
-#else
-static inline void omap_init_mcpdm(void) {}
-#endif
-
-/*-------------------------------------------------------------------------*/
-
 #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
        defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
@@ -291,7 +256,6 @@ static int __init omap_init_devices(void)
         * in alphabetical order so they're easier to sort through.
         */
        omap_init_rng();
-       omap_init_mcpdm();
        omap_init_uwire();
        return 0;
 }
index 154b7a3..2a828e5 100644 (file)
@@ -74,12 +74,12 @@ static irqreturn_t twl6040_vib_irq_handler(int irq, void *data)
        if (status & TWL6040_VIBLOCDET) {
                dev_warn(info->dev, "Left Vibrator overcurrent detected\n");
                twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLL,
-                                  TWL6040_VIBENAL);
+                                  TWL6040_VIBENA);
        }
        if (status & TWL6040_VIBROCDET) {
                dev_warn(info->dev, "Right Vibrator overcurrent detected\n");
                twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLR,
-                                  TWL6040_VIBENAR);
+                                  TWL6040_VIBENA);
        }
 
        return IRQ_HANDLED;
@@ -104,16 +104,16 @@ static void twl6040_vibra_enable(struct vibra_info *info)
                 * overcurrent detection
                 */
                twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
-                                 TWL6040_VIBENAL | TWL6040_VIBCTRLL);
+                                 TWL6040_VIBENA | TWL6040_VIBCTRL);
                twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
-                                 TWL6040_VIBENAR | TWL6040_VIBCTRLR);
+                                 TWL6040_VIBENA | TWL6040_VIBCTRL);
                usleep_range(3000, 3500);
        }
 
        twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLL,
-                         TWL6040_VIBENAL);
+                         TWL6040_VIBENA);
        twl6040_reg_write(twl6040, TWL6040_REG_VIBCTLR,
-                         TWL6040_VIBENAR);
+                         TWL6040_VIBENA);
 
        info->enabled = true;
 }
@@ -201,6 +201,13 @@ static int vibra_play(struct input_dev *input, void *data,
        struct vibra_info *info = input_get_drvdata(input);
        int ret;
 
+       /* Do not allow effect, while the routing is set to use audio */
+       ret = twl6040_get_vibralr_status(info->twl6040);
+       if (ret & TWL6040_VIBSEL) {
+               dev_info(&input->dev, "Vibra is configured for audio\n");
+               return -EBUSY;
+       }
+
        info->weak_speed = effect->u.rumble.weak_magnitude;
        info->strong_speed = effect->u.rumble.strong_magnitude;
        info->direction = effect->direction < EFFECT_DIR_180_DEG ? 1 : -1;
index 7dc8c47..268f80f 100644 (file)
 #include <linux/mfd/core.h>
 #include <linux/mfd/twl6040.h>
 
+#define VIBRACTRL_MEMBER(reg) ((reg == TWL6040_REG_VIBCTLL) ? 0 : 1)
+
 int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
 {
        int ret;
        u8 val = 0;
 
        mutex_lock(&twl6040->io_mutex);
-       ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
-       if (ret < 0) {
-               mutex_unlock(&twl6040->io_mutex);
-               return ret;
+       /* Vibra control registers from cache */
+       if (unlikely(reg == TWL6040_REG_VIBCTLL ||
+                    reg == TWL6040_REG_VIBCTLR)) {
+               val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)];
+       } else {
+               ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
+               if (ret < 0) {
+                       mutex_unlock(&twl6040->io_mutex);
+                       return ret;
+               }
        }
        mutex_unlock(&twl6040->io_mutex);
 
@@ -57,6 +65,9 @@ int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val)
 
        mutex_lock(&twl6040->io_mutex);
        ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
+       /* Cache the vibra control registers */
+       if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR)
+               twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val;
        mutex_unlock(&twl6040->io_mutex);
 
        return ret;
@@ -433,6 +444,18 @@ unsigned int twl6040_get_sysclk(struct twl6040 *twl6040)
 }
 EXPORT_SYMBOL(twl6040_get_sysclk);
 
+/* Get the combined status of the vibra control register */
+int twl6040_get_vibralr_status(struct twl6040 *twl6040)
+{
+       u8 status;
+
+       status = twl6040->vibra_ctrl_cache[0] | twl6040->vibra_ctrl_cache[1];
+       status &= (TWL6040_VIBENA | TWL6040_VIBSEL);
+
+       return status;
+}
+EXPORT_SYMBOL(twl6040_get_vibralr_status);
+
 static struct resource twl6040_vibra_rsrc[] = {
        {
                .flags = IORESOURCE_IRQ,
index 96479c9..7c13ab2 100644 (file)
@@ -243,6 +243,18 @@ static struct mfd_cell wm8994_devs[] = {
  * and should be handled via the standard regulator API supply
  * management.
  */
+static const char *wm1811_main_supplies[] = {
+       "DBVDD1",
+       "DBVDD2",
+       "DBVDD3",
+       "DCVDD",
+       "AVDD1",
+       "AVDD2",
+       "CPVDD",
+       "SPKVDD1",
+       "SPKVDD2",
+};
+
 static const char *wm8994_main_supplies[] = {
        "DBVDD",
        "DCVDD",
@@ -401,6 +413,9 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
        }
 
        switch (wm8994->type) {
+       case WM1811:
+               wm8994->num_supplies = ARRAY_SIZE(wm1811_main_supplies);
+               break;
        case WM8994:
                wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies);
                break;
@@ -421,6 +436,10 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
        }
 
        switch (wm8994->type) {
+       case WM1811:
+               for (i = 0; i < ARRAY_SIZE(wm1811_main_supplies); i++)
+                       wm8994->supplies[i].supply = wm1811_main_supplies[i];
+               break;
        case WM8994:
                for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++)
                        wm8994->supplies[i].supply = wm8994_main_supplies[i];
@@ -454,6 +473,13 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
                goto err_enable;
        }
        switch (ret) {
+       case 0x1811:
+               devname = "WM1811";
+               if (wm8994->type != WM1811)
+                       dev_warn(wm8994->dev, "Device registered as type %d\n",
+                                wm8994->type);
+               wm8994->type = WM1811;
+               break;
        case 0x8994:
                devname = "WM8994";
                if (wm8994->type != WM8994)
@@ -651,6 +677,7 @@ static int wm8994_i2c_remove(struct i2c_client *i2c)
 }
 
 static const struct i2c_device_id wm8994_i2c_id[] = {
+       { "wm1811", WM1811 },
        { "wm8994", WM8994 },
        { "wm8958", WM8958 },
        { }
index d0bde70..9e4c123 100644 (file)
@@ -1599,13 +1599,18 @@ static void regulator_disable_work(struct work_struct *work)
 int regulator_disable_deferred(struct regulator *regulator, int ms)
 {
        struct regulator_dev *rdev = regulator->rdev;
+       int ret;
 
        mutex_lock(&rdev->mutex);
        rdev->deferred_disables++;
        mutex_unlock(&rdev->mutex);
 
-       return schedule_delayed_work(&rdev->disable_work,
-                                    msecs_to_jiffies(ms));
+       ret = schedule_delayed_work(&rdev->disable_work,
+                                   msecs_to_jiffies(ms));
+       if (ret < 0)
+               return ret;
+       else
+               return 0;
 }
 EXPORT_SYMBOL_GPL(regulator_disable_deferred);
 
index 1a6a690..b87bf5c 100644 (file)
@@ -140,6 +140,14 @@ static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev,
                return (selector * 100000) + 900000;
        case WM8958:
                return (selector * 100000) + 1000000;
+       case WM1811:
+               switch (selector) {
+               case 0:
+                       return -EINVAL;
+               default:
+                       return (selector * 100000) + 950000;
+               }
+               break;
        default:
                return -EINVAL;
        }
@@ -170,6 +178,11 @@ static int wm8994_ldo2_set_voltage(struct regulator_dev *rdev,
        case WM8958:
                selector = (min_uV - 1000000) / 100000;
                break;
+       case WM1811:
+               selector = (min_uV - 950000) / 100000;
+               if (selector == 0)
+                       selector = 1;
+               break;
        default:
                return -EINVAL;
        }
index ec1ec79..2463c26 100644 (file)
@@ -68,8 +68,6 @@
 #define TWL6040_REG_ACCCTL             0x2D
 #define TWL6040_REG_STATUS             0x2E
 
-#define TWL6040_CACHEREGNUM            (TWL6040_REG_STATUS + 1)
-
 /* INTID (0x03) fields */
 
 #define TWL6040_THINT                  0x01
 #define TWL6040_LPLLFIN                        0x08
 #define TWL6040_HPLLSEL                        0x10
 
-/* HSLCTL (0x10) fields */
-
-#define TWL6040_HSDACMODEL             0x02
-#define TWL6040_HSDRVMODEL             0x08
-
-/* HSRCTL (0x11) fields */
+/* HSLCTL/R (0x10/0x11) fields */
 
-#define TWL6040_HSDACMODER             0x02
-#define TWL6040_HSDRVMODER             0x08
+#define TWL6040_HSDACENA               (1 << 0)
+#define TWL6040_HSDACMODE              (1 << 1)
+#define TWL6040_HSDRVMODE              (1 << 3)
 
-/* VIBCTLL (0x18) fields */
+/* VIBCTLL/R (0x18/0x1A) fields */
 
-#define TWL6040_VIBENAL                        0x01
-#define TWL6040_VIBCTRLL               0x04
-#define TWL6040_VIBCTRLLP              0x08
-#define TWL6040_VIBCTRLLN              0x10
+#define TWL6040_VIBENA                 (1 << 0)
+#define TWL6040_VIBSEL                 (1 << 1)
+#define TWL6040_VIBCTRL                        (1 << 2)
+#define TWL6040_VIBCTRL_P              (1 << 3)
+#define TWL6040_VIBCTRL_N              (1 << 4)
 
-/* VIBDATL (0x19) fields */
+/* VIBDATL/R (0x19/0x1B) fields */
 
 #define TWL6040_VIBDAT_MAX             0x64
 
-/* VIBCTLR (0x1A) fields */
-
-#define TWL6040_VIBENAR                        0x01
-#define TWL6040_VIBCTRLR               0x04
-#define TWL6040_VIBCTRLRP              0x08
-#define TWL6040_VIBCTRLRN              0x10
-
 /* GPOCTL (0x1E) fields */
 
 #define TWL6040_GPO1                   0x01
@@ -197,6 +185,7 @@ struct twl6040 {
        int audpwron;
        int power_count;
        int rev;
+       u8 vibra_ctrl_cache[2];
 
        int pll;
        unsigned int sysclk;
@@ -221,10 +210,13 @@ int twl6040_get_pll(struct twl6040 *twl6040);
 unsigned int twl6040_get_sysclk(struct twl6040 *twl6040);
 int twl6040_irq_init(struct twl6040 *twl6040);
 void twl6040_irq_exit(struct twl6040 *twl6040);
+/* Get the combined status of the vibra control register */
+int twl6040_get_vibralr_status(struct twl6040 *twl6040);
 
 static inline int twl6040_get_revid(struct twl6040 *twl6040)
 {
        return twl6040->rev;
 }
 
+
 #endif  /* End of __TWL6040_CODEC_H__ */
index f0b69cd..bfb221b 100644 (file)
@@ -20,6 +20,7 @@
 enum wm8994_type {
        WM8994 = 0,
        WM8958 = 1,
+       WM1811 = 2,
 };
 
 struct regulator_dev;
index 83ecdcd..fae2950 100644 (file)
 /*
  * R96 (0x60) - Analogue HP (1)
  */
+#define WM1811_HPOUT1_ATTN                      0x0100  /* HPOUT1_ATTN */
+#define WM1811_HPOUT1_ATTN_MASK                 0x0100  /* HPOUT1_ATTN */
+#define WM1811_HPOUT1_ATTN_SHIFT                     8  /* HPOUT1_ATTN */
+#define WM1811_HPOUT1_ATTN_WIDTH                     1  /* HPOUT1_ATTN */
 #define WM8994_HPOUT1L_RMV_SHORT                0x0080  /* HPOUT1L_RMV_SHORT */
 #define WM8994_HPOUT1L_RMV_SHORT_MASK           0x0080  /* HPOUT1L_RMV_SHORT */
 #define WM8994_HPOUT1L_RMV_SHORT_SHIFT               7  /* HPOUT1L_RMV_SHORT */
index 5ad5f3a..2413acc 100644 (file)
@@ -24,13 +24,13 @@ struct snd_pcm_substream;
  * Describes the physical PCM data formating and clocking. Add new formats
  * to the end.
  */
-#define SND_SOC_DAIFMT_I2S             0 /* I2S mode */
-#define SND_SOC_DAIFMT_RIGHT_J         1 /* Right Justified mode */
-#define SND_SOC_DAIFMT_LEFT_J          2 /* Left Justified mode */
-#define SND_SOC_DAIFMT_DSP_A           3 /* L data MSB after FRM LRC */
-#define SND_SOC_DAIFMT_DSP_B           4 /* L data MSB during FRM LRC */
-#define SND_SOC_DAIFMT_AC97            5 /* AC97 */
-#define SND_SOC_DAIFMT_PDM             6 /* Pulse density modulation */
+#define SND_SOC_DAIFMT_I2S             1 /* I2S mode */
+#define SND_SOC_DAIFMT_RIGHT_J         2 /* Right Justified mode */
+#define SND_SOC_DAIFMT_LEFT_J          3 /* Left Justified mode */
+#define SND_SOC_DAIFMT_DSP_A           4 /* L data MSB after FRM LRC */
+#define SND_SOC_DAIFMT_DSP_B           5 /* L data MSB during FRM LRC */
+#define SND_SOC_DAIFMT_AC97            6 /* AC97 */
+#define SND_SOC_DAIFMT_PDM             7 /* Pulse density modulation */
 
 /* left and right justified also known as MSB and LSB respectively */
 #define SND_SOC_DAIFMT_MSB             SND_SOC_DAIFMT_LEFT_J
@@ -42,8 +42,8 @@ struct snd_pcm_substream;
  * DAI bit clocks can be be gated (disabled) when the DAI is not
  * sending or receiving PCM data in a frame. This can be used to save power.
  */
-#define SND_SOC_DAIFMT_CONT            (0 << 4) /* continuous clock */
-#define SND_SOC_DAIFMT_GATED           (1 << 4) /* clock is gated */
+#define SND_SOC_DAIFMT_CONT            (1 << 4) /* continuous clock */
+#define SND_SOC_DAIFMT_GATED           (2 << 4) /* clock is gated */
 
 /*
  * DAI hardware signal inversions.
@@ -51,10 +51,10 @@ struct snd_pcm_substream;
  * Specifies whether the DAI can also support inverted clocks for the specified
  * format.
  */
-#define SND_SOC_DAIFMT_NB_NF           (0 << 8) /* normal bit clock + frame */
-#define SND_SOC_DAIFMT_NB_IF           (1 << 8) /* normal BCLK + inv FRM */
-#define SND_SOC_DAIFMT_IB_NF           (2 << 8) /* invert BCLK + nor FRM */
-#define SND_SOC_DAIFMT_IB_IF           (3 << 8) /* invert BCLK + FRM */
+#define SND_SOC_DAIFMT_NB_NF           (1 << 8) /* normal bit clock + frame */
+#define SND_SOC_DAIFMT_NB_IF           (2 << 8) /* normal BCLK + inv FRM */
+#define SND_SOC_DAIFMT_IB_NF           (3 << 8) /* invert BCLK + nor FRM */
+#define SND_SOC_DAIFMT_IB_IF           (4 << 8) /* invert BCLK + FRM */
 
 /*
  * DAI hardware clock masters.
@@ -63,10 +63,10 @@ struct snd_pcm_substream;
  * i.e. if the codec is clk and FRM master then the interface is
  * clk and frame slave.
  */
-#define SND_SOC_DAIFMT_CBM_CFM         (0 << 12) /* codec clk & FRM master */
-#define SND_SOC_DAIFMT_CBS_CFM         (1 << 12) /* codec clk slave & FRM master */
-#define SND_SOC_DAIFMT_CBM_CFS         (2 << 12) /* codec clk master & frame slave */
-#define SND_SOC_DAIFMT_CBS_CFS         (3 << 12) /* codec clk & FRM slave */
+#define SND_SOC_DAIFMT_CBM_CFM         (1 << 12) /* codec clk & FRM master */
+#define SND_SOC_DAIFMT_CBS_CFM         (2 << 12) /* codec clk slave & FRM master */
+#define SND_SOC_DAIFMT_CBM_CFS         (3 << 12) /* codec clk master & frame slave */
+#define SND_SOC_DAIFMT_CBS_CFS         (4 << 12) /* codec clk & FRM slave */
 
 #define SND_SOC_DAIFMT_FORMAT_MASK     0x000f
 #define SND_SOC_DAIFMT_CLOCK_MASK      0x00f0
@@ -242,6 +242,9 @@ struct snd_soc_dai {
        void *playback_dma_data;
        void *capture_dma_data;
 
+       /* Symmetry data - only valid if symmetry is being enforced */
+       unsigned int rate;
+
        /* parent platform/codec */
        union {
                struct snd_soc_platform *platform;
index 350b1b3..17a4c17 100644 (file)
@@ -381,6 +381,9 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
 int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
                                const char *pin);
 
+/* Mostly internal - should not normally be used */
+void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason);
+
 /* dapm widget types */
 enum snd_soc_dapm_type {
        snd_soc_dapm_input = 0,         /* input pin */
@@ -473,6 +476,8 @@ struct snd_soc_dapm_widget {
        unsigned char ext:1;                    /* has external widgets */
        unsigned char force:1;                  /* force state */
        unsigned char ignore_suspend:1;         /* kept enabled over suspend */
+       unsigned char new_power:1;              /* power from this run */
+       unsigned char power_checked:1;          /* power checked this run */
        int subseq;                             /* sort within widget type */
 
        int (*power_check)(struct snd_soc_dapm_widget *w);
@@ -492,6 +497,9 @@ struct snd_soc_dapm_widget {
 
        /* used during DAPM updates */
        struct list_head power_list;
+       struct list_head dirty;
+       int inputs;
+       int outputs;
 };
 
 struct snd_soc_dapm_update {
@@ -537,4 +545,10 @@ struct snd_soc_dapm_widget_list {
        struct snd_soc_dapm_widget *widgets[0];
 };
 
+struct snd_soc_dapm_stats {
+       int power_checks;
+       int path_checks;
+       int neighbour_checks;
+};
+
 #endif
index 24e17be..11cfb59 100644 (file)
 /*
  * Convenience kcontrol builders
  */
-#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \
+#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert) \
        ((unsigned long)&(struct soc_mixer_control) \
-       {.reg = xreg, .shift = xshift, .rshift = xshift, .max = xmax, \
-       .platform_max = xmax, .invert = xinvert})
+       {.reg = xreg, .rreg = xreg, .shift = shift_left, \
+       .rshift = shift_right, .max = xmax, .platform_max = xmax, \
+       .invert = xinvert})
+#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \
+       SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert)
 #define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
        ((unsigned long)&(struct soc_mixer_control) \
        {.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert})
+#define SOC_DOUBLE_R_VALUE(xlreg, xrreg, xshift, xmax, xinvert) \
+       ((unsigned long)&(struct soc_mixer_control) \
+       {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \
+       .max = xmax, .platform_max = xmax, .invert = xinvert})
 #define SOC_SINGLE(xname, reg, shift, max, invert) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
        .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
        .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
        .put = snd_soc_put_volsw, \
        .private_value =  SOC_SINGLE_VALUE(reg, shift, max, invert) }
-#define SOC_DOUBLE(xname, xreg, shift_left, shift_right, xmax, xinvert) \
+#define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
        .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
        .put = snd_soc_put_volsw, \
-       .private_value = (unsigned long)&(struct soc_mixer_control) \
-               {.reg = xreg, .shift = shift_left, .rshift = shift_right, \
-                .max = xmax, .platform_max = xmax, .invert = xinvert} }
+       .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
+                                         max, invert) }
 #define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
-       .info = snd_soc_info_volsw_2r, \
-       .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
-       .private_value = (unsigned long)&(struct soc_mixer_control) \
-               {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
-               .max = xmax, .platform_max = xmax, .invert = xinvert} }
-#define SOC_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert, tlv_array) \
+       .info = snd_soc_info_volsw, \
+       .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
+       .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
+                                           xmax, xinvert) }
+#define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
        .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
                 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
        .tlv.p = (tlv_array), \
        .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
        .put = snd_soc_put_volsw, \
-       .private_value = (unsigned long)&(struct soc_mixer_control) \
-               {.reg = xreg, .shift = shift_left, .rshift = shift_right,\
-                .max = xmax, .platform_max = xmax, .invert = xinvert} }
+       .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
+                                         max, invert) }
 #define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
        .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
                 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
        .tlv.p = (tlv_array), \
-       .info = snd_soc_info_volsw_2r, \
-       .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
-       .private_value = (unsigned long)&(struct soc_mixer_control) \
-               {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
-               .max = xmax, .platform_max = xmax, .invert = xinvert} }
+       .info = snd_soc_info_volsw, \
+       .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
+       .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
+                                           xmax, xinvert) }
 #define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \
 {      .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
        .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
        .info = snd_soc_info_volsw, \
        .get = xhandler_get, .put = xhandler_put, \
        .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) }
-#define SOC_DOUBLE_EXT(xname, xreg, shift_left, shift_right, xmax, xinvert,\
+#define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\
         xhandler_get, xhandler_put) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
        .info = snd_soc_info_volsw, \
        .get = xhandler_get, .put = xhandler_put, \
-       .private_value = (unsigned long)&(struct soc_mixer_control) \
-               {.reg = xreg, .shift = shift_left, .rshift = shift_right, \
-                .max = xmax, .platform_max = xmax, .invert = xinvert} }
+       .private_value = \
+               SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert) }
 #define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
         xhandler_get, xhandler_put, tlv_array) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
        .tlv.p = (tlv_array), \
        .info = snd_soc_info_volsw, \
        .get = xhandler_get, .put = xhandler_put, \
-       .private_value = (unsigned long)&(struct soc_mixer_control) \
-               {.reg = xreg, .shift = shift_left, .rshift = shift_right, \
-               .max = xmax, .platform_max = xmax, .invert = xinvert} }
+       .private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \
+                                         xmax, xinvert) }
 #define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\
         xhandler_get, xhandler_put, tlv_array) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
        .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
                 SNDRV_CTL_ELEM_ACCESS_READWRITE, \
        .tlv.p = (tlv_array), \
-       .info = snd_soc_info_volsw_2r, \
+       .info = snd_soc_info_volsw, \
        .get = xhandler_get, .put = xhandler_put, \
-       .private_value = (unsigned long)&(struct soc_mixer_control) \
-               {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
-               .max = xmax, .platform_max = xmax, .invert = xinvert} }
+       .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
+                                           xmax, xinvert) }
 #define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
        .info = snd_soc_info_bool_ext, \
@@ -393,12 +393,8 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
 int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
-int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_info *uinfo);
-int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol);
-int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol);
+#define snd_soc_get_volsw_2r snd_soc_get_volsw
+#define snd_soc_put_volsw_2r snd_soc_put_volsw
 int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_info *uinfo);
 int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
@@ -582,6 +578,7 @@ struct snd_soc_codec {
 
        /* dapm */
        struct snd_soc_dapm_context dapm;
+       unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
 
 #ifdef CONFIG_DEBUG_FS
        struct dentry *debugfs_codec_root;
@@ -713,6 +710,8 @@ struct snd_soc_dai_link {
        const char *cpu_dai_name;
        const char *codec_dai_name;
 
+       unsigned int dai_fmt;           /* format to set on init */
+
        /* Keep DAI active over suspend */
        unsigned int ignore_suspend:1;
 
@@ -825,9 +824,11 @@ struct snd_soc_card {
        struct list_head widgets;
        struct list_head paths;
        struct list_head dapm_list;
+       struct list_head dapm_dirty;
 
        /* Generic DAPM context for the card */
        struct snd_soc_dapm_context dapm;
+       struct snd_soc_dapm_stats dapm_stats;
 
 #ifdef CONFIG_DEBUG_FS
        struct dentry *debugfs_card_root;
@@ -850,8 +851,6 @@ struct snd_soc_pcm_runtime  {
        unsigned int complete:1;
        unsigned int dev_registered:1;
 
-       /* Symmetry data - only valid if symmetry is being enforced */
-       unsigned int rate;
        long pmdown_time;
 
        /* runtime devices */
@@ -946,6 +945,18 @@ static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
        INIT_LIST_HEAD(&card->dapm_list);
 }
 
+static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc)
+{
+       if (mc->reg == mc->rreg && mc->shift == mc->rshift)
+               return 0;
+       /*
+        * mc->reg == mc->rreg && mc->shift != mc->rshift, or
+        * mc->reg != mc->rreg means that the control is
+        * stereo (bits in one register or in two registers)
+        */
+       return 1;
+}
+
 int snd_soc_util_init(void);
 void snd_soc_util_exit(void);
 
index 89beccb..4cc1093 100644 (file)
 #ifndef TPA6130A2_PLAT_H
 #define TPA6130A2_PLAT_H
 
-enum tpa_model {
-       TPA6130A2,
-       TPA6140A2,
-};
-
 struct tpa6130a2_platform_data {
-       enum tpa_model id;
        int power_gpio;
 };
 
diff --git a/include/sound/wm1250-ev1.h b/include/sound/wm1250-ev1.h
new file mode 100644 (file)
index 0000000..7dff828
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * linux/sound/wm1250-ev1.h - Platform data for WM1250-EV1
+ *
+ * Copyright 2011 Wolfson Microelectronics. PLC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_WM1250_EV1_H
+#define __LINUX_SND_WM1250_EV1_H
+
+#define WM1250_EV1_NUM_GPIOS 5
+
+#define WM1250_EV1_GPIO_CLK_ENA  0
+#define WM1250_EV1_GPIO_CLK_SEL0 1
+#define WM1250_EV1_GPIO_CLK_SEL1 2
+#define WM1250_EV1_GPIO_OSR      3
+#define WM1250_EV1_GPIO_MASTER   4
+
+
+struct wm1250_ev1_pdata {
+       int gpios[WM1250_EV1_NUM_GPIOS];
+};
+
+#endif
diff --git a/include/sound/wm5100.h b/include/sound/wm5100.h
new file mode 100644 (file)
index 0000000..617d0c4
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * linux/sound/wm5100.h -- Platform data for WM5100
+ *
+ * Copyright 2011 Wolfson Microelectronics. PLC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_WM5100_H
+#define __LINUX_SND_WM5100_H
+
+enum wm5100_in_mode {
+       WM5100_IN_SE = 0,
+       WM5100_IN_DIFF = 1,
+       WM5100_IN_DMIC = 2,
+};
+
+enum wm5100_dmic_sup {
+       WM5100_DMIC_SUP_MICVDD = 0,
+       WM5100_DMIC_SUP_MICBIAS1 = 1,
+       WM5100_DMIC_SUP_MICBIAS2 = 2,
+       WM5100_DMIC_SUP_MICBIAS3 = 3,
+};
+
+enum wm5100_micdet_bias {
+       WM5100_MICDET_MICBIAS1 = 0,
+       WM5100_MICDET_MICBIAS2 = 1,
+       WM5100_MICDET_MICBIAS3 = 2,
+};
+
+struct wm5100_jack_mode {
+       enum wm5100_micdet_bias bias;
+       int hp_pol;
+       int micd_src;
+};
+
+#define WM5100_GPIO_SET 0x10000
+
+struct wm5100_pdata {
+       int reset;      /** GPIO controlling /RESET, if any */
+       int ldo_ena;    /** GPIO controlling LODENA, if any */
+       int hp_pol;     /** GPIO controlling headset polarity, if any */
+       int irq_flags;
+       int gpio_base;
+
+       struct wm5100_jack_mode jack_modes[2];
+
+       /* Input pin mode selection */
+       enum wm5100_in_mode in_mode[4];
+
+       /* DMIC supply selection */
+       enum wm5100_dmic_sup dmic_sup[4];
+
+       int gpio_defaults[6];
+};
+
+#endif
index 603f5a0..ab26f8a 100644 (file)
@@ -216,6 +216,31 @@ DEFINE_EVENT(snd_soc_dapm_widget, snd_soc_dapm_widget_event_done,
 
 );
 
+TRACE_EVENT(snd_soc_dapm_walk_done,
+
+       TP_PROTO(struct snd_soc_card *card),
+
+       TP_ARGS(card),
+
+       TP_STRUCT__entry(
+               __string(       name,   card->name              )
+               __field(        int,    power_checks            )
+               __field(        int,    path_checks             )
+               __field(        int,    neighbour_checks        )
+       ),
+
+       TP_fast_assign(
+               __assign_str(name, card->name);
+               __entry->power_checks = card->dapm_stats.power_checks;
+               __entry->path_checks = card->dapm_stats.path_checks;
+               __entry->neighbour_checks = card->dapm_stats.neighbour_checks;
+       ),
+
+       TP_printk("%s: checks %d power, %d path, %d neighbour",
+                 __get_str(name), (int)__entry->power_checks,
+                 (int)__entry->path_checks, (int)__entry->neighbour_checks)
+);
+
 TRACE_EVENT(snd_soc_jack_irq,
 
        TP_PROTO(const char *name),
index 2909bfa..73ae99a 100644 (file)
@@ -338,7 +338,6 @@ static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd)
        /* always connected pins */
        snd_soc_dapm_enable_pin(dapm, "Int Mic");
        snd_soc_dapm_enable_pin(dapm, "Ext Spk");
-       snd_soc_dapm_sync(dapm);
 
 
 
index bad3aa1..0377c54 100644 (file)
@@ -173,8 +173,6 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
        /* always connected */
        snd_soc_dapm_enable_pin(dapm, "Ext Spk");
 
-       snd_soc_dapm_sync(dapm);
-
        return 0;
 }
 
index 5e4d499..d427e92 100644 (file)
@@ -117,8 +117,6 @@ static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_enable_pin(dapm, "Line In");
        snd_soc_dapm_enable_pin(dapm, "Mic Jack");
 
-       snd_soc_dapm_sync(dapm);
-
        return 0;
 }
 
index 13802ff..726bd65 100644 (file)
@@ -226,7 +226,7 @@ static struct snd_soc_dai_driver au1xac97c_dai_driver = {
 static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
 {
        int ret;
-       struct resource *r;
+       struct resource *iores, *dmares;
        struct au1xpsc_audio_data *ctx;
 
        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
@@ -235,29 +235,30 @@ static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
 
        mutex_init(&ctx->lock);
 
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
+       iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!iores) {
                ret = -ENODEV;
                goto out0;
        }
 
        ret = -EBUSY;
-       if (!request_mem_region(r->start, resource_size(r), pdev->name))
+       if (!request_mem_region(iores->start, resource_size(iores),
+                               pdev->name))
                goto out0;
 
-       ctx->mmio = ioremap_nocache(r->start, resource_size(r));
+       ctx->mmio = ioremap_nocache(iores->start, resource_size(iores));
        if (!ctx->mmio)
                goto out1;
 
-       r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-       if (!r)
-               goto out1;
-       ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start;
+       dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!dmares)
+               goto out2;
+       ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
 
-       r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-       if (!r)
-               goto out1;
-       ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start;
+       dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!dmares)
+               goto out2;
+       ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
 
        /* switch it on */
        WR(ctx, AC97_ENABLE, EN_D | EN_CE);
@@ -270,13 +271,15 @@ static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
 
        ret = snd_soc_register_dai(&pdev->dev, &au1xac97c_dai_driver);
        if (ret)
-               goto out1;
+               goto out2;
 
        ac97c_workdata = ctx;
        return 0;
 
+out2:
+       iounmap(ctx->mmio);
 out1:
-       release_mem_region(r->start, resource_size(r));
+       release_mem_region(iores->start, resource_size(iores));
 out0:
        kfree(ctx);
        return ret;
index 19e0d2a..6bcf48f 100644 (file)
@@ -228,47 +228,50 @@ static struct snd_soc_dai_driver au1xi2s_dai_driver = {
 static int __devinit au1xi2s_drvprobe(struct platform_device *pdev)
 {
        int ret;
-       struct resource *r;
+       struct resource *iores, *dmares;
        struct au1xpsc_audio_data *ctx;
 
        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return -ENOMEM;
 
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
+       iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!iores) {
                ret = -ENODEV;
                goto out0;
        }
 
        ret = -EBUSY;
-       if (!request_mem_region(r->start, resource_size(r), pdev->name))
+       if (!request_mem_region(iores->start, resource_size(iores),
+                               pdev->name))
                goto out0;
 
-       ctx->mmio = ioremap_nocache(r->start, resource_size(r));
+       ctx->mmio = ioremap_nocache(iores->start, resource_size(iores));
        if (!ctx->mmio)
                goto out1;
 
-       r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-       if (!r)
-               goto out1;
-       ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start;
+       dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!dmares)
+               goto out2;
+       ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
 
-       r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-       if (!r)
-               goto out1;
-       ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start;
+       dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!dmares)
+               goto out2;
+       ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
 
        platform_set_drvdata(pdev, ctx);
 
        ret = snd_soc_register_dai(&pdev->dev, &au1xi2s_dai_driver);
        if (ret)
-               goto out1;
+               goto out2;
 
        return 0;
 
+out2:
+       iounmap(ctx->mmio);
 out1:
-       release_mem_region(r->start, resource_size(r));
+       release_mem_region(iores->start, resource_size(iores));
 out0:
        kfree(ctx);
        return ret;
index 172eefd..0c6acd5 100644 (file)
@@ -364,7 +364,7 @@ static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {
 static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
 {
        int ret;
-       struct resource *r;
+       struct resource *iores, *dmares;
        unsigned long sel;
        struct au1xpsc_audio_data *wd;
 
@@ -374,29 +374,30 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
 
        mutex_init(&wd->lock);
 
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
+       iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!iores) {
                ret = -ENODEV;
                goto out0;
        }
 
        ret = -EBUSY;
-       if (!request_mem_region(r->start, resource_size(r), pdev->name))
+       if (!request_mem_region(iores->start, resource_size(iores),
+                               pdev->name))
                goto out0;
 
-       wd->mmio = ioremap(r->start, resource_size(r));
+       wd->mmio = ioremap(iores->start, resource_size(iores));
        if (!wd->mmio)
                goto out1;
 
-       r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-       if (!r)
+       dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!dmares)
                goto out2;
-       wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start;
+       wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
 
-       r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-       if (!r)
+       dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!dmares)
                goto out2;
-       wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start;
+       wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
 
        /* configuration: max dma trigger threshold, enable ac97 */
        wd->cfg = PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8 |
@@ -428,7 +429,7 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
 out2:
        iounmap(wd->mmio);
 out1:
-       release_mem_region(r->start, resource_size(r));
+       release_mem_region(iores->start, resource_size(iores));
 out0:
        kfree(wd);
        return ret;
index 7c5ae92..e03c5ce 100644 (file)
@@ -290,7 +290,7 @@ static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = {
 
 static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
 {
-       struct resource *r;
+       struct resource *iores, *dmares;
        unsigned long sel;
        int ret;
        struct au1xpsc_audio_data *wd;
@@ -299,29 +299,30 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
        if (!wd)
                return -ENOMEM;
 
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r) {
+       iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!iores) {
                ret = -ENODEV;
                goto out0;
        }
 
        ret = -EBUSY;
-       if (!request_mem_region(r->start, resource_size(r), pdev->name))
+       if (!request_mem_region(iores->start, resource_size(iores),
+                               pdev->name))
                goto out0;
 
-       wd->mmio = ioremap(r->start, resource_size(r));
+       wd->mmio = ioremap(iores->start, resource_size(iores));
        if (!wd->mmio)
                goto out1;
 
-       r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-       if (!r)
+       dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!dmares)
                goto out2;
-       wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = r->start;
+       wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
 
-       r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-       if (!r)
+       dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!dmares)
                goto out2;
-       wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = r->start;
+       wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
 
        /* preserve PSC clock source set up by platform (dev.platform_data
         * is already occupied by soc layer)
@@ -355,7 +356,7 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
 out2:
        iounmap(wd->mmio);
 out1:
-       release_mem_region(r->start, resource_size(r));
+       release_mem_region(iores->start, resource_size(iores));
 out0:
        kfree(wd);
        return ret;
index 9e59f68..56815c1 100644 (file)
@@ -418,7 +418,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
 
 static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
 
-int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd)
+static int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_soc_dai *dai = rtd->cpu_dai;
index 61ddf94..7565e15 100644 (file)
@@ -257,7 +257,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
 
 static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
 
-int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
+static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_soc_dai *dai = rtd->cpu_dai;
index 1924157..5ca122e 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/88pm860x.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -772,11 +773,12 @@ static const struct snd_soc_dapm_widget pm860x_dapm_widgets[] = {
 
 
        SND_SOC_DAPM_AIF_IN("I2S DIN", "I2S Playback", 0,
-                           PM860X_DAC_EN_2, 0, 0),
+                           SND_SOC_NOPM, 0, 0),
        SND_SOC_DAPM_AIF_IN("I2S DIN1", "I2S Playback", 0,
-                           PM860X_DAC_EN_2, 0, 0),
+                           SND_SOC_NOPM, 0, 0),
        SND_SOC_DAPM_AIF_OUT("I2S DOUT", "I2S Capture", 0,
                             PM860X_I2S_IFACE_3, 5, 1),
+       SND_SOC_DAPM_SUPPLY("I2S CLK", PM860X_DAC_EN_2, 0, 0, NULL, 0),
        SND_SOC_DAPM_MUX("I2S Mic Mux", SND_SOC_NOPM, 0, 0, &i2s_mic_mux),
        SND_SOC_DAPM_MUX("ADC Left Mux", SND_SOC_NOPM, 0, 0, &adcl_mux),
        SND_SOC_DAPM_MUX("ADC Right Mux", SND_SOC_NOPM, 0, 0, &adcr_mux),
@@ -868,6 +870,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Left ADC", NULL, "Left ADC MOD"},
        {"Right ADC", NULL, "Right ADC MOD"},
 
+       /* I2S Clock */
+       {"I2S DIN", NULL, "I2S CLK"},
+       {"I2S DIN1", NULL, "I2S CLK"},
+       {"I2S DOUT", NULL, "I2S CLK"},
+
        /* PCM/AIF1 Inputs */
        {"PCM SDO", NULL, "ADC Left Mux"},
        {"PCM SDO", NULL, "ADCR EC Mux"},
@@ -1173,6 +1180,9 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec,
        case SND_SOC_BIAS_STANDBY:
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
                        /* Enable Audio PLL & Audio section */
+                       data = AUDIO_PLL | AUDIO_SECTION_ON;
+                       pm860x_reg_write(codec->control_data, REG_MISC2, data);
+                       udelay(300);
                        data = AUDIO_PLL | AUDIO_SECTION_RESET
                                | AUDIO_SECTION_ON;
                        pm860x_reg_write(codec->control_data, REG_MISC2, data);
index 71b46c8..4584514 100644 (file)
@@ -40,6 +40,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_MAX9850 if I2C
        select SND_SOC_MAX9877 if I2C
        select SND_SOC_PCM3008
+       select SND_SOC_RT5631 if I2C
        select SND_SOC_SGTL5000 if I2C
        select SND_SOC_SN95031 if INTEL_SCU_IPC
        select SND_SOC_SPDIF
@@ -48,7 +49,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
        select SND_SOC_TLV320AIC23 if I2C
        select SND_SOC_TLV320AIC26 if SPI_MASTER
-       select SND_SOC_TVL320AIC32X4 if I2C
+       select SND_SOC_TLV320AIC32X4 if I2C
        select SND_SOC_TLV320AIC3X if I2C
        select SND_SOC_TPA6130A2 if I2C
        select SND_SOC_TLV320DAC33 if I2C
@@ -59,6 +60,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_WL1273 if MFD_WL1273_CORE
        select SND_SOC_WM1250_EV1 if I2C
        select SND_SOC_WM2000 if I2C
+       select SND_SOC_WM5100 if I2C
        select SND_SOC_WM8350 if MFD_WM8350
        select SND_SOC_WM8400 if MFD_WM8400
        select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
@@ -218,6 +220,9 @@ config SND_SOC_MAX9850
 config SND_SOC_PCM3008
        tristate
 
+config SND_SOC_RT5631
+       tristate
+
 #Freescale sgtl5000 codec
 config SND_SOC_SGTL5000
        tristate
@@ -244,7 +249,7 @@ config SND_SOC_TLV320AIC26
        tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE
        depends on SPI
 
-config SND_SOC_TVL320AIC32X4
+config SND_SOC_TLV320AIC32X4
        tristate
 
 config SND_SOC_TLV320AIC3X
@@ -273,6 +278,9 @@ config SND_SOC_WL1273
 config SND_SOC_WM1250_EV1
        tristate
 
+config SND_SOC_WM5100
+       tristate
+
 config SND_SOC_WM8350
        tristate
 
index 70c1769..a2c7842 100644 (file)
@@ -26,6 +26,7 @@ snd-soc-max98088-objs := max98088.o
 snd-soc-max98095-objs := max98095.o
 snd-soc-max9850-objs := max9850.o
 snd-soc-pcm3008-objs := pcm3008.o
+snd-soc-rt5631-objs := rt5631.o
 snd-soc-sgtl5000-objs := sgtl5000.o
 snd-soc-alc5623-objs := alc5623.o
 snd-soc-sn95031-objs := sn95031.o
@@ -44,6 +45,7 @@ snd-soc-uda134x-objs := uda134x.o
 snd-soc-uda1380-objs := uda1380.o
 snd-soc-wl1273-objs := wl1273.o
 snd-soc-wm1250-ev1-objs := wm1250-ev1.o
+snd-soc-wm5100-objs := wm5100.o wm5100-tables.o
 snd-soc-wm8350-objs := wm8350.o
 snd-soc-wm8400-objs := wm8400.o
 snd-soc-wm8510-objs := wm8510.o
@@ -125,6 +127,7 @@ obj-$(CONFIG_SND_SOC_MAX98088)      += snd-soc-max98088.o
 obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
 obj-$(CONFIG_SND_SOC_MAX9850)  += snd-soc-max9850.o
 obj-$(CONFIG_SND_SOC_PCM3008)  += snd-soc-pcm3008.o
+obj-$(CONFIG_SND_SOC_RT5631)   += snd-soc-rt5631.o
 obj-$(CONFIG_SND_SOC_SGTL5000)  += snd-soc-sgtl5000.o
 obj-$(CONFIG_SND_SOC_SN95031)  +=snd-soc-sn95031.o
 obj-$(CONFIG_SND_SOC_SPDIF)    += snd-soc-spdif.o
@@ -134,7 +137,7 @@ obj-$(CONFIG_SND_SOC_STAC9766)      += snd-soc-stac9766.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)      += snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC26)      += snd-soc-tlv320aic26.o
 obj-$(CONFIG_SND_SOC_TLV320AIC3X)      += snd-soc-tlv320aic3x.o
-obj-$(CONFIG_SND_SOC_TVL320AIC32X4)     += snd-soc-tlv320aic32x4.o
+obj-$(CONFIG_SND_SOC_TLV320AIC32X4)     += snd-soc-tlv320aic32x4.o
 obj-$(CONFIG_SND_SOC_TLV320DAC33)      += snd-soc-tlv320dac33.o
 obj-$(CONFIG_SND_SOC_TWL4030)  += snd-soc-twl4030.o
 obj-$(CONFIG_SND_SOC_TWL6040)  += snd-soc-twl6040.o
@@ -142,6 +145,7 @@ obj-$(CONFIG_SND_SOC_UDA134X)       += snd-soc-uda134x.o
 obj-$(CONFIG_SND_SOC_UDA1380)  += snd-soc-uda1380.o
 obj-$(CONFIG_SND_SOC_WL1273)   += snd-soc-wl1273.o
 obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
+obj-$(CONFIG_SND_SOC_WM5100)   += snd-soc-wm5100.o
 obj-$(CONFIG_SND_SOC_WM8350)   += snd-soc-wm8350.o
 obj-$(CONFIG_SND_SOC_WM8400)   += snd-soc-wm8400.o
 obj-$(CONFIG_SND_SOC_WM8510)   += snd-soc-wm8510.o
index f934670..1206021 100644 (file)
@@ -103,12 +103,14 @@ static const struct snd_soc_dapm_route audio_paths[] = {
 static int ad193x_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
-       int reg;
 
-       reg = snd_soc_read(codec, AD193X_DAC_CTRL2);
-       reg = (mute > 0) ? reg | AD193X_DAC_MASTER_MUTE : reg &
-               (~AD193X_DAC_MASTER_MUTE);
-       snd_soc_write(codec, AD193X_DAC_CTRL2, reg);
+       if (mute)
+               snd_soc_update_bits(codec, AD193X_DAC_CTRL2,
+                                   AD193X_DAC_MASTER_MUTE,
+                                   AD193X_DAC_MASTER_MUTE);
+       else
+               snd_soc_update_bits(codec, AD193X_DAC_CTRL2,
+                                   AD193X_DAC_MASTER_MUTE, 0);
 
        return 0;
 }
@@ -262,7 +264,7 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
                struct snd_pcm_hw_params *params,
                struct snd_soc_dai *dai)
 {
-       int word_len = 0, reg = 0, master_rate = 0;
+       int word_len = 0, master_rate = 0;
 
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_codec *codec = rtd->codec;
@@ -297,18 +299,15 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
                break;
        }
 
-       reg = snd_soc_read(codec, AD193X_PLL_CLK_CTRL0);
-       reg = (reg & AD193X_PLL_INPUT_MASK) | master_rate;
-       snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, reg);
+       snd_soc_update_bits(codec, AD193X_PLL_CLK_CTRL0,
+                           AD193X_PLL_INPUT_MASK, master_rate);
 
-       reg = snd_soc_read(codec, AD193X_DAC_CTRL2);
-       reg = (reg & (~AD193X_DAC_WORD_LEN_MASK))
-               | (word_len << AD193X_DAC_WORD_LEN_SHFT);
-       snd_soc_write(codec, AD193X_DAC_CTRL2, reg);
+       snd_soc_update_bits(codec, AD193X_DAC_CTRL2,
+                           AD193X_DAC_WORD_LEN_MASK,
+                           word_len << AD193X_DAC_WORD_LEN_SHFT);
 
-       reg = snd_soc_read(codec, AD193X_ADC_CTRL1);
-       reg = (reg & (~AD193X_ADC_WORD_LEN_MASK)) | word_len;
-       snd_soc_write(codec, AD193X_ADC_CTRL1, reg);
+       snd_soc_update_bits(codec, AD193X_ADC_CTRL1,
+                           AD193X_ADC_WORD_LEN_MASK, word_len);
 
        return 0;
 }
index 536e5f2..1507eaa 100644 (file)
@@ -11,7 +11,7 @@
 
 #define AD193X_PLL_CLK_CTRL0    0x00
 #define AD193X_PLL_POWERDOWN           0x01
-#define AD193X_PLL_INPUT_MASK   (~0x6)
+#define AD193X_PLL_INPUT_MASK   0x6
 #define AD193X_PLL_INPUT_256    (0 << 1)
 #define AD193X_PLL_INPUT_384    (1 << 1)
 #define AD193X_PLL_INPUT_512    (2 << 1)
index 4c0fc30..e3931cc 100644 (file)
@@ -148,7 +148,6 @@ static struct snd_soc_dai_driver ad1980_dai = {
                .rates = SNDRV_PCM_RATE_48000,
                .formats = SND_SOC_STD_AC97_FMTS, },
 };
-EXPORT_SYMBOL_GPL(ad1980_dai);
 
 static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)
 {
index 2aa40c3..1ccf8dd 100644 (file)
@@ -974,7 +974,7 @@ static int adau1373_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                break;
        case SND_SOC_DAIFMT_CBS_CFS:
                ctrl = 0;
-               adau1373_dai->master = true;
+               adau1373_dai->master = false;
                break;
        default:
                return -EINVAL;
index 2758d5f..8b7e1c5 100644 (file)
@@ -401,7 +401,7 @@ static int adau1701_digital_mute(struct snd_soc_dai *dai, int mute)
 }
 
 static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id,
-       unsigned int freq, int dir)
+       int source, unsigned int freq, int dir)
 {
        unsigned int val;
 
@@ -458,6 +458,7 @@ static int adau1701_probe(struct snd_soc_codec *codec)
        int ret;
 
        codec->dapm.idle_bias_off = 1;
+       codec->control_data = to_i2c_client(codec->dev);
 
        ret = adau1701_load_firmware(codec);
        if (ret)
diff --git a/sound/soc/codecs/ads117x.h b/sound/soc/codecs/ads117x.h
deleted file mode 100644 (file)
index 3ce0286..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * ads117x.h  --  Driver for ads1174/8 ADC chips
- *
- * Copyright 2009 ShotSpotter Inc.
- * Author: Graeme Gregory <gg@slimlogic.co.uk>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- */
-extern struct snd_soc_dai_driver ads117x_dai;
-extern struct snd_soc_codec_driver soc_codec_dev_ads117x;
index cbf0b6d..d3b29dc 100644 (file)
@@ -247,7 +247,7 @@ static struct snd_soc_codec_driver soc_codec_device_ak4104 = {
        .probe =        ak4104_probe,
        .remove =       ak4104_remove,
        .reg_cache_size = AK4104_NUM_REGS,
-       .reg_word_size = sizeof(u16),
+       .reg_word_size = sizeof(u8),
 };
 
 static int ak4104_spi_probe(struct spi_device *spi)
index e1a214e..95d782d 100644 (file)
 struct ak4535_priv {
        unsigned int sysclk;
        enum snd_soc_control_type control_type;
-       void *control_data;
 };
 
 /*
  * ak4535 register cache
  */
-static const u16 ak4535_reg[AK4535_CACHEREGNUM] = {
-    0x0000, 0x0080, 0x0000, 0x0003,
-    0x0002, 0x0000, 0x0011, 0x0001,
-    0x0000, 0x0040, 0x0036, 0x0010,
-    0x0000, 0x0000, 0x0057, 0x0000,
-};
-
-/*
- * read ak4535 register cache
- */
-static inline unsigned int ak4535_read_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg >= AK4535_CACHEREGNUM)
-               return -1;
-       return cache[reg];
-}
-
-/*
- * write ak4535 register cache
- */
-static inline void ak4535_write_reg_cache(struct snd_soc_codec *codec,
-       u16 reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg >= AK4535_CACHEREGNUM)
-               return;
-       cache[reg] = value;
-}
-
-/*
- * write to the AK4535 register space
- */
-static int ak4535_write(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int value)
-{
-       u8 data[2];
-
-       /* data is
-        *   D15..D8 AK4535 register offset
-        *   D7...D0 register data
-        */
-       data[0] = reg & 0xff;
-       data[1] = value & 0xff;
-
-       ak4535_write_reg_cache(codec, reg, value);
-       if (codec->hw_write(codec->control_data, data, 2) == 2)
-               return 0;
-       else
-               return -EIO;
-}
-
-static int ak4535_sync(struct snd_soc_codec *codec)
-{
-       u16 *cache = codec->reg_cache;
-       int i, r = 0;
-
-       for (i = 0; i < AK4535_CACHEREGNUM; i++)
-               r |= ak4535_write(codec, i, cache[i]);
-
-       return r;
+static const u8 ak4535_reg[AK4535_CACHEREGNUM] = {
+       0x00, 0x80, 0x00, 0x03,
+       0x02, 0x00, 0x11, 0x01,
+       0x00, 0x40, 0x36, 0x10,
+       0x00, 0x00, 0x57, 0x00,
 };
 
 static const char *ak4535_mono_gain[] = {"+6dB", "-17dB"};
@@ -304,7 +246,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_codec *codec = rtd->codec;
        struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
-       u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5);
+       u8 mode2 = snd_soc_read(codec, AK4535_MODE2) & ~(0x3 << 5);
        int rate = params_rate(params), fs = 256;
 
        if (rate)
@@ -323,7 +265,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream,
        }
 
        /* set rate */
-       ak4535_write(codec, AK4535_MODE2, mode2);
+       snd_soc_write(codec, AK4535_MODE2, mode2);
        return 0;
 }
 
@@ -348,44 +290,37 @@ static int ak4535_set_dai_fmt(struct snd_soc_dai *codec_dai,
        /* use 32 fs for BCLK to save power */
        mode1 |= 0x4;
 
-       ak4535_write(codec, AK4535_MODE1, mode1);
+       snd_soc_write(codec, AK4535_MODE1, mode1);
        return 0;
 }
 
 static int ak4535_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
-       u16 mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC);
+       u16 mute_reg = snd_soc_read(codec, AK4535_DAC);
        if (!mute)
-               ak4535_write(codec, AK4535_DAC, mute_reg & ~0x20);
+               snd_soc_write(codec, AK4535_DAC, mute_reg & ~0x20);
        else
-               ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
+               snd_soc_write(codec, AK4535_DAC, mute_reg | 0x20);
        return 0;
 }
 
 static int ak4535_set_bias_level(struct snd_soc_codec *codec,
        enum snd_soc_bias_level level)
 {
-       u16 i, mute_reg;
-
        switch (level) {
        case SND_SOC_BIAS_ON:
-               mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC);
-               ak4535_write(codec, AK4535_DAC, mute_reg & ~0x20);
+               snd_soc_update_bits(codec, AK4535_DAC, 0x20, 0);
                break;
        case SND_SOC_BIAS_PREPARE:
-               mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC);
-               ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
+               snd_soc_update_bits(codec, AK4535_DAC, 0x20, 0x20);
                break;
        case SND_SOC_BIAS_STANDBY:
-               i = ak4535_read_reg_cache(codec, AK4535_PM1);
-               ak4535_write(codec, AK4535_PM1, i | 0x80);
-               i = ak4535_read_reg_cache(codec, AK4535_PM2);
-               ak4535_write(codec, AK4535_PM2, i & (~0x80));
+               snd_soc_update_bits(codec, AK4535_PM1, 0x80, 0x80);
+               snd_soc_update_bits(codec, AK4535_PM2, 0x80, 0);
                break;
        case SND_SOC_BIAS_OFF:
-               i = ak4535_read_reg_cache(codec, AK4535_PM1);
-               ak4535_write(codec, AK4535_PM1, i & (~0x80));
+               snd_soc_update_bits(codec, AK4535_PM1, 0x80, 0);
                break;
        }
        codec->dapm.bias_level = level;
@@ -428,7 +363,7 @@ static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int ak4535_resume(struct snd_soc_codec *codec)
 {
-       ak4535_sync(codec);
+       snd_soc_cache_sync(codec);
        ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        return 0;
 }
@@ -436,11 +371,15 @@ static int ak4535_resume(struct snd_soc_codec *codec)
 static int ak4535_probe(struct snd_soc_codec *codec)
 {
        struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
        printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
 
-       codec->control_data = ak4535->control_data;
-
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4535->control_type);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
        /* power on device */
        ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
@@ -461,8 +400,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
        .remove =       ak4535_remove,
        .suspend =      ak4535_suspend,
        .resume =       ak4535_resume,
-       .read = ak4535_read_reg_cache,
-       .write = ak4535_write,
        .set_bias_level = ak4535_set_bias_level,
        .reg_cache_size = ARRAY_SIZE(ak4535_reg),
        .reg_word_size = sizeof(u8),
@@ -485,7 +422,6 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, ak4535);
-       ak4535->control_data = i2c;
        ak4535->control_type = SND_SOC_I2C;
 
        ret = snd_soc_register_codec(&i2c->dev,
index 7a64e58..7783858 100644 (file)
@@ -31,7 +31,6 @@
 
 /* codec private data */
 struct ak4641_priv {
-       struct snd_soc_codec *codec;
        unsigned int sysclk;
        int deemph;
        int playback_fs;
@@ -226,7 +225,7 @@ static const struct snd_soc_dapm_widget ak4641_dapm_widgets[] = {
        SND_SOC_DAPM_PGA("Mono Out 2", AK4641_PM2, 3, 0, NULL, 0),
 
        SND_SOC_DAPM_ADC("Voice ADC", "Voice Capture", AK4641_BTIF, 0, 0),
-       SND_SOC_DAPM_ADC("Voice DAC", "Voice Playback", AK4641_BTIF, 1, 0),
+       SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", AK4641_BTIF, 1, 0),
 
        SND_SOC_DAPM_MICBIAS("Mic Int Bias", AK4641_MIC, 3, 0),
        SND_SOC_DAPM_MICBIAS("Mic Ext Bias", AK4641_MIC, 4, 0),
index 65f4604..d8fc044 100644 (file)
@@ -156,81 +156,22 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = {
 struct ak4642_priv {
        unsigned int sysclk;
        enum snd_soc_control_type control_type;
-       void *control_data;
 };
 
 /*
  * ak4642 register cache
  */
-static const u16 ak4642_reg[AK4642_CACHEREGNUM] = {
-       0x0000, 0x0000, 0x0001, 0x0000,
-       0x0002, 0x0000, 0x0000, 0x0000,
-       0x00e1, 0x00e1, 0x0018, 0x0000,
-       0x00e1, 0x0018, 0x0011, 0x0008,
-       0x0000, 0x0000, 0x0000, 0x0000,
-       0x0000, 0x0000, 0x0000, 0x0000,
-       0x0000, 0x0000, 0x0000, 0x0000,
-       0x0000, 0x0000, 0x0000, 0x0000,
-       0x0000, 0x0000, 0x0000, 0x0000,
-       0x0000,
-};
-
-/*
- * read ak4642 register cache
- */
-static inline unsigned int ak4642_read_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg >= AK4642_CACHEREGNUM)
-               return -1;
-       return cache[reg];
-}
-
-/*
- * write ak4642 register cache
- */
-static inline void ak4642_write_reg_cache(struct snd_soc_codec *codec,
-       u16 reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg >= AK4642_CACHEREGNUM)
-               return;
-
-       cache[reg] = value;
-}
-
-/*
- * write to the AK4642 register space
- */
-static int ak4642_write(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int value)
-{
-       u8 data[2];
-
-       /* data is
-        *   D15..D8 AK4642 register offset
-        *   D7...D0 register data
-        */
-       data[0] = reg & 0xff;
-       data[1] = value & 0xff;
-
-       if (codec->hw_write(codec->control_data, data, 2) == 2) {
-               ak4642_write_reg_cache(codec, reg, value);
-               return 0;
-       } else
-               return -EIO;
-}
-
-static int ak4642_sync(struct snd_soc_codec *codec)
-{
-       u16 *cache = codec->reg_cache;
-       int i, r = 0;
-
-       for (i = 0; i < AK4642_CACHEREGNUM; i++)
-               r |= ak4642_write(codec, i, cache[i]);
-
-       return r;
+static const u8 ak4642_reg[AK4642_CACHEREGNUM] = {
+       0x00, 0x00, 0x01, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0xe1, 0xe1, 0x18, 0x00,
+       0xe1, 0x18, 0x11, 0x08,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00,
 };
 
 static int ak4642_dai_startup(struct snd_pcm_substream *substream,
@@ -252,8 +193,8 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
                 */
                snd_soc_update_bits(codec, MD_CTL4, DACH, DACH);
                snd_soc_update_bits(codec, MD_CTL3, BST1, BST1);
-               ak4642_write(codec, L_IVC, 0x91); /* volume */
-               ak4642_write(codec, R_IVC, 0x91); /* volume */
+               snd_soc_write(codec, L_IVC, 0x91); /* volume */
+               snd_soc_write(codec, R_IVC, 0x91); /* volume */
                snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMMIN | PMDAC,
                                                     PMVCM | PMMIN | PMDAC);
                snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP);
@@ -272,9 +213,9 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
                 * This operation came from example code of
                 * "ASAHI KASEI AK4642" (japanese) manual p94.
                 */
-               ak4642_write(codec, SG_SL1, PMMP | MGAIN0);
-               ak4642_write(codec, TIMER, ZTM(0x3) | WTM(0x3));
-               ak4642_write(codec, ALC_CTL1, ALC | LMTH0);
+               snd_soc_write(codec, SG_SL1, PMMP | MGAIN0);
+               snd_soc_write(codec, TIMER, ZTM(0x3) | WTM(0x3));
+               snd_soc_write(codec, ALC_CTL1, ALC | LMTH0);
                snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMADL,
                                                     PMVCM | PMADL);
                snd_soc_update_bits(codec, PW_MGMT3, PMADR, PMADR);
@@ -462,7 +403,7 @@ static struct snd_soc_dai_driver ak4642_dai = {
 
 static int ak4642_resume(struct snd_soc_codec *codec)
 {
-       ak4642_sync(codec);
+       snd_soc_cache_sync(codec);
        return 0;
 }
 
@@ -470,11 +411,15 @@ static int ak4642_resume(struct snd_soc_codec *codec)
 static int ak4642_probe(struct snd_soc_codec *codec)
 {
        struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
        dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
 
-       codec->hw_write         = (hw_write_t)i2c_master_send;
-       codec->control_data     = ak4642->control_data;
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4642->control_type);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
 
        snd_soc_add_controls(codec, ak4642_snd_controls,
                             ARRAY_SIZE(ak4642_snd_controls));
@@ -485,8 +430,6 @@ static int ak4642_probe(struct snd_soc_codec *codec)
 static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
        .probe                  = ak4642_probe,
        .resume                 = ak4642_resume,
-       .read                   = ak4642_read_reg_cache,
-       .write                  = ak4642_write,
        .reg_cache_size         = ARRAY_SIZE(ak4642_reg),
        .reg_word_size          = sizeof(u8),
        .reg_cache_default      = ak4642_reg,
@@ -504,7 +447,6 @@ static __devinit int ak4642_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, ak4642);
-       ak4642->control_data = i2c;
        ak4642->control_type = SND_SOC_I2C;
 
        ret =  snd_soc_register_codec(&i2c->dev,
index 88b29f8..de9ff66 100644 (file)
@@ -26,7 +26,6 @@
 /* codec private data */
 struct ak4671_priv {
        enum snd_soc_control_type control_type;
-       void *control_data;
 };
 
 /* ak4671 register cache & default register settings */
@@ -169,18 +168,15 @@ static int ak4671_out2_event(struct snd_soc_dapm_widget *w,
                struct snd_kcontrol *kcontrol, int event)
 {
        struct snd_soc_codec *codec = w->codec;
-       u8 reg;
 
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
-               reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT);
-               reg |= AK4671_MUTEN;
-               snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg);
+               snd_soc_update_bits(codec, AK4671_LOUT2_POWER_MANAGERMENT,
+                                   AK4671_MUTEN, AK4671_MUTEN);
                break;
        case SND_SOC_DAPM_PRE_PMD:
-               reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT);
-               reg &= ~AK4671_MUTEN;
-               snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg);
+               snd_soc_update_bits(codec, AK4671_LOUT2_POWER_MANAGERMENT,
+                                   AK4671_MUTEN, 0);
                break;
        }
 
@@ -576,15 +572,12 @@ static int ak4671_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 static int ak4671_set_bias_level(struct snd_soc_codec *codec,
                enum snd_soc_bias_level level)
 {
-       u8 reg;
-
        switch (level) {
        case SND_SOC_BIAS_ON:
        case SND_SOC_BIAS_PREPARE:
        case SND_SOC_BIAS_STANDBY:
-               reg = snd_soc_read(codec, AK4671_AD_DA_POWER_MANAGEMENT);
-               snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT,
-                               reg | AK4671_PMVCM);
+               snd_soc_update_bits(codec, AK4671_AD_DA_POWER_MANAGEMENT,
+                                   AK4671_PMVCM, AK4671_PMVCM);
                break;
        case SND_SOC_BIAS_OFF:
                snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00);
@@ -629,8 +622,6 @@ static int ak4671_probe(struct snd_soc_codec *codec)
        struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
-       codec->hw_write = (hw_write_t)i2c_master_send;
-
        ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -675,7 +666,6 @@ static int __devinit ak4671_i2c_probe(struct i2c_client *client,
                return -ENOMEM;
 
        i2c_set_clientdata(client, ak4671);
-       ak4671->control_data = client;
        ak4671->control_type = SND_SOC_I2C;
 
        ret = snd_soc_register_codec(&client->dev,
index 0517315..984b14b 100644 (file)
@@ -40,7 +40,6 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)");
 /* codec private data */
 struct alc5623_priv {
        enum snd_soc_control_type control_type;
-       void *control_data;
        u8 id;
        unsigned int sysclk;
        u16 reg_cache[ALC5623_VENDOR_ID2+2];
@@ -54,8 +53,10 @@ static void alc5623_fill_cache(struct snd_soc_codec *codec)
        u16 *cache = codec->reg_cache;
 
        /* not really efficient ... */
+       codec->cache_bypass = 1;
        for (i = 0 ; i < codec->driver->reg_cache_size ; i += step)
-               cache[i] = codec->hw_read(codec, i);
+               cache[i] = snd_soc_read(codec, i);
+       codec->cache_bypass = 0;
 }
 
 static inline int alc5623_reset(struct snd_soc_codec *codec)
@@ -1049,7 +1050,6 @@ static int alc5623_i2c_probe(struct i2c_client *client,
        }
 
        i2c_set_clientdata(client, alc5623);
-       alc5623->control_data = client;
        alc5623->control_type = SND_SOC_I2C;
 
        ret =  snd_soc_register_codec(&client->dev,
index 6cc8678..f1f237e 100644 (file)
@@ -128,7 +128,6 @@ static const char *supply_names[] = {
 /* Private data for the CS4270 */
 struct cs4270_private {
        enum snd_soc_control_type control_type;
-       void *control_data;
        unsigned int mclk; /* Input frequency of the MCLK pin */
        unsigned int mode; /* The mode (I2S or left-justified) */
        unsigned int slave_mode;
@@ -262,7 +261,6 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
-       int ret = 0;
 
        /* set DAI format */
        switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -272,7 +270,7 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
                break;
        default:
                dev_err(codec->dev, "invalid dai format\n");
-               ret = -EINVAL;
+               return -EINVAL;
        }
 
        /* set master/slave audio interface */
@@ -285,10 +283,11 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
                break;
        default:
                /* all other modes are unsupported by the hardware */
-               ret = -EINVAL;
+               dev_err(codec->dev, "Unknown master/slave configuration\n");
+               return -EINVAL;
        }
 
-       return ret;
+       return 0;
 }
 
 /**
@@ -490,8 +489,6 @@ static int cs4270_probe(struct snd_soc_codec *codec)
        struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
        int i, ret;
 
-       codec->control_data = cs4270->control_data;
-
        /* Tell ASoC what kind of I/O to use to read the registers.  ASoC will
         * then do the I2C transactions itself.
         */
@@ -604,7 +601,7 @@ static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
 static int cs4270_soc_resume(struct snd_soc_codec *codec)
 {
        struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
-       struct i2c_client *i2c_client = codec->control_data;
+       struct i2c_client *i2c_client = to_i2c_client(codec->dev);
        int reg;
 
        regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
@@ -690,7 +687,6 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
        }
 
        i2c_set_clientdata(i2c_client, cs4270);
-       cs4270->control_data = i2c_client;
        cs4270->control_type = SND_SOC_I2C;
 
        ret = snd_soc_register_codec(&i2c_client->dev,
index 083aab9..23d1bd5 100644 (file)
@@ -156,7 +156,6 @@ static const u8 cs4271_dflt_reg[CS4271_NR_REGS] = {
 struct cs4271_private {
        /* SND_SOC_I2C or SND_SOC_SPI */
        enum snd_soc_control_type       bus_type;
-       void                            *control_data;
        unsigned int                    mclk;
        bool                            master;
        bool                            deemph;
@@ -466,8 +465,6 @@ static int cs4271_probe(struct snd_soc_codec *codec)
        int ret;
        int gpio_nreset = -EINVAL;
 
-       codec->control_data = cs4271->control_data;
-
        if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset))
                gpio_nreset = cs4271plat->gpio_nreset;
 
@@ -555,7 +552,6 @@ static int __devinit cs4271_spi_probe(struct spi_device *spi)
                return -ENOMEM;
 
        spi_set_drvdata(spi, cs4271);
-       cs4271->control_data = spi;
        cs4271->bus_type = SND_SOC_SPI;
 
        return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271,
@@ -595,7 +591,6 @@ static int __devinit cs4271_i2c_probe(struct i2c_client *client,
                return -ENOMEM;
 
        i2c_set_clientdata(client, cs4271);
-       cs4271->control_data = client;
        cs4271->bus_type = SND_SOC_I2C;
 
        return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271,
index 8fb7070..8c3c820 100644 (file)
@@ -42,7 +42,6 @@ enum master_slave_mode {
 
 struct cs42l51_private {
        enum snd_soc_control_type control_type;
-       void *control_data;
        unsigned int mclk;
        unsigned int audio_mode;        /* The mode (I2S or left-justified) */
        enum master_slave_mode func;
@@ -57,7 +56,7 @@ struct cs42l51_private {
 static int cs42l51_fill_cache(struct snd_soc_codec *codec)
 {
        u8 *cache = codec->reg_cache + 1;
-       struct i2c_client *i2c_client = codec->control_data;
+       struct i2c_client *i2c_client = to_i2c_client(codec->dev);
        s32 length;
 
        length = i2c_smbus_read_i2c_block_data(i2c_client,
@@ -289,7 +288,6 @@ static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
-       int ret = 0;
 
        switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
@@ -299,7 +297,7 @@ static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
                break;
        default:
                dev_err(codec->dev, "invalid DAI format\n");
-               ret = -EINVAL;
+               return -EINVAL;
        }
 
        switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -310,11 +308,11 @@ static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
                cs42l51->func = MODE_SLAVE_AUTO;
                break;
        default:
-               ret = -EINVAL;
-               break;
+               dev_err(codec->dev, "Unknown master/slave configuration\n");
+               return -EINVAL;
        }
 
-       return ret;
+       return 0;
 }
 
 struct cs42l51_ratios {
@@ -520,8 +518,6 @@ static int cs42l51_probe(struct snd_soc_codec *codec)
        struct snd_soc_dapm_context *dapm = &codec->dapm;
        int ret, reg;
 
-       codec->control_data = cs42l51->control_data;
-
        ret = cs42l51_fill_cache(codec);
        if (ret < 0) {
                dev_err(codec->dev, "failed to fill register cache\n");
@@ -593,7 +589,6 @@ static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
        }
 
        i2c_set_clientdata(i2c_client, cs42l51);
-       cs42l51->control_data = i2c_client;
        cs42l51->control_type = SND_SOC_I2C;
 
        ret =  snd_soc_register_codec(&i2c_client->dev,
index 92fd9d7..0ebcbd5 100644 (file)
 #include <sound/tlv.h>
 
 /* DA7210 register space */
+#define DA7210_CONTROL                 0x01
 #define DA7210_STATUS                  0x02
 #define DA7210_STARTUP1                        0x03
+#define DA7210_STARTUP2                        0x04
+#define DA7210_STARTUP3                        0x05
 #define DA7210_MIC_L                   0x07
 #define DA7210_MIC_R                   0x08
+#define DA7210_AUX1_L                  0x09
+#define DA7210_AUX1_R                  0x0A
+#define DA7210_AUX2                    0x0B
+#define DA7210_IN_GAIN                 0x0C
 #define DA7210_INMIX_L                 0x0D
 #define DA7210_INMIX_R                 0x0E
 #define DA7210_ADC_HPF                 0x0F
 #define DA7210_ADC                     0x10
+#define DA7210_ADC_EQ1_2               0X11
+#define DA7210_ADC_EQ3_4               0x12
+#define DA7210_ADC_EQ5                 0x13
 #define DA7210_DAC_HPF                 0x14
 #define DA7210_DAC_L                   0x15
 #define DA7210_DAC_R                   0x16
 #define DA7210_DAC_SEL                 0x17
+#define DA7210_SOFTMUTE                        0x18
+#define DA7210_DAC_EQ1_2               0x19
+#define DA7210_DAC_EQ3_4               0x1A
+#define DA7210_DAC_EQ5                 0x1B
 #define DA7210_OUTMIX_L                        0x1C
 #define DA7210_OUTMIX_R                        0x1D
+#define DA7210_OUT1_L                  0x1E
+#define DA7210_OUT1_R                  0x1F
+#define DA7210_OUT2                    0x20
 #define DA7210_HP_L_VOL                        0x21
 #define DA7210_HP_R_VOL                        0x22
 #define DA7210_HP_CFG                  0x23
+#define DA7210_ZERO_CROSS              0x24
 #define DA7210_DAI_SRC_SEL             0x25
 #define DA7210_DAI_CFG1                        0x26
 #define DA7210_DAI_CFG3                        0x28
 #define DA7210_PLL_DIV2                        0x2A
 #define DA7210_PLL_DIV3                        0x2B
 #define DA7210_PLL                     0x2C
+#define DA7210_ALC_MAX                 0x83
+#define DA7210_ALC_MIN                 0x84
+#define DA7210_ALC_NOIS                        0x85
+#define DA7210_ALC_ATT                 0x86
+#define DA7210_ALC_REL                 0x87
+#define DA7210_ALC_DEL                 0x88
 #define DA7210_A_HID_UNLOCK            0x8A
 #define DA7210_A_TEST_UNLOCK           0x8B
 #define DA7210_A_PLL1                  0x90
@@ -72,6 +96,7 @@
 #define DA7210_IN_R_EN                 (1 << 7)
 
 /* ADC bit fields */
+#define DA7210_ADC_ALC_EN              (1 << 0)
 #define DA7210_ADC_L_EN                        (1 << 3)
 #define DA7210_ADC_R_EN                        (1 << 7)
 
 
 /* DAI_CFG1 bit fields */
 #define DA7210_DAI_WORD_S16_LE         (0 << 0)
+#define DA7210_DAI_WORD_S20_3LE                (1 << 0)
 #define DA7210_DAI_WORD_S24_LE         (2 << 0)
+#define DA7210_DAI_WORD_S32_LE         (3 << 0)
 #define DA7210_DAI_FLEN_64BIT          (1 << 2)
+#define DA7210_DAI_MODE_SLAVE          (0 << 7)
 #define DA7210_DAI_MODE_MASTER         (1 << 7)
 
 /* DAI_CFG3 bit fields */
 #define DA7210_DAI_FORMAT_I2SMODE      (0 << 0)
+#define DA7210_DAI_FORMAT_LEFT_J       (1 << 0)
+#define DA7210_DAI_FORMAT_RIGHT_J      (2 << 0)
 #define DA7210_DAI_OE                  (1 << 3)
 #define DA7210_DAI_EN                  (1 << 7)
 
 #define DA7210_PLL_FS_96000            (0xF << 0)
 #define DA7210_PLL_EN                  (0x1 << 7)
 
+/* SOFTMUTE bit fields */
+#define DA7210_RAMP_EN                 (1 << 6)
+
+/* CONTROL bit fields */
+#define DA7210_NOISE_SUP_EN            (1 << 3)
+
+/* IN_GAIN bit fields */
+#define DA7210_INPGA_L_VOL             (0x0F << 0)
+#define DA7210_INPGA_R_VOL             (0xF0 << 0)
+
+/* ZERO_CROSS bit fields */
+#define DA7210_AUX1_L_ZC               (1 << 0)
+#define DA7210_AUX1_R_ZC               (1 << 1)
+#define DA7210_HP_L_ZC                 (1 << 6)
+#define DA7210_HP_R_ZC                 (1 << 7)
+
+/* AUX1_L bit fields */
+#define DA7210_AUX1_L_VOL              (0x3F << 0)
+
+/* AUX1_R bit fields */
+#define DA7210_AUX1_R_VOL              (0x3F << 0)
+
+/* Minimum INPGA and AUX1 volume to enable noise suppression */
+#define DA7210_INPGA_MIN_VOL_NS                0x0A  /* 10.5dB */
+#define DA7210_AUX1_MIN_VOL_NS         0x35  /* 6dB */
+
+/* OUT1_L bit fields */
+#define DA7210_OUT1_L_EN               (1 << 7)
+
+/* OUT1_R bit fields */
+#define DA7210_OUT1_R_EN               (1 << 7)
+
+/* OUT2 bit fields */
+#define DA7210_OUT2_OUTMIX_R           (1 << 5)
+#define DA7210_OUT2_OUTMIX_L           (1 << 6)
+#define DA7210_OUT2_EN                 (1 << 7)
+
 #define DA7210_VERSION "0.0.1"
 
 /*
  * mute                : 0x10
  * reserved    : 0x00 - 0x0F
  *
- * ** FIXME **
- *
  * Reserved area are considered as "mute".
- * -> min = -79.5 dB
  */
-static const DECLARE_TLV_DB_SCALE(hp_out_tlv, -7950, 150, 1);
+static const unsigned int hp_out_tlv[] = {
+       TLV_DB_RANGE_HEAD(2),
+       0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
+       /* -54 dB to +15 dB */
+       0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0),
+};
+
+static const unsigned int lineout_vol_tlv[] = {
+       TLV_DB_RANGE_HEAD(2),
+       0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
+       /* -54dB to 15dB */
+       0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0)
+};
+
+static const unsigned int mono_vol_tlv[] = {
+       TLV_DB_RANGE_HEAD(2),
+       0x0, 0x2, TLV_DB_SCALE_ITEM(-1800, 0, 1),
+       /* -18dB to 6dB */
+       0x3, 0x7, TLV_DB_SCALE_ITEM(-1800, 600, 0)
+};
+
+static const DECLARE_TLV_DB_SCALE(eq_gain_tlv, -1050, 150, 0);
+static const DECLARE_TLV_DB_SCALE(adc_eq_master_gain_tlv, -1800, 600, 1);
+static const DECLARE_TLV_DB_SCALE(dac_gain_tlv, -7725, 75, 0);
+
+/* ADC and DAC high pass filter f0 value */
+static const char const *da7210_hpf_cutoff_txt[] = {
+       "Fs/8192*pi", "Fs/4096*pi", "Fs/2048*pi", "Fs/1024*pi"
+};
+
+static const struct soc_enum da7210_dac_hpf_cutoff =
+       SOC_ENUM_SINGLE(DA7210_DAC_HPF, 0, 4, da7210_hpf_cutoff_txt);
+
+static const struct soc_enum da7210_adc_hpf_cutoff =
+       SOC_ENUM_SINGLE(DA7210_ADC_HPF, 0, 4, da7210_hpf_cutoff_txt);
+
+/* ADC and DAC voice (8kHz) high pass cutoff value */
+static const char const *da7210_vf_cutoff_txt[] = {
+       "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
+};
+
+static const struct soc_enum da7210_dac_vf_cutoff =
+       SOC_ENUM_SINGLE(DA7210_DAC_HPF, 4, 8, da7210_vf_cutoff_txt);
+
+static const struct soc_enum da7210_adc_vf_cutoff =
+       SOC_ENUM_SINGLE(DA7210_ADC_HPF, 4, 8, da7210_vf_cutoff_txt);
+
+static const char *da7210_hp_mode_txt[] = {
+       "Class H", "Class G"
+};
+
+static const struct soc_enum da7210_hp_mode_sel =
+       SOC_ENUM_SINGLE(DA7210_HP_CFG, 0, 2, da7210_hp_mode_txt);
+
+/* ALC can be enabled only if noise suppression is disabled */
+static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol,
+                            struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+       if (ucontrol->value.integer.value[0]) {
+               /* Check if noise suppression is enabled */
+               if (snd_soc_read(codec, DA7210_CONTROL) & DA7210_NOISE_SUP_EN) {
+                       dev_dbg(codec->dev,
+                               "Disable noise suppression to enable ALC\n");
+                       return -EINVAL;
+               }
+       }
+       /* If all conditions are met or we are actually disabling ALC */
+       return snd_soc_put_volsw(kcontrol, ucontrol);
+}
+
+/* Noise suppression can be enabled only if following conditions are met
+ *  ALC disabled
+ *  ZC enabled for HP and AUX1 PGA
+ *  INPGA_L_VOL and INPGA_R_VOL >= 10.5 dB
+ *  AUX1_L_VOL and AUX1_R_VOL >= 6 dB
+ */
+static int da7210_put_noise_sup_sw(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       u8 val;
+
+       if (ucontrol->value.integer.value[0]) {
+               /* Check if ALC is enabled */
+               if (snd_soc_read(codec, DA7210_ADC) & DA7210_ADC_ALC_EN)
+                       goto err;
+
+               /* Check ZC for HP and AUX1 PGA */
+               if ((snd_soc_read(codec, DA7210_ZERO_CROSS) &
+                       (DA7210_AUX1_L_ZC | DA7210_AUX1_R_ZC | DA7210_HP_L_ZC |
+                       DA7210_HP_R_ZC)) != (DA7210_AUX1_L_ZC |
+                       DA7210_AUX1_R_ZC | DA7210_HP_L_ZC | DA7210_HP_R_ZC))
+                       goto err;
+
+               /* Check INPGA_L_VOL and INPGA_R_VOL */
+               val = snd_soc_read(codec, DA7210_IN_GAIN);
+               if (((val & DA7210_INPGA_L_VOL) < DA7210_INPGA_MIN_VOL_NS) ||
+                       (((val & DA7210_INPGA_R_VOL) >> 4) <
+                       DA7210_INPGA_MIN_VOL_NS))
+                       goto err;
+
+               /* Check AUX1_L_VOL and AUX1_R_VOL */
+               if (((snd_soc_read(codec, DA7210_AUX1_L) & DA7210_AUX1_L_VOL) <
+                   DA7210_AUX1_MIN_VOL_NS) ||
+                   ((snd_soc_read(codec, DA7210_AUX1_R) & DA7210_AUX1_R_VOL) <
+                   DA7210_AUX1_MIN_VOL_NS))
+                       goto err;
+       }
+       /* If all conditions are met or we are actually disabling Noise sup */
+       return snd_soc_put_volsw(kcontrol, ucontrol);
+
+err:
+       return -EINVAL;
+}
 
 static const struct snd_kcontrol_new da7210_snd_controls[] = {
 
        SOC_DOUBLE_R_TLV("HeadPhone Playback Volume",
                         DA7210_HP_L_VOL, DA7210_HP_R_VOL,
                         0, 0x3F, 0, hp_out_tlv),
+       SOC_DOUBLE_R_TLV("Digital Playback Volume",
+                        DA7210_DAC_L, DA7210_DAC_R,
+                        0, 0x77, 1, dac_gain_tlv),
+       SOC_DOUBLE_R_TLV("Lineout Playback Volume",
+                        DA7210_OUT1_L, DA7210_OUT1_R,
+                        0, 0x3f, 0, lineout_vol_tlv),
+       SOC_SINGLE_TLV("Mono Playback Volume", DA7210_OUT2, 0, 0x7, 0,
+                      mono_vol_tlv),
+
+       /* DAC Equalizer  controls */
+       SOC_SINGLE("DAC EQ Switch", DA7210_DAC_EQ5, 7, 1, 0),
+       SOC_SINGLE_TLV("DAC EQ1 Volume", DA7210_DAC_EQ1_2, 0, 0xf, 1,
+                      eq_gain_tlv),
+       SOC_SINGLE_TLV("DAC EQ2 Volume", DA7210_DAC_EQ1_2, 4, 0xf, 1,
+                      eq_gain_tlv),
+       SOC_SINGLE_TLV("DAC EQ3 Volume", DA7210_DAC_EQ3_4, 0, 0xf, 1,
+                      eq_gain_tlv),
+       SOC_SINGLE_TLV("DAC EQ4 Volume", DA7210_DAC_EQ3_4, 4, 0xf, 1,
+                      eq_gain_tlv),
+       SOC_SINGLE_TLV("DAC EQ5 Volume", DA7210_DAC_EQ5, 0, 0xf, 1,
+                      eq_gain_tlv),
+
+       /* ADC Equalizer  controls */
+       SOC_SINGLE("ADC EQ Switch", DA7210_ADC_EQ5, 7, 1, 0),
+       SOC_SINGLE_TLV("ADC EQ Master Volume", DA7210_ADC_EQ5, 4, 0x3,
+                      1, adc_eq_master_gain_tlv),
+       SOC_SINGLE_TLV("ADC EQ1 Volume", DA7210_ADC_EQ1_2, 0, 0xf, 1,
+                      eq_gain_tlv),
+       SOC_SINGLE_TLV("ADC EQ2 Volume", DA7210_ADC_EQ1_2, 4, 0xf, 1,
+                      eq_gain_tlv),
+       SOC_SINGLE_TLV("ADC EQ3 Volume", DA7210_ADC_EQ3_4, 0, 0xf, 1,
+                      eq_gain_tlv),
+       SOC_SINGLE_TLV("ADC EQ4 Volume", DA7210_ADC_EQ3_4, 4, 0xf, 1,
+                      eq_gain_tlv),
+       SOC_SINGLE_TLV("ADC EQ5 Volume", DA7210_ADC_EQ5, 0, 0xf, 1,
+                      eq_gain_tlv),
+
+       SOC_SINGLE("DAC HPF Switch", DA7210_DAC_HPF, 3, 1, 0),
+       SOC_ENUM("DAC HPF Cutoff", da7210_dac_hpf_cutoff),
+       SOC_SINGLE("DAC Voice Mode Switch", DA7210_DAC_HPF, 7, 1, 0),
+       SOC_ENUM("DAC Voice Cutoff", da7210_dac_vf_cutoff),
+
+       SOC_SINGLE("ADC HPF Switch", DA7210_ADC_HPF, 3, 1, 0),
+       SOC_ENUM("ADC HPF Cutoff", da7210_adc_hpf_cutoff),
+       SOC_SINGLE("ADC Voice Mode Switch", DA7210_ADC_HPF, 7, 1, 0),
+       SOC_ENUM("ADC Voice Cutoff", da7210_adc_vf_cutoff),
+
+       /* Mute controls */
+       SOC_DOUBLE_R("Mic Capture Switch", DA7210_MIC_L, DA7210_MIC_R, 3, 1, 0),
+       SOC_SINGLE("Aux2 Capture Switch", DA7210_AUX2, 2, 1, 0),
+       SOC_DOUBLE("ADC Capture Switch", DA7210_ADC, 2, 6, 1, 0),
+       SOC_SINGLE("Digital Soft Mute Switch", DA7210_SOFTMUTE, 7, 1, 0),
+       SOC_SINGLE("Digital Soft Mute Rate", DA7210_SOFTMUTE, 0, 0x7, 0),
+
+       /* Zero cross controls */
+       SOC_DOUBLE("Aux1 ZC Switch", DA7210_ZERO_CROSS, 0, 1, 1, 0),
+       SOC_DOUBLE("In PGA ZC Switch", DA7210_ZERO_CROSS, 2, 3, 1, 0),
+       SOC_DOUBLE("Lineout ZC Switch", DA7210_ZERO_CROSS, 4, 5, 1, 0),
+       SOC_DOUBLE("Headphone ZC Switch", DA7210_ZERO_CROSS, 6, 7, 1, 0),
+
+       SOC_ENUM("Headphone Class", da7210_hp_mode_sel),
+
+       /* ALC controls */
+       SOC_SINGLE_EXT("ALC Enable Switch", DA7210_ADC, 0, 1, 0,
+                      snd_soc_get_volsw, da7210_put_alc_sw),
+       SOC_SINGLE("ALC Capture Max Volume", DA7210_ALC_MAX, 0, 0x3F, 0),
+       SOC_SINGLE("ALC Capture Min Volume", DA7210_ALC_MIN, 0, 0x3F, 0),
+       SOC_SINGLE("ALC Capture Noise Volume", DA7210_ALC_NOIS, 0, 0x3F, 0),
+       SOC_SINGLE("ALC Capture Attack Rate", DA7210_ALC_ATT, 0, 0xFF, 0),
+       SOC_SINGLE("ALC Capture Release Rate", DA7210_ALC_REL, 0, 0xFF, 0),
+       SOC_SINGLE("ALC Capture Release Delay", DA7210_ALC_DEL, 0, 0xFF, 0),
+
+       SOC_SINGLE_EXT("Noise Suppression Enable Switch", DA7210_CONTROL, 3, 1,
+                      0, snd_soc_get_volsw, da7210_put_noise_sup_sw),
+};
+
+/*
+ * DAPM Controls
+ *
+ * Current DAPM implementation covers almost all codec components e.g. IOs,
+ * mixers, PGAs,ADC and DAC.
+ */
+/* In Mixer Left */
+static const struct snd_kcontrol_new da7210_dapm_inmixl_controls[] = {
+       SOC_DAPM_SINGLE("Mic Left Switch", DA7210_INMIX_L, 0, 1, 0),
+       SOC_DAPM_SINGLE("Mic Right Switch", DA7210_INMIX_L, 1, 1, 0),
+};
+
+/* In Mixer Right */
+static const struct snd_kcontrol_new da7210_dapm_inmixr_controls[] = {
+       SOC_DAPM_SINGLE("Mic Right Switch", DA7210_INMIX_R, 0, 1, 0),
+       SOC_DAPM_SINGLE("Mic Left Switch", DA7210_INMIX_R, 1, 1, 0),
+};
+
+/* Out Mixer Left */
+static const struct snd_kcontrol_new da7210_dapm_outmixl_controls[] = {
+       SOC_DAPM_SINGLE("DAC Left Switch", DA7210_OUTMIX_L, 4, 1, 0),
+};
+
+/* Out Mixer Right */
+static const struct snd_kcontrol_new da7210_dapm_outmixr_controls[] = {
+       SOC_DAPM_SINGLE("DAC Right Switch", DA7210_OUTMIX_R, 4, 1, 0),
+};
+
+/* Mono Mixer */
+static const struct snd_kcontrol_new da7210_dapm_monomix_controls[] = {
+       SOC_DAPM_SINGLE("Outmix Right Switch", DA7210_OUT2, 5, 1, 0),
+       SOC_DAPM_SINGLE("Outmix Left Switch", DA7210_OUT2, 6, 1, 0),
+};
+
+/* DAPM widgets */
+static const struct snd_soc_dapm_widget da7210_dapm_widgets[] = {
+       /* Input Side */
+       /* Input Lines */
+       SND_SOC_DAPM_INPUT("MICL"),
+       SND_SOC_DAPM_INPUT("MICR"),
+
+       /* Input PGAs */
+       SND_SOC_DAPM_PGA("Mic Left", DA7210_STARTUP3, 0, 1, NULL, 0),
+       SND_SOC_DAPM_PGA("Mic Right", DA7210_STARTUP3, 1, 1, NULL, 0),
+
+       SND_SOC_DAPM_PGA("INPGA Left", DA7210_INMIX_L, 7, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("INPGA Right", DA7210_INMIX_R, 7, 0, NULL, 0),
+
+       /* Input Mixers */
+       SND_SOC_DAPM_MIXER("In Mixer Left", SND_SOC_NOPM, 0, 0,
+               &da7210_dapm_inmixl_controls[0],
+               ARRAY_SIZE(da7210_dapm_inmixl_controls)),
+
+       SND_SOC_DAPM_MIXER("In Mixer Right", SND_SOC_NOPM, 0, 0,
+               &da7210_dapm_inmixr_controls[0],
+               ARRAY_SIZE(da7210_dapm_inmixr_controls)),
+
+       /* ADCs */
+       SND_SOC_DAPM_ADC("ADC Left", "Capture", DA7210_STARTUP3, 5, 1),
+       SND_SOC_DAPM_ADC("ADC Right", "Capture", DA7210_STARTUP3, 6, 1),
+
+       /* Output Side */
+       /* DACs */
+       SND_SOC_DAPM_DAC("DAC Left", "Playback", DA7210_STARTUP2, 5, 1),
+       SND_SOC_DAPM_DAC("DAC Right", "Playback", DA7210_STARTUP2, 6, 1),
+
+       /* Output Mixers */
+       SND_SOC_DAPM_MIXER("Out Mixer Left", SND_SOC_NOPM, 0, 0,
+               &da7210_dapm_outmixl_controls[0],
+               ARRAY_SIZE(da7210_dapm_outmixl_controls)),
+
+       SND_SOC_DAPM_MIXER("Out Mixer Right", SND_SOC_NOPM, 0, 0,
+               &da7210_dapm_outmixr_controls[0],
+               ARRAY_SIZE(da7210_dapm_outmixr_controls)),
+
+       SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0,
+               &da7210_dapm_monomix_controls[0],
+               ARRAY_SIZE(da7210_dapm_monomix_controls)),
+
+       /* Output PGAs */
+       SND_SOC_DAPM_PGA("OUTPGA Left Enable", DA7210_OUTMIX_L, 7, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("OUTPGA Right Enable", DA7210_OUTMIX_R, 7, 0, NULL, 0),
+
+       SND_SOC_DAPM_PGA("Out1 Left", DA7210_STARTUP2, 0, 1, NULL, 0),
+       SND_SOC_DAPM_PGA("Out1 Right", DA7210_STARTUP2, 1, 1, NULL, 0),
+       SND_SOC_DAPM_PGA("Out2 Mono", DA7210_STARTUP2, 2, 1, NULL, 0),
+       SND_SOC_DAPM_PGA("Headphone Left", DA7210_STARTUP2, 3, 1, NULL, 0),
+       SND_SOC_DAPM_PGA("Headphone Right", DA7210_STARTUP2, 4, 1, NULL, 0),
+
+       /* Output Lines */
+       SND_SOC_DAPM_OUTPUT("OUT1L"),
+       SND_SOC_DAPM_OUTPUT("OUT1R"),
+       SND_SOC_DAPM_OUTPUT("HPL"),
+       SND_SOC_DAPM_OUTPUT("HPR"),
+       SND_SOC_DAPM_OUTPUT("OUT2"),
+};
+
+/* DAPM audio route definition */
+static const struct snd_soc_dapm_route da7210_audio_map[] = {
+       /* Dest       Connecting Widget    source */
+       /* Input path */
+       {"Mic Left", NULL, "MICL"},
+       {"Mic Right", NULL, "MICR"},
+
+       {"In Mixer Left", "Mic Left Switch", "Mic Left"},
+       {"In Mixer Left", "Mic Right Switch", "Mic Right"},
+
+       {"In Mixer Right", "Mic Right Switch", "Mic Right"},
+       {"In Mixer Right", "Mic Left Switch", "Mic Left"},
+
+       {"INPGA Left", NULL, "In Mixer Left"},
+       {"ADC Left", NULL, "INPGA Left"},
+
+       {"INPGA Right", NULL, "In Mixer Right"},
+       {"ADC Right", NULL, "INPGA Right"},
+
+       /* Output path */
+       {"Out Mixer Left", "DAC Left Switch", "DAC Left"},
+       {"Out Mixer Right", "DAC Right Switch", "DAC Right"},
+
+       {"Mono Mixer", "Outmix Right Switch", "Out Mixer Right"},
+       {"Mono Mixer", "Outmix Left Switch", "Out Mixer Left"},
+
+       {"OUTPGA Left Enable", NULL, "Out Mixer Left"},
+       {"OUTPGA Right Enable", NULL, "Out Mixer Right"},
+
+       {"Out1 Left", NULL, "OUTPGA Left Enable"},
+       {"OUT1L", NULL, "Out1 Left"},
+
+       {"Out1 Right", NULL, "OUTPGA Right Enable"},
+       {"OUT1R", NULL, "Out1 Right"},
+
+       {"Headphone Left", NULL, "OUTPGA Left Enable"},
+       {"HPL", NULL, "Headphone Left"},
+
+       {"Headphone Right", NULL, "OUTPGA Right Enable"},
+       {"HPR", NULL, "Headphone Right"},
+
+       {"Out2 Mono", NULL, "Mono Mixer"},
+       {"OUT2", NULL, "Out2 Mono"},
 };
 
 /* Codec private data */
 struct da7210_priv {
        enum snd_soc_control_type control_type;
-       void *control_data;
 };
 
 /*
@@ -188,72 +582,15 @@ static const u8 da7210_reg[] = {
        0x00,                                           /* R88       */
 };
 
-/*
- * Read da7210 register cache
- */
-static inline u32 da7210_read_reg_cache(struct snd_soc_codec *codec, u32 reg)
-{
-       u8 *cache = codec->reg_cache;
-       BUG_ON(reg >= ARRAY_SIZE(da7210_reg));
-       return cache[reg];
-}
-
-/*
- * Write to the da7210 register space
- */
-static int da7210_write(struct snd_soc_codec *codec, u32 reg, u32 value)
+static int da7210_volatile_register(struct snd_soc_codec *codec,
+                                   unsigned int reg)
 {
-       u8 *cache = codec->reg_cache;
-       u8 data[2];
-
-       BUG_ON(codec->driver->volatile_register);
-
-       data[0] = reg & 0xff;
-       data[1] = value & 0xff;
-
-       if (reg >= codec->driver->reg_cache_size)
-               return -EIO;
-
-       if (2 != codec->hw_write(codec->control_data, data, 2))
-               return -EIO;
-
-       cache[reg] = value;
-       return 0;
-}
-
-/*
- * Read from the da7210 register space.
- */
-static inline u32 da7210_read(struct snd_soc_codec *codec, u32 reg)
-{
-       if (DA7210_STATUS == reg)
-               return i2c_smbus_read_byte_data(codec->control_data, reg);
-
-       return da7210_read_reg_cache(codec, reg);
-}
-
-static int da7210_startup(struct snd_pcm_substream *substream,
-                         struct snd_soc_dai *dai)
-{
-       int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-       struct snd_soc_codec *codec = dai->codec;
-
-       if (is_play) {
-               /* Enable Out */
-               snd_soc_update_bits(codec, DA7210_OUTMIX_L, 0x1F, 0x10);
-               snd_soc_update_bits(codec, DA7210_OUTMIX_R, 0x1F, 0x10);
-
-       } else {
-               /* Volume 7 */
-               snd_soc_update_bits(codec, DA7210_MIC_L, 0x7, 0x7);
-               snd_soc_update_bits(codec, DA7210_MIC_R, 0x7, 0x7);
-
-               /* Enable Mic */
-               snd_soc_update_bits(codec, DA7210_INMIX_L, 0x1F, 0x1);
-               snd_soc_update_bits(codec, DA7210_INMIX_R, 0x1F, 0x1);
+       switch (reg) {
+       case DA7210_STATUS:
+               return 1;
+       default:
+               return 0;
        }
-
-       return 0;
 }
 
 /*
@@ -266,93 +603,75 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_codec *codec = rtd->codec;
        u32 dai_cfg1;
-       u32 hpf_reg, hpf_mask, hpf_value;
        u32 fs, bypass;
 
        /* set DAI source to Left and Right ADC */
-       da7210_write(codec, DA7210_DAI_SRC_SEL,
+       snd_soc_write(codec, DA7210_DAI_SRC_SEL,
                     DA7210_DAI_OUT_R_SRC | DA7210_DAI_OUT_L_SRC);
 
        /* Enable DAI */
-       da7210_write(codec, DA7210_DAI_CFG3, DA7210_DAI_OE | DA7210_DAI_EN);
+       snd_soc_write(codec, DA7210_DAI_CFG3, DA7210_DAI_OE | DA7210_DAI_EN);
 
-       dai_cfg1 = 0xFC & da7210_read(codec, DA7210_DAI_CFG1);
+       dai_cfg1 = 0xFC & snd_soc_read(codec, DA7210_DAI_CFG1);
 
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
                dai_cfg1 |= DA7210_DAI_WORD_S16_LE;
                break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               dai_cfg1 |= DA7210_DAI_WORD_S20_3LE;
+               break;
        case SNDRV_PCM_FORMAT_S24_LE:
                dai_cfg1 |= DA7210_DAI_WORD_S24_LE;
                break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               dai_cfg1 |= DA7210_DAI_WORD_S32_LE;
+               break;
        default:
                return -EINVAL;
        }
 
-       da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1);
-
-       hpf_reg = (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) ?
-               DA7210_DAC_HPF : DA7210_ADC_HPF;
+       snd_soc_write(codec, DA7210_DAI_CFG1, dai_cfg1);
 
        switch (params_rate(params)) {
        case 8000:
                fs              = DA7210_PLL_FS_8000;
-               hpf_mask        = DA7210_VOICE_F0_MASK  | DA7210_VOICE_EN;
-               hpf_value       = DA7210_VOICE_F0_25    | DA7210_VOICE_EN;
                bypass          = DA7210_PLL_BYP;
                break;
        case 11025:
                fs              = DA7210_PLL_FS_11025;
-               hpf_mask        = DA7210_VOICE_F0_MASK  | DA7210_VOICE_EN;
-               hpf_value       = DA7210_VOICE_F0_25    | DA7210_VOICE_EN;
                bypass          = 0;
                break;
        case 12000:
                fs              = DA7210_PLL_FS_12000;
-               hpf_mask        = DA7210_VOICE_F0_MASK  | DA7210_VOICE_EN;
-               hpf_value       = DA7210_VOICE_F0_25    | DA7210_VOICE_EN;
                bypass          = DA7210_PLL_BYP;
                break;
        case 16000:
                fs              = DA7210_PLL_FS_16000;
-               hpf_mask        = DA7210_VOICE_F0_MASK  | DA7210_VOICE_EN;
-               hpf_value       = DA7210_VOICE_F0_25    | DA7210_VOICE_EN;
                bypass          = DA7210_PLL_BYP;
                break;
        case 22050:
                fs              = DA7210_PLL_FS_22050;
-               hpf_mask        = DA7210_VOICE_EN;
-               hpf_value       = 0;
                bypass          = 0;
                break;
        case 32000:
                fs              = DA7210_PLL_FS_32000;
-               hpf_mask        = DA7210_VOICE_EN;
-               hpf_value       = 0;
                bypass          = DA7210_PLL_BYP;
                break;
        case 44100:
                fs              = DA7210_PLL_FS_44100;
-               hpf_mask        = DA7210_VOICE_EN;
-               hpf_value       = 0;
                bypass          = 0;
                break;
        case 48000:
                fs              = DA7210_PLL_FS_48000;
-               hpf_mask        = DA7210_VOICE_EN;
-               hpf_value       = 0;
                bypass          = DA7210_PLL_BYP;
                break;
        case 88200:
                fs              = DA7210_PLL_FS_88200;
-               hpf_mask        = DA7210_VOICE_EN;
-               hpf_value       = 0;
                bypass          = 0;
                break;
        case 96000:
                fs              = DA7210_PLL_FS_96000;
-               hpf_mask        = DA7210_VOICE_EN;
-               hpf_value       = 0;
                bypass          = DA7210_PLL_BYP;
                break;
        default:
@@ -362,7 +681,6 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
        /* Disable active mode */
        snd_soc_update_bits(codec, DA7210_STARTUP1, DA7210_SC_MST_EN, 0);
 
-       snd_soc_update_bits(codec, hpf_reg, hpf_mask, hpf_value);
        snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_FS_MASK, fs);
        snd_soc_update_bits(codec, DA7210_PLL_DIV3, DA7210_PLL_BYP, bypass);
 
@@ -382,13 +700,16 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
        u32 dai_cfg1;
        u32 dai_cfg3;
 
-       dai_cfg1 = 0x7f & da7210_read(codec, DA7210_DAI_CFG1);
-       dai_cfg3 = 0xfc & da7210_read(codec, DA7210_DAI_CFG3);
+       dai_cfg1 = 0x7f & snd_soc_read(codec, DA7210_DAI_CFG1);
+       dai_cfg3 = 0xfc & snd_soc_read(codec, DA7210_DAI_CFG3);
 
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBM_CFM:
                dai_cfg1 |= DA7210_DAI_MODE_MASTER;
                break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               dai_cfg1 |= DA7210_DAI_MODE_SLAVE;
+               break;
        default:
                return -EINVAL;
        }
@@ -401,6 +722,12 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
        case SND_SOC_DAIFMT_I2S:
                dai_cfg3 |= DA7210_DAI_FORMAT_I2SMODE;
                break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               dai_cfg3 |= DA7210_DAI_FORMAT_LEFT_J;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               dai_cfg3 |= DA7210_DAI_FORMAT_RIGHT_J;
+               break;
        default:
                return -EINVAL;
        }
@@ -411,19 +738,32 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
         */
        dai_cfg1 |= DA7210_DAI_FLEN_64BIT;
 
-       da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1);
-       da7210_write(codec, DA7210_DAI_CFG3, dai_cfg3);
+       snd_soc_write(codec, DA7210_DAI_CFG1, dai_cfg1);
+       snd_soc_write(codec, DA7210_DAI_CFG3, dai_cfg3);
+
+       return 0;
+}
+
+static int da7210_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       u8 mute_reg = snd_soc_read(codec, DA7210_DAC_HPF) & 0xFB;
 
+       if (mute)
+               snd_soc_write(codec, DA7210_DAC_HPF, mute_reg | 0x4);
+       else
+               snd_soc_write(codec, DA7210_DAC_HPF, mute_reg);
        return 0;
 }
 
-#define DA7210_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
+#define DA7210_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+                       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
 /* DAI operations */
 static struct snd_soc_dai_ops da7210_dai_ops = {
-       .startup        = da7210_startup,
        .hw_params      = da7210_hw_params,
        .set_fmt        = da7210_set_dai_fmt,
+       .digital_mute   = da7210_mute,
 };
 
 static struct snd_soc_dai_driver da7210_dai = {
@@ -451,11 +791,15 @@ static struct snd_soc_dai_driver da7210_dai = {
 static int da7210_probe(struct snd_soc_codec *codec)
 {
        struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
        dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
 
-       codec->control_data     = da7210->control_data;
-       codec->hw_write         = (hw_write_t)i2c_master_send;
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, da7210->control_type);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
 
        /* FIXME
         *
@@ -472,8 +816,8 @@ static int da7210_probe(struct snd_soc_codec *codec)
        /*
         * make sure that DA7210 use bypass mode before start up
         */
-       da7210_write(codec, DA7210_STARTUP1, 0);
-       da7210_write(codec, DA7210_PLL_DIV3,
+       snd_soc_write(codec, DA7210_STARTUP1, 0);
+       snd_soc_write(codec, DA7210_PLL_DIV3,
                     DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
 
        /*
@@ -481,36 +825,70 @@ static int da7210_probe(struct snd_soc_codec *codec)
         */
 
        /* Enable Left & Right MIC PGA and Mic Bias */
-       da7210_write(codec, DA7210_MIC_L, DA7210_MIC_L_EN | DA7210_MICBIAS_EN);
-       da7210_write(codec, DA7210_MIC_R, DA7210_MIC_R_EN);
+       snd_soc_write(codec, DA7210_MIC_L, DA7210_MIC_L_EN | DA7210_MICBIAS_EN);
+       snd_soc_write(codec, DA7210_MIC_R, DA7210_MIC_R_EN);
 
        /* Enable Left and Right input PGA */
-       da7210_write(codec, DA7210_INMIX_L, DA7210_IN_L_EN);
-       da7210_write(codec, DA7210_INMIX_R, DA7210_IN_R_EN);
+       snd_soc_write(codec, DA7210_INMIX_L, DA7210_IN_L_EN);
+       snd_soc_write(codec, DA7210_INMIX_R, DA7210_IN_R_EN);
 
        /* Enable Left and Right ADC */
-       da7210_write(codec, DA7210_ADC, DA7210_ADC_L_EN | DA7210_ADC_R_EN);
+       snd_soc_write(codec, DA7210_ADC, DA7210_ADC_L_EN | DA7210_ADC_R_EN);
 
        /*
         * DAC settings
         */
 
        /* Enable Left and Right DAC */
-       da7210_write(codec, DA7210_DAC_SEL,
+       snd_soc_write(codec, DA7210_DAC_SEL,
                     DA7210_DAC_L_SRC_DAI_L | DA7210_DAC_L_EN |
                     DA7210_DAC_R_SRC_DAI_R | DA7210_DAC_R_EN);
 
        /* Enable Left and Right out PGA */
-       da7210_write(codec, DA7210_OUTMIX_L, DA7210_OUT_L_EN);
-       da7210_write(codec, DA7210_OUTMIX_R, DA7210_OUT_R_EN);
+       snd_soc_write(codec, DA7210_OUTMIX_L, DA7210_OUT_L_EN);
+       snd_soc_write(codec, DA7210_OUTMIX_R, DA7210_OUT_R_EN);
 
        /* Enable Left and Right HeadPhone PGA */
-       da7210_write(codec, DA7210_HP_CFG,
+       snd_soc_write(codec, DA7210_HP_CFG,
                     DA7210_HP_2CAP_MODE | DA7210_HP_SENSE_EN |
                     DA7210_HP_L_EN | DA7210_HP_MODE | DA7210_HP_R_EN);
 
+       /* Enable ramp mode for DAC gain update */
+       snd_soc_write(codec, DA7210_SOFTMUTE, DA7210_RAMP_EN);
+
+       /*
+        * For DA7210 codec, there are two ways to enable/disable analog IOs
+        * and ADC/DAC,
+        * (1) Using "Enable Bit" of register associated with that IO
+        * (or ADC/DAC)
+        *      e.g. Mic Left can be enabled using bit 7 of MIC_L(0x7) reg
+        *
+        * (2) Using "Standby Bit" of STARTUP2 or STARTUP3 register
+        *      e.g. Mic left can be put to STANDBY using bit 0 of STARTUP3(0x5)
+        *
+        * Out of these two methods, the one using STANDBY bits is preferred
+        * way to enable/disable individual blocks. This is because STANDBY
+        * registers are part of system controller which allows system power
+        * up/down in a controlled, pop-free manner. Also, as per application
+        * note of DA7210, STANDBY register bits are only effective if a
+        * particular IO (or ADC/DAC) is already enabled using enable/disable
+        * register bits. Keeping these things in mind, current DAPM
+        * implementation manipulates only STANDBY bits.
+        *
+        * Overall implementation can be outlined as below,
+        *
+        * - "Enable bit" of an IO or ADC/DAC is used to enable it in probe()
+        * - "STANDBY bit" is controlled by DAPM
+        */
+
+       /* Enable Line out amplifiers */
+       snd_soc_write(codec, DA7210_OUT1_L, DA7210_OUT1_L_EN);
+       snd_soc_write(codec, DA7210_OUT1_R, DA7210_OUT1_R_EN);
+       snd_soc_write(codec, DA7210_OUT2, DA7210_OUT2_EN |
+                    DA7210_OUT2_OUTMIX_L | DA7210_OUT2_OUTMIX_R);
+
        /* Diable PLL and bypass it */
-       da7210_write(codec, DA7210_PLL, DA7210_PLL_FS_48000);
+       snd_soc_write(codec, DA7210_PLL, DA7210_PLL_FS_48000);
 
        /*
         * If 48kHz sound came, it use bypass mode,
@@ -521,25 +899,22 @@ static int da7210_probe(struct snd_soc_codec *codec)
         * DA7210_PLL_DIV3 :: DA7210_PLL_BYP bit.
         *   see da7210_hw_params
         */
-       da7210_write(codec, DA7210_PLL_DIV1, 0xE5); /* MCLK = 12.288MHz */
-       da7210_write(codec, DA7210_PLL_DIV2, 0x99);
-       da7210_write(codec, DA7210_PLL_DIV3, 0x0A |
+       snd_soc_write(codec, DA7210_PLL_DIV1, 0xE5); /* MCLK = 12.288MHz */
+       snd_soc_write(codec, DA7210_PLL_DIV2, 0x99);
+       snd_soc_write(codec, DA7210_PLL_DIV3, 0x0A |
                     DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
        snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN);
 
        /* As suggested by Dialog */
-       da7210_write(codec, DA7210_A_HID_UNLOCK,        0x8B); /* unlock */
-       da7210_write(codec, DA7210_A_TEST_UNLOCK,       0xB4);
-       da7210_write(codec, DA7210_A_PLL1,              0x01);
-       da7210_write(codec, DA7210_A_CP_MODE,           0x7C);
-       da7210_write(codec, DA7210_A_HID_UNLOCK,        0x00); /* re-lock */
-       da7210_write(codec, DA7210_A_TEST_UNLOCK,       0x00);
+       snd_soc_write(codec, DA7210_A_HID_UNLOCK,       0x8B); /* unlock */
+       snd_soc_write(codec, DA7210_A_TEST_UNLOCK,      0xB4);
+       snd_soc_write(codec, DA7210_A_PLL1,             0x01);
+       snd_soc_write(codec, DA7210_A_CP_MODE,          0x7C);
+       snd_soc_write(codec, DA7210_A_HID_UNLOCK,       0x00); /* re-lock */
+       snd_soc_write(codec, DA7210_A_TEST_UNLOCK,      0x00);
 
        /* Activate all enabled subsystem */
-       da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
-
-       snd_soc_add_controls(codec, da7210_snd_controls,
-                            ARRAY_SIZE(da7210_snd_controls));
+       snd_soc_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
 
        dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
 
@@ -548,11 +923,18 @@ static int da7210_probe(struct snd_soc_codec *codec)
 
 static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
        .probe                  = da7210_probe,
-       .read                   = da7210_read,
-       .write                  = da7210_write,
        .reg_cache_size         = ARRAY_SIZE(da7210_reg),
        .reg_word_size          = sizeof(u8),
        .reg_cache_default      = da7210_reg,
+       .volatile_register      = da7210_volatile_register,
+
+       .controls               = da7210_snd_controls,
+       .num_controls           = ARRAY_SIZE(da7210_snd_controls),
+
+       .dapm_widgets           = da7210_dapm_widgets,
+       .num_dapm_widgets       = ARRAY_SIZE(da7210_dapm_widgets),
+       .dapm_routes            = da7210_audio_map,
+       .num_dapm_routes        = ARRAY_SIZE(da7210_audio_map),
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
@@ -567,7 +949,6 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, da7210);
-       da7210->control_data = i2c;
        da7210->control_type = SND_SOC_I2C;
 
        ret =  snd_soc_register_codec(&i2c->dev,
index 2c2a681..c387daf 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2007 Wolfson Microelectronics PLC.
  * Author: Graeme Gregory
- *         graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
+ *         graeme.gregory@wolfsonmicro.com
  * Copyright 2011 Lars-Peter Clausen <lars@metafoo.de>
  *
  *  This program is free software; you can redistribute  it and/or modify it
index ac65a2d..ebbf63c 100644 (file)
@@ -40,7 +40,6 @@ struct max98088_cdata {
 
 struct max98088_priv {
        enum max98088_type devtype;
-       void *control_data;
        struct max98088_pdata *pdata;
        unsigned int sysclk;
        struct max98088_cdata dai[2];
@@ -1697,13 +1696,19 @@ static struct snd_soc_dai_driver max98088_dai[] = {
 }
 };
 
-static int max98088_get_channel(const char *name)
+static const char *eq_mode_name[] = {"EQ1 Mode", "EQ2 Mode"};
+
+static int max98088_get_channel(struct snd_soc_codec *codec, const char *name)
 {
-       if (strcmp(name, "EQ1 Mode") == 0)
-               return 0;
-       if (strcmp(name, "EQ2 Mode") == 0)
-               return 1;
-       return -EINVAL;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(eq_mode_name); i++)
+               if (strcmp(name, eq_mode_name[i]) == 0)
+                       return i;
+
+       /* Shouldn't happen */
+       dev_err(codec->dev, "Bad EQ channel name '%s'\n", name);
+       return -EINVAL;
 }
 
 static void max98088_setup_eq1(struct snd_soc_codec *codec)
@@ -1807,10 +1812,13 @@ static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
        struct max98088_pdata *pdata = max98088->pdata;
-       int channel = max98088_get_channel(kcontrol->id.name);
+       int channel = max98088_get_channel(codec, kcontrol->id.name);
        struct max98088_cdata *cdata;
        int sel = ucontrol->value.integer.value[0];
 
+       if (channel < 0)
+              return channel;
+
        cdata = &max98088->dai[channel];
 
        if (sel >= pdata->eq_cfgcnt)
@@ -1835,9 +1843,12 @@ static int max98088_get_eq_enum(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
-       int channel = max98088_get_channel(kcontrol->id.name);
+       int channel = max98088_get_channel(codec, kcontrol->id.name);
        struct max98088_cdata *cdata;
 
+       if (channel < 0)
+              return channel;
+
        cdata = &max98088->dai[channel];
        ucontrol->value.enumerated.item[0] = cdata->eq_sel;
        return 0;
@@ -1852,17 +1863,17 @@ static void max98088_handle_eq_pdata(struct snd_soc_codec *codec)
        int i, j;
        const char **t;
        int ret;
-
        struct snd_kcontrol_new controls[] = {
-               SOC_ENUM_EXT("EQ1 Mode",
+               SOC_ENUM_EXT((char *)eq_mode_name[0],
                        max98088->eq_enum,
                        max98088_get_eq_enum,
                        max98088_put_eq_enum),
-               SOC_ENUM_EXT("EQ2 Mode",
+               SOC_ENUM_EXT((char *)eq_mode_name[1],
                        max98088->eq_enum,
                        max98088_get_eq_enum,
                        max98088_put_eq_enum),
        };
+       BUILD_BUG_ON(ARRAY_SIZE(controls) != ARRAY_SIZE(eq_mode_name));
 
        cfg = pdata->eq_cfg;
        cfgcnt = pdata->eq_cfgcnt;
@@ -2066,7 +2077,6 @@ static int max98088_i2c_probe(struct i2c_client *i2c,
        max98088->devtype = id->driver_data;
 
        i2c_set_clientdata(i2c, max98088);
-       max98088->control_data = i2c;
        max98088->pdata = i2c->dev.platform_data;
 
        ret = snd_soc_register_codec(&i2c->dev,
index 668434d..26d7b08 100644 (file)
@@ -40,7 +40,6 @@ struct max98095_cdata {
 
 struct max98095_priv {
        enum max98095_type devtype;
-       void *control_data;
        struct max98095_pdata *pdata;
        unsigned int sysclk;
        struct max98095_cdata dai[3];
@@ -618,14 +617,13 @@ static int max98095_volatile(struct snd_soc_codec *codec, unsigned int reg)
 static int max98095_hw_write(struct snd_soc_codec *codec, unsigned int reg,
                             unsigned int value)
 {
-       u8 data[2];
+       int ret;
 
-       data[0] = reg;
-       data[1] = value;
-       if (codec->hw_write(codec->control_data, data, 2) == 2)
-               return 0;
-       else
-               return -EIO;
+       codec->cache_bypass = 1;
+       ret = snd_soc_write(codec, reg, value);
+       codec->cache_bypass = 0;
+
+       return ret ? -EIO : 0;
 }
 
 /*
@@ -1992,12 +1990,19 @@ static void max98095_handle_eq_pdata(struct snd_soc_codec *codec)
                dev_err(codec->dev, "Failed to add EQ control: %d\n", ret);
 }
 
-static int max98095_get_bq_channel(const char *name)
+static const char *bq_mode_name[] = {"Biquad1 Mode", "Biquad2 Mode"};
+
+static int max98095_get_bq_channel(struct snd_soc_codec *codec,
+                                  const char *name)
 {
-       if (strcmp(name, "Biquad1 Mode") == 0)
-               return 0;
-       if (strcmp(name, "Biquad2 Mode") == 0)
-               return 1;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(bq_mode_name); i++)
+               if (strcmp(name, bq_mode_name[i]) == 0)
+                       return i;
+
+       /* Shouldn't happen */
+       dev_err(codec->dev, "Bad biquad channel name '%s'\n", name);
        return -EINVAL;
 }
 
@@ -2007,14 +2012,15 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
        struct max98095_pdata *pdata = max98095->pdata;
-       int channel = max98095_get_bq_channel(kcontrol->id.name);
+       int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
        struct max98095_cdata *cdata;
        int sel = ucontrol->value.integer.value[0];
        struct max98095_biquad_cfg *coef_set;
        int fs, best, best_val, i;
        int regmask, regsave;
 
-       BUG_ON(channel > 1);
+       if (channel < 0)
+               return channel;
 
        if (!pdata || !max98095->bq_textcnt)
                return 0;
@@ -2066,9 +2072,12 @@ static int max98095_get_bq_enum(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
-       int channel = max98095_get_bq_channel(kcontrol->id.name);
+       int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
        struct max98095_cdata *cdata;
 
+       if (channel < 0)
+               return channel;
+
        cdata = &max98095->dai[channel];
        ucontrol->value.enumerated.item[0] = cdata->bq_sel;
 
@@ -2086,15 +2095,16 @@ static void max98095_handle_bq_pdata(struct snd_soc_codec *codec)
        int ret;
 
        struct snd_kcontrol_new controls[] = {
-               SOC_ENUM_EXT("Biquad1 Mode",
+               SOC_ENUM_EXT((char *)bq_mode_name[0],
                        max98095->bq_enum,
                        max98095_get_bq_enum,
                        max98095_put_bq_enum),
-               SOC_ENUM_EXT("Biquad2 Mode",
+               SOC_ENUM_EXT((char *)bq_mode_name[1],
                        max98095->bq_enum,
                        max98095_get_bq_enum,
                        max98095_put_bq_enum),
        };
+       BUILD_BUG_ON(ARRAY_SIZE(controls) != ARRAY_SIZE(bq_mode_name));
 
        cfg = pdata->bq_cfg;
        cfgcnt = pdata->bq_cfgcnt;
@@ -2337,7 +2347,6 @@ static int max98095_i2c_probe(struct i2c_client *i2c,
 
        max98095->devtype = id->driver_data;
        i2c_set_clientdata(i2c, max98095);
-       max98095->control_data = i2c;
        max98095->pdata = i2c->dev.platform_data;
 
        ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98095,
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
new file mode 100644 (file)
index 0000000..27a078c
--- /dev/null
@@ -0,0 +1,1773 @@
+/*
+ * rt5631.c  --  RT5631 ALSA Soc Audio driver
+ *
+ * Copyright 2011 Realtek Microelectronics
+ *
+ * Author: flove <flove@realtek.com>
+ *
+ * Based on WM8753.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "rt5631.h"
+
+struct rt5631_priv {
+       int codec_version;
+       int master;
+       int sysclk;
+       int rx_rate;
+       int bclk_rate;
+       int dmic_used_flag;
+};
+
+static const u16 rt5631_reg[RT5631_VENDOR_ID2 + 1] = {
+       [RT5631_SPK_OUT_VOL] = 0x8888,
+       [RT5631_HP_OUT_VOL] = 0x8080,
+       [RT5631_MONO_AXO_1_2_VOL] = 0xa080,
+       [RT5631_AUX_IN_VOL] = 0x0808,
+       [RT5631_ADC_REC_MIXER] = 0xf0f0,
+       [RT5631_VDAC_DIG_VOL] = 0x0010,
+       [RT5631_OUTMIXER_L_CTRL] = 0xffc0,
+       [RT5631_OUTMIXER_R_CTRL] = 0xffc0,
+       [RT5631_AXO1MIXER_CTRL] = 0x88c0,
+       [RT5631_AXO2MIXER_CTRL] = 0x88c0,
+       [RT5631_DIG_MIC_CTRL] = 0x3000,
+       [RT5631_MONO_INPUT_VOL] = 0x8808,
+       [RT5631_SPK_MIXER_CTRL] = 0xf8f8,
+       [RT5631_SPK_MONO_OUT_CTRL] = 0xfc00,
+       [RT5631_SPK_MONO_HP_OUT_CTRL] = 0x4440,
+       [RT5631_SDP_CTRL] = 0x8000,
+       [RT5631_MONO_SDP_CTRL] = 0x8000,
+       [RT5631_STEREO_AD_DA_CLK_CTRL] = 0x2010,
+       [RT5631_GEN_PUR_CTRL_REG] = 0x0e00,
+       [RT5631_INT_ST_IRQ_CTRL_2] = 0x071a,
+       [RT5631_MISC_CTRL] = 0x2040,
+       [RT5631_DEPOP_FUN_CTRL_2] = 0x8000,
+       [RT5631_SOFT_VOL_CTRL] = 0x07e0,
+       [RT5631_ALC_CTRL_1] = 0x0206,
+       [RT5631_ALC_CTRL_3] = 0x2000,
+       [RT5631_PSEUDO_SPATL_CTRL] = 0x0553,
+};
+
+/**
+ * rt5631_write_index - write index register of 2nd layer
+ */
+static void rt5631_write_index(struct snd_soc_codec *codec,
+               unsigned int reg, unsigned int value)
+{
+       snd_soc_write(codec, RT5631_INDEX_ADD, reg);
+       snd_soc_write(codec, RT5631_INDEX_DATA, value);
+}
+
+/**
+ * rt5631_read_index - read index register of 2nd layer
+ */
+static unsigned int rt5631_read_index(struct snd_soc_codec *codec,
+                               unsigned int reg)
+{
+       unsigned int value;
+
+       snd_soc_write(codec, RT5631_INDEX_ADD, reg);
+       value = snd_soc_read(codec, RT5631_INDEX_DATA);
+
+       return value;
+}
+
+static int rt5631_reset(struct snd_soc_codec *codec)
+{
+       return snd_soc_write(codec, RT5631_RESET, 0);
+}
+
+static int rt5631_volatile_register(struct snd_soc_codec *codec,
+                                   unsigned int reg)
+{
+       switch (reg) {
+       case RT5631_RESET:
+       case RT5631_INT_ST_IRQ_CTRL_2:
+       case RT5631_INDEX_ADD:
+       case RT5631_INDEX_DATA:
+       case RT5631_EQ_CTRL:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static int rt5631_readable_register(struct snd_soc_codec *codec,
+                                   unsigned int reg)
+{
+       switch (reg) {
+       case RT5631_RESET:
+       case RT5631_SPK_OUT_VOL:
+       case RT5631_HP_OUT_VOL:
+       case RT5631_MONO_AXO_1_2_VOL:
+       case RT5631_AUX_IN_VOL:
+       case RT5631_STEREO_DAC_VOL_1:
+       case RT5631_MIC_CTRL_1:
+       case RT5631_STEREO_DAC_VOL_2:
+       case RT5631_ADC_CTRL_1:
+       case RT5631_ADC_REC_MIXER:
+       case RT5631_ADC_CTRL_2:
+       case RT5631_VDAC_DIG_VOL:
+       case RT5631_OUTMIXER_L_CTRL:
+       case RT5631_OUTMIXER_R_CTRL:
+       case RT5631_AXO1MIXER_CTRL:
+       case RT5631_AXO2MIXER_CTRL:
+       case RT5631_MIC_CTRL_2:
+       case RT5631_DIG_MIC_CTRL:
+       case RT5631_MONO_INPUT_VOL:
+       case RT5631_SPK_MIXER_CTRL:
+       case RT5631_SPK_MONO_OUT_CTRL:
+       case RT5631_SPK_MONO_HP_OUT_CTRL:
+       case RT5631_SDP_CTRL:
+       case RT5631_MONO_SDP_CTRL:
+       case RT5631_STEREO_AD_DA_CLK_CTRL:
+       case RT5631_PWR_MANAG_ADD1:
+       case RT5631_PWR_MANAG_ADD2:
+       case RT5631_PWR_MANAG_ADD3:
+       case RT5631_PWR_MANAG_ADD4:
+       case RT5631_GEN_PUR_CTRL_REG:
+       case RT5631_GLOBAL_CLK_CTRL:
+       case RT5631_PLL_CTRL:
+       case RT5631_INT_ST_IRQ_CTRL_1:
+       case RT5631_INT_ST_IRQ_CTRL_2:
+       case RT5631_GPIO_CTRL:
+       case RT5631_MISC_CTRL:
+       case RT5631_DEPOP_FUN_CTRL_1:
+       case RT5631_DEPOP_FUN_CTRL_2:
+       case RT5631_JACK_DET_CTRL:
+       case RT5631_SOFT_VOL_CTRL:
+       case RT5631_ALC_CTRL_1:
+       case RT5631_ALC_CTRL_2:
+       case RT5631_ALC_CTRL_3:
+       case RT5631_PSEUDO_SPATL_CTRL:
+       case RT5631_INDEX_ADD:
+       case RT5631_INDEX_DATA:
+       case RT5631_EQ_CTRL:
+       case RT5631_VENDOR_ID:
+       case RT5631_VENDOR_ID1:
+       case RT5631_VENDOR_ID2:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -95625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
+/* {0, +20, +24, +30, +35, +40, +44, +50, +52}dB */
+static unsigned int mic_bst_tlv[] = {
+       TLV_DB_RANGE_HEAD(6),
+       0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+       1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
+       2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
+       3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
+       6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
+       7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
+       8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
+};
+
+static int rt5631_dmic_get(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.integer.value[0] = rt5631->dmic_used_flag;
+
+       return 0;
+}
+
+static int rt5631_dmic_put(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+       rt5631->dmic_used_flag = ucontrol->value.integer.value[0];
+       return 0;
+}
+
+/* MIC Input Type */
+static const char *rt5631_input_mode[] = {
+       "Single ended", "Differential"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1,
+       RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode);
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1,
+       RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode);
+
+/* MONO Input Type */
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL,
+       RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode);
+
+/* SPK Ratio Gain Control */
+static const char *rt5631_spk_ratio[] = {"1.00x", "1.09x", "1.27x", "1.44x",
+                       "1.56x", "1.68x", "1.99x", "2.34x"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG,
+       RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio);
+
+static const struct snd_kcontrol_new rt5631_snd_controls[] = {
+       /* MIC */
+       SOC_ENUM("MIC1 Mode Control",  rt5631_mic1_mode_enum),
+       SOC_SINGLE_TLV("MIC1 Boost", RT5631_MIC_CTRL_2,
+               RT5631_MIC1_BOOST_SHIFT, 8, 0, mic_bst_tlv),
+       SOC_ENUM("MIC2 Mode Control", rt5631_mic2_mode_enum),
+       SOC_SINGLE_TLV("MIC2 Boost", RT5631_MIC_CTRL_2,
+               RT5631_MIC2_BOOST_SHIFT, 8, 0, mic_bst_tlv),
+       /* MONO IN */
+       SOC_ENUM("MONOIN Mode Control", rt5631_monoin_mode_enum),
+       SOC_DOUBLE_TLV("MONOIN_RX Capture Volume", RT5631_MONO_INPUT_VOL,
+                       RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT,
+                       RT5631_VOL_MASK, 1, in_vol_tlv),
+       /* AXI */
+       SOC_DOUBLE_TLV("AXI Capture Volume", RT5631_AUX_IN_VOL,
+                       RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT,
+                       RT5631_VOL_MASK, 1, in_vol_tlv),
+       /* DAC */
+       SOC_DOUBLE_TLV("PCM Playback Volume", RT5631_STEREO_DAC_VOL_2,
+                       RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT,
+                       RT5631_DAC_VOL_MASK, 1, dac_vol_tlv),
+       SOC_DOUBLE("PCM Playback Switch", RT5631_STEREO_DAC_VOL_1,
+                       RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1),
+       /* AXO */
+       SOC_SINGLE("AXO1 Playback Switch", RT5631_MONO_AXO_1_2_VOL,
+                               RT5631_L_MUTE_SHIFT, 1, 1),
+       SOC_SINGLE("AXO2 Playback Switch", RT5631_MONO_AXO_1_2_VOL,
+                               RT5631_R_VOL_SHIFT, 1, 1),
+       /* OUTVOL */
+       SOC_DOUBLE("OUTVOL Channel Switch", RT5631_SPK_OUT_VOL,
+               RT5631_L_EN_SHIFT, RT5631_R_EN_SHIFT, 1, 0),
+
+       /* SPK */
+       SOC_DOUBLE("Speaker Playback Switch", RT5631_SPK_OUT_VOL,
+               RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1),
+       SOC_DOUBLE_TLV("Speaker Playback Volume", RT5631_SPK_OUT_VOL,
+               RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT, 39, 1, out_vol_tlv),
+       /* MONO OUT */
+       SOC_SINGLE("MONO Playback Switch", RT5631_MONO_AXO_1_2_VOL,
+                               RT5631_MUTE_MONO_SHIFT, 1, 1),
+       /* HP */
+       SOC_DOUBLE("HP Playback Switch", RT5631_HP_OUT_VOL,
+               RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1),
+       SOC_DOUBLE_TLV("HP Playback Volume", RT5631_HP_OUT_VOL,
+               RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT,
+               RT5631_VOL_MASK, 1, out_vol_tlv),
+       /* DMIC */
+       SOC_SINGLE_EXT("DMIC Switch", 0, 0, 1, 0,
+               rt5631_dmic_get, rt5631_dmic_put),
+       SOC_DOUBLE("DMIC Capture Switch", RT5631_DIG_MIC_CTRL,
+               RT5631_DMIC_L_CH_MUTE_SHIFT,
+               RT5631_DMIC_R_CH_MUTE_SHIFT, 1, 1),
+
+       /* SPK Ratio Gain Control */
+       SOC_ENUM("SPK Ratio Control", rt5631_spk_ratio_enum),
+};
+
+static int check_sysclk1_source(struct snd_soc_dapm_widget *source,
+                        struct snd_soc_dapm_widget *sink)
+{
+       unsigned int reg;
+
+       reg = snd_soc_read(source->codec, RT5631_GLOBAL_CLK_CTRL);
+       return reg & RT5631_SYSCLK_SOUR_SEL_PLL;
+}
+
+static int check_dmic_used(struct snd_soc_dapm_widget *source,
+                        struct snd_soc_dapm_widget *sink)
+{
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(source->codec);
+       return rt5631->dmic_used_flag;
+}
+
+static int check_dacl_to_outmixl(struct snd_soc_dapm_widget *source,
+                        struct snd_soc_dapm_widget *sink)
+{
+       unsigned int reg;
+
+       reg = snd_soc_read(source->codec, RT5631_OUTMIXER_L_CTRL);
+       return !(reg & RT5631_M_DAC_L_TO_OUTMIXER_L);
+}
+
+static int check_dacr_to_outmixr(struct snd_soc_dapm_widget *source,
+                        struct snd_soc_dapm_widget *sink)
+{
+       unsigned int reg;
+
+       reg = snd_soc_read(source->codec, RT5631_OUTMIXER_R_CTRL);
+       return !(reg & RT5631_M_DAC_R_TO_OUTMIXER_R);
+}
+
+static int check_dacl_to_spkmixl(struct snd_soc_dapm_widget *source,
+                        struct snd_soc_dapm_widget *sink)
+{
+       unsigned int reg;
+
+       reg = snd_soc_read(source->codec, RT5631_SPK_MIXER_CTRL);
+       return !(reg & RT5631_M_DAC_L_TO_SPKMIXER_L);
+}
+
+static int check_dacr_to_spkmixr(struct snd_soc_dapm_widget *source,
+                        struct snd_soc_dapm_widget *sink)
+{
+       unsigned int reg;
+
+       reg = snd_soc_read(source->codec, RT5631_SPK_MIXER_CTRL);
+       return !(reg & RT5631_M_DAC_R_TO_SPKMIXER_R);
+}
+
+static int check_adcl_select(struct snd_soc_dapm_widget *source,
+                        struct snd_soc_dapm_widget *sink)
+{
+       unsigned int reg;
+
+       reg = snd_soc_read(source->codec, RT5631_ADC_REC_MIXER);
+       return !(reg & RT5631_M_MIC1_TO_RECMIXER_L);
+}
+
+static int check_adcr_select(struct snd_soc_dapm_widget *source,
+                        struct snd_soc_dapm_widget *sink)
+{
+       unsigned int reg;
+
+       reg = snd_soc_read(source->codec, RT5631_ADC_REC_MIXER);
+       return !(reg & RT5631_M_MIC2_TO_RECMIXER_R);
+}
+
+/**
+ * onebit_depop_power_stage - auto depop in power stage.
+ * @enable: power on/off
+ *
+ * When power on/off headphone, the depop sequence is done by hardware.
+ */
+static void onebit_depop_power_stage(struct snd_soc_codec *codec, int enable)
+{
+       unsigned int soft_vol, hp_zc;
+
+       /* enable one-bit depop function */
+       snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2,
+                               RT5631_EN_ONE_BIT_DEPOP, 0);
+
+       /* keep soft volume and zero crossing setting */
+       soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL);
+       snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0);
+       hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2);
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff);
+       if (enable) {
+               /* config one-bit depop parameter */
+               rt5631_write_index(codec, RT5631_TEST_MODE_CTRL, 0x84c0);
+               rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x309f);
+               rt5631_write_index(codec, RT5631_CP_INTL_REG2, 0x6530);
+               /* power on capless block */
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_2,
+                               RT5631_EN_CAP_FREE_DEPOP);
+       } else {
+               /* power off capless block */
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_2, 0);
+               msleep(100);
+       }
+
+       /* recover soft volume and zero crossing setting */
+       snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol);
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc);
+}
+
+/**
+ * onebit_depop_mute_stage - auto depop in mute stage.
+ * @enable: mute/unmute
+ *
+ * When mute/unmute headphone, the depop sequence is done by hardware.
+ */
+static void onebit_depop_mute_stage(struct snd_soc_codec *codec, int enable)
+{
+       unsigned int soft_vol, hp_zc;
+
+       /* enable one-bit depop function */
+       snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2,
+                               RT5631_EN_ONE_BIT_DEPOP, 0);
+
+       /* keep soft volume and zero crossing setting */
+       soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL);
+       snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0);
+       hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2);
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff);
+       if (enable) {
+               schedule_timeout_uninterruptible(msecs_to_jiffies(10));
+               /* config one-bit depop parameter */
+               rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x307f);
+               snd_soc_update_bits(codec, RT5631_HP_OUT_VOL,
+                               RT5631_L_MUTE | RT5631_R_MUTE, 0);
+               msleep(300);
+       } else {
+               snd_soc_update_bits(codec, RT5631_HP_OUT_VOL,
+                       RT5631_L_MUTE | RT5631_R_MUTE,
+                       RT5631_L_MUTE | RT5631_R_MUTE);
+               msleep(100);
+       }
+
+       /* recover soft volume and zero crossing setting */
+       snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol);
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc);
+}
+
+/**
+ * onebit_depop_power_stage - step by step depop sequence in power stage.
+ * @enable: power on/off
+ *
+ * When power on/off headphone, the depop sequence is done in step by step.
+ */
+static void depop_seq_power_stage(struct snd_soc_codec *codec, int enable)
+{
+       unsigned int soft_vol, hp_zc;
+
+       /* depop control by register */
+       snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2,
+               RT5631_EN_ONE_BIT_DEPOP, RT5631_EN_ONE_BIT_DEPOP);
+
+       /* keep soft volume and zero crossing setting */
+       soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL);
+       snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0);
+       hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2);
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff);
+       if (enable) {
+               /* config depop sequence parameter */
+               rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x303e);
+
+               /* power on headphone and charge pump */
+               snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+                       RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP |
+                       RT5631_PWR_HP_R_AMP,
+                       RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP |
+                       RT5631_PWR_HP_R_AMP);
+
+               /* power on soft generator and depop mode2 */
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+                       RT5631_POW_ON_SOFT_GEN | RT5631_EN_DEPOP2_FOR_HP);
+               msleep(100);
+
+               /* stop depop mode */
+               snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+                       RT5631_PWR_HP_DEPOP_DIS, RT5631_PWR_HP_DEPOP_DIS);
+       } else {
+               /* config depop sequence parameter */
+               rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x303F);
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+                       RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP |
+                       RT5631_PD_HPAMP_L_ST_UP | RT5631_PD_HPAMP_R_ST_UP);
+               msleep(75);
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+                       RT5631_POW_ON_SOFT_GEN | RT5631_PD_HPAMP_L_ST_UP |
+                       RT5631_PD_HPAMP_R_ST_UP);
+
+               /* start depop mode */
+               snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+                               RT5631_PWR_HP_DEPOP_DIS, 0);
+
+               /* config depop sequence parameter */
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+                       RT5631_POW_ON_SOFT_GEN | RT5631_EN_DEPOP2_FOR_HP |
+                       RT5631_PD_HPAMP_L_ST_UP | RT5631_PD_HPAMP_R_ST_UP);
+               msleep(80);
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+                       RT5631_POW_ON_SOFT_GEN);
+
+               /* power down headphone and charge pump */
+               snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+                       RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP |
+                       RT5631_PWR_HP_R_AMP, 0);
+       }
+
+       /* recover soft volume and zero crossing setting */
+       snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol);
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc);
+}
+
+/**
+ * depop_seq_mute_stage - step by step depop sequence in mute stage.
+ * @enable: mute/unmute
+ *
+ * When mute/unmute headphone, the depop sequence is done in step by step.
+ */
+static void depop_seq_mute_stage(struct snd_soc_codec *codec, int enable)
+{
+       unsigned int soft_vol, hp_zc;
+
+       /* depop control by register */
+       snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2,
+               RT5631_EN_ONE_BIT_DEPOP, RT5631_EN_ONE_BIT_DEPOP);
+
+       /* keep soft volume and zero crossing setting */
+       soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL);
+       snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0);
+       hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2);
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff);
+       if (enable) {
+               schedule_timeout_uninterruptible(msecs_to_jiffies(10));
+
+               /* config depop sequence parameter */
+               rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x302f);
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+                       RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP |
+                       RT5631_EN_HP_R_M_UN_MUTE_DEPOP |
+                       RT5631_EN_HP_L_M_UN_MUTE_DEPOP);
+
+               snd_soc_update_bits(codec, RT5631_HP_OUT_VOL,
+                               RT5631_L_MUTE | RT5631_R_MUTE, 0);
+               msleep(160);
+       } else {
+               /* config depop sequence parameter */
+               rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x302f);
+               snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+                       RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP |
+                       RT5631_EN_HP_R_M_UN_MUTE_DEPOP |
+                       RT5631_EN_HP_L_M_UN_MUTE_DEPOP);
+
+               snd_soc_update_bits(codec, RT5631_HP_OUT_VOL,
+                       RT5631_L_MUTE | RT5631_R_MUTE,
+                       RT5631_L_MUTE | RT5631_R_MUTE);
+               msleep(150);
+       }
+
+       /* recover soft volume and zero crossing setting */
+       snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol);
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc);
+}
+
+static int hp_event(struct snd_soc_dapm_widget *w,
+       struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMD:
+               if (rt5631->codec_version) {
+                       onebit_depop_mute_stage(codec, 0);
+                       onebit_depop_power_stage(codec, 0);
+               } else {
+                       depop_seq_mute_stage(codec, 0);
+                       depop_seq_power_stage(codec, 0);
+               }
+               break;
+
+       case SND_SOC_DAPM_POST_PMU:
+               if (rt5631->codec_version) {
+                       onebit_depop_power_stage(codec, 1);
+                       onebit_depop_mute_stage(codec, 1);
+               } else {
+                       depop_seq_power_stage(codec, 1);
+                       depop_seq_mute_stage(codec, 1);
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int set_dmic_params(struct snd_soc_dapm_widget *w,
+       struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+       switch (rt5631->rx_rate) {
+       case 44100:
+       case 48000:
+               snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL,
+                       RT5631_DMIC_CLK_CTRL_MASK,
+                       RT5631_DMIC_CLK_CTRL_TO_32FS);
+               break;
+
+       case 32000:
+       case 22050:
+               snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL,
+                       RT5631_DMIC_CLK_CTRL_MASK,
+                       RT5631_DMIC_CLK_CTRL_TO_64FS);
+               break;
+
+       case 16000:
+       case 11025:
+       case 8000:
+               snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL,
+                       RT5631_DMIC_CLK_CTRL_MASK,
+                       RT5631_DMIC_CLK_CTRL_TO_128FS);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct snd_kcontrol_new rt5631_recmixl_mixer_controls[] = {
+       SOC_DAPM_SINGLE("OUTMIXL Capture Switch", RT5631_ADC_REC_MIXER,
+                       RT5631_M_OUTMIXL_RECMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC1_BST1 Capture Switch", RT5631_ADC_REC_MIXER,
+                       RT5631_M_MIC1_RECMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("AXILVOL Capture Switch", RT5631_ADC_REC_MIXER,
+                       RT5631_M_AXIL_RECMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MONOIN_RX Capture Switch", RT5631_ADC_REC_MIXER,
+                       RT5631_M_MONO_IN_RECMIXL_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_recmixr_mixer_controls[] = {
+       SOC_DAPM_SINGLE("MONOIN_RX Capture Switch", RT5631_ADC_REC_MIXER,
+                       RT5631_M_MONO_IN_RECMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("AXIRVOL Capture Switch", RT5631_ADC_REC_MIXER,
+                       RT5631_M_AXIR_RECMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC2_BST2 Capture Switch", RT5631_ADC_REC_MIXER,
+                       RT5631_M_MIC2_RECMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("OUTMIXR Capture Switch", RT5631_ADC_REC_MIXER,
+                       RT5631_M_OUTMIXR_RECMIXR_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_spkmixl_mixer_controls[] = {
+       SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_SPK_MIXER_CTRL,
+                       RT5631_M_RECMIXL_SPKMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC1_P Playback Switch", RT5631_SPK_MIXER_CTRL,
+                       RT5631_M_MIC1P_SPKMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("DACL Playback Switch", RT5631_SPK_MIXER_CTRL,
+                       RT5631_M_DACL_SPKMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("OUTMIXL Playback Switch", RT5631_SPK_MIXER_CTRL,
+                       RT5631_M_OUTMIXL_SPKMIXL_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_spkmixr_mixer_controls[] = {
+       SOC_DAPM_SINGLE("OUTMIXR Playback Switch", RT5631_SPK_MIXER_CTRL,
+                       RT5631_M_OUTMIXR_SPKMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("DACR Playback Switch", RT5631_SPK_MIXER_CTRL,
+                       RT5631_M_DACR_SPKMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC2_P Playback Switch", RT5631_SPK_MIXER_CTRL,
+                       RT5631_M_MIC2P_SPKMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_SPK_MIXER_CTRL,
+                       RT5631_M_RECMIXR_SPKMIXR_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_outmixl_mixer_controls[] = {
+       SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_RECMIXL_OUTMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_RECMIXR_OUTMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("DACL Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_DACL_OUTMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_MIC1_OUTMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_MIC2_OUTMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MONOIN_RXP Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_MONO_INP_OUTMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("AXILVOL Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_AXIL_OUTMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("AXIRVOL Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_AXIR_OUTMIXL_BIT, 1, 1),
+       SOC_DAPM_SINGLE("VDAC Playback Switch", RT5631_OUTMIXER_L_CTRL,
+                               RT5631_M_VDAC_OUTMIXL_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_outmixr_mixer_controls[] = {
+       SOC_DAPM_SINGLE("VDAC Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_VDAC_OUTMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("AXIRVOL Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_AXIR_OUTMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("AXILVOL Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_AXIL_OUTMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MONOIN_RXN Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_MONO_INN_OUTMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_MIC2_OUTMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_MIC1_OUTMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("DACR Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_DACR_OUTMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_RECMIXR_OUTMIXR_BIT, 1, 1),
+       SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_OUTMIXER_R_CTRL,
+                               RT5631_M_RECMIXL_OUTMIXR_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_AXO1MIX_mixer_controls[] = {
+       SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_AXO1MIXER_CTRL,
+                               RT5631_M_MIC1_AXO1MIX_BIT , 1, 1),
+       SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_AXO1MIXER_CTRL,
+                               RT5631_M_MIC2_AXO1MIX_BIT, 1, 1),
+       SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_AXO1MIXER_CTRL,
+                               RT5631_M_OUTMIXL_AXO1MIX_BIT , 1 , 1),
+       SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_AXO1MIXER_CTRL,
+                               RT5631_M_OUTMIXR_AXO1MIX_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_AXO2MIX_mixer_controls[] = {
+       SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_AXO2MIXER_CTRL,
+                               RT5631_M_MIC1_AXO2MIX_BIT, 1, 1),
+       SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_AXO2MIXER_CTRL,
+                               RT5631_M_MIC2_AXO2MIX_BIT, 1, 1),
+       SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_AXO2MIXER_CTRL,
+                               RT5631_M_OUTMIXL_AXO2MIX_BIT, 1, 1),
+       SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_AXO2MIXER_CTRL,
+                               RT5631_M_OUTMIXR_AXO2MIX_BIT, 1 , 1),
+};
+
+static const struct snd_kcontrol_new rt5631_spolmix_mixer_controls[] = {
+       SOC_DAPM_SINGLE("SPKVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+                               RT5631_M_SPKVOLL_SPOLMIX_BIT, 1, 1),
+       SOC_DAPM_SINGLE("SPKVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+                               RT5631_M_SPKVOLR_SPOLMIX_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_spormix_mixer_controls[] = {
+       SOC_DAPM_SINGLE("SPKVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+                               RT5631_M_SPKVOLL_SPORMIX_BIT, 1, 1),
+       SOC_DAPM_SINGLE("SPKVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+                               RT5631_M_SPKVOLR_SPORMIX_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_monomix_mixer_controls[] = {
+       SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+                               RT5631_M_OUTVOLL_MONOMIX_BIT, 1, 1),
+       SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+                               RT5631_M_OUTVOLR_MONOMIX_BIT, 1, 1),
+};
+
+/* Left SPK Volume Input */
+static const char *rt5631_spkvoll_sel[] = {"Vmid", "SPKMIXL"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL,
+       RT5631_L_EN_SHIFT, rt5631_spkvoll_sel);
+
+static const struct snd_kcontrol_new rt5631_spkvoll_mux_control =
+       SOC_DAPM_ENUM("Left SPKVOL SRC", rt5631_spkvoll_enum);
+
+/* Left HP Volume Input */
+static const char *rt5631_hpvoll_sel[] = {"Vmid", "OUTMIXL"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_hpvoll_enum, RT5631_HP_OUT_VOL,
+       RT5631_L_EN_SHIFT, rt5631_hpvoll_sel);
+
+static const struct snd_kcontrol_new rt5631_hpvoll_mux_control =
+       SOC_DAPM_ENUM("Left HPVOL SRC", rt5631_hpvoll_enum);
+
+/* Left Out Volume Input */
+static const char *rt5631_outvoll_sel[] = {"Vmid", "OUTMIXL"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL,
+       RT5631_L_EN_SHIFT, rt5631_outvoll_sel);
+
+static const struct snd_kcontrol_new rt5631_outvoll_mux_control =
+       SOC_DAPM_ENUM("Left OUTVOL SRC", rt5631_outvoll_enum);
+
+/* Right Out Volume Input */
+static const char *rt5631_outvolr_sel[] = {"Vmid", "OUTMIXR"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL,
+       RT5631_R_EN_SHIFT, rt5631_outvolr_sel);
+
+static const struct snd_kcontrol_new rt5631_outvolr_mux_control =
+       SOC_DAPM_ENUM("Right OUTVOL SRC", rt5631_outvolr_enum);
+
+/* Right HP Volume Input */
+static const char *rt5631_hpvolr_sel[] = {"Vmid", "OUTMIXR"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_hpvolr_enum, RT5631_HP_OUT_VOL,
+       RT5631_R_EN_SHIFT, rt5631_hpvolr_sel);
+
+static const struct snd_kcontrol_new rt5631_hpvolr_mux_control =
+       SOC_DAPM_ENUM("Right HPVOL SRC", rt5631_hpvolr_enum);
+
+/* Right SPK Volume Input */
+static const char *rt5631_spkvolr_sel[] = {"Vmid", "SPKMIXR"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL,
+       RT5631_R_EN_SHIFT, rt5631_spkvolr_sel);
+
+static const struct snd_kcontrol_new rt5631_spkvolr_mux_control =
+       SOC_DAPM_ENUM("Right SPKVOL SRC", rt5631_spkvolr_enum);
+
+/* SPO Left Channel Input */
+static const char *rt5631_spol_src_sel[] = {
+       "SPOLMIX", "MONOIN_RX", "VDAC", "DACL"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+       RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel);
+
+static const struct snd_kcontrol_new rt5631_spol_mux_control =
+       SOC_DAPM_ENUM("SPOL SRC", rt5631_spol_src_enum);
+
+/* SPO Right Channel Input */
+static const char *rt5631_spor_src_sel[] = {
+       "SPORMIX", "MONOIN_RX", "VDAC", "DACR"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+       RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel);
+
+static const struct snd_kcontrol_new rt5631_spor_mux_control =
+       SOC_DAPM_ENUM("SPOR SRC", rt5631_spor_src_enum);
+
+/* MONO Input */
+static const char *rt5631_mono_src_sel[] = {"MONOMIX", "MONOIN_RX", "VDAC"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+       RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel);
+
+static const struct snd_kcontrol_new rt5631_mono_mux_control =
+       SOC_DAPM_ENUM("MONO SRC", rt5631_mono_src_enum);
+
+/* Left HPO Input */
+static const char *rt5631_hpl_src_sel[] = {"Left HPVOL", "Left DAC"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+       RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel);
+
+static const struct snd_kcontrol_new rt5631_hpl_mux_control =
+       SOC_DAPM_ENUM("HPL SRC", rt5631_hpl_src_enum);
+
+/* Right HPO Input */
+static const char *rt5631_hpr_src_sel[] = {"Right HPVOL", "Right DAC"};
+
+static const SOC_ENUM_SINGLE_DECL(
+       rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+       RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel);
+
+static const struct snd_kcontrol_new rt5631_hpr_mux_control =
+       SOC_DAPM_ENUM("HPR SRC", rt5631_hpr_src_enum);
+
+static const struct snd_soc_dapm_widget rt5631_dapm_widgets[] = {
+       /* Vmid */
+       SND_SOC_DAPM_VMID("Vmid"),
+       /* PLL1 */
+       SND_SOC_DAPM_SUPPLY("PLL1", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_PLL1_BIT, 0, NULL, 0),
+
+       /* Input Side */
+       /* Input Lines */
+       SND_SOC_DAPM_INPUT("MIC1"),
+       SND_SOC_DAPM_INPUT("MIC2"),
+       SND_SOC_DAPM_INPUT("AXIL"),
+       SND_SOC_DAPM_INPUT("AXIR"),
+       SND_SOC_DAPM_INPUT("MONOIN_RXN"),
+       SND_SOC_DAPM_INPUT("MONOIN_RXP"),
+       SND_SOC_DAPM_INPUT("DMIC"),
+
+       /* MICBIAS */
+       SND_SOC_DAPM_MICBIAS("MIC Bias1", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_MICBIAS1_VOL_BIT, 0),
+       SND_SOC_DAPM_MICBIAS("MIC Bias2", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_MICBIAS2_VOL_BIT, 0),
+
+       /* Boost */
+       SND_SOC_DAPM_PGA("MIC1 Boost", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_MIC1_BOOT_GAIN_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("MIC2 Boost", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_MIC2_BOOT_GAIN_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("MONOIN_RXP Boost", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_MONO_IN_P_VOL_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("MONOIN_RXN Boost", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_MONO_IN_N_VOL_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("AXIL Boost", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_AXIL_IN_VOL_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("AXIR Boost", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_AXIR_IN_VOL_BIT, 0, NULL, 0),
+
+       /* MONO In */
+       SND_SOC_DAPM_MIXER("MONO_IN", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       /* REC Mixer */
+       SND_SOC_DAPM_MIXER("RECMIXL Mixer", RT5631_PWR_MANAG_ADD2,
+               RT5631_PWR_RECMIXER_L_BIT, 0,
+               &rt5631_recmixl_mixer_controls[0],
+               ARRAY_SIZE(rt5631_recmixl_mixer_controls)),
+       SND_SOC_DAPM_MIXER("RECMIXR Mixer", RT5631_PWR_MANAG_ADD2,
+               RT5631_PWR_RECMIXER_R_BIT, 0,
+               &rt5631_recmixr_mixer_controls[0],
+               ARRAY_SIZE(rt5631_recmixr_mixer_controls)),
+       /* Because of record duplication for L/R channel,
+        * L/R ADCs need power up at the same time */
+       SND_SOC_DAPM_MIXER("ADC Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       /* DMIC */
+       SND_SOC_DAPM_SUPPLY("DMIC Supply", RT5631_DIG_MIC_CTRL,
+               RT5631_DMIC_ENA_SHIFT, 0,
+               set_dmic_params, SND_SOC_DAPM_PRE_PMU),
+       /* ADC Data Srouce */
+       SND_SOC_DAPM_SUPPLY("Left ADC Select", RT5631_INT_ST_IRQ_CTRL_2,
+                       RT5631_ADC_DATA_SEL_MIC1_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("Right ADC Select", RT5631_INT_ST_IRQ_CTRL_2,
+                       RT5631_ADC_DATA_SEL_MIC2_SHIFT, 0, NULL, 0),
+
+       /* ADCs */
+       SND_SOC_DAPM_ADC("Left ADC", "HIFI Capture",
+               RT5631_PWR_MANAG_ADD1, RT5631_PWR_ADC_L_CLK_BIT, 0),
+       SND_SOC_DAPM_ADC("Right ADC", "HIFI Capture",
+               RT5631_PWR_MANAG_ADD1, RT5631_PWR_ADC_R_CLK_BIT, 0),
+
+       /* DAC and ADC supply power */
+       SND_SOC_DAPM_SUPPLY("I2S", RT5631_PWR_MANAG_ADD1,
+                       RT5631_PWR_MAIN_I2S_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("DAC REF", RT5631_PWR_MANAG_ADD1,
+                       RT5631_PWR_DAC_REF_BIT, 0, NULL, 0),
+
+       /* Output Side */
+       /* DACs */
+       SND_SOC_DAPM_DAC("Left DAC", "HIFI Playback",
+               RT5631_PWR_MANAG_ADD1, RT5631_PWR_DAC_L_CLK_BIT, 0),
+       SND_SOC_DAPM_DAC("Right DAC", "HIFI Playback",
+               RT5631_PWR_MANAG_ADD1, RT5631_PWR_DAC_R_CLK_BIT, 0),
+       SND_SOC_DAPM_DAC("Voice DAC", "Voice DAC Mono Playback",
+                               SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_PGA("Voice DAC Boost", SND_SOC_NOPM, 0, 0, NULL, 0),
+       /* DAC supply power */
+       SND_SOC_DAPM_SUPPLY("Left DAC To Mixer", RT5631_PWR_MANAG_ADD1,
+                       RT5631_PWR_DAC_L_TO_MIXER_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("Right DAC To Mixer", RT5631_PWR_MANAG_ADD1,
+                       RT5631_PWR_DAC_R_TO_MIXER_BIT, 0, NULL, 0),
+
+       /* Left SPK Mixer */
+       SND_SOC_DAPM_MIXER("SPKMIXL Mixer", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_SPKMIXER_L_BIT, 0,
+                       &rt5631_spkmixl_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_spkmixl_mixer_controls)),
+       /* Left Out Mixer */
+       SND_SOC_DAPM_MIXER("OUTMIXL Mixer", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_OUTMIXER_L_BIT, 0,
+                       &rt5631_outmixl_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_outmixl_mixer_controls)),
+       /* Right Out Mixer */
+       SND_SOC_DAPM_MIXER("OUTMIXR Mixer", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_OUTMIXER_R_BIT, 0,
+                       &rt5631_outmixr_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_outmixr_mixer_controls)),
+       /* Right SPK Mixer */
+       SND_SOC_DAPM_MIXER("SPKMIXR Mixer", RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_SPKMIXER_R_BIT, 0,
+                       &rt5631_spkmixr_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_spkmixr_mixer_controls)),
+
+       /* Volume Mux */
+       SND_SOC_DAPM_MUX("Left SPKVOL Mux", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_SPK_L_VOL_BIT, 0,
+                       &rt5631_spkvoll_mux_control),
+       SND_SOC_DAPM_MUX("Left HPVOL Mux", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_HP_L_OUT_VOL_BIT, 0,
+                       &rt5631_hpvoll_mux_control),
+       SND_SOC_DAPM_MUX("Left OUTVOL Mux", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_LOUT_VOL_BIT, 0,
+                       &rt5631_outvoll_mux_control),
+       SND_SOC_DAPM_MUX("Right OUTVOL Mux", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_ROUT_VOL_BIT, 0,
+                       &rt5631_outvolr_mux_control),
+       SND_SOC_DAPM_MUX("Right HPVOL Mux", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_HP_R_OUT_VOL_BIT, 0,
+                       &rt5631_hpvolr_mux_control),
+       SND_SOC_DAPM_MUX("Right SPKVOL Mux", RT5631_PWR_MANAG_ADD4,
+                       RT5631_PWR_SPK_R_VOL_BIT, 0,
+                       &rt5631_spkvolr_mux_control),
+
+       /* DAC To HP */
+       SND_SOC_DAPM_PGA_S("Left DAC_HP", 0, SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA_S("Right DAC_HP", 0, SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       /* HP Depop */
+       SND_SOC_DAPM_PGA_S("HP Depop", 1, SND_SOC_NOPM, 0, 0,
+               hp_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+
+       /* AXO1 Mixer */
+       SND_SOC_DAPM_MIXER("AXO1MIX Mixer", RT5631_PWR_MANAG_ADD3,
+                       RT5631_PWR_AXO1MIXER_BIT, 0,
+                       &rt5631_AXO1MIX_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_AXO1MIX_mixer_controls)),
+       /* SPOL Mixer */
+       SND_SOC_DAPM_MIXER("SPOLMIX Mixer", SND_SOC_NOPM, 0, 0,
+                       &rt5631_spolmix_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_spolmix_mixer_controls)),
+       /* MONO Mixer */
+       SND_SOC_DAPM_MIXER("MONOMIX Mixer", RT5631_PWR_MANAG_ADD3,
+                       RT5631_PWR_MONOMIXER_BIT, 0,
+                       &rt5631_monomix_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_monomix_mixer_controls)),
+       /* SPOR Mixer */
+       SND_SOC_DAPM_MIXER("SPORMIX Mixer", SND_SOC_NOPM, 0, 0,
+                       &rt5631_spormix_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_spormix_mixer_controls)),
+       /* AXO2 Mixer */
+       SND_SOC_DAPM_MIXER("AXO2MIX Mixer", RT5631_PWR_MANAG_ADD3,
+                       RT5631_PWR_AXO2MIXER_BIT, 0,
+                       &rt5631_AXO2MIX_mixer_controls[0],
+                       ARRAY_SIZE(rt5631_AXO2MIX_mixer_controls)),
+
+       /* Mux */
+       SND_SOC_DAPM_MUX("SPOL Mux", SND_SOC_NOPM, 0, 0,
+                       &rt5631_spol_mux_control),
+       SND_SOC_DAPM_MUX("SPOR Mux", SND_SOC_NOPM, 0, 0,
+                       &rt5631_spor_mux_control),
+       SND_SOC_DAPM_MUX("MONO Mux", SND_SOC_NOPM, 0, 0,
+                       &rt5631_mono_mux_control),
+       SND_SOC_DAPM_MUX("HPL Mux", SND_SOC_NOPM, 0, 0,
+                       &rt5631_hpl_mux_control),
+       SND_SOC_DAPM_MUX("HPR Mux", SND_SOC_NOPM, 0, 0,
+                       &rt5631_hpr_mux_control),
+
+       /* AMP supply */
+       SND_SOC_DAPM_SUPPLY("MONO Depop", RT5631_PWR_MANAG_ADD3,
+                       RT5631_PWR_MONO_DEPOP_DIS_BIT, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("Class D", RT5631_PWR_MANAG_ADD1,
+                       RT5631_PWR_CLASS_D_BIT, 0, NULL, 0),
+
+       /* Output Lines */
+       SND_SOC_DAPM_OUTPUT("AUXO1"),
+       SND_SOC_DAPM_OUTPUT("AUXO2"),
+       SND_SOC_DAPM_OUTPUT("SPOL"),
+       SND_SOC_DAPM_OUTPUT("SPOR"),
+       SND_SOC_DAPM_OUTPUT("HPOL"),
+       SND_SOC_DAPM_OUTPUT("HPOR"),
+       SND_SOC_DAPM_OUTPUT("MONO"),
+};
+
+static const struct snd_soc_dapm_route rt5631_dapm_routes[] = {
+       {"MIC1 Boost", NULL, "MIC1"},
+       {"MIC2 Boost", NULL, "MIC2"},
+       {"MONOIN_RXP Boost", NULL, "MONOIN_RXP"},
+       {"MONOIN_RXN Boost", NULL, "MONOIN_RXN"},
+       {"AXIL Boost", NULL, "AXIL"},
+       {"AXIR Boost", NULL, "AXIR"},
+
+       {"MONO_IN", NULL, "MONOIN_RXP Boost"},
+       {"MONO_IN", NULL, "MONOIN_RXN Boost"},
+
+       {"RECMIXL Mixer", "OUTMIXL Capture Switch", "OUTMIXL Mixer"},
+       {"RECMIXL Mixer", "MIC1_BST1 Capture Switch", "MIC1 Boost"},
+       {"RECMIXL Mixer", "AXILVOL Capture Switch", "AXIL Boost"},
+       {"RECMIXL Mixer", "MONOIN_RX Capture Switch", "MONO_IN"},
+
+       {"RECMIXR Mixer", "OUTMIXR Capture Switch", "OUTMIXR Mixer"},
+       {"RECMIXR Mixer", "MIC2_BST2 Capture Switch", "MIC2 Boost"},
+       {"RECMIXR Mixer", "AXIRVOL Capture Switch", "AXIR Boost"},
+       {"RECMIXR Mixer", "MONOIN_RX Capture Switch", "MONO_IN"},
+
+       {"ADC Mixer", NULL, "RECMIXL Mixer"},
+       {"ADC Mixer", NULL, "RECMIXR Mixer"},
+
+       {"Left ADC", NULL, "ADC Mixer"},
+       {"Left ADC", NULL, "Left ADC Select", check_adcl_select},
+       {"Left ADC", NULL, "PLL1", check_sysclk1_source},
+       {"Left ADC", NULL, "I2S"},
+       {"Left ADC", NULL, "DAC REF"},
+
+       {"Right ADC", NULL, "ADC Mixer"},
+       {"Right ADC", NULL, "Right ADC Select", check_adcr_select},
+       {"Right ADC", NULL, "PLL1", check_sysclk1_source},
+       {"Right ADC", NULL, "I2S"},
+       {"Right ADC", NULL, "DAC REF"},
+
+       {"DMIC", NULL, "DMIC Supply", check_dmic_used},
+       {"Left ADC", NULL, "DMIC"},
+       {"Right ADC", NULL, "DMIC"},
+
+       {"Left DAC", NULL, "PLL1", check_sysclk1_source},
+       {"Left DAC", NULL, "I2S"},
+       {"Left DAC", NULL, "DAC REF"},
+       {"Right DAC", NULL, "PLL1", check_sysclk1_source},
+       {"Right DAC", NULL, "I2S"},
+       {"Right DAC", NULL, "DAC REF"},
+
+       {"Voice DAC Boost", NULL, "Voice DAC"},
+
+       {"SPKMIXL Mixer", NULL, "Left DAC To Mixer", check_dacl_to_spkmixl},
+       {"SPKMIXL Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"},
+       {"SPKMIXL Mixer", "MIC1_P Playback Switch", "MIC1"},
+       {"SPKMIXL Mixer", "DACL Playback Switch", "Left DAC"},
+       {"SPKMIXL Mixer", "OUTMIXL Playback Switch", "OUTMIXL Mixer"},
+
+       {"SPKMIXR Mixer", NULL, "Right DAC To Mixer", check_dacr_to_spkmixr},
+       {"SPKMIXR Mixer", "OUTMIXR Playback Switch", "OUTMIXR Mixer"},
+       {"SPKMIXR Mixer", "DACR Playback Switch", "Right DAC"},
+       {"SPKMIXR Mixer", "MIC2_P Playback Switch", "MIC2"},
+       {"SPKMIXR Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"},
+
+       {"OUTMIXL Mixer", NULL, "Left DAC To Mixer", check_dacl_to_outmixl},
+       {"OUTMIXL Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"},
+       {"OUTMIXL Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"},
+       {"OUTMIXL Mixer", "DACL Playback Switch", "Left DAC"},
+       {"OUTMIXL Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"},
+       {"OUTMIXL Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"},
+       {"OUTMIXL Mixer", "MONOIN_RXP Playback Switch", "MONOIN_RXP Boost"},
+       {"OUTMIXL Mixer", "AXILVOL Playback Switch", "AXIL Boost"},
+       {"OUTMIXL Mixer", "AXIRVOL Playback Switch", "AXIR Boost"},
+       {"OUTMIXL Mixer", "VDAC Playback Switch", "Voice DAC Boost"},
+
+       {"OUTMIXR Mixer", NULL, "Right DAC To Mixer", check_dacr_to_outmixr},
+       {"OUTMIXR Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"},
+       {"OUTMIXR Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"},
+       {"OUTMIXR Mixer", "DACR Playback Switch", "Right DAC"},
+       {"OUTMIXR Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"},
+       {"OUTMIXR Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"},
+       {"OUTMIXR Mixer", "MONOIN_RXN Playback Switch", "MONOIN_RXN Boost"},
+       {"OUTMIXR Mixer", "AXILVOL Playback Switch", "AXIL Boost"},
+       {"OUTMIXR Mixer", "AXIRVOL Playback Switch", "AXIR Boost"},
+       {"OUTMIXR Mixer", "VDAC Playback Switch", "Voice DAC Boost"},
+
+       {"Left SPKVOL Mux",  "SPKMIXL", "SPKMIXL Mixer"},
+       {"Left SPKVOL Mux",  "Vmid", "Vmid"},
+       {"Left HPVOL Mux",  "OUTMIXL", "OUTMIXL Mixer"},
+       {"Left HPVOL Mux",  "Vmid", "Vmid"},
+       {"Left OUTVOL Mux",  "OUTMIXL", "OUTMIXL Mixer"},
+       {"Left OUTVOL Mux",  "Vmid", "Vmid"},
+       {"Right OUTVOL Mux",  "OUTMIXR", "OUTMIXR Mixer"},
+       {"Right OUTVOL Mux",  "Vmid", "Vmid"},
+       {"Right HPVOL Mux",  "OUTMIXR", "OUTMIXR Mixer"},
+       {"Right HPVOL Mux",  "Vmid", "Vmid"},
+       {"Right SPKVOL Mux",  "SPKMIXR", "SPKMIXR Mixer"},
+       {"Right SPKVOL Mux",  "Vmid", "Vmid"},
+
+       {"AXO1MIX Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"},
+       {"AXO1MIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"},
+       {"AXO1MIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"},
+       {"AXO1MIX Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"},
+
+       {"AXO2MIX Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"},
+       {"AXO2MIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"},
+       {"AXO2MIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"},
+       {"AXO2MIX Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"},
+
+       {"SPOLMIX Mixer", "SPKVOLL Playback Switch", "Left SPKVOL Mux"},
+       {"SPOLMIX Mixer", "SPKVOLR Playback Switch", "Right SPKVOL Mux"},
+
+       {"SPORMIX Mixer", "SPKVOLL Playback Switch", "Left SPKVOL Mux"},
+       {"SPORMIX Mixer", "SPKVOLR Playback Switch", "Right SPKVOL Mux"},
+
+       {"MONOMIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"},
+       {"MONOMIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"},
+
+       {"SPOL Mux", "SPOLMIX", "SPOLMIX Mixer"},
+       {"SPOL Mux", "MONOIN_RX", "MONO_IN"},
+       {"SPOL Mux", "VDAC", "Voice DAC Boost"},
+       {"SPOL Mux", "DACL", "Left DAC"},
+
+       {"SPOR Mux", "SPORMIX", "SPORMIX Mixer"},
+       {"SPOR Mux", "MONOIN_RX", "MONO_IN"},
+       {"SPOR Mux", "VDAC", "Voice DAC Boost"},
+       {"SPOR Mux", "DACR", "Right DAC"},
+
+       {"MONO Mux", "MONOMIX", "MONOMIX Mixer"},
+       {"MONO Mux", "MONOIN_RX", "MONO_IN"},
+       {"MONO Mux", "VDAC", "Voice DAC Boost"},
+
+       {"Right DAC_HP", NULL, "Right DAC"},
+       {"Left DAC_HP", NULL, "Left DAC"},
+
+       {"HPL Mux", "Left HPVOL", "Left HPVOL Mux"},
+       {"HPL Mux", "Left DAC", "Left DAC_HP"},
+       {"HPR Mux", "Right HPVOL", "Right HPVOL Mux"},
+       {"HPR Mux", "Right DAC", "Right DAC_HP"},
+
+       {"HP Depop", NULL, "HPL Mux"},
+       {"HP Depop", NULL, "HPR Mux"},
+
+       {"AUXO1", NULL, "AXO1MIX Mixer"},
+       {"AUXO2", NULL, "AXO2MIX Mixer"},
+
+       {"SPOL", NULL, "Class D"},
+       {"SPOL", NULL, "SPOL Mux"},
+       {"SPOR", NULL, "Class D"},
+       {"SPOR", NULL, "SPOR Mux"},
+
+       {"HPOL", NULL, "HP Depop"},
+       {"HPOR", NULL, "HP Depop"},
+
+       {"MONO", NULL, "MONO Depop"},
+       {"MONO", NULL, "MONO Mux"},
+};
+
+struct coeff_clk_div {
+       u32 mclk;
+       u32 bclk;
+       u32 rate;
+       u16 reg_val;
+};
+
+/* PLL divisors */
+struct pll_div {
+       u32 pll_in;
+       u32 pll_out;
+       u16 reg_val;
+};
+
+static const struct pll_div codec_master_pll_div[] = {
+       {2048000,  8192000,  0x0ea0},
+       {3686400,  8192000,  0x4e27},
+       {12000000,  8192000,  0x456b},
+       {13000000,  8192000,  0x495f},
+       {13100000,  8192000,  0x0320},
+       {2048000,  11289600,  0xf637},
+       {3686400,  11289600,  0x2f22},
+       {12000000,  11289600,  0x3e2f},
+       {13000000,  11289600,  0x4d5b},
+       {13100000,  11289600,  0x363b},
+       {2048000,  16384000,  0x1ea0},
+       {3686400,  16384000,  0x9e27},
+       {12000000,  16384000,  0x452b},
+       {13000000,  16384000,  0x542f},
+       {13100000,  16384000,  0x03a0},
+       {2048000,  16934400,  0xe625},
+       {3686400,  16934400,  0x9126},
+       {12000000,  16934400,  0x4d2c},
+       {13000000,  16934400,  0x742f},
+       {13100000,  16934400,  0x3c27},
+       {2048000,  22579200,  0x2aa0},
+       {3686400,  22579200,  0x2f20},
+       {12000000,  22579200,  0x7e2f},
+       {13000000,  22579200,  0x742f},
+       {13100000,  22579200,  0x3c27},
+       {2048000,  24576000,  0x2ea0},
+       {3686400,  24576000,  0xee27},
+       {12000000,  24576000,  0x2915},
+       {13000000,  24576000,  0x772e},
+       {13100000,  24576000,  0x0d20},
+       {26000000,  24576000,  0x2027},
+       {26000000,  22579200,  0x392f},
+       {24576000,  22579200,  0x0921},
+       {24576000,  24576000,  0x02a0},
+};
+
+static const struct pll_div codec_slave_pll_div[] = {
+       {256000,  2048000,  0x46f0},
+       {256000,  4096000,  0x3ea0},
+       {352800,  5644800,  0x3ea0},
+       {512000,  8192000,  0x3ea0},
+       {1024000,  8192000,  0x46f0},
+       {705600,  11289600,  0x3ea0},
+       {1024000,  16384000,  0x3ea0},
+       {1411200,  22579200,  0x3ea0},
+       {1536000,  24576000,  0x3ea0},
+       {2048000,  16384000,  0x1ea0},
+       {2822400,  22579200,  0x1ea0},
+       {2822400,  45158400,  0x5ec0},
+       {5644800,  45158400,  0x46f0},
+       {3072000,  24576000,  0x1ea0},
+       {3072000,  49152000,  0x5ec0},
+       {6144000,  49152000,  0x46f0},
+       {705600,  11289600,  0x3ea0},
+       {705600,  8467200,  0x3ab0},
+       {24576000,  24576000,  0x02a0},
+       {1411200,  11289600,  0x1690},
+       {2822400,  11289600,  0x0a90},
+       {1536000,  12288000,  0x1690},
+       {3072000,  12288000,  0x0a90},
+};
+
+static struct coeff_clk_div coeff_div[] = {
+       /* sysclk is 256fs */
+       {2048000,  8000 * 32,  8000, 0x1000},
+       {2048000,  8000 * 64,  8000, 0x0000},
+       {2822400,  11025 * 32,  11025,  0x1000},
+       {2822400,  11025 * 64,  11025,  0x0000},
+       {4096000,  16000 * 32,  16000,  0x1000},
+       {4096000,  16000 * 64,  16000,  0x0000},
+       {5644800,  22050 * 32,  22050,  0x1000},
+       {5644800,  22050 * 64,  22050,  0x0000},
+       {8192000,  32000 * 32,  32000,  0x1000},
+       {8192000,  32000 * 64,  32000,  0x0000},
+       {11289600,  44100 * 32,  44100,  0x1000},
+       {11289600,  44100 * 64,  44100,  0x0000},
+       {12288000,  48000 * 32,  48000,  0x1000},
+       {12288000,  48000 * 64,  48000,  0x0000},
+       {22579200,  88200 * 32,  88200,  0x1000},
+       {22579200,  88200 * 64,  88200,  0x0000},
+       {24576000,  96000 * 32,  96000,  0x1000},
+       {24576000,  96000 * 64,  96000,  0x0000},
+       /* sysclk is 512fs */
+       {4096000,  8000 * 32,  8000, 0x3000},
+       {4096000,  8000 * 64,  8000, 0x2000},
+       {5644800,  11025 * 32,  11025, 0x3000},
+       {5644800,  11025 * 64,  11025, 0x2000},
+       {8192000,  16000 * 32,  16000, 0x3000},
+       {8192000,  16000 * 64,  16000, 0x2000},
+       {11289600,  22050 * 32,  22050, 0x3000},
+       {11289600,  22050 * 64,  22050, 0x2000},
+       {16384000,  32000 * 32,  32000, 0x3000},
+       {16384000,  32000 * 64,  32000, 0x2000},
+       {22579200,  44100 * 32,  44100, 0x3000},
+       {22579200,  44100 * 64,  44100, 0x2000},
+       {24576000,  48000 * 32,  48000, 0x3000},
+       {24576000,  48000 * 64,  48000, 0x2000},
+       {45158400,  88200 * 32,  88200, 0x3000},
+       {45158400,  88200 * 64,  88200, 0x2000},
+       {49152000,  96000 * 32,  96000, 0x3000},
+       {49152000,  96000 * 64,  96000, 0x2000},
+       /* sysclk is 24.576Mhz or 22.5792Mhz */
+       {24576000,  8000 * 32,  8000,  0x7080},
+       {24576000,  8000 * 64,  8000,  0x6080},
+       {24576000,  16000 * 32,  16000,  0x5080},
+       {24576000,  16000 * 64,  16000,  0x4080},
+       {24576000,  24000 * 32,  24000,  0x5000},
+       {24576000,  24000 * 64,  24000,  0x4000},
+       {24576000,  32000 * 32,  32000,  0x3080},
+       {24576000,  32000 * 64,  32000,  0x2080},
+       {22579200,  11025 * 32,  11025,  0x7000},
+       {22579200,  11025 * 64,  11025,  0x6000},
+       {22579200,  22050 * 32,  22050,  0x5000},
+       {22579200,  22050 * 64,  22050,  0x4000},
+};
+
+static int get_coeff(int mclk, int rate, int timesofbclk)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
+               if (coeff_div[i].mclk == mclk && coeff_div[i].rate == rate &&
+                       (coeff_div[i].bclk / coeff_div[i].rate) == timesofbclk)
+                       return i;
+       }
+       return -EINVAL;
+}
+
+static int rt5631_hifi_pcm_params(struct snd_pcm_substream *substream,
+               struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_codec *codec = rtd->codec;
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+       int timesofbclk = 32, coeff;
+       unsigned int iface = 0;
+
+       dev_dbg(codec->dev, "enter %s\n", __func__);
+
+       rt5631->bclk_rate = snd_soc_params_to_bclk(params);
+       if (rt5631->bclk_rate < 0) {
+               dev_err(codec->dev, "Fail to get BCLK rate\n");
+               return rt5631->bclk_rate;
+       }
+       rt5631->rx_rate = params_rate(params);
+
+       if (rt5631->master)
+               coeff = get_coeff(rt5631->sysclk, rt5631->rx_rate,
+                       rt5631->bclk_rate / rt5631->rx_rate);
+       else
+               coeff = get_coeff(rt5631->sysclk, rt5631->rx_rate,
+                                       timesofbclk);
+       if (coeff < 0) {
+               dev_err(codec->dev, "Fail to get coeff\n");
+               return -EINVAL;
+       }
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               iface |= RT5631_SDP_I2S_DL_20;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               iface |= RT5631_SDP_I2S_DL_24;
+               break;
+       case SNDRV_PCM_FORMAT_S8:
+               iface |= RT5631_SDP_I2S_DL_8;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, RT5631_SDP_CTRL,
+               RT5631_SDP_I2S_DL_MASK, iface);
+       snd_soc_write(codec, RT5631_STEREO_AD_DA_CLK_CTRL,
+                                       coeff_div[coeff].reg_val);
+
+       return 0;
+}
+
+static int rt5631_hifi_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
+                                               unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+       unsigned int iface = 0;
+
+       dev_dbg(codec->dev, "enter %s\n", __func__);
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               rt5631->master = 1;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               iface |= RT5631_SDP_MODE_SEL_SLAVE;
+               rt5631->master = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               iface |= RT5631_SDP_I2S_DF_LEFT;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               iface |= RT5631_SDP_I2S_DF_PCM_A;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               iface  |= RT5631_SDP_I2S_DF_PCM_B;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               iface |= RT5631_SDP_I2S_BCLK_POL_CTRL;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_write(codec, RT5631_SDP_CTRL, iface);
+
+       return 0;
+}
+
+static int rt5631_hifi_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+                               int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+       dev_dbg(codec->dev, "enter %s, syclk=%d\n", __func__, freq);
+
+       if ((freq >= (256 * 8000)) && (freq <= (512 * 96000))) {
+               rt5631->sysclk = freq;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static int rt5631_codec_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
+               int source, unsigned int freq_in, unsigned int freq_out)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+       int i, ret = -EINVAL;
+
+       dev_dbg(codec->dev, "enter %s\n", __func__);
+
+       if (!freq_in || !freq_out) {
+               dev_dbg(codec->dev, "PLL disabled\n");
+
+               snd_soc_update_bits(codec, RT5631_GLOBAL_CLK_CTRL,
+                       RT5631_SYSCLK_SOUR_SEL_MASK,
+                       RT5631_SYSCLK_SOUR_SEL_MCLK);
+
+               return 0;
+       }
+
+       if (rt5631->master) {
+               for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++)
+                       if (freq_in == codec_master_pll_div[i].pll_in &&
+                       freq_out == codec_master_pll_div[i].pll_out) {
+                               dev_info(codec->dev,
+                                       "change PLL in master mode\n");
+                               snd_soc_write(codec, RT5631_PLL_CTRL,
+                                       codec_master_pll_div[i].reg_val);
+                               schedule_timeout_uninterruptible(
+                                       msecs_to_jiffies(20));
+                               snd_soc_update_bits(codec,
+                                       RT5631_GLOBAL_CLK_CTRL,
+                                       RT5631_SYSCLK_SOUR_SEL_MASK |
+                                       RT5631_PLLCLK_SOUR_SEL_MASK,
+                                       RT5631_SYSCLK_SOUR_SEL_PLL |
+                                       RT5631_PLLCLK_SOUR_SEL_MCLK);
+                               ret = 0;
+                               break;
+                       }
+       } else {
+               for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++)
+                       if (freq_in == codec_slave_pll_div[i].pll_in &&
+                       freq_out == codec_slave_pll_div[i].pll_out) {
+                               dev_info(codec->dev,
+                                       "change PLL in slave mode\n");
+                               snd_soc_write(codec, RT5631_PLL_CTRL,
+                                       codec_slave_pll_div[i].reg_val);
+                               schedule_timeout_uninterruptible(
+                                       msecs_to_jiffies(20));
+                               snd_soc_update_bits(codec,
+                                       RT5631_GLOBAL_CLK_CTRL,
+                                       RT5631_SYSCLK_SOUR_SEL_MASK |
+                                       RT5631_PLLCLK_SOUR_SEL_MASK,
+                                       RT5631_SYSCLK_SOUR_SEL_PLL |
+                                       RT5631_PLLCLK_SOUR_SEL_BCLK);
+                               ret = 0;
+                               break;
+                       }
+       }
+
+       return ret;
+}
+
+static int rt5631_set_bias_level(struct snd_soc_codec *codec,
+                       enum snd_soc_bias_level level)
+{
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+       case SND_SOC_BIAS_PREPARE:
+               snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD2,
+                       RT5631_PWR_MICBIAS1_VOL | RT5631_PWR_MICBIAS2_VOL,
+                       RT5631_PWR_MICBIAS1_VOL | RT5631_PWR_MICBIAS2_VOL);
+               break;
+
+       case SND_SOC_BIAS_STANDBY:
+               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+                               RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS,
+                               RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS);
+                       msleep(80);
+                       snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+                               RT5631_PWR_FAST_VREF_CTRL,
+                               RT5631_PWR_FAST_VREF_CTRL);
+                       codec->cache_only = false;
+                       snd_soc_cache_sync(codec);
+               }
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               snd_soc_write(codec, RT5631_PWR_MANAG_ADD1, 0x0000);
+               snd_soc_write(codec, RT5631_PWR_MANAG_ADD2, 0x0000);
+               snd_soc_write(codec, RT5631_PWR_MANAG_ADD3, 0x0000);
+               snd_soc_write(codec, RT5631_PWR_MANAG_ADD4, 0x0000);
+               break;
+
+       default:
+               break;
+       }
+       codec->dapm.bias_level = level;
+
+       return 0;
+}
+
+static int rt5631_probe(struct snd_soc_codec *codec)
+{
+       struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+       unsigned int val;
+       int ret;
+
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
+
+       val = rt5631_read_index(codec, RT5631_ADDA_MIXER_INTL_REG3);
+       if (val & 0x0002)
+               rt5631->codec_version = 1;
+       else
+               rt5631->codec_version = 0;
+
+       rt5631_reset(codec);
+       snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+               RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS,
+               RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS);
+       msleep(80);
+       snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+               RT5631_PWR_FAST_VREF_CTRL, RT5631_PWR_FAST_VREF_CTRL);
+       /* enable HP zero cross */
+       snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, 0x0f18);
+       /* power off ClassD auto Recovery */
+       if (rt5631->codec_version)
+               snd_soc_update_bits(codec, RT5631_INT_ST_IRQ_CTRL_2,
+                                       0x2000, 0x2000);
+       else
+               snd_soc_update_bits(codec, RT5631_INT_ST_IRQ_CTRL_2,
+                                       0x2000, 0);
+       /* DMIC */
+       if (rt5631->dmic_used_flag) {
+               snd_soc_update_bits(codec, RT5631_GPIO_CTRL,
+                       RT5631_GPIO_PIN_FUN_SEL_MASK |
+                       RT5631_GPIO_DMIC_FUN_SEL_MASK,
+                       RT5631_GPIO_PIN_FUN_SEL_GPIO_DIMC |
+                       RT5631_GPIO_DMIC_FUN_SEL_DIMC);
+               snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL,
+                       RT5631_DMIC_L_CH_LATCH_MASK |
+                       RT5631_DMIC_R_CH_LATCH_MASK,
+                       RT5631_DMIC_L_CH_LATCH_FALLING |
+                       RT5631_DMIC_R_CH_LATCH_RISING);
+       }
+
+       codec->dapm.bias_level = SND_SOC_BIAS_STANDBY;
+
+       return 0;
+}
+
+static int rt5631_remove(struct snd_soc_codec *codec)
+{
+       rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int rt5631_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+       rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static int rt5631_resume(struct snd_soc_codec *codec)
+{
+       rt5631_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       return 0;
+}
+#else
+#define rt5631_suspend NULL
+#define rt5631_resume NULL
+#endif
+
+#define RT5631_STEREO_RATES SNDRV_PCM_RATE_8000_96000
+#define RT5631_FORMAT  (SNDRV_PCM_FMTBIT_S16_LE | \
+                       SNDRV_PCM_FMTBIT_S20_3LE | \
+                       SNDRV_PCM_FMTBIT_S24_LE | \
+                       SNDRV_PCM_FMTBIT_S8)
+
+static struct snd_soc_dai_ops rt5631_ops = {
+       .hw_params = rt5631_hifi_pcm_params,
+       .set_fmt = rt5631_hifi_codec_set_dai_fmt,
+       .set_sysclk = rt5631_hifi_codec_set_dai_sysclk,
+       .set_pll = rt5631_codec_set_dai_pll,
+};
+
+static struct snd_soc_dai_driver rt5631_dai[] = {
+       {
+               .name = "rt5631-hifi",
+               .id = 1,
+               .playback = {
+                       .stream_name = "HIFI Playback",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = RT5631_STEREO_RATES,
+                       .formats = RT5631_FORMAT,
+               },
+               .capture = {
+                       .stream_name = "HIFI Capture",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = RT5631_STEREO_RATES,
+                       .formats = RT5631_FORMAT,
+               },
+               .ops = &rt5631_ops,
+       },
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_rt5631 = {
+       .probe = rt5631_probe,
+       .remove = rt5631_remove,
+       .suspend = rt5631_suspend,
+       .resume = rt5631_resume,
+       .set_bias_level = rt5631_set_bias_level,
+       .reg_cache_size = RT5631_VENDOR_ID2 + 1,
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = rt5631_reg,
+       .volatile_register = rt5631_volatile_register,
+       .readable_register = rt5631_readable_register,
+       .reg_cache_step = 1,
+       .controls = rt5631_snd_controls,
+       .num_controls = ARRAY_SIZE(rt5631_snd_controls),
+       .dapm_widgets = rt5631_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(rt5631_dapm_widgets),
+       .dapm_routes = rt5631_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(rt5631_dapm_routes),
+};
+
+static const struct i2c_device_id rt5631_i2c_id[] = {
+       { "rt5631", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id);
+
+static int rt5631_i2c_probe(struct i2c_client *i2c,
+                   const struct i2c_device_id *id)
+{
+       struct rt5631_priv *rt5631;
+       int ret;
+
+       rt5631 = kzalloc(sizeof(struct rt5631_priv), GFP_KERNEL);
+       if (NULL == rt5631)
+               return -ENOMEM;
+
+       i2c_set_clientdata(i2c, rt5631);
+
+       ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5631,
+                       rt5631_dai, ARRAY_SIZE(rt5631_dai));
+       if (ret < 0)
+               kfree(rt5631);
+
+       return ret;
+}
+
+static __devexit int rt5631_i2c_remove(struct i2c_client *client)
+{
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
+       return 0;
+}
+
+static struct i2c_driver rt5631_i2c_driver = {
+       .driver = {
+               .name = "rt5631",
+               .owner = THIS_MODULE,
+       },
+       .probe = rt5631_i2c_probe,
+       .remove   = __devexit_p(rt5631_i2c_remove),
+       .id_table = rt5631_i2c_id,
+};
+
+static int __init rt5631_modinit(void)
+{
+       return i2c_add_driver(&rt5631_i2c_driver);
+}
+module_init(rt5631_modinit);
+
+static void __exit rt5631_modexit(void)
+{
+       i2c_del_driver(&rt5631_i2c_driver);
+}
+module_exit(rt5631_modexit);
+
+MODULE_DESCRIPTION("ASoC RT5631 driver");
+MODULE_AUTHOR("flove <flove@realtek.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/rt5631.h b/sound/soc/codecs/rt5631.h
new file mode 100644 (file)
index 0000000..1340158
--- /dev/null
@@ -0,0 +1,701 @@
+#ifndef __RTCODEC5631_H__
+#define __RTCODEC5631_H__
+
+
+#define RT5631_RESET                           0x00
+#define RT5631_SPK_OUT_VOL                     0x02
+#define RT5631_HP_OUT_VOL                      0x04
+#define RT5631_MONO_AXO_1_2_VOL                0x06
+#define RT5631_AUX_IN_VOL                      0x0A
+#define RT5631_STEREO_DAC_VOL_1                0x0C
+#define RT5631_MIC_CTRL_1                      0x0E
+#define RT5631_STEREO_DAC_VOL_2                0x10
+#define RT5631_ADC_CTRL_1                      0x12
+#define RT5631_ADC_REC_MIXER                   0x14
+#define RT5631_ADC_CTRL_2                      0x16
+#define RT5631_VDAC_DIG_VOL                    0x18
+#define RT5631_OUTMIXER_L_CTRL                 0x1A
+#define RT5631_OUTMIXER_R_CTRL                 0x1C
+#define RT5631_AXO1MIXER_CTRL                  0x1E
+#define RT5631_AXO2MIXER_CTRL                  0x20
+#define RT5631_MIC_CTRL_2                      0x22
+#define RT5631_DIG_MIC_CTRL                    0x24
+#define RT5631_MONO_INPUT_VOL                  0x26
+#define RT5631_SPK_MIXER_CTRL                  0x28
+#define RT5631_SPK_MONO_OUT_CTRL               0x2A
+#define RT5631_SPK_MONO_HP_OUT_CTRL            0x2C
+#define RT5631_SDP_CTRL                                0x34
+#define RT5631_MONO_SDP_CTRL                   0x36
+#define RT5631_STEREO_AD_DA_CLK_CTRL           0x38
+#define RT5631_PWR_MANAG_ADD1          0x3A
+#define RT5631_PWR_MANAG_ADD2          0x3B
+#define RT5631_PWR_MANAG_ADD3          0x3C
+#define RT5631_PWR_MANAG_ADD4          0x3E
+#define RT5631_GEN_PUR_CTRL_REG                0x40
+#define RT5631_GLOBAL_CLK_CTRL                 0x42
+#define RT5631_PLL_CTRL                                0x44
+#define RT5631_INT_ST_IRQ_CTRL_1               0x48
+#define RT5631_INT_ST_IRQ_CTRL_2               0x4A
+#define RT5631_GPIO_CTRL                       0x4C
+#define RT5631_MISC_CTRL                       0x52
+#define RT5631_DEPOP_FUN_CTRL_1                0x54
+#define RT5631_DEPOP_FUN_CTRL_2                0x56
+#define RT5631_JACK_DET_CTRL                   0x5A
+#define RT5631_SOFT_VOL_CTRL                   0x5C
+#define RT5631_ALC_CTRL_1                      0x64
+#define RT5631_ALC_CTRL_2                      0x65
+#define RT5631_ALC_CTRL_3                      0x66
+#define RT5631_PSEUDO_SPATL_CTRL               0x68
+#define RT5631_INDEX_ADD                       0x6A
+#define RT5631_INDEX_DATA                      0x6C
+#define RT5631_EQ_CTRL                         0x6E
+#define RT5631_VENDOR_ID                       0x7A
+#define RT5631_VENDOR_ID1                      0x7C
+#define RT5631_VENDOR_ID2                      0x7E
+
+/* Index of Codec Private Register definition */
+#define RT5631_EQ_BW_LOP                       0x00
+#define RT5631_EQ_GAIN_LOP                     0x01
+#define RT5631_EQ_FC_BP1                       0x02
+#define RT5631_EQ_BW_BP1                       0x03
+#define RT5631_EQ_GAIN_BP1                     0x04
+#define RT5631_EQ_FC_BP2                       0x05
+#define RT5631_EQ_BW_BP2                       0x06
+#define RT5631_EQ_GAIN_BP2                     0x07
+#define RT5631_EQ_FC_BP3                       0x08
+#define RT5631_EQ_BW_BP3                       0x09
+#define RT5631_EQ_GAIN_BP3                     0x0a
+#define RT5631_EQ_BW_HIP                       0x0b
+#define RT5631_EQ_GAIN_HIP                     0x0c
+#define RT5631_EQ_HPF_A1                       0x0d
+#define RT5631_EQ_HPF_A2                       0x0e
+#define RT5631_EQ_HPF_GAIN                     0x0f
+#define RT5631_EQ_PRE_VOL_CTRL                 0x11
+#define RT5631_EQ_POST_VOL_CTRL                0x12
+#define RT5631_TEST_MODE_CTRL                  0x39
+#define RT5631_CP_INTL_REG2                    0x45
+#define RT5631_ADDA_MIXER_INTL_REG3            0x52
+#define RT5631_SPK_INTL_CTRL                   0x56
+
+
+/* global definition */
+#define RT5631_L_MUTE                                  (0x1 << 15)
+#define RT5631_L_MUTE_SHIFT                            15
+#define RT5631_L_EN                                    (0x1 << 14)
+#define RT5631_L_EN_SHIFT                              14
+#define RT5631_R_MUTE                                  (0x1 << 7)
+#define RT5631_R_MUTE_SHIFT                            7
+#define RT5631_R_EN                                    (0x1 << 6)
+#define RT5631_R_EN_SHIFT                              6
+#define RT5631_VOL_MASK                                0x1f
+#define RT5631_L_VOL_SHIFT                             8
+#define RT5631_R_VOL_SHIFT                             0
+
+/* Speaker Output Control(0x02) */
+#define RT5631_SPK_L_VOL_SEL_MASK                      (0x1 << 14)
+#define RT5631_SPK_L_VOL_SEL_VMID                      (0x0 << 14)
+#define RT5631_SPK_L_VOL_SEL_SPKMIX_L                  (0x1 << 14)
+#define RT5631_SPK_R_VOL_SEL_MASK                      (0x1 << 6)
+#define RT5631_SPK_R_VOL_SEL_VMID                      (0x0 << 6)
+#define RT5631_SPK_R_VOL_SEL_SPKMIX_R                  (0x1 << 6)
+
+/* Headphone Output Control(0x04) */
+#define RT5631_HP_L_VOL_SEL_MASK                       (0x1 << 14)
+#define RT5631_HP_L_VOL_SEL_VMID                       (0x0 << 14)
+#define RT5631_HP_L_VOL_SEL_OUTMIX_L                   (0x1 << 14)
+#define RT5631_HP_R_VOL_SEL_MASK                       (0x1 << 6)
+#define RT5631_HP_R_VOL_SEL_VMID                       (0x0 << 6)
+#define RT5631_HP_R_VOL_SEL_OUTMIX_R                   (0x1 << 6)
+
+/* Output Control for AUXOUT/MONO(0x06) */
+#define RT5631_AUXOUT_1_VOL_SEL_MASK                   (0x1 << 14)
+#define RT5631_AUXOUT_1_VOL_SEL_VMID                   (0x0 << 14)
+#define RT5631_AUXOUT_1_VOL_SEL_OUTMIX_L               (0x1 << 14)
+#define RT5631_MUTE_MONO                               (0x1 << 13)
+#define RT5631_MUTE_MONO_SHIFT                 13
+#define RT5631_AUXOUT_2_VOL_SEL_MASK                   (0x1 << 6)
+#define RT5631_AUXOUT_2_VOL_SEL_VMID                   (0x0 << 6)
+#define RT5631_AUXOUT_2_VOL_SEL_OUTMIX_R               (0x1 << 6)
+
+/* Microphone Input Control 1(0x0E) */
+#define RT5631_MIC1_DIFF_INPUT_CTRL                    (0x1 << 15)
+#define RT5631_MIC1_DIFF_INPUT_SHIFT                   15
+#define RT5631_MIC2_DIFF_INPUT_CTRL                    (0x1 << 7)
+#define RT5631_MIC2_DIFF_INPUT_SHIFT                   7
+
+/* Stereo DAC Digital Volume2(0x10) */
+#define RT5631_DAC_VOL_MASK                            0xff
+
+/* ADC Recording Mixer Control(0x14) */
+#define RT5631_M_OUTMIXER_L_TO_RECMIXER_L              (0x1 << 15)
+#define RT5631_M_OUTMIXL_RECMIXL_BIT                   15
+#define RT5631_M_MIC1_TO_RECMIXER_L                    (0x1 << 14)
+#define RT5631_M_MIC1_RECMIXL_BIT                      14
+#define RT5631_M_AXIL_TO_RECMIXER_L                    (0x1 << 13)
+#define RT5631_M_AXIL_RECMIXL_BIT                      13
+#define RT5631_M_MONO_IN_TO_RECMIXER_L         (0x1 << 12)
+#define RT5631_M_MONO_IN_RECMIXL_BIT                   12
+#define RT5631_M_OUTMIXER_R_TO_RECMIXER_R              (0x1 << 7)
+#define RT5631_M_OUTMIXR_RECMIXR_BIT                   7
+#define RT5631_M_MIC2_TO_RECMIXER_R                    (0x1 << 6)
+#define RT5631_M_MIC2_RECMIXR_BIT                      6
+#define RT5631_M_AXIR_TO_RECMIXER_R                    (0x1 << 5)
+#define RT5631_M_AXIR_RECMIXR_BIT                      5
+#define RT5631_M_MONO_IN_TO_RECMIXER_R         (0x1 << 4)
+#define RT5631_M_MONO_IN_RECMIXR_BIT                   4
+
+/* Left Output Mixer Control(0x1A) */
+#define RT5631_M_RECMIXER_L_TO_OUTMIXER_L              (0x1 << 15)
+#define RT5631_M_RECMIXL_OUTMIXL_BIT                   15
+#define RT5631_M_RECMIXER_R_TO_OUTMIXER_L              (0x1 << 14)
+#define RT5631_M_RECMIXR_OUTMIXL_BIT                   14
+#define RT5631_M_DAC_L_TO_OUTMIXER_L                   (0x1 << 13)
+#define RT5631_M_DACL_OUTMIXL_BIT                      13
+#define RT5631_M_MIC1_TO_OUTMIXER_L                    (0x1 << 12)
+#define RT5631_M_MIC1_OUTMIXL_BIT                      12
+#define RT5631_M_MIC2_TO_OUTMIXER_L                    (0x1 << 11)
+#define RT5631_M_MIC2_OUTMIXL_BIT                      11
+#define RT5631_M_MONO_IN_P_TO_OUTMIXER_L               (0x1 << 10)
+#define RT5631_M_MONO_INP_OUTMIXL_BIT          10
+#define RT5631_M_AXIL_TO_OUTMIXER_L                    (0x1 << 9)
+#define RT5631_M_AXIL_OUTMIXL_BIT                      9
+#define RT5631_M_AXIR_TO_OUTMIXER_L                    (0x1 << 8)
+#define RT5631_M_AXIR_OUTMIXL_BIT                      8
+#define RT5631_M_VDAC_TO_OUTMIXER_L                    (0x1 << 7)
+#define RT5631_M_VDAC_OUTMIXL_BIT                      7
+
+/* Right Output Mixer Control(0x1C) */
+#define RT5631_M_RECMIXER_L_TO_OUTMIXER_R              (0x1 << 15)
+#define RT5631_M_RECMIXL_OUTMIXR_BIT                   15
+#define RT5631_M_RECMIXER_R_TO_OUTMIXER_R              (0x1 << 14)
+#define RT5631_M_RECMIXR_OUTMIXR_BIT                   14
+#define RT5631_M_DAC_R_TO_OUTMIXER_R                   (0x1 << 13)
+#define RT5631_M_DACR_OUTMIXR_BIT                      13
+#define RT5631_M_MIC1_TO_OUTMIXER_R                    (0x1 << 12)
+#define RT5631_M_MIC1_OUTMIXR_BIT                      12
+#define RT5631_M_MIC2_TO_OUTMIXER_R                    (0x1 << 11)
+#define RT5631_M_MIC2_OUTMIXR_BIT                      11
+#define RT5631_M_MONO_IN_N_TO_OUTMIXER_R               (0x1 << 10)
+#define RT5631_M_MONO_INN_OUTMIXR_BIT          10
+#define RT5631_M_AXIL_TO_OUTMIXER_R                    (0x1 << 9)
+#define RT5631_M_AXIL_OUTMIXR_BIT                      9
+#define RT5631_M_AXIR_TO_OUTMIXER_R                    (0x1 << 8)
+#define RT5631_M_AXIR_OUTMIXR_BIT                      8
+#define RT5631_M_VDAC_TO_OUTMIXER_R                    (0x1 << 7)
+#define RT5631_M_VDAC_OUTMIXR_BIT                      7
+
+/* Lout Mixer Control(0x1E) */
+#define RT5631_M_MIC1_TO_AXO1MIXER                     (0x1 << 15)
+#define RT5631_M_MIC1_AXO1MIX_BIT                      15
+#define RT5631_M_MIC2_TO_AXO1MIXER                     (0x1 << 11)
+#define RT5631_M_MIC2_AXO1MIX_BIT                      11
+#define RT5631_M_OUTMIXER_L_TO_AXO1MIXER               (0x1 << 7)
+#define RT5631_M_OUTMIXL_AXO1MIX_BIT                   7
+#define RT5631_M_OUTMIXER_R_TO_AXO1MIXER               (0x1 << 6)
+#define RT5631_M_OUTMIXR_AXO1MIX_BIT                   6
+
+/* Rout Mixer Control(0x20) */
+#define RT5631_M_MIC1_TO_AXO2MIXER                     (0x1 << 15)
+#define RT5631_M_MIC1_AXO2MIX_BIT                      15
+#define RT5631_M_MIC2_TO_AXO2MIXER                     (0x1 << 11)
+#define RT5631_M_MIC2_AXO2MIX_BIT                      11
+#define RT5631_M_OUTMIXER_L_TO_AXO2MIXER               (0x1 << 7)
+#define RT5631_M_OUTMIXL_AXO2MIX_BIT                   7
+#define RT5631_M_OUTMIXER_R_TO_AXO2MIXER               (0x1 << 6)
+#define RT5631_M_OUTMIXR_AXO2MIX_BIT                   6
+
+/* Micphone Input Control 2(0x22) */
+#define RT5631_MIC_BIAS_90_PRECNET_AVDD 1
+#define RT5631_MIC_BIAS_75_PRECNET_AVDD 2
+
+#define RT5631_MIC1_BOOST_CTRL_MASK                    (0xf << 12)
+#define RT5631_MIC1_BOOST_CTRL_BYPASS          (0x0 << 12)
+#define RT5631_MIC1_BOOST_CTRL_20DB                    (0x1 << 12)
+#define RT5631_MIC1_BOOST_CTRL_24DB                    (0x2 << 12)
+#define RT5631_MIC1_BOOST_CTRL_30DB                    (0x3 << 12)
+#define RT5631_MIC1_BOOST_CTRL_35DB                    (0x4 << 12)
+#define RT5631_MIC1_BOOST_CTRL_40DB                    (0x5 << 12)
+#define RT5631_MIC1_BOOST_CTRL_34DB                    (0x6 << 12)
+#define RT5631_MIC1_BOOST_CTRL_50DB                    (0x7 << 12)
+#define RT5631_MIC1_BOOST_CTRL_52DB                    (0x8 << 12)
+#define RT5631_MIC1_BOOST_SHIFT                        12
+
+#define RT5631_MIC2_BOOST_CTRL_MASK                    (0xf << 8)
+#define RT5631_MIC2_BOOST_CTRL_BYPASS          (0x0 << 8)
+#define RT5631_MIC2_BOOST_CTRL_20DB                    (0x1 << 8)
+#define RT5631_MIC2_BOOST_CTRL_24DB                    (0x2 << 8)
+#define RT5631_MIC2_BOOST_CTRL_30DB                    (0x3 << 8)
+#define RT5631_MIC2_BOOST_CTRL_35DB                    (0x4 << 8)
+#define RT5631_MIC2_BOOST_CTRL_40DB                    (0x5 << 8)
+#define RT5631_MIC2_BOOST_CTRL_34DB                    (0x6 << 8)
+#define RT5631_MIC2_BOOST_CTRL_50DB                    (0x7 << 8)
+#define RT5631_MIC2_BOOST_CTRL_52DB                    (0x8 << 8)
+#define RT5631_MIC2_BOOST_SHIFT                        8
+
+#define RT5631_MICBIAS1_VOLT_CTRL_MASK         (0x1 << 7)
+#define RT5631_MICBIAS1_VOLT_CTRL_90P                  (0x0 << 7)
+#define RT5631_MICBIAS1_VOLT_CTRL_75P                  (0x1 << 7)
+
+#define RT5631_MICBIAS1_S_C_DET_MASK                   (0x1 << 6)
+#define RT5631_MICBIAS1_S_C_DET_DIS                    (0x0 << 6)
+#define RT5631_MICBIAS1_S_C_DET_ENA                    (0x1 << 6)
+
+#define RT5631_MICBIAS1_SHORT_CURR_DET_MASK            (0x3 << 4)
+#define RT5631_MICBIAS1_SHORT_CURR_DET_600UA   (0x0 << 4)
+#define RT5631_MICBIAS1_SHORT_CURR_DET_1500UA  (0x1 << 4)
+#define RT5631_MICBIAS1_SHORT_CURR_DET_2000UA  (0x2 << 4)
+
+#define RT5631_MICBIAS2_VOLT_CTRL_MASK         (0x1 << 3)
+#define RT5631_MICBIAS2_VOLT_CTRL_90P                  (0x0 << 3)
+#define RT5631_MICBIAS2_VOLT_CTRL_75P                  (0x1 << 3)
+
+#define RT5631_MICBIAS2_S_C_DET_MASK                   (0x1 << 2)
+#define RT5631_MICBIAS2_S_C_DET_DIS                    (0x0 << 2)
+#define RT5631_MICBIAS2_S_C_DET_ENA                    (0x1 << 2)
+
+#define RT5631_MICBIAS2_SHORT_CURR_DET_MASK            (0x3)
+#define RT5631_MICBIAS2_SHORT_CURR_DET_600UA   (0x0)
+#define RT5631_MICBIAS2_SHORT_CURR_DET_1500UA  (0x1)
+#define RT5631_MICBIAS2_SHORT_CURR_DET_2000UA  (0x2)
+
+
+/* Digital Microphone Control(0x24) */
+#define RT5631_DMIC_ENA_MASK                           (0x1 << 15)
+#define RT5631_DMIC_ENA_SHIFT                          15
+/* DMIC_ENA: DMIC to ADC Digital filter */
+#define RT5631_DMIC_ENA                                (0x1 << 15)
+/* DMIC_DIS: ADC mixer to ADC Digital filter */
+#define RT5631_DMIC_DIS                                        (0x0 << 15)
+#define RT5631_DMIC_L_CH_MUTE                          (0x1 << 13)
+#define RT5631_DMIC_L_CH_MUTE_SHIFT                    13
+#define RT5631_DMIC_R_CH_MUTE                          (0x1 << 12)
+#define RT5631_DMIC_R_CH_MUTE_SHIFT                    12
+#define RT5631_DMIC_L_CH_LATCH_MASK                    (0x1 << 9)
+#define RT5631_DMIC_L_CH_LATCH_RISING                  (0x1 << 9)
+#define RT5631_DMIC_L_CH_LATCH_FALLING         (0x0 << 9)
+#define RT5631_DMIC_R_CH_LATCH_MASK                    (0x1 << 8)
+#define RT5631_DMIC_R_CH_LATCH_RISING                  (0x1 << 8)
+#define RT5631_DMIC_R_CH_LATCH_FALLING         (0x0 << 8)
+#define RT5631_DMIC_CLK_CTRL_MASK                      (0x3 << 4)
+#define RT5631_DMIC_CLK_CTRL_TO_128FS                  (0x0 << 4)
+#define RT5631_DMIC_CLK_CTRL_TO_64FS                   (0x1 << 4)
+#define RT5631_DMIC_CLK_CTRL_TO_32FS                   (0x2 << 4)
+
+/* Microphone Input Volume(0x26) */
+#define RT5631_MONO_DIFF_INPUT_SHIFT                   15
+
+/* Speaker Mixer Control(0x28) */
+#define RT5631_M_RECMIXER_L_TO_SPKMIXER_L              (0x1 << 15)
+#define RT5631_M_RECMIXL_SPKMIXL_BIT                   15
+#define RT5631_M_MIC1_P_TO_SPKMIXER_L          (0x1 << 14)
+#define RT5631_M_MIC1P_SPKMIXL_BIT                     14
+#define RT5631_M_DAC_L_TO_SPKMIXER_L                   (0x1 << 13)
+#define RT5631_M_DACL_SPKMIXL_BIT                      13
+#define RT5631_M_OUTMIXER_L_TO_SPKMIXER_L              (0x1 << 12)
+#define RT5631_M_OUTMIXL_SPKMIXL_BIT                   12
+
+#define RT5631_M_RECMIXER_R_TO_SPKMIXER_R              (0x1 << 7)
+#define RT5631_M_RECMIXR_SPKMIXR_BIT                   7
+#define RT5631_M_MIC2_P_TO_SPKMIXER_R          (0x1 << 6)
+#define RT5631_M_MIC2P_SPKMIXR_BIT                     6
+#define RT5631_M_DAC_R_TO_SPKMIXER_R                   (0x1 << 5)
+#define RT5631_M_DACR_SPKMIXR_BIT                      5
+#define RT5631_M_OUTMIXER_R_TO_SPKMIXER_R              (0x1 << 4)
+#define RT5631_M_OUTMIXR_SPKMIXR_BIT                   4
+
+/* Speaker/Mono Output Control(0x2A) */
+#define RT5631_M_SPKVOL_L_TO_SPOL_MIXER                (0x1 << 15)
+#define RT5631_M_SPKVOLL_SPOLMIX_BIT                   15
+#define RT5631_M_SPKVOL_R_TO_SPOL_MIXER                (0x1 << 14)
+#define RT5631_M_SPKVOLR_SPOLMIX_BIT                   14
+#define RT5631_M_SPKVOL_L_TO_SPOR_MIXER                (0x1 << 13)
+#define RT5631_M_SPKVOLL_SPORMIX_BIT                   13
+#define RT5631_M_SPKVOL_R_TO_SPOR_MIXER                (0x1 << 12)
+#define RT5631_M_SPKVOLR_SPORMIX_BIT                   12
+#define RT5631_M_OUTVOL_L_TO_MONOMIXER         (0x1 << 11)
+#define RT5631_M_OUTVOLL_MONOMIX_BIT                   11
+#define RT5631_M_OUTVOL_R_TO_MONOMIXER         (0x1 << 10)
+#define RT5631_M_OUTVOLR_MONOMIX_BIT                   10
+
+/* Speaker/Mono/HP Output Control(0x2C) */
+#define RT5631_SPK_L_MUX_SEL_MASK                      (0x3 << 14)
+#define RT5631_SPK_L_MUX_SEL_SPKMIXER_L                (0x0 << 14)
+#define RT5631_SPK_L_MUX_SEL_MONO_IN                   (0x1 << 14)
+#define RT5631_SPK_L_MUX_SEL_DAC_L                     (0x3 << 14)
+#define RT5631_SPK_L_MUX_SEL_SHIFT                     14
+
+#define RT5631_SPK_R_MUX_SEL_MASK                      (0x3 << 10)
+#define RT5631_SPK_R_MUX_SEL_SPKMIXER_R                (0x0 << 10)
+#define RT5631_SPK_R_MUX_SEL_MONO_IN                   (0x1 << 10)
+#define RT5631_SPK_R_MUX_SEL_DAC_R                     (0x3 << 10)
+#define RT5631_SPK_R_MUX_SEL_SHIFT                     10
+
+#define RT5631_MONO_MUX_SEL_MASK                       (0x3 << 6)
+#define RT5631_MONO_MUX_SEL_MONOMIXER          (0x0 << 6)
+#define RT5631_MONO_MUX_SEL_MONO_IN                    (0x1 << 6)
+#define RT5631_MONO_MUX_SEL_SHIFT                      6
+
+#define RT5631_HP_L_MUX_SEL_MASK                       (0x1 << 3)
+#define RT5631_HP_L_MUX_SEL_HPVOL_L                    (0x0 << 3)
+#define RT5631_HP_L_MUX_SEL_DAC_L                      (0x1 << 3)
+#define RT5631_HP_L_MUX_SEL_SHIFT                      3
+
+#define RT5631_HP_R_MUX_SEL_MASK                       (0x1 << 2)
+#define RT5631_HP_R_MUX_SEL_HPVOL_R                    (0x0 << 2)
+#define RT5631_HP_R_MUX_SEL_DAC_R                      (0x1 << 2)
+#define RT5631_HP_R_MUX_SEL_SHIFT                      2
+
+/* Stereo I2S Serial Data Port Control(0x34) */
+#define RT5631_SDP_MODE_SEL_MASK                       (0x1 << 15)
+#define RT5631_SDP_MODE_SEL_MASTER                     (0x0 << 15)
+#define RT5631_SDP_MODE_SEL_SLAVE                      (0x1 << 15)
+
+#define RT5631_SDP_ADC_CPS_SEL_MASK                    (0x3 << 10)
+#define RT5631_SDP_ADC_CPS_SEL_OFF                     (0x0 << 10)
+#define RT5631_SDP_ADC_CPS_SEL_U_LAW                   (0x1 << 10)
+#define RT5631_SDP_ADC_CPS_SEL_A_LAW                   (0x2 << 10)
+
+#define RT5631_SDP_DAC_CPS_SEL_MASK                    (0x3 << 8)
+#define RT5631_SDP_DAC_CPS_SEL_OFF                     (0x0 << 8)
+#define RT5631_SDP_DAC_CPS_SEL_U_LAW                   (0x1 << 8)
+#define RT5631_SDP_DAC_CPS_SEL_A_LAW                   (0x2 << 8)
+/* 0:Normal 1:Invert */
+#define RT5631_SDP_I2S_BCLK_POL_CTRL                   (0x1 << 7)
+/* 0:Normal 1:Invert */
+#define RT5631_SDP_DAC_R_INV                           (0x1 << 6)
+/* 0:ADC data appear at left phase of LRCK
+ * 1:ADC data appear at right phase of LRCK
+ */
+#define RT5631_SDP_ADC_DATA_L_R_SWAP                   (0x1 << 5)
+/* 0:DAC data appear at left phase of LRCK
+ * 1:DAC data appear at right phase of LRCK
+ */
+#define RT5631_SDP_DAC_DATA_L_R_SWAP                   (0x1 << 4)
+
+/* Data Length Slection */
+#define RT5631_SDP_I2S_DL_MASK                         (0x3 << 2)
+#define RT5631_SDP_I2S_DL_16                           (0x0 << 2)
+#define RT5631_SDP_I2S_DL_20                           (0x1 << 2)
+#define RT5631_SDP_I2S_DL_24                           (0x2 << 2)
+#define RT5631_SDP_I2S_DL_8                            (0x3 << 2)
+
+/* PCM Data Format Selection */
+#define RT5631_SDP_I2S_DF_MASK                         (0x3)
+#define RT5631_SDP_I2S_DF_I2S                          (0x0)
+#define RT5631_SDP_I2S_DF_LEFT                         (0x1)
+#define RT5631_SDP_I2S_DF_PCM_A                        (0x2)
+#define RT5631_SDP_I2S_DF_PCM_B                        (0x3)
+
+/* Stereo AD/DA Clock Control(0x38h) */
+#define RT5631_I2S_PRE_DIV_MASK                        (0x7 << 13)
+#define RT5631_I2S_PRE_DIV_1                           (0x0 << 13)
+#define RT5631_I2S_PRE_DIV_2                           (0x1 << 13)
+#define RT5631_I2S_PRE_DIV_4                           (0x2 << 13)
+#define RT5631_I2S_PRE_DIV_8                           (0x3 << 13)
+#define RT5631_I2S_PRE_DIV_16                          (0x4 << 13)
+#define RT5631_I2S_PRE_DIV_32                          (0x5 << 13)
+/* CLOCK RELATIVE OF BCLK AND LCRK */
+#define RT5631_I2S_LRCK_SEL_N_BCLK_MASK                (0x1 << 12)
+#define RT5631_I2S_LRCK_SEL_64_BCLK                    (0x0 << 12) /* 64FS */
+#define RT5631_I2S_LRCK_SEL_32_BCLK                    (0x1 << 12) /* 32FS */
+
+#define RT5631_DAC_OSR_SEL_MASK                        (0x3 << 10)
+#define RT5631_DAC_OSR_SEL_128FS                       (0x3 << 10)
+#define RT5631_DAC_OSR_SEL_64FS                        (0x3 << 10)
+#define RT5631_DAC_OSR_SEL_32FS                        (0x3 << 10)
+#define RT5631_DAC_OSR_SEL_16FS                        (0x3 << 10)
+
+#define RT5631_ADC_OSR_SEL_MASK                        (0x3 << 8)
+#define RT5631_ADC_OSR_SEL_128FS                       (0x3 << 8)
+#define RT5631_ADC_OSR_SEL_64FS                        (0x3 << 8)
+#define RT5631_ADC_OSR_SEL_32FS                        (0x3 << 8)
+#define RT5631_ADC_OSR_SEL_16FS                        (0x3 << 8)
+
+#define RT5631_ADDA_FILTER_CLK_SEL_256FS               (0 << 7) /* 256FS */
+#define RT5631_ADDA_FILTER_CLK_SEL_384FS               (1 << 7) /* 384FS */
+
+/* Power managment addition 1 (0x3A) */
+#define RT5631_PWR_MAIN_I2S_EN                 (0x1 << 15)
+#define RT5631_PWR_MAIN_I2S_BIT                        15
+#define RT5631_PWR_CLASS_D                             (0x1 << 12)
+#define RT5631_PWR_CLASS_D_BIT                 12
+#define RT5631_PWR_ADC_L_CLK                           (0x1 << 11)
+#define RT5631_PWR_ADC_L_CLK_BIT                       11
+#define RT5631_PWR_ADC_R_CLK                           (0x1 << 10)
+#define RT5631_PWR_ADC_R_CLK_BIT                       10
+#define RT5631_PWR_DAC_L_CLK                           (0x1 << 9)
+#define RT5631_PWR_DAC_L_CLK_BIT                       9
+#define RT5631_PWR_DAC_R_CLK                           (0x1 << 8)
+#define RT5631_PWR_DAC_R_CLK_BIT                       8
+#define RT5631_PWR_DAC_REF                             (0x1 << 7)
+#define RT5631_PWR_DAC_REF_BIT                 7
+#define RT5631_PWR_DAC_L_TO_MIXER                      (0x1 << 6)
+#define RT5631_PWR_DAC_L_TO_MIXER_BIT          6
+#define RT5631_PWR_DAC_R_TO_MIXER                      (0x1 << 5)
+#define RT5631_PWR_DAC_R_TO_MIXER_BIT          5
+
+/* Power managment addition 2 (0x3B) */
+#define RT5631_PWR_OUTMIXER_L                          (0x1 << 15)
+#define RT5631_PWR_OUTMIXER_L_BIT                      15
+#define RT5631_PWR_OUTMIXER_R                          (0x1 << 14)
+#define RT5631_PWR_OUTMIXER_R_BIT                      14
+#define RT5631_PWR_SPKMIXER_L                          (0x1 << 13)
+#define RT5631_PWR_SPKMIXER_L_BIT                      13
+#define RT5631_PWR_SPKMIXER_R                          (0x1 << 12)
+#define RT5631_PWR_SPKMIXER_R_BIT                      12
+#define RT5631_PWR_RECMIXER_L                          (0x1 << 11)
+#define RT5631_PWR_RECMIXER_L_BIT                      11
+#define RT5631_PWR_RECMIXER_R                          (0x1 << 10)
+#define RT5631_PWR_RECMIXER_R_BIT                      10
+#define RT5631_PWR_MIC1_BOOT_GAIN                      (0x1 << 5)
+#define RT5631_PWR_MIC1_BOOT_GAIN_BIT          5
+#define RT5631_PWR_MIC2_BOOT_GAIN                      (0x1 << 4)
+#define RT5631_PWR_MIC2_BOOT_GAIN_BIT          4
+#define RT5631_PWR_MICBIAS1_VOL                        (0x1 << 3)
+#define RT5631_PWR_MICBIAS1_VOL_BIT                    3
+#define RT5631_PWR_MICBIAS2_VOL                        (0x1 << 2)
+#define RT5631_PWR_MICBIAS2_VOL_BIT                    2
+#define RT5631_PWR_PLL1                                (0x1 << 1)
+#define RT5631_PWR_PLL1_BIT                            1
+#define RT5631_PWR_PLL2                                (0x1 << 0)
+#define RT5631_PWR_PLL2_BIT                            0
+
+/* Power managment addition 3(0x3C) */
+#define RT5631_PWR_VREF                                (0x1 << 15)
+#define RT5631_PWR_VREF_BIT                            15
+#define RT5631_PWR_FAST_VREF_CTRL                      (0x1 << 14)
+#define RT5631_PWR_FAST_VREF_CTRL_BIT                  14
+#define RT5631_PWR_MAIN_BIAS                           (0x1 << 13)
+#define RT5631_PWR_MAIN_BIAS_BIT                       13
+#define RT5631_PWR_AXO1MIXER                           (0x1 << 11)
+#define RT5631_PWR_AXO1MIXER_BIT                       11
+#define RT5631_PWR_AXO2MIXER                           (0x1 << 10)
+#define RT5631_PWR_AXO2MIXER_BIT                       10
+#define RT5631_PWR_MONOMIXER                           (0x1 << 9)
+#define RT5631_PWR_MONOMIXER_BIT                       9
+#define RT5631_PWR_MONO_DEPOP_DIS                      (0x1 << 8)
+#define RT5631_PWR_MONO_DEPOP_DIS_BIT          8
+#define RT5631_PWR_MONO_AMP_EN                 (0x1 << 7)
+#define RT5631_PWR_MONO_AMP_EN_BIT                     7
+#define RT5631_PWR_CHARGE_PUMP                 (0x1 << 4)
+#define RT5631_PWR_CHARGE_PUMP_BIT                     4
+#define RT5631_PWR_HP_L_AMP                            (0x1 << 3)
+#define RT5631_PWR_HP_L_AMP_BIT                        3
+#define RT5631_PWR_HP_R_AMP                            (0x1 << 2)
+#define RT5631_PWR_HP_R_AMP_BIT                        2
+#define RT5631_PWR_HP_DEPOP_DIS                        (0x1 << 1)
+#define RT5631_PWR_HP_DEPOP_DIS_BIT                    1
+#define RT5631_PWR_HP_AMP_DRIVING                      (0x1 << 0)
+#define RT5631_PWR_HP_AMP_DRIVING_BIT          0
+
+/* Power managment addition 4(0x3E) */
+#define RT5631_PWR_SPK_L_VOL                           (0x1 << 15)
+#define RT5631_PWR_SPK_L_VOL_BIT                       15
+#define RT5631_PWR_SPK_R_VOL                           (0x1 << 14)
+#define RT5631_PWR_SPK_R_VOL_BIT                       14
+#define RT5631_PWR_LOUT_VOL                            (0x1 << 13)
+#define RT5631_PWR_LOUT_VOL_BIT                        13
+#define RT5631_PWR_ROUT_VOL                            (0x1 << 12)
+#define RT5631_PWR_ROUT_VOL_BIT                        12
+#define RT5631_PWR_HP_L_OUT_VOL                        (0x1 << 11)
+#define RT5631_PWR_HP_L_OUT_VOL_BIT                    11
+#define RT5631_PWR_HP_R_OUT_VOL                        (0x1 << 10)
+#define RT5631_PWR_HP_R_OUT_VOL_BIT                    10
+#define RT5631_PWR_AXIL_IN_VOL                         (0x1 << 9)
+#define RT5631_PWR_AXIL_IN_VOL_BIT                     9
+#define RT5631_PWR_AXIR_IN_VOL                 (0x1 << 8)
+#define RT5631_PWR_AXIR_IN_VOL_BIT                     8
+#define RT5631_PWR_MONO_IN_P_VOL                       (0x1 << 7)
+#define RT5631_PWR_MONO_IN_P_VOL_BIT                   7
+#define RT5631_PWR_MONO_IN_N_VOL                       (0x1 << 6)
+#define RT5631_PWR_MONO_IN_N_VOL_BIT                   6
+
+/* General Purpose Control Register(0x40) */
+#define RT5631_SPK_AMP_AUTO_RATIO_EN                   (0x1 << 15)
+
+#define RT5631_SPK_AMP_RATIO_CTRL_MASK         (0x7 << 12)
+#define RT5631_SPK_AMP_RATIO_CTRL_2_34         (0x0 << 12) /* 7.40DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_99         (0x1 << 12) /* 5.99DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_68         (0x2 << 12) /* 4.50DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_56         (0x3 << 12) /* 3.86DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_44         (0x4 << 12) /* 3.16DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_27         (0x5 << 12) /* 2.10DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_09         (0x6 << 12) /* 0.80DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_00         (0x7 << 12) /* 0.00DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_SHIFT                12
+
+#define RT5631_STEREO_DAC_HI_PASS_FILT_EN              (0x1 << 11)
+#define RT5631_STEREO_ADC_HI_PASS_FILT_EN              (0x1 << 10)
+/* Select ADC Wind Filter Clock type */
+#define RT5631_ADC_WIND_FILT_MASK                      (0x3 << 4)
+#define RT5631_ADC_WIND_FILT_8_16_32K                  (0x0 << 4) /*8/16/32k*/
+#define RT5631_ADC_WIND_FILT_11_22_44K         (0x1 << 4) /*11/22/44k*/
+#define RT5631_ADC_WIND_FILT_12_24_48K         (0x2 << 4) /*12/24/48k*/
+#define RT5631_ADC_WIND_FILT_EN                        (0x1 << 3)
+/* SelectADC Wind Filter Corner Frequency */
+#define RT5631_ADC_WIND_CNR_FREQ_MASK  (0x7 << 0)
+#define RT5631_ADC_WIND_CNR_FREQ_82_113_122    (0x0 << 0) /* 82/113/122 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_102_141_153 (0x1 << 0) /* 102/141/153 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_131_180_156 (0x2 << 0) /* 131/180/156 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_163_225_245 (0x3 << 0) /* 163/225/245 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_204_281_306 (0x4 << 0) /* 204/281/306 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_261_360_392 (0x5 << 0) /* 261/360/392 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_327_450_490 (0x6 << 0) /* 327/450/490 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_408_563_612 (0x7 << 0) /* 408/563/612 Hz */
+
+/* Global Clock Control Register(0x42) */
+#define RT5631_SYSCLK_SOUR_SEL_MASK                    (0x3 << 14)
+#define RT5631_SYSCLK_SOUR_SEL_MCLK                    (0x0 << 14)
+#define RT5631_SYSCLK_SOUR_SEL_PLL                     (0x1 << 14)
+#define RT5631_SYSCLK_SOUR_SEL_PLL_TCK         (0x2 << 14)
+
+#define RT5631_PLLCLK_SOUR_SEL_MASK                    (0x3 << 12)
+#define RT5631_PLLCLK_SOUR_SEL_MCLK                    (0x0 << 12)
+#define RT5631_PLLCLK_SOUR_SEL_BCLK                    (0x1 << 12)
+#define RT5631_PLLCLK_SOUR_SEL_VBCLK                   (0x2 << 12)
+
+#define RT5631_PLLCLK_PRE_DIV1                         (0x0 << 11)
+#define RT5631_PLLCLK_PRE_DIV2                         (0x1 << 11)
+
+/* PLL Control(0x44) */
+#define RT5631_PLL_CTRL_M_VAL(m)                       ((m)&0xf)
+#define RT5631_PLL_CTRL_K_VAL(k)                       (((k)&0x7) << 4)
+#define RT5631_PLL_CTRL_N_VAL(n)                       (((n)&0xff) << 8)
+
+/* Internal Status and IRQ Control2(0x4A) */
+#define RT5631_ADC_DATA_SEL_MASK                       (0x3 << 14)
+#define RT5631_ADC_DATA_SEL_Disable                    (0x0 << 14)
+#define RT5631_ADC_DATA_SEL_MIC1                       (0x1 << 14)
+#define RT5631_ADC_DATA_SEL_MIC1_SHIFT         14
+#define RT5631_ADC_DATA_SEL_MIC2                       (0x2 << 14)
+#define RT5631_ADC_DATA_SEL_MIC2_SHIFT         15
+#define RT5631_ADC_DATA_SEL_STO                        (0x3 << 14)
+#define RT5631_ADC_DATA_SEL_SHIFT                      14
+
+/* GPIO Pin Configuration(0x4C) */
+#define RT5631_GPIO_PIN_FUN_SEL_MASK                   (0x1 << 15)
+#define RT5631_GPIO_PIN_FUN_SEL_IRQ                    (0x1 << 15)
+#define RT5631_GPIO_PIN_FUN_SEL_GPIO_DIMC              (0x0 << 15)
+
+#define RT5631_GPIO_DMIC_FUN_SEL_MASK          (0x1 << 3)
+#define RT5631_GPIO_DMIC_FUN_SEL_DIMC          (0x1 << 3)
+#define RT5631_GPIO_DMIC_FUN_SEL_GPIO                  (0x0 << 3)
+
+#define RT5631_GPIO_PIN_CON_MASK                       (0x1 << 2)
+#define RT5631_GPIO_PIN_SET_INPUT                      (0x0 << 2)
+#define RT5631_GPIO_PIN_SET_OUTPUT                     (0x1 << 2)
+
+/* De-POP function Control 1(0x54) */
+#define RT5631_POW_ON_SOFT_GEN                 (0x1 << 15)
+#define RT5631_EN_MUTE_UNMUTE_DEPOP                    (0x1 << 14)
+#define RT5631_EN_DEPOP2_FOR_HP                        (0x1 << 7)
+/* Power Down HPAMP_L Starts Up Signal */
+#define RT5631_PD_HPAMP_L_ST_UP                        (0x1 << 5)
+/* Power Down HPAMP_R Starts Up Signal */
+#define RT5631_PD_HPAMP_R_ST_UP                        (0x1 << 4)
+/* Enable left HP mute/unmute depop */
+#define RT5631_EN_HP_L_M_UN_MUTE_DEPOP         (0x1 << 1)
+/* Enable right HP mute/unmute depop */
+#define RT5631_EN_HP_R_M_UN_MUTE_DEPOP         (0x1 << 0)
+
+/* De-POP Fnction Control(0x56) */
+#define RT5631_EN_ONE_BIT_DEPOP                        (0x1 << 15)
+#define RT5631_EN_CAP_FREE_DEPOP                       (0x1 << 14)
+
+/* Jack Detect Control Register(0x5A) */
+#define RT5631_JD_USE_MASK                             (0x3 << 14)
+#define RT5631_JD_USE_JD2                              (0x3 << 14)
+#define RT5631_JD_USE_JD1                              (0x2 << 14)
+#define RT5631_JD_USE_GPIO                             (0x1 << 14)
+#define RT5631_JD_OFF                                  (0x0 << 14)
+/* JD trigger enable for HP */
+#define RT5631_JD_HP_EN                                        (0x1 << 11)
+#define RT5631_JD_HP_TRI_MASK                          (0x1 << 10)
+#define RT5631_JD_HP_TRI_HI                            (0x1 << 10)
+#define RT5631_JD_HP_TRI_LO                            (0x1 << 10)
+/* JD trigger enable for speaker LP/LN */
+#define RT5631_JD_SPK_L_EN                             (0x1 << 9)
+#define RT5631_JD_SPK_L_TRI_MASK                       (0x1 << 8)
+#define RT5631_JD_SPK_L_TRI_HI                         (0x1 << 8)
+#define RT5631_JD_SPK_L_TRI_LO                         (0x0 << 8)
+/* JD trigger enable for speaker RP/RN */
+#define RT5631_JD_SPK_R_EN                             (0x1 << 7)
+#define RT5631_JD_SPK_R_TRI_MASK                       (0x1 << 6)
+#define RT5631_JD_SPK_R_TRI_HI                         (0x1 << 6)
+#define RT5631_JD_SPK_R_TRI_LO                         (0x0 << 6)
+/* JD trigger enable for monoout */
+#define RT5631_JD_MONO_EN                              (0x1 << 5)
+#define RT5631_JD_MONO_TRI_MASK                        (0x1 << 4)
+#define RT5631_JD_MONO_TRI_HI                          (0x1 << 4)
+#define RT5631_JD_MONO_TRI_LO                          (0x0 << 4)
+/* JD trigger enable for Lout */
+#define RT5631_JD_AUX_1_EN                             (0x1 << 3)
+#define RT5631_JD_AUX_1_MASK                           (0x1 << 2)
+#define RT5631_JD_AUX_1_TRI_HI                         (0x1 << 2)
+#define RT5631_JD_AUX_1_TRI_LO                         (0x0 << 2)
+/* JD trigger enable for Rout */
+#define RT5631_JD_AUX_2_EN                             (0x1 << 1)
+#define RT5631_JD_AUX_2_MASK                           (0x1 << 0)
+#define RT5631_JD_AUX_2_TRI_HI                         (0x1 << 0)
+#define RT5631_JD_AUX_2_TRI_LO                         (0x0 << 0)
+
+/* ALC CONTROL 1(0x64) */
+#define RT5631_ALC_ATTACK_RATE_MASK                    (0x1F << 8)
+#define RT5631_ALC_RECOVERY_RATE_MASK          (0x1F << 0)
+
+/* ALC CONTROL 2(0x65) */
+/* select Compensation gain for Noise gate function */
+#define RT5631_ALC_COM_NOISE_GATE_MASK         (0xF << 0)
+
+/* ALC CONTROL 3(0x66) */
+#define RT5631_ALC_FUN_MASK                            (0x3 << 14)
+#define RT5631_ALC_FUN_DIS                             (0x0 << 14)
+#define RT5631_ALC_ENA_DAC_PATH                        (0x1 << 14)
+#define RT5631_ALC_ENA_ADC_PATH                        (0x3 << 14)
+#define RT5631_ALC_PARA_UPDATE                 (0x1 << 13)
+#define RT5631_ALC_LIMIT_LEVEL_MASK                    (0x1F << 8)
+#define RT5631_ALC_NOISE_GATE_FUN_MASK         (0x1 << 7)
+#define RT5631_ALC_NOISE_GATE_FUN_DIS                  (0x0 << 7)
+#define RT5631_ALC_NOISE_GATE_FUN_ENA          (0x1 << 7)
+/* ALC noise gate hold data function */
+#define RT5631_ALC_NOISE_GATE_H_D_MASK         (0x1 << 6)
+#define RT5631_ALC_NOISE_GATE_H_D_DIS                  (0x0 << 6)
+#define RT5631_ALC_NOISE_GATE_H_D_ENA          (0x1 << 6)
+
+/* Psedueo Stereo & Spatial Effect Block Control(0x68) */
+#define RT5631_SPATIAL_CTRL_EN                         (0x1 << 15)
+#define RT5631_ALL_PASS_FILTER_EN                      (0x1 << 14)
+#define RT5631_PSEUDO_STEREO_EN                        (0x1 << 13)
+#define RT5631_STEREO_EXPENSION_EN                     (0x1 << 12)
+/* 3D gain parameter */
+#define RT5631_GAIN_3D_PARA_MASK               (0x3 << 6)
+#define RT5631_GAIN_3D_PARA_1_00               (0x0 << 6) /* 3D gain 1.0 */
+#define RT5631_GAIN_3D_PARA_1_50               (0x1 << 6) /* 3D gain 1.5 */
+#define RT5631_GAIN_3D_PARA_2_00               (0x2 << 6) /* 3D gain 2.0 */
+/* 3D ratio parameter */
+#define RT5631_RATIO_3D_MASK                   (0x3 << 4)
+#define RT5631_RATIO_3D_0_0                    (0x0 << 4) /* 3D ratio 0.0 */
+#define RT5631_RATIO_3D_0_66                   (0x1 << 4) /* 3D ratio 0.66 */
+#define RT5631_RATIO_3D_1_0                    (0x2 << 4) /* 3D ratio 1.0 */
+/* select samplerate for all pass filter */
+#define RT5631_APF_FUN_SLE_MASK                        (0x3 << 0)
+#define RT5631_APF_FUN_SEL_48K                         (0x3 << 0)
+#define RT5631_APF_FUN_SEL_44_1K                       (0x2 << 0)
+#define RT5631_APF_FUN_SEL_32K                         (0x1 << 0)
+#define RT5631_APF_FUN_DIS                             (0x0 << 0)
+
+/* EQ CONTROL 1(0x6E) */
+#define RT5631_HW_EQ_PATH_SEL_MASK                     (0x1 << 15)
+#define RT5631_HW_EQ_PATH_SEL_DAC                      (0x0 << 15)
+#define RT5631_HW_EQ_PATH_SEL_ADC                      (0x1 << 15)
+#define RT5631_HW_EQ_UPDATE_CTRL                       (0x1 << 14)
+
+#define RT5631_EN_HW_EQ_HPF2                           (0x1 << 5)
+#define RT5631_EN_HW_EQ_HPF1                           (0x1 << 4)
+#define RT5631_EN_HW_EQ_BP3                            (0x1 << 3)
+#define RT5631_EN_HW_EQ_BP2                            (0x1 << 2)
+#define RT5631_EN_HW_EQ_BP1                            (0x1 << 1)
+#define RT5631_EN_HW_EQ_LPF                            (0x1 << 0)
+
+
+#endif /* __RTCODEC5631_H__ */
index 91130fb..d15695d 100644 (file)
@@ -131,16 +131,13 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w,
        case SND_SOC_DAPM_POST_PMU:
                /* change mic bias resistor to 4Kohm */
                snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL,
-                               SGTL5000_BIAS_R_4k, SGTL5000_BIAS_R_4k);
+                               SGTL5000_BIAS_R_MASK,
+                               SGTL5000_BIAS_R_4k << SGTL5000_BIAS_R_SHIFT);
                break;
 
        case SND_SOC_DAPM_PRE_PMD:
-               /*
-                * SGTL5000_BIAS_R_8k as mask to clean the two bits
-                * of mic bias and output impedance
-                */
                snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL,
-                               SGTL5000_BIAS_R_8k, 0);
+                               SGTL5000_BIAS_R_MASK, 0);
                break;
        }
        return 0;
@@ -726,7 +723,9 @@ static int sgtl5000_pcm_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       snd_soc_update_bits(codec, SGTL5000_CHIP_I2S_CTRL, i2s_ctl, i2s_ctl);
+       snd_soc_update_bits(codec, SGTL5000_CHIP_I2S_CTRL,
+                           SGTL5000_I2S_DLEN_MASK | SGTL5000_I2S_SCLKFREQ_MASK,
+                           i2s_ctl);
 
        return 0;
 }
@@ -757,7 +756,7 @@ static int ldo_regulator_enable(struct regulator_dev *dev)
 
        /* set voltage to register */
        snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
-                               (0x1 << 4) - 1, reg);
+                               SGTL5000_LINREG_VDDD_MASK, reg);
 
        snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
                                SGTL5000_LINEREG_D_POWERUP,
@@ -783,7 +782,7 @@ static int ldo_regulator_disable(struct regulator_dev *dev)
 
        /* clear voltage info */
        snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
-                               (0x1 << 4) - 1, 0);
+                               SGTL5000_LINREG_VDDD_MASK, 0);
 
        ldo->enabled = 0;
 
@@ -809,6 +808,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
                                int voltage)
 {
        struct ldo_regulator *ldo;
+       struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
 
        ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL);
 
@@ -843,6 +843,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
 
                return ret;
        }
+       sgtl5000->ldo = ldo;
 
        return 0;
 }
@@ -1116,7 +1117,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
 
        /* set voltage to register */
        snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
-                               (0x1 << 4) - 1, 0x8);
+                               SGTL5000_LINREG_VDDD_MASK, 0x8);
 
        /*
         * if vddd linear reg has been enabled,
@@ -1147,8 +1148,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
                vag = (vag - SGTL5000_ANA_GND_BASE) / SGTL5000_ANA_GND_STP;
 
        snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL,
-                       vag << SGTL5000_ANA_GND_SHIFT,
-                       vag << SGTL5000_ANA_GND_SHIFT);
+                       SGTL5000_ANA_GND_MASK, vag << SGTL5000_ANA_GND_SHIFT);
 
        /* set line out VAG to vddio / 2, in range (0.8v, 1.675v) */
        vag = vddio / 2;
@@ -1162,9 +1162,8 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
                    SGTL5000_LINE_OUT_GND_STP;
 
        snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_CTRL,
-                       vag << SGTL5000_LINE_OUT_GND_SHIFT |
-                       SGTL5000_LINE_OUT_CURRENT_360u <<
-                               SGTL5000_LINE_OUT_CURRENT_SHIFT,
+                       SGTL5000_LINE_OUT_CURRENT_MASK |
+                       SGTL5000_LINE_OUT_GND_MASK,
                        vag << SGTL5000_LINE_OUT_GND_SHIFT |
                        SGTL5000_LINE_OUT_CURRENT_360u <<
                                SGTL5000_LINE_OUT_CURRENT_SHIFT);
index eec3ab3..8a9f435 100644 (file)
 /*
  * SGTL5000_CHIP_MIC_CTRL
  */
-#define SGTL5000_BIAS_R_MASK                   0x0200
+#define SGTL5000_BIAS_R_MASK                   0x0300
 #define SGTL5000_BIAS_R_SHIFT                  8
 #define SGTL5000_BIAS_R_WIDTH                  2
 #define SGTL5000_BIAS_R_off                    0x0
index 29945b0..f681e41 100644 (file)
@@ -102,7 +102,7 @@ static int sn95031_initialize_adc(struct snd_soc_codec *sn95031_codec)
 {
        int base_addr, chnl_addr;
        int value;
-       static int channel_index;
+       int channel_index;
 
        /* Index of the first channel in which the stop bit is set */
        channel_index = find_free_channel(sn95031_codec);
@@ -161,7 +161,6 @@ static unsigned int sn95031_get_mic_bias(struct snd_soc_codec *codec)
        pr_debug("mic bias = %dmV\n", mic_bias);
        return mic_bias;
 }
-EXPORT_SYMBOL_GPL(sn95031_get_mic_bias);
 /*end - adc helper functions */
 
 static inline unsigned int sn95031_read(struct snd_soc_codec *codec,
@@ -716,7 +715,7 @@ static struct snd_soc_dai_ops sn95031_vib2_dai_ops = {
        .hw_params      = sn95031_pcm_hw_params,
 };
 
-struct snd_soc_dai_driver sn95031_dais[] = {
+static struct snd_soc_dai_driver sn95031_dais[] = {
 {
        .name = "SN95031 Headset",
        .playback = {
@@ -827,7 +826,6 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
 {
        pr_debug("codec_probe called\n");
 
-       codec->dapm.bias_level = SND_SOC_BIAS_OFF;
        codec->dapm.idle_bias_off = 1;
 
        /* PCM interface config
index 32d6c51..3cb3271 100644 (file)
@@ -59,6 +59,7 @@ struct ssm2602_priv {
        struct snd_pcm_substream *slave_substream;
 
        enum ssm2602_type type;
+       unsigned int clk_out_pwr;
 };
 
 /*
@@ -342,12 +343,14 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
 static int ssm2602_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
-       u16 mute_reg = snd_soc_read(codec, SSM2602_APDIGI) & ~APDIGI_ENABLE_DAC_MUTE;
+
        if (mute)
-               snd_soc_write(codec, SSM2602_APDIGI,
-                               mute_reg | APDIGI_ENABLE_DAC_MUTE);
+               snd_soc_update_bits(codec, SSM2602_APDIGI,
+                                   APDIGI_ENABLE_DAC_MUTE,
+                                   APDIGI_ENABLE_DAC_MUTE);
        else
-               snd_soc_write(codec, SSM2602_APDIGI, mute_reg);
+               snd_soc_update_bits(codec, SSM2602_APDIGI,
+                                   APDIGI_ENABLE_DAC_MUTE, 0);
        return 0;
 }
 
@@ -356,16 +359,46 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
-       switch (freq) {
-       case 11289600:
-       case 12000000:
-       case 12288000:
-       case 16934400:
-       case 18432000:
-               ssm2602->sysclk = freq;
-               return 0;
+
+       if (dir == SND_SOC_CLOCK_IN) {
+               if (clk_id != SSM2602_SYSCLK)
+                       return -EINVAL;
+
+               switch (freq) {
+               case 11289600:
+               case 12000000:
+               case 12288000:
+               case 16934400:
+               case 18432000:
+                       ssm2602->sysclk = freq;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       } else {
+               unsigned int mask;
+
+               switch (clk_id) {
+               case SSM2602_CLK_CLKOUT:
+                       mask = PWR_CLK_OUT_PDN;
+                       break;
+               case SSM2602_CLK_XTO:
+                       mask = PWR_OSC_PDN;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+
+               if (freq == 0)
+                       ssm2602->clk_out_pwr |= mask;
+               else
+                       ssm2602->clk_out_pwr &= ~mask;
+
+               snd_soc_update_bits(codec, SSM2602_PWR,
+                       PWR_CLK_OUT_PDN | PWR_OSC_PDN, ssm2602->clk_out_pwr);
        }
-       return -EINVAL;
+
+       return 0;
 }
 
 static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
@@ -430,23 +463,27 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
 static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
-       u16 reg = snd_soc_read(codec, SSM2602_PWR);
-       reg &= ~(PWR_POWER_OFF | PWR_OSC_PDN);
+       struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
 
        switch (level) {
        case SND_SOC_BIAS_ON:
-               /* vref/mid, osc on, dac unmute */
-               snd_soc_write(codec, SSM2602_PWR, reg);
+               /* vref/mid on, osc and clkout on if enabled */
+               snd_soc_update_bits(codec, SSM2602_PWR,
+                       PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
+                       ssm2602->clk_out_pwr);
                break;
        case SND_SOC_BIAS_PREPARE:
                break;
        case SND_SOC_BIAS_STANDBY:
                /* everything off except vref/vmid, */
-               snd_soc_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN);
+               snd_soc_update_bits(codec, SSM2602_PWR,
+                       PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
+                       PWR_CLK_OUT_PDN | PWR_OSC_PDN);
                break;
        case SND_SOC_BIAS_OFF:
-               /* everything off, dac mute, inactive */
-               snd_soc_write(codec, SSM2602_PWR, 0xffff);
+               /* everything off */
+               snd_soc_update_bits(codec, SSM2602_PWR,
+                       PWR_POWER_OFF, PWR_POWER_OFF);
                break;
 
        }
@@ -505,12 +542,12 @@ static int ssm2602_resume(struct snd_soc_codec *codec)
 static int ssm2602_probe(struct snd_soc_codec *codec)
 {
        struct snd_soc_dapm_context *dapm = &codec->dapm;
-       int ret, reg;
+       int ret;
 
-       reg = snd_soc_read(codec, SSM2602_LOUT1V);
-       snd_soc_write(codec, SSM2602_LOUT1V, reg | LOUT1V_LRHP_BOTH);
-       reg = snd_soc_read(codec, SSM2602_ROUT1V);
-       snd_soc_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH);
+       snd_soc_update_bits(codec, SSM2602_LOUT1V,
+                           LOUT1V_LRHP_BOTH, LOUT1V_LRHP_BOTH);
+       snd_soc_update_bits(codec, SSM2602_ROUT1V,
+                           ROUT1V_RLHP_BOTH, ROUT1V_RLHP_BOTH);
 
        ret = snd_soc_add_controls(codec, ssm2602_snd_controls,
                        ARRAY_SIZE(ssm2602_snd_controls));
@@ -543,7 +580,7 @@ static int ssm2604_probe(struct snd_soc_codec *codec)
 static int ssm260x_probe(struct snd_soc_codec *codec)
 {
        struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
-       int ret, reg;
+       int ret;
 
        pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION);
 
@@ -560,10 +597,10 @@ static int ssm260x_probe(struct snd_soc_codec *codec)
        }
 
        /* set the update bits */
-       reg = snd_soc_read(codec, SSM2602_LINVOL);
-       snd_soc_write(codec, SSM2602_LINVOL, reg | LINVOL_LRIN_BOTH);
-       reg = snd_soc_read(codec, SSM2602_RINVOL);
-       snd_soc_write(codec, SSM2602_RINVOL, reg | RINVOL_RLIN_BOTH);
+       snd_soc_update_bits(codec, SSM2602_LINVOL,
+                           LINVOL_LRIN_BOTH, LINVOL_LRIN_BOTH);
+       snd_soc_update_bits(codec, SSM2602_RINVOL,
+                           RINVOL_RLIN_BOTH, RINVOL_RLIN_BOTH);
        /*select Line in as default input*/
        snd_soc_write(codec, SSM2602_APANA, APANA_SELECT_DAC |
                        APANA_ENABLE_MIC_BOOST);
@@ -577,7 +614,12 @@ static int ssm260x_probe(struct snd_soc_codec *codec)
                break;
        }
 
-       return ret;
+       if (ret)
+               return ret;
+
+       ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       return 0;
 }
 
 /* remove everything here */
index b98c691..fbd07d7 100644 (file)
 
 #define SSM2602_CACHEREGNUM    10
 
-#define SSM2602_SYSCLK 0
+enum ssm2602_clk {
+       SSM2602_SYSCLK,
+       SSM2602_CLK_CLKOUT,
+       SSM2602_CLK_XTO
+};
 
 #endif
index 5c7def3..bb82408 100644 (file)
@@ -756,25 +756,19 @@ static int sta32x_probe(struct snd_soc_codec *codec)
                return ret;
        }
 
-       /* read reg reset values into cache */
-       for (i = 0; i < STA32X_REGISTER_COUNT; i++)
-               snd_soc_cache_write(codec, i, sta32x_regs[i]);
-
-       /* preserve reset values of reserved register bits */
-       snd_soc_cache_write(codec, STA32X_CONFC,
-                           codec->hw_read(codec, STA32X_CONFC));
-       snd_soc_cache_write(codec, STA32X_CONFE,
-                           codec->hw_read(codec, STA32X_CONFE));
-       snd_soc_cache_write(codec, STA32X_CONFF,
-                           codec->hw_read(codec, STA32X_CONFF));
-       snd_soc_cache_write(codec, STA32X_MMUTE,
-                           codec->hw_read(codec, STA32X_MMUTE));
-       snd_soc_cache_write(codec, STA32X_AUTO1,
-                           codec->hw_read(codec, STA32X_AUTO1));
-       snd_soc_cache_write(codec, STA32X_AUTO3,
-                           codec->hw_read(codec, STA32X_AUTO3));
-       snd_soc_cache_write(codec, STA32X_C3CFG,
-                           codec->hw_read(codec, STA32X_C3CFG));
+       /* Chip documentation explicitly requires that the reset values
+        * of reserved register bits are left untouched.
+        * Write the register default value to cache for reserved registers,
+        * so the write to the these registers are suppressed by the cache
+        * restore code when it skips writes of default registers.
+        */
+       snd_soc_cache_write(codec, STA32X_CONFC, 0xc2);
+       snd_soc_cache_write(codec, STA32X_CONFE, 0xc2);
+       snd_soc_cache_write(codec, STA32X_CONFF, 0x5c);
+       snd_soc_cache_write(codec, STA32X_MMUTE, 0x10);
+       snd_soc_cache_write(codec, STA32X_AUTO1, 0x60);
+       snd_soc_cache_write(codec, STA32X_AUTO3, 0x00);
+       snd_soc_cache_write(codec, STA32X_C3CFG, 0x40);
 
        /* FIXME enable thermal warning adjustment and recovery  */
        snd_soc_update_bits(codec, STA32X_CONFA,
@@ -837,6 +831,7 @@ static const struct snd_soc_codec_driver sta32x_codec = {
        .resume =               sta32x_resume,
        .reg_cache_size =       STA32X_REGISTER_COUNT,
        .reg_word_size =        sizeof(u8),
+       .reg_cache_default =    sta32x_regs,
        .volatile_register =    sta32x_reg_is_volatile,
        .set_bias_level =       sta32x_set_bias_level,
        .controls =             sta32x_snd_controls,
index 33bb52f..ab27dbc 100644 (file)
@@ -47,63 +47,6 @@ static const u16 tlv320aic23_reg[] = {
        0x0000, 0x0000, 0x0000, 0x0000, /* 12 */
 };
 
-/*
- * read tlv320aic23 register cache
- */
-static inline unsigned int tlv320aic23_read_reg_cache(struct snd_soc_codec
-                                                     *codec, unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg >= ARRAY_SIZE(tlv320aic23_reg))
-               return -1;
-       return cache[reg];
-}
-
-/*
- * write tlv320aic23 register cache
- */
-static inline void tlv320aic23_write_reg_cache(struct snd_soc_codec *codec,
-                                              u8 reg, u16 value)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg >= ARRAY_SIZE(tlv320aic23_reg))
-               return;
-       cache[reg] = value;
-}
-
-/*
- * write to the tlv320aic23 register space
- */
-static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
-                            unsigned int value)
-{
-
-       u8 data[2];
-
-       /* TLV320AIC23 has 7 bit address and 9 bits of data
-        * so we need to switch one data bit into reg and rest
-        * of data into val
-        */
-
-       if (reg > 9 && reg != 15) {
-               printk(KERN_WARNING "%s Invalid register R%u\n", __func__, reg);
-               return -1;
-       }
-
-       data[0] = (reg << 1) | (value >> 8 & 0x01);
-       data[1] = value & 0xff;
-
-       tlv320aic23_write_reg_cache(codec, reg, value);
-
-       if (codec->hw_write(codec->control_data, data, 2) == 2)
-               return 0;
-
-       printk(KERN_ERR "%s cannot write %03x to register R%u\n", __func__,
-              value, reg);
-
-       return -EIO;
-}
-
 static const char *rec_src_text[] = { "Line", "Mic" };
 static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"};
 
@@ -139,8 +82,8 @@ static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol,
        */
        val = (val >= 4) ? 4  : (3 - val);
 
-       reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (~0x1C0);
-       tlv320aic23_write(codec, TLV320AIC23_ANLG, reg | (val << 6));
+       reg = snd_soc_read(codec, TLV320AIC23_ANLG) & (~0x1C0);
+       snd_soc_write(codec, TLV320AIC23_ANLG, reg | (val << 6));
 
        return 0;
 }
@@ -151,7 +94,7 @@ static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        u16 val;
 
-       val = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (0x1C0);
+       val = snd_soc_read(codec, TLV320AIC23_ANLG) & (0x1C0);
        val = val >> 6;
        val = (val >= 4) ? 4  : (3 -  val);
        ucontrol->value.integer.value[0] = val;
@@ -159,15 +102,6 @@ static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
 
 }
 
-#define SOC_TLV320AIC23_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
-       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
-                SNDRV_CTL_ELEM_ACCESS_READWRITE,\
-       .tlv.p = (tlv_array), \
-       .info = snd_soc_info_volsw, .get = snd_soc_tlv320aic23_get_volsw,\
-       .put = snd_soc_tlv320aic23_put_volsw, \
-       .private_value =  SOC_SINGLE_VALUE(reg, shift, max, invert) }
-
 static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = {
        SOC_DOUBLE_R_TLV("Digital Playback Volume", TLV320AIC23_LCHNVOL,
                         TLV320AIC23_RCHNVOL, 0, 127, 0, out_gain_tlv),
@@ -178,8 +112,9 @@ static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = {
                         TLV320AIC23_RINVOL, 0, 31, 0, input_gain_tlv),
        SOC_SINGLE("Mic Input Switch", TLV320AIC23_ANLG, 1, 1, 1),
        SOC_SINGLE("Mic Booster Switch", TLV320AIC23_ANLG, 0, 1, 0),
-       SOC_TLV320AIC23_SINGLE_TLV("Sidetone Volume", TLV320AIC23_ANLG,
-                                 6, 4, 0, sidetone_vol_tlv),
+       SOC_SINGLE_EXT_TLV("Sidetone Volume", TLV320AIC23_ANLG, 6, 4, 0,
+                          snd_soc_tlv320aic23_get_volsw,
+                          snd_soc_tlv320aic23_put_volsw, sidetone_vol_tlv),
        SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph),
 };
 
@@ -240,7 +175,6 @@ static const struct snd_soc_dapm_route tlv320aic23_intercon[] = {
 /* AIC23 driver data */
 struct aic23 {
        enum snd_soc_control_type control_type;
-       void *control_data;
        int mclk;
        int requested_adc;
        int requested_dac;
@@ -352,7 +286,7 @@ static int find_rate(int mclk, u32 need_adc, u32 need_dac)
 static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk,
                u32 *sample_rate_adc, u32 *sample_rate_dac)
 {
-       int src = tlv320aic23_read_reg_cache(codec, TLV320AIC23_SRATE);
+       int src = snd_soc_read(codec, TLV320AIC23_SRATE);
        int sr = (src >> 2) & 0x0f;
        int val = (mclk / bosr_usb_divisor_table[src & 3]);
        int adc = (val * sr_adc_mult_table[sr]) / SR_MULT;
@@ -376,7 +310,7 @@ static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk,
                                __func__, sample_rate_adc, sample_rate_dac);
                return -EINVAL;
        }
-       tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
+       snd_soc_write(codec, TLV320AIC23_SRATE, data);
 #ifdef DEBUG
        {
                u32 adc, dac;
@@ -415,9 +349,8 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
        if (ret < 0)
                return ret;
 
-       iface_reg =
-           tlv320aic23_read_reg_cache(codec,
-                                      TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
+       iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
+
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
                break;
@@ -431,7 +364,7 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
                iface_reg |= (0x03 << 2);
                break;
        }
-       tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
+       snd_soc_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
 
        return 0;
 }
@@ -443,7 +376,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
        struct snd_soc_codec *codec = rtd->codec;
 
        /* set active */
-       tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001);
+       snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0001);
 
        return 0;
 }
@@ -458,7 +391,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
        /* deactivate */
        if (!codec->active) {
                udelay(50);
-               tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
+               snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0);
        }
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                aic23->requested_dac = 0;
@@ -471,14 +404,14 @@ static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute)
        struct snd_soc_codec *codec = dai->codec;
        u16 reg;
 
-       reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT);
+       reg = snd_soc_read(codec, TLV320AIC23_DIGT);
        if (mute)
                reg |= TLV320AIC23_DACM_MUTE;
 
        else
                reg &= ~TLV320AIC23_DACM_MUTE;
 
-       tlv320aic23_write(codec, TLV320AIC23_DIGT, reg);
+       snd_soc_write(codec, TLV320AIC23_DIGT, reg);
 
        return 0;
 }
@@ -489,8 +422,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
        struct snd_soc_codec *codec = codec_dai->codec;
        u16 iface_reg;
 
-       iface_reg =
-           tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT_FMT) & (~0x03);
+       iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & (~0x03);
 
        /* set master/slave audio interface */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -524,7 +456,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
 
        }
 
-       tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
+       snd_soc_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
 
        return 0;
 }
@@ -540,26 +472,26 @@ static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
                                      enum snd_soc_bias_level level)
 {
-       u16 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_PWR) & 0xff7f;
+       u16 reg = snd_soc_read(codec, TLV320AIC23_PWR) & 0xff7f;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
                /* vref/mid, osc on, dac unmute */
                reg &= ~(TLV320AIC23_DEVICE_PWR_OFF | TLV320AIC23_OSC_OFF | \
                        TLV320AIC23_DAC_OFF);
-               tlv320aic23_write(codec, TLV320AIC23_PWR, reg);
+               snd_soc_write(codec, TLV320AIC23_PWR, reg);
                break;
        case SND_SOC_BIAS_PREPARE:
                break;
        case SND_SOC_BIAS_STANDBY:
                /* everything off except vref/vmid, */
-               tlv320aic23_write(codec, TLV320AIC23_PWR, reg | \
-                       TLV320AIC23_CLK_OFF);
+               snd_soc_write(codec, TLV320AIC23_PWR,
+                             reg | TLV320AIC23_CLK_OFF);
                break;
        case SND_SOC_BIAS_OFF:
                /* everything off, dac mute, inactive */
-               tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
-               tlv320aic23_write(codec, TLV320AIC23_PWR, 0xffff);
+               snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0);
+               snd_soc_write(codec, TLV320AIC23_PWR, 0xffff);
                break;
        }
        codec->dapm.bias_level = level;
@@ -606,13 +538,7 @@ static int tlv320aic23_suspend(struct snd_soc_codec *codec,
 
 static int tlv320aic23_resume(struct snd_soc_codec *codec)
 {
-       u16 reg;
-
-       /* Sync reg_cache with the hardware */
-       for (reg = 0; reg <= TLV320AIC23_ACTIVE; reg++) {
-               u16 val = tlv320aic23_read_reg_cache(codec, reg);
-               tlv320aic23_write(codec, reg, val);
-       }
+       snd_soc_cache_sync(codec);
        tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
@@ -621,46 +547,52 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec)
 static int tlv320aic23_probe(struct snd_soc_codec *codec)
 {
        struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
-       int reg;
+       int ret;
 
        printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
-       codec->control_data = aic23->control_data;
-       codec->hw_write = (hw_write_t)i2c_master_send;
-       codec->hw_read = NULL;
+
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, aic23->control_type);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
 
        /* Reset codec */
-       tlv320aic23_write(codec, TLV320AIC23_RESET, 0);
+       snd_soc_write(codec, TLV320AIC23_RESET, 0);
+
+       /* Write the register default value to cache for reserved registers,
+        * so the write to the these registers are suppressed by the cache
+        * restore code when it skips writes of default registers.
+        */
+       snd_soc_cache_write(codec, 0x0A, 0);
+       snd_soc_cache_write(codec, 0x0B, 0);
+       snd_soc_cache_write(codec, 0x0C, 0);
+       snd_soc_cache_write(codec, 0x0D, 0);
+       snd_soc_cache_write(codec, 0x0E, 0);
 
        /* power on device */
        tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       tlv320aic23_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K);
+       snd_soc_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K);
 
        /* Unmute input */
-       reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_LINVOL);
-       tlv320aic23_write(codec, TLV320AIC23_LINVOL,
-                         (reg & (~TLV320AIC23_LIM_MUTED)) |
-                         (TLV320AIC23_LRS_ENABLED));
+       snd_soc_update_bits(codec, TLV320AIC23_LINVOL,
+                           TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED);
 
-       reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_RINVOL);
-       tlv320aic23_write(codec, TLV320AIC23_RINVOL,
-                         (reg & (~TLV320AIC23_LIM_MUTED)) |
-                         TLV320AIC23_LRS_ENABLED);
+       snd_soc_update_bits(codec, TLV320AIC23_RINVOL,
+                           TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED);
 
-       reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG);
-       tlv320aic23_write(codec, TLV320AIC23_ANLG,
-                        (reg) & (~TLV320AIC23_BYPASS_ON) &
-                        (~TLV320AIC23_MICM_MUTED));
+       snd_soc_update_bits(codec, TLV320AIC23_ANLG,
+                           TLV320AIC23_BYPASS_ON | TLV320AIC23_MICM_MUTED,
+                           0);
 
        /* Default output volume */
-       tlv320aic23_write(codec, TLV320AIC23_LCHNVOL,
-                         TLV320AIC23_DEFAULT_OUT_VOL &
-                         TLV320AIC23_OUT_VOL_MASK);
-       tlv320aic23_write(codec, TLV320AIC23_RCHNVOL,
-                         TLV320AIC23_DEFAULT_OUT_VOL &
-                         TLV320AIC23_OUT_VOL_MASK);
+       snd_soc_write(codec, TLV320AIC23_LCHNVOL,
+                     TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK);
+       snd_soc_write(codec, TLV320AIC23_RCHNVOL,
+                     TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK);
 
-       tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1);
+       snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1);
 
        snd_soc_add_controls(codec, tlv320aic23_snd_controls,
                                ARRAY_SIZE(tlv320aic23_snd_controls));
@@ -682,8 +614,6 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
        .remove = tlv320aic23_remove,
        .suspend = tlv320aic23_suspend,
        .resume = tlv320aic23_resume,
-       .read = tlv320aic23_read_reg_cache,
-       .write = tlv320aic23_write,
        .set_bias_level = tlv320aic23_set_bias_level,
        .dapm_widgets = tlv320aic23_dapm_widgets,
        .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
@@ -710,7 +640,6 @@ static int tlv320aic23_codec_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, aic23);
-       aic23->control_data = i2c;
        aic23->control_type = SND_SOC_I2C;
 
        ret =  snd_soc_register_codec(&i2c->dev,
index e93b9d1..b21c610 100644 (file)
@@ -528,40 +528,33 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
                                  enum snd_soc_bias_level level)
 {
        struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
-       u8 value;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
                if (aic32x4->master) {
                        /* Switch on PLL */
-                       value = snd_soc_read(codec, AIC32X4_PLLPR);
-                       snd_soc_write(codec, AIC32X4_PLLPR,
-                                     (value | AIC32X4_PLLEN));
+                       snd_soc_update_bits(codec, AIC32X4_PLLPR,
+                                           AIC32X4_PLLEN, AIC32X4_PLLEN);
 
                        /* Switch on NDAC Divider */
-                       value = snd_soc_read(codec, AIC32X4_NDAC);
-                       snd_soc_write(codec, AIC32X4_NDAC,
-                                     value | AIC32X4_NDACEN);
+                       snd_soc_update_bits(codec, AIC32X4_NDAC,
+                                           AIC32X4_NDACEN, AIC32X4_NDACEN);
 
                        /* Switch on MDAC Divider */
-                       value = snd_soc_read(codec, AIC32X4_MDAC);
-                       snd_soc_write(codec, AIC32X4_MDAC,
-                                     value | AIC32X4_MDACEN);
+                       snd_soc_update_bits(codec, AIC32X4_MDAC,
+                                           AIC32X4_MDACEN, AIC32X4_MDACEN);
 
                        /* Switch on NADC Divider */
-                       value = snd_soc_read(codec, AIC32X4_NADC);
-                       snd_soc_write(codec, AIC32X4_NADC,
-                                     value | AIC32X4_MDACEN);
+                       snd_soc_update_bits(codec, AIC32X4_NADC,
+                                           AIC32X4_NADCEN, AIC32X4_NADCEN);
 
                        /* Switch on MADC Divider */
-                       value = snd_soc_read(codec, AIC32X4_MADC);
-                       snd_soc_write(codec, AIC32X4_MADC,
-                                     value | AIC32X4_MDACEN);
+                       snd_soc_update_bits(codec, AIC32X4_MADC,
+                                           AIC32X4_MADCEN, AIC32X4_MADCEN);
 
                        /* Switch on BCLK_N Divider */
-                       value = snd_soc_read(codec, AIC32X4_BCLKN);
-                       snd_soc_write(codec, AIC32X4_BCLKN,
-                                     value | AIC32X4_BCLKEN);
+                       snd_soc_update_bits(codec, AIC32X4_BCLKN,
+                                           AIC32X4_BCLKEN, AIC32X4_BCLKEN);
                }
                break;
        case SND_SOC_BIAS_PREPARE:
@@ -569,34 +562,28 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
        case SND_SOC_BIAS_STANDBY:
                if (aic32x4->master) {
                        /* Switch off PLL */
-                       value = snd_soc_read(codec, AIC32X4_PLLPR);
-                       snd_soc_write(codec, AIC32X4_PLLPR,
-                                     (value & ~AIC32X4_PLLEN));
+                       snd_soc_update_bits(codec, AIC32X4_PLLPR,
+                                           AIC32X4_PLLEN, 0);
 
                        /* Switch off NDAC Divider */
-                       value = snd_soc_read(codec, AIC32X4_NDAC);
-                       snd_soc_write(codec, AIC32X4_NDAC,
-                                     value & ~AIC32X4_NDACEN);
+                       snd_soc_update_bits(codec, AIC32X4_NDAC,
+                                           AIC32X4_NDACEN, 0);
 
                        /* Switch off MDAC Divider */
-                       value = snd_soc_read(codec, AIC32X4_MDAC);
-                       snd_soc_write(codec, AIC32X4_MDAC,
-                                     value & ~AIC32X4_MDACEN);
+                       snd_soc_update_bits(codec, AIC32X4_MDAC,
+                                           AIC32X4_MDACEN, 0);
 
                        /* Switch off NADC Divider */
-                       value = snd_soc_read(codec, AIC32X4_NADC);
-                       snd_soc_write(codec, AIC32X4_NADC,
-                                     value & ~AIC32X4_NDACEN);
+                       snd_soc_update_bits(codec, AIC32X4_NADC,
+                                           AIC32X4_NADCEN, 0);
 
                        /* Switch off MADC Divider */
-                       value = snd_soc_read(codec, AIC32X4_MADC);
-                       snd_soc_write(codec, AIC32X4_MADC,
-                                     value & ~AIC32X4_MDACEN);
-                       value = snd_soc_read(codec, AIC32X4_BCLKN);
+                       snd_soc_update_bits(codec, AIC32X4_MADC,
+                                           AIC32X4_MADCEN, 0);
 
                        /* Switch off BCLK_N Divider */
-                       snd_soc_write(codec, AIC32X4_BCLKN,
-                                     value & ~AIC32X4_BCLKEN);
+                       snd_soc_update_bits(codec, AIC32X4_BCLKN,
+                                           AIC32X4_BCLKEN, 0);
                }
                break;
        case SND_SOC_BIAS_OFF:
@@ -685,10 +672,10 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
        }
 
        /* Mic PGA routing */
-       if (aic32x4->micpga_routing | AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) {
+       if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) {
                snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_IN2R_10K);
        }
-       if (aic32x4->micpga_routing | AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) {
+       if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) {
                snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_IN1L_10K);
        }
 
index 0963c4c..7a49390 100644 (file)
@@ -76,7 +76,6 @@ struct aic3x_priv {
        struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES];
        enum snd_soc_control_type control_type;
        struct aic3x_setup_data *setup;
-       void *control_data;
        unsigned int sysclk;
        struct list_head list;
        int master;
@@ -138,7 +137,10 @@ static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
        if (reg >= AIC3X_CACHEREGNUM)
                return -1;
 
-       *value = codec->hw_read(codec, reg);
+       codec->cache_bypass = 1;
+       *value = snd_soc_read(codec, reg);
+       codec->cache_bypass = 0;
+
        cache[reg] = *value;
 
        return 0;
@@ -198,6 +200,10 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
                        else
                                /* old connection must be powered down */
                                path->connect = invert ? 1 : 0;
+
+                       dapm_mark_dirty(path->source, "tlv320aic3x source");
+                       dapm_mark_dirty(path->sink, "tlv320aic3x sink");
+
                        break;
                }
 
@@ -1383,7 +1389,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
        int ret, i;
 
        INIT_LIST_HEAD(&aic3x->list);
-       codec->control_data = aic3x->control_data;
        aic3x->codec = codec;
        codec->dapm.idle_bias_off = 1;
 
@@ -1495,9 +1500,9 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
  */
 
 static const struct i2c_device_id aic3x_i2c_id[] = {
-       [AIC3X_MODEL_3X] = { "tlv320aic3x", 0 },
-       [AIC3X_MODEL_33] = { "tlv320aic33", 0 },
-       [AIC3X_MODEL_3007] = { "tlv320aic3007", 0 },
+       { "tlv320aic3x", AIC3X_MODEL_3X },
+       { "tlv320aic33", AIC3X_MODEL_33 },
+       { "tlv320aic3007", AIC3X_MODEL_3007 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
@@ -1512,7 +1517,6 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
        struct aic3x_pdata *pdata = i2c->dev.platform_data;
        struct aic3x_priv *aic3x;
        int ret;
-       const struct i2c_device_id *tbl;
 
        aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
        if (aic3x == NULL) {
@@ -1520,7 +1524,6 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
        }
 
-       aic3x->control_data = i2c;
        aic3x->control_type = SND_SOC_I2C;
 
        i2c_set_clientdata(i2c, aic3x);
@@ -1531,11 +1534,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
                aic3x->gpio_reset = -1;
        }
 
-       for (tbl = aic3x_i2c_id; tbl->name[0]; tbl++) {
-               if (!strcmp(tbl->name, id->name))
-                       break;
-       }
-       aic3x->model = tbl - aic3x_i2c_id;
+       aic3x->model = id->driver_data;
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_aic3x, &aic3x_dai, 1);
index 243d177..dc8a2b2 100644 (file)
 #define BURST_BASEFREQ_HZ      49152000
 
 #define SAMPLES_TO_US(rate, samples) \
-       (1000000000 / ((rate * 1000) / samples))
+       (1000000000 / (((rate) * 1000) / (samples)))
 
 #define US_TO_SAMPLES(rate, us) \
-       (rate / (1000000 / (us < 1000000 ? us : 1000000)))
+       ((rate) / (1000000 / ((us) < 1000000 ? (us) : 1000000)))
 
 #define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \
-       ((samples * 5000) / ((burstrate * 5000) / (burstrate - playrate)))
+       (((samples)*5000) / (((burstrate)*5000) / ((burstrate) - (playrate))))
 
 static void dac33_calculate_times(struct snd_pcm_substream *substream);
 static int dac33_prepare_chip(struct snd_pcm_substream *substream);
@@ -627,18 +627,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"RIGHT_LO", NULL, "Codec Power"},
 };
 
-static int dac33_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_new_controls(dapm, dac33_dapm_widgets,
-                                 ARRAY_SIZE(dac33_dapm_widgets));
-       /* set up audio path interconnects */
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-       return 0;
-}
-
 static int dac33_set_bias_level(struct snd_soc_codec *codec,
                                enum snd_soc_bias_level level)
 {
@@ -1451,15 +1439,11 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
                }
        }
 
-       snd_soc_add_controls(codec, dac33_snd_controls,
-                            ARRAY_SIZE(dac33_snd_controls));
        /* Only add the FIFO controls, if we have valid IRQ number */
        if (dac33->irq >= 0)
                snd_soc_add_controls(codec, dac33_mode_snd_controls,
                                     ARRAY_SIZE(dac33_mode_snd_controls));
 
-       dac33_add_widgets(codec);
-
 err_power:
        return ret;
 }
@@ -1502,6 +1486,13 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = {
        .remove = dac33_soc_remove,
        .suspend = dac33_soc_suspend,
        .resume = dac33_soc_resume,
+
+       .controls = dac33_snd_controls,
+       .num_controls = ARRAY_SIZE(dac33_snd_controls),
+       .dapm_widgets = dac33_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(dac33_dapm_widgets),
+       .dapm_routes = audio_map,
+       .num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 #define DAC33_RATES    (SNDRV_PCM_RATE_44100 | \
index b2572c4..7eeca79 100644 (file)
 
 #include "tpa6130a2.h"
 
+enum tpa_model {
+       TPA6130A2,
+       TPA6140A2,
+};
+
 static struct i2c_client *tpa6130a2_client;
 
 /* This struct is used to save the context */
@@ -383,7 +388,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
 
        pdata = client->dev.platform_data;
        data->power_gpio = pdata->power_gpio;
-       data->id = pdata->id;
+       data->id = id->driver_data;
 
        mutex_init(&data->mutex);
 
@@ -405,7 +410,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
        switch (data->id) {
        default:
                dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n",
-                        pdata->id);
+                        data->id);
        case TPA6130A2:
                regulator = "Vdd";
                break;
@@ -469,7 +474,8 @@ static int __devexit tpa6130a2_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id tpa6130a2_id[] = {
-       { "tpa6130a2", 0 },
+       { "tpa6130a2", TPA6130A2 },
+       { "tpa6140a2", TPA6140A2 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, tpa6130a2_id);
index 71674be..f798247 100644 (file)
@@ -863,34 +863,6 @@ static int digimic_event(struct snd_soc_dapm_widget *w,
  * Inverting not going to help with these.
  * Custom volsw and volsw_2r get/put functions to handle these gain bits.
  */
-#define SOC_DOUBLE_TLV_TWL4030(xname, xreg, shift_left, shift_right, xmax,\
-                              xinvert, tlv_array) \
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
-       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
-                SNDRV_CTL_ELEM_ACCESS_READWRITE,\
-       .tlv.p = (tlv_array), \
-       .info = snd_soc_info_volsw, \
-       .get = snd_soc_get_volsw_twl4030, \
-       .put = snd_soc_put_volsw_twl4030, \
-       .private_value = (unsigned long)&(struct soc_mixer_control) \
-               {.reg = xreg, .shift = shift_left, .rshift = shift_right,\
-                .max = xmax, .invert = xinvert} }
-#define SOC_DOUBLE_R_TLV_TWL4030(xname, reg_left, reg_right, xshift, xmax,\
-                                xinvert, tlv_array) \
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
-       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
-                SNDRV_CTL_ELEM_ACCESS_READWRITE,\
-       .tlv.p = (tlv_array), \
-       .info = snd_soc_info_volsw_2r, \
-       .get = snd_soc_get_volsw_r2_twl4030,\
-       .put = snd_soc_put_volsw_r2_twl4030, \
-       .private_value = (unsigned long)&(struct soc_mixer_control) \
-               {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
-                .rshift = xshift, .max = xmax, .invert = xinvert} }
-#define SOC_SINGLE_TLV_TWL4030(xname, xreg, xshift, xmax, xinvert, tlv_array) \
-       SOC_DOUBLE_TLV_TWL4030(xname, xreg, xshift, xshift, xmax, \
-                              xinvert, tlv_array)
-
 static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
@@ -1197,19 +1169,23 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
                TWL4030_REG_VDL_APGA_CTL, 1, 1, 0),
 
        /* Separate output gain controls */
-       SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume",
+       SOC_DOUBLE_R_EXT_TLV("PreDriv Playback Volume",
                TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL,
-               4, 3, 0, output_tvl),
+               4, 3, 0, snd_soc_get_volsw_r2_twl4030,
+               snd_soc_put_volsw_r2_twl4030, output_tvl),
 
-       SOC_DOUBLE_TLV_TWL4030("Headset Playback Volume",
-               TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, output_tvl),
+       SOC_DOUBLE_EXT_TLV("Headset Playback Volume",
+               TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, snd_soc_get_volsw_twl4030,
+               snd_soc_put_volsw_twl4030, output_tvl),
 
-       SOC_DOUBLE_R_TLV_TWL4030("Carkit Playback Volume",
+       SOC_DOUBLE_R_EXT_TLV("Carkit Playback Volume",
                TWL4030_REG_PRECKL_CTL, TWL4030_REG_PRECKR_CTL,
-               4, 3, 0, output_tvl),
+               4, 3, 0, snd_soc_get_volsw_r2_twl4030,
+               snd_soc_put_volsw_r2_twl4030, output_tvl),
 
-       SOC_SINGLE_TLV_TWL4030("Earpiece Playback Volume",
-               TWL4030_REG_EAR_CTL, 4, 3, 0, output_ear_tvl),
+       SOC_SINGLE_EXT_TLV("Earpiece Playback Volume",
+               TWL4030_REG_EAR_CTL, 4, 3, 0, snd_soc_get_volsw_twl4030,
+               snd_soc_put_volsw_twl4030, output_ear_tvl),
 
        /* Common capture gain controls */
        SOC_DOUBLE_R_TLV("TX1 Digital Capture Volume",
@@ -1633,17 +1609,6 @@ static const struct snd_soc_dapm_route intercon[] = {
 
 };
 
-static int twl4030_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_new_controls(dapm, twl4030_dapm_widgets,
-                                ARRAY_SIZE(twl4030_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
-
-       return 0;
-}
-
 static int twl4030_set_bias_level(struct snd_soc_codec *codec,
                                  enum snd_soc_bias_level level)
 {
@@ -2265,9 +2230,6 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
 
        twl4030_init_chip(codec);
 
-       snd_soc_add_controls(codec, twl4030_snd_controls,
-                               ARRAY_SIZE(twl4030_snd_controls));
-       twl4030_add_widgets(codec);
        return 0;
 }
 
@@ -2293,6 +2255,13 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
        .reg_cache_size = sizeof(twl4030_reg),
        .reg_word_size = sizeof(u8),
        .reg_cache_default = twl4030_reg,
+
+       .controls = twl4030_snd_controls,
+       .num_controls = ARRAY_SIZE(twl4030_snd_controls),
+       .dapm_widgets = twl4030_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(twl4030_dapm_widgets),
+       .dapm_routes = intercon,
+       .num_dapm_routes = ARRAY_SIZE(intercon),
 };
 
 static int __devinit twl4030_codec_probe(struct platform_device *pdev)
index 81645c6..73e11f0 100644 (file)
 #define TWL6040_HF_VOL_MASK    0x1F
 #define TWL6040_HF_VOL_SHIFT   0
 
+/* Shadow register used by the driver */
+#define TWL6040_REG_SW_SHADOW  0x2F
+#define TWL6040_CACHEREGNUM    (TWL6040_REG_SW_SHADOW + 1)
+
+/* TWL6040_REG_SW_SHADOW (0x2F) fields */
+#define TWL6040_EAR_PATH_ENABLE        0x01
+
 struct twl6040_output {
        u16 active;
        u16 left_vol;
@@ -65,12 +72,13 @@ struct twl6040_output {
        u16 right_step;
        unsigned int step_delay;
        u16 ramp;
-       u16 mute;
+       struct delayed_work work;
        struct completion ramp_done;
 };
 
 struct twl6040_jack_data {
        struct snd_soc_jack *jack;
+       struct delayed_work work;
        int report;
 };
 
@@ -79,7 +87,6 @@ struct twl6040_data {
        int plug_irq;
        int codec_powered;
        int pll;
-       int non_lp;
        int pll_power_mode;
        int hs_power_mode;
        int hs_power_mode_locked;
@@ -92,67 +99,64 @@ struct twl6040_data {
        struct twl6040_jack_data hs_jack;
        struct snd_soc_codec *codec;
        struct workqueue_struct *workqueue;
-       struct delayed_work delayed_work;
        struct mutex mutex;
        struct twl6040_output headset;
        struct twl6040_output handsfree;
-       struct workqueue_struct *hf_workqueue;
-       struct workqueue_struct *hs_workqueue;
-       struct delayed_work hs_delayed_work;
-       struct delayed_work hf_delayed_work;
 };
 
 /*
  * twl6040 register cache & default register settings
  */
 static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = {
-       0x00, /* not used               0x00    */
-       0x4B, /* TWL6040_ASICID (ro)    0x01    */
-       0x00, /* TWL6040_ASICREV (ro)   0x02    */
-       0x00, /* TWL6040_INTID          0x03    */
-       0x00, /* TWL6040_INTMR          0x04    */
-       0x00, /* TWL6040_NCPCTRL        0x05    */
-       0x00, /* TWL6040_LDOCTL         0x06    */
-       0x60, /* TWL6040_HPPLLCTL       0x07    */
-       0x00, /* TWL6040_LPPLLCTL       0x08    */
-       0x4A, /* TWL6040_LPPLLDIV       0x09    */
-       0x00, /* TWL6040_AMICBCTL       0x0A    */
-       0x00, /* TWL6040_DMICBCTL       0x0B    */
-       0x00, /* TWL6040_MICLCTL        0x0C    */
-       0x00, /* TWL6040_MICRCTL        0x0D    */
-       0x00, /* TWL6040_MICGAIN        0x0E    */
-       0x1B, /* TWL6040_LINEGAIN       0x0F    */
-       0x00, /* TWL6040_HSLCTL         0x10    */
-       0x00, /* TWL6040_HSRCTL         0x11    */
-       0x00, /* TWL6040_HSGAIN         0x12    */
-       0x00, /* TWL6040_EARCTL         0x13    */
-       0x00, /* TWL6040_HFLCTL         0x14    */
-       0x00, /* TWL6040_HFLGAIN        0x15    */
-       0x00, /* TWL6040_HFRCTL         0x16    */
-       0x00, /* TWL6040_HFRGAIN        0x17    */
-       0x00, /* TWL6040_VIBCTLL        0x18    */
-       0x00, /* TWL6040_VIBDATL        0x19    */
-       0x00, /* TWL6040_VIBCTLR        0x1A    */
-       0x00, /* TWL6040_VIBDATR        0x1B    */
-       0x00, /* TWL6040_HKCTL1         0x1C    */
-       0x00, /* TWL6040_HKCTL2         0x1D    */
-       0x00, /* TWL6040_GPOCTL         0x1E    */
-       0x00, /* TWL6040_ALB            0x1F    */
-       0x00, /* TWL6040_DLB            0x20    */
-       0x00, /* not used               0x21    */
-       0x00, /* not used               0x22    */
-       0x00, /* not used               0x23    */
-       0x00, /* not used               0x24    */
-       0x00, /* not used               0x25    */
-       0x00, /* not used               0x26    */
-       0x00, /* not used               0x27    */
-       0x00, /* TWL6040_TRIM1          0x28    */
-       0x00, /* TWL6040_TRIM2          0x29    */
-       0x00, /* TWL6040_TRIM3          0x2A    */
-       0x00, /* TWL6040_HSOTRIM        0x2B    */
-       0x00, /* TWL6040_HFOTRIM        0x2C    */
-       0x09, /* TWL6040_ACCCTL         0x2D    */
-       0x00, /* TWL6040_STATUS (ro)    0x2E    */
+       0x00, /* not used       0x00    */
+       0x4B, /* REG_ASICID     0x01 (ro) */
+       0x00, /* REG_ASICREV    0x02 (ro) */
+       0x00, /* REG_INTID      0x03    */
+       0x00, /* REG_INTMR      0x04    */
+       0x00, /* REG_NCPCTRL    0x05    */
+       0x00, /* REG_LDOCTL     0x06    */
+       0x60, /* REG_HPPLLCTL   0x07    */
+       0x00, /* REG_LPPLLCTL   0x08    */
+       0x4A, /* REG_LPPLLDIV   0x09    */
+       0x00, /* REG_AMICBCTL   0x0A    */
+       0x00, /* REG_DMICBCTL   0x0B    */
+       0x00, /* REG_MICLCTL    0x0C    */
+       0x00, /* REG_MICRCTL    0x0D    */
+       0x00, /* REG_MICGAIN    0x0E    */
+       0x1B, /* REG_LINEGAIN   0x0F    */
+       0x00, /* REG_HSLCTL     0x10    */
+       0x00, /* REG_HSRCTL     0x11    */
+       0x00, /* REG_HSGAIN     0x12    */
+       0x00, /* REG_EARCTL     0x13    */
+       0x00, /* REG_HFLCTL     0x14    */
+       0x00, /* REG_HFLGAIN    0x15    */
+       0x00, /* REG_HFRCTL     0x16    */
+       0x00, /* REG_HFRGAIN    0x17    */
+       0x00, /* REG_VIBCTLL    0x18    */
+       0x00, /* REG_VIBDATL    0x19    */
+       0x00, /* REG_VIBCTLR    0x1A    */
+       0x00, /* REG_VIBDATR    0x1B    */
+       0x00, /* REG_HKCTL1     0x1C    */
+       0x00, /* REG_HKCTL2     0x1D    */
+       0x00, /* REG_GPOCTL     0x1E    */
+       0x00, /* REG_ALB        0x1F    */
+       0x00, /* REG_DLB        0x20    */
+       0x00, /* not used       0x21    */
+       0x00, /* not used       0x22    */
+       0x00, /* not used       0x23    */
+       0x00, /* not used       0x24    */
+       0x00, /* not used       0x25    */
+       0x00, /* not used       0x26    */
+       0x00, /* not used       0x27    */
+       0x00, /* REG_TRIM1      0x28    */
+       0x00, /* REG_TRIM2      0x29    */
+       0x00, /* REG_TRIM3      0x2A    */
+       0x00, /* REG_HSOTRIM    0x2B    */
+       0x00, /* REG_HFOTRIM    0x2C    */
+       0x09, /* REG_ACCCTL     0x2D    */
+       0x00, /* REG_STATUS     0x2E (ro) */
+
+       0x00, /* REG_SW_SHADOW  0x2F - Shadow, non HW register */
 };
 
 /* List of registers to be restored after power up */
@@ -236,8 +240,12 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
        if (reg >= TWL6040_CACHEREGNUM)
                return -EIO;
 
-       value = twl6040_reg_read(twl6040, reg);
-       twl6040_write_reg_cache(codec, reg, value);
+       if (likely(reg < TWL6040_REG_SW_SHADOW)) {
+               value = twl6040_reg_read(twl6040, reg);
+               twl6040_write_reg_cache(codec, reg, value);
+       } else {
+               value = twl6040_read_reg_cache(codec, reg);
+       }
 
        return value;
 }
@@ -254,7 +262,10 @@ static int twl6040_write(struct snd_soc_codec *codec,
                return -EIO;
 
        twl6040_write_reg_cache(codec, reg, value);
-       return twl6040_reg_write(twl6040, reg, value);
+       if (likely(reg < TWL6040_REG_SW_SHADOW))
+               return twl6040_reg_write(twl6040, reg, value);
+       else
+               return 0;
 }
 
 static void twl6040_init_chip(struct snd_soc_codec *codec)
@@ -262,13 +273,31 @@ static void twl6040_init_chip(struct snd_soc_codec *codec)
        struct twl6040 *twl6040 = codec->control_data;
        u8 val;
 
+       /* Update reg_cache: ASICREV, and TRIM values */
        val = twl6040_get_revid(twl6040);
        twl6040_write_reg_cache(codec, TWL6040_REG_ASICREV, val);
 
+       twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM1);
+       twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM2);
+       twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM3);
+       twl6040_read_reg_volatile(codec, TWL6040_REG_HSOTRIM);
+       twl6040_read_reg_volatile(codec, TWL6040_REG_HFOTRIM);
+
        /* Change chip defaults */
        /* No imput selected for microphone amplifiers */
        twl6040_write_reg_cache(codec, TWL6040_REG_MICLCTL, 0x18);
        twl6040_write_reg_cache(codec, TWL6040_REG_MICRCTL, 0x18);
+
+       /*
+        * We need to lower the default gain values, so the ramp code
+        * can work correctly for the first playback.
+        * This reduces the pop noise heard at the first playback.
+        */
+       twl6040_write_reg_cache(codec, TWL6040_REG_HSGAIN, 0xff);
+       twl6040_write_reg_cache(codec, TWL6040_REG_EARCTL, 0x1e);
+       twl6040_write_reg_cache(codec, TWL6040_REG_HFLGAIN, 0x1d);
+       twl6040_write_reg_cache(codec, TWL6040_REG_HFRGAIN, 0x1d);
+       twl6040_write_reg_cache(codec, TWL6040_REG_LINEGAIN, 0);
 }
 
 static void twl6040_restore_regs(struct snd_soc_codec *codec)
@@ -456,18 +485,17 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
 static void twl6040_pga_hs_work(struct work_struct *work)
 {
        struct twl6040_data *priv =
-               container_of(work, struct twl6040_data, hs_delayed_work.work);
+               container_of(work, struct twl6040_data, headset.work.work);
        struct snd_soc_codec *codec = priv->codec;
        struct twl6040_output *headset = &priv->headset;
-       unsigned int delay = headset->step_delay;
        int i, headset_complete;
 
        /* do we need to ramp at all ? */
        if (headset->ramp == TWL6040_RAMP_NONE)
                return;
 
-       /* HS PGA volumes have 4 bits of resolution to ramp */
-       for (i = 0; i <= 16; i++) {
+       /* HS PGA gain range: 0x0 - 0xf (0 - 15) */
+       for (i = 0; i < 16; i++) {
                headset_complete = twl6040_hs_ramp_step(codec,
                                                headset->left_step,
                                                headset->right_step);
@@ -476,15 +504,8 @@ static void twl6040_pga_hs_work(struct work_struct *work)
                if (headset_complete)
                        break;
 
-               /*
-                * TODO: tune: delay is longer over 0dB
-                * as increases are larger.
-                */
-               if (i >= 8)
-                       schedule_timeout_interruptible(msecs_to_jiffies(delay +
-                                                       (delay >> 1)));
-               else
-                       schedule_timeout_interruptible(msecs_to_jiffies(delay));
+               schedule_timeout_interruptible(
+                               msecs_to_jiffies(headset->step_delay));
        }
 
        if (headset->ramp == TWL6040_RAMP_DOWN) {
@@ -499,18 +520,18 @@ static void twl6040_pga_hs_work(struct work_struct *work)
 static void twl6040_pga_hf_work(struct work_struct *work)
 {
        struct twl6040_data *priv =
-               container_of(work, struct twl6040_data, hf_delayed_work.work);
+               container_of(work, struct twl6040_data, handsfree.work.work);
        struct snd_soc_codec *codec = priv->codec;
        struct twl6040_output *handsfree = &priv->handsfree;
-       unsigned int delay = handsfree->step_delay;
        int i, handsfree_complete;
 
        /* do we need to ramp at all ? */
        if (handsfree->ramp == TWL6040_RAMP_NONE)
                return;
 
-       /* HF PGA volumes have 5 bits of resolution to ramp */
-       for (i = 0; i <= 32; i++) {
+       /*
+        * HF PGA gain range: 0x00 - 0x1d (0 - 29) */
+       for (i = 0; i < 30; i++) {
                handsfree_complete = twl6040_hf_ramp_step(codec,
                                                handsfree->left_step,
                                                handsfree->right_step);
@@ -519,15 +540,8 @@ static void twl6040_pga_hf_work(struct work_struct *work)
                if (handsfree_complete)
                        break;
 
-               /*
-                * TODO: tune: delay is longer over 0dB
-                * as increases are larger.
-                */
-               if (i >= 16)
-                       schedule_timeout_interruptible(msecs_to_jiffies(delay +
-                                                      (delay >> 1)));
-               else
-                       schedule_timeout_interruptible(msecs_to_jiffies(delay));
+               schedule_timeout_interruptible(
+                               msecs_to_jiffies(handsfree->step_delay));
        }
 
 
@@ -539,36 +553,40 @@ static void twl6040_pga_hf_work(struct work_struct *work)
        handsfree->ramp = TWL6040_RAMP_NONE;
 }
 
-static int pga_event(struct snd_soc_dapm_widget *w,
+static int out_drv_event(struct snd_soc_dapm_widget *w,
                        struct snd_kcontrol *kcontrol, int event)
 {
        struct snd_soc_codec *codec = w->codec;
        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
        struct twl6040_output *out;
        struct delayed_work *work;
-       struct workqueue_struct *queue;
 
        switch (w->shift) {
-       case 2:
-       case 3:
+       case 2: /* Headset output driver */
                out = &priv->headset;
-               work = &priv->hs_delayed_work;
-               queue = priv->hs_workqueue;
+               work = &out->work;
+               /*
+                * Make sure, that we do not mess up variables for already
+                * executing work.
+                */
+               cancel_delayed_work_sync(work);
+
                out->left_step = priv->hs_left_step;
                out->right_step = priv->hs_right_step;
                out->step_delay = 5;    /* 5 ms between volume ramp steps */
                break;
-       case 4:
+       case 4: /* Handsfree output driver */
                out = &priv->handsfree;
-               work = &priv->hf_delayed_work;
-               queue = priv->hf_workqueue;
+               work = &out->work;
+               /*
+                * Make sure, that we do not mess up variables for already
+                * executing work.
+                */
+               cancel_delayed_work_sync(work);
+
                out->left_step = priv->hf_left_step;
                out->right_step = priv->hf_right_step;
                out->step_delay = 5;    /* 5 ms between volume ramp steps */
-               if (SND_SOC_DAPM_EVENT_ON(event))
-                       priv->non_lp++;
-               else
-                       priv->non_lp--;
                break;
        default:
                return -1;
@@ -580,31 +598,25 @@ static int pga_event(struct snd_soc_dapm_widget *w,
                        break;
 
                /* don't use volume ramp for power-up */
+               out->ramp = TWL6040_RAMP_UP;
                out->left_step = out->left_vol;
                out->right_step = out->right_vol;
 
-               if (!delayed_work_pending(work)) {
-                       out->ramp = TWL6040_RAMP_UP;
-                       queue_delayed_work(queue, work,
-                                       msecs_to_jiffies(1));
-               }
+               queue_delayed_work(priv->workqueue, work, msecs_to_jiffies(1));
                break;
 
        case SND_SOC_DAPM_PRE_PMD:
                if (!out->active)
                        break;
 
-               if (!delayed_work_pending(work)) {
-                       /* use volume ramp for power-down */
-                       out->ramp = TWL6040_RAMP_DOWN;
-                       INIT_COMPLETION(out->ramp_done);
+               /* use volume ramp for power-down */
+               out->ramp = TWL6040_RAMP_DOWN;
+               INIT_COMPLETION(out->ramp_done);
 
-                       queue_delayed_work(queue, work,
-                                       msecs_to_jiffies(1));
+               queue_delayed_work(priv->workqueue, work, msecs_to_jiffies(1));
 
-                       wait_for_completion_timeout(&out->ramp_done,
-                                       msecs_to_jiffies(2000));
-               }
+               wait_for_completion_timeout(&out->ramp_done,
+                                           msecs_to_jiffies(2000));
                break;
        }
 
@@ -615,7 +627,7 @@ static int pga_event(struct snd_soc_dapm_widget *w,
 static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
 {
        int hslctl, hsrctl;
-       int mask = TWL6040_HSDRVMODEL | TWL6040_HSDACMODEL;
+       int mask = TWL6040_HSDRVMODE | TWL6040_HSDACMODE;
 
        hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL);
        hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL);
@@ -637,11 +649,31 @@ static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
 static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w,
                        struct snd_kcontrol *kcontrol, int event)
 {
+       struct snd_soc_codec *codec = w->codec;
+       u8 hslctl, hsrctl;
+
+       /*
+        * Workaround for Headset DC offset caused pop noise:
+        * Both HS DAC need to be turned on (before the HS driver) and off at
+        * the same time.
+        */
+       hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL);
+       hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL);
+       if (SND_SOC_DAPM_EVENT_ON(event)) {
+               hslctl |= TWL6040_HSDACENA;
+               hsrctl |= TWL6040_HSDACENA;
+       } else {
+               hslctl &= ~TWL6040_HSDACENA;
+               hsrctl &= ~TWL6040_HSDACENA;
+       }
+       twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl);
+       twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl);
+
        msleep(1);
        return 0;
 }
 
-static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
+static int twl6040_ep_drv_event(struct snd_soc_dapm_widget *w,
                        struct snd_kcontrol *kcontrol, int event)
 {
        struct snd_soc_codec *codec = w->codec;
@@ -649,18 +681,12 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
        int ret = 0;
 
        if (SND_SOC_DAPM_EVENT_ON(event)) {
-               priv->non_lp++;
-               if (!strcmp(w->name, "Earphone Driver")) {
-                       /* Earphone doesn't support low power mode */
-                       priv->hs_power_mode_locked = 1;
-                       ret = headset_power_mode(codec, 1);
-               }
+               /* Earphone doesn't support low power mode */
+               priv->hs_power_mode_locked = 1;
+               ret = headset_power_mode(codec, 1);
        } else {
-               priv->non_lp--;
-               if (!strcmp(w->name, "Earphone Driver")) {
-                       priv->hs_power_mode_locked = 0;
-                       ret = headset_power_mode(codec, priv->hs_power_mode);
-               }
+               priv->hs_power_mode_locked = 0;
+               ret = headset_power_mode(codec, priv->hs_power_mode);
        }
 
        msleep(1);
@@ -702,7 +728,7 @@ EXPORT_SYMBOL_GPL(twl6040_hs_jack_detect);
 static void twl6040_accessory_work(struct work_struct *work)
 {
        struct twl6040_data *priv = container_of(work,
-                                       struct twl6040_data, delayed_work.work);
+                                       struct twl6040_data, hs_jack.work.work);
        struct snd_soc_codec *codec = priv->codec;
        struct twl6040_jack_data *hs_jack = &priv->hs_jack;
 
@@ -713,15 +739,10 @@ static void twl6040_accessory_work(struct work_struct *work)
 static irqreturn_t twl6040_audio_handler(int irq, void *data)
 {
        struct snd_soc_codec *codec = data;
-       struct twl6040 *twl6040 = codec->control_data;
        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
-       u8 intid;
 
-       intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
-
-       if ((intid & TWL6040_PLUGINT) || (intid & TWL6040_UNPLUGINT))
-               queue_delayed_work(priv->workqueue, &priv->delayed_work,
-                                                       msecs_to_jiffies(200));
+       queue_delayed_work(priv->workqueue, &priv->hs_jack.work,
+                          msecs_to_jiffies(200));
 
        return IRQ_HANDLED;
 }
@@ -735,25 +756,27 @@ static int twl6040_put_volsw(struct snd_kcontrol *kcontrol,
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
        int ret;
-       unsigned int reg = mc->reg;
 
        /* For HS and HF we shadow the values and only actually write
         * them out when active in order to ensure the amplifier comes on
         * as quietly as possible. */
-       switch (reg) {
+       switch (mc->reg) {
        case TWL6040_REG_HSGAIN:
                out = &twl6040_priv->headset;
                break;
-       default:
+       case TWL6040_REG_HFLGAIN:
+               out = &twl6040_priv->handsfree;
                break;
+       default:
+               dev_warn(codec->dev, "%s: Unexpected register: 0x%02x\n",
+                                       __func__, mc->reg);
+               return -EINVAL;
        }
 
-       if (out) {
-               out->left_vol = ucontrol->value.integer.value[0];
-               out->right_vol = ucontrol->value.integer.value[1];
-               if (!out->active)
-                       return 1;
-       }
+       out->left_vol = ucontrol->value.integer.value[0];
+       out->right_vol = ucontrol->value.integer.value[1];
+       if (!out->active)
+               return 1;
 
        ret = snd_soc_put_volsw(kcontrol, ucontrol);
        if (ret < 0)
@@ -770,112 +793,42 @@ static int twl6040_get_volsw(struct snd_kcontrol *kcontrol,
        struct twl6040_output *out = &twl6040_priv->headset;
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
-       unsigned int reg = mc->reg;
 
-       switch (reg) {
+       switch (mc->reg) {
        case TWL6040_REG_HSGAIN:
                out = &twl6040_priv->headset;
-               ucontrol->value.integer.value[0] = out->left_vol;
-               ucontrol->value.integer.value[1] = out->right_vol;
-               return 0;
-
-       default:
                break;
-       }
-
-       return snd_soc_get_volsw(kcontrol, ucontrol);
-}
-
-static int twl6040_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
-                                 struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
-       struct twl6040_output *out = NULL;
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       int ret;
-       unsigned int reg = mc->reg;
-
-       /* For HS and HF we shadow the values and only actually write
-        * them out when active in order to ensure the amplifier comes on
-        * as quietly as possible. */
-       switch (reg) {
        case TWL6040_REG_HFLGAIN:
-       case TWL6040_REG_HFRGAIN:
                out = &twl6040_priv->handsfree;
                break;
        default:
-               break;
-       }
-
-       if (out) {
-               out->left_vol = ucontrol->value.integer.value[0];
-               out->right_vol = ucontrol->value.integer.value[1];
-               if (!out->active)
-                       return 1;
+               dev_warn(codec->dev, "%s: Unexpected register: 0x%02x\n",
+                                       __func__, mc->reg);
+               return -EINVAL;
        }
 
-       ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
-       if (ret < 0)
-               return ret;
-
-       return 1;
+       ucontrol->value.integer.value[0] = out->left_vol;
+       ucontrol->value.integer.value[1] = out->right_vol;
+       return 0;
 }
 
-static int twl6040_get_volsw_2r(struct snd_kcontrol *kcontrol,
-                               struct snd_ctl_elem_value *ucontrol)
+static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
-       struct twl6040_output *out = &twl6040_priv->handsfree;
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       unsigned int reg = mc->reg;
-
-       /* If these are cached registers use the cache */
-       switch (reg) {
-       case TWL6040_REG_HFLGAIN:
-       case TWL6040_REG_HFRGAIN:
-               out = &twl6040_priv->handsfree;
-               ucontrol->value.integer.value[0] = out->left_vol;
-               ucontrol->value.integer.value[1] = out->right_vol;
-               return 0;
-
-       default:
-               break;
-       }
-
-       return snd_soc_get_volsw_2r(kcontrol, ucontrol);
+       struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+       struct snd_soc_codec *codec = widget->codec;
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+       unsigned int val;
+
+       /* Do not allow changes while Input/FF efect is running */
+       val = twl6040_read_reg_volatile(codec, e->reg);
+       if (val & TWL6040_VIBENA && !(val & TWL6040_VIBSEL))
+               return -EBUSY;
+
+       return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
 }
 
-/* double control with volume update */
-#define SOC_TWL6040_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax,\
-                                                       xinvert, tlv_array)\
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
-       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
-                SNDRV_CTL_ELEM_ACCESS_READWRITE,\
-       .tlv.p = (tlv_array), \
-       .info = snd_soc_info_volsw, .get = twl6040_get_volsw, \
-       .put = twl6040_put_volsw, \
-       .private_value = (unsigned long)&(struct soc_mixer_control) \
-               {.reg = xreg, .shift = shift_left, .rshift = shift_right,\
-                .max = xmax, .platform_max = xmax, .invert = xinvert} }
-
-/* double control with volume update */
-#define SOC_TWL6040_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax,\
-                               xinvert, tlv_array)\
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
-       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
-               SNDRV_CTL_ELEM_ACCESS_READWRITE | \
-               SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
-       .tlv.p = (tlv_array), \
-       .info = snd_soc_info_volsw_2r, \
-       .get = twl6040_get_volsw_2r, .put = twl6040_put_volsw_2r_vu, \
-       .private_value = (unsigned long)&(struct soc_mixer_control) \
-               {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
-                .rshift = xshift, .max = xmax, .invert = xinvert}, }
-
 /*
  * MICATT volume control:
  * from -6 to 0 dB in 6 dB steps
@@ -947,6 +900,19 @@ static const struct soc_enum twl6040_hf_enum[] = {
                        twl6040_hf_texts),
 };
 
+static const char *twl6040_vibrapath_texts[] = {
+       "Input FF", "Audio PDM"
+};
+
+static const struct soc_enum twl6040_vibra_enum[] = {
+       SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLL, 1,
+                       ARRAY_SIZE(twl6040_vibrapath_texts),
+                       twl6040_vibrapath_texts),
+       SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLR, 1,
+                       ARRAY_SIZE(twl6040_vibrapath_texts),
+                       twl6040_vibrapath_texts),
+};
+
 static const struct snd_kcontrol_new amicl_control =
        SOC_DAPM_ENUM("Route", twl6040_enum[0]);
 
@@ -967,8 +933,25 @@ static const struct snd_kcontrol_new hfl_mux_controls =
 static const struct snd_kcontrol_new hfr_mux_controls =
        SOC_DAPM_ENUM("Route", twl6040_hf_enum[1]);
 
-static const struct snd_kcontrol_new ep_driver_switch_controls =
-       SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0);
+static const struct snd_kcontrol_new ep_path_enable_control =
+       SOC_DAPM_SINGLE("Switch", TWL6040_REG_SW_SHADOW, 0, 1, 0);
+
+static const struct snd_kcontrol_new auxl_switch_control =
+       SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 6, 1, 0);
+
+static const struct snd_kcontrol_new auxr_switch_control =
+       SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 6, 1, 0);
+
+/* Vibra playback switches */
+static const struct snd_kcontrol_new vibral_mux_controls =
+       SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[0],
+               snd_soc_dapm_get_enum_double,
+               twl6040_soc_dapm_put_vibra_enum);
+
+static const struct snd_kcontrol_new vibrar_mux_controls =
+       SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[1],
+               snd_soc_dapm_get_enum_double,
+               twl6040_soc_dapm_put_vibra_enum);
 
 /* Headset power mode */
 static const char *twl6040_power_mode_texts[] = {
@@ -1037,6 +1020,15 @@ int twl6040_get_clk_id(struct snd_soc_codec *codec)
 }
 EXPORT_SYMBOL_GPL(twl6040_get_clk_id);
 
+int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim)
+{
+       if (unlikely(trim >= TWL6040_TRIM_INVAL))
+               return -EINVAL;
+
+       return twl6040_read_reg_cache(codec, TWL6040_REG_TRIM1 + trim);
+}
+EXPORT_SYMBOL_GPL(twl6040_get_trim_value);
+
 static const struct snd_kcontrol_new twl6040_snd_controls[] = {
        /* Capture gains */
        SOC_DOUBLE_TLV("Capture Preamplifier Volume",
@@ -1049,10 +1041,12 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = {
                TWL6040_REG_LINEGAIN, 0, 3, 7, 0, afm_amp_tlv),
 
        /* Playback gains */
-       SOC_TWL6040_DOUBLE_TLV("Headset Playback Volume",
-               TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv),
-       SOC_TWL6040_DOUBLE_R_TLV("Handsfree Playback Volume",
-               TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
+       SOC_DOUBLE_EXT_TLV("Headset Playback Volume",
+               TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, twl6040_get_volsw,
+               twl6040_put_volsw, hs_tlv),
+       SOC_DOUBLE_R_EXT_TLV("Handsfree Playback Volume",
+               TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1,
+               twl6040_get_volsw, twl6040_put_volsw, hf_tlv),
        SOC_SINGLE_TLV("Earphone Playback Volume",
                TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv),
 
@@ -1078,6 +1072,10 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
        SND_SOC_DAPM_OUTPUT("HFL"),
        SND_SOC_DAPM_OUTPUT("HFR"),
        SND_SOC_DAPM_OUTPUT("EP"),
+       SND_SOC_DAPM_OUTPUT("AUXL"),
+       SND_SOC_DAPM_OUTPUT("AUXR"),
+       SND_SOC_DAPM_OUTPUT("VIBRAL"),
+       SND_SOC_DAPM_OUTPUT("VIBRAR"),
 
        /* Analog input muxes for the capture amplifiers */
        SND_SOC_DAPM_MUX("Analog Left Capture Route",
@@ -1114,59 +1112,76 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
                        TWL6040_REG_DMICBCTL, 4, 0),
 
        /* DACs */
-       SND_SOC_DAPM_DAC_E("HSDAC Left", "Headset Playback",
-                       TWL6040_REG_HSLCTL, 0, 0,
-                       twl6040_hs_dac_event,
-                       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-       SND_SOC_DAPM_DAC_E("HSDAC Right", "Headset Playback",
-                       TWL6040_REG_HSRCTL, 0, 0,
-                       twl6040_hs_dac_event,
-                       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-       SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback",
-                       TWL6040_REG_HFLCTL, 0, 0,
-                       twl6040_power_mode_event,
-                       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-       SND_SOC_DAPM_DAC_E("HFDAC Right", "Handsfree Playback",
-                       TWL6040_REG_HFRCTL, 0, 0,
-                       twl6040_power_mode_event,
-                       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
-       SND_SOC_DAPM_MUX("HF Left Playback",
+       SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback", SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_DAC("HSDAC Right", "Headset Playback", SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_DAC("HFDAC Left", "Handsfree Playback",
+                        TWL6040_REG_HFLCTL, 0, 0),
+       SND_SOC_DAPM_DAC("HFDAC Right", "Handsfree Playback",
+                        TWL6040_REG_HFRCTL, 0, 0),
+       /* Virtual DAC for vibra path (DL4 channel) */
+       SND_SOC_DAPM_DAC("VIBRA DAC", "Vibra Playback",
+                       SND_SOC_NOPM, 0, 0),
+
+       SND_SOC_DAPM_MUX("Handsfree Left Playback",
                        SND_SOC_NOPM, 0, 0, &hfl_mux_controls),
-       SND_SOC_DAPM_MUX("HF Right Playback",
+       SND_SOC_DAPM_MUX("Handsfree Right Playback",
                        SND_SOC_NOPM, 0, 0, &hfr_mux_controls),
        /* Analog playback Muxes */
-       SND_SOC_DAPM_MUX("HS Left Playback",
+       SND_SOC_DAPM_MUX("Headset Left Playback",
                        SND_SOC_NOPM, 0, 0, &hsl_mux_controls),
-       SND_SOC_DAPM_MUX("HS Right Playback",
+       SND_SOC_DAPM_MUX("Headset Right Playback",
                        SND_SOC_NOPM, 0, 0, &hsr_mux_controls),
 
+       SND_SOC_DAPM_MUX("Vibra Left Playback", SND_SOC_NOPM, 0, 0,
+                       &vibral_mux_controls),
+       SND_SOC_DAPM_MUX("Vibra Right Playback", SND_SOC_NOPM, 0, 0,
+                       &vibrar_mux_controls),
+
+       SND_SOC_DAPM_SWITCH("Earphone Playback", SND_SOC_NOPM, 0, 0,
+                       &ep_path_enable_control),
+       SND_SOC_DAPM_SWITCH("AUXL Playback", SND_SOC_NOPM, 0, 0,
+                       &auxl_switch_control),
+       SND_SOC_DAPM_SWITCH("AUXR Playback", SND_SOC_NOPM, 0, 0,
+                       &auxr_switch_control),
+
        /* Analog playback drivers */
-       SND_SOC_DAPM_OUT_DRV_E("Handsfree Left Driver",
+       SND_SOC_DAPM_OUT_DRV_E("HF Left Driver",
                        TWL6040_REG_HFLCTL, 4, 0, NULL, 0,
-                       pga_event,
+                       out_drv_event,
                        SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-       SND_SOC_DAPM_OUT_DRV_E("Handsfree Right Driver",
+       SND_SOC_DAPM_OUT_DRV_E("HF Right Driver",
                        TWL6040_REG_HFRCTL, 4, 0, NULL, 0,
-                       pga_event,
+                       out_drv_event,
                        SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-       SND_SOC_DAPM_OUT_DRV_E("Headset Left Driver",
+       SND_SOC_DAPM_OUT_DRV_E("HS Left Driver",
                        TWL6040_REG_HSLCTL, 2, 0, NULL, 0,
-                       pga_event,
+                       out_drv_event,
                        SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-       SND_SOC_DAPM_OUT_DRV_E("Headset Right Driver",
+       SND_SOC_DAPM_OUT_DRV_E("HS Right Driver",
                        TWL6040_REG_HSRCTL, 2, 0, NULL, 0,
-                       pga_event,
+                       out_drv_event,
                        SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-       SND_SOC_DAPM_SWITCH_E("Earphone Driver",
-                       SND_SOC_NOPM, 0, 0, &ep_driver_switch_controls,
-                       twl6040_power_mode_event,
-                       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_OUT_DRV_E("Earphone Driver",
+                       TWL6040_REG_EARCTL, 0, 0, NULL, 0,
+                       twl6040_ep_drv_event,
+                       SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_OUT_DRV("Vibra Left Driver",
+                       TWL6040_REG_VIBCTLL, 0, 0, NULL, 0),
+       SND_SOC_DAPM_OUT_DRV("Vibra Right Driver",
+                       TWL6040_REG_VIBCTLR, 0, 0, NULL, 0),
+
+       SND_SOC_DAPM_SUPPLY("Vibra Left Control", TWL6040_REG_VIBCTLL, 2, 0,
+                           NULL, 0),
+       SND_SOC_DAPM_SUPPLY("Vibra Right Control", TWL6040_REG_VIBCTLR, 2, 0,
+                           NULL, 0),
+       SND_SOC_DAPM_SUPPLY_S("HSDAC Power", 1, SND_SOC_NOPM, 0, 0,
+                             twl6040_hs_dac_event,
+                             SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
        /* Analog playback PGAs */
-       SND_SOC_DAPM_PGA("HFDAC Left PGA",
+       SND_SOC_DAPM_PGA("HF Left PGA",
                        TWL6040_REG_HFLCTL, 1, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("HFDAC Right PGA",
+       SND_SOC_DAPM_PGA("HF Right PGA",
                        TWL6040_REG_HFRCTL, 1, 0, NULL, 0),
 
 };
@@ -1188,52 +1203,62 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"ADC Right", NULL, "MicAmpR"},
 
        /* AFM path */
-       {"AFMAmpL", "NULL", "AFML"},
-       {"AFMAmpR", "NULL", "AFMR"},
+       {"AFMAmpL", NULL, "AFML"},
+       {"AFMAmpR", NULL, "AFMR"},
 
-       {"HS Left Playback", "HS DAC", "HSDAC Left"},
-       {"HS Left Playback", "Line-In amp", "AFMAmpL"},
+       {"HSDAC Left", NULL, "HSDAC Power"},
+       {"HSDAC Right", NULL, "HSDAC Power"},
 
-       {"HS Right Playback", "HS DAC", "HSDAC Right"},
-       {"HS Right Playback", "Line-In amp", "AFMAmpR"},
+       {"Headset Left Playback", "HS DAC", "HSDAC Left"},
+       {"Headset Left Playback", "Line-In amp", "AFMAmpL"},
 
-       {"Headset Left Driver", "NULL", "HS Left Playback"},
-       {"Headset Right Driver", "NULL", "HS Right Playback"},
+       {"Headset Right Playback", "HS DAC", "HSDAC Right"},
+       {"Headset Right Playback", "Line-In amp", "AFMAmpR"},
 
-       {"HSOL", NULL, "Headset Left Driver"},
-       {"HSOR", NULL, "Headset Right Driver"},
+       {"HS Left Driver", NULL, "Headset Left Playback"},
+       {"HS Right Driver", NULL, "Headset Right Playback"},
+
+       {"HSOL", NULL, "HS Left Driver"},
+       {"HSOR", NULL, "HS Right Driver"},
 
        /* Earphone playback path */
-       {"Earphone Driver", "Switch", "HSDAC Left"},
+       {"Earphone Playback", "Switch", "HSDAC Left"},
+       {"Earphone Driver", NULL, "Earphone Playback"},
        {"EP", NULL, "Earphone Driver"},
 
-       {"HF Left Playback", "HF DAC", "HFDAC Left"},
-       {"HF Left Playback", "Line-In amp", "AFMAmpL"},
+       {"Handsfree Left Playback", "HF DAC", "HFDAC Left"},
+       {"Handsfree Left Playback", "Line-In amp", "AFMAmpL"},
 
-       {"HF Right Playback", "HF DAC", "HFDAC Right"},
-       {"HF Right Playback", "Line-In amp", "AFMAmpR"},
+       {"Handsfree Right Playback", "HF DAC", "HFDAC Right"},
+       {"Handsfree Right Playback", "Line-In amp", "AFMAmpR"},
 
-       {"HFDAC Left PGA", NULL, "HF Left Playback"},
-       {"HFDAC Right PGA", NULL, "HF Right Playback"},
+       {"HF Left PGA", NULL, "Handsfree Left Playback"},
+       {"HF Right PGA", NULL, "Handsfree Right Playback"},
 
-       {"Handsfree Left Driver", "Switch", "HFDAC Left PGA"},
-       {"Handsfree Right Driver", "Switch", "HFDAC Right PGA"},
+       {"HF Left Driver", NULL, "HF Left PGA"},
+       {"HF Right Driver", NULL, "HF Right PGA"},
 
-       {"HFL", NULL, "Handsfree Left Driver"},
-       {"HFR", NULL, "Handsfree Right Driver"},
-};
+       {"HFL", NULL, "HF Left Driver"},
+       {"HFR", NULL, "HF Right Driver"},
 
-static int twl6040_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
+       {"AUXL Playback", "Switch", "HF Left PGA"},
+       {"AUXR Playback", "Switch", "HF Right PGA"},
 
-       snd_soc_dapm_new_controls(dapm, twl6040_dapm_widgets,
-                                ARRAY_SIZE(twl6040_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
-       snd_soc_dapm_new_widgets(dapm);
+       {"AUXL", NULL, "AUXL Playback"},
+       {"AUXR", NULL, "AUXR Playback"},
 
-       return 0;
-}
+       /* Vibrator paths */
+       {"Vibra Left Playback", "Audio PDM", "VIBRA DAC"},
+       {"Vibra Right Playback", "Audio PDM", "VIBRA DAC"},
+
+       {"Vibra Left Driver", NULL, "Vibra Left Playback"},
+       {"Vibra Right Driver", NULL, "Vibra Right Playback"},
+       {"Vibra Left Driver", NULL, "Vibra Left Control"},
+       {"Vibra Right Driver", NULL, "Vibra Right Control"},
+
+       {"VIBRAL", NULL, "Vibra Left Driver"},
+       {"VIBRAR", NULL, "Vibra Right Driver"},
+};
 
 static int twl6040_set_bias_level(struct snd_soc_codec *codec,
                                enum snd_soc_bias_level level)
@@ -1311,13 +1336,6 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
                                rate);
                        return -EINVAL;
                }
-               /* Capture is not supported with 17.64MHz sysclk */
-               if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
-                       dev_err(codec->dev,
-                               "capture mode is not supported at %dHz\n",
-                               rate);
-                       return -EINVAL;
-               }
                priv->sysclk = 17640000;
                break;
        case 8000:
@@ -1350,13 +1368,6 @@ static int twl6040_prepare(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       if ((priv->sysclk == 17640000) && priv->non_lp) {
-                       dev_err(codec->dev,
-                               "some enabled paths aren't supported at %dHz\n",
-                               priv->sysclk);
-                       return -EPERM;
-       }
-
        ret = twl6040_set_pll(twl6040, priv->pll, priv->clk_in, priv->sysclk);
        if (ret) {
                dev_err(codec->dev, "Can not set PLL (%d)\n", ret);
@@ -1395,7 +1406,7 @@ static struct snd_soc_dai_ops twl6040_dai_ops = {
 
 static struct snd_soc_dai_driver twl6040_dai[] = {
 {
-       .name = "twl6040-hifi",
+       .name = "twl6040-legacy",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -1493,6 +1504,7 @@ static int twl6040_probe(struct snd_soc_codec *codec)
 
        priv->codec = codec;
        codec->control_data = dev_get_drvdata(codec->dev->parent);
+       codec->ignore_pmdown_time = 1;
 
        if (pdata && pdata->hs_left_step && pdata->hs_right_step) {
                priv->hs_left_step = pdata->hs_left_step;
@@ -1517,33 +1529,21 @@ static int twl6040_probe(struct snd_soc_codec *codec)
                goto work_err;
        }
 
-       priv->workqueue = create_singlethread_workqueue("twl6040-codec");
+       priv->workqueue = alloc_workqueue("twl6040-codec", 0, 0);
        if (!priv->workqueue) {
                ret = -ENOMEM;
                goto work_err;
        }
 
-       INIT_DELAYED_WORK(&priv->delayed_work, twl6040_accessory_work);
+       INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work);
+       INIT_DELAYED_WORK(&priv->headset.work, twl6040_pga_hs_work);
+       INIT_DELAYED_WORK(&priv->handsfree.work, twl6040_pga_hf_work);
 
        mutex_init(&priv->mutex);
 
        init_completion(&priv->headset.ramp_done);
        init_completion(&priv->handsfree.ramp_done);
 
-       priv->hf_workqueue = create_singlethread_workqueue("twl6040-hf");
-       if (priv->hf_workqueue == NULL) {
-               ret = -ENOMEM;
-               goto hfwq_err;
-       }
-       priv->hs_workqueue = create_singlethread_workqueue("twl6040-hs");
-       if (priv->hs_workqueue == NULL) {
-               ret = -ENOMEM;
-               goto hswq_err;
-       }
-
-       INIT_DELAYED_WORK(&priv->hs_delayed_work, twl6040_pga_hs_work);
-       INIT_DELAYED_WORK(&priv->hf_delayed_work, twl6040_pga_hf_work);
-
        ret = request_threaded_irq(priv->plug_irq, NULL, twl6040_audio_handler,
                                   0, "twl6040_irq_plug", codec);
        if (ret) {
@@ -1555,22 +1555,12 @@ static int twl6040_probe(struct snd_soc_codec *codec)
 
        /* power on device */
        ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-       if (ret)
-               goto bias_err;
-
-       snd_soc_add_controls(codec, twl6040_snd_controls,
-                               ARRAY_SIZE(twl6040_snd_controls));
-       twl6040_add_widgets(codec);
-
-       return 0;
+       if (!ret)
+               return 0;
 
-bias_err:
+       /* Error path */
        free_irq(priv->plug_irq, codec);
 plugirq_err:
-       destroy_workqueue(priv->hs_workqueue);
-hswq_err:
-       destroy_workqueue(priv->hf_workqueue);
-hfwq_err:
        destroy_workqueue(priv->workqueue);
 work_err:
        kfree(priv);
@@ -1584,8 +1574,6 @@ static int twl6040_remove(struct snd_soc_codec *codec)
        twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
        free_irq(priv->plug_irq, codec);
        destroy_workqueue(priv->workqueue);
-       destroy_workqueue(priv->hf_workqueue);
-       destroy_workqueue(priv->hs_workqueue);
        kfree(priv);
 
        return 0;
@@ -1602,6 +1590,13 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
        .reg_cache_size = ARRAY_SIZE(twl6040_reg),
        .reg_word_size = sizeof(u8),
        .reg_cache_default = twl6040_reg,
+
+       .controls = twl6040_snd_controls,
+       .num_controls = ARRAY_SIZE(twl6040_snd_controls),
+       .dapm_widgets = twl6040_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets),
+       .dapm_routes = intercon,
+       .num_dapm_routes = ARRAY_SIZE(intercon),
 };
 
 static int __devinit twl6040_codec_probe(struct platform_device *pdev)
index d8de678..a83277b 100644 (file)
 #ifndef __TWL6040_H__
 #define __TWL6040_H__
 
+enum twl6040_trim {
+       TWL6040_TRIM_TRIM1 = 0,
+       TWL6040_TRIM_TRIM2,
+       TWL6040_TRIM_TRIM3,
+       TWL6040_TRIM_HSOTRIM,
+       TWL6040_TRIM_HFOTRIM,
+       TWL6040_TRIM_INVAL,
+};
+
+#define TWL6040_HSF_TRIM_LEFT(x)       (x & 0x0f)
+#define TWL6040_HSF_TRIM_RIGHT(x)      ((x >> 4) & 0x0f)
+
 void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
                            struct snd_soc_jack *jack, int report);
 int twl6040_get_clk_id(struct snd_soc_codec *codec);
+int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim);
 
 #endif /* End of __TWL6040_H__ */
index 5836201..9fa1429 100644 (file)
@@ -462,7 +462,6 @@ static int wl1273_probe(struct snd_soc_codec *codec)
        wl1273->core = *core;
 
        snd_soc_codec_set_drvdata(codec, wl1273);
-       mutex_init(&codec->mutex);
 
        r = snd_soc_add_controls(codec, wl1273_controls,
                                 ARRAY_SIZE(wl1273_controls));
index 4523c4c..cd0ec0f 100644 (file)
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/gpio.h>
 
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
+#include <sound/wm1250-ev1.h>
+
+static const char *wm1250_gpio_names[WM1250_EV1_NUM_GPIOS] = {
+       "WM1250 CLK_ENA",
+       "WM1250 CLK_SEL0",
+       "WM1250 CLK_SEL1",
+       "WM1250 OSR",
+       "WM1250 MASTER",
+};
+
+struct wm1250_priv {
+       struct gpio gpios[WM1250_EV1_NUM_GPIOS];
+};
+
+static int wm1250_ev1_set_bias_level(struct snd_soc_codec *codec,
+                                    enum snd_soc_bias_level level)
+{
+       struct wm1250_priv *wm1250 = dev_get_drvdata(codec->dev);
+       int ena;
+
+       if (wm1250)
+               ena = wm1250->gpios[WM1250_EV1_GPIO_CLK_ENA].gpio;
+       else
+               ena = -1;
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               break;
+
+       case SND_SOC_BIAS_PREPARE:
+               break;
+
+       case SND_SOC_BIAS_STANDBY:
+               if (ena >= 0)
+                       gpio_set_value_cansleep(ena, 1);
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               if (ena >= 0)
+                       gpio_set_value_cansleep(ena, 0);
+               break;
+       }
+
+       codec->dapm.bias_level = level;
+
+       return 0;
+}
 
 static const struct snd_soc_dapm_widget wm1250_ev1_dapm_widgets[] = {
 SND_SOC_DAPM_ADC("ADC", "wm1250-ev1 Capture", SND_SOC_NOPM, 0, 0),
@@ -53,12 +102,67 @@ static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = {
        .num_dapm_widgets = ARRAY_SIZE(wm1250_ev1_dapm_widgets),
        .dapm_routes = wm1250_ev1_dapm_routes,
        .num_dapm_routes = ARRAY_SIZE(wm1250_ev1_dapm_routes),
+
+       .set_bias_level = wm1250_ev1_set_bias_level,
+       .idle_bias_off = true,
 };
 
+static int __devinit wm1250_ev1_pdata(struct i2c_client *i2c)
+{
+       struct wm1250_ev1_pdata *pdata = dev_get_platdata(&i2c->dev);
+       struct wm1250_priv *wm1250;
+       int i, ret;
+
+       if (!pdata)
+               return 0;
+
+       wm1250 = kzalloc(sizeof(*wm1250), GFP_KERNEL);
+       if (!wm1250) {
+               dev_err(&i2c->dev, "Unable to allocate private data\n");
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm1250->gpios); i++) {
+               wm1250->gpios[i].gpio = pdata->gpios[i];
+               wm1250->gpios[i].label = wm1250_gpio_names[i];
+               wm1250->gpios[i].flags = GPIOF_OUT_INIT_LOW;
+       }
+       wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL0].flags = GPIOF_OUT_INIT_HIGH;
+       wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL1].flags = GPIOF_OUT_INIT_HIGH;
+
+       ret = gpio_request_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to get GPIOs: %d\n", ret);
+               goto err_alloc;
+       }
+
+       dev_set_drvdata(&i2c->dev, wm1250);
+
+       return ret;
+
+err_alloc:
+       kfree(wm1250);
+err:
+       return ret;
+}
+
+static void wm1250_ev1_free(struct i2c_client *i2c)
+{
+       struct wm1250_priv *wm1250 = dev_get_drvdata(&i2c->dev);
+
+       if (wm1250) {
+               gpio_free_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
+               kfree(wm1250);
+       }
+}
+
 static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *i2c_id)
 {
-       int id, board, rev;
+       int id, board, rev, ret;
+
+       dev_set_drvdata(&i2c->dev, NULL);
 
        board = i2c_smbus_read_byte_data(i2c, 0);
        if (board < 0) {
@@ -76,13 +180,25 @@ static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
 
        dev_info(&i2c->dev, "revision %d\n", rev + 1);
 
-       return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1,
-                                     &wm1250_ev1_dai, 1);
+       ret = wm1250_ev1_pdata(i2c);
+       if (ret != 0)
+               return ret;
+
+       ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1,
+                                    &wm1250_ev1_dai, 1);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+               wm1250_ev1_free(i2c);
+               return ret;
+       }
+
+       return 0;
 }
 
 static int __devexit wm1250_ev1_remove(struct i2c_client *i2c)
 {
        snd_soc_unregister_codec(&i2c->dev);
+       wm1250_ev1_free(i2c);
 
        return 0;
 }
diff --git a/sound/soc/codecs/wm5100-tables.c b/sound/soc/codecs/wm5100-tables.c
new file mode 100644 (file)
index 0000000..e9ce81a
--- /dev/null
@@ -0,0 +1,1531 @@
+/*
+ * wm5100-tables.c  --  WM5100 ALSA SoC Audio driver data
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "wm5100.h"
+
+int wm5100_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+{
+       switch (reg) {
+       case WM5100_SOFTWARE_RESET:
+       case WM5100_DEVICE_REVISION:
+       case WM5100_FX_CTRL:
+       case WM5100_INTERRUPT_STATUS_1:
+       case WM5100_INTERRUPT_STATUS_2:
+       case WM5100_INTERRUPT_STATUS_3:
+       case WM5100_INTERRUPT_STATUS_4:
+       case WM5100_INTERRUPT_RAW_STATUS_2:
+       case WM5100_INTERRUPT_RAW_STATUS_3:
+       case WM5100_INTERRUPT_RAW_STATUS_4:
+       case WM5100_OUTPUT_STATUS_1:
+       case WM5100_OUTPUT_STATUS_2:
+       case WM5100_INPUT_ENABLES_STATUS:
+       case WM5100_MIC_DETECT_3:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+int wm5100_readable_register(struct snd_soc_codec *codec, unsigned int reg)
+{
+       switch (reg) {
+       case WM5100_SOFTWARE_RESET:
+       case WM5100_DEVICE_REVISION:
+       case WM5100_CTRL_IF_1:
+       case WM5100_TONE_GENERATOR_1:
+       case WM5100_PWM_DRIVE_1:
+       case WM5100_PWM_DRIVE_2:
+       case WM5100_PWM_DRIVE_3:
+       case WM5100_CLOCKING_1:
+       case WM5100_CLOCKING_3:
+       case WM5100_CLOCKING_4:
+       case WM5100_CLOCKING_5:
+       case WM5100_CLOCKING_6:
+       case WM5100_CLOCKING_7:
+       case WM5100_CLOCKING_8:
+       case WM5100_ASRC_ENABLE:
+       case WM5100_ASRC_STATUS:
+       case WM5100_ASRC_RATE1:
+       case WM5100_ISRC_1_CTRL_1:
+       case WM5100_ISRC_1_CTRL_2:
+       case WM5100_ISRC_2_CTRL1:
+       case WM5100_ISRC_2_CTRL_2:
+       case WM5100_FLL1_CONTROL_1:
+       case WM5100_FLL1_CONTROL_2:
+       case WM5100_FLL1_CONTROL_3:
+       case WM5100_FLL1_CONTROL_5:
+       case WM5100_FLL1_CONTROL_6:
+       case WM5100_FLL1_EFS_1:
+       case WM5100_FLL2_CONTROL_1:
+       case WM5100_FLL2_CONTROL_2:
+       case WM5100_FLL2_CONTROL_3:
+       case WM5100_FLL2_CONTROL_5:
+       case WM5100_FLL2_CONTROL_6:
+       case WM5100_FLL2_EFS_1:
+       case WM5100_MIC_CHARGE_PUMP_1:
+       case WM5100_MIC_CHARGE_PUMP_2:
+       case WM5100_HP_CHARGE_PUMP_1:
+       case WM5100_LDO1_CONTROL:
+       case WM5100_MIC_BIAS_CTRL_1:
+       case WM5100_MIC_BIAS_CTRL_2:
+       case WM5100_MIC_BIAS_CTRL_3:
+       case WM5100_ACCESSORY_DETECT_MODE_1:
+       case WM5100_HEADPHONE_DETECT_1:
+       case WM5100_HEADPHONE_DETECT_2:
+       case WM5100_MIC_DETECT_1:
+       case WM5100_MIC_DETECT_2:
+       case WM5100_MIC_DETECT_3:
+       case WM5100_INPUT_ENABLES:
+       case WM5100_INPUT_ENABLES_STATUS:
+       case WM5100_IN1L_CONTROL:
+       case WM5100_IN1R_CONTROL:
+       case WM5100_IN2L_CONTROL:
+       case WM5100_IN2R_CONTROL:
+       case WM5100_IN3L_CONTROL:
+       case WM5100_IN3R_CONTROL:
+       case WM5100_IN4L_CONTROL:
+       case WM5100_IN4R_CONTROL:
+       case WM5100_RXANC_SRC:
+       case WM5100_INPUT_VOLUME_RAMP:
+       case WM5100_ADC_DIGITAL_VOLUME_1L:
+       case WM5100_ADC_DIGITAL_VOLUME_1R:
+       case WM5100_ADC_DIGITAL_VOLUME_2L:
+       case WM5100_ADC_DIGITAL_VOLUME_2R:
+       case WM5100_ADC_DIGITAL_VOLUME_3L:
+       case WM5100_ADC_DIGITAL_VOLUME_3R:
+       case WM5100_ADC_DIGITAL_VOLUME_4L:
+       case WM5100_ADC_DIGITAL_VOLUME_4R:
+       case WM5100_OUTPUT_ENABLES_2:
+       case WM5100_OUTPUT_STATUS_1:
+       case WM5100_OUTPUT_STATUS_2:
+       case WM5100_CHANNEL_ENABLES_1:
+       case WM5100_OUT_VOLUME_1L:
+       case WM5100_OUT_VOLUME_1R:
+       case WM5100_DAC_VOLUME_LIMIT_1L:
+       case WM5100_DAC_VOLUME_LIMIT_1R:
+       case WM5100_OUT_VOLUME_2L:
+       case WM5100_OUT_VOLUME_2R:
+       case WM5100_DAC_VOLUME_LIMIT_2L:
+       case WM5100_DAC_VOLUME_LIMIT_2R:
+       case WM5100_OUT_VOLUME_3L:
+       case WM5100_OUT_VOLUME_3R:
+       case WM5100_DAC_VOLUME_LIMIT_3L:
+       case WM5100_DAC_VOLUME_LIMIT_3R:
+       case WM5100_OUT_VOLUME_4L:
+       case WM5100_OUT_VOLUME_4R:
+       case WM5100_DAC_VOLUME_LIMIT_5L:
+       case WM5100_DAC_VOLUME_LIMIT_5R:
+       case WM5100_DAC_VOLUME_LIMIT_6L:
+       case WM5100_DAC_VOLUME_LIMIT_6R:
+       case WM5100_DAC_AEC_CONTROL_1:
+       case WM5100_OUTPUT_VOLUME_RAMP:
+       case WM5100_DAC_DIGITAL_VOLUME_1L:
+       case WM5100_DAC_DIGITAL_VOLUME_1R:
+       case WM5100_DAC_DIGITAL_VOLUME_2L:
+       case WM5100_DAC_DIGITAL_VOLUME_2R:
+       case WM5100_DAC_DIGITAL_VOLUME_3L:
+       case WM5100_DAC_DIGITAL_VOLUME_3R:
+       case WM5100_DAC_DIGITAL_VOLUME_4L:
+       case WM5100_DAC_DIGITAL_VOLUME_4R:
+       case WM5100_DAC_DIGITAL_VOLUME_5L:
+       case WM5100_DAC_DIGITAL_VOLUME_5R:
+       case WM5100_DAC_DIGITAL_VOLUME_6L:
+       case WM5100_DAC_DIGITAL_VOLUME_6R:
+       case WM5100_PDM_SPK1_CTRL_1:
+       case WM5100_PDM_SPK1_CTRL_2:
+       case WM5100_PDM_SPK2_CTRL_1:
+       case WM5100_PDM_SPK2_CTRL_2:
+       case WM5100_AUDIO_IF_1_1:
+       case WM5100_AUDIO_IF_1_2:
+       case WM5100_AUDIO_IF_1_3:
+       case WM5100_AUDIO_IF_1_4:
+       case WM5100_AUDIO_IF_1_5:
+       case WM5100_AUDIO_IF_1_6:
+       case WM5100_AUDIO_IF_1_7:
+       case WM5100_AUDIO_IF_1_8:
+       case WM5100_AUDIO_IF_1_9:
+       case WM5100_AUDIO_IF_1_10:
+       case WM5100_AUDIO_IF_1_11:
+       case WM5100_AUDIO_IF_1_12:
+       case WM5100_AUDIO_IF_1_13:
+       case WM5100_AUDIO_IF_1_14:
+       case WM5100_AUDIO_IF_1_15:
+       case WM5100_AUDIO_IF_1_16:
+       case WM5100_AUDIO_IF_1_17:
+       case WM5100_AUDIO_IF_1_18:
+       case WM5100_AUDIO_IF_1_19:
+       case WM5100_AUDIO_IF_1_20:
+       case WM5100_AUDIO_IF_1_21:
+       case WM5100_AUDIO_IF_1_22:
+       case WM5100_AUDIO_IF_1_23:
+       case WM5100_AUDIO_IF_1_24:
+       case WM5100_AUDIO_IF_1_25:
+       case WM5100_AUDIO_IF_1_26:
+       case WM5100_AUDIO_IF_1_27:
+       case WM5100_AUDIO_IF_2_1:
+       case WM5100_AUDIO_IF_2_2:
+       case WM5100_AUDIO_IF_2_3:
+       case WM5100_AUDIO_IF_2_4:
+       case WM5100_AUDIO_IF_2_5:
+       case WM5100_AUDIO_IF_2_6:
+       case WM5100_AUDIO_IF_2_7:
+       case WM5100_AUDIO_IF_2_8:
+       case WM5100_AUDIO_IF_2_9:
+       case WM5100_AUDIO_IF_2_10:
+       case WM5100_AUDIO_IF_2_11:
+       case WM5100_AUDIO_IF_2_18:
+       case WM5100_AUDIO_IF_2_19:
+       case WM5100_AUDIO_IF_2_26:
+       case WM5100_AUDIO_IF_2_27:
+       case WM5100_AUDIO_IF_3_1:
+       case WM5100_AUDIO_IF_3_2:
+       case WM5100_AUDIO_IF_3_3:
+       case WM5100_AUDIO_IF_3_4:
+       case WM5100_AUDIO_IF_3_5:
+       case WM5100_AUDIO_IF_3_6:
+       case WM5100_AUDIO_IF_3_7:
+       case WM5100_AUDIO_IF_3_8:
+       case WM5100_AUDIO_IF_3_9:
+       case WM5100_AUDIO_IF_3_10:
+       case WM5100_AUDIO_IF_3_11:
+       case WM5100_AUDIO_IF_3_18:
+       case WM5100_AUDIO_IF_3_19:
+       case WM5100_AUDIO_IF_3_26:
+       case WM5100_AUDIO_IF_3_27:
+       case WM5100_PWM1MIX_INPUT_1_SOURCE:
+       case WM5100_PWM1MIX_INPUT_1_VOLUME:
+       case WM5100_PWM1MIX_INPUT_2_SOURCE:
+       case WM5100_PWM1MIX_INPUT_2_VOLUME:
+       case WM5100_PWM1MIX_INPUT_3_SOURCE:
+       case WM5100_PWM1MIX_INPUT_3_VOLUME:
+       case WM5100_PWM1MIX_INPUT_4_SOURCE:
+       case WM5100_PWM1MIX_INPUT_4_VOLUME:
+       case WM5100_PWM2MIX_INPUT_1_SOURCE:
+       case WM5100_PWM2MIX_INPUT_1_VOLUME:
+       case WM5100_PWM2MIX_INPUT_2_SOURCE:
+       case WM5100_PWM2MIX_INPUT_2_VOLUME:
+       case WM5100_PWM2MIX_INPUT_3_SOURCE:
+       case WM5100_PWM2MIX_INPUT_3_VOLUME:
+       case WM5100_PWM2MIX_INPUT_4_SOURCE:
+       case WM5100_PWM2MIX_INPUT_4_VOLUME:
+       case WM5100_OUT1LMIX_INPUT_1_SOURCE:
+       case WM5100_OUT1LMIX_INPUT_1_VOLUME:
+       case WM5100_OUT1LMIX_INPUT_2_SOURCE:
+       case WM5100_OUT1LMIX_INPUT_2_VOLUME:
+       case WM5100_OUT1LMIX_INPUT_3_SOURCE:
+       case WM5100_OUT1LMIX_INPUT_3_VOLUME:
+       case WM5100_OUT1LMIX_INPUT_4_SOURCE:
+       case WM5100_OUT1LMIX_INPUT_4_VOLUME:
+       case WM5100_OUT1RMIX_INPUT_1_SOURCE:
+       case WM5100_OUT1RMIX_INPUT_1_VOLUME:
+       case WM5100_OUT1RMIX_INPUT_2_SOURCE:
+       case WM5100_OUT1RMIX_INPUT_2_VOLUME:
+       case WM5100_OUT1RMIX_INPUT_3_SOURCE:
+       case WM5100_OUT1RMIX_INPUT_3_VOLUME:
+       case WM5100_OUT1RMIX_INPUT_4_SOURCE:
+       case WM5100_OUT1RMIX_INPUT_4_VOLUME:
+       case WM5100_OUT2LMIX_INPUT_1_SOURCE:
+       case WM5100_OUT2LMIX_INPUT_1_VOLUME:
+       case WM5100_OUT2LMIX_INPUT_2_SOURCE:
+       case WM5100_OUT2LMIX_INPUT_2_VOLUME:
+       case WM5100_OUT2LMIX_INPUT_3_SOURCE:
+       case WM5100_OUT2LMIX_INPUT_3_VOLUME:
+       case WM5100_OUT2LMIX_INPUT_4_SOURCE:
+       case WM5100_OUT2LMIX_INPUT_4_VOLUME:
+       case WM5100_OUT2RMIX_INPUT_1_SOURCE:
+       case WM5100_OUT2RMIX_INPUT_1_VOLUME:
+       case WM5100_OUT2RMIX_INPUT_2_SOURCE:
+       case WM5100_OUT2RMIX_INPUT_2_VOLUME:
+       case WM5100_OUT2RMIX_INPUT_3_SOURCE:
+       case WM5100_OUT2RMIX_INPUT_3_VOLUME:
+       case WM5100_OUT2RMIX_INPUT_4_SOURCE:
+       case WM5100_OUT2RMIX_INPUT_4_VOLUME:
+       case WM5100_OUT3LMIX_INPUT_1_SOURCE:
+       case WM5100_OUT3LMIX_INPUT_1_VOLUME:
+       case WM5100_OUT3LMIX_INPUT_2_SOURCE:
+       case WM5100_OUT3LMIX_INPUT_2_VOLUME:
+       case WM5100_OUT3LMIX_INPUT_3_SOURCE:
+       case WM5100_OUT3LMIX_INPUT_3_VOLUME:
+       case WM5100_OUT3LMIX_INPUT_4_SOURCE:
+       case WM5100_OUT3LMIX_INPUT_4_VOLUME:
+       case WM5100_OUT3RMIX_INPUT_1_SOURCE:
+       case WM5100_OUT3RMIX_INPUT_1_VOLUME:
+       case WM5100_OUT3RMIX_INPUT_2_SOURCE:
+       case WM5100_OUT3RMIX_INPUT_2_VOLUME:
+       case WM5100_OUT3RMIX_INPUT_3_SOURCE:
+       case WM5100_OUT3RMIX_INPUT_3_VOLUME:
+       case WM5100_OUT3RMIX_INPUT_4_SOURCE:
+       case WM5100_OUT3RMIX_INPUT_4_VOLUME:
+       case WM5100_OUT4LMIX_INPUT_1_SOURCE:
+       case WM5100_OUT4LMIX_INPUT_1_VOLUME:
+       case WM5100_OUT4LMIX_INPUT_2_SOURCE:
+       case WM5100_OUT4LMIX_INPUT_2_VOLUME:
+       case WM5100_OUT4LMIX_INPUT_3_SOURCE:
+       case WM5100_OUT4LMIX_INPUT_3_VOLUME:
+       case WM5100_OUT4LMIX_INPUT_4_SOURCE:
+       case WM5100_OUT4LMIX_INPUT_4_VOLUME:
+       case WM5100_OUT4RMIX_INPUT_1_SOURCE:
+       case WM5100_OUT4RMIX_INPUT_1_VOLUME:
+       case WM5100_OUT4RMIX_INPUT_2_SOURCE:
+       case WM5100_OUT4RMIX_INPUT_2_VOLUME:
+       case WM5100_OUT4RMIX_INPUT_3_SOURCE:
+       case WM5100_OUT4RMIX_INPUT_3_VOLUME:
+       case WM5100_OUT4RMIX_INPUT_4_SOURCE:
+       case WM5100_OUT4RMIX_INPUT_4_VOLUME:
+       case WM5100_OUT5LMIX_INPUT_1_SOURCE:
+       case WM5100_OUT5LMIX_INPUT_1_VOLUME:
+       case WM5100_OUT5LMIX_INPUT_2_SOURCE:
+       case WM5100_OUT5LMIX_INPUT_2_VOLUME:
+       case WM5100_OUT5LMIX_INPUT_3_SOURCE:
+       case WM5100_OUT5LMIX_INPUT_3_VOLUME:
+       case WM5100_OUT5LMIX_INPUT_4_SOURCE:
+       case WM5100_OUT5LMIX_INPUT_4_VOLUME:
+       case WM5100_OUT5RMIX_INPUT_1_SOURCE:
+       case WM5100_OUT5RMIX_INPUT_1_VOLUME:
+       case WM5100_OUT5RMIX_INPUT_2_SOURCE:
+       case WM5100_OUT5RMIX_INPUT_2_VOLUME:
+       case WM5100_OUT5RMIX_INPUT_3_SOURCE:
+       case WM5100_OUT5RMIX_INPUT_3_VOLUME:
+       case WM5100_OUT5RMIX_INPUT_4_SOURCE:
+       case WM5100_OUT5RMIX_INPUT_4_VOLUME:
+       case WM5100_OUT6LMIX_INPUT_1_SOURCE:
+       case WM5100_OUT6LMIX_INPUT_1_VOLUME:
+       case WM5100_OUT6LMIX_INPUT_2_SOURCE:
+       case WM5100_OUT6LMIX_INPUT_2_VOLUME:
+       case WM5100_OUT6LMIX_INPUT_3_SOURCE:
+       case WM5100_OUT6LMIX_INPUT_3_VOLUME:
+       case WM5100_OUT6LMIX_INPUT_4_SOURCE:
+       case WM5100_OUT6LMIX_INPUT_4_VOLUME:
+       case WM5100_OUT6RMIX_INPUT_1_SOURCE:
+       case WM5100_OUT6RMIX_INPUT_1_VOLUME:
+       case WM5100_OUT6RMIX_INPUT_2_SOURCE:
+       case WM5100_OUT6RMIX_INPUT_2_VOLUME:
+       case WM5100_OUT6RMIX_INPUT_3_SOURCE:
+       case WM5100_OUT6RMIX_INPUT_3_VOLUME:
+       case WM5100_OUT6RMIX_INPUT_4_SOURCE:
+       case WM5100_OUT6RMIX_INPUT_4_VOLUME:
+       case WM5100_AIF1TX1MIX_INPUT_1_SOURCE:
+       case WM5100_AIF1TX1MIX_INPUT_1_VOLUME:
+       case WM5100_AIF1TX1MIX_INPUT_2_SOURCE:
+       case WM5100_AIF1TX1MIX_INPUT_2_VOLUME:
+       case WM5100_AIF1TX1MIX_INPUT_3_SOURCE:
+       case WM5100_AIF1TX1MIX_INPUT_3_VOLUME:
+       case WM5100_AIF1TX1MIX_INPUT_4_SOURCE:
+       case WM5100_AIF1TX1MIX_INPUT_4_VOLUME:
+       case WM5100_AIF1TX2MIX_INPUT_1_SOURCE:
+       case WM5100_AIF1TX2MIX_INPUT_1_VOLUME:
+       case WM5100_AIF1TX2MIX_INPUT_2_SOURCE:
+       case WM5100_AIF1TX2MIX_INPUT_2_VOLUME:
+       case WM5100_AIF1TX2MIX_INPUT_3_SOURCE:
+       case WM5100_AIF1TX2MIX_INPUT_3_VOLUME:
+       case WM5100_AIF1TX2MIX_INPUT_4_SOURCE:
+       case WM5100_AIF1TX2MIX_INPUT_4_VOLUME:
+       case WM5100_AIF1TX3MIX_INPUT_1_SOURCE:
+       case WM5100_AIF1TX3MIX_INPUT_1_VOLUME:
+       case WM5100_AIF1TX3MIX_INPUT_2_SOURCE:
+       case WM5100_AIF1TX3MIX_INPUT_2_VOLUME:
+       case WM5100_AIF1TX3MIX_INPUT_3_SOURCE:
+       case WM5100_AIF1TX3MIX_INPUT_3_VOLUME:
+       case WM5100_AIF1TX3MIX_INPUT_4_SOURCE:
+       case WM5100_AIF1TX3MIX_INPUT_4_VOLUME:
+       case WM5100_AIF1TX4MIX_INPUT_1_SOURCE:
+       case WM5100_AIF1TX4MIX_INPUT_1_VOLUME:
+       case WM5100_AIF1TX4MIX_INPUT_2_SOURCE:
+       case WM5100_AIF1TX4MIX_INPUT_2_VOLUME:
+       case WM5100_AIF1TX4MIX_INPUT_3_SOURCE:
+       case WM5100_AIF1TX4MIX_INPUT_3_VOLUME:
+       case WM5100_AIF1TX4MIX_INPUT_4_SOURCE:
+       case WM5100_AIF1TX4MIX_INPUT_4_VOLUME:
+       case WM5100_AIF1TX5MIX_INPUT_1_SOURCE:
+       case WM5100_AIF1TX5MIX_INPUT_1_VOLUME:
+       case WM5100_AIF1TX5MIX_INPUT_2_SOURCE:
+       case WM5100_AIF1TX5MIX_INPUT_2_VOLUME:
+       case WM5100_AIF1TX5MIX_INPUT_3_SOURCE:
+       case WM5100_AIF1TX5MIX_INPUT_3_VOLUME:
+       case WM5100_AIF1TX5MIX_INPUT_4_SOURCE:
+       case WM5100_AIF1TX5MIX_INPUT_4_VOLUME:
+       case WM5100_AIF1TX6MIX_INPUT_1_SOURCE:
+       case WM5100_AIF1TX6MIX_INPUT_1_VOLUME:
+       case WM5100_AIF1TX6MIX_INPUT_2_SOURCE:
+       case WM5100_AIF1TX6MIX_INPUT_2_VOLUME:
+       case WM5100_AIF1TX6MIX_INPUT_3_SOURCE:
+       case WM5100_AIF1TX6MIX_INPUT_3_VOLUME:
+       case WM5100_AIF1TX6MIX_INPUT_4_SOURCE:
+       case WM5100_AIF1TX6MIX_INPUT_4_VOLUME:
+       case WM5100_AIF1TX7MIX_INPUT_1_SOURCE:
+       case WM5100_AIF1TX7MIX_INPUT_1_VOLUME:
+       case WM5100_AIF1TX7MIX_INPUT_2_SOURCE:
+       case WM5100_AIF1TX7MIX_INPUT_2_VOLUME:
+       case WM5100_AIF1TX7MIX_INPUT_3_SOURCE:
+       case WM5100_AIF1TX7MIX_INPUT_3_VOLUME:
+       case WM5100_AIF1TX7MIX_INPUT_4_SOURCE:
+       case WM5100_AIF1TX7MIX_INPUT_4_VOLUME:
+       case WM5100_AIF1TX8MIX_INPUT_1_SOURCE:
+       case WM5100_AIF1TX8MIX_INPUT_1_VOLUME:
+       case WM5100_AIF1TX8MIX_INPUT_2_SOURCE:
+       case WM5100_AIF1TX8MIX_INPUT_2_VOLUME:
+       case WM5100_AIF1TX8MIX_INPUT_3_SOURCE:
+       case WM5100_AIF1TX8MIX_INPUT_3_VOLUME:
+       case WM5100_AIF1TX8MIX_INPUT_4_SOURCE:
+       case WM5100_AIF1TX8MIX_INPUT_4_VOLUME:
+       case WM5100_AIF2TX1MIX_INPUT_1_SOURCE:
+       case WM5100_AIF2TX1MIX_INPUT_1_VOLUME:
+       case WM5100_AIF2TX1MIX_INPUT_2_SOURCE:
+       case WM5100_AIF2TX1MIX_INPUT_2_VOLUME:
+       case WM5100_AIF2TX1MIX_INPUT_3_SOURCE:
+       case WM5100_AIF2TX1MIX_INPUT_3_VOLUME:
+       case WM5100_AIF2TX1MIX_INPUT_4_SOURCE:
+       case WM5100_AIF2TX1MIX_INPUT_4_VOLUME:
+       case WM5100_AIF2TX2MIX_INPUT_1_SOURCE:
+       case WM5100_AIF2TX2MIX_INPUT_1_VOLUME:
+       case WM5100_AIF2TX2MIX_INPUT_2_SOURCE:
+       case WM5100_AIF2TX2MIX_INPUT_2_VOLUME:
+       case WM5100_AIF2TX2MIX_INPUT_3_SOURCE:
+       case WM5100_AIF2TX2MIX_INPUT_3_VOLUME:
+       case WM5100_AIF2TX2MIX_INPUT_4_SOURCE:
+       case WM5100_AIF2TX2MIX_INPUT_4_VOLUME:
+       case WM5100_AIF3TX1MIX_INPUT_1_SOURCE:
+       case WM5100_AIF3TX1MIX_INPUT_1_VOLUME:
+       case WM5100_AIF3TX1MIX_INPUT_2_SOURCE:
+       case WM5100_AIF3TX1MIX_INPUT_2_VOLUME:
+       case WM5100_AIF3TX1MIX_INPUT_3_SOURCE:
+       case WM5100_AIF3TX1MIX_INPUT_3_VOLUME:
+       case WM5100_AIF3TX1MIX_INPUT_4_SOURCE:
+       case WM5100_AIF3TX1MIX_INPUT_4_VOLUME:
+       case WM5100_AIF3TX2MIX_INPUT_1_SOURCE:
+       case WM5100_AIF3TX2MIX_INPUT_1_VOLUME:
+       case WM5100_AIF3TX2MIX_INPUT_2_SOURCE:
+       case WM5100_AIF3TX2MIX_INPUT_2_VOLUME:
+       case WM5100_AIF3TX2MIX_INPUT_3_SOURCE:
+       case WM5100_AIF3TX2MIX_INPUT_3_VOLUME:
+       case WM5100_AIF3TX2MIX_INPUT_4_SOURCE:
+       case WM5100_AIF3TX2MIX_INPUT_4_VOLUME:
+       case WM5100_EQ1MIX_INPUT_1_SOURCE:
+       case WM5100_EQ1MIX_INPUT_1_VOLUME:
+       case WM5100_EQ1MIX_INPUT_2_SOURCE:
+       case WM5100_EQ1MIX_INPUT_2_VOLUME:
+       case WM5100_EQ1MIX_INPUT_3_SOURCE:
+       case WM5100_EQ1MIX_INPUT_3_VOLUME:
+       case WM5100_EQ1MIX_INPUT_4_SOURCE:
+       case WM5100_EQ1MIX_INPUT_4_VOLUME:
+       case WM5100_EQ2MIX_INPUT_1_SOURCE:
+       case WM5100_EQ2MIX_INPUT_1_VOLUME:
+       case WM5100_EQ2MIX_INPUT_2_SOURCE:
+       case WM5100_EQ2MIX_INPUT_2_VOLUME:
+       case WM5100_EQ2MIX_INPUT_3_SOURCE:
+       case WM5100_EQ2MIX_INPUT_3_VOLUME:
+       case WM5100_EQ2MIX_INPUT_4_SOURCE:
+       case WM5100_EQ2MIX_INPUT_4_VOLUME:
+       case WM5100_EQ3MIX_INPUT_1_SOURCE:
+       case WM5100_EQ3MIX_INPUT_1_VOLUME:
+       case WM5100_EQ3MIX_INPUT_2_SOURCE:
+       case WM5100_EQ3MIX_INPUT_2_VOLUME:
+       case WM5100_EQ3MIX_INPUT_3_SOURCE:
+       case WM5100_EQ3MIX_INPUT_3_VOLUME:
+       case WM5100_EQ3MIX_INPUT_4_SOURCE:
+       case WM5100_EQ3MIX_INPUT_4_VOLUME:
+       case WM5100_EQ4MIX_INPUT_1_SOURCE:
+       case WM5100_EQ4MIX_INPUT_1_VOLUME:
+       case WM5100_EQ4MIX_INPUT_2_SOURCE:
+       case WM5100_EQ4MIX_INPUT_2_VOLUME:
+       case WM5100_EQ4MIX_INPUT_3_SOURCE:
+       case WM5100_EQ4MIX_INPUT_3_VOLUME:
+       case WM5100_EQ4MIX_INPUT_4_SOURCE:
+       case WM5100_EQ4MIX_INPUT_4_VOLUME:
+       case WM5100_DRC1LMIX_INPUT_1_SOURCE:
+       case WM5100_DRC1LMIX_INPUT_1_VOLUME:
+       case WM5100_DRC1LMIX_INPUT_2_SOURCE:
+       case WM5100_DRC1LMIX_INPUT_2_VOLUME:
+       case WM5100_DRC1LMIX_INPUT_3_SOURCE:
+       case WM5100_DRC1LMIX_INPUT_3_VOLUME:
+       case WM5100_DRC1LMIX_INPUT_4_SOURCE:
+       case WM5100_DRC1LMIX_INPUT_4_VOLUME:
+       case WM5100_DRC1RMIX_INPUT_1_SOURCE:
+       case WM5100_DRC1RMIX_INPUT_1_VOLUME:
+       case WM5100_DRC1RMIX_INPUT_2_SOURCE:
+       case WM5100_DRC1RMIX_INPUT_2_VOLUME:
+       case WM5100_DRC1RMIX_INPUT_3_SOURCE:
+       case WM5100_DRC1RMIX_INPUT_3_VOLUME:
+       case WM5100_DRC1RMIX_INPUT_4_SOURCE:
+       case WM5100_DRC1RMIX_INPUT_4_VOLUME:
+       case WM5100_HPLP1MIX_INPUT_1_SOURCE:
+       case WM5100_HPLP1MIX_INPUT_1_VOLUME:
+       case WM5100_HPLP1MIX_INPUT_2_SOURCE:
+       case WM5100_HPLP1MIX_INPUT_2_VOLUME:
+       case WM5100_HPLP1MIX_INPUT_3_SOURCE:
+       case WM5100_HPLP1MIX_INPUT_3_VOLUME:
+       case WM5100_HPLP1MIX_INPUT_4_SOURCE:
+       case WM5100_HPLP1MIX_INPUT_4_VOLUME:
+       case WM5100_HPLP2MIX_INPUT_1_SOURCE:
+       case WM5100_HPLP2MIX_INPUT_1_VOLUME:
+       case WM5100_HPLP2MIX_INPUT_2_SOURCE:
+       case WM5100_HPLP2MIX_INPUT_2_VOLUME:
+       case WM5100_HPLP2MIX_INPUT_3_SOURCE:
+       case WM5100_HPLP2MIX_INPUT_3_VOLUME:
+       case WM5100_HPLP2MIX_INPUT_4_SOURCE:
+       case WM5100_HPLP2MIX_INPUT_4_VOLUME:
+       case WM5100_HPLP3MIX_INPUT_1_SOURCE:
+       case WM5100_HPLP3MIX_INPUT_1_VOLUME:
+       case WM5100_HPLP3MIX_INPUT_2_SOURCE:
+       case WM5100_HPLP3MIX_INPUT_2_VOLUME:
+       case WM5100_HPLP3MIX_INPUT_3_SOURCE:
+       case WM5100_HPLP3MIX_INPUT_3_VOLUME:
+       case WM5100_HPLP3MIX_INPUT_4_SOURCE:
+       case WM5100_HPLP3MIX_INPUT_4_VOLUME:
+       case WM5100_HPLP4MIX_INPUT_1_SOURCE:
+       case WM5100_HPLP4MIX_INPUT_1_VOLUME:
+       case WM5100_HPLP4MIX_INPUT_2_SOURCE:
+       case WM5100_HPLP4MIX_INPUT_2_VOLUME:
+       case WM5100_HPLP4MIX_INPUT_3_SOURCE:
+       case WM5100_HPLP4MIX_INPUT_3_VOLUME:
+       case WM5100_HPLP4MIX_INPUT_4_SOURCE:
+       case WM5100_HPLP4MIX_INPUT_4_VOLUME:
+       case WM5100_DSP1LMIX_INPUT_1_SOURCE:
+       case WM5100_DSP1LMIX_INPUT_1_VOLUME:
+       case WM5100_DSP1LMIX_INPUT_2_SOURCE:
+       case WM5100_DSP1LMIX_INPUT_2_VOLUME:
+       case WM5100_DSP1LMIX_INPUT_3_SOURCE:
+       case WM5100_DSP1LMIX_INPUT_3_VOLUME:
+       case WM5100_DSP1LMIX_INPUT_4_SOURCE:
+       case WM5100_DSP1LMIX_INPUT_4_VOLUME:
+       case WM5100_DSP1RMIX_INPUT_1_SOURCE:
+       case WM5100_DSP1RMIX_INPUT_1_VOLUME:
+       case WM5100_DSP1RMIX_INPUT_2_SOURCE:
+       case WM5100_DSP1RMIX_INPUT_2_VOLUME:
+       case WM5100_DSP1RMIX_INPUT_3_SOURCE:
+       case WM5100_DSP1RMIX_INPUT_3_VOLUME:
+       case WM5100_DSP1RMIX_INPUT_4_SOURCE:
+       case WM5100_DSP1RMIX_INPUT_4_VOLUME:
+       case WM5100_DSP1AUX1MIX_INPUT_1_SOURCE:
+       case WM5100_DSP1AUX2MIX_INPUT_1_SOURCE:
+       case WM5100_DSP1AUX3MIX_INPUT_1_SOURCE:
+       case WM5100_DSP1AUX4MIX_INPUT_1_SOURCE:
+       case WM5100_DSP1AUX5MIX_INPUT_1_SOURCE:
+       case WM5100_DSP1AUX6MIX_INPUT_1_SOURCE:
+       case WM5100_DSP2LMIX_INPUT_1_SOURCE:
+       case WM5100_DSP2LMIX_INPUT_1_VOLUME:
+       case WM5100_DSP2LMIX_INPUT_2_SOURCE:
+       case WM5100_DSP2LMIX_INPUT_2_VOLUME:
+       case WM5100_DSP2LMIX_INPUT_3_SOURCE:
+       case WM5100_DSP2LMIX_INPUT_3_VOLUME:
+       case WM5100_DSP2LMIX_INPUT_4_SOURCE:
+       case WM5100_DSP2LMIX_INPUT_4_VOLUME:
+       case WM5100_DSP2RMIX_INPUT_1_SOURCE:
+       case WM5100_DSP2RMIX_INPUT_1_VOLUME:
+       case WM5100_DSP2RMIX_INPUT_2_SOURCE:
+       case WM5100_DSP2RMIX_INPUT_2_VOLUME:
+       case WM5100_DSP2RMIX_INPUT_3_SOURCE:
+       case WM5100_DSP2RMIX_INPUT_3_VOLUME:
+       case WM5100_DSP2RMIX_INPUT_4_SOURCE:
+       case WM5100_DSP2RMIX_INPUT_4_VOLUME:
+       case WM5100_DSP2AUX1MIX_INPUT_1_SOURCE:
+       case WM5100_DSP2AUX2MIX_INPUT_1_SOURCE:
+       case WM5100_DSP2AUX3MIX_INPUT_1_SOURCE:
+       case WM5100_DSP2AUX4MIX_INPUT_1_SOURCE:
+       case WM5100_DSP2AUX5MIX_INPUT_1_SOURCE:
+       case WM5100_DSP2AUX6MIX_INPUT_1_SOURCE:
+       case WM5100_DSP3LMIX_INPUT_1_SOURCE:
+       case WM5100_DSP3LMIX_INPUT_1_VOLUME:
+       case WM5100_DSP3LMIX_INPUT_2_SOURCE:
+       case WM5100_DSP3LMIX_INPUT_2_VOLUME:
+       case WM5100_DSP3LMIX_INPUT_3_SOURCE:
+       case WM5100_DSP3LMIX_INPUT_3_VOLUME:
+       case WM5100_DSP3LMIX_INPUT_4_SOURCE:
+       case WM5100_DSP3LMIX_INPUT_4_VOLUME:
+       case WM5100_DSP3RMIX_INPUT_1_SOURCE:
+       case WM5100_DSP3RMIX_INPUT_1_VOLUME:
+       case WM5100_DSP3RMIX_INPUT_2_SOURCE:
+       case WM5100_DSP3RMIX_INPUT_2_VOLUME:
+       case WM5100_DSP3RMIX_INPUT_3_SOURCE:
+       case WM5100_DSP3RMIX_INPUT_3_VOLUME:
+       case WM5100_DSP3RMIX_INPUT_4_SOURCE:
+       case WM5100_DSP3RMIX_INPUT_4_VOLUME:
+       case WM5100_DSP3AUX1MIX_INPUT_1_SOURCE:
+       case WM5100_DSP3AUX2MIX_INPUT_1_SOURCE:
+       case WM5100_DSP3AUX3MIX_INPUT_1_SOURCE:
+       case WM5100_DSP3AUX4MIX_INPUT_1_SOURCE:
+       case WM5100_DSP3AUX5MIX_INPUT_1_SOURCE:
+       case WM5100_DSP3AUX6MIX_INPUT_1_SOURCE:
+       case WM5100_ASRC1LMIX_INPUT_1_SOURCE:
+       case WM5100_ASRC1RMIX_INPUT_1_SOURCE:
+       case WM5100_ASRC2LMIX_INPUT_1_SOURCE:
+       case WM5100_ASRC2RMIX_INPUT_1_SOURCE:
+       case WM5100_ISRC1DEC1MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC1DEC2MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC1DEC3MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC1DEC4MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC1INT1MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC1INT2MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC1INT3MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC1INT4MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC2DEC1MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC2DEC2MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC2DEC3MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC2DEC4MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC2INT1MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC2INT2MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC2INT3MIX_INPUT_1_SOURCE:
+       case WM5100_ISRC2INT4MIX_INPUT_1_SOURCE:
+       case WM5100_GPIO_CTRL_1:
+       case WM5100_GPIO_CTRL_2:
+       case WM5100_GPIO_CTRL_3:
+       case WM5100_GPIO_CTRL_4:
+       case WM5100_GPIO_CTRL_5:
+       case WM5100_GPIO_CTRL_6:
+       case WM5100_MISC_PAD_CTRL_1:
+       case WM5100_MISC_PAD_CTRL_2:
+       case WM5100_MISC_PAD_CTRL_3:
+       case WM5100_MISC_PAD_CTRL_4:
+       case WM5100_MISC_PAD_CTRL_5:
+       case WM5100_MISC_GPIO_1:
+       case WM5100_INTERRUPT_STATUS_1:
+       case WM5100_INTERRUPT_STATUS_2:
+       case WM5100_INTERRUPT_STATUS_3:
+       case WM5100_INTERRUPT_STATUS_4:
+       case WM5100_INTERRUPT_RAW_STATUS_2:
+       case WM5100_INTERRUPT_RAW_STATUS_3:
+       case WM5100_INTERRUPT_RAW_STATUS_4:
+       case WM5100_INTERRUPT_STATUS_1_MASK:
+       case WM5100_INTERRUPT_STATUS_2_MASK:
+       case WM5100_INTERRUPT_STATUS_3_MASK:
+       case WM5100_INTERRUPT_STATUS_4_MASK:
+       case WM5100_INTERRUPT_CONTROL:
+       case WM5100_IRQ_DEBOUNCE_1:
+       case WM5100_IRQ_DEBOUNCE_2:
+       case WM5100_FX_CTRL:
+       case WM5100_EQ1_1:
+       case WM5100_EQ1_2:
+       case WM5100_EQ1_3:
+       case WM5100_EQ1_4:
+       case WM5100_EQ1_5:
+       case WM5100_EQ1_6:
+       case WM5100_EQ1_7:
+       case WM5100_EQ1_8:
+       case WM5100_EQ1_9:
+       case WM5100_EQ1_10:
+       case WM5100_EQ1_11:
+       case WM5100_EQ1_12:
+       case WM5100_EQ1_13:
+       case WM5100_EQ1_14:
+       case WM5100_EQ1_15:
+       case WM5100_EQ1_16:
+       case WM5100_EQ1_17:
+       case WM5100_EQ1_18:
+       case WM5100_EQ1_19:
+       case WM5100_EQ1_20:
+       case WM5100_EQ2_1:
+       case WM5100_EQ2_2:
+       case WM5100_EQ2_3:
+       case WM5100_EQ2_4:
+       case WM5100_EQ2_5:
+       case WM5100_EQ2_6:
+       case WM5100_EQ2_7:
+       case WM5100_EQ2_8:
+       case WM5100_EQ2_9:
+       case WM5100_EQ2_10:
+       case WM5100_EQ2_11:
+       case WM5100_EQ2_12:
+       case WM5100_EQ2_13:
+       case WM5100_EQ2_14:
+       case WM5100_EQ2_15:
+       case WM5100_EQ2_16:
+       case WM5100_EQ2_17:
+       case WM5100_EQ2_18:
+       case WM5100_EQ2_19:
+       case WM5100_EQ2_20:
+       case WM5100_EQ3_1:
+       case WM5100_EQ3_2:
+       case WM5100_EQ3_3:
+       case WM5100_EQ3_4:
+       case WM5100_EQ3_5:
+       case WM5100_EQ3_6:
+       case WM5100_EQ3_7:
+       case WM5100_EQ3_8:
+       case WM5100_EQ3_9:
+       case WM5100_EQ3_10:
+       case WM5100_EQ3_11:
+       case WM5100_EQ3_12:
+       case WM5100_EQ3_13:
+       case WM5100_EQ3_14:
+       case WM5100_EQ3_15:
+       case WM5100_EQ3_16:
+       case WM5100_EQ3_17:
+       case WM5100_EQ3_18:
+       case WM5100_EQ3_19:
+       case WM5100_EQ3_20:
+       case WM5100_EQ4_1:
+       case WM5100_EQ4_2:
+       case WM5100_EQ4_3:
+       case WM5100_EQ4_4:
+       case WM5100_EQ4_5:
+       case WM5100_EQ4_6:
+       case WM5100_EQ4_7:
+       case WM5100_EQ4_8:
+       case WM5100_EQ4_9:
+       case WM5100_EQ4_10:
+       case WM5100_EQ4_11:
+       case WM5100_EQ4_12:
+       case WM5100_EQ4_13:
+       case WM5100_EQ4_14:
+       case WM5100_EQ4_15:
+       case WM5100_EQ4_16:
+       case WM5100_EQ4_17:
+       case WM5100_EQ4_18:
+       case WM5100_EQ4_19:
+       case WM5100_EQ4_20:
+       case WM5100_DRC1_CTRL1:
+       case WM5100_DRC1_CTRL2:
+       case WM5100_DRC1_CTRL3:
+       case WM5100_DRC1_CTRL4:
+       case WM5100_DRC1_CTRL5:
+       case WM5100_HPLPF1_1:
+       case WM5100_HPLPF1_2:
+       case WM5100_HPLPF2_1:
+       case WM5100_HPLPF2_2:
+       case WM5100_HPLPF3_1:
+       case WM5100_HPLPF3_2:
+       case WM5100_HPLPF4_1:
+       case WM5100_HPLPF4_2:
+       case WM5100_DSP1_DM_0:
+       case WM5100_DSP1_DM_1:
+       case WM5100_DSP1_DM_2:
+       case WM5100_DSP1_DM_3:
+       case WM5100_DSP1_DM_508:
+       case WM5100_DSP1_DM_509:
+       case WM5100_DSP1_DM_510:
+       case WM5100_DSP1_DM_511:
+       case WM5100_DSP1_PM_0:
+       case WM5100_DSP1_PM_1:
+       case WM5100_DSP1_PM_2:
+       case WM5100_DSP1_PM_3:
+       case WM5100_DSP1_PM_4:
+       case WM5100_DSP1_PM_5:
+       case WM5100_DSP1_PM_1530:
+       case WM5100_DSP1_PM_1531:
+       case WM5100_DSP1_PM_1532:
+       case WM5100_DSP1_PM_1533:
+       case WM5100_DSP1_PM_1534:
+       case WM5100_DSP1_PM_1535:
+       case WM5100_DSP1_ZM_0:
+       case WM5100_DSP1_ZM_1:
+       case WM5100_DSP1_ZM_2:
+       case WM5100_DSP1_ZM_3:
+       case WM5100_DSP1_ZM_2044:
+       case WM5100_DSP1_ZM_2045:
+       case WM5100_DSP1_ZM_2046:
+       case WM5100_DSP1_ZM_2047:
+       case WM5100_DSP2_DM_0:
+       case WM5100_DSP2_DM_1:
+       case WM5100_DSP2_DM_2:
+       case WM5100_DSP2_DM_3:
+       case WM5100_DSP2_DM_508:
+       case WM5100_DSP2_DM_509:
+       case WM5100_DSP2_DM_510:
+       case WM5100_DSP2_DM_511:
+       case WM5100_DSP2_PM_0:
+       case WM5100_DSP2_PM_1:
+       case WM5100_DSP2_PM_2:
+       case WM5100_DSP2_PM_3:
+       case WM5100_DSP2_PM_4:
+       case WM5100_DSP2_PM_5:
+       case WM5100_DSP2_PM_1530:
+       case WM5100_DSP2_PM_1531:
+       case WM5100_DSP2_PM_1532:
+       case WM5100_DSP2_PM_1533:
+       case WM5100_DSP2_PM_1534:
+       case WM5100_DSP2_PM_1535:
+       case WM5100_DSP2_ZM_0:
+       case WM5100_DSP2_ZM_1:
+       case WM5100_DSP2_ZM_2:
+       case WM5100_DSP2_ZM_3:
+       case WM5100_DSP2_ZM_2044:
+       case WM5100_DSP2_ZM_2045:
+       case WM5100_DSP2_ZM_2046:
+       case WM5100_DSP2_ZM_2047:
+       case WM5100_DSP3_DM_0:
+       case WM5100_DSP3_DM_1:
+       case WM5100_DSP3_DM_2:
+       case WM5100_DSP3_DM_3:
+       case WM5100_DSP3_DM_508:
+       case WM5100_DSP3_DM_509:
+       case WM5100_DSP3_DM_510:
+       case WM5100_DSP3_DM_511:
+       case WM5100_DSP3_PM_0:
+       case WM5100_DSP3_PM_1:
+       case WM5100_DSP3_PM_2:
+       case WM5100_DSP3_PM_3:
+       case WM5100_DSP3_PM_4:
+       case WM5100_DSP3_PM_5:
+       case WM5100_DSP3_PM_1530:
+       case WM5100_DSP3_PM_1531:
+       case WM5100_DSP3_PM_1532:
+       case WM5100_DSP3_PM_1533:
+       case WM5100_DSP3_PM_1534:
+       case WM5100_DSP3_PM_1535:
+       case WM5100_DSP3_ZM_0:
+       case WM5100_DSP3_ZM_1:
+       case WM5100_DSP3_ZM_2:
+       case WM5100_DSP3_ZM_3:
+       case WM5100_DSP3_ZM_2044:
+       case WM5100_DSP3_ZM_2045:
+       case WM5100_DSP3_ZM_2046:
+       case WM5100_DSP3_ZM_2047:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+u16 wm5100_reg_defaults[WM5100_MAX_REGISTER + 1] = {
+       [0x0000] = 0x0000,     /* R0     - software reset */
+       [0x0001] = 0x0000,     /* R1     - Device Revision */
+       [0x0010] = 0x0801,     /* R16    - Ctrl IF 1 */
+       [0x0020] = 0x0000,     /* R32    - Tone Generator 1 */
+       [0x0030] = 0x0000,     /* R48    - PWM Drive 1 */
+       [0x0031] = 0x0100,     /* R49    - PWM Drive 2 */
+       [0x0032] = 0x0100,     /* R50    - PWM Drive 3 */
+       [0x0100] = 0x0002,     /* R256   - Clocking 1 */
+       [0x0101] = 0x0000,     /* R257   - Clocking 3 */
+       [0x0102] = 0x0011,     /* R258   - Clocking 4 */
+       [0x0103] = 0x0011,     /* R259   - Clocking 5 */
+       [0x0104] = 0x0011,     /* R260   - Clocking 6 */
+       [0x0107] = 0x0000,     /* R263   - Clocking 7 */
+       [0x0108] = 0x0000,     /* R264   - Clocking 8 */
+       [0x0120] = 0x0000,     /* R288   - ASRC_ENABLE */
+       [0x0121] = 0x0000,     /* R289   - ASRC_STATUS */
+       [0x0122] = 0x0000,     /* R290   - ASRC_RATE1 */
+       [0x0141] = 0x8000,     /* R321   - ISRC 1 CTRL 1 */
+       [0x0142] = 0x0000,     /* R322   - ISRC 1 CTRL 2 */
+       [0x0143] = 0x8000,     /* R323   - ISRC 2 CTRL1 */
+       [0x0144] = 0x0000,     /* R324   - ISRC 2 CTRL 2 */
+       [0x0182] = 0x0000,     /* R386   - FLL1 Control 1 */
+       [0x0183] = 0x0000,     /* R387   - FLL1 Control 2 */
+       [0x0184] = 0x0000,     /* R388   - FLL1 Control 3 */
+       [0x0186] = 0x0177,     /* R390   - FLL1 Control 5 */
+       [0x0187] = 0x0001,     /* R391   - FLL1 Control 6 */
+       [0x0188] = 0x0000,     /* R392   - FLL1 EFS 1 */
+       [0x01A2] = 0x0000,     /* R418   - FLL2 Control 1 */
+       [0x01A3] = 0x0000,     /* R419   - FLL2 Control 2 */
+       [0x01A4] = 0x0000,     /* R420   - FLL2 Control 3 */
+       [0x01A6] = 0x0177,     /* R422   - FLL2 Control 5 */
+       [0x01A7] = 0x0001,     /* R423   - FLL2 Control 6 */
+       [0x01A8] = 0x0000,     /* R424   - FLL2 EFS 1 */
+       [0x0200] = 0x0020,     /* R512   - Mic Charge Pump 1 */
+       [0x0201] = 0xB084,     /* R513   - Mic Charge Pump 2 */
+       [0x0202] = 0xBBDE,     /* R514   - HP Charge Pump 1 */
+       [0x0211] = 0x20D4,     /* R529   - LDO1 Control */
+       [0x0215] = 0x0062,     /* R533   - Mic Bias Ctrl 1 */
+       [0x0216] = 0x0062,     /* R534   - Mic Bias Ctrl 2 */
+       [0x0217] = 0x0062,     /* R535   - Mic Bias Ctrl 3 */
+       [0x0280] = 0x0004,     /* R640   - Accessory Detect Mode 1 */
+       [0x0288] = 0x0020,     /* R648   - Headphone Detect 1 */
+       [0x0289] = 0x0000,     /* R649   - Headphone Detect 2 */
+       [0x0290] = 0x1100,     /* R656   - Mic Detect 1 */
+       [0x0291] = 0x009F,     /* R657   - Mic Detect 2 */
+       [0x0292] = 0x0000,     /* R658   - Mic Detect 3 */
+       [0x0301] = 0x0000,     /* R769   - Input Enables */
+       [0x0302] = 0x0000,     /* R770   - Input Enables Status */
+       [0x0310] = 0x2280,     /* R784   - Status */
+       [0x0311] = 0x0080,     /* R785   - IN1R Control */
+       [0x0312] = 0x2280,     /* R786   - IN2L Control */
+       [0x0313] = 0x0080,     /* R787   - IN2R Control */
+       [0x0314] = 0x2280,     /* R788   - IN3L Control */
+       [0x0315] = 0x0080,     /* R789   - IN3R Control */
+       [0x0316] = 0x2280,     /* R790   - IN4L Control */
+       [0x0317] = 0x0080,     /* R791   - IN4R Control */
+       [0x0318] = 0x0000,     /* R792   - RXANC_SRC */
+       [0x0319] = 0x0022,     /* R793   - Input Volume Ramp */
+       [0x0320] = 0x0180,     /* R800   - ADC Digital Volume 1L */
+       [0x0321] = 0x0180,     /* R801   - ADC Digital Volume 1R */
+       [0x0322] = 0x0180,     /* R802   - ADC Digital Volume 2L */
+       [0x0323] = 0x0180,     /* R803   - ADC Digital Volume 2R */
+       [0x0324] = 0x0180,     /* R804   - ADC Digital Volume 3L */
+       [0x0325] = 0x0180,     /* R805   - ADC Digital Volume 3R */
+       [0x0326] = 0x0180,     /* R806   - ADC Digital Volume 4L */
+       [0x0327] = 0x0180,     /* R807   - ADC Digital Volume 4R */
+       [0x0401] = 0x0000,     /* R1025  - Output Enables 2 */
+       [0x0402] = 0x0000,     /* R1026  - Output Status 1 */
+       [0x0403] = 0x0000,     /* R1027  - Output Status 2 */
+       [0x0408] = 0x0000,     /* R1032  - Channel Enables 1 */
+       [0x0410] = 0x0080,     /* R1040  - Out Volume 1L */
+       [0x0411] = 0x0080,     /* R1041  - Out Volume 1R */
+       [0x0412] = 0x0080,     /* R1042  - DAC Volume Limit 1L */
+       [0x0413] = 0x0080,     /* R1043  - DAC Volume Limit 1R */
+       [0x0414] = 0x0080,     /* R1044  - Out Volume 2L */
+       [0x0415] = 0x0080,     /* R1045  - Out Volume 2R */
+       [0x0416] = 0x0080,     /* R1046  - DAC Volume Limit 2L */
+       [0x0417] = 0x0080,     /* R1047  - DAC Volume Limit 2R */
+       [0x0418] = 0x0080,     /* R1048  - Out Volume 3L */
+       [0x0419] = 0x0080,     /* R1049  - Out Volume 3R */
+       [0x041A] = 0x0080,     /* R1050  - DAC Volume Limit 3L */
+       [0x041B] = 0x0080,     /* R1051  - DAC Volume Limit 3R */
+       [0x041C] = 0x0080,     /* R1052  - Out Volume 4L */
+       [0x041D] = 0x0080,     /* R1053  - Out Volume 4R */
+       [0x041E] = 0x0080,     /* R1054  - DAC Volume Limit 5L */
+       [0x041F] = 0x0080,     /* R1055  - DAC Volume Limit 5R */
+       [0x0420] = 0x0080,     /* R1056  - DAC Volume Limit 6L */
+       [0x0421] = 0x0080,     /* R1057  - DAC Volume Limit 6R */
+       [0x0440] = 0x0000,     /* R1088  - DAC AEC Control 1 */
+       [0x0441] = 0x0022,     /* R1089  - Output Volume Ramp */
+       [0x0480] = 0x0180,     /* R1152  - DAC Digital Volume 1L */
+       [0x0481] = 0x0180,     /* R1153  - DAC Digital Volume 1R */
+       [0x0482] = 0x0180,     /* R1154  - DAC Digital Volume 2L */
+       [0x0483] = 0x0180,     /* R1155  - DAC Digital Volume 2R */
+       [0x0484] = 0x0180,     /* R1156  - DAC Digital Volume 3L */
+       [0x0485] = 0x0180,     /* R1157  - DAC Digital Volume 3R */
+       [0x0486] = 0x0180,     /* R1158  - DAC Digital Volume 4L */
+       [0x0487] = 0x0180,     /* R1159  - DAC Digital Volume 4R */
+       [0x0488] = 0x0180,     /* R1160  - DAC Digital Volume 5L */
+       [0x0489] = 0x0180,     /* R1161  - DAC Digital Volume 5R */
+       [0x048A] = 0x0180,     /* R1162  - DAC Digital Volume 6L */
+       [0x048B] = 0x0180,     /* R1163  - DAC Digital Volume 6R */
+       [0x04C0] = 0x0069,     /* R1216  - PDM SPK1 CTRL 1 */
+       [0x04C1] = 0x0000,     /* R1217  - PDM SPK1 CTRL 2 */
+       [0x04C2] = 0x0069,     /* R1218  - PDM SPK2 CTRL 1 */
+       [0x04C3] = 0x0000,     /* R1219  - PDM SPK2 CTRL 2 */
+       [0x0500] = 0x000C,     /* R1280  - Audio IF 1_1 */
+       [0x0501] = 0x0008,     /* R1281  - Audio IF 1_2 */
+       [0x0502] = 0x0000,     /* R1282  - Audio IF 1_3 */
+       [0x0503] = 0x0000,     /* R1283  - Audio IF 1_4 */
+       [0x0504] = 0x0000,     /* R1284  - Audio IF 1_5 */
+       [0x0505] = 0x0300,     /* R1285  - Audio IF 1_6 */
+       [0x0506] = 0x0300,     /* R1286  - Audio IF 1_7 */
+       [0x0507] = 0x1820,     /* R1287  - Audio IF 1_8 */
+       [0x0508] = 0x1820,     /* R1288  - Audio IF 1_9 */
+       [0x0509] = 0x0000,     /* R1289  - Audio IF 1_10 */
+       [0x050A] = 0x0001,     /* R1290  - Audio IF 1_11 */
+       [0x050B] = 0x0002,     /* R1291  - Audio IF 1_12 */
+       [0x050C] = 0x0003,     /* R1292  - Audio IF 1_13 */
+       [0x050D] = 0x0004,     /* R1293  - Audio IF 1_14 */
+       [0x050E] = 0x0005,     /* R1294  - Audio IF 1_15 */
+       [0x050F] = 0x0006,     /* R1295  - Audio IF 1_16 */
+       [0x0510] = 0x0007,     /* R1296  - Audio IF 1_17 */
+       [0x0511] = 0x0000,     /* R1297  - Audio IF 1_18 */
+       [0x0512] = 0x0001,     /* R1298  - Audio IF 1_19 */
+       [0x0513] = 0x0002,     /* R1299  - Audio IF 1_20 */
+       [0x0514] = 0x0003,     /* R1300  - Audio IF 1_21 */
+       [0x0515] = 0x0004,     /* R1301  - Audio IF 1_22 */
+       [0x0516] = 0x0005,     /* R1302  - Audio IF 1_23 */
+       [0x0517] = 0x0006,     /* R1303  - Audio IF 1_24 */
+       [0x0518] = 0x0007,     /* R1304  - Audio IF 1_25 */
+       [0x0519] = 0x0000,     /* R1305  - Audio IF 1_26 */
+       [0x051A] = 0x0000,     /* R1306  - Audio IF 1_27 */
+       [0x0540] = 0x000C,     /* R1344  - Audio IF 2_1 */
+       [0x0541] = 0x0008,     /* R1345  - Audio IF 2_2 */
+       [0x0542] = 0x0000,     /* R1346  - Audio IF 2_3 */
+       [0x0543] = 0x0000,     /* R1347  - Audio IF 2_4 */
+       [0x0544] = 0x0000,     /* R1348  - Audio IF 2_5 */
+       [0x0545] = 0x0300,     /* R1349  - Audio IF 2_6 */
+       [0x0546] = 0x0300,     /* R1350  - Audio IF 2_7 */
+       [0x0547] = 0x1820,     /* R1351  - Audio IF 2_8 */
+       [0x0548] = 0x1820,     /* R1352  - Audio IF 2_9 */
+       [0x0549] = 0x0000,     /* R1353  - Audio IF 2_10 */
+       [0x054A] = 0x0001,     /* R1354  - Audio IF 2_11 */
+       [0x0551] = 0x0000,     /* R1361  - Audio IF 2_18 */
+       [0x0552] = 0x0001,     /* R1362  - Audio IF 2_19 */
+       [0x0559] = 0x0000,     /* R1369  - Audio IF 2_26 */
+       [0x055A] = 0x0000,     /* R1370  - Audio IF 2_27 */
+       [0x0580] = 0x000C,     /* R1408  - Audio IF 3_1 */
+       [0x0581] = 0x0008,     /* R1409  - Audio IF 3_2 */
+       [0x0582] = 0x0000,     /* R1410  - Audio IF 3_3 */
+       [0x0583] = 0x0000,     /* R1411  - Audio IF 3_4 */
+       [0x0584] = 0x0000,     /* R1412  - Audio IF 3_5 */
+       [0x0585] = 0x0300,     /* R1413  - Audio IF 3_6 */
+       [0x0586] = 0x0300,     /* R1414  - Audio IF 3_7 */
+       [0x0587] = 0x1820,     /* R1415  - Audio IF 3_8 */
+       [0x0588] = 0x1820,     /* R1416  - Audio IF 3_9 */
+       [0x0589] = 0x0000,     /* R1417  - Audio IF 3_10 */
+       [0x058A] = 0x0001,     /* R1418  - Audio IF 3_11 */
+       [0x0591] = 0x0000,     /* R1425  - Audio IF 3_18 */
+       [0x0592] = 0x0001,     /* R1426  - Audio IF 3_19 */
+       [0x0599] = 0x0000,     /* R1433  - Audio IF 3_26 */
+       [0x059A] = 0x0000,     /* R1434  - Audio IF 3_27 */
+       [0x0640] = 0x0000,     /* R1600  - PWM1MIX Input 1 Source */
+       [0x0641] = 0x0080,     /* R1601  - PWM1MIX Input 1 Volume */
+       [0x0642] = 0x0000,     /* R1602  - PWM1MIX Input 2 Source */
+       [0x0643] = 0x0080,     /* R1603  - PWM1MIX Input 2 Volume */
+       [0x0644] = 0x0000,     /* R1604  - PWM1MIX Input 3 Source */
+       [0x0645] = 0x0080,     /* R1605  - PWM1MIX Input 3 Volume */
+       [0x0646] = 0x0000,     /* R1606  - PWM1MIX Input 4 Source */
+       [0x0647] = 0x0080,     /* R1607  - PWM1MIX Input 4 Volume */
+       [0x0648] = 0x0000,     /* R1608  - PWM2MIX Input 1 Source */
+       [0x0649] = 0x0080,     /* R1609  - PWM2MIX Input 1 Volume */
+       [0x064A] = 0x0000,     /* R1610  - PWM2MIX Input 2 Source */
+       [0x064B] = 0x0080,     /* R1611  - PWM2MIX Input 2 Volume */
+       [0x064C] = 0x0000,     /* R1612  - PWM2MIX Input 3 Source */
+       [0x064D] = 0x0080,     /* R1613  - PWM2MIX Input 3 Volume */
+       [0x064E] = 0x0000,     /* R1614  - PWM2MIX Input 4 Source */
+       [0x064F] = 0x0080,     /* R1615  - PWM2MIX Input 4 Volume */
+       [0x0680] = 0x0000,     /* R1664  - OUT1LMIX Input 1 Source */
+       [0x0681] = 0x0080,     /* R1665  - OUT1LMIX Input 1 Volume */
+       [0x0682] = 0x0000,     /* R1666  - OUT1LMIX Input 2 Source */
+       [0x0683] = 0x0080,     /* R1667  - OUT1LMIX Input 2 Volume */
+       [0x0684] = 0x0000,     /* R1668  - OUT1LMIX Input 3 Source */
+       [0x0685] = 0x0080,     /* R1669  - OUT1LMIX Input 3 Volume */
+       [0x0686] = 0x0000,     /* R1670  - OUT1LMIX Input 4 Source */
+       [0x0687] = 0x0080,     /* R1671  - OUT1LMIX Input 4 Volume */
+       [0x0688] = 0x0000,     /* R1672  - OUT1RMIX Input 1 Source */
+       [0x0689] = 0x0080,     /* R1673  - OUT1RMIX Input 1 Volume */
+       [0x068A] = 0x0000,     /* R1674  - OUT1RMIX Input 2 Source */
+       [0x068B] = 0x0080,     /* R1675  - OUT1RMIX Input 2 Volume */
+       [0x068C] = 0x0000,     /* R1676  - OUT1RMIX Input 3 Source */
+       [0x068D] = 0x0080,     /* R1677  - OUT1RMIX Input 3 Volume */
+       [0x068E] = 0x0000,     /* R1678  - OUT1RMIX Input 4 Source */
+       [0x068F] = 0x0080,     /* R1679  - OUT1RMIX Input 4 Volume */
+       [0x0690] = 0x0000,     /* R1680  - OUT2LMIX Input 1 Source */
+       [0x0691] = 0x0080,     /* R1681  - OUT2LMIX Input 1 Volume */
+       [0x0692] = 0x0000,     /* R1682  - OUT2LMIX Input 2 Source */
+       [0x0693] = 0x0080,     /* R1683  - OUT2LMIX Input 2 Volume */
+       [0x0694] = 0x0000,     /* R1684  - OUT2LMIX Input 3 Source */
+       [0x0695] = 0x0080,     /* R1685  - OUT2LMIX Input 3 Volume */
+       [0x0696] = 0x0000,     /* R1686  - OUT2LMIX Input 4 Source */
+       [0x0697] = 0x0080,     /* R1687  - OUT2LMIX Input 4 Volume */
+       [0x0698] = 0x0000,     /* R1688  - OUT2RMIX Input 1 Source */
+       [0x0699] = 0x0080,     /* R1689  - OUT2RMIX Input 1 Volume */
+       [0x069A] = 0x0000,     /* R1690  - OUT2RMIX Input 2 Source */
+       [0x069B] = 0x0080,     /* R1691  - OUT2RMIX Input 2 Volume */
+       [0x069C] = 0x0000,     /* R1692  - OUT2RMIX Input 3 Source */
+       [0x069D] = 0x0080,     /* R1693  - OUT2RMIX Input 3 Volume */
+       [0x069E] = 0x0000,     /* R1694  - OUT2RMIX Input 4 Source */
+       [0x069F] = 0x0080,     /* R1695  - OUT2RMIX Input 4 Volume */
+       [0x06A0] = 0x0000,     /* R1696  - OUT3LMIX Input 1 Source */
+       [0x06A1] = 0x0080,     /* R1697  - OUT3LMIX Input 1 Volume */
+       [0x06A2] = 0x0000,     /* R1698  - OUT3LMIX Input 2 Source */
+       [0x06A3] = 0x0080,     /* R1699  - OUT3LMIX Input 2 Volume */
+       [0x06A4] = 0x0000,     /* R1700  - OUT3LMIX Input 3 Source */
+       [0x06A5] = 0x0080,     /* R1701  - OUT3LMIX Input 3 Volume */
+       [0x06A6] = 0x0000,     /* R1702  - OUT3LMIX Input 4 Source */
+       [0x06A7] = 0x0080,     /* R1703  - OUT3LMIX Input 4 Volume */
+       [0x06A8] = 0x0000,     /* R1704  - OUT3RMIX Input 1 Source */
+       [0x06A9] = 0x0080,     /* R1705  - OUT3RMIX Input 1 Volume */
+       [0x06AA] = 0x0000,     /* R1706  - OUT3RMIX Input 2 Source */
+       [0x06AB] = 0x0080,     /* R1707  - OUT3RMIX Input 2 Volume */
+       [0x06AC] = 0x0000,     /* R1708  - OUT3RMIX Input 3 Source */
+       [0x06AD] = 0x0080,     /* R1709  - OUT3RMIX Input 3 Volume */
+       [0x06AE] = 0x0000,     /* R1710  - OUT3RMIX Input 4 Source */
+       [0x06AF] = 0x0080,     /* R1711  - OUT3RMIX Input 4 Volume */
+       [0x06B0] = 0x0000,     /* R1712  - OUT4LMIX Input 1 Source */
+       [0x06B1] = 0x0080,     /* R1713  - OUT4LMIX Input 1 Volume */
+       [0x06B2] = 0x0000,     /* R1714  - OUT4LMIX Input 2 Source */
+       [0x06B3] = 0x0080,     /* R1715  - OUT4LMIX Input 2 Volume */
+       [0x06B4] = 0x0000,     /* R1716  - OUT4LMIX Input 3 Source */
+       [0x06B5] = 0x0080,     /* R1717  - OUT4LMIX Input 3 Volume */
+       [0x06B6] = 0x0000,     /* R1718  - OUT4LMIX Input 4 Source */
+       [0x06B7] = 0x0080,     /* R1719  - OUT4LMIX Input 4 Volume */
+       [0x06B8] = 0x0000,     /* R1720  - OUT4RMIX Input 1 Source */
+       [0x06B9] = 0x0080,     /* R1721  - OUT4RMIX Input 1 Volume */
+       [0x06BA] = 0x0000,     /* R1722  - OUT4RMIX Input 2 Source */
+       [0x06BB] = 0x0080,     /* R1723  - OUT4RMIX Input 2 Volume */
+       [0x06BC] = 0x0000,     /* R1724  - OUT4RMIX Input 3 Source */
+       [0x06BD] = 0x0080,     /* R1725  - OUT4RMIX Input 3 Volume */
+       [0x06BE] = 0x0000,     /* R1726  - OUT4RMIX Input 4 Source */
+       [0x06BF] = 0x0080,     /* R1727  - OUT4RMIX Input 4 Volume */
+       [0x06C0] = 0x0000,     /* R1728  - OUT5LMIX Input 1 Source */
+       [0x06C1] = 0x0080,     /* R1729  - OUT5LMIX Input 1 Volume */
+       [0x06C2] = 0x0000,     /* R1730  - OUT5LMIX Input 2 Source */
+       [0x06C3] = 0x0080,     /* R1731  - OUT5LMIX Input 2 Volume */
+       [0x06C4] = 0x0000,     /* R1732  - OUT5LMIX Input 3 Source */
+       [0x06C5] = 0x0080,     /* R1733  - OUT5LMIX Input 3 Volume */
+       [0x06C6] = 0x0000,     /* R1734  - OUT5LMIX Input 4 Source */
+       [0x06C7] = 0x0080,     /* R1735  - OUT5LMIX Input 4 Volume */
+       [0x06C8] = 0x0000,     /* R1736  - OUT5RMIX Input 1 Source */
+       [0x06C9] = 0x0080,     /* R1737  - OUT5RMIX Input 1 Volume */
+       [0x06CA] = 0x0000,     /* R1738  - OUT5RMIX Input 2 Source */
+       [0x06CB] = 0x0080,     /* R1739  - OUT5RMIX Input 2 Volume */
+       [0x06CC] = 0x0000,     /* R1740  - OUT5RMIX Input 3 Source */
+       [0x06CD] = 0x0080,     /* R1741  - OUT5RMIX Input 3 Volume */
+       [0x06CE] = 0x0000,     /* R1742  - OUT5RMIX Input 4 Source */
+       [0x06CF] = 0x0080,     /* R1743  - OUT5RMIX Input 4 Volume */
+       [0x06D0] = 0x0000,     /* R1744  - OUT6LMIX Input 1 Source */
+       [0x06D1] = 0x0080,     /* R1745  - OUT6LMIX Input 1 Volume */
+       [0x06D2] = 0x0000,     /* R1746  - OUT6LMIX Input 2 Source */
+       [0x06D3] = 0x0080,     /* R1747  - OUT6LMIX Input 2 Volume */
+       [0x06D4] = 0x0000,     /* R1748  - OUT6LMIX Input 3 Source */
+       [0x06D5] = 0x0080,     /* R1749  - OUT6LMIX Input 3 Volume */
+       [0x06D6] = 0x0000,     /* R1750  - OUT6LMIX Input 4 Source */
+       [0x06D7] = 0x0080,     /* R1751  - OUT6LMIX Input 4 Volume */
+       [0x06D8] = 0x0000,     /* R1752  - OUT6RMIX Input 1 Source */
+       [0x06D9] = 0x0080,     /* R1753  - OUT6RMIX Input 1 Volume */
+       [0x06DA] = 0x0000,     /* R1754  - OUT6RMIX Input 2 Source */
+       [0x06DB] = 0x0080,     /* R1755  - OUT6RMIX Input 2 Volume */
+       [0x06DC] = 0x0000,     /* R1756  - OUT6RMIX Input 3 Source */
+       [0x06DD] = 0x0080,     /* R1757  - OUT6RMIX Input 3 Volume */
+       [0x06DE] = 0x0000,     /* R1758  - OUT6RMIX Input 4 Source */
+       [0x06DF] = 0x0080,     /* R1759  - OUT6RMIX Input 4 Volume */
+       [0x0700] = 0x0000,     /* R1792  - AIF1TX1MIX Input 1 Source */
+       [0x0701] = 0x0080,     /* R1793  - AIF1TX1MIX Input 1 Volume */
+       [0x0702] = 0x0000,     /* R1794  - AIF1TX1MIX Input 2 Source */
+       [0x0703] = 0x0080,     /* R1795  - AIF1TX1MIX Input 2 Volume */
+       [0x0704] = 0x0000,     /* R1796  - AIF1TX1MIX Input 3 Source */
+       [0x0705] = 0x0080,     /* R1797  - AIF1TX1MIX Input 3 Volume */
+       [0x0706] = 0x0000,     /* R1798  - AIF1TX1MIX Input 4 Source */
+       [0x0707] = 0x0080,     /* R1799  - AIF1TX1MIX Input 4 Volume */
+       [0x0708] = 0x0000,     /* R1800  - AIF1TX2MIX Input 1 Source */
+       [0x0709] = 0x0080,     /* R1801  - AIF1TX2MIX Input 1 Volume */
+       [0x070A] = 0x0000,     /* R1802  - AIF1TX2MIX Input 2 Source */
+       [0x070B] = 0x0080,     /* R1803  - AIF1TX2MIX Input 2 Volume */
+       [0x070C] = 0x0000,     /* R1804  - AIF1TX2MIX Input 3 Source */
+       [0x070D] = 0x0080,     /* R1805  - AIF1TX2MIX Input 3 Volume */
+       [0x070E] = 0x0000,     /* R1806  - AIF1TX2MIX Input 4 Source */
+       [0x070F] = 0x0080,     /* R1807  - AIF1TX2MIX Input 4 Volume */
+       [0x0710] = 0x0000,     /* R1808  - AIF1TX3MIX Input 1 Source */
+       [0x0711] = 0x0080,     /* R1809  - AIF1TX3MIX Input 1 Volume */
+       [0x0712] = 0x0000,     /* R1810  - AIF1TX3MIX Input 2 Source */
+       [0x0713] = 0x0080,     /* R1811  - AIF1TX3MIX Input 2 Volume */
+       [0x0714] = 0x0000,     /* R1812  - AIF1TX3MIX Input 3 Source */
+       [0x0715] = 0x0080,     /* R1813  - AIF1TX3MIX Input 3 Volume */
+       [0x0716] = 0x0000,     /* R1814  - AIF1TX3MIX Input 4 Source */
+       [0x0717] = 0x0080,     /* R1815  - AIF1TX3MIX Input 4 Volume */
+       [0x0718] = 0x0000,     /* R1816  - AIF1TX4MIX Input 1 Source */
+       [0x0719] = 0x0080,     /* R1817  - AIF1TX4MIX Input 1 Volume */
+       [0x071A] = 0x0000,     /* R1818  - AIF1TX4MIX Input 2 Source */
+       [0x071B] = 0x0080,     /* R1819  - AIF1TX4MIX Input 2 Volume */
+       [0x071C] = 0x0000,     /* R1820  - AIF1TX4MIX Input 3 Source */
+       [0x071D] = 0x0080,     /* R1821  - AIF1TX4MIX Input 3 Volume */
+       [0x071E] = 0x0000,     /* R1822  - AIF1TX4MIX Input 4 Source */
+       [0x071F] = 0x0080,     /* R1823  - AIF1TX4MIX Input 4 Volume */
+       [0x0720] = 0x0000,     /* R1824  - AIF1TX5MIX Input 1 Source */
+       [0x0721] = 0x0080,     /* R1825  - AIF1TX5MIX Input 1 Volume */
+       [0x0722] = 0x0000,     /* R1826  - AIF1TX5MIX Input 2 Source */
+       [0x0723] = 0x0080,     /* R1827  - AIF1TX5MIX Input 2 Volume */
+       [0x0724] = 0x0000,     /* R1828  - AIF1TX5MIX Input 3 Source */
+       [0x0725] = 0x0080,     /* R1829  - AIF1TX5MIX Input 3 Volume */
+       [0x0726] = 0x0000,     /* R1830  - AIF1TX5MIX Input 4 Source */
+       [0x0727] = 0x0080,     /* R1831  - AIF1TX5MIX Input 4 Volume */
+       [0x0728] = 0x0000,     /* R1832  - AIF1TX6MIX Input 1 Source */
+       [0x0729] = 0x0080,     /* R1833  - AIF1TX6MIX Input 1 Volume */
+       [0x072A] = 0x0000,     /* R1834  - AIF1TX6MIX Input 2 Source */
+       [0x072B] = 0x0080,     /* R1835  - AIF1TX6MIX Input 2 Volume */
+       [0x072C] = 0x0000,     /* R1836  - AIF1TX6MIX Input 3 Source */
+       [0x072D] = 0x0080,     /* R1837  - AIF1TX6MIX Input 3 Volume */
+       [0x072E] = 0x0000,     /* R1838  - AIF1TX6MIX Input 4 Source */
+       [0x072F] = 0x0080,     /* R1839  - AIF1TX6MIX Input 4 Volume */
+       [0x0730] = 0x0000,     /* R1840  - AIF1TX7MIX Input 1 Source */
+       [0x0731] = 0x0080,     /* R1841  - AIF1TX7MIX Input 1 Volume */
+       [0x0732] = 0x0000,     /* R1842  - AIF1TX7MIX Input 2 Source */
+       [0x0733] = 0x0080,     /* R1843  - AIF1TX7MIX Input 2 Volume */
+       [0x0734] = 0x0000,     /* R1844  - AIF1TX7MIX Input 3 Source */
+       [0x0735] = 0x0080,     /* R1845  - AIF1TX7MIX Input 3 Volume */
+       [0x0736] = 0x0000,     /* R1846  - AIF1TX7MIX Input 4 Source */
+       [0x0737] = 0x0080,     /* R1847  - AIF1TX7MIX Input 4 Volume */
+       [0x0738] = 0x0000,     /* R1848  - AIF1TX8MIX Input 1 Source */
+       [0x0739] = 0x0080,     /* R1849  - AIF1TX8MIX Input 1 Volume */
+       [0x073A] = 0x0000,     /* R1850  - AIF1TX8MIX Input 2 Source */
+       [0x073B] = 0x0080,     /* R1851  - AIF1TX8MIX Input 2 Volume */
+       [0x073C] = 0x0000,     /* R1852  - AIF1TX8MIX Input 3 Source */
+       [0x073D] = 0x0080,     /* R1853  - AIF1TX8MIX Input 3 Volume */
+       [0x073E] = 0x0000,     /* R1854  - AIF1TX8MIX Input 4 Source */
+       [0x073F] = 0x0080,     /* R1855  - AIF1TX8MIX Input 4 Volume */
+       [0x0740] = 0x0000,     /* R1856  - AIF2TX1MIX Input 1 Source */
+       [0x0741] = 0x0080,     /* R1857  - AIF2TX1MIX Input 1 Volume */
+       [0x0742] = 0x0000,     /* R1858  - AIF2TX1MIX Input 2 Source */
+       [0x0743] = 0x0080,     /* R1859  - AIF2TX1MIX Input 2 Volume */
+       [0x0744] = 0x0000,     /* R1860  - AIF2TX1MIX Input 3 Source */
+       [0x0745] = 0x0080,     /* R1861  - AIF2TX1MIX Input 3 Volume */
+       [0x0746] = 0x0000,     /* R1862  - AIF2TX1MIX Input 4 Source */
+       [0x0747] = 0x0080,     /* R1863  - AIF2TX1MIX Input 4 Volume */
+       [0x0748] = 0x0000,     /* R1864  - AIF2TX2MIX Input 1 Source */
+       [0x0749] = 0x0080,     /* R1865  - AIF2TX2MIX Input 1 Volume */
+       [0x074A] = 0x0000,     /* R1866  - AIF2TX2MIX Input 2 Source */
+       [0x074B] = 0x0080,     /* R1867  - AIF2TX2MIX Input 2 Volume */
+       [0x074C] = 0x0000,     /* R1868  - AIF2TX2MIX Input 3 Source */
+       [0x074D] = 0x0080,     /* R1869  - AIF2TX2MIX Input 3 Volume */
+       [0x074E] = 0x0000,     /* R1870  - AIF2TX2MIX Input 4 Source */
+       [0x074F] = 0x0080,     /* R1871  - AIF2TX2MIX Input 4 Volume */
+       [0x0780] = 0x0000,     /* R1920  - AIF3TX1MIX Input 1 Source */
+       [0x0781] = 0x0080,     /* R1921  - AIF3TX1MIX Input 1 Volume */
+       [0x0782] = 0x0000,     /* R1922  - AIF3TX1MIX Input 2 Source */
+       [0x0783] = 0x0080,     /* R1923  - AIF3TX1MIX Input 2 Volume */
+       [0x0784] = 0x0000,     /* R1924  - AIF3TX1MIX Input 3 Source */
+       [0x0785] = 0x0080,     /* R1925  - AIF3TX1MIX Input 3 Volume */
+       [0x0786] = 0x0000,     /* R1926  - AIF3TX1MIX Input 4 Source */
+       [0x0787] = 0x0080,     /* R1927  - AIF3TX1MIX Input 4 Volume */
+       [0x0788] = 0x0000,     /* R1928  - AIF3TX2MIX Input 1 Source */
+       [0x0789] = 0x0080,     /* R1929  - AIF3TX2MIX Input 1 Volume */
+       [0x078A] = 0x0000,     /* R1930  - AIF3TX2MIX Input 2 Source */
+       [0x078B] = 0x0080,     /* R1931  - AIF3TX2MIX Input 2 Volume */
+       [0x078C] = 0x0000,     /* R1932  - AIF3TX2MIX Input 3 Source */
+       [0x078D] = 0x0080,     /* R1933  - AIF3TX2MIX Input 3 Volume */
+       [0x078E] = 0x0000,     /* R1934  - AIF3TX2MIX Input 4 Source */
+       [0x078F] = 0x0080,     /* R1935  - AIF3TX2MIX Input 4 Volume */
+       [0x0880] = 0x0000,     /* R2176  - EQ1MIX Input 1 Source */
+       [0x0881] = 0x0080,     /* R2177  - EQ1MIX Input 1 Volume */
+       [0x0882] = 0x0000,     /* R2178  - EQ1MIX Input 2 Source */
+       [0x0883] = 0x0080,     /* R2179  - EQ1MIX Input 2 Volume */
+       [0x0884] = 0x0000,     /* R2180  - EQ1MIX Input 3 Source */
+       [0x0885] = 0x0080,     /* R2181  - EQ1MIX Input 3 Volume */
+       [0x0886] = 0x0000,     /* R2182  - EQ1MIX Input 4 Source */
+       [0x0887] = 0x0080,     /* R2183  - EQ1MIX Input 4 Volume */
+       [0x0888] = 0x0000,     /* R2184  - EQ2MIX Input 1 Source */
+       [0x0889] = 0x0080,     /* R2185  - EQ2MIX Input 1 Volume */
+       [0x088A] = 0x0000,     /* R2186  - EQ2MIX Input 2 Source */
+       [0x088B] = 0x0080,     /* R2187  - EQ2MIX Input 2 Volume */
+       [0x088C] = 0x0000,     /* R2188  - EQ2MIX Input 3 Source */
+       [0x088D] = 0x0080,     /* R2189  - EQ2MIX Input 3 Volume */
+       [0x088E] = 0x0000,     /* R2190  - EQ2MIX Input 4 Source */
+       [0x088F] = 0x0080,     /* R2191  - EQ2MIX Input 4 Volume */
+       [0x0890] = 0x0000,     /* R2192  - EQ3MIX Input 1 Source */
+       [0x0891] = 0x0080,     /* R2193  - EQ3MIX Input 1 Volume */
+       [0x0892] = 0x0000,     /* R2194  - EQ3MIX Input 2 Source */
+       [0x0893] = 0x0080,     /* R2195  - EQ3MIX Input 2 Volume */
+       [0x0894] = 0x0000,     /* R2196  - EQ3MIX Input 3 Source */
+       [0x0895] = 0x0080,     /* R2197  - EQ3MIX Input 3 Volume */
+       [0x0896] = 0x0000,     /* R2198  - EQ3MIX Input 4 Source */
+       [0x0897] = 0x0080,     /* R2199  - EQ3MIX Input 4 Volume */
+       [0x0898] = 0x0000,     /* R2200  - EQ4MIX Input 1 Source */
+       [0x0899] = 0x0080,     /* R2201  - EQ4MIX Input 1 Volume */
+       [0x089A] = 0x0000,     /* R2202  - EQ4MIX Input 2 Source */
+       [0x089B] = 0x0080,     /* R2203  - EQ4MIX Input 2 Volume */
+       [0x089C] = 0x0000,     /* R2204  - EQ4MIX Input 3 Source */
+       [0x089D] = 0x0080,     /* R2205  - EQ4MIX Input 3 Volume */
+       [0x089E] = 0x0000,     /* R2206  - EQ4MIX Input 4 Source */
+       [0x089F] = 0x0080,     /* R2207  - EQ4MIX Input 4 Volume */
+       [0x08C0] = 0x0000,     /* R2240  - DRC1LMIX Input 1 Source */
+       [0x08C1] = 0x0080,     /* R2241  - DRC1LMIX Input 1 Volume */
+       [0x08C2] = 0x0000,     /* R2242  - DRC1LMIX Input 2 Source */
+       [0x08C3] = 0x0080,     /* R2243  - DRC1LMIX Input 2 Volume */
+       [0x08C4] = 0x0000,     /* R2244  - DRC1LMIX Input 3 Source */
+       [0x08C5] = 0x0080,     /* R2245  - DRC1LMIX Input 3 Volume */
+       [0x08C6] = 0x0000,     /* R2246  - DRC1LMIX Input 4 Source */
+       [0x08C7] = 0x0080,     /* R2247  - DRC1LMIX Input 4 Volume */
+       [0x08C8] = 0x0000,     /* R2248  - DRC1RMIX Input 1 Source */
+       [0x08C9] = 0x0080,     /* R2249  - DRC1RMIX Input 1 Volume */
+       [0x08CA] = 0x0000,     /* R2250  - DRC1RMIX Input 2 Source */
+       [0x08CB] = 0x0080,     /* R2251  - DRC1RMIX Input 2 Volume */
+       [0x08CC] = 0x0000,     /* R2252  - DRC1RMIX Input 3 Source */
+       [0x08CD] = 0x0080,     /* R2253  - DRC1RMIX Input 3 Volume */
+       [0x08CE] = 0x0000,     /* R2254  - DRC1RMIX Input 4 Source */
+       [0x08CF] = 0x0080,     /* R2255  - DRC1RMIX Input 4 Volume */
+       [0x0900] = 0x0000,     /* R2304  - HPLP1MIX Input 1 Source */
+       [0x0901] = 0x0080,     /* R2305  - HPLP1MIX Input 1 Volume */
+       [0x0902] = 0x0000,     /* R2306  - HPLP1MIX Input 2 Source */
+       [0x0903] = 0x0080,     /* R2307  - HPLP1MIX Input 2 Volume */
+       [0x0904] = 0x0000,     /* R2308  - HPLP1MIX Input 3 Source */
+       [0x0905] = 0x0080,     /* R2309  - HPLP1MIX Input 3 Volume */
+       [0x0906] = 0x0000,     /* R2310  - HPLP1MIX Input 4 Source */
+       [0x0907] = 0x0080,     /* R2311  - HPLP1MIX Input 4 Volume */
+       [0x0908] = 0x0000,     /* R2312  - HPLP2MIX Input 1 Source */
+       [0x0909] = 0x0080,     /* R2313  - HPLP2MIX Input 1 Volume */
+       [0x090A] = 0x0000,     /* R2314  - HPLP2MIX Input 2 Source */
+       [0x090B] = 0x0080,     /* R2315  - HPLP2MIX Input 2 Volume */
+       [0x090C] = 0x0000,     /* R2316  - HPLP2MIX Input 3 Source */
+       [0x090D] = 0x0080,     /* R2317  - HPLP2MIX Input 3 Volume */
+       [0x090E] = 0x0000,     /* R2318  - HPLP2MIX Input 4 Source */
+       [0x090F] = 0x0080,     /* R2319  - HPLP2MIX Input 4 Volume */
+       [0x0910] = 0x0000,     /* R2320  - HPLP3MIX Input 1 Source */
+       [0x0911] = 0x0080,     /* R2321  - HPLP3MIX Input 1 Volume */
+       [0x0912] = 0x0000,     /* R2322  - HPLP3MIX Input 2 Source */
+       [0x0913] = 0x0080,     /* R2323  - HPLP3MIX Input 2 Volume */
+       [0x0914] = 0x0000,     /* R2324  - HPLP3MIX Input 3 Source */
+       [0x0915] = 0x0080,     /* R2325  - HPLP3MIX Input 3 Volume */
+       [0x0916] = 0x0000,     /* R2326  - HPLP3MIX Input 4 Source */
+       [0x0917] = 0x0080,     /* R2327  - HPLP3MIX Input 4 Volume */
+       [0x0918] = 0x0000,     /* R2328  - HPLP4MIX Input 1 Source */
+       [0x0919] = 0x0080,     /* R2329  - HPLP4MIX Input 1 Volume */
+       [0x091A] = 0x0000,     /* R2330  - HPLP4MIX Input 2 Source */
+       [0x091B] = 0x0080,     /* R2331  - HPLP4MIX Input 2 Volume */
+       [0x091C] = 0x0000,     /* R2332  - HPLP4MIX Input 3 Source */
+       [0x091D] = 0x0080,     /* R2333  - HPLP4MIX Input 3 Volume */
+       [0x091E] = 0x0000,     /* R2334  - HPLP4MIX Input 4 Source */
+       [0x091F] = 0x0080,     /* R2335  - HPLP4MIX Input 4 Volume */
+       [0x0940] = 0x0000,     /* R2368  - DSP1LMIX Input 1 Source */
+       [0x0941] = 0x0080,     /* R2369  - DSP1LMIX Input 1 Volume */
+       [0x0942] = 0x0000,     /* R2370  - DSP1LMIX Input 2 Source */
+       [0x0943] = 0x0080,     /* R2371  - DSP1LMIX Input 2 Volume */
+       [0x0944] = 0x0000,     /* R2372  - DSP1LMIX Input 3 Source */
+       [0x0945] = 0x0080,     /* R2373  - DSP1LMIX Input 3 Volume */
+       [0x0946] = 0x0000,     /* R2374  - DSP1LMIX Input 4 Source */
+       [0x0947] = 0x0080,     /* R2375  - DSP1LMIX Input 4 Volume */
+       [0x0948] = 0x0000,     /* R2376  - DSP1RMIX Input 1 Source */
+       [0x0949] = 0x0080,     /* R2377  - DSP1RMIX Input 1 Volume */
+       [0x094A] = 0x0000,     /* R2378  - DSP1RMIX Input 2 Source */
+       [0x094B] = 0x0080,     /* R2379  - DSP1RMIX Input 2 Volume */
+       [0x094C] = 0x0000,     /* R2380  - DSP1RMIX Input 3 Source */
+       [0x094D] = 0x0080,     /* R2381  - DSP1RMIX Input 3 Volume */
+       [0x094E] = 0x0000,     /* R2382  - DSP1RMIX Input 4 Source */
+       [0x094F] = 0x0080,     /* R2383  - DSP1RMIX Input 4 Volume */
+       [0x0950] = 0x0000,     /* R2384  - DSP1AUX1MIX Input 1 Source */
+       [0x0958] = 0x0000,     /* R2392  - DSP1AUX2MIX Input 1 Source */
+       [0x0960] = 0x0000,     /* R2400  - DSP1AUX3MIX Input 1 Source */
+       [0x0968] = 0x0000,     /* R2408  - DSP1AUX4MIX Input 1 Source */
+       [0x0970] = 0x0000,     /* R2416  - DSP1AUX5MIX Input 1 Source */
+       [0x0978] = 0x0000,     /* R2424  - DSP1AUX6MIX Input 1 Source */
+       [0x0980] = 0x0000,     /* R2432  - DSP2LMIX Input 1 Source */
+       [0x0981] = 0x0080,     /* R2433  - DSP2LMIX Input 1 Volume */
+       [0x0982] = 0x0000,     /* R2434  - DSP2LMIX Input 2 Source */
+       [0x0983] = 0x0080,     /* R2435  - DSP2LMIX Input 2 Volume */
+       [0x0984] = 0x0000,     /* R2436  - DSP2LMIX Input 3 Source */
+       [0x0985] = 0x0080,     /* R2437  - DSP2LMIX Input 3 Volume */
+       [0x0986] = 0x0000,     /* R2438  - DSP2LMIX Input 4 Source */
+       [0x0987] = 0x0080,     /* R2439  - DSP2LMIX Input 4 Volume */
+       [0x0988] = 0x0000,     /* R2440  - DSP2RMIX Input 1 Source */
+       [0x0989] = 0x0080,     /* R2441  - DSP2RMIX Input 1 Volume */
+       [0x098A] = 0x0000,     /* R2442  - DSP2RMIX Input 2 Source */
+       [0x098B] = 0x0080,     /* R2443  - DSP2RMIX Input 2 Volume */
+       [0x098C] = 0x0000,     /* R2444  - DSP2RMIX Input 3 Source */
+       [0x098D] = 0x0080,     /* R2445  - DSP2RMIX Input 3 Volume */
+       [0x098E] = 0x0000,     /* R2446  - DSP2RMIX Input 4 Source */
+       [0x098F] = 0x0080,     /* R2447  - DSP2RMIX Input 4 Volume */
+       [0x0990] = 0x0000,     /* R2448  - DSP2AUX1MIX Input 1 Source */
+       [0x0998] = 0x0000,     /* R2456  - DSP2AUX2MIX Input 1 Source */
+       [0x09A0] = 0x0000,     /* R2464  - DSP2AUX3MIX Input 1 Source */
+       [0x09A8] = 0x0000,     /* R2472  - DSP2AUX4MIX Input 1 Source */
+       [0x09B0] = 0x0000,     /* R2480  - DSP2AUX5MIX Input 1 Source */
+       [0x09B8] = 0x0000,     /* R2488  - DSP2AUX6MIX Input 1 Source */
+       [0x09C0] = 0x0000,     /* R2496  - DSP3LMIX Input 1 Source */
+       [0x09C1] = 0x0080,     /* R2497  - DSP3LMIX Input 1 Volume */
+       [0x09C2] = 0x0000,     /* R2498  - DSP3LMIX Input 2 Source */
+       [0x09C3] = 0x0080,     /* R2499  - DSP3LMIX Input 2 Volume */
+       [0x09C4] = 0x0000,     /* R2500  - DSP3LMIX Input 3 Source */
+       [0x09C5] = 0x0080,     /* R2501  - DSP3LMIX Input 3 Volume */
+       [0x09C6] = 0x0000,     /* R2502  - DSP3LMIX Input 4 Source */
+       [0x09C7] = 0x0080,     /* R2503  - DSP3LMIX Input 4 Volume */
+       [0x09C8] = 0x0000,     /* R2504  - DSP3RMIX Input 1 Source */
+       [0x09C9] = 0x0080,     /* R2505  - DSP3RMIX Input 1 Volume */
+       [0x09CA] = 0x0000,     /* R2506  - DSP3RMIX Input 2 Source */
+       [0x09CB] = 0x0080,     /* R2507  - DSP3RMIX Input 2 Volume */
+       [0x09CC] = 0x0000,     /* R2508  - DSP3RMIX Input 3 Source */
+       [0x09CD] = 0x0080,     /* R2509  - DSP3RMIX Input 3 Volume */
+       [0x09CE] = 0x0000,     /* R2510  - DSP3RMIX Input 4 Source */
+       [0x09CF] = 0x0080,     /* R2511  - DSP3RMIX Input 4 Volume */
+       [0x09D0] = 0x0000,     /* R2512  - DSP3AUX1MIX Input 1 Source */
+       [0x09D8] = 0x0000,     /* R2520  - DSP3AUX2MIX Input 1 Source */
+       [0x09E0] = 0x0000,     /* R2528  - DSP3AUX3MIX Input 1 Source */
+       [0x09E8] = 0x0000,     /* R2536  - DSP3AUX4MIX Input 1 Source */
+       [0x09F0] = 0x0000,     /* R2544  - DSP3AUX5MIX Input 1 Source */
+       [0x09F8] = 0x0000,     /* R2552  - DSP3AUX6MIX Input 1 Source */
+       [0x0A80] = 0x0000,     /* R2688  - ASRC1LMIX Input 1 Source */
+       [0x0A88] = 0x0000,     /* R2696  - ASRC1RMIX Input 1 Source */
+       [0x0A90] = 0x0000,     /* R2704  - ASRC2LMIX Input 1 Source */
+       [0x0A98] = 0x0000,     /* R2712  - ASRC2RMIX Input 1 Source */
+       [0x0B00] = 0x0000,     /* R2816  - ISRC1DEC1MIX Input 1 Source */
+       [0x0B08] = 0x0000,     /* R2824  - ISRC1DEC2MIX Input 1 Source */
+       [0x0B10] = 0x0000,     /* R2832  - ISRC1DEC3MIX Input 1 Source */
+       [0x0B18] = 0x0000,     /* R2840  - ISRC1DEC4MIX Input 1 Source */
+       [0x0B20] = 0x0000,     /* R2848  - ISRC1INT1MIX Input 1 Source */
+       [0x0B28] = 0x0000,     /* R2856  - ISRC1INT2MIX Input 1 Source */
+       [0x0B30] = 0x0000,     /* R2864  - ISRC1INT3MIX Input 1 Source */
+       [0x0B38] = 0x0000,     /* R2872  - ISRC1INT4MIX Input 1 Source */
+       [0x0B40] = 0x0000,     /* R2880  - ISRC2DEC1MIX Input 1 Source */
+       [0x0B48] = 0x0000,     /* R2888  - ISRC2DEC2MIX Input 1 Source */
+       [0x0B50] = 0x0000,     /* R2896  - ISRC2DEC3MIX Input 1 Source */
+       [0x0B58] = 0x0000,     /* R2904  - ISRC2DEC4MIX Input 1 Source */
+       [0x0B60] = 0x0000,     /* R2912  - ISRC2INT1MIX Input 1 Source */
+       [0x0B68] = 0x0000,     /* R2920  - ISRC2INT2MIX Input 1 Source */
+       [0x0B70] = 0x0000,     /* R2928  - ISRC2INT3MIX Input 1 Source */
+       [0x0B78] = 0x0000,     /* R2936  - ISRC2INT4MIX Input 1 Source */
+       [0x0C00] = 0xA001,     /* R3072  - GPIO CTRL 1 */
+       [0x0C01] = 0xA001,     /* R3073  - GPIO CTRL 2 */
+       [0x0C02] = 0xA001,     /* R3074  - GPIO CTRL 3 */
+       [0x0C03] = 0xA001,     /* R3075  - GPIO CTRL 4 */
+       [0x0C04] = 0xA001,     /* R3076  - GPIO CTRL 5 */
+       [0x0C05] = 0xA001,     /* R3077  - GPIO CTRL 6 */
+       [0x0C23] = 0x4003,     /* R3107  - Misc Pad Ctrl 1 */
+       [0x0C24] = 0x0000,     /* R3108  - Misc Pad Ctrl 2 */
+       [0x0C25] = 0x0000,     /* R3109  - Misc Pad Ctrl 3 */
+       [0x0C26] = 0x0000,     /* R3110  - Misc Pad Ctrl 4 */
+       [0x0C27] = 0x0000,     /* R3111  - Misc Pad Ctrl 5 */
+       [0x0C28] = 0x0000,     /* R3112  - Misc GPIO 1 */
+       [0x0D00] = 0x0000,     /* R3328  - Interrupt Status 1 */
+       [0x0D01] = 0x0000,     /* R3329  - Interrupt Status 2 */
+       [0x0D02] = 0x0000,     /* R3330  - Interrupt Status 3 */
+       [0x0D03] = 0x0000,     /* R3331  - Interrupt Status 4 */
+       [0x0D04] = 0x0000,     /* R3332  - Interrupt Raw Status 2 */
+       [0x0D05] = 0x0000,     /* R3333  - Interrupt Raw Status 3 */
+       [0x0D06] = 0x0000,     /* R3334  - Interrupt Raw Status 4 */
+       [0x0D07] = 0xFFFF,     /* R3335  - Interrupt Status 1 Mask */
+       [0x0D08] = 0xFFFF,     /* R3336  - Interrupt Status 2 Mask */
+       [0x0D09] = 0xFFFF,     /* R3337  - Interrupt Status 3 Mask */
+       [0x0D0A] = 0xFFFF,     /* R3338  - Interrupt Status 4 Mask */
+       [0x0D1F] = 0x0000,     /* R3359  - Interrupt Control */
+       [0x0D20] = 0xFFFF,     /* R3360  - IRQ Debounce 1 */
+       [0x0D21] = 0xFFFF,     /* R3361  - IRQ Debounce 2 */
+       [0x0E00] = 0x0000,     /* R3584  - FX_Ctrl */
+       [0x0E10] = 0x6318,     /* R3600  - EQ1_1 */
+       [0x0E11] = 0x6300,     /* R3601  - EQ1_2 */
+       [0x0E12] = 0x0FC8,     /* R3602  - EQ1_3 */
+       [0x0E13] = 0x03FE,     /* R3603  - EQ1_4 */
+       [0x0E14] = 0x00E0,     /* R3604  - EQ1_5 */
+       [0x0E15] = 0x1EC4,     /* R3605  - EQ1_6 */
+       [0x0E16] = 0xF136,     /* R3606  - EQ1_7 */
+       [0x0E17] = 0x0409,     /* R3607  - EQ1_8 */
+       [0x0E18] = 0x04CC,     /* R3608  - EQ1_9 */
+       [0x0E19] = 0x1C9B,     /* R3609  - EQ1_10 */
+       [0x0E1A] = 0xF337,     /* R3610  - EQ1_11 */
+       [0x0E1B] = 0x040B,     /* R3611  - EQ1_12 */
+       [0x0E1C] = 0x0CBB,     /* R3612  - EQ1_13 */
+       [0x0E1D] = 0x16F8,     /* R3613  - EQ1_14 */
+       [0x0E1E] = 0xF7D9,     /* R3614  - EQ1_15 */
+       [0x0E1F] = 0x040A,     /* R3615  - EQ1_16 */
+       [0x0E20] = 0x1F14,     /* R3616  - EQ1_17 */
+       [0x0E21] = 0x058C,     /* R3617  - EQ1_18 */
+       [0x0E22] = 0x0563,     /* R3618  - EQ1_19 */
+       [0x0E23] = 0x4000,     /* R3619  - EQ1_20 */
+       [0x0E26] = 0x6318,     /* R3622  - EQ2_1 */
+       [0x0E27] = 0x6300,     /* R3623  - EQ2_2 */
+       [0x0E28] = 0x0FC8,     /* R3624  - EQ2_3 */
+       [0x0E29] = 0x03FE,     /* R3625  - EQ2_4 */
+       [0x0E2A] = 0x00E0,     /* R3626  - EQ2_5 */
+       [0x0E2B] = 0x1EC4,     /* R3627  - EQ2_6 */
+       [0x0E2C] = 0xF136,     /* R3628  - EQ2_7 */
+       [0x0E2D] = 0x0409,     /* R3629  - EQ2_8 */
+       [0x0E2E] = 0x04CC,     /* R3630  - EQ2_9 */
+       [0x0E2F] = 0x1C9B,     /* R3631  - EQ2_10 */
+       [0x0E30] = 0xF337,     /* R3632  - EQ2_11 */
+       [0x0E31] = 0x040B,     /* R3633  - EQ2_12 */
+       [0x0E32] = 0x0CBB,     /* R3634  - EQ2_13 */
+       [0x0E33] = 0x16F8,     /* R3635  - EQ2_14 */
+       [0x0E34] = 0xF7D9,     /* R3636  - EQ2_15 */
+       [0x0E35] = 0x040A,     /* R3637  - EQ2_16 */
+       [0x0E36] = 0x1F14,     /* R3638  - EQ2_17 */
+       [0x0E37] = 0x058C,     /* R3639  - EQ2_18 */
+       [0x0E38] = 0x0563,     /* R3640  - EQ2_19 */
+       [0x0E39] = 0x4000,     /* R3641  - EQ2_20 */
+       [0x0E3C] = 0x6318,     /* R3644  - EQ3_1 */
+       [0x0E3D] = 0x6300,     /* R3645  - EQ3_2 */
+       [0x0E3E] = 0x0FC8,     /* R3646  - EQ3_3 */
+       [0x0E3F] = 0x03FE,     /* R3647  - EQ3_4 */
+       [0x0E40] = 0x00E0,     /* R3648  - EQ3_5 */
+       [0x0E41] = 0x1EC4,     /* R3649  - EQ3_6 */
+       [0x0E42] = 0xF136,     /* R3650  - EQ3_7 */
+       [0x0E43] = 0x0409,     /* R3651  - EQ3_8 */
+       [0x0E44] = 0x04CC,     /* R3652  - EQ3_9 */
+       [0x0E45] = 0x1C9B,     /* R3653  - EQ3_10 */
+       [0x0E46] = 0xF337,     /* R3654  - EQ3_11 */
+       [0x0E47] = 0x040B,     /* R3655  - EQ3_12 */
+       [0x0E48] = 0x0CBB,     /* R3656  - EQ3_13 */
+       [0x0E49] = 0x16F8,     /* R3657  - EQ3_14 */
+       [0x0E4A] = 0xF7D9,     /* R3658  - EQ3_15 */
+       [0x0E4B] = 0x040A,     /* R3659  - EQ3_16 */
+       [0x0E4C] = 0x1F14,     /* R3660  - EQ3_17 */
+       [0x0E4D] = 0x058C,     /* R3661  - EQ3_18 */
+       [0x0E4E] = 0x0563,     /* R3662  - EQ3_19 */
+       [0x0E4F] = 0x4000,     /* R3663  - EQ3_20 */
+       [0x0E52] = 0x6318,     /* R3666  - EQ4_1 */
+       [0x0E53] = 0x6300,     /* R3667  - EQ4_2 */
+       [0x0E54] = 0x0FC8,     /* R3668  - EQ4_3 */
+       [0x0E55] = 0x03FE,     /* R3669  - EQ4_4 */
+       [0x0E56] = 0x00E0,     /* R3670  - EQ4_5 */
+       [0x0E57] = 0x1EC4,     /* R3671  - EQ4_6 */
+       [0x0E58] = 0xF136,     /* R3672  - EQ4_7 */
+       [0x0E59] = 0x0409,     /* R3673  - EQ4_8 */
+       [0x0E5A] = 0x04CC,     /* R3674  - EQ4_9 */
+       [0x0E5B] = 0x1C9B,     /* R3675  - EQ4_10 */
+       [0x0E5C] = 0xF337,     /* R3676  - EQ4_11 */
+       [0x0E5D] = 0x040B,     /* R3677  - EQ4_12 */
+       [0x0E5E] = 0x0CBB,     /* R3678  - EQ4_13 */
+       [0x0E5F] = 0x16F8,     /* R3679  - EQ4_14 */
+       [0x0E60] = 0xF7D9,     /* R3680  - EQ4_15 */
+       [0x0E61] = 0x040A,     /* R3681  - EQ4_16 */
+       [0x0E62] = 0x1F14,     /* R3682  - EQ4_17 */
+       [0x0E63] = 0x058C,     /* R3683  - EQ4_18 */
+       [0x0E64] = 0x0563,     /* R3684  - EQ4_19 */
+       [0x0E65] = 0x4000,     /* R3685  - EQ4_20 */
+       [0x0E80] = 0x0018,     /* R3712  - DRC1 ctrl1 */
+       [0x0E81] = 0x0933,     /* R3713  - DRC1 ctrl2 */
+       [0x0E82] = 0x0018,     /* R3714  - DRC1 ctrl3 */
+       [0x0E83] = 0x0000,     /* R3715  - DRC1 ctrl4 */
+       [0x0E84] = 0x0000,     /* R3716  - DRC1 ctrl5 */
+       [0x0EC0] = 0x0000,     /* R3776  - HPLPF1_1 */
+       [0x0EC1] = 0x0000,     /* R3777  - HPLPF1_2 */
+       [0x0EC4] = 0x0000,     /* R3780  - HPLPF2_1 */
+       [0x0EC5] = 0x0000,     /* R3781  - HPLPF2_2 */
+       [0x0EC8] = 0x0000,     /* R3784  - HPLPF3_1 */
+       [0x0EC9] = 0x0000,     /* R3785  - HPLPF3_2 */
+       [0x0ECC] = 0x0000,     /* R3788  - HPLPF4_1 */
+       [0x0ECD] = 0x0000,     /* R3789  - HPLPF4_2 */
+       [0x4000] = 0x0000,     /* R16384 - DSP1 DM 0 */
+       [0x4001] = 0x0000,     /* R16385 - DSP1 DM 1 */
+       [0x4002] = 0x0000,     /* R16386 - DSP1 DM 2 */
+       [0x4003] = 0x0000,     /* R16387 - DSP1 DM 3 */
+       [0x41FC] = 0x0000,     /* R16892 - DSP1 DM 508 */
+       [0x41FD] = 0x0000,     /* R16893 - DSP1 DM 509 */
+       [0x41FE] = 0x0000,     /* R16894 - DSP1 DM 510 */
+       [0x41FF] = 0x0000,     /* R16895 - DSP1 DM 511 */
+       [0x4800] = 0x0000,     /* R18432 - DSP1 PM 0 */
+       [0x4801] = 0x0000,     /* R18433 - DSP1 PM 1 */
+       [0x4802] = 0x0000,     /* R18434 - DSP1 PM 2 */
+       [0x4803] = 0x0000,     /* R18435 - DSP1 PM 3 */
+       [0x4804] = 0x0000,     /* R18436 - DSP1 PM 4 */
+       [0x4805] = 0x0000,     /* R18437 - DSP1 PM 5 */
+       [0x4DFA] = 0x0000,     /* R19962 - DSP1 PM 1530 */
+       [0x4DFB] = 0x0000,     /* R19963 - DSP1 PM 1531 */
+       [0x4DFC] = 0x0000,     /* R19964 - DSP1 PM 1532 */
+       [0x4DFD] = 0x0000,     /* R19965 - DSP1 PM 1533 */
+       [0x4DFE] = 0x0000,     /* R19966 - DSP1 PM 1534 */
+       [0x4DFF] = 0x0000,     /* R19967 - DSP1 PM 1535 */
+       [0x5000] = 0x0000,     /* R20480 - DSP1 ZM 0 */
+       [0x5001] = 0x0000,     /* R20481 - DSP1 ZM 1 */
+       [0x5002] = 0x0000,     /* R20482 - DSP1 ZM 2 */
+       [0x5003] = 0x0000,     /* R20483 - DSP1 ZM 3 */
+       [0x57FC] = 0x0000,     /* R22524 - DSP1 ZM 2044 */
+       [0x57FD] = 0x0000,     /* R22525 - DSP1 ZM 2045 */
+       [0x57FE] = 0x0000,     /* R22526 - DSP1 ZM 2046 */
+       [0x57FF] = 0x0000,     /* R22527 - DSP1 ZM 2047 */
+       [0x6000] = 0x0000,     /* R24576 - DSP2 DM 0 */
+       [0x6001] = 0x0000,     /* R24577 - DSP2 DM 1 */
+       [0x6002] = 0x0000,     /* R24578 - DSP2 DM 2 */
+       [0x6003] = 0x0000,     /* R24579 - DSP2 DM 3 */
+       [0x61FC] = 0x0000,     /* R25084 - DSP2 DM 508 */
+       [0x61FD] = 0x0000,     /* R25085 - DSP2 DM 509 */
+       [0x61FE] = 0x0000,     /* R25086 - DSP2 DM 510 */
+       [0x61FF] = 0x0000,     /* R25087 - DSP2 DM 511 */
+       [0x6800] = 0x0000,     /* R26624 - DSP2 PM 0 */
+       [0x6801] = 0x0000,     /* R26625 - DSP2 PM 1 */
+       [0x6802] = 0x0000,     /* R26626 - DSP2 PM 2 */
+       [0x6803] = 0x0000,     /* R26627 - DSP2 PM 3 */
+       [0x6804] = 0x0000,     /* R26628 - DSP2 PM 4 */
+       [0x6805] = 0x0000,     /* R26629 - DSP2 PM 5 */
+       [0x6DFA] = 0x0000,     /* R28154 - DSP2 PM 1530 */
+       [0x6DFB] = 0x0000,     /* R28155 - DSP2 PM 1531 */
+       [0x6DFC] = 0x0000,     /* R28156 - DSP2 PM 1532 */
+       [0x6DFD] = 0x0000,     /* R28157 - DSP2 PM 1533 */
+       [0x6DFE] = 0x0000,     /* R28158 - DSP2 PM 1534 */
+       [0x6DFF] = 0x0000,     /* R28159 - DSP2 PM 1535 */
+       [0x7000] = 0x0000,     /* R28672 - DSP2 ZM 0 */
+       [0x7001] = 0x0000,     /* R28673 - DSP2 ZM 1 */
+       [0x7002] = 0x0000,     /* R28674 - DSP2 ZM 2 */
+       [0x7003] = 0x0000,     /* R28675 - DSP2 ZM 3 */
+       [0x77FC] = 0x0000,     /* R30716 - DSP2 ZM 2044 */
+       [0x77FD] = 0x0000,     /* R30717 - DSP2 ZM 2045 */
+       [0x77FE] = 0x0000,     /* R30718 - DSP2 ZM 2046 */
+       [0x77FF] = 0x0000,     /* R30719 - DSP2 ZM 2047 */
+       [0x8000] = 0x0000,     /* R32768 - DSP3 DM 0 */
+       [0x8001] = 0x0000,     /* R32769 - DSP3 DM 1 */
+       [0x8002] = 0x0000,     /* R32770 - DSP3 DM 2 */
+       [0x8003] = 0x0000,     /* R32771 - DSP3 DM 3 */
+       [0x81FC] = 0x0000,     /* R33276 - DSP3 DM 508 */
+       [0x81FD] = 0x0000,     /* R33277 - DSP3 DM 509 */
+       [0x81FE] = 0x0000,     /* R33278 - DSP3 DM 510 */
+       [0x81FF] = 0x0000,     /* R33279 - DSP3 DM 511 */
+       [0x8800] = 0x0000,     /* R34816 - DSP3 PM 0 */
+       [0x8801] = 0x0000,     /* R34817 - DSP3 PM 1 */
+       [0x8802] = 0x0000,     /* R34818 - DSP3 PM 2 */
+       [0x8803] = 0x0000,     /* R34819 - DSP3 PM 3 */
+       [0x8804] = 0x0000,     /* R34820 - DSP3 PM 4 */
+       [0x8805] = 0x0000,     /* R34821 - DSP3 PM 5 */
+       [0x8DFA] = 0x0000,     /* R36346 - DSP3 PM 1530 */
+       [0x8DFB] = 0x0000,     /* R36347 - DSP3 PM 1531 */
+       [0x8DFC] = 0x0000,     /* R36348 - DSP3 PM 1532 */
+       [0x8DFD] = 0x0000,     /* R36349 - DSP3 PM 1533 */
+       [0x8DFE] = 0x0000,     /* R36350 - DSP3 PM 1534 */
+       [0x8DFF] = 0x0000,     /* R36351 - DSP3 PM 1535 */
+       [0x9000] = 0x0000,     /* R36864 - DSP3 ZM 0 */
+       [0x9001] = 0x0000,     /* R36865 - DSP3 ZM 1 */
+       [0x9002] = 0x0000,     /* R36866 - DSP3 ZM 2 */
+       [0x9003] = 0x0000,     /* R36867 - DSP3 ZM 3 */
+       [0x97FC] = 0x0000,     /* R38908 - DSP3 ZM 2044 */
+       [0x97FD] = 0x0000,     /* R38909 - DSP3 ZM 2045 */
+       [0x97FE] = 0x0000,     /* R38910 - DSP3 ZM 2046 */
+       [0x97FF] = 0x0000      /* R38911 - DSP3 ZM 2047 */
+};
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
new file mode 100644 (file)
index 0000000..5d88c99
--- /dev/null
@@ -0,0 +1,2809 @@
+/*
+ * wm5100.c  --  WM5100 ALSA SoC Audio driver
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/gcd.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/fixed.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/wm5100.h>
+
+#include "wm5100.h"
+
+#define WM5100_NUM_CORE_SUPPLIES 2
+static const char *wm5100_core_supply_names[WM5100_NUM_CORE_SUPPLIES] = {
+       "DBVDD1",
+       "LDOVDD", /* If DCVDD is supplied externally specify as LDOVDD */
+};
+
+#define WM5100_AIFS     3
+#define WM5100_SYNC_SRS 3
+
+struct wm5100_fll {
+       int fref;
+       int fout;
+       int src;
+       struct completion lock;
+};
+
+/* codec private data */
+struct wm5100_priv {
+       struct snd_soc_codec *codec;
+
+       struct regulator_bulk_data core_supplies[WM5100_NUM_CORE_SUPPLIES];
+       struct regulator *cpvdd;
+       struct regulator *dbvdd2;
+       struct regulator *dbvdd3;
+
+       int rev;
+
+       int sysclk;
+       int asyncclk;
+
+       bool aif_async[WM5100_AIFS];
+       bool aif_symmetric[WM5100_AIFS];
+       int sr_ref[WM5100_SYNC_SRS];
+
+       bool out_ena[2];
+
+       struct snd_soc_jack *jack;
+       bool jack_detecting;
+       bool jack_mic;
+       int jack_mode;
+
+       struct wm5100_fll fll[2];
+
+       struct wm5100_pdata pdata;
+
+#ifdef CONFIG_GPIOLIB
+       struct gpio_chip gpio_chip;
+#endif
+};
+
+static int wm5100_sr_code[] = {
+       0,
+       12000,
+       24000,
+       48000,
+       96000,
+       192000,
+       384000,
+       768000,
+       0,
+       11025,
+       22050,
+       44100,
+       88200,
+       176400,
+       352800,
+       705600,
+       4000,
+       8000,
+       16000,
+       32000,
+       64000,
+       128000,
+       256000,
+       512000,
+};
+
+static int wm5100_sr_regs[WM5100_SYNC_SRS] = {
+       WM5100_CLOCKING_4,
+       WM5100_CLOCKING_5,
+       WM5100_CLOCKING_6,
+};
+
+static int wm5100_alloc_sr(struct snd_soc_codec *codec, int rate)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int sr_code, sr_free, i;
+
+       for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++)
+               if (wm5100_sr_code[i] == rate)
+                       break;
+       if (i == ARRAY_SIZE(wm5100_sr_code)) {
+               dev_err(codec->dev, "Unsupported sample rate: %dHz\n", rate);
+               return -EINVAL;
+       }
+       sr_code = i;
+
+       if ((wm5100->sysclk % rate) == 0) {
+               /* Is this rate already in use? */
+               sr_free = -1;
+               for (i = 0; i < ARRAY_SIZE(wm5100_sr_regs); i++) {
+                       if (!wm5100->sr_ref[i] && sr_free == -1) {
+                               sr_free = i;
+                               continue;
+                       }
+                       if ((snd_soc_read(codec, wm5100_sr_regs[i]) &
+                            WM5100_SAMPLE_RATE_1_MASK) == sr_code)
+                               break;
+               }
+
+               if (i < ARRAY_SIZE(wm5100_sr_regs)) {
+                       wm5100->sr_ref[i]++;
+                       dev_dbg(codec->dev, "SR %dHz, slot %d, ref %d\n",
+                               rate, i, wm5100->sr_ref[i]);
+                       return i;
+               }
+
+               if (sr_free == -1) {
+                       dev_err(codec->dev, "All SR slots already in use\n");
+                       return -EBUSY;
+               }
+
+               dev_dbg(codec->dev, "Allocating SR slot %d for %dHz\n",
+                       sr_free, rate);
+               wm5100->sr_ref[sr_free]++;
+               snd_soc_update_bits(codec, wm5100_sr_regs[sr_free],
+                                   WM5100_SAMPLE_RATE_1_MASK,
+                                   sr_code);
+
+               return sr_free;
+
+       } else {
+               dev_err(codec->dev,
+                       "SR %dHz incompatible with %dHz SYSCLK and %dHz ASYNCCLK\n",
+                       rate, wm5100->sysclk, wm5100->asyncclk);
+               return -EINVAL;
+       }
+}
+
+static void wm5100_free_sr(struct snd_soc_codec *codec, int rate)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int i, sr_code;
+
+       for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++)
+               if (wm5100_sr_code[i] == rate)
+                       break;
+       if (i == ARRAY_SIZE(wm5100_sr_code)) {
+               dev_err(codec->dev, "Unsupported sample rate: %dHz\n", rate);
+               return;
+       }
+       sr_code = wm5100_sr_code[i];
+
+       for (i = 0; i < ARRAY_SIZE(wm5100_sr_regs); i++) {
+               if (!wm5100->sr_ref[i])
+                       continue;
+
+               if ((snd_soc_read(codec, wm5100_sr_regs[i]) &
+                    WM5100_SAMPLE_RATE_1_MASK) == sr_code)
+                       break;
+       }
+       if (i < ARRAY_SIZE(wm5100_sr_regs)) {
+               wm5100->sr_ref[i]--;
+               dev_dbg(codec->dev, "Dereference SR %dHz, count now %d\n",
+                       rate, wm5100->sr_ref[i]);
+       } else {
+               dev_warn(codec->dev, "Freeing unreferenced sample rate %dHz\n",
+                        rate);
+       }
+}
+
+static int wm5100_reset(struct snd_soc_codec *codec)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+
+       if (wm5100->pdata.reset) {
+               gpio_set_value_cansleep(wm5100->pdata.reset, 0);
+               gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+
+               return 0;
+       } else {
+               return snd_soc_write(codec, WM5100_SOFTWARE_RESET, 0);
+       }
+}
+
+static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0);
+static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static DECLARE_TLV_DB_SCALE(mixer_tlv, -3200, 100, 0);
+static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
+static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
+
+static const char *wm5100_mixer_texts[] = {
+       "None",
+       "Tone Generator 1",
+       "Tone Generator 2",
+       "AEC loopback",
+       "IN1L",
+       "IN1R",
+       "IN2L",
+       "IN2R",
+       "IN3L",
+       "IN3R",
+       "IN4L",
+       "IN4R",
+       "AIF1RX1",
+       "AIF1RX2",
+       "AIF1RX3",
+       "AIF1RX4",
+       "AIF1RX5",
+       "AIF1RX6",
+       "AIF1RX7",
+       "AIF1RX8",
+       "AIF2RX1",
+       "AIF2RX2",
+       "AIF3RX1",
+       "AIF3RX2",
+       "EQ1",
+       "EQ2",
+       "EQ3",
+       "EQ4",
+       "DRC1L",
+       "DRC1R",
+       "LHPF1",
+       "LHPF2",
+       "LHPF3",
+       "LHPF4",
+       "DSP1.1",
+       "DSP1.2",
+       "DSP1.3",
+       "DSP1.4",
+       "DSP1.5",
+       "DSP1.6",
+       "DSP2.1",
+       "DSP2.2",
+       "DSP2.3",
+       "DSP2.4",
+       "DSP2.5",
+       "DSP2.6",
+       "DSP3.1",
+       "DSP3.2",
+       "DSP3.3",
+       "DSP3.4",
+       "DSP3.5",
+       "DSP3.6",
+       "ASRC1L",
+       "ASRC1R",
+       "ASRC2L",
+       "ASRC2R",
+       "ISRC1INT1",
+       "ISRC1INT2",
+       "ISRC1INT3",
+       "ISRC1INT4",
+       "ISRC2INT1",
+       "ISRC2INT2",
+       "ISRC2INT3",
+       "ISRC2INT4",
+       "ISRC1DEC1",
+       "ISRC1DEC2",
+       "ISRC1DEC3",
+       "ISRC1DEC4",
+       "ISRC2DEC1",
+       "ISRC2DEC2",
+       "ISRC2DEC3",
+       "ISRC2DEC4",
+};
+
+static int wm5100_mixer_values[] = {
+       0x00,
+       0x04,   /* Tone */
+       0x05,
+       0x08,   /* AEC */
+       0x10,   /* Input */
+       0x11,
+       0x12,
+       0x13,
+       0x14,
+       0x15,
+       0x16,
+       0x17,
+       0x20,   /* AIF */
+       0x21,
+       0x22,
+       0x23,
+       0x24,
+       0x25,
+       0x26,
+       0x27,
+       0x28,
+       0x29,
+       0x30,   /* AIF3 - check */
+       0x31,
+       0x50,   /* EQ */
+       0x51,
+       0x52,
+       0x53,
+       0x54,
+       0x58,   /* DRC */
+       0x59,
+       0x60,   /* LHPF1 */
+       0x61,   /* LHPF2 */
+       0x62,   /* LHPF3 */
+       0x63,   /* LHPF4 */
+       0x68,   /* DSP1 */
+       0x69,
+       0x6a,
+       0x6b,
+       0x6c,
+       0x6d,
+       0x70,   /* DSP2 */
+       0x71,
+       0x72,
+       0x73,
+       0x74,
+       0x75,
+       0x78,   /* DSP3 */
+       0x79,
+       0x7a,
+       0x7b,
+       0x7c,
+       0x7d,
+       0x90,   /* ASRC1 */
+       0x91,
+       0x92,   /* ASRC2 */
+       0x93,
+       0xa0,   /* ISRC1DEC1 */
+       0xa1,
+       0xa2,
+       0xa3,
+       0xa4,   /* ISRC1INT1 */
+       0xa5,
+       0xa6,
+       0xa7,
+       0xa8,   /* ISRC2DEC1 */
+       0xa9,
+       0xaa,
+       0xab,
+       0xac,   /* ISRC2INT1 */
+       0xad,
+       0xae,
+       0xaf,
+};
+
+#define WM5100_MIXER_CONTROLS(name, base) \
+       SOC_SINGLE_TLV(name " Input 1 Volume", base + 1 , \
+                      WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+       SOC_SINGLE_TLV(name " Input 2 Volume", base + 3 , \
+                      WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+       SOC_SINGLE_TLV(name " Input 3 Volume", base + 5 , \
+                      WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+       SOC_SINGLE_TLV(name " Input 4 Volume", base + 7 , \
+                      WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv)
+
+#define WM5100_MUX_ENUM_DECL(name, reg) \
+       SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff,                  \
+                                  wm5100_mixer_texts, wm5100_mixer_values)
+
+#define WM5100_MUX_CTL_DECL(name) \
+       const struct snd_kcontrol_new name##_mux =      \
+               SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+
+#define WM5100_MIXER_ENUMS(name, base_reg) \
+       static WM5100_MUX_ENUM_DECL(name##_in1_enum, base_reg);      \
+       static WM5100_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2);  \
+       static WM5100_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4);  \
+       static WM5100_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6);  \
+       static WM5100_MUX_CTL_DECL(name##_in1); \
+       static WM5100_MUX_CTL_DECL(name##_in2); \
+       static WM5100_MUX_CTL_DECL(name##_in3); \
+       static WM5100_MUX_CTL_DECL(name##_in4) 
+
+WM5100_MIXER_ENUMS(HPOUT1L, WM5100_OUT1LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT1R, WM5100_OUT1RMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT2L, WM5100_OUT2LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT2R, WM5100_OUT2RMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT3L, WM5100_OUT3LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT3R, WM5100_OUT3RMIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(SPKOUTL, WM5100_OUT4LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKOUTR, WM5100_OUT4RMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKDAT1L, WM5100_OUT5LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKDAT1R, WM5100_OUT5RMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKDAT2L, WM5100_OUT6LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKDAT2R, WM5100_OUT6RMIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(PWM1, WM5100_PWM1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(PWM2, WM5100_PWM1MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(AIF1TX1, WM5100_AIF1TX1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX2, WM5100_AIF1TX2MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX3, WM5100_AIF1TX3MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX4, WM5100_AIF1TX4MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX5, WM5100_AIF1TX5MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX6, WM5100_AIF1TX6MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX7, WM5100_AIF1TX7MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX8, WM5100_AIF1TX8MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(AIF2TX1, WM5100_AIF2TX1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF2TX2, WM5100_AIF2TX2MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(AIF3TX1, WM5100_AIF1TX1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF3TX2, WM5100_AIF1TX2MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(EQ1, WM5100_EQ1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(EQ2, WM5100_EQ2MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(EQ3, WM5100_EQ3MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(EQ4, WM5100_EQ4MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(DRC1L, WM5100_DRC1LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(DRC1R, WM5100_DRC1RMIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(LHPF1, WM5100_HPLP1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(LHPF2, WM5100_HPLP2MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(LHPF3, WM5100_HPLP3MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(LHPF4, WM5100_HPLP4MIX_INPUT_1_SOURCE);
+
+#define WM5100_MUX(name, ctrl) \
+       SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+
+#define WM5100_MIXER_WIDGETS(name, name_str)   \
+       WM5100_MUX(name_str " Input 1", &name##_in1_mux), \
+       WM5100_MUX(name_str " Input 2", &name##_in2_mux), \
+       WM5100_MUX(name_str " Input 3", &name##_in3_mux), \
+       WM5100_MUX(name_str " Input 4", &name##_in4_mux), \
+       SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
+
+#define WM5100_MIXER_INPUT_ROUTES(name)        \
+       { name, "Tone Generator 1", "Tone Generator 1" }, \
+        { name, "Tone Generator 2", "Tone Generator 2" }, \
+        { name, "IN1L", "IN1L PGA" }, \
+        { name, "IN1R", "IN1R PGA" }, \
+        { name, "IN2L", "IN2L PGA" }, \
+        { name, "IN2R", "IN2R PGA" }, \
+        { name, "IN3L", "IN3L PGA" }, \
+        { name, "IN3R", "IN3R PGA" }, \
+        { name, "IN4L", "IN4L PGA" }, \
+        { name, "IN4R", "IN4R PGA" }, \
+        { name, "AIF1RX1", "AIF1RX1" }, \
+        { name, "AIF1RX2", "AIF1RX2" }, \
+        { name, "AIF1RX3", "AIF1RX3" }, \
+        { name, "AIF1RX4", "AIF1RX4" }, \
+        { name, "AIF1RX5", "AIF1RX5" }, \
+        { name, "AIF1RX6", "AIF1RX6" }, \
+        { name, "AIF1RX7", "AIF1RX7" }, \
+        { name, "AIF1RX8", "AIF1RX8" }, \
+        { name, "AIF2RX1", "AIF2RX1" }, \
+        { name, "AIF2RX2", "AIF2RX2" }, \
+        { name, "AIF3RX1", "AIF3RX1" }, \
+        { name, "AIF3RX2", "AIF3RX2" }, \
+        { name, "EQ1", "EQ1" }, \
+        { name, "EQ2", "EQ2" }, \
+        { name, "EQ3", "EQ3" }, \
+        { name, "EQ4", "EQ4" }, \
+        { name, "DRC1L", "DRC1L" }, \
+        { name, "DRC1R", "DRC1R" }, \
+        { name, "LHPF1", "LHPF1" }, \
+        { name, "LHPF2", "LHPF2" }, \
+        { name, "LHPF3", "LHPF3" }, \
+        { name, "LHPF4", "LHPF4" }
+
+#define WM5100_MIXER_ROUTES(widget, name) \
+       { widget, NULL, name " Mixer" },         \
+       { name " Mixer", NULL, name " Input 1" }, \
+       { name " Mixer", NULL, name " Input 2" }, \
+       { name " Mixer", NULL, name " Input 3" }, \
+       { name " Mixer", NULL, name " Input 4" }, \
+       WM5100_MIXER_INPUT_ROUTES(name " Input 1"), \
+       WM5100_MIXER_INPUT_ROUTES(name " Input 2"), \
+       WM5100_MIXER_INPUT_ROUTES(name " Input 3"), \
+       WM5100_MIXER_INPUT_ROUTES(name " Input 4")
+
+static const char *wm5100_lhpf_mode_text[] = {
+       "Low-pass", "High-pass"
+};
+
+static const struct soc_enum wm5100_lhpf1_mode =
+       SOC_ENUM_SINGLE(WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT, 2,
+                       wm5100_lhpf_mode_text);
+
+static const struct soc_enum wm5100_lhpf2_mode =
+       SOC_ENUM_SINGLE(WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT, 2,
+                       wm5100_lhpf_mode_text);
+
+static const struct soc_enum wm5100_lhpf3_mode =
+       SOC_ENUM_SINGLE(WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT, 2,
+                       wm5100_lhpf_mode_text);
+
+static const struct soc_enum wm5100_lhpf4_mode =
+       SOC_ENUM_SINGLE(WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT, 2,
+                       wm5100_lhpf_mode_text);
+
+static const struct snd_kcontrol_new wm5100_snd_controls[] = {
+SOC_SINGLE("IN1 High Performance Switch", WM5100_IN1L_CONTROL,
+          WM5100_IN1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN2 High Performance Switch", WM5100_IN2L_CONTROL,
+          WM5100_IN2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN3 High Performance Switch", WM5100_IN3L_CONTROL,
+          WM5100_IN3_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN4 High Performance Switch", WM5100_IN4L_CONTROL,
+          WM5100_IN4_OSR_SHIFT, 1, 0),
+
+/* Only applicable for analogue inputs */
+SOC_DOUBLE_R_TLV("IN1 Volume", WM5100_IN1L_CONTROL, WM5100_IN1R_CONTROL,
+                WM5100_IN1L_PGA_VOL_SHIFT, 94, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN2 Volume", WM5100_IN2L_CONTROL, WM5100_IN2R_CONTROL,
+                WM5100_IN2L_PGA_VOL_SHIFT, 94, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN3 Volume", WM5100_IN3L_CONTROL, WM5100_IN3R_CONTROL,
+                WM5100_IN3L_PGA_VOL_SHIFT, 94, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN4 Volume", WM5100_IN4L_CONTROL, WM5100_IN4R_CONTROL,
+                WM5100_IN4L_PGA_VOL_SHIFT, 94, 0, in_tlv),
+
+SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_1L,
+                WM5100_ADC_DIGITAL_VOLUME_1R, WM5100_IN1L_VOL_SHIFT, 191,
+                0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_2L,
+                WM5100_ADC_DIGITAL_VOLUME_2R, WM5100_IN2L_VOL_SHIFT, 191,
+                0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_3L,
+                WM5100_ADC_DIGITAL_VOLUME_3R, WM5100_IN3L_VOL_SHIFT, 191,
+                0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN4 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_4L,
+                WM5100_ADC_DIGITAL_VOLUME_4R, WM5100_IN4L_VOL_SHIFT, 191,
+                0, digital_tlv),
+
+SOC_DOUBLE_R("IN1 Switch", WM5100_ADC_DIGITAL_VOLUME_1L,
+            WM5100_ADC_DIGITAL_VOLUME_1R, WM5100_IN1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN2 Switch", WM5100_ADC_DIGITAL_VOLUME_2L,
+            WM5100_ADC_DIGITAL_VOLUME_2R, WM5100_IN2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN3 Switch", WM5100_ADC_DIGITAL_VOLUME_3L,
+            WM5100_ADC_DIGITAL_VOLUME_3R, WM5100_IN3L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN4 Switch", WM5100_ADC_DIGITAL_VOLUME_4L,
+            WM5100_ADC_DIGITAL_VOLUME_4R, WM5100_IN4L_MUTE_SHIFT, 1, 1),
+
+SOC_SINGLE("HPOUT1 High Performance Switch", WM5100_OUT_VOLUME_1L,
+          WM5100_OUT1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("HPOUT2 High Performance Switch", WM5100_OUT_VOLUME_2L,
+          WM5100_OUT2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("HPOUT3 High Performance Switch", WM5100_OUT_VOLUME_3L,
+          WM5100_OUT3_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKOUT High Performance Switch", WM5100_OUT_VOLUME_4L,
+          WM5100_OUT4_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKDAT1 High Performance Switch", WM5100_DAC_VOLUME_LIMIT_5L,
+          WM5100_OUT5_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKDAT2 High Performance Switch", WM5100_DAC_VOLUME_LIMIT_6L,
+          WM5100_OUT6_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_1L,
+                WM5100_DAC_DIGITAL_VOLUME_1R, WM5100_OUT1L_VOL_SHIFT, 159, 0,
+                digital_tlv),
+SOC_DOUBLE_R_TLV("HPOUT2 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_2L,
+                WM5100_DAC_DIGITAL_VOLUME_2R, WM5100_OUT2L_VOL_SHIFT, 159, 0,
+                digital_tlv),
+SOC_DOUBLE_R_TLV("HPOUT3 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_3L,
+                WM5100_DAC_DIGITAL_VOLUME_3R, WM5100_OUT3L_VOL_SHIFT, 159, 0,
+                digital_tlv),
+SOC_DOUBLE_R_TLV("SPKOUT Digital Volume", WM5100_DAC_DIGITAL_VOLUME_4L,
+                WM5100_DAC_DIGITAL_VOLUME_4R, WM5100_OUT4L_VOL_SHIFT, 159, 0,
+                digital_tlv),
+SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_5L,
+                WM5100_DAC_DIGITAL_VOLUME_5R, WM5100_OUT5L_VOL_SHIFT, 159, 0,
+                digital_tlv),
+SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_6L,
+                WM5100_DAC_DIGITAL_VOLUME_6R, WM5100_OUT6L_VOL_SHIFT, 159, 0,
+                digital_tlv),
+
+SOC_DOUBLE_R("HPOUT1 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_1L,
+            WM5100_DAC_DIGITAL_VOLUME_1R, WM5100_OUT1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("HPOUT2 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_2L,
+            WM5100_DAC_DIGITAL_VOLUME_2R, WM5100_OUT2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("HPOUT3 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_3L,
+            WM5100_DAC_DIGITAL_VOLUME_3R, WM5100_OUT3L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("SPKOUT Digital Switch", WM5100_DAC_DIGITAL_VOLUME_4L,
+            WM5100_DAC_DIGITAL_VOLUME_4R, WM5100_OUT4L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("SPKDAT1 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_5L,
+            WM5100_DAC_DIGITAL_VOLUME_5R, WM5100_OUT5L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("SPKDAT2 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_6L,
+            WM5100_DAC_DIGITAL_VOLUME_6R, WM5100_OUT6L_MUTE_SHIFT, 1, 1),
+
+/* FIXME: Only valid from -12dB to 0dB (52-64) */
+SOC_DOUBLE_R_TLV("HPOUT1 Volume", WM5100_OUT_VOLUME_1L, WM5100_OUT_VOLUME_1R,
+                WM5100_OUT1L_PGA_VOL_SHIFT, 64, 0, out_tlv),
+SOC_DOUBLE_R_TLV("HPOUT2 Volume", WM5100_OUT_VOLUME_2L, WM5100_OUT_VOLUME_2R,
+                WM5100_OUT2L_PGA_VOL_SHIFT, 64, 0, out_tlv),
+SOC_DOUBLE_R_TLV("HPOUT3 Volume", WM5100_OUT_VOLUME_3L, WM5100_OUT_VOLUME_3R,
+                WM5100_OUT2L_PGA_VOL_SHIFT, 64, 0, out_tlv),
+
+SOC_DOUBLE("SPKDAT1 Switch", WM5100_PDM_SPK1_CTRL_1, WM5100_SPK1L_MUTE_SHIFT,
+          WM5100_SPK1R_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE("SPKDAT2 Switch", WM5100_PDM_SPK2_CTRL_1, WM5100_SPK2L_MUTE_SHIFT,
+          WM5100_SPK2R_MUTE_SHIFT, 1, 1),
+
+SOC_SINGLE_TLV("EQ1 Band 1 Volume", WM5100_EQ1_1, WM5100_EQ1_B1_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 Band 2 Volume", WM5100_EQ1_1, WM5100_EQ1_B2_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 Band 3 Volume", WM5100_EQ1_1, WM5100_EQ1_B3_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 Band 4 Volume", WM5100_EQ1_2, WM5100_EQ1_B4_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 Band 5 Volume", WM5100_EQ1_2, WM5100_EQ1_B5_GAIN_SHIFT,
+              24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ2 Band 1 Volume", WM5100_EQ2_1, WM5100_EQ2_B1_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Band 2 Volume", WM5100_EQ2_1, WM5100_EQ2_B2_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Band 3 Volume", WM5100_EQ2_1, WM5100_EQ2_B3_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Band 4 Volume", WM5100_EQ2_2, WM5100_EQ2_B4_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Band 5 Volume", WM5100_EQ2_2, WM5100_EQ2_B5_GAIN_SHIFT,
+              24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ3 Band 1 Volume", WM5100_EQ1_1, WM5100_EQ3_B1_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Band 2 Volume", WM5100_EQ3_1, WM5100_EQ3_B2_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Band 3 Volume", WM5100_EQ3_1, WM5100_EQ3_B3_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Band 4 Volume", WM5100_EQ3_2, WM5100_EQ3_B4_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Band 5 Volume", WM5100_EQ3_2, WM5100_EQ3_B5_GAIN_SHIFT,
+              24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ4 Band 1 Volume", WM5100_EQ4_1, WM5100_EQ4_B1_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Band 2 Volume", WM5100_EQ4_1, WM5100_EQ4_B2_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Band 3 Volume", WM5100_EQ4_1, WM5100_EQ4_B3_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Band 4 Volume", WM5100_EQ4_2, WM5100_EQ4_B4_GAIN_SHIFT,
+              24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Band 5 Volume", WM5100_EQ4_2, WM5100_EQ4_B5_GAIN_SHIFT,
+              24, 0, eq_tlv),
+
+SOC_ENUM("LHPF1 Mode", wm5100_lhpf1_mode),
+SOC_ENUM("LHPF2 Mode", wm5100_lhpf2_mode),
+SOC_ENUM("LHPF3 Mode", wm5100_lhpf3_mode),
+SOC_ENUM("LHPF4 Mode", wm5100_lhpf4_mode),
+
+WM5100_MIXER_CONTROLS("HPOUT1L", WM5100_OUT1LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT1R", WM5100_OUT1RMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT2L", WM5100_OUT2LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT2R", WM5100_OUT2RMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT3L", WM5100_OUT3LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT3R", WM5100_OUT3RMIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("SPKOUTL", WM5100_OUT4LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKOUTR", WM5100_OUT4RMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKDAT1L", WM5100_OUT5LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKDAT1R", WM5100_OUT5RMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKDAT2L", WM5100_OUT6LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKDAT2R", WM5100_OUT6RMIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("PWM1", WM5100_PWM1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("PWM2", WM5100_PWM2MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("AIF1TX1", WM5100_AIF1TX1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX2", WM5100_AIF1TX2MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX3", WM5100_AIF1TX3MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX4", WM5100_AIF1TX4MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX5", WM5100_AIF1TX5MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX6", WM5100_AIF1TX6MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX7", WM5100_AIF1TX7MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX8", WM5100_AIF1TX8MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("AIF2TX1", WM5100_AIF2TX1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF2TX2", WM5100_AIF2TX2MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("AIF3TX1", WM5100_AIF3TX1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF3TX2", WM5100_AIF3TX2MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("EQ1", WM5100_EQ1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("EQ2", WM5100_EQ2MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("EQ3", WM5100_EQ3MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("EQ4", WM5100_EQ4MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("DRC1L", WM5100_DRC1LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("DRC1R", WM5100_DRC1RMIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("LHPF1", WM5100_HPLP1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("LHPF2", WM5100_HPLP2MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("LHPF3", WM5100_HPLP3MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("LHPF4", WM5100_HPLP4MIX_INPUT_1_SOURCE),
+};
+
+static void wm5100_seq_notifier(struct snd_soc_dapm_context *dapm,
+                               enum snd_soc_dapm_type event, int subseq)
+{
+       struct snd_soc_codec *codec = container_of(dapm,
+                                                  struct snd_soc_codec, dapm);
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       u16 val, expect, i;
+
+       /* Wait for the outputs to flag themselves as enabled */
+       if (wm5100->out_ena[0]) {
+               expect = snd_soc_read(codec, WM5100_CHANNEL_ENABLES_1);
+               for (i = 0; i < 200; i++) {
+                       val = snd_soc_read(codec, WM5100_OUTPUT_STATUS_1);
+                       if (val == expect) {
+                               wm5100->out_ena[0] = false;
+                               break;
+                       }
+               }
+               if (i == 200) {
+                       dev_err(codec->dev, "Timeout waiting for OUTPUT1 %x\n",
+                               expect);
+               }
+       }
+
+       if (wm5100->out_ena[1]) {
+               expect = snd_soc_read(codec, WM5100_OUTPUT_ENABLES_2);
+               for (i = 0; i < 200; i++) {
+                       val = snd_soc_read(codec, WM5100_OUTPUT_STATUS_2);
+                       if (val == expect) {
+                               wm5100->out_ena[1] = false;
+                               break;
+                       }
+               }
+               if (i == 200) {
+                       dev_err(codec->dev, "Timeout waiting for OUTPUT2 %x\n",
+                               expect);
+               }
+       }
+}
+
+static int wm5100_out_ev(struct snd_soc_dapm_widget *w,
+                        struct snd_kcontrol *kcontrol,
+                        int event)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(w->codec);
+
+       switch (w->reg) {
+       case WM5100_CHANNEL_ENABLES_1:
+               wm5100->out_ena[0] = true;
+               break;
+       case WM5100_OUTPUT_ENABLES_2:
+               wm5100->out_ena[0] = true;
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int wm5100_cp_ev(struct snd_soc_dapm_widget *w,
+                       struct snd_kcontrol *kcontrol,
+                       int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               ret = regulator_enable(wm5100->cpvdd);
+               if (ret != 0) {
+                       dev_err(codec->dev, "Failed to enable CPVDD: %d\n",
+                               ret);
+                       return ret;
+               }
+               return ret;
+
+       case SND_SOC_DAPM_POST_PMD:
+               ret = regulator_disable_deferred(wm5100->cpvdd, 20);
+               if (ret != 0) {
+                       dev_err(codec->dev, "Failed to disable CPVDD: %d\n",
+                               ret);
+                       return ret;
+               }
+               return ret;
+
+       default:
+               BUG();
+               return 0;
+       }
+}
+
+static int wm5100_dbvdd_ev(struct snd_soc_dapm_widget *w,
+                          struct snd_kcontrol *kcontrol,
+                          int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       struct regulator *regulator;
+       int ret;
+
+       switch (w->shift) {
+       case 2:
+               regulator = wm5100->dbvdd2;
+               break;
+       case 3:
+               regulator = wm5100->dbvdd3;
+               break;
+       default:
+               BUG();
+               return 0;
+       }
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               ret = regulator_enable(regulator);
+               if (ret != 0) {
+                       dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n",
+                               w->shift, ret);
+                       return ret;
+               }
+               return ret;
+
+       case SND_SOC_DAPM_POST_PMD:
+               ret = regulator_disable(regulator);
+               if (ret != 0) {
+                       dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n",
+                               w->shift, ret);
+                       return ret;
+               }
+               return ret;
+
+       default:
+               BUG();
+               return 0;
+       }
+}
+
+static void wm5100_log_status3(struct snd_soc_codec *codec, int val)
+{
+       if (val & WM5100_SPK_SHUTDOWN_WARN_EINT)
+               dev_crit(codec->dev, "Speaker shutdown warning\n");
+       if (val & WM5100_SPK_SHUTDOWN_EINT)
+               dev_crit(codec->dev, "Speaker shutdown\n");
+       if (val & WM5100_CLKGEN_ERR_EINT)
+               dev_crit(codec->dev, "SYSCLK underclocked\n");
+       if (val & WM5100_CLKGEN_ERR_ASYNC_EINT)
+               dev_crit(codec->dev, "ASYNCCLK underclocked\n");
+}
+
+static void wm5100_log_status4(struct snd_soc_codec *codec, int val)
+{
+       if (val & WM5100_AIF3_ERR_EINT)
+               dev_err(codec->dev, "AIF3 configuration error\n");
+       if (val & WM5100_AIF2_ERR_EINT)
+               dev_err(codec->dev, "AIF2 configuration error\n");
+       if (val & WM5100_AIF1_ERR_EINT)
+               dev_err(codec->dev, "AIF1 configuration error\n");
+       if (val & WM5100_CTRLIF_ERR_EINT)
+               dev_err(codec->dev, "Control interface error\n");
+       if (val & WM5100_ISRC2_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "ISRC2 underclocked\n");
+       if (val & WM5100_ISRC1_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "ISRC1 underclocked\n");
+       if (val & WM5100_FX_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "FX underclocked\n");
+       if (val & WM5100_AIF3_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "AIF3 underclocked\n");
+       if (val & WM5100_AIF2_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "AIF2 underclocked\n");
+       if (val & WM5100_AIF1_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "AIF1 underclocked\n");
+       if (val & WM5100_ASRC_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "ASRC underclocked\n");
+       if (val & WM5100_DAC_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "DAC underclocked\n");
+       if (val & WM5100_ADC_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "ADC underclocked\n");
+       if (val & WM5100_MIXER_UNDERCLOCKED_EINT)
+               dev_err(codec->dev, "Mixer underclocked\n");
+}
+
+static int wm5100_post_ev(struct snd_soc_dapm_widget *w,
+                         struct snd_kcontrol *kcontrol,
+                         int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       int ret;
+
+       ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_3);
+       ret &= WM5100_SPK_SHUTDOWN_WARN_STS |
+               WM5100_SPK_SHUTDOWN_STS | WM5100_CLKGEN_ERR_STS |
+               WM5100_CLKGEN_ERR_ASYNC_STS;
+       wm5100_log_status3(codec, ret);
+
+       ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_4);
+       wm5100_log_status4(codec, ret);
+
+       return 0;
+}
+
+static const struct snd_soc_dapm_widget wm5100_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("SYSCLK", WM5100_CLOCKING_3, WM5100_SYSCLK_ENA_SHIFT, 0,
+                   NULL, 0),
+SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT,
+                   0, NULL, 0),
+
+SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0,
+                   wm5100_cp_ev,
+                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("CP2", WM5100_MIC_CHARGE_PUMP_1, WM5100_CP2_ENA_SHIFT, 0,
+                   NULL, 0),
+SND_SOC_DAPM_SUPPLY("CP2 Active", WM5100_MIC_CHARGE_PUMP_1,
+                   WM5100_CP2_BYPASS_SHIFT, 1, wm5100_cp_ev,
+                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("DBVDD2", SND_SOC_NOPM, 2, 0, wm5100_dbvdd_ev,
+                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("DBVDD3", SND_SOC_NOPM, 3, 0, wm5100_dbvdd_ev,
+                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+SND_SOC_DAPM_SUPPLY("MICBIAS1", WM5100_MIC_BIAS_CTRL_1, WM5100_MICB1_ENA_SHIFT,
+                   0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", WM5100_MIC_BIAS_CTRL_2, WM5100_MICB2_ENA_SHIFT,
+                   0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS3", WM5100_MIC_BIAS_CTRL_3, WM5100_MICB3_ENA_SHIFT,
+                   0, NULL, 0),
+
+SND_SOC_DAPM_INPUT("IN1L"),
+SND_SOC_DAPM_INPUT("IN1R"),
+SND_SOC_DAPM_INPUT("IN2L"),
+SND_SOC_DAPM_INPUT("IN2R"),
+SND_SOC_DAPM_INPUT("IN3L"),
+SND_SOC_DAPM_INPUT("IN3R"),
+SND_SOC_DAPM_INPUT("IN4L"),
+SND_SOC_DAPM_INPUT("IN4R"),
+SND_SOC_DAPM_INPUT("TONE"),
+
+SND_SOC_DAPM_PGA_E("IN1L PGA", WM5100_INPUT_ENABLES, WM5100_IN1L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN1R PGA", WM5100_INPUT_ENABLES, WM5100_IN1R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN2L PGA", WM5100_INPUT_ENABLES, WM5100_IN2L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN2R PGA", WM5100_INPUT_ENABLES, WM5100_IN2R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN3L PGA", WM5100_INPUT_ENABLES, WM5100_IN3L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN3R PGA", WM5100_INPUT_ENABLES, WM5100_IN3R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN4L PGA", WM5100_INPUT_ENABLES, WM5100_IN4L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN4R PGA", WM5100_INPUT_ENABLES, WM5100_IN4R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+
+SND_SOC_DAPM_PGA("Tone Generator 1", WM5100_TONE_GENERATOR_1,
+                WM5100_TONE1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Tone Generator 2", WM5100_TONE_GENERATOR_1,
+                WM5100_TONE2_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX1", "AIF1 Playback", 0,
+                   WM5100_AUDIO_IF_1_27, WM5100_AIF1RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", "AIF1 Playback", 1,
+                   WM5100_AUDIO_IF_1_27, WM5100_AIF1RX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", "AIF1 Playback", 2,
+                   WM5100_AUDIO_IF_1_27, WM5100_AIF1RX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", "AIF1 Playback", 3,
+                   WM5100_AUDIO_IF_1_27, WM5100_AIF1RX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 4,
+                   WM5100_AUDIO_IF_1_27, WM5100_AIF1RX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX6", "AIF1 Playback", 5,
+                   WM5100_AUDIO_IF_1_27, WM5100_AIF1RX6_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX7", "AIF1 Playback", 6,
+                   WM5100_AUDIO_IF_1_27, WM5100_AIF1RX7_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX8", "AIF1 Playback", 7,
+                   WM5100_AUDIO_IF_1_27, WM5100_AIF1RX8_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0,
+                   WM5100_AUDIO_IF_2_27, WM5100_AIF2RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX2", "AIF2 Playback", 1,
+                   WM5100_AUDIO_IF_2_27, WM5100_AIF2RX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF3RX1", "AIF3 Playback", 0,
+                   WM5100_AUDIO_IF_3_27, WM5100_AIF3RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF3RX2", "AIF3 Playback", 1,
+                   WM5100_AUDIO_IF_3_27, WM5100_AIF3RX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", "AIF1 Capture", 0,
+                   WM5100_AUDIO_IF_1_26, WM5100_AIF1TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", "AIF1 Capture", 1,
+                   WM5100_AUDIO_IF_1_26, WM5100_AIF1TX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", "AIF1 Capture", 2,
+                   WM5100_AUDIO_IF_1_26, WM5100_AIF1TX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", "AIF1 Capture", 3,
+                   WM5100_AUDIO_IF_1_26, WM5100_AIF1TX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", "AIF1 Capture", 4,
+                   WM5100_AUDIO_IF_1_26, WM5100_AIF1TX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX6", "AIF1 Capture", 5,
+                   WM5100_AUDIO_IF_1_26, WM5100_AIF1TX6_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX7", "AIF1 Capture", 6,
+                   WM5100_AUDIO_IF_1_26, WM5100_AIF1TX7_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX8", "AIF1 Capture", 7,
+                   WM5100_AUDIO_IF_1_26, WM5100_AIF1TX8_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF2TX1", "AIF2 Capture", 0,
+                   WM5100_AUDIO_IF_2_26, WM5100_AIF2TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX2", "AIF2 Capture", 1,
+                   WM5100_AUDIO_IF_2_26, WM5100_AIF2TX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF3TX1", "AIF3 Capture", 0,
+                   WM5100_AUDIO_IF_3_26, WM5100_AIF3TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF3TX2", "AIF3 Capture", 1,
+                   WM5100_AUDIO_IF_3_26, WM5100_AIF3TX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA_E("OUT6L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT6L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT6R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT6R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT5L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT5L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT5R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT5R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT4L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT4L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT4R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT4R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT3L", WM5100_CHANNEL_ENABLES_1, WM5100_HP3L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT3R", WM5100_CHANNEL_ENABLES_1, WM5100_HP3R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT2L", WM5100_CHANNEL_ENABLES_1, WM5100_HP2L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT2R", WM5100_CHANNEL_ENABLES_1, WM5100_HP2R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT1L", WM5100_CHANNEL_ENABLES_1, WM5100_HP1L_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT1R", WM5100_CHANNEL_ENABLES_1, WM5100_HP1R_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("PWM1 Driver", WM5100_PWM_DRIVE_1, WM5100_PWM1_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("PWM2 Driver", WM5100_PWM_DRIVE_1, WM5100_PWM2_ENA_SHIFT, 0,
+                  NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+
+SND_SOC_DAPM_PGA("EQ1", WM5100_EQ1_1, WM5100_EQ1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ2", WM5100_EQ2_1, WM5100_EQ2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ3", WM5100_EQ3_1, WM5100_EQ3_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ4", WM5100_EQ4_1, WM5100_EQ4_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("DRC1L", WM5100_DRC1_CTRL1, WM5100_DRCL_ENA_SHIFT, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("DRC1R", WM5100_DRC1_CTRL1, WM5100_DRCR_ENA_SHIFT, 0,
+                NULL, 0),
+
+SND_SOC_DAPM_PGA("LHPF1", WM5100_HPLPF1_1, WM5100_LHPF1_ENA_SHIFT, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("LHPF2", WM5100_HPLPF2_1, WM5100_LHPF2_ENA_SHIFT, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("LHPF3", WM5100_HPLPF3_1, WM5100_LHPF3_ENA_SHIFT, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("LHPF4", WM5100_HPLPF4_1, WM5100_LHPF4_ENA_SHIFT, 0,
+                NULL, 0),
+
+WM5100_MIXER_WIDGETS(EQ1, "EQ1"),
+WM5100_MIXER_WIDGETS(EQ2, "EQ2"),
+WM5100_MIXER_WIDGETS(EQ3, "EQ3"),
+WM5100_MIXER_WIDGETS(EQ4, "EQ4"),
+
+WM5100_MIXER_WIDGETS(DRC1L, "DRC1L"),
+WM5100_MIXER_WIDGETS(DRC1R, "DRC1R"),
+
+WM5100_MIXER_WIDGETS(LHPF1, "LHPF1"),
+WM5100_MIXER_WIDGETS(LHPF2, "LHPF2"),
+WM5100_MIXER_WIDGETS(LHPF3, "LHPF3"),
+WM5100_MIXER_WIDGETS(LHPF4, "LHPF4"),
+
+WM5100_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
+WM5100_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
+WM5100_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
+WM5100_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
+WM5100_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
+WM5100_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
+WM5100_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"),
+WM5100_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"),
+
+WM5100_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"),
+WM5100_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
+
+WM5100_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
+WM5100_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
+
+WM5100_MIXER_WIDGETS(HPOUT1L, "HPOUT1L"),
+WM5100_MIXER_WIDGETS(HPOUT1R, "HPOUT1R"),
+WM5100_MIXER_WIDGETS(HPOUT2L, "HPOUT2L"),
+WM5100_MIXER_WIDGETS(HPOUT2R, "HPOUT2R"),
+WM5100_MIXER_WIDGETS(HPOUT3L, "HPOUT3L"),
+WM5100_MIXER_WIDGETS(HPOUT3R, "HPOUT3R"),
+
+WM5100_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"),
+WM5100_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"),
+WM5100_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"),
+WM5100_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"),
+WM5100_MIXER_WIDGETS(SPKDAT2L, "SPKDAT2L"),
+WM5100_MIXER_WIDGETS(SPKDAT2R, "SPKDAT2R"),
+
+WM5100_MIXER_WIDGETS(PWM1, "PWM1"),
+WM5100_MIXER_WIDGETS(PWM2, "PWM2"),
+
+SND_SOC_DAPM_OUTPUT("HPOUT1L"),
+SND_SOC_DAPM_OUTPUT("HPOUT1R"),
+SND_SOC_DAPM_OUTPUT("HPOUT2L"),
+SND_SOC_DAPM_OUTPUT("HPOUT2R"),
+SND_SOC_DAPM_OUTPUT("HPOUT3L"),
+SND_SOC_DAPM_OUTPUT("HPOUT3R"),
+SND_SOC_DAPM_OUTPUT("SPKOUTL"),
+SND_SOC_DAPM_OUTPUT("SPKOUTR"),
+SND_SOC_DAPM_OUTPUT("SPKDAT1"),
+SND_SOC_DAPM_OUTPUT("SPKDAT2"),
+SND_SOC_DAPM_OUTPUT("PWM1"),
+SND_SOC_DAPM_OUTPUT("PWM2"),
+};
+
+/* We register a _POST event if we don't have IRQ support so we can
+ * look at the error status from the CODEC - if we've got the IRQ
+ * hooked up then we will get prompted to look by an interrupt.
+ */
+static const struct snd_soc_dapm_widget wm5100_dapm_widgets_noirq[] = {
+SND_SOC_DAPM_POST("Post", wm5100_post_ev),
+};
+
+static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
+       { "IN1L", NULL, "SYSCLK" },
+       { "IN1R", NULL, "SYSCLK" },
+       { "IN2L", NULL, "SYSCLK" },
+       { "IN2R", NULL, "SYSCLK" },
+       { "IN3L", NULL, "SYSCLK" },
+       { "IN3R", NULL, "SYSCLK" },
+       { "IN4L", NULL, "SYSCLK" },
+       { "IN4R", NULL, "SYSCLK" },
+
+       { "OUT1L", NULL, "SYSCLK" },
+       { "OUT1R", NULL, "SYSCLK" },
+       { "OUT2L", NULL, "SYSCLK" },
+       { "OUT2R", NULL, "SYSCLK" },
+       { "OUT3L", NULL, "SYSCLK" },
+       { "OUT3R", NULL, "SYSCLK" },
+       { "OUT4L", NULL, "SYSCLK" },
+       { "OUT4R", NULL, "SYSCLK" },
+       { "OUT5L", NULL, "SYSCLK" },
+       { "OUT5R", NULL, "SYSCLK" },
+       { "OUT6L", NULL, "SYSCLK" },
+       { "OUT6R", NULL, "SYSCLK" },
+
+       { "AIF1RX1", NULL, "SYSCLK" },
+       { "AIF1RX2", NULL, "SYSCLK" },
+       { "AIF1RX3", NULL, "SYSCLK" },
+       { "AIF1RX4", NULL, "SYSCLK" },
+       { "AIF1RX5", NULL, "SYSCLK" },
+       { "AIF1RX6", NULL, "SYSCLK" },
+       { "AIF1RX7", NULL, "SYSCLK" },
+       { "AIF1RX8", NULL, "SYSCLK" },
+
+       { "AIF2RX1", NULL, "SYSCLK" },
+       { "AIF2RX1", NULL, "DBVDD2" },
+       { "AIF2RX2", NULL, "SYSCLK" },
+       { "AIF2RX2", NULL, "DBVDD2" },
+
+       { "AIF3RX1", NULL, "SYSCLK" },
+       { "AIF3RX1", NULL, "DBVDD3" },
+       { "AIF3RX2", NULL, "SYSCLK" },
+       { "AIF3RX2", NULL, "DBVDD3" },
+
+       { "AIF1TX1", NULL, "SYSCLK" },
+       { "AIF1TX2", NULL, "SYSCLK" },
+       { "AIF1TX3", NULL, "SYSCLK" },
+       { "AIF1TX4", NULL, "SYSCLK" },
+       { "AIF1TX5", NULL, "SYSCLK" },
+       { "AIF1TX6", NULL, "SYSCLK" },
+       { "AIF1TX7", NULL, "SYSCLK" },
+       { "AIF1TX8", NULL, "SYSCLK" },
+
+       { "AIF2TX1", NULL, "SYSCLK" },
+       { "AIF2TX1", NULL, "DBVDD2" },
+       { "AIF2TX2", NULL, "SYSCLK" },
+       { "AIF2TX2", NULL, "DBVDD2" },
+
+       { "AIF3TX1", NULL, "SYSCLK" },
+       { "AIF3TX1", NULL, "DBVDD3" },
+       { "AIF3TX2", NULL, "SYSCLK" },
+       { "AIF3TX2", NULL, "DBVDD3" },
+
+       { "MICBIAS1", NULL, "CP2" },
+       { "MICBIAS2", NULL, "CP2" },
+       { "MICBIAS3", NULL, "CP2" },
+
+       { "IN1L PGA", NULL, "CP2" },
+       { "IN1R PGA", NULL, "CP2" },
+       { "IN2L PGA", NULL, "CP2" },
+       { "IN2R PGA", NULL, "CP2" },
+       { "IN3L PGA", NULL, "CP2" },
+       { "IN3R PGA", NULL, "CP2" },
+       { "IN4L PGA", NULL, "CP2" },
+       { "IN4R PGA", NULL, "CP2" },
+
+       { "IN1L PGA", NULL, "CP2 Active" },
+       { "IN1R PGA", NULL, "CP2 Active" },
+       { "IN2L PGA", NULL, "CP2 Active" },
+       { "IN2R PGA", NULL, "CP2 Active" },
+       { "IN3L PGA", NULL, "CP2 Active" },
+       { "IN3R PGA", NULL, "CP2 Active" },
+       { "IN4L PGA", NULL, "CP2 Active" },
+       { "IN4R PGA", NULL, "CP2 Active" },
+
+       { "OUT1L", NULL, "CP1" },
+       { "OUT1R", NULL, "CP1" },
+       { "OUT2L", NULL, "CP1" },
+       { "OUT2R", NULL, "CP1" },
+       { "OUT3L", NULL, "CP1" },
+       { "OUT3R", NULL, "CP1" },
+
+       { "Tone Generator 1", NULL, "TONE" },
+       { "Tone Generator 2", NULL, "TONE" },
+
+       { "IN1L PGA", NULL, "IN1L" },
+       { "IN1R PGA", NULL, "IN1R" },
+       { "IN2L PGA", NULL, "IN2L" },
+       { "IN2R PGA", NULL, "IN2R" },
+       { "IN3L PGA", NULL, "IN3L" },
+       { "IN3R PGA", NULL, "IN3R" },
+       { "IN4L PGA", NULL, "IN4L" },
+       { "IN4R PGA", NULL, "IN4R" },
+
+       WM5100_MIXER_ROUTES("OUT1L", "HPOUT1L"),
+       WM5100_MIXER_ROUTES("OUT1R", "HPOUT1R"),
+       WM5100_MIXER_ROUTES("OUT2L", "HPOUT2L"),
+       WM5100_MIXER_ROUTES("OUT2R", "HPOUT2R"),
+       WM5100_MIXER_ROUTES("OUT3L", "HPOUT3L"),
+       WM5100_MIXER_ROUTES("OUT3R", "HPOUT3R"),
+
+       WM5100_MIXER_ROUTES("OUT4L", "SPKOUTL"),
+       WM5100_MIXER_ROUTES("OUT4R", "SPKOUTR"),
+       WM5100_MIXER_ROUTES("OUT5L", "SPKDAT1L"),
+       WM5100_MIXER_ROUTES("OUT5R", "SPKDAT1R"),
+       WM5100_MIXER_ROUTES("OUT6L", "SPKDAT2L"),
+       WM5100_MIXER_ROUTES("OUT6R", "SPKDAT2R"),
+
+       WM5100_MIXER_ROUTES("PWM1 Driver", "PWM1"),
+       WM5100_MIXER_ROUTES("PWM2 Driver", "PWM2"),
+
+       WM5100_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
+       WM5100_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
+       WM5100_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
+       WM5100_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
+       WM5100_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
+       WM5100_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
+       WM5100_MIXER_ROUTES("AIF1TX7", "AIF1TX7"),
+       WM5100_MIXER_ROUTES("AIF1TX8", "AIF1TX8"),
+
+       WM5100_MIXER_ROUTES("AIF2TX1", "AIF2TX1"),
+       WM5100_MIXER_ROUTES("AIF2TX2", "AIF2TX2"),
+
+       WM5100_MIXER_ROUTES("AIF3TX1", "AIF3TX1"),
+       WM5100_MIXER_ROUTES("AIF3TX2", "AIF3TX2"),
+
+       WM5100_MIXER_ROUTES("EQ1", "EQ1"),
+       WM5100_MIXER_ROUTES("EQ2", "EQ2"),
+       WM5100_MIXER_ROUTES("EQ3", "EQ3"),
+       WM5100_MIXER_ROUTES("EQ4", "EQ4"),
+
+       WM5100_MIXER_ROUTES("DRC1L", "DRC1L"),
+       WM5100_MIXER_ROUTES("DRC1R", "DRC1R"),
+
+       WM5100_MIXER_ROUTES("LHPF1", "LHPF1"),
+       WM5100_MIXER_ROUTES("LHPF2", "LHPF2"),
+       WM5100_MIXER_ROUTES("LHPF3", "LHPF3"),
+       WM5100_MIXER_ROUTES("LHPF4", "LHPF4"),
+
+       { "HPOUT1L", NULL, "OUT1L" },
+       { "HPOUT1R", NULL, "OUT1R" },
+       { "HPOUT2L", NULL, "OUT2L" },
+       { "HPOUT2R", NULL, "OUT2R" },
+       { "HPOUT3L", NULL, "OUT3L" },
+       { "HPOUT3R", NULL, "OUT3R" },
+       { "SPKOUTL", NULL, "OUT4L" },
+       { "SPKOUTR", NULL, "OUT4R" },
+       { "SPKDAT1", NULL, "OUT5L" },
+       { "SPKDAT1", NULL, "OUT5R" },
+       { "SPKDAT2", NULL, "OUT6L" },
+       { "SPKDAT2", NULL, "OUT6R" },
+       { "PWM1", NULL, "PWM1 Driver" },
+       { "PWM2", NULL, "PWM2 Driver" },
+};
+
+static struct {
+       int reg;
+       int val;
+} wm5100_reva_patches[] = {
+       { WM5100_AUDIO_IF_1_10, 0 },
+       { WM5100_AUDIO_IF_1_11, 1 },
+       { WM5100_AUDIO_IF_1_12, 2 },
+       { WM5100_AUDIO_IF_1_13, 3 },
+       { WM5100_AUDIO_IF_1_14, 4 },
+       { WM5100_AUDIO_IF_1_15, 5 },
+       { WM5100_AUDIO_IF_1_16, 6 },
+       { WM5100_AUDIO_IF_1_17, 7 },
+
+       { WM5100_AUDIO_IF_1_18, 0 },
+       { WM5100_AUDIO_IF_1_19, 1 },
+       { WM5100_AUDIO_IF_1_20, 2 },
+       { WM5100_AUDIO_IF_1_21, 3 },
+       { WM5100_AUDIO_IF_1_22, 4 },
+       { WM5100_AUDIO_IF_1_23, 5 },
+       { WM5100_AUDIO_IF_1_24, 6 },
+       { WM5100_AUDIO_IF_1_25, 7 },
+
+       { WM5100_AUDIO_IF_2_10, 0 },
+       { WM5100_AUDIO_IF_2_11, 1 },
+
+       { WM5100_AUDIO_IF_2_18, 0 },
+       { WM5100_AUDIO_IF_2_19, 1 },
+
+       { WM5100_AUDIO_IF_3_10, 0 },
+       { WM5100_AUDIO_IF_3_11, 1 },
+
+       { WM5100_AUDIO_IF_3_18, 0 },
+       { WM5100_AUDIO_IF_3_19, 1 },
+};
+
+static int wm5100_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int ret, i;
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               break;
+
+       case SND_SOC_BIAS_PREPARE:
+               break;
+
+       case SND_SOC_BIAS_STANDBY:
+               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
+                                                   wm5100->core_supplies);
+                       if (ret != 0) {
+                               dev_err(codec->dev,
+                                       "Failed to enable supplies: %d\n",
+                                       ret);
+                               return ret;
+                       }
+
+                       if (wm5100->pdata.ldo_ena) {
+                               gpio_set_value_cansleep(wm5100->pdata.ldo_ena,
+                                                       1);
+                               msleep(2);
+                       }
+
+                       codec->cache_only = false;
+
+                       switch (wm5100->rev) {
+                       case 0:
+                               snd_soc_write(codec, 0x11, 0x3);
+                               snd_soc_write(codec, 0x203, 0xc);
+                               snd_soc_write(codec, 0x206, 0);
+                               snd_soc_write(codec, 0x207, 0xf0);
+                               snd_soc_write(codec, 0x208, 0x3c);
+                               snd_soc_write(codec, 0x209, 0);
+                               snd_soc_write(codec, 0x211, 0x20d8);
+                               snd_soc_write(codec, 0x11, 0);
+
+                               for (i = 0;
+                                    i < ARRAY_SIZE(wm5100_reva_patches);
+                                    i++)
+                                       snd_soc_write(codec,
+                                                     wm5100_reva_patches[i].reg,
+                                                     wm5100_reva_patches[i].val);
+                               break;
+                       default:
+                               break;
+                       }
+
+                       snd_soc_cache_sync(codec);
+               }
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               if (wm5100->pdata.ldo_ena)
+                       gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+               regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
+                                      wm5100->core_supplies);
+               break;
+       }
+       codec->dapm.bias_level = level;
+
+       return 0;
+}
+
+static int wm5100_dai_to_base(struct snd_soc_dai *dai)
+{
+       switch (dai->id) {
+       case 0:
+               return WM5100_AUDIO_IF_1_1 - 1;
+       case 1:
+               return WM5100_AUDIO_IF_2_1 - 1;
+       case 2:
+               return WM5100_AUDIO_IF_3_1 - 1;
+       default:
+               BUG();
+               return -EINVAL;
+       }
+}
+
+static int wm5100_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       int lrclk, bclk, mask, base;
+
+       base = wm5100_dai_to_base(dai);
+       if (base < 0)
+               return base;
+
+       lrclk = 0;
+       bclk = 0;
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+               mask = 0;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               mask = 1;
+               break;
+       case SND_SOC_DAIFMT_I2S:
+               mask = 2;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               mask = 3;
+               break;
+       default:
+               dev_err(codec->dev, "Unsupported DAI format %d\n",
+                       fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               break;
+       case SND_SOC_DAIFMT_CBS_CFM:
+               lrclk |= WM5100_AIF1TX_LRCLK_MSTR;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFS:
+               bclk |= WM5100_AIF1_BCLK_MSTR;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFM:
+               lrclk |= WM5100_AIF1TX_LRCLK_MSTR;
+               bclk |= WM5100_AIF1_BCLK_MSTR;
+               break;
+       default:
+               dev_err(codec->dev, "Unsupported master mode %d\n",
+                       fmt & SND_SOC_DAIFMT_MASTER_MASK);
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               bclk |= WM5100_AIF1_BCLK_INV;
+               lrclk |= WM5100_AIF1TX_LRCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               bclk |= WM5100_AIF1_BCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               lrclk |= WM5100_AIF1TX_LRCLK_INV;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, base + 1, WM5100_AIF1_BCLK_MSTR |
+                           WM5100_AIF1_BCLK_INV, bclk);
+       snd_soc_update_bits(codec, base + 2, WM5100_AIF1TX_LRCLK_MSTR |
+                           WM5100_AIF1TX_LRCLK_INV, lrclk);
+       snd_soc_update_bits(codec, base + 3, WM5100_AIF1TX_LRCLK_MSTR |
+                           WM5100_AIF1TX_LRCLK_INV, lrclk);
+       snd_soc_update_bits(codec, base + 5, WM5100_AIF1_FMT_MASK, mask);
+
+       return 0;
+}
+
+#define WM5100_NUM_BCLK_RATES 19
+
+static int wm5100_bclk_rates_dat[WM5100_NUM_BCLK_RATES] = {
+       32000,
+       48000,
+       64000,
+       96000,
+       128000,
+       192000,
+       256000,
+       384000,
+       512000,
+       768000,
+       1024000,
+       1536000,
+       2048000,
+       3072000,
+       4096000,
+       6144000,
+       8192000,
+       12288000,
+       24576000,
+};
+
+static int wm5100_bclk_rates_cd[WM5100_NUM_BCLK_RATES] = {
+       29400,
+       44100,
+       58800,
+       88200,
+       117600,
+       176400,
+       235200,
+       352800,
+       470400,
+       705600,
+       940800,
+       1411200,
+       1881600,
+       2882400,
+       3763200,
+       5644800,
+       7526400,
+       11289600,
+       22579600,
+};
+
+static int wm5100_hw_params(struct snd_pcm_substream *substream,
+                           struct snd_pcm_hw_params *params,
+                           struct snd_soc_dai *dai)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       bool async = wm5100->aif_async[dai->id];
+       int i, base, bclk, aif_rate, lrclk, wl, fl, sr;
+       int *bclk_rates;
+
+       base = wm5100_dai_to_base(dai);
+       if (base < 0)
+               return base;
+
+       /* Data sizes if not using TDM */
+       wl = snd_pcm_format_width(params_format(params));
+       if (wl < 0)
+               return wl;
+       fl = snd_soc_params_to_frame_size(params);
+       if (fl < 0)
+               return fl;
+
+       dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n",
+               wl, fl);
+
+       /* Target BCLK rate */
+       bclk = snd_soc_params_to_bclk(params);
+       if (bclk < 0)
+               return bclk;
+
+       /* Root for BCLK depends on SYS/ASYNCCLK */
+       if (!async) {
+               aif_rate = wm5100->sysclk;
+               sr = wm5100_alloc_sr(codec, params_rate(params));
+               if (sr < 0)
+                       return sr;
+       } else {
+               /* If we're in ASYNCCLK set the ASYNC sample rate */
+               aif_rate = wm5100->asyncclk;
+               sr = 3;
+
+               for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++)
+                       if (params_rate(params) == wm5100_sr_code[i])
+                               break;
+               if (i == ARRAY_SIZE(wm5100_sr_code)) {
+                       dev_err(codec->dev, "Invalid rate %dHzn",
+                               params_rate(params));
+                       return -EINVAL;
+               }
+
+               /* TODO: We should really check for symmetry */
+               snd_soc_update_bits(codec, WM5100_CLOCKING_8,
+                                   WM5100_ASYNC_SAMPLE_RATE_MASK, i);
+       }
+
+       if (!aif_rate) {
+               dev_err(codec->dev, "%s has no rate set\n",
+                       async ? "ASYNCCLK" : "SYSCLK");
+               return -EINVAL;
+       }
+
+       dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz %s\n",
+               bclk, aif_rate, async ? "ASYNCCLK" : "SYSCLK");
+
+       if (aif_rate % 4000)
+               bclk_rates = wm5100_bclk_rates_cd;
+       else
+               bclk_rates = wm5100_bclk_rates_dat;
+
+       for (i = 0; i < WM5100_NUM_BCLK_RATES; i++)
+               if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0))
+                       break;
+       if (i == WM5100_NUM_BCLK_RATES) {
+               dev_err(codec->dev,
+                       "No valid BCLK for %dHz found from %dHz %s\n",
+                       bclk, aif_rate, async ? "ASYNCCLK" : "SYSCLK");
+               return -EINVAL;
+       }
+
+       bclk = i;
+       dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]);
+       snd_soc_update_bits(codec, base + 1, WM5100_AIF1_BCLK_FREQ_MASK, bclk);
+
+       lrclk = bclk_rates[bclk] / params_rate(params);
+       dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+           wm5100->aif_symmetric[dai->id])
+               snd_soc_update_bits(codec, base + 7,
+                                   WM5100_AIF1RX_BCPF_MASK, lrclk);
+       else
+               snd_soc_update_bits(codec, base + 6,
+                                   WM5100_AIF1TX_BCPF_MASK, lrclk);
+
+       i = (wl << WM5100_AIF1TX_WL_SHIFT) | fl;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               snd_soc_update_bits(codec, base + 9,
+                                   WM5100_AIF1RX_WL_MASK |
+                                   WM5100_AIF1RX_SLOT_LEN_MASK, i);
+       else
+               snd_soc_update_bits(codec, base + 8,
+                                   WM5100_AIF1TX_WL_MASK |
+                                   WM5100_AIF1TX_SLOT_LEN_MASK, i);
+
+       snd_soc_update_bits(codec, base + 4, WM5100_AIF1_RATE_MASK, sr);
+
+       return 0;
+}
+
+static struct snd_soc_dai_ops wm5100_dai_ops = {
+       .set_fmt = wm5100_set_fmt,
+       .hw_params = wm5100_hw_params,
+};
+
+static int wm5100_set_sysclk(struct snd_soc_codec *codec, int clk_id,
+                            int source, unsigned int freq, int dir)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int *rate_store;
+       int fval, audio_rate, ret, reg;
+
+       switch (clk_id) {
+       case WM5100_CLK_SYSCLK:
+               reg = WM5100_CLOCKING_3;
+               rate_store = &wm5100->sysclk;
+               break;
+       case WM5100_CLK_ASYNCCLK:
+               reg = WM5100_CLOCKING_7;
+               rate_store = &wm5100->asyncclk;
+               break;
+       case WM5100_CLK_32KHZ:
+               /* The 32kHz clock is slightly different to the others */
+               switch (source) {
+               case WM5100_CLKSRC_MCLK1:
+               case WM5100_CLKSRC_MCLK2:
+               case WM5100_CLKSRC_SYSCLK:
+                       snd_soc_update_bits(codec, WM5100_CLOCKING_1,
+                                           WM5100_CLK_32K_SRC_MASK,
+                                           source);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               return 0;
+
+       case WM5100_CLK_AIF1:
+       case WM5100_CLK_AIF2:
+       case WM5100_CLK_AIF3:
+               /* Not real clocks, record which clock domain they're in */
+               switch (source) {
+               case WM5100_CLKSRC_SYSCLK:
+                       wm5100->aif_async[clk_id - 1] = false;
+                       break;
+               case WM5100_CLKSRC_ASYNCCLK:
+                       wm5100->aif_async[clk_id - 1] = true;
+                       break;
+               default:
+                       dev_err(codec->dev, "Invalid source %d\n", source);
+                       return -EINVAL;
+               }       
+               return 0;
+
+       case WM5100_CLK_OPCLK:
+               switch (freq) {
+               case 5644800:
+               case 6144000:
+                       snd_soc_update_bits(codec, WM5100_MISC_GPIO_1,
+                                           WM5100_OPCLK_SEL_MASK, 0);
+                       break;
+               case 11289600:
+               case 12288000:
+                       snd_soc_update_bits(codec, WM5100_MISC_GPIO_1,
+                                           WM5100_OPCLK_SEL_MASK, 0);
+                       break;
+               case 22579200:
+               case 24576000:
+                       snd_soc_update_bits(codec, WM5100_MISC_GPIO_1,
+                                           WM5100_OPCLK_SEL_MASK, 0);
+                       break;
+               default:
+                       dev_err(codec->dev, "Unsupported OPCLK %dHz\n",
+                               freq);
+                       return -EINVAL;
+               }
+               return 0;
+
+       default:
+               dev_err(codec->dev, "Unknown clock %d\n", clk_id);
+               return -EINVAL;
+       }
+
+       switch (source) {
+       case WM5100_CLKSRC_SYSCLK:
+       case WM5100_CLKSRC_ASYNCCLK:
+               dev_err(codec->dev, "Invalid source %d\n", source);
+               return -EINVAL;
+       }
+
+       switch (freq) {
+       case 5644800:
+       case 6144000:
+               fval = 0;
+               break;
+       case 11289600:
+       case 12288000:
+               fval = 1;
+               break;
+       case 22579200:
+       case 24576000:
+               fval = 2;
+               break;
+       default:
+               dev_err(codec->dev, "Invalid clock rate: %d\n", freq);
+               return -EINVAL;
+       }
+
+       switch (freq) {
+       case 5644800:
+       case 11289600:
+       case 22579200:
+               audio_rate = 44100;
+               break;
+
+       case 6144000:
+       case 12288000:
+       case 24576000:
+               audio_rate = 48000;
+               break;
+
+       default:
+               BUG();
+               audio_rate = 0;
+               break;
+       }
+
+       /* TODO: Check if MCLKs are in use and enable/disable pulls to
+        * match.
+        */
+
+       snd_soc_update_bits(codec, reg, WM5100_SYSCLK_FREQ_MASK |
+                           WM5100_SYSCLK_SRC_MASK,
+                           fval << WM5100_SYSCLK_FREQ_SHIFT | source);
+
+       /* If this is SYSCLK then configure the clock rate for the
+        * internal audio functions to the natural sample rate for
+        * this clock rate.
+        */
+       if (clk_id == WM5100_CLK_SYSCLK) {
+               dev_dbg(codec->dev, "Setting primary audio rate to %dHz",
+                       audio_rate);
+               if (0 && *rate_store)
+                       wm5100_free_sr(codec, audio_rate);
+               ret = wm5100_alloc_sr(codec, audio_rate);
+               if (ret != 0)
+                       dev_warn(codec->dev, "Primary audio slot is %d\n",
+                                ret);
+       }
+
+       *rate_store = freq;
+
+       return 0;
+}
+
+struct _fll_div {
+       u16 fll_fratio;
+       u16 fll_outdiv;
+       u16 fll_refclk_div;
+       u16 n;
+       u16 theta;
+       u16 lambda;
+};
+
+static struct {
+       unsigned int min;
+       unsigned int max;
+       u16 fll_fratio;
+       int ratio;
+} fll_fratios[] = {
+       {       0,    64000, 4, 16 },
+       {   64000,   128000, 3,  8 },
+       {  128000,   256000, 2,  4 },
+       {  256000,  1000000, 1,  2 },
+       { 1000000, 13500000, 0,  1 },
+};
+
+static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
+                      unsigned int Fout)
+{
+       unsigned int target;
+       unsigned int div;
+       unsigned int fratio, gcd_fll;
+       int i;
+
+       /* Fref must be <=13.5MHz */
+       div = 1;
+       fll_div->fll_refclk_div = 0;
+       while ((Fref / div) > 13500000) {
+               div *= 2;
+               fll_div->fll_refclk_div++;
+
+               if (div > 8) {
+                       pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
+                              Fref);
+                       return -EINVAL;
+               }
+       }
+
+       pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
+
+       /* Apply the division for our remaining calculations */
+       Fref /= div;
+
+       /* Fvco should be 90-100MHz; don't check the upper bound */
+       div = 2;
+       while (Fout * div < 90000000) {
+               div++;
+               if (div > 64) {
+                       pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
+                              Fout);
+                       return -EINVAL;
+               }
+       }
+       target = Fout * div;
+       fll_div->fll_outdiv = div - 1;
+
+       pr_debug("FLL Fvco=%dHz\n", target);
+
+       /* Find an appropraite FLL_FRATIO and factor it out of the target */
+       for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
+               if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
+                       fll_div->fll_fratio = fll_fratios[i].fll_fratio;
+                       fratio = fll_fratios[i].ratio;
+                       break;
+               }
+       }
+       if (i == ARRAY_SIZE(fll_fratios)) {
+               pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
+               return -EINVAL;
+       }
+
+       fll_div->n = target / (fratio * Fref);
+
+       if (target % Fref == 0) {
+               fll_div->theta = 0;
+               fll_div->lambda = 0;
+       } else {
+               gcd_fll = gcd(target, fratio * Fref);
+
+               fll_div->theta = (target - (fll_div->n * fratio * Fref))
+                       / gcd_fll;
+               fll_div->lambda = (fratio * Fref) / gcd_fll;
+       }
+
+       pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
+                fll_div->n, fll_div->theta, fll_div->lambda);
+       pr_debug("FLL_FRATIO=%x(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
+                fll_div->fll_fratio, fratio, fll_div->fll_outdiv,
+                fll_div->fll_refclk_div);
+
+       return 0;
+}
+
+static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
+                         unsigned int Fref, unsigned int Fout)
+{
+       struct i2c_client *i2c = to_i2c_client(codec->dev);
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       struct _fll_div factors;
+       struct wm5100_fll *fll;
+       int ret, base, lock, i, timeout;
+
+       switch (fll_id) {
+       case WM5100_FLL1:
+               fll = &wm5100->fll[0];
+               base = WM5100_FLL1_CONTROL_1 - 1;
+               lock = WM5100_FLL1_LOCK_STS;
+               break;
+       case WM5100_FLL2:
+               fll = &wm5100->fll[1];
+               base = WM5100_FLL2_CONTROL_2 - 1;
+               lock = WM5100_FLL2_LOCK_STS;
+               break;
+       default:
+               dev_err(codec->dev, "Unknown FLL %d\n",fll_id);
+               return -EINVAL;
+       }
+
+       if (!Fout) {
+               dev_dbg(codec->dev, "FLL%d disabled", fll_id);
+               fll->fout = 0;
+               snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0);
+               return 0;
+       }
+
+       switch (source) {
+       case WM5100_FLL_SRC_MCLK1:
+       case WM5100_FLL_SRC_MCLK2:
+       case WM5100_FLL_SRC_FLL1:
+       case WM5100_FLL_SRC_FLL2:
+       case WM5100_FLL_SRC_AIF1BCLK:
+       case WM5100_FLL_SRC_AIF2BCLK:
+       case WM5100_FLL_SRC_AIF3BCLK:
+               break;
+       default:
+               dev_err(codec->dev, "Invalid FLL source %d\n", source);
+               return -EINVAL;
+       }
+
+       ret = fll_factors(&factors, Fref, Fout);
+       if (ret < 0)
+               return ret;
+
+       /* Disable the FLL while we reconfigure */
+       snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0);
+
+       snd_soc_update_bits(codec, base + 2,
+                           WM5100_FLL1_OUTDIV_MASK | WM5100_FLL1_FRATIO_MASK,
+                           (factors.fll_outdiv << WM5100_FLL1_OUTDIV_SHIFT) |
+                           factors.fll_fratio);
+       snd_soc_update_bits(codec, base + 3, WM5100_FLL1_THETA_MASK,
+                           factors.theta);
+       snd_soc_update_bits(codec, base + 5, WM5100_FLL1_N_MASK, factors.n);
+       snd_soc_update_bits(codec, base + 6,
+                           WM5100_FLL1_REFCLK_DIV_MASK |
+                           WM5100_FLL1_REFCLK_SRC_MASK,
+                           (factors.fll_refclk_div
+                            << WM5100_FLL1_REFCLK_DIV_SHIFT) | source);
+       snd_soc_update_bits(codec, base + 7, WM5100_FLL1_LAMBDA_MASK,
+                           factors.lambda);
+
+       /* Clear any pending completions */
+       try_wait_for_completion(&fll->lock);
+
+       snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, WM5100_FLL1_ENA);
+
+       if (i2c->irq)
+               timeout = 2;
+       else
+               timeout = 50;
+
+       /* Poll for the lock; will use interrupt when we can test */
+       for (i = 0; i < timeout; i++) {
+               if (i2c->irq) {
+                       ret = wait_for_completion_timeout(&fll->lock,
+                                                         msecs_to_jiffies(25));
+                       if (ret > 0)
+                               break;
+               } else {
+                       msleep(1);
+               }
+
+               ret = snd_soc_read(codec,
+                                  WM5100_INTERRUPT_RAW_STATUS_3);
+               if (ret < 0) {
+                       dev_err(codec->dev,
+                               "Failed to read FLL status: %d\n",
+                               ret);
+                       continue;
+               }
+               if (ret & lock)
+                       break;
+       }
+       if (i == timeout) {
+               dev_err(codec->dev, "FLL%d lock timed out\n", fll_id);
+               return -ETIMEDOUT;
+       }
+
+       fll->src = source;
+       fll->fref = Fref;
+       fll->fout = Fout;
+
+       dev_dbg(codec->dev, "FLL%d running %dHz->%dHz\n", fll_id,
+               Fref, Fout);
+
+       return 0;
+}
+
+/* Actually go much higher */
+#define WM5100_RATES SNDRV_PCM_RATE_8000_192000
+
+#define WM5100_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+                       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver wm5100_dai[] = {
+       {
+               .name = "wm5100-aif1",
+               .playback = {
+                       .stream_name = "AIF1 Playback",
+                       .channels_min = 2,
+                       .channels_max = 2,
+                       .rates = WM5100_RATES,
+                       .formats = WM5100_FORMATS,
+               },
+               .capture = {
+                        .stream_name = "AIF1 Capture",
+                        .channels_min = 2,
+                        .channels_max = 2,
+                        .rates = WM5100_RATES,
+                        .formats = WM5100_FORMATS,
+                },
+               .ops = &wm5100_dai_ops,
+       },
+       {
+               .name = "wm5100-aif2",
+               .id = 1,
+               .playback = {
+                       .stream_name = "AIF2 Playback",
+                       .channels_min = 2,
+                       .channels_max = 2,
+                       .rates = WM5100_RATES,
+                       .formats = WM5100_FORMATS,
+               },
+               .capture = {
+                        .stream_name = "AIF2 Capture",
+                        .channels_min = 2,
+                        .channels_max = 2,
+                        .rates = WM5100_RATES,
+                        .formats = WM5100_FORMATS,
+                },
+               .ops = &wm5100_dai_ops,
+       },
+       {
+               .name = "wm5100-aif3",
+               .id = 2,
+               .playback = {
+                       .stream_name = "AIF3 Playback",
+                       .channels_min = 2,
+                       .channels_max = 2,
+                       .rates = WM5100_RATES,
+                       .formats = WM5100_FORMATS,
+               },
+               .capture = {
+                        .stream_name = "AIF3 Capture",
+                        .channels_min = 2,
+                        .channels_max = 2,
+                        .rates = WM5100_RATES,
+                        .formats = WM5100_FORMATS,
+                },
+               .ops = &wm5100_dai_ops,
+       },
+};
+
+static int wm5100_dig_vu[] = {
+       WM5100_ADC_DIGITAL_VOLUME_1L,
+       WM5100_ADC_DIGITAL_VOLUME_1R,
+       WM5100_ADC_DIGITAL_VOLUME_2L,
+       WM5100_ADC_DIGITAL_VOLUME_2R,
+       WM5100_ADC_DIGITAL_VOLUME_3L,
+       WM5100_ADC_DIGITAL_VOLUME_3R,
+       WM5100_ADC_DIGITAL_VOLUME_4L,
+       WM5100_ADC_DIGITAL_VOLUME_4R,
+
+       WM5100_DAC_DIGITAL_VOLUME_1L,
+       WM5100_DAC_DIGITAL_VOLUME_1R,
+       WM5100_DAC_DIGITAL_VOLUME_2L,
+       WM5100_DAC_DIGITAL_VOLUME_2R,
+       WM5100_DAC_DIGITAL_VOLUME_3L,
+       WM5100_DAC_DIGITAL_VOLUME_3R,
+       WM5100_DAC_DIGITAL_VOLUME_4L,
+       WM5100_DAC_DIGITAL_VOLUME_4R,
+       WM5100_DAC_DIGITAL_VOLUME_5L,
+       WM5100_DAC_DIGITAL_VOLUME_5R,
+       WM5100_DAC_DIGITAL_VOLUME_6L,
+       WM5100_DAC_DIGITAL_VOLUME_6R,
+};
+
+static void wm5100_set_detect_mode(struct snd_soc_codec *codec, int the_mode)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       struct wm5100_jack_mode *mode = &wm5100->pdata.jack_modes[the_mode];
+
+       BUG_ON(the_mode >= ARRAY_SIZE(wm5100->pdata.jack_modes));
+
+       gpio_set_value_cansleep(wm5100->pdata.hp_pol, mode->hp_pol);
+       snd_soc_update_bits(codec, WM5100_ACCESSORY_DETECT_MODE_1,
+                           WM5100_ACCDET_BIAS_SRC_MASK |
+                           WM5100_ACCDET_SRC,
+                           (mode->bias << WM5100_ACCDET_BIAS_SRC_SHIFT) |
+                           mode->micd_src << WM5100_ACCDET_SRC_SHIFT);
+       snd_soc_update_bits(codec, WM5100_MISC_CONTROL,
+                           WM5100_HPCOM_SRC,
+                           mode->micd_src << WM5100_HPCOM_SRC_SHIFT);
+
+       wm5100->jack_mode = the_mode;
+
+       dev_dbg(codec->dev, "Set microphone polarity to %d\n",
+               wm5100->jack_mode);
+}
+
+static void wm5100_micd_irq(struct snd_soc_codec *codec)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int val;
+
+       val = snd_soc_read(codec, WM5100_MIC_DETECT_3);
+
+       dev_dbg(codec->dev, "Microphone event: %x\n", val);
+
+       if (!(val & WM5100_ACCDET_VALID)) {
+               dev_warn(codec->dev, "Microphone detection state invalid\n");
+               return;
+       }
+
+       /* No accessory, reset everything and report removal */
+       if (!(val & WM5100_ACCDET_STS)) {
+               dev_dbg(codec->dev, "Jack removal detected\n");
+               wm5100->jack_mic = false;
+               wm5100->jack_detecting = true;
+               snd_soc_jack_report(wm5100->jack, 0,
+                                   SND_JACK_LINEOUT | SND_JACK_HEADSET |
+                                   SND_JACK_BTN_0);
+
+               snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
+                                   WM5100_ACCDET_RATE_MASK,
+                                   WM5100_ACCDET_RATE_MASK);
+               return;
+       }
+
+       /* If the measurement is very high we've got a microphone,
+        * either we just detected one or if we already reported then
+        * we've got a button release event.
+        */
+       if (val & 0x400) {
+               if (wm5100->jack_detecting) {
+                       dev_dbg(codec->dev, "Microphone detected\n");
+                       wm5100->jack_mic = true;
+                       snd_soc_jack_report(wm5100->jack,
+                                           SND_JACK_HEADSET,
+                                           SND_JACK_HEADSET | SND_JACK_BTN_0);
+
+                       /* Increase poll rate to give better responsiveness
+                        * for buttons */
+                       snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
+                                           WM5100_ACCDET_RATE_MASK,
+                                           5 << WM5100_ACCDET_RATE_SHIFT);
+               } else {
+                       dev_dbg(codec->dev, "Mic button up\n");
+                       snd_soc_jack_report(wm5100->jack, 0, SND_JACK_BTN_0);
+               }
+
+               return;
+       }
+
+       /* If we detected a lower impedence during initial startup
+        * then we probably have the wrong polarity, flip it.  Don't
+        * do this for the lowest impedences to speed up detection of
+        * plain headphones.
+        */
+       if (wm5100->jack_detecting && (val & 0x3f8)) {
+               wm5100_set_detect_mode(codec, !wm5100->jack_mode);
+
+               return;
+       }
+
+       /* Don't distinguish between buttons, just report any low
+        * impedence as BTN_0.
+        */
+       if (val & 0x3fc) {
+               if (wm5100->jack_mic) {
+                       dev_dbg(codec->dev, "Mic button detected\n");
+                       snd_soc_jack_report(wm5100->jack, SND_JACK_BTN_0,
+                                           SND_JACK_BTN_0);
+               } else if (wm5100->jack_detecting) {
+                       dev_dbg(codec->dev, "Headphone detected\n");
+                       snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,
+                                           SND_JACK_HEADPHONE);
+
+                       /* Increase the detection rate a bit for
+                        * responsiveness.
+                        */
+                       snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
+                                           WM5100_ACCDET_RATE_MASK,
+                                           7 << WM5100_ACCDET_RATE_SHIFT);
+               }
+       }
+}
+
+int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+
+       if (jack) {
+               wm5100->jack = jack;
+               wm5100->jack_detecting = true;
+
+               wm5100_set_detect_mode(codec, 0);
+
+               /* Slowest detection rate, gives debounce for initial
+                * detection */
+               snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
+                                   WM5100_ACCDET_BIAS_STARTTIME_MASK |
+                                   WM5100_ACCDET_RATE_MASK,
+                                   (7 << WM5100_ACCDET_BIAS_STARTTIME_SHIFT) |
+                                   WM5100_ACCDET_RATE_MASK);
+
+               /* We need the charge pump to power MICBIAS */
+               snd_soc_dapm_force_enable_pin(&codec->dapm, "CP2");
+               snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK");
+               snd_soc_dapm_sync(&codec->dapm);
+
+               /* We start off just enabling microphone detection - even a
+                * plain headphone will trigger detection.
+                */
+               snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
+                                   WM5100_ACCDET_ENA, WM5100_ACCDET_ENA);
+
+               snd_soc_update_bits(codec, WM5100_INTERRUPT_STATUS_3_MASK,
+                                   WM5100_IM_ACCDET_EINT, 0);
+       } else {
+               snd_soc_update_bits(codec, WM5100_INTERRUPT_STATUS_3_MASK,
+                                   WM5100_IM_HPDET_EINT |
+                                   WM5100_IM_ACCDET_EINT,
+                                   WM5100_IM_HPDET_EINT |
+                                   WM5100_IM_ACCDET_EINT);
+               snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
+                                   WM5100_ACCDET_ENA, 0);
+               wm5100->jack = NULL;
+       }
+
+       return 0;
+}
+
+static irqreturn_t wm5100_irq(int irq, void *data)
+{
+       struct snd_soc_codec *codec = data;
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       irqreturn_t status = IRQ_NONE;
+       int irq_val;
+
+       irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3);
+       if (irq_val < 0) {
+               dev_err(codec->dev, "Failed to read IRQ status 3: %d\n",
+                       irq_val);
+               irq_val = 0;
+       }
+       irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3_MASK);
+
+       snd_soc_write(codec, WM5100_INTERRUPT_STATUS_3, irq_val);
+
+       if (irq_val)
+               status = IRQ_HANDLED;
+
+       wm5100_log_status3(codec, irq_val);
+
+       if (irq_val & WM5100_FLL1_LOCK_EINT) {
+               dev_dbg(codec->dev, "FLL1 locked\n");
+               complete(&wm5100->fll[0].lock);
+       }
+       if (irq_val & WM5100_FLL2_LOCK_EINT) {
+               dev_dbg(codec->dev, "FLL2 locked\n");
+               complete(&wm5100->fll[1].lock);
+       }
+
+       if (irq_val & WM5100_ACCDET_EINT)
+               wm5100_micd_irq(codec);
+
+       irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4);
+       if (irq_val < 0) {
+               dev_err(codec->dev, "Failed to read IRQ status 4: %d\n",
+                       irq_val);
+               irq_val = 0;
+       }
+       irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4_MASK);
+
+       if (irq_val)
+               status = IRQ_HANDLED;
+
+       snd_soc_write(codec, WM5100_INTERRUPT_STATUS_4, irq_val);
+
+       wm5100_log_status4(codec, irq_val);
+
+       return status;
+}
+
+static irqreturn_t wm5100_edge_irq(int irq, void *data)
+{
+       irqreturn_t ret = IRQ_NONE;
+       irqreturn_t val;
+
+       do {
+               val = wm5100_irq(irq, data);
+               if (val != IRQ_NONE)
+                       ret = val;
+       } while (val != IRQ_NONE);
+
+       return ret;
+}
+
+#ifdef CONFIG_GPIOLIB
+static inline struct wm5100_priv *gpio_to_wm5100(struct gpio_chip *chip)
+{
+       return container_of(chip, struct wm5100_priv, gpio_chip);
+}
+
+static void wm5100_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
+       struct snd_soc_codec *codec = wm5100->codec;
+
+       snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset,
+                           WM5100_GP1_LVL, !!value << WM5100_GP1_LVL_SHIFT);
+}
+
+static int wm5100_gpio_direction_out(struct gpio_chip *chip,
+                                    unsigned offset, int value)
+{
+       struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
+       struct snd_soc_codec *codec = wm5100->codec;
+       int val;
+
+       val = (1 << WM5100_GP1_FN_SHIFT) | (!!value << WM5100_GP1_LVL_SHIFT);
+
+       return snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset,
+                                  WM5100_GP1_FN_MASK | WM5100_GP1_DIR |
+                                  WM5100_GP1_LVL, val);
+}
+
+static int wm5100_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
+       struct snd_soc_codec *codec = wm5100->codec;
+       int ret;
+
+       ret = snd_soc_read(codec, WM5100_GPIO_CTRL_1 + offset);
+       if (ret < 0)
+               return ret;
+
+       return (ret & WM5100_GP1_LVL) != 0;
+}
+
+static int wm5100_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
+       struct snd_soc_codec *codec = wm5100->codec;
+
+       return snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset,
+                                  WM5100_GP1_FN_MASK | WM5100_GP1_DIR,
+                                  (1 << WM5100_GP1_FN_SHIFT) |
+                                  (1 << WM5100_GP1_DIR_SHIFT));
+}
+
+static struct gpio_chip wm5100_template_chip = {
+       .label                  = "wm5100",
+       .owner                  = THIS_MODULE,
+       .direction_output       = wm5100_gpio_direction_out,
+       .set                    = wm5100_gpio_set,
+       .direction_input        = wm5100_gpio_direction_in,
+       .get                    = wm5100_gpio_get,
+       .can_sleep              = 1,
+};
+
+static void wm5100_init_gpio(struct snd_soc_codec *codec)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+       wm5100->gpio_chip = wm5100_template_chip;
+       wm5100->gpio_chip.ngpio = 6;
+       wm5100->gpio_chip.dev = codec->dev;
+
+       if (wm5100->pdata.gpio_base)
+               wm5100->gpio_chip.base = wm5100->pdata.gpio_base;
+       else
+               wm5100->gpio_chip.base = -1;
+
+       ret = gpiochip_add(&wm5100->gpio_chip);
+       if (ret != 0)
+               dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
+}
+
+static void wm5100_free_gpio(struct snd_soc_codec *codec)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+       ret = gpiochip_remove(&wm5100->gpio_chip);
+       if (ret != 0)
+               dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
+}
+#else
+static void wm5100_init_gpio(struct snd_soc_codec *codec)
+{
+}
+
+static void wm5100_free_gpio(struct snd_soc_codec *codec)
+{
+}
+#endif
+
+static int wm5100_probe(struct snd_soc_codec *codec)
+{
+       struct i2c_client *i2c = to_i2c_client(codec->dev);
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       int ret, i, irq_flags;
+
+       wm5100->codec = codec;
+
+       ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm5100->core_supplies); i++)
+               wm5100->core_supplies[i].supply = wm5100_core_supply_names[i];
+
+       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm5100->core_supplies),
+                                wm5100->core_supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request core supplies: %d\n",
+                       ret);
+               return ret;
+       }
+
+       wm5100->cpvdd = regulator_get(&i2c->dev, "CPVDD");
+       if (IS_ERR(wm5100->cpvdd)) {
+               ret = PTR_ERR(wm5100->cpvdd);
+               dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret);
+               goto err_core;
+       }
+
+       wm5100->dbvdd2 = regulator_get(&i2c->dev, "DBVDD2");
+       if (IS_ERR(wm5100->dbvdd2)) {
+               ret = PTR_ERR(wm5100->dbvdd2);
+               dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret);
+               goto err_cpvdd;
+       }
+
+       wm5100->dbvdd3 = regulator_get(&i2c->dev, "DBVDD3");
+       if (IS_ERR(wm5100->dbvdd3)) {
+               ret = PTR_ERR(wm5100->dbvdd3);
+               dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret);
+               goto err_dbvdd2;
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
+                                   wm5100->core_supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to enable core supplies: %d\n",
+                       ret);
+               goto err_dbvdd3;
+       }
+
+       if (wm5100->pdata.ldo_ena) {
+               ret = gpio_request_one(wm5100->pdata.ldo_ena,
+                                      GPIOF_OUT_INIT_HIGH, "WM5100 LDOENA");
+               if (ret < 0) {
+                       dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
+                               wm5100->pdata.ldo_ena, ret);
+                       goto err_enable;
+               }
+               msleep(2);
+       }
+
+       if (wm5100->pdata.reset) {
+               ret = gpio_request_one(wm5100->pdata.reset,
+                                      GPIOF_OUT_INIT_HIGH, "WM5100 /RESET");
+               if (ret < 0) {
+                       dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
+                               wm5100->pdata.reset, ret);
+                       goto err_ldo;
+               }
+       }
+
+       ret = snd_soc_read(codec, WM5100_SOFTWARE_RESET);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to read ID register\n");
+               goto err_reset;
+       }
+       switch (ret) {
+       case 0x8997:
+       case 0x5100:
+               break;
+
+       default:
+               dev_err(codec->dev, "Device is not a WM5100, ID is %x\n", ret);
+               ret = -EINVAL;
+               goto err_reset;
+       }
+
+       ret = snd_soc_read(codec, WM5100_DEVICE_REVISION);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to read revision register\n");
+               goto err_reset;
+       }
+       wm5100->rev = ret & WM5100_DEVICE_REVISION_MASK;
+
+       dev_info(codec->dev, "revision %c\n", wm5100->rev + 'A');
+
+       ret = wm5100_reset(codec);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to issue reset\n");
+               goto err_reset;
+       }
+
+       codec->cache_only = true;
+
+       wm5100_init_gpio(codec);
+
+       for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++)
+               snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU,
+                                   WM5100_OUT_VU);
+
+       for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) {
+               snd_soc_update_bits(codec, WM5100_IN1L_CONTROL,
+                                   WM5100_IN1_MODE_MASK |
+                                   WM5100_IN1_DMIC_SUP_MASK,
+                                   (wm5100->pdata.in_mode[i] <<
+                                    WM5100_IN1_MODE_SHIFT) |
+                                   (wm5100->pdata.dmic_sup[i] <<
+                                    WM5100_IN1_DMIC_SUP_SHIFT));
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm5100->pdata.gpio_defaults); i++) {
+               if (!wm5100->pdata.gpio_defaults[i])
+                       continue;
+
+               snd_soc_write(codec, WM5100_GPIO_CTRL_1 + i,
+                             wm5100->pdata.gpio_defaults[i]);
+       }
+
+       /* Don't debounce interrupts to support use of SYSCLK only */
+       snd_soc_write(codec, WM5100_IRQ_DEBOUNCE_1, 0);
+       snd_soc_write(codec, WM5100_IRQ_DEBOUNCE_2, 0);
+
+       /* TODO: check if we're symmetric */
+
+       if (i2c->irq) {
+               if (wm5100->pdata.irq_flags)
+                       irq_flags = wm5100->pdata.irq_flags;
+               else
+                       irq_flags = IRQF_TRIGGER_LOW;
+
+               irq_flags |= IRQF_ONESHOT;
+
+               if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
+                       ret = request_threaded_irq(i2c->irq, NULL,
+                                                  wm5100_edge_irq,
+                                                  irq_flags, "wm5100", codec);
+               else
+                       ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq,
+                                                  irq_flags, "wm5100", codec);
+
+               if (ret != 0) {
+                       dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
+                               i2c->irq, ret);
+               } else {
+                       /* Enable default interrupts */
+                       snd_soc_update_bits(codec,
+                                           WM5100_INTERRUPT_STATUS_3_MASK,
+                                           WM5100_IM_SPK_SHUTDOWN_WARN_EINT |
+                                           WM5100_IM_SPK_SHUTDOWN_EINT |
+                                           WM5100_IM_ASRC2_LOCK_EINT |
+                                           WM5100_IM_ASRC1_LOCK_EINT |
+                                           WM5100_IM_FLL2_LOCK_EINT |
+                                           WM5100_IM_FLL1_LOCK_EINT |
+                                           WM5100_CLKGEN_ERR_EINT |
+                                           WM5100_CLKGEN_ERR_ASYNC_EINT, 0);
+
+                       snd_soc_update_bits(codec,
+                                           WM5100_INTERRUPT_STATUS_4_MASK,
+                                           WM5100_AIF3_ERR_EINT |
+                                           WM5100_AIF2_ERR_EINT |
+                                           WM5100_AIF1_ERR_EINT |
+                                           WM5100_CTRLIF_ERR_EINT |
+                                           WM5100_ISRC2_UNDERCLOCKED_EINT |
+                                           WM5100_ISRC1_UNDERCLOCKED_EINT |
+                                           WM5100_FX_UNDERCLOCKED_EINT |
+                                           WM5100_AIF3_UNDERCLOCKED_EINT |
+                                           WM5100_AIF2_UNDERCLOCKED_EINT |
+                                           WM5100_AIF1_UNDERCLOCKED_EINT |
+                                           WM5100_ASRC_UNDERCLOCKED_EINT |
+                                           WM5100_DAC_UNDERCLOCKED_EINT |
+                                           WM5100_ADC_UNDERCLOCKED_EINT |
+                                           WM5100_MIXER_UNDERCLOCKED_EINT, 0);
+               }
+       } else {
+               snd_soc_dapm_new_controls(&codec->dapm,
+                                         wm5100_dapm_widgets_noirq,
+                                         ARRAY_SIZE(wm5100_dapm_widgets_noirq));
+       }
+
+       if (wm5100->pdata.hp_pol) {
+               ret = gpio_request_one(wm5100->pdata.hp_pol,
+                                      GPIOF_OUT_INIT_HIGH, "WM5100 HP_POL");
+               if (ret < 0) {
+                       dev_err(&i2c->dev, "Failed to request HP_POL %d: %d\n",
+                               wm5100->pdata.hp_pol, ret);
+                       goto err_gpio;
+               }
+       }
+
+       /* We'll get woken up again when the system has something useful
+        * for us to do.
+        */
+       if (wm5100->pdata.ldo_ena)
+               gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+       regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
+                              wm5100->core_supplies);
+
+       return 0;
+
+err_gpio:
+       if (i2c->irq)
+               free_irq(i2c->irq, codec);
+       wm5100_free_gpio(codec);
+err_reset:
+       if (wm5100->pdata.reset) {
+               gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+               gpio_free(wm5100->pdata.reset);
+       }
+err_ldo:
+       if (wm5100->pdata.ldo_ena) {
+               gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+               gpio_free(wm5100->pdata.ldo_ena);
+       }
+err_enable:
+       regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
+                              wm5100->core_supplies);
+err_dbvdd3:
+       regulator_put(wm5100->dbvdd3);
+err_dbvdd2:
+       regulator_put(wm5100->dbvdd2);
+err_cpvdd:
+       regulator_put(wm5100->cpvdd);
+err_core:
+       regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
+                           wm5100->core_supplies);
+
+       return ret;
+}
+
+static int wm5100_remove(struct snd_soc_codec *codec)
+{
+       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       struct i2c_client *i2c = to_i2c_client(codec->dev);
+
+       wm5100_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       if (wm5100->pdata.hp_pol) {
+               gpio_free(wm5100->pdata.hp_pol);
+       }
+       if (i2c->irq)
+               free_irq(i2c->irq, codec);
+       wm5100_free_gpio(codec);
+       if (wm5100->pdata.reset) {
+               gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+               gpio_free(wm5100->pdata.reset);
+       }
+       if (wm5100->pdata.ldo_ena) {
+               gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+               gpio_free(wm5100->pdata.ldo_ena);
+       }
+       regulator_put(wm5100->dbvdd3);
+       regulator_put(wm5100->dbvdd2);
+       regulator_put(wm5100->cpvdd);
+       regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
+                           wm5100->core_supplies);
+       return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_wm5100 = {
+       .probe =        wm5100_probe,
+       .remove =       wm5100_remove,
+
+       .set_sysclk = wm5100_set_sysclk,
+       .set_pll = wm5100_set_fll,
+       .set_bias_level = wm5100_set_bias_level,
+       .idle_bias_off = 1,
+
+       .seq_notifier = wm5100_seq_notifier,
+       .controls = wm5100_snd_controls,
+       .num_controls = ARRAY_SIZE(wm5100_snd_controls),
+       .dapm_widgets = wm5100_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm5100_dapm_widgets),
+       .dapm_routes = wm5100_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm5100_dapm_routes),
+
+       .reg_cache_size = ARRAY_SIZE(wm5100_reg_defaults),
+       .reg_word_size = sizeof(u16),
+       .compress_type = SND_SOC_RBTREE_COMPRESSION,
+       .reg_cache_default = wm5100_reg_defaults,
+
+       .volatile_register = wm5100_volatile_register,
+       .readable_register = wm5100_readable_register,
+};
+
+static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
+{
+       struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev);
+       struct wm5100_priv *wm5100;
+       int ret, i;
+
+       wm5100 = kzalloc(sizeof(struct wm5100_priv), GFP_KERNEL);
+       if (wm5100 == NULL)
+               return -ENOMEM;
+
+       for (i = 0; i < ARRAY_SIZE(wm5100->fll); i++)
+               init_completion(&wm5100->fll[i].lock);
+
+       if (pdata)
+               wm5100->pdata = *pdata;
+
+       i2c_set_clientdata(i2c, wm5100);
+
+       ret = snd_soc_register_codec(&i2c->dev,
+                                    &soc_codec_dev_wm5100, wm5100_dai,
+                                    ARRAY_SIZE(wm5100_dai));
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to register WM5100: %d\n", ret);
+               kfree(wm5100);
+       }
+
+       return ret;
+}
+
+static __devexit int wm5100_i2c_remove(struct i2c_client *client)
+{
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
+       return 0;
+}
+
+static const struct i2c_device_id wm5100_i2c_id[] = {
+       { "wm5100", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm5100_i2c_id);
+
+static struct i2c_driver wm5100_i2c_driver = {
+       .driver = {
+               .name = "wm5100",
+               .owner = THIS_MODULE,
+       },
+       .probe =    wm5100_i2c_probe,
+       .remove =   __devexit_p(wm5100_i2c_remove),
+       .id_table = wm5100_i2c_id,
+};
+
+static int __init wm5100_modinit(void)
+{
+       return i2c_add_driver(&wm5100_i2c_driver);
+}
+module_init(wm5100_modinit);
+
+static void __exit wm5100_exit(void)
+{
+       i2c_del_driver(&wm5100_i2c_driver);
+}
+module_exit(wm5100_exit);
+
+MODULE_DESCRIPTION("ASoC WM5100 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm5100.h b/sound/soc/codecs/wm5100.h
new file mode 100644 (file)
index 0000000..9707596
--- /dev/null
@@ -0,0 +1,5155 @@
+/*
+ * wm5100.h  --  WM5100 ALSA SoC Audio driver
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef WM5100_ASOC_H
+#define WM5100_ASOC_H
+
+#include <sound/soc.h>
+
+int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
+
+#define WM5100_CLK_AIF1     1
+#define WM5100_CLK_AIF2     2
+#define WM5100_CLK_AIF3     3
+#define WM5100_CLK_SYSCLK   4
+#define WM5100_CLK_ASYNCCLK 5
+#define WM5100_CLK_32KHZ    6
+#define WM5100_CLK_OPCLK    7
+
+#define WM5100_CLKSRC_MCLK1    0
+#define WM5100_CLKSRC_MCLK2    1
+#define WM5100_CLKSRC_SYSCLK   2
+#define WM5100_CLKSRC_FLL1     4
+#define WM5100_CLKSRC_FLL2     5
+#define WM5100_CLKSRC_AIF1BCLK 8
+#define WM5100_CLKSRC_AIF2BCLK 9
+#define WM5100_CLKSRC_AIF3BCLK 10
+#define WM5100_CLKSRC_ASYNCCLK 0x100
+
+#define WM5100_FLL1 1
+#define WM5100_FLL2 2
+
+#define WM5100_FLL_SRC_MCLK1    0x0
+#define WM5100_FLL_SRC_MCLK2    0x1
+#define WM5100_FLL_SRC_FLL1     0x4
+#define WM5100_FLL_SRC_FLL2     0x5
+#define WM5100_FLL_SRC_AIF1BCLK 0x8
+#define WM5100_FLL_SRC_AIF2BCLK 0x9
+#define WM5100_FLL_SRC_AIF3BCLK 0xa
+
+/*
+ * Register values.
+ */
+#define WM5100_SOFTWARE_RESET                   0x00
+#define WM5100_DEVICE_REVISION                  0x01
+#define WM5100_CTRL_IF_1                        0x10
+#define WM5100_TONE_GENERATOR_1                 0x20
+#define WM5100_PWM_DRIVE_1                      0x30
+#define WM5100_PWM_DRIVE_2                      0x31
+#define WM5100_PWM_DRIVE_3                      0x32
+#define WM5100_CLOCKING_1                       0x100
+#define WM5100_CLOCKING_3                       0x101
+#define WM5100_CLOCKING_4                       0x102
+#define WM5100_CLOCKING_5                       0x103
+#define WM5100_CLOCKING_6                       0x104
+#define WM5100_CLOCKING_7                       0x107
+#define WM5100_CLOCKING_8                       0x108
+#define WM5100_ASRC_ENABLE                      0x120
+#define WM5100_ASRC_STATUS                      0x121
+#define WM5100_ASRC_RATE1                       0x122
+#define WM5100_ISRC_1_CTRL_1                    0x141
+#define WM5100_ISRC_1_CTRL_2                    0x142
+#define WM5100_ISRC_2_CTRL1                     0x143
+#define WM5100_ISRC_2_CTRL_2                    0x144
+#define WM5100_FLL1_CONTROL_1                   0x182
+#define WM5100_FLL1_CONTROL_2                   0x183
+#define WM5100_FLL1_CONTROL_3                   0x184
+#define WM5100_FLL1_CONTROL_5                   0x186
+#define WM5100_FLL1_CONTROL_6                   0x187
+#define WM5100_FLL1_EFS_1                       0x188
+#define WM5100_FLL2_CONTROL_1                   0x1A2
+#define WM5100_FLL2_CONTROL_2                   0x1A3
+#define WM5100_FLL2_CONTROL_3                   0x1A4
+#define WM5100_FLL2_CONTROL_5                   0x1A6
+#define WM5100_FLL2_CONTROL_6                   0x1A7
+#define WM5100_FLL2_EFS_1                       0x1A8
+#define WM5100_MIC_CHARGE_PUMP_1                0x200
+#define WM5100_MIC_CHARGE_PUMP_2                0x201
+#define WM5100_HP_CHARGE_PUMP_1                 0x202
+#define WM5100_LDO1_CONTROL                     0x211
+#define WM5100_MIC_BIAS_CTRL_1                  0x215
+#define WM5100_MIC_BIAS_CTRL_2                  0x216
+#define WM5100_MIC_BIAS_CTRL_3                  0x217
+#define WM5100_ACCESSORY_DETECT_MODE_1          0x280
+#define WM5100_HEADPHONE_DETECT_1               0x288
+#define WM5100_HEADPHONE_DETECT_2               0x289
+#define WM5100_MIC_DETECT_1                     0x290
+#define WM5100_MIC_DETECT_2                     0x291
+#define WM5100_MIC_DETECT_3                     0x292
+#define WM5100_MISC_CONTROL                     0x2BB
+#define WM5100_INPUT_ENABLES                    0x301
+#define WM5100_INPUT_ENABLES_STATUS             0x302
+#define WM5100_IN1L_CONTROL                     0x310
+#define WM5100_IN1R_CONTROL                     0x311
+#define WM5100_IN2L_CONTROL                     0x312
+#define WM5100_IN2R_CONTROL                     0x313
+#define WM5100_IN3L_CONTROL                     0x314
+#define WM5100_IN3R_CONTROL                     0x315
+#define WM5100_IN4L_CONTROL                     0x316
+#define WM5100_IN4R_CONTROL                     0x317
+#define WM5100_RXANC_SRC                        0x318
+#define WM5100_INPUT_VOLUME_RAMP                0x319
+#define WM5100_ADC_DIGITAL_VOLUME_1L            0x320
+#define WM5100_ADC_DIGITAL_VOLUME_1R            0x321
+#define WM5100_ADC_DIGITAL_VOLUME_2L            0x322
+#define WM5100_ADC_DIGITAL_VOLUME_2R            0x323
+#define WM5100_ADC_DIGITAL_VOLUME_3L            0x324
+#define WM5100_ADC_DIGITAL_VOLUME_3R            0x325
+#define WM5100_ADC_DIGITAL_VOLUME_4L            0x326
+#define WM5100_ADC_DIGITAL_VOLUME_4R            0x327
+#define WM5100_OUTPUT_ENABLES_2                 0x401
+#define WM5100_OUTPUT_STATUS_1                  0x402
+#define WM5100_OUTPUT_STATUS_2                  0x403
+#define WM5100_CHANNEL_ENABLES_1                0x408
+#define WM5100_OUT_VOLUME_1L                    0x410
+#define WM5100_OUT_VOLUME_1R                    0x411
+#define WM5100_DAC_VOLUME_LIMIT_1L              0x412
+#define WM5100_DAC_VOLUME_LIMIT_1R              0x413
+#define WM5100_OUT_VOLUME_2L                    0x414
+#define WM5100_OUT_VOLUME_2R                    0x415
+#define WM5100_DAC_VOLUME_LIMIT_2L              0x416
+#define WM5100_DAC_VOLUME_LIMIT_2R              0x417
+#define WM5100_OUT_VOLUME_3L                    0x418
+#define WM5100_OUT_VOLUME_3R                    0x419
+#define WM5100_DAC_VOLUME_LIMIT_3L              0x41A
+#define WM5100_DAC_VOLUME_LIMIT_3R              0x41B
+#define WM5100_OUT_VOLUME_4L                    0x41C
+#define WM5100_OUT_VOLUME_4R                    0x41D
+#define WM5100_DAC_VOLUME_LIMIT_5L              0x41E
+#define WM5100_DAC_VOLUME_LIMIT_5R              0x41F
+#define WM5100_DAC_VOLUME_LIMIT_6L              0x420
+#define WM5100_DAC_VOLUME_LIMIT_6R              0x421
+#define WM5100_DAC_AEC_CONTROL_1                0x440
+#define WM5100_OUTPUT_VOLUME_RAMP               0x441
+#define WM5100_DAC_DIGITAL_VOLUME_1L            0x480
+#define WM5100_DAC_DIGITAL_VOLUME_1R            0x481
+#define WM5100_DAC_DIGITAL_VOLUME_2L            0x482
+#define WM5100_DAC_DIGITAL_VOLUME_2R            0x483
+#define WM5100_DAC_DIGITAL_VOLUME_3L            0x484
+#define WM5100_DAC_DIGITAL_VOLUME_3R            0x485
+#define WM5100_DAC_DIGITAL_VOLUME_4L            0x486
+#define WM5100_DAC_DIGITAL_VOLUME_4R            0x487
+#define WM5100_DAC_DIGITAL_VOLUME_5L            0x488
+#define WM5100_DAC_DIGITAL_VOLUME_5R            0x489
+#define WM5100_DAC_DIGITAL_VOLUME_6L            0x48A
+#define WM5100_DAC_DIGITAL_VOLUME_6R            0x48B
+#define WM5100_PDM_SPK1_CTRL_1                  0x4C0
+#define WM5100_PDM_SPK1_CTRL_2                  0x4C1
+#define WM5100_PDM_SPK2_CTRL_1                  0x4C2
+#define WM5100_PDM_SPK2_CTRL_2                  0x4C3
+#define WM5100_AUDIO_IF_1_1                     0x500
+#define WM5100_AUDIO_IF_1_2                     0x501
+#define WM5100_AUDIO_IF_1_3                     0x502
+#define WM5100_AUDIO_IF_1_4                     0x503
+#define WM5100_AUDIO_IF_1_5                     0x504
+#define WM5100_AUDIO_IF_1_6                     0x505
+#define WM5100_AUDIO_IF_1_7                     0x506
+#define WM5100_AUDIO_IF_1_8                     0x507
+#define WM5100_AUDIO_IF_1_9                     0x508
+#define WM5100_AUDIO_IF_1_10                    0x509
+#define WM5100_AUDIO_IF_1_11                    0x50A
+#define WM5100_AUDIO_IF_1_12                    0x50B
+#define WM5100_AUDIO_IF_1_13                    0x50C
+#define WM5100_AUDIO_IF_1_14                    0x50D
+#define WM5100_AUDIO_IF_1_15                    0x50E
+#define WM5100_AUDIO_IF_1_16                    0x50F
+#define WM5100_AUDIO_IF_1_17                    0x510
+#define WM5100_AUDIO_IF_1_18                    0x511
+#define WM5100_AUDIO_IF_1_19                    0x512
+#define WM5100_AUDIO_IF_1_20                    0x513
+#define WM5100_AUDIO_IF_1_21                    0x514
+#define WM5100_AUDIO_IF_1_22                    0x515
+#define WM5100_AUDIO_IF_1_23                    0x516
+#define WM5100_AUDIO_IF_1_24                    0x517
+#define WM5100_AUDIO_IF_1_25                    0x518
+#define WM5100_AUDIO_IF_1_26                    0x519
+#define WM5100_AUDIO_IF_1_27                    0x51A
+#define WM5100_AUDIO_IF_2_1                     0x540
+#define WM5100_AUDIO_IF_2_2                     0x541
+#define WM5100_AUDIO_IF_2_3                     0x542
+#define WM5100_AUDIO_IF_2_4                     0x543
+#define WM5100_AUDIO_IF_2_5                     0x544
+#define WM5100_AUDIO_IF_2_6                     0x545
+#define WM5100_AUDIO_IF_2_7                     0x546
+#define WM5100_AUDIO_IF_2_8                     0x547
+#define WM5100_AUDIO_IF_2_9                     0x548
+#define WM5100_AUDIO_IF_2_10                    0x549
+#define WM5100_AUDIO_IF_2_11                    0x54A
+#define WM5100_AUDIO_IF_2_18                    0x551
+#define WM5100_AUDIO_IF_2_19                    0x552
+#define WM5100_AUDIO_IF_2_26                    0x559
+#define WM5100_AUDIO_IF_2_27                    0x55A
+#define WM5100_AUDIO_IF_3_1                     0x580
+#define WM5100_AUDIO_IF_3_2                     0x581
+#define WM5100_AUDIO_IF_3_3                     0x582
+#define WM5100_AUDIO_IF_3_4                     0x583
+#define WM5100_AUDIO_IF_3_5                     0x584
+#define WM5100_AUDIO_IF_3_6                     0x585
+#define WM5100_AUDIO_IF_3_7                     0x586
+#define WM5100_AUDIO_IF_3_8                     0x587
+#define WM5100_AUDIO_IF_3_9                     0x588
+#define WM5100_AUDIO_IF_3_10                    0x589
+#define WM5100_AUDIO_IF_3_11                    0x58A
+#define WM5100_AUDIO_IF_3_18                    0x591
+#define WM5100_AUDIO_IF_3_19                    0x592
+#define WM5100_AUDIO_IF_3_26                    0x599
+#define WM5100_AUDIO_IF_3_27                    0x59A
+#define WM5100_PWM1MIX_INPUT_1_SOURCE           0x640
+#define WM5100_PWM1MIX_INPUT_1_VOLUME           0x641
+#define WM5100_PWM1MIX_INPUT_2_SOURCE           0x642
+#define WM5100_PWM1MIX_INPUT_2_VOLUME           0x643
+#define WM5100_PWM1MIX_INPUT_3_SOURCE           0x644
+#define WM5100_PWM1MIX_INPUT_3_VOLUME           0x645
+#define WM5100_PWM1MIX_INPUT_4_SOURCE           0x646
+#define WM5100_PWM1MIX_INPUT_4_VOLUME           0x647
+#define WM5100_PWM2MIX_INPUT_1_SOURCE           0x648
+#define WM5100_PWM2MIX_INPUT_1_VOLUME           0x649
+#define WM5100_PWM2MIX_INPUT_2_SOURCE           0x64A
+#define WM5100_PWM2MIX_INPUT_2_VOLUME           0x64B
+#define WM5100_PWM2MIX_INPUT_3_SOURCE           0x64C
+#define WM5100_PWM2MIX_INPUT_3_VOLUME           0x64D
+#define WM5100_PWM2MIX_INPUT_4_SOURCE           0x64E
+#define WM5100_PWM2MIX_INPUT_4_VOLUME           0x64F
+#define WM5100_OUT1LMIX_INPUT_1_SOURCE          0x680
+#define WM5100_OUT1LMIX_INPUT_1_VOLUME          0x681
+#define WM5100_OUT1LMIX_INPUT_2_SOURCE          0x682
+#define WM5100_OUT1LMIX_INPUT_2_VOLUME          0x683
+#define WM5100_OUT1LMIX_INPUT_3_SOURCE          0x684
+#define WM5100_OUT1LMIX_INPUT_3_VOLUME          0x685
+#define WM5100_OUT1LMIX_INPUT_4_SOURCE          0x686
+#define WM5100_OUT1LMIX_INPUT_4_VOLUME          0x687
+#define WM5100_OUT1RMIX_INPUT_1_SOURCE          0x688
+#define WM5100_OUT1RMIX_INPUT_1_VOLUME          0x689
+#define WM5100_OUT1RMIX_INPUT_2_SOURCE          0x68A
+#define WM5100_OUT1RMIX_INPUT_2_VOLUME          0x68B
+#define WM5100_OUT1RMIX_INPUT_3_SOURCE          0x68C
+#define WM5100_OUT1RMIX_INPUT_3_VOLUME          0x68D
+#define WM5100_OUT1RMIX_INPUT_4_SOURCE          0x68E
+#define WM5100_OUT1RMIX_INPUT_4_VOLUME          0x68F
+#define WM5100_OUT2LMIX_INPUT_1_SOURCE          0x690
+#define WM5100_OUT2LMIX_INPUT_1_VOLUME          0x691
+#define WM5100_OUT2LMIX_INPUT_2_SOURCE          0x692
+#define WM5100_OUT2LMIX_INPUT_2_VOLUME          0x693
+#define WM5100_OUT2LMIX_INPUT_3_SOURCE          0x694
+#define WM5100_OUT2LMIX_INPUT_3_VOLUME          0x695
+#define WM5100_OUT2LMIX_INPUT_4_SOURCE          0x696
+#define WM5100_OUT2LMIX_INPUT_4_VOLUME          0x697
+#define WM5100_OUT2RMIX_INPUT_1_SOURCE          0x698
+#define WM5100_OUT2RMIX_INPUT_1_VOLUME          0x699
+#define WM5100_OUT2RMIX_INPUT_2_SOURCE          0x69A
+#define WM5100_OUT2RMIX_INPUT_2_VOLUME          0x69B
+#define WM5100_OUT2RMIX_INPUT_3_SOURCE          0x69C
+#define WM5100_OUT2RMIX_INPUT_3_VOLUME          0x69D
+#define WM5100_OUT2RMIX_INPUT_4_SOURCE          0x69E
+#define WM5100_OUT2RMIX_INPUT_4_VOLUME          0x69F
+#define WM5100_OUT3LMIX_INPUT_1_SOURCE          0x6A0
+#define WM5100_OUT3LMIX_INPUT_1_VOLUME          0x6A1
+#define WM5100_OUT3LMIX_INPUT_2_SOURCE          0x6A2
+#define WM5100_OUT3LMIX_INPUT_2_VOLUME          0x6A3
+#define WM5100_OUT3LMIX_INPUT_3_SOURCE          0x6A4
+#define WM5100_OUT3LMIX_INPUT_3_VOLUME          0x6A5
+#define WM5100_OUT3LMIX_INPUT_4_SOURCE          0x6A6
+#define WM5100_OUT3LMIX_INPUT_4_VOLUME          0x6A7
+#define WM5100_OUT3RMIX_INPUT_1_SOURCE          0x6A8
+#define WM5100_OUT3RMIX_INPUT_1_VOLUME          0x6A9
+#define WM5100_OUT3RMIX_INPUT_2_SOURCE          0x6AA
+#define WM5100_OUT3RMIX_INPUT_2_VOLUME          0x6AB
+#define WM5100_OUT3RMIX_INPUT_3_SOURCE          0x6AC
+#define WM5100_OUT3RMIX_INPUT_3_VOLUME          0x6AD
+#define WM5100_OUT3RMIX_INPUT_4_SOURCE          0x6AE
+#define WM5100_OUT3RMIX_INPUT_4_VOLUME          0x6AF
+#define WM5100_OUT4LMIX_INPUT_1_SOURCE          0x6B0
+#define WM5100_OUT4LMIX_INPUT_1_VOLUME          0x6B1
+#define WM5100_OUT4LMIX_INPUT_2_SOURCE          0x6B2
+#define WM5100_OUT4LMIX_INPUT_2_VOLUME          0x6B3
+#define WM5100_OUT4LMIX_INPUT_3_SOURCE          0x6B4
+#define WM5100_OUT4LMIX_INPUT_3_VOLUME          0x6B5
+#define WM5100_OUT4LMIX_INPUT_4_SOURCE          0x6B6
+#define WM5100_OUT4LMIX_INPUT_4_VOLUME          0x6B7
+#define WM5100_OUT4RMIX_INPUT_1_SOURCE          0x6B8
+#define WM5100_OUT4RMIX_INPUT_1_VOLUME          0x6B9
+#define WM5100_OUT4RMIX_INPUT_2_SOURCE          0x6BA
+#define WM5100_OUT4RMIX_INPUT_2_VOLUME          0x6BB
+#define WM5100_OUT4RMIX_INPUT_3_SOURCE          0x6BC
+#define WM5100_OUT4RMIX_INPUT_3_VOLUME          0x6BD
+#define WM5100_OUT4RMIX_INPUT_4_SOURCE          0x6BE
+#define WM5100_OUT4RMIX_INPUT_4_VOLUME          0x6BF
+#define WM5100_OUT5LMIX_INPUT_1_SOURCE          0x6C0
+#define WM5100_OUT5LMIX_INPUT_1_VOLUME          0x6C1
+#define WM5100_OUT5LMIX_INPUT_2_SOURCE          0x6C2
+#define WM5100_OUT5LMIX_INPUT_2_VOLUME          0x6C3
+#define WM5100_OUT5LMIX_INPUT_3_SOURCE          0x6C4
+#define WM5100_OUT5LMIX_INPUT_3_VOLUME          0x6C5
+#define WM5100_OUT5LMIX_INPUT_4_SOURCE          0x6C6
+#define WM5100_OUT5LMIX_INPUT_4_VOLUME          0x6C7
+#define WM5100_OUT5RMIX_INPUT_1_SOURCE          0x6C8
+#define WM5100_OUT5RMIX_INPUT_1_VOLUME          0x6C9
+#define WM5100_OUT5RMIX_INPUT_2_SOURCE          0x6CA
+#define WM5100_OUT5RMIX_INPUT_2_VOLUME          0x6CB
+#define WM5100_OUT5RMIX_INPUT_3_SOURCE          0x6CC
+#define WM5100_OUT5RMIX_INPUT_3_VOLUME          0x6CD
+#define WM5100_OUT5RMIX_INPUT_4_SOURCE          0x6CE
+#define WM5100_OUT5RMIX_INPUT_4_VOLUME          0x6CF
+#define WM5100_OUT6LMIX_INPUT_1_SOURCE          0x6D0
+#define WM5100_OUT6LMIX_INPUT_1_VOLUME          0x6D1
+#define WM5100_OUT6LMIX_INPUT_2_SOURCE          0x6D2
+#define WM5100_OUT6LMIX_INPUT_2_VOLUME          0x6D3
+#define WM5100_OUT6LMIX_INPUT_3_SOURCE          0x6D4
+#define WM5100_OUT6LMIX_INPUT_3_VOLUME          0x6D5
+#define WM5100_OUT6LMIX_INPUT_4_SOURCE          0x6D6
+#define WM5100_OUT6LMIX_INPUT_4_VOLUME          0x6D7
+#define WM5100_OUT6RMIX_INPUT_1_SOURCE          0x6D8
+#define WM5100_OUT6RMIX_INPUT_1_VOLUME          0x6D9
+#define WM5100_OUT6RMIX_INPUT_2_SOURCE          0x6DA
+#define WM5100_OUT6RMIX_INPUT_2_VOLUME          0x6DB
+#define WM5100_OUT6RMIX_INPUT_3_SOURCE          0x6DC
+#define WM5100_OUT6RMIX_INPUT_3_VOLUME          0x6DD
+#define WM5100_OUT6RMIX_INPUT_4_SOURCE          0x6DE
+#define WM5100_OUT6RMIX_INPUT_4_VOLUME          0x6DF
+#define WM5100_AIF1TX1MIX_INPUT_1_SOURCE        0x700
+#define WM5100_AIF1TX1MIX_INPUT_1_VOLUME        0x701
+#define WM5100_AIF1TX1MIX_INPUT_2_SOURCE        0x702
+#define WM5100_AIF1TX1MIX_INPUT_2_VOLUME        0x703
+#define WM5100_AIF1TX1MIX_INPUT_3_SOURCE        0x704
+#define WM5100_AIF1TX1MIX_INPUT_3_VOLUME        0x705
+#define WM5100_AIF1TX1MIX_INPUT_4_SOURCE        0x706
+#define WM5100_AIF1TX1MIX_INPUT_4_VOLUME        0x707
+#define WM5100_AIF1TX2MIX_INPUT_1_SOURCE        0x708
+#define WM5100_AIF1TX2MIX_INPUT_1_VOLUME        0x709
+#define WM5100_AIF1TX2MIX_INPUT_2_SOURCE        0x70A
+#define WM5100_AIF1TX2MIX_INPUT_2_VOLUME        0x70B
+#define WM5100_AIF1TX2MIX_INPUT_3_SOURCE        0x70C
+#define WM5100_AIF1TX2MIX_INPUT_3_VOLUME        0x70D
+#define WM5100_AIF1TX2MIX_INPUT_4_SOURCE        0x70E
+#define WM5100_AIF1TX2MIX_INPUT_4_VOLUME        0x70F
+#define WM5100_AIF1TX3MIX_INPUT_1_SOURCE        0x710
+#define WM5100_AIF1TX3MIX_INPUT_1_VOLUME        0x711
+#define WM5100_AIF1TX3MIX_INPUT_2_SOURCE        0x712
+#define WM5100_AIF1TX3MIX_INPUT_2_VOLUME        0x713
+#define WM5100_AIF1TX3MIX_INPUT_3_SOURCE        0x714
+#define WM5100_AIF1TX3MIX_INPUT_3_VOLUME        0x715
+#define WM5100_AIF1TX3MIX_INPUT_4_SOURCE        0x716
+#define WM5100_AIF1TX3MIX_INPUT_4_VOLUME        0x717
+#define WM5100_AIF1TX4MIX_INPUT_1_SOURCE        0x718
+#define WM5100_AIF1TX4MIX_INPUT_1_VOLUME        0x719
+#define WM5100_AIF1TX4MIX_INPUT_2_SOURCE        0x71A
+#define WM5100_AIF1TX4MIX_INPUT_2_VOLUME        0x71B
+#define WM5100_AIF1TX4MIX_INPUT_3_SOURCE        0x71C
+#define WM5100_AIF1TX4MIX_INPUT_3_VOLUME        0x71D
+#define WM5100_AIF1TX4MIX_INPUT_4_SOURCE        0x71E
+#define WM5100_AIF1TX4MIX_INPUT_4_VOLUME        0x71F
+#define WM5100_AIF1TX5MIX_INPUT_1_SOURCE        0x720
+#define WM5100_AIF1TX5MIX_INPUT_1_VOLUME        0x721
+#define WM5100_AIF1TX5MIX_INPUT_2_SOURCE        0x722
+#define WM5100_AIF1TX5MIX_INPUT_2_VOLUME        0x723
+#define WM5100_AIF1TX5MIX_INPUT_3_SOURCE        0x724
+#define WM5100_AIF1TX5MIX_INPUT_3_VOLUME        0x725
+#define WM5100_AIF1TX5MIX_INPUT_4_SOURCE        0x726
+#define WM5100_AIF1TX5MIX_INPUT_4_VOLUME        0x727
+#define WM5100_AIF1TX6MIX_INPUT_1_SOURCE        0x728
+#define WM5100_AIF1TX6MIX_INPUT_1_VOLUME        0x729
+#define WM5100_AIF1TX6MIX_INPUT_2_SOURCE        0x72A
+#define WM5100_AIF1TX6MIX_INPUT_2_VOLUME        0x72B
+#define WM5100_AIF1TX6MIX_INPUT_3_SOURCE        0x72C
+#define WM5100_AIF1TX6MIX_INPUT_3_VOLUME        0x72D
+#define WM5100_AIF1TX6MIX_INPUT_4_SOURCE        0x72E
+#define WM5100_AIF1TX6MIX_INPUT_4_VOLUME        0x72F
+#define WM5100_AIF1TX7MIX_INPUT_1_SOURCE        0x730
+#define WM5100_AIF1TX7MIX_INPUT_1_VOLUME        0x731
+#define WM5100_AIF1TX7MIX_INPUT_2_SOURCE        0x732
+#define WM5100_AIF1TX7MIX_INPUT_2_VOLUME        0x733
+#define WM5100_AIF1TX7MIX_INPUT_3_SOURCE        0x734
+#define WM5100_AIF1TX7MIX_INPUT_3_VOLUME        0x735
+#define WM5100_AIF1TX7MIX_INPUT_4_SOURCE        0x736
+#define WM5100_AIF1TX7MIX_INPUT_4_VOLUME        0x737
+#define WM5100_AIF1TX8MIX_INPUT_1_SOURCE        0x738
+#define WM5100_AIF1TX8MIX_INPUT_1_VOLUME        0x739
+#define WM5100_AIF1TX8MIX_INPUT_2_SOURCE        0x73A
+#define WM5100_AIF1TX8MIX_INPUT_2_VOLUME        0x73B
+#define WM5100_AIF1TX8MIX_INPUT_3_SOURCE        0x73C
+#define WM5100_AIF1TX8MIX_INPUT_3_VOLUME        0x73D
+#define WM5100_AIF1TX8MIX_INPUT_4_SOURCE        0x73E
+#define WM5100_AIF1TX8MIX_INPUT_4_VOLUME        0x73F
+#define WM5100_AIF2TX1MIX_INPUT_1_SOURCE        0x740
+#define WM5100_AIF2TX1MIX_INPUT_1_VOLUME        0x741
+#define WM5100_AIF2TX1MIX_INPUT_2_SOURCE        0x742
+#define WM5100_AIF2TX1MIX_INPUT_2_VOLUME        0x743
+#define WM5100_AIF2TX1MIX_INPUT_3_SOURCE        0x744
+#define WM5100_AIF2TX1MIX_INPUT_3_VOLUME        0x745
+#define WM5100_AIF2TX1MIX_INPUT_4_SOURCE        0x746
+#define WM5100_AIF2TX1MIX_INPUT_4_VOLUME        0x747
+#define WM5100_AIF2TX2MIX_INPUT_1_SOURCE        0x748
+#define WM5100_AIF2TX2MIX_INPUT_1_VOLUME        0x749
+#define WM5100_AIF2TX2MIX_INPUT_2_SOURCE        0x74A
+#define WM5100_AIF2TX2MIX_INPUT_2_VOLUME        0x74B
+#define WM5100_AIF2TX2MIX_INPUT_3_SOURCE        0x74C
+#define WM5100_AIF2TX2MIX_INPUT_3_VOLUME        0x74D
+#define WM5100_AIF2TX2MIX_INPUT_4_SOURCE        0x74E
+#define WM5100_AIF2TX2MIX_INPUT_4_VOLUME        0x74F
+#define WM5100_AIF3TX1MIX_INPUT_1_SOURCE        0x780
+#define WM5100_AIF3TX1MIX_INPUT_1_VOLUME        0x781
+#define WM5100_AIF3TX1MIX_INPUT_2_SOURCE        0x782
+#define WM5100_AIF3TX1MIX_INPUT_2_VOLUME        0x783
+#define WM5100_AIF3TX1MIX_INPUT_3_SOURCE        0x784
+#define WM5100_AIF3TX1MIX_INPUT_3_VOLUME        0x785
+#define WM5100_AIF3TX1MIX_INPUT_4_SOURCE        0x786
+#define WM5100_AIF3TX1MIX_INPUT_4_VOLUME        0x787
+#define WM5100_AIF3TX2MIX_INPUT_1_SOURCE        0x788
+#define WM5100_AIF3TX2MIX_INPUT_1_VOLUME        0x789
+#define WM5100_AIF3TX2MIX_INPUT_2_SOURCE        0x78A
+#define WM5100_AIF3TX2MIX_INPUT_2_VOLUME        0x78B
+#define WM5100_AIF3TX2MIX_INPUT_3_SOURCE        0x78C
+#define WM5100_AIF3TX2MIX_INPUT_3_VOLUME        0x78D
+#define WM5100_AIF3TX2MIX_INPUT_4_SOURCE        0x78E
+#define WM5100_AIF3TX2MIX_INPUT_4_VOLUME        0x78F
+#define WM5100_EQ1MIX_INPUT_1_SOURCE            0x880
+#define WM5100_EQ1MIX_INPUT_1_VOLUME            0x881
+#define WM5100_EQ1MIX_INPUT_2_SOURCE            0x882
+#define WM5100_EQ1MIX_INPUT_2_VOLUME            0x883
+#define WM5100_EQ1MIX_INPUT_3_SOURCE            0x884
+#define WM5100_EQ1MIX_INPUT_3_VOLUME            0x885
+#define WM5100_EQ1MIX_INPUT_4_SOURCE            0x886
+#define WM5100_EQ1MIX_INPUT_4_VOLUME            0x887
+#define WM5100_EQ2MIX_INPUT_1_SOURCE            0x888
+#define WM5100_EQ2MIX_INPUT_1_VOLUME            0x889
+#define WM5100_EQ2MIX_INPUT_2_SOURCE            0x88A
+#define WM5100_EQ2MIX_INPUT_2_VOLUME            0x88B
+#define WM5100_EQ2MIX_INPUT_3_SOURCE            0x88C
+#define WM5100_EQ2MIX_INPUT_3_VOLUME            0x88D
+#define WM5100_EQ2MIX_INPUT_4_SOURCE            0x88E
+#define WM5100_EQ2MIX_INPUT_4_VOLUME            0x88F
+#define WM5100_EQ3MIX_INPUT_1_SOURCE            0x890
+#define WM5100_EQ3MIX_INPUT_1_VOLUME            0x891
+#define WM5100_EQ3MIX_INPUT_2_SOURCE            0x892
+#define WM5100_EQ3MIX_INPUT_2_VOLUME            0x893
+#define WM5100_EQ3MIX_INPUT_3_SOURCE            0x894
+#define WM5100_EQ3MIX_INPUT_3_VOLUME            0x895
+#define WM5100_EQ3MIX_INPUT_4_SOURCE            0x896
+#define WM5100_EQ3MIX_INPUT_4_VOLUME            0x897
+#define WM5100_EQ4MIX_INPUT_1_SOURCE            0x898
+#define WM5100_EQ4MIX_INPUT_1_VOLUME            0x899
+#define WM5100_EQ4MIX_INPUT_2_SOURCE            0x89A
+#define WM5100_EQ4MIX_INPUT_2_VOLUME            0x89B
+#define WM5100_EQ4MIX_INPUT_3_SOURCE            0x89C
+#define WM5100_EQ4MIX_INPUT_3_VOLUME            0x89D
+#define WM5100_EQ4MIX_INPUT_4_SOURCE            0x89E
+#define WM5100_EQ4MIX_INPUT_4_VOLUME            0x89F
+#define WM5100_DRC1LMIX_INPUT_1_SOURCE          0x8C0
+#define WM5100_DRC1LMIX_INPUT_1_VOLUME          0x8C1
+#define WM5100_DRC1LMIX_INPUT_2_SOURCE          0x8C2
+#define WM5100_DRC1LMIX_INPUT_2_VOLUME          0x8C3
+#define WM5100_DRC1LMIX_INPUT_3_SOURCE          0x8C4
+#define WM5100_DRC1LMIX_INPUT_3_VOLUME          0x8C5
+#define WM5100_DRC1LMIX_INPUT_4_SOURCE          0x8C6
+#define WM5100_DRC1LMIX_INPUT_4_VOLUME          0x8C7
+#define WM5100_DRC1RMIX_INPUT_1_SOURCE          0x8C8
+#define WM5100_DRC1RMIX_INPUT_1_VOLUME          0x8C9
+#define WM5100_DRC1RMIX_INPUT_2_SOURCE          0x8CA
+#define WM5100_DRC1RMIX_INPUT_2_VOLUME          0x8CB
+#define WM5100_DRC1RMIX_INPUT_3_SOURCE          0x8CC
+#define WM5100_DRC1RMIX_INPUT_3_VOLUME          0x8CD
+#define WM5100_DRC1RMIX_INPUT_4_SOURCE          0x8CE
+#define WM5100_DRC1RMIX_INPUT_4_VOLUME          0x8CF
+#define WM5100_HPLP1MIX_INPUT_1_SOURCE          0x900
+#define WM5100_HPLP1MIX_INPUT_1_VOLUME          0x901
+#define WM5100_HPLP1MIX_INPUT_2_SOURCE          0x902
+#define WM5100_HPLP1MIX_INPUT_2_VOLUME          0x903
+#define WM5100_HPLP1MIX_INPUT_3_SOURCE          0x904
+#define WM5100_HPLP1MIX_INPUT_3_VOLUME          0x905
+#define WM5100_HPLP1MIX_INPUT_4_SOURCE          0x906
+#define WM5100_HPLP1MIX_INPUT_4_VOLUME          0x907
+#define WM5100_HPLP2MIX_INPUT_1_SOURCE          0x908
+#define WM5100_HPLP2MIX_INPUT_1_VOLUME          0x909
+#define WM5100_HPLP2MIX_INPUT_2_SOURCE          0x90A
+#define WM5100_HPLP2MIX_INPUT_2_VOLUME          0x90B
+#define WM5100_HPLP2MIX_INPUT_3_SOURCE          0x90C
+#define WM5100_HPLP2MIX_INPUT_3_VOLUME          0x90D
+#define WM5100_HPLP2MIX_INPUT_4_SOURCE          0x90E
+#define WM5100_HPLP2MIX_INPUT_4_VOLUME          0x90F
+#define WM5100_HPLP3MIX_INPUT_1_SOURCE          0x910
+#define WM5100_HPLP3MIX_INPUT_1_VOLUME          0x911
+#define WM5100_HPLP3MIX_INPUT_2_SOURCE          0x912
+#define WM5100_HPLP3MIX_INPUT_2_VOLUME          0x913
+#define WM5100_HPLP3MIX_INPUT_3_SOURCE          0x914
+#define WM5100_HPLP3MIX_INPUT_3_VOLUME          0x915
+#define WM5100_HPLP3MIX_INPUT_4_SOURCE          0x916
+#define WM5100_HPLP3MIX_INPUT_4_VOLUME          0x917
+#define WM5100_HPLP4MIX_INPUT_1_SOURCE          0x918
+#define WM5100_HPLP4MIX_INPUT_1_VOLUME          0x919
+#define WM5100_HPLP4MIX_INPUT_2_SOURCE          0x91A
+#define WM5100_HPLP4MIX_INPUT_2_VOLUME          0x91B
+#define WM5100_HPLP4MIX_INPUT_3_SOURCE          0x91C
+#define WM5100_HPLP4MIX_INPUT_3_VOLUME          0x91D
+#define WM5100_HPLP4MIX_INPUT_4_SOURCE          0x91E
+#define WM5100_HPLP4MIX_INPUT_4_VOLUME          0x91F
+#define WM5100_DSP1LMIX_INPUT_1_SOURCE          0x940
+#define WM5100_DSP1LMIX_INPUT_1_VOLUME          0x941
+#define WM5100_DSP1LMIX_INPUT_2_SOURCE          0x942
+#define WM5100_DSP1LMIX_INPUT_2_VOLUME          0x943
+#define WM5100_DSP1LMIX_INPUT_3_SOURCE          0x944
+#define WM5100_DSP1LMIX_INPUT_3_VOLUME          0x945
+#define WM5100_DSP1LMIX_INPUT_4_SOURCE          0x946
+#define WM5100_DSP1LMIX_INPUT_4_VOLUME          0x947
+#define WM5100_DSP1RMIX_INPUT_1_SOURCE          0x948
+#define WM5100_DSP1RMIX_INPUT_1_VOLUME          0x949
+#define WM5100_DSP1RMIX_INPUT_2_SOURCE          0x94A
+#define WM5100_DSP1RMIX_INPUT_2_VOLUME          0x94B
+#define WM5100_DSP1RMIX_INPUT_3_SOURCE          0x94C
+#define WM5100_DSP1RMIX_INPUT_3_VOLUME          0x94D
+#define WM5100_DSP1RMIX_INPUT_4_SOURCE          0x94E
+#define WM5100_DSP1RMIX_INPUT_4_VOLUME          0x94F
+#define WM5100_DSP1AUX1MIX_INPUT_1_SOURCE       0x950
+#define WM5100_DSP1AUX2MIX_INPUT_1_SOURCE       0x958
+#define WM5100_DSP1AUX3MIX_INPUT_1_SOURCE       0x960
+#define WM5100_DSP1AUX4MIX_INPUT_1_SOURCE       0x968
+#define WM5100_DSP1AUX5MIX_INPUT_1_SOURCE       0x970
+#define WM5100_DSP1AUX6MIX_INPUT_1_SOURCE       0x978
+#define WM5100_DSP2LMIX_INPUT_1_SOURCE          0x980
+#define WM5100_DSP2LMIX_INPUT_1_VOLUME          0x981
+#define WM5100_DSP2LMIX_INPUT_2_SOURCE          0x982
+#define WM5100_DSP2LMIX_INPUT_2_VOLUME          0x983
+#define WM5100_DSP2LMIX_INPUT_3_SOURCE          0x984
+#define WM5100_DSP2LMIX_INPUT_3_VOLUME          0x985
+#define WM5100_DSP2LMIX_INPUT_4_SOURCE          0x986
+#define WM5100_DSP2LMIX_INPUT_4_VOLUME          0x987
+#define WM5100_DSP2RMIX_INPUT_1_SOURCE          0x988
+#define WM5100_DSP2RMIX_INPUT_1_VOLUME          0x989
+#define WM5100_DSP2RMIX_INPUT_2_SOURCE          0x98A
+#define WM5100_DSP2RMIX_INPUT_2_VOLUME          0x98B
+#define WM5100_DSP2RMIX_INPUT_3_SOURCE          0x98C
+#define WM5100_DSP2RMIX_INPUT_3_VOLUME          0x98D
+#define WM5100_DSP2RMIX_INPUT_4_SOURCE          0x98E
+#define WM5100_DSP2RMIX_INPUT_4_VOLUME          0x98F
+#define WM5100_DSP2AUX1MIX_INPUT_1_SOURCE       0x990
+#define WM5100_DSP2AUX2MIX_INPUT_1_SOURCE       0x998
+#define WM5100_DSP2AUX3MIX_INPUT_1_SOURCE       0x9A0
+#define WM5100_DSP2AUX4MIX_INPUT_1_SOURCE       0x9A8
+#define WM5100_DSP2AUX5MIX_INPUT_1_SOURCE       0x9B0
+#define WM5100_DSP2AUX6MIX_INPUT_1_SOURCE       0x9B8
+#define WM5100_DSP3LMIX_INPUT_1_SOURCE          0x9C0
+#define WM5100_DSP3LMIX_INPUT_1_VOLUME          0x9C1
+#define WM5100_DSP3LMIX_INPUT_2_SOURCE          0x9C2
+#define WM5100_DSP3LMIX_INPUT_2_VOLUME          0x9C3
+#define WM5100_DSP3LMIX_INPUT_3_SOURCE          0x9C4
+#define WM5100_DSP3LMIX_INPUT_3_VOLUME          0x9C5
+#define WM5100_DSP3LMIX_INPUT_4_SOURCE          0x9C6
+#define WM5100_DSP3LMIX_INPUT_4_VOLUME          0x9C7
+#define WM5100_DSP3RMIX_INPUT_1_SOURCE          0x9C8
+#define WM5100_DSP3RMIX_INPUT_1_VOLUME          0x9C9
+#define WM5100_DSP3RMIX_INPUT_2_SOURCE          0x9CA
+#define WM5100_DSP3RMIX_INPUT_2_VOLUME          0x9CB
+#define WM5100_DSP3RMIX_INPUT_3_SOURCE          0x9CC
+#define WM5100_DSP3RMIX_INPUT_3_VOLUME          0x9CD
+#define WM5100_DSP3RMIX_INPUT_4_SOURCE          0x9CE
+#define WM5100_DSP3RMIX_INPUT_4_VOLUME          0x9CF
+#define WM5100_DSP3AUX1MIX_INPUT_1_SOURCE       0x9D0
+#define WM5100_DSP3AUX2MIX_INPUT_1_SOURCE       0x9D8
+#define WM5100_DSP3AUX3MIX_INPUT_1_SOURCE       0x9E0
+#define WM5100_DSP3AUX4MIX_INPUT_1_SOURCE       0x9E8
+#define WM5100_DSP3AUX5MIX_INPUT_1_SOURCE       0x9F0
+#define WM5100_DSP3AUX6MIX_INPUT_1_SOURCE       0x9F8
+#define WM5100_ASRC1LMIX_INPUT_1_SOURCE         0xA80
+#define WM5100_ASRC1RMIX_INPUT_1_SOURCE         0xA88
+#define WM5100_ASRC2LMIX_INPUT_1_SOURCE         0xA90
+#define WM5100_ASRC2RMIX_INPUT_1_SOURCE         0xA98
+#define WM5100_ISRC1DEC1MIX_INPUT_1_SOURCE      0xB00
+#define WM5100_ISRC1DEC2MIX_INPUT_1_SOURCE      0xB08
+#define WM5100_ISRC1DEC3MIX_INPUT_1_SOURCE      0xB10
+#define WM5100_ISRC1DEC4MIX_INPUT_1_SOURCE      0xB18
+#define WM5100_ISRC1INT1MIX_INPUT_1_SOURCE      0xB20
+#define WM5100_ISRC1INT2MIX_INPUT_1_SOURCE      0xB28
+#define WM5100_ISRC1INT3MIX_INPUT_1_SOURCE      0xB30
+#define WM5100_ISRC1INT4MIX_INPUT_1_SOURCE      0xB38
+#define WM5100_ISRC2DEC1MIX_INPUT_1_SOURCE      0xB40
+#define WM5100_ISRC2DEC2MIX_INPUT_1_SOURCE      0xB48
+#define WM5100_ISRC2DEC3MIX_INPUT_1_SOURCE      0xB50
+#define WM5100_ISRC2DEC4MIX_INPUT_1_SOURCE      0xB58
+#define WM5100_ISRC2INT1MIX_INPUT_1_SOURCE      0xB60
+#define WM5100_ISRC2INT2MIX_INPUT_1_SOURCE      0xB68
+#define WM5100_ISRC2INT3MIX_INPUT_1_SOURCE      0xB70
+#define WM5100_ISRC2INT4MIX_INPUT_1_SOURCE      0xB78
+#define WM5100_GPIO_CTRL_1                      0xC00
+#define WM5100_GPIO_CTRL_2                      0xC01
+#define WM5100_GPIO_CTRL_3                      0xC02
+#define WM5100_GPIO_CTRL_4                      0xC03
+#define WM5100_GPIO_CTRL_5                      0xC04
+#define WM5100_GPIO_CTRL_6                      0xC05
+#define WM5100_MISC_PAD_CTRL_1                  0xC23
+#define WM5100_MISC_PAD_CTRL_2                  0xC24
+#define WM5100_MISC_PAD_CTRL_3                  0xC25
+#define WM5100_MISC_PAD_CTRL_4                  0xC26
+#define WM5100_MISC_PAD_CTRL_5                  0xC27
+#define WM5100_MISC_GPIO_1                      0xC28
+#define WM5100_INTERRUPT_STATUS_1               0xD00
+#define WM5100_INTERRUPT_STATUS_2               0xD01
+#define WM5100_INTERRUPT_STATUS_3               0xD02
+#define WM5100_INTERRUPT_STATUS_4               0xD03
+#define WM5100_INTERRUPT_RAW_STATUS_2           0xD04
+#define WM5100_INTERRUPT_RAW_STATUS_3           0xD05
+#define WM5100_INTERRUPT_RAW_STATUS_4           0xD06
+#define WM5100_INTERRUPT_STATUS_1_MASK          0xD07
+#define WM5100_INTERRUPT_STATUS_2_MASK          0xD08
+#define WM5100_INTERRUPT_STATUS_3_MASK          0xD09
+#define WM5100_INTERRUPT_STATUS_4_MASK          0xD0A
+#define WM5100_INTERRUPT_CONTROL                0xD1F
+#define WM5100_IRQ_DEBOUNCE_1                   0xD20
+#define WM5100_IRQ_DEBOUNCE_2                   0xD21
+#define WM5100_FX_CTRL                          0xE00
+#define WM5100_EQ1_1                            0xE10
+#define WM5100_EQ1_2                            0xE11
+#define WM5100_EQ1_3                            0xE12
+#define WM5100_EQ1_4                            0xE13
+#define WM5100_EQ1_5                            0xE14
+#define WM5100_EQ1_6                            0xE15
+#define WM5100_EQ1_7                            0xE16
+#define WM5100_EQ1_8                            0xE17
+#define WM5100_EQ1_9                            0xE18
+#define WM5100_EQ1_10                           0xE19
+#define WM5100_EQ1_11                           0xE1A
+#define WM5100_EQ1_12                           0xE1B
+#define WM5100_EQ1_13                           0xE1C
+#define WM5100_EQ1_14                           0xE1D
+#define WM5100_EQ1_15                           0xE1E
+#define WM5100_EQ1_16                           0xE1F
+#define WM5100_EQ1_17                           0xE20
+#define WM5100_EQ1_18                           0xE21
+#define WM5100_EQ1_19                           0xE22
+#define WM5100_EQ1_20                           0xE23
+#define WM5100_EQ2_1                            0xE26
+#define WM5100_EQ2_2                            0xE27
+#define WM5100_EQ2_3                            0xE28
+#define WM5100_EQ2_4                            0xE29
+#define WM5100_EQ2_5                            0xE2A
+#define WM5100_EQ2_6                            0xE2B
+#define WM5100_EQ2_7                            0xE2C
+#define WM5100_EQ2_8                            0xE2D
+#define WM5100_EQ2_9                            0xE2E
+#define WM5100_EQ2_10                           0xE2F
+#define WM5100_EQ2_11                           0xE30
+#define WM5100_EQ2_12                           0xE31
+#define WM5100_EQ2_13                           0xE32
+#define WM5100_EQ2_14                           0xE33
+#define WM5100_EQ2_15                           0xE34
+#define WM5100_EQ2_16                           0xE35
+#define WM5100_EQ2_17                           0xE36
+#define WM5100_EQ2_18                           0xE37
+#define WM5100_EQ2_19                           0xE38
+#define WM5100_EQ2_20                           0xE39
+#define WM5100_EQ3_1                            0xE3C
+#define WM5100_EQ3_2                            0xE3D
+#define WM5100_EQ3_3                            0xE3E
+#define WM5100_EQ3_4                            0xE3F
+#define WM5100_EQ3_5                            0xE40
+#define WM5100_EQ3_6                            0xE41
+#define WM5100_EQ3_7                            0xE42
+#define WM5100_EQ3_8                            0xE43
+#define WM5100_EQ3_9                            0xE44
+#define WM5100_EQ3_10                           0xE45
+#define WM5100_EQ3_11                           0xE46
+#define WM5100_EQ3_12                           0xE47
+#define WM5100_EQ3_13                           0xE48
+#define WM5100_EQ3_14                           0xE49
+#define WM5100_EQ3_15                           0xE4A
+#define WM5100_EQ3_16                           0xE4B
+#define WM5100_EQ3_17                           0xE4C
+#define WM5100_EQ3_18                           0xE4D
+#define WM5100_EQ3_19                           0xE4E
+#define WM5100_EQ3_20                           0xE4F
+#define WM5100_EQ4_1                            0xE52
+#define WM5100_EQ4_2                            0xE53
+#define WM5100_EQ4_3                            0xE54
+#define WM5100_EQ4_4                            0xE55
+#define WM5100_EQ4_5                            0xE56
+#define WM5100_EQ4_6                            0xE57
+#define WM5100_EQ4_7                            0xE58
+#define WM5100_EQ4_8                            0xE59
+#define WM5100_EQ4_9                            0xE5A
+#define WM5100_EQ4_10                           0xE5B
+#define WM5100_EQ4_11                           0xE5C
+#define WM5100_EQ4_12                           0xE5D
+#define WM5100_EQ4_13                           0xE5E
+#define WM5100_EQ4_14                           0xE5F
+#define WM5100_EQ4_15                           0xE60
+#define WM5100_EQ4_16                           0xE61
+#define WM5100_EQ4_17                           0xE62
+#define WM5100_EQ4_18                           0xE63
+#define WM5100_EQ4_19                           0xE64
+#define WM5100_EQ4_20                           0xE65
+#define WM5100_DRC1_CTRL1                       0xE80
+#define WM5100_DRC1_CTRL2                       0xE81
+#define WM5100_DRC1_CTRL3                       0xE82
+#define WM5100_DRC1_CTRL4                       0xE83
+#define WM5100_DRC1_CTRL5                       0xE84
+#define WM5100_HPLPF1_1                         0xEC0
+#define WM5100_HPLPF1_2                         0xEC1
+#define WM5100_HPLPF2_1                         0xEC4
+#define WM5100_HPLPF2_2                         0xEC5
+#define WM5100_HPLPF3_1                         0xEC8
+#define WM5100_HPLPF3_2                         0xEC9
+#define WM5100_HPLPF4_1                         0xECC
+#define WM5100_HPLPF4_2                         0xECD
+#define WM5100_DSP1_DM_0                        0x4000
+#define WM5100_DSP1_DM_1                        0x4001
+#define WM5100_DSP1_DM_2                        0x4002
+#define WM5100_DSP1_DM_3                        0x4003
+#define WM5100_DSP1_DM_508                      0x41FC
+#define WM5100_DSP1_DM_509                      0x41FD
+#define WM5100_DSP1_DM_510                      0x41FE
+#define WM5100_DSP1_DM_511                      0x41FF
+#define WM5100_DSP1_PM_0                        0x4800
+#define WM5100_DSP1_PM_1                        0x4801
+#define WM5100_DSP1_PM_2                        0x4802
+#define WM5100_DSP1_PM_3                        0x4803
+#define WM5100_DSP1_PM_4                        0x4804
+#define WM5100_DSP1_PM_5                        0x4805
+#define WM5100_DSP1_PM_1530                     0x4DFA
+#define WM5100_DSP1_PM_1531                     0x4DFB
+#define WM5100_DSP1_PM_1532                     0x4DFC
+#define WM5100_DSP1_PM_1533                     0x4DFD
+#define WM5100_DSP1_PM_1534                     0x4DFE
+#define WM5100_DSP1_PM_1535                     0x4DFF
+#define WM5100_DSP1_ZM_0                        0x5000
+#define WM5100_DSP1_ZM_1                        0x5001
+#define WM5100_DSP1_ZM_2                        0x5002
+#define WM5100_DSP1_ZM_3                        0x5003
+#define WM5100_DSP1_ZM_2044                     0x57FC
+#define WM5100_DSP1_ZM_2045                     0x57FD
+#define WM5100_DSP1_ZM_2046                     0x57FE
+#define WM5100_DSP1_ZM_2047                     0x57FF
+#define WM5100_DSP2_DM_0                        0x6000
+#define WM5100_DSP2_DM_1                        0x6001
+#define WM5100_DSP2_DM_2                        0x6002
+#define WM5100_DSP2_DM_3                        0x6003
+#define WM5100_DSP2_DM_508                      0x61FC
+#define WM5100_DSP2_DM_509                      0x61FD
+#define WM5100_DSP2_DM_510                      0x61FE
+#define WM5100_DSP2_DM_511                      0x61FF
+#define WM5100_DSP2_PM_0                        0x6800
+#define WM5100_DSP2_PM_1                        0x6801
+#define WM5100_DSP2_PM_2                        0x6802
+#define WM5100_DSP2_PM_3                        0x6803
+#define WM5100_DSP2_PM_4                        0x6804
+#define WM5100_DSP2_PM_5                        0x6805
+#define WM5100_DSP2_PM_1530                     0x6DFA
+#define WM5100_DSP2_PM_1531                     0x6DFB
+#define WM5100_DSP2_PM_1532                     0x6DFC
+#define WM5100_DSP2_PM_1533                     0x6DFD
+#define WM5100_DSP2_PM_1534                     0x6DFE
+#define WM5100_DSP2_PM_1535                     0x6DFF
+#define WM5100_DSP2_ZM_0                        0x7000
+#define WM5100_DSP2_ZM_1                        0x7001
+#define WM5100_DSP2_ZM_2                        0x7002
+#define WM5100_DSP2_ZM_3                        0x7003
+#define WM5100_DSP2_ZM_2044                     0x77FC
+#define WM5100_DSP2_ZM_2045                     0x77FD
+#define WM5100_DSP2_ZM_2046                     0x77FE
+#define WM5100_DSP2_ZM_2047                     0x77FF
+#define WM5100_DSP3_DM_0                        0x8000
+#define WM5100_DSP3_DM_1                        0x8001
+#define WM5100_DSP3_DM_2                        0x8002
+#define WM5100_DSP3_DM_3                        0x8003
+#define WM5100_DSP3_DM_508                      0x81FC
+#define WM5100_DSP3_DM_509                      0x81FD
+#define WM5100_DSP3_DM_510                      0x81FE
+#define WM5100_DSP3_DM_511                      0x81FF
+#define WM5100_DSP3_PM_0                        0x8800
+#define WM5100_DSP3_PM_1                        0x8801
+#define WM5100_DSP3_PM_2                        0x8802
+#define WM5100_DSP3_PM_3                        0x8803
+#define WM5100_DSP3_PM_4                        0x8804
+#define WM5100_DSP3_PM_5                        0x8805
+#define WM5100_DSP3_PM_1530                     0x8DFA
+#define WM5100_DSP3_PM_1531                     0x8DFB
+#define WM5100_DSP3_PM_1532                     0x8DFC
+#define WM5100_DSP3_PM_1533                     0x8DFD
+#define WM5100_DSP3_PM_1534                     0x8DFE
+#define WM5100_DSP3_PM_1535                     0x8DFF
+#define WM5100_DSP3_ZM_0                        0x9000
+#define WM5100_DSP3_ZM_1                        0x9001
+#define WM5100_DSP3_ZM_2                        0x9002
+#define WM5100_DSP3_ZM_3                        0x9003
+#define WM5100_DSP3_ZM_2044                     0x97FC
+#define WM5100_DSP3_ZM_2045                     0x97FD
+#define WM5100_DSP3_ZM_2046                     0x97FE
+#define WM5100_DSP3_ZM_2047                     0x97FF
+
+#define WM5100_REGISTER_COUNT                   1435
+#define WM5100_MAX_REGISTER                     0x97FF
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - software reset
+ */
+#define WM5100_SW_RST_DEV_ID1_MASK              0xFFFF  /* SW_RST_DEV_ID1 - [15:0] */
+#define WM5100_SW_RST_DEV_ID1_SHIFT                  0  /* SW_RST_DEV_ID1 - [15:0] */
+#define WM5100_SW_RST_DEV_ID1_WIDTH                 16  /* SW_RST_DEV_ID1 - [15:0] */
+
+/*
+ * R1 (0x01) - Device Revision
+ */
+#define WM5100_DEVICE_REVISION_MASK             0x000F  /* DEVICE_REVISION - [3:0] */
+#define WM5100_DEVICE_REVISION_SHIFT                 0  /* DEVICE_REVISION - [3:0] */
+#define WM5100_DEVICE_REVISION_WIDTH                 4  /* DEVICE_REVISION - [3:0] */
+
+/*
+ * R16 (0x10) - Ctrl IF 1
+ */
+#define WM5100_AUTO_INC                         0x0001  /* AUTO_INC */
+#define WM5100_AUTO_INC_MASK                    0x0001  /* AUTO_INC */
+#define WM5100_AUTO_INC_SHIFT                        0  /* AUTO_INC */
+#define WM5100_AUTO_INC_WIDTH                        1  /* AUTO_INC */
+
+/*
+ * R32 (0x20) - Tone Generator 1
+ */
+#define WM5100_TONE_RATE_MASK                   0x3000  /* TONE_RATE - [13:12] */
+#define WM5100_TONE_RATE_SHIFT                      12  /* TONE_RATE - [13:12] */
+#define WM5100_TONE_RATE_WIDTH                       2  /* TONE_RATE - [13:12] */
+#define WM5100_TONE_OFFSET_MASK                 0x0300  /* TONE_OFFSET - [9:8] */
+#define WM5100_TONE_OFFSET_SHIFT                     8  /* TONE_OFFSET - [9:8] */
+#define WM5100_TONE_OFFSET_WIDTH                     2  /* TONE_OFFSET - [9:8] */
+#define WM5100_TONE2_ENA                        0x0002  /* TONE2_ENA */
+#define WM5100_TONE2_ENA_MASK                   0x0002  /* TONE2_ENA */
+#define WM5100_TONE2_ENA_SHIFT                       1  /* TONE2_ENA */
+#define WM5100_TONE2_ENA_WIDTH                       1  /* TONE2_ENA */
+#define WM5100_TONE1_ENA                        0x0001  /* TONE1_ENA */
+#define WM5100_TONE1_ENA_MASK                   0x0001  /* TONE1_ENA */
+#define WM5100_TONE1_ENA_SHIFT                       0  /* TONE1_ENA */
+#define WM5100_TONE1_ENA_WIDTH                       1  /* TONE1_ENA */
+
+/*
+ * R48 (0x30) - PWM Drive 1
+ */
+#define WM5100_PWM_RATE_MASK                    0x3000  /* PWM_RATE - [13:12] */
+#define WM5100_PWM_RATE_SHIFT                       12  /* PWM_RATE - [13:12] */
+#define WM5100_PWM_RATE_WIDTH                        2  /* PWM_RATE - [13:12] */
+#define WM5100_PWM_CLK_SEL_MASK                 0x0300  /* PWM_CLK_SEL - [9:8] */
+#define WM5100_PWM_CLK_SEL_SHIFT                     8  /* PWM_CLK_SEL - [9:8] */
+#define WM5100_PWM_CLK_SEL_WIDTH                     2  /* PWM_CLK_SEL - [9:8] */
+#define WM5100_PWM2_OVD                         0x0020  /* PWM2_OVD */
+#define WM5100_PWM2_OVD_MASK                    0x0020  /* PWM2_OVD */
+#define WM5100_PWM2_OVD_SHIFT                        5  /* PWM2_OVD */
+#define WM5100_PWM2_OVD_WIDTH                        1  /* PWM2_OVD */
+#define WM5100_PWM1_OVD                         0x0010  /* PWM1_OVD */
+#define WM5100_PWM1_OVD_MASK                    0x0010  /* PWM1_OVD */
+#define WM5100_PWM1_OVD_SHIFT                        4  /* PWM1_OVD */
+#define WM5100_PWM1_OVD_WIDTH                        1  /* PWM1_OVD */
+#define WM5100_PWM2_ENA                         0x0002  /* PWM2_ENA */
+#define WM5100_PWM2_ENA_MASK                    0x0002  /* PWM2_ENA */
+#define WM5100_PWM2_ENA_SHIFT                        1  /* PWM2_ENA */
+#define WM5100_PWM2_ENA_WIDTH                        1  /* PWM2_ENA */
+#define WM5100_PWM1_ENA                         0x0001  /* PWM1_ENA */
+#define WM5100_PWM1_ENA_MASK                    0x0001  /* PWM1_ENA */
+#define WM5100_PWM1_ENA_SHIFT                        0  /* PWM1_ENA */
+#define WM5100_PWM1_ENA_WIDTH                        1  /* PWM1_ENA */
+
+/*
+ * R49 (0x31) - PWM Drive 2
+ */
+#define WM5100_PWM1_LVL_MASK                    0x03FF  /* PWM1_LVL - [9:0] */
+#define WM5100_PWM1_LVL_SHIFT                        0  /* PWM1_LVL - [9:0] */
+#define WM5100_PWM1_LVL_WIDTH                       10  /* PWM1_LVL - [9:0] */
+
+/*
+ * R50 (0x32) - PWM Drive 3
+ */
+#define WM5100_PWM2_LVL_MASK                    0x03FF  /* PWM2_LVL - [9:0] */
+#define WM5100_PWM2_LVL_SHIFT                        0  /* PWM2_LVL - [9:0] */
+#define WM5100_PWM2_LVL_WIDTH                       10  /* PWM2_LVL - [9:0] */
+
+/*
+ * R256 (0x100) - Clocking 1
+ */
+#define WM5100_CLK_32K_SRC_MASK                 0x000F  /* CLK_32K_SRC - [3:0] */
+#define WM5100_CLK_32K_SRC_SHIFT                     0  /* CLK_32K_SRC - [3:0] */
+#define WM5100_CLK_32K_SRC_WIDTH                     4  /* CLK_32K_SRC - [3:0] */
+
+/*
+ * R257 (0x101) - Clocking 3
+ */
+#define WM5100_SYSCLK_FREQ_MASK                 0x0700  /* SYSCLK_FREQ - [10:8] */
+#define WM5100_SYSCLK_FREQ_SHIFT                     8  /* SYSCLK_FREQ - [10:8] */
+#define WM5100_SYSCLK_FREQ_WIDTH                     3  /* SYSCLK_FREQ - [10:8] */
+#define WM5100_SYSCLK_ENA                       0x0040  /* SYSCLK_ENA */
+#define WM5100_SYSCLK_ENA_MASK                  0x0040  /* SYSCLK_ENA */
+#define WM5100_SYSCLK_ENA_SHIFT                      6  /* SYSCLK_ENA */
+#define WM5100_SYSCLK_ENA_WIDTH                      1  /* SYSCLK_ENA */
+#define WM5100_SYSCLK_SRC_MASK                  0x000F  /* SYSCLK_SRC - [3:0] */
+#define WM5100_SYSCLK_SRC_SHIFT                      0  /* SYSCLK_SRC - [3:0] */
+#define WM5100_SYSCLK_SRC_WIDTH                      4  /* SYSCLK_SRC - [3:0] */
+
+/*
+ * R258 (0x102) - Clocking 4
+ */
+#define WM5100_SAMPLE_RATE_1_MASK               0x001F  /* SAMPLE_RATE_1 - [4:0] */
+#define WM5100_SAMPLE_RATE_1_SHIFT                   0  /* SAMPLE_RATE_1 - [4:0] */
+#define WM5100_SAMPLE_RATE_1_WIDTH                   5  /* SAMPLE_RATE_1 - [4:0] */
+
+/*
+ * R259 (0x103) - Clocking 5
+ */
+#define WM5100_SAMPLE_RATE_2_MASK               0x001F  /* SAMPLE_RATE_2 - [4:0] */
+#define WM5100_SAMPLE_RATE_2_SHIFT                   0  /* SAMPLE_RATE_2 - [4:0] */
+#define WM5100_SAMPLE_RATE_2_WIDTH                   5  /* SAMPLE_RATE_2 - [4:0] */
+
+/*
+ * R260 (0x104) - Clocking 6
+ */
+#define WM5100_SAMPLE_RATE_3_MASK               0x001F  /* SAMPLE_RATE_3 - [4:0] */
+#define WM5100_SAMPLE_RATE_3_SHIFT                   0  /* SAMPLE_RATE_3 - [4:0] */
+#define WM5100_SAMPLE_RATE_3_WIDTH                   5  /* SAMPLE_RATE_3 - [4:0] */
+
+/*
+ * R263 (0x107) - Clocking 7
+ */
+#define WM5100_ASYNC_CLK_FREQ_MASK              0x0700  /* ASYNC_CLK_FREQ - [10:8] */
+#define WM5100_ASYNC_CLK_FREQ_SHIFT                  8  /* ASYNC_CLK_FREQ - [10:8] */
+#define WM5100_ASYNC_CLK_FREQ_WIDTH                  3  /* ASYNC_CLK_FREQ - [10:8] */
+#define WM5100_ASYNC_CLK_ENA                    0x0040  /* ASYNC_CLK_ENA */
+#define WM5100_ASYNC_CLK_ENA_MASK               0x0040  /* ASYNC_CLK_ENA */
+#define WM5100_ASYNC_CLK_ENA_SHIFT                   6  /* ASYNC_CLK_ENA */
+#define WM5100_ASYNC_CLK_ENA_WIDTH                   1  /* ASYNC_CLK_ENA */
+#define WM5100_ASYNC_CLK_SRC_MASK               0x000F  /* ASYNC_CLK_SRC - [3:0] */
+#define WM5100_ASYNC_CLK_SRC_SHIFT                   0  /* ASYNC_CLK_SRC - [3:0] */
+#define WM5100_ASYNC_CLK_SRC_WIDTH                   4  /* ASYNC_CLK_SRC - [3:0] */
+
+/*
+ * R264 (0x108) - Clocking 8
+ */
+#define WM5100_ASYNC_SAMPLE_RATE_MASK           0x001F  /* ASYNC_SAMPLE_RATE - [4:0] */
+#define WM5100_ASYNC_SAMPLE_RATE_SHIFT               0  /* ASYNC_SAMPLE_RATE - [4:0] */
+#define WM5100_ASYNC_SAMPLE_RATE_WIDTH               5  /* ASYNC_SAMPLE_RATE - [4:0] */
+
+/*
+ * R288 (0x120) - ASRC_ENABLE
+ */
+#define WM5100_ASRC2L_ENA                       0x0008  /* ASRC2L_ENA */
+#define WM5100_ASRC2L_ENA_MASK                  0x0008  /* ASRC2L_ENA */
+#define WM5100_ASRC2L_ENA_SHIFT                      3  /* ASRC2L_ENA */
+#define WM5100_ASRC2L_ENA_WIDTH                      1  /* ASRC2L_ENA */
+#define WM5100_ASRC2R_ENA                       0x0004  /* ASRC2R_ENA */
+#define WM5100_ASRC2R_ENA_MASK                  0x0004  /* ASRC2R_ENA */
+#define WM5100_ASRC2R_ENA_SHIFT                      2  /* ASRC2R_ENA */
+#define WM5100_ASRC2R_ENA_WIDTH                      1  /* ASRC2R_ENA */
+#define WM5100_ASRC1L_ENA                       0x0002  /* ASRC1L_ENA */
+#define WM5100_ASRC1L_ENA_MASK                  0x0002  /* ASRC1L_ENA */
+#define WM5100_ASRC1L_ENA_SHIFT                      1  /* ASRC1L_ENA */
+#define WM5100_ASRC1L_ENA_WIDTH                      1  /* ASRC1L_ENA */
+#define WM5100_ASRC1R_ENA                       0x0001  /* ASRC1R_ENA */
+#define WM5100_ASRC1R_ENA_MASK                  0x0001  /* ASRC1R_ENA */
+#define WM5100_ASRC1R_ENA_SHIFT                      0  /* ASRC1R_ENA */
+#define WM5100_ASRC1R_ENA_WIDTH                      1  /* ASRC1R_ENA */
+
+/*
+ * R289 (0x121) - ASRC_STATUS
+ */
+#define WM5100_ASRC2L_ENA_STS                   0x0008  /* ASRC2L_ENA_STS */
+#define WM5100_ASRC2L_ENA_STS_MASK              0x0008  /* ASRC2L_ENA_STS */
+#define WM5100_ASRC2L_ENA_STS_SHIFT                  3  /* ASRC2L_ENA_STS */
+#define WM5100_ASRC2L_ENA_STS_WIDTH                  1  /* ASRC2L_ENA_STS */
+#define WM5100_ASRC2R_ENA_STS                   0x0004  /* ASRC2R_ENA_STS */
+#define WM5100_ASRC2R_ENA_STS_MASK              0x0004  /* ASRC2R_ENA_STS */
+#define WM5100_ASRC2R_ENA_STS_SHIFT                  2  /* ASRC2R_ENA_STS */
+#define WM5100_ASRC2R_ENA_STS_WIDTH                  1  /* ASRC2R_ENA_STS */
+#define WM5100_ASRC1L_ENA_STS                   0x0002  /* ASRC1L_ENA_STS */
+#define WM5100_ASRC1L_ENA_STS_MASK              0x0002  /* ASRC1L_ENA_STS */
+#define WM5100_ASRC1L_ENA_STS_SHIFT                  1  /* ASRC1L_ENA_STS */
+#define WM5100_ASRC1L_ENA_STS_WIDTH                  1  /* ASRC1L_ENA_STS */
+#define WM5100_ASRC1R_ENA_STS                   0x0001  /* ASRC1R_ENA_STS */
+#define WM5100_ASRC1R_ENA_STS_MASK              0x0001  /* ASRC1R_ENA_STS */
+#define WM5100_ASRC1R_ENA_STS_SHIFT                  0  /* ASRC1R_ENA_STS */
+#define WM5100_ASRC1R_ENA_STS_WIDTH                  1  /* ASRC1R_ENA_STS */
+
+/*
+ * R290 (0x122) - ASRC_RATE1
+ */
+#define WM5100_ASRC_RATE1_MASK                  0x0006  /* ASRC_RATE1 - [2:1] */
+#define WM5100_ASRC_RATE1_SHIFT                      1  /* ASRC_RATE1 - [2:1] */
+#define WM5100_ASRC_RATE1_WIDTH                      2  /* ASRC_RATE1 - [2:1] */
+
+/*
+ * R321 (0x141) - ISRC 1 CTRL 1
+ */
+#define WM5100_ISRC1_DFS_ENA                    0x2000  /* ISRC1_DFS_ENA */
+#define WM5100_ISRC1_DFS_ENA_MASK               0x2000  /* ISRC1_DFS_ENA */
+#define WM5100_ISRC1_DFS_ENA_SHIFT                  13  /* ISRC1_DFS_ENA */
+#define WM5100_ISRC1_DFS_ENA_WIDTH                   1  /* ISRC1_DFS_ENA */
+#define WM5100_ISRC1_CLK_SEL_MASK               0x0300  /* ISRC1_CLK_SEL - [9:8] */
+#define WM5100_ISRC1_CLK_SEL_SHIFT                   8  /* ISRC1_CLK_SEL - [9:8] */
+#define WM5100_ISRC1_CLK_SEL_WIDTH                   2  /* ISRC1_CLK_SEL - [9:8] */
+#define WM5100_ISRC1_FSH_MASK                   0x000C  /* ISRC1_FSH - [3:2] */
+#define WM5100_ISRC1_FSH_SHIFT                       2  /* ISRC1_FSH - [3:2] */
+#define WM5100_ISRC1_FSH_WIDTH                       2  /* ISRC1_FSH - [3:2] */
+#define WM5100_ISRC1_FSL_MASK                   0x0003  /* ISRC1_FSL - [1:0] */
+#define WM5100_ISRC1_FSL_SHIFT                       0  /* ISRC1_FSL - [1:0] */
+#define WM5100_ISRC1_FSL_WIDTH                       2  /* ISRC1_FSL - [1:0] */
+
+/*
+ * R322 (0x142) - ISRC 1 CTRL 2
+ */
+#define WM5100_ISRC1_INT1_ENA                   0x8000  /* ISRC1_INT1_ENA */
+#define WM5100_ISRC1_INT1_ENA_MASK              0x8000  /* ISRC1_INT1_ENA */
+#define WM5100_ISRC1_INT1_ENA_SHIFT                 15  /* ISRC1_INT1_ENA */
+#define WM5100_ISRC1_INT1_ENA_WIDTH                  1  /* ISRC1_INT1_ENA */
+#define WM5100_ISRC1_INT2_ENA                   0x4000  /* ISRC1_INT2_ENA */
+#define WM5100_ISRC1_INT2_ENA_MASK              0x4000  /* ISRC1_INT2_ENA */
+#define WM5100_ISRC1_INT2_ENA_SHIFT                 14  /* ISRC1_INT2_ENA */
+#define WM5100_ISRC1_INT2_ENA_WIDTH                  1  /* ISRC1_INT2_ENA */
+#define WM5100_ISRC1_INT3_ENA                   0x2000  /* ISRC1_INT3_ENA */
+#define WM5100_ISRC1_INT3_ENA_MASK              0x2000  /* ISRC1_INT3_ENA */
+#define WM5100_ISRC1_INT3_ENA_SHIFT                 13  /* ISRC1_INT3_ENA */
+#define WM5100_ISRC1_INT3_ENA_WIDTH                  1  /* ISRC1_INT3_ENA */
+#define WM5100_ISRC1_INT4_ENA                   0x1000  /* ISRC1_INT4_ENA */
+#define WM5100_ISRC1_INT4_ENA_MASK              0x1000  /* ISRC1_INT4_ENA */
+#define WM5100_ISRC1_INT4_ENA_SHIFT                 12  /* ISRC1_INT4_ENA */
+#define WM5100_ISRC1_INT4_ENA_WIDTH                  1  /* ISRC1_INT4_ENA */
+#define WM5100_ISRC1_DEC1_ENA                   0x0200  /* ISRC1_DEC1_ENA */
+#define WM5100_ISRC1_DEC1_ENA_MASK              0x0200  /* ISRC1_DEC1_ENA */
+#define WM5100_ISRC1_DEC1_ENA_SHIFT                  9  /* ISRC1_DEC1_ENA */
+#define WM5100_ISRC1_DEC1_ENA_WIDTH                  1  /* ISRC1_DEC1_ENA */
+#define WM5100_ISRC1_DEC2_ENA                   0x0100  /* ISRC1_DEC2_ENA */
+#define WM5100_ISRC1_DEC2_ENA_MASK              0x0100  /* ISRC1_DEC2_ENA */
+#define WM5100_ISRC1_DEC2_ENA_SHIFT                  8  /* ISRC1_DEC2_ENA */
+#define WM5100_ISRC1_DEC2_ENA_WIDTH                  1  /* ISRC1_DEC2_ENA */
+#define WM5100_ISRC1_DEC3_ENA                   0x0080  /* ISRC1_DEC3_ENA */
+#define WM5100_ISRC1_DEC3_ENA_MASK              0x0080  /* ISRC1_DEC3_ENA */
+#define WM5100_ISRC1_DEC3_ENA_SHIFT                  7  /* ISRC1_DEC3_ENA */
+#define WM5100_ISRC1_DEC3_ENA_WIDTH                  1  /* ISRC1_DEC3_ENA */
+#define WM5100_ISRC1_DEC4_ENA                   0x0040  /* ISRC1_DEC4_ENA */
+#define WM5100_ISRC1_DEC4_ENA_MASK              0x0040  /* ISRC1_DEC4_ENA */
+#define WM5100_ISRC1_DEC4_ENA_SHIFT                  6  /* ISRC1_DEC4_ENA */
+#define WM5100_ISRC1_DEC4_ENA_WIDTH                  1  /* ISRC1_DEC4_ENA */
+#define WM5100_ISRC1_NOTCH_ENA                  0x0001  /* ISRC1_NOTCH_ENA */
+#define WM5100_ISRC1_NOTCH_ENA_MASK             0x0001  /* ISRC1_NOTCH_ENA */
+#define WM5100_ISRC1_NOTCH_ENA_SHIFT                 0  /* ISRC1_NOTCH_ENA */
+#define WM5100_ISRC1_NOTCH_ENA_WIDTH                 1  /* ISRC1_NOTCH_ENA */
+
+/*
+ * R323 (0x143) - ISRC 2 CTRL1
+ */
+#define WM5100_ISRC2_DFS_ENA                    0x2000  /* ISRC2_DFS_ENA */
+#define WM5100_ISRC2_DFS_ENA_MASK               0x2000  /* ISRC2_DFS_ENA */
+#define WM5100_ISRC2_DFS_ENA_SHIFT                  13  /* ISRC2_DFS_ENA */
+#define WM5100_ISRC2_DFS_ENA_WIDTH                   1  /* ISRC2_DFS_ENA */
+#define WM5100_ISRC2_CLK_SEL_MASK               0x0300  /* ISRC2_CLK_SEL - [9:8] */
+#define WM5100_ISRC2_CLK_SEL_SHIFT                   8  /* ISRC2_CLK_SEL - [9:8] */
+#define WM5100_ISRC2_CLK_SEL_WIDTH                   2  /* ISRC2_CLK_SEL - [9:8] */
+#define WM5100_ISRC2_FSH_MASK                   0x000C  /* ISRC2_FSH - [3:2] */
+#define WM5100_ISRC2_FSH_SHIFT                       2  /* ISRC2_FSH - [3:2] */
+#define WM5100_ISRC2_FSH_WIDTH                       2  /* ISRC2_FSH - [3:2] */
+#define WM5100_ISRC2_FSL_MASK                   0x0003  /* ISRC2_FSL - [1:0] */
+#define WM5100_ISRC2_FSL_SHIFT                       0  /* ISRC2_FSL - [1:0] */
+#define WM5100_ISRC2_FSL_WIDTH                       2  /* ISRC2_FSL - [1:0] */
+
+/*
+ * R324 (0x144) - ISRC 2 CTRL 2
+ */
+#define WM5100_ISRC2_INT1_ENA                   0x8000  /* ISRC2_INT1_ENA */
+#define WM5100_ISRC2_INT1_ENA_MASK              0x8000  /* ISRC2_INT1_ENA */
+#define WM5100_ISRC2_INT1_ENA_SHIFT                 15  /* ISRC2_INT1_ENA */
+#define WM5100_ISRC2_INT1_ENA_WIDTH                  1  /* ISRC2_INT1_ENA */
+#define WM5100_ISRC2_INT2_ENA                   0x4000  /* ISRC2_INT2_ENA */
+#define WM5100_ISRC2_INT2_ENA_MASK              0x4000  /* ISRC2_INT2_ENA */
+#define WM5100_ISRC2_INT2_ENA_SHIFT                 14  /* ISRC2_INT2_ENA */
+#define WM5100_ISRC2_INT2_ENA_WIDTH                  1  /* ISRC2_INT2_ENA */
+#define WM5100_ISRC2_INT3_ENA                   0x2000  /* ISRC2_INT3_ENA */
+#define WM5100_ISRC2_INT3_ENA_MASK              0x2000  /* ISRC2_INT3_ENA */
+#define WM5100_ISRC2_INT3_ENA_SHIFT                 13  /* ISRC2_INT3_ENA */
+#define WM5100_ISRC2_INT3_ENA_WIDTH                  1  /* ISRC2_INT3_ENA */
+#define WM5100_ISRC2_INT4_ENA                   0x1000  /* ISRC2_INT4_ENA */
+#define WM5100_ISRC2_INT4_ENA_MASK              0x1000  /* ISRC2_INT4_ENA */
+#define WM5100_ISRC2_INT4_ENA_SHIFT                 12  /* ISRC2_INT4_ENA */
+#define WM5100_ISRC2_INT4_ENA_WIDTH                  1  /* ISRC2_INT4_ENA */
+#define WM5100_ISRC2_DEC1_ENA                   0x0200  /* ISRC2_DEC1_ENA */
+#define WM5100_ISRC2_DEC1_ENA_MASK              0x0200  /* ISRC2_DEC1_ENA */
+#define WM5100_ISRC2_DEC1_ENA_SHIFT                  9  /* ISRC2_DEC1_ENA */
+#define WM5100_ISRC2_DEC1_ENA_WIDTH                  1  /* ISRC2_DEC1_ENA */
+#define WM5100_ISRC2_DEC2_ENA                   0x0100  /* ISRC2_DEC2_ENA */
+#define WM5100_ISRC2_DEC2_ENA_MASK              0x0100  /* ISRC2_DEC2_ENA */
+#define WM5100_ISRC2_DEC2_ENA_SHIFT                  8  /* ISRC2_DEC2_ENA */
+#define WM5100_ISRC2_DEC2_ENA_WIDTH                  1  /* ISRC2_DEC2_ENA */
+#define WM5100_ISRC2_DEC3_ENA                   0x0080  /* ISRC2_DEC3_ENA */
+#define WM5100_ISRC2_DEC3_ENA_MASK              0x0080  /* ISRC2_DEC3_ENA */
+#define WM5100_ISRC2_DEC3_ENA_SHIFT                  7  /* ISRC2_DEC3_ENA */
+#define WM5100_ISRC2_DEC3_ENA_WIDTH                  1  /* ISRC2_DEC3_ENA */
+#define WM5100_ISRC2_DEC4_ENA                   0x0040  /* ISRC2_DEC4_ENA */
+#define WM5100_ISRC2_DEC4_ENA_MASK              0x0040  /* ISRC2_DEC4_ENA */
+#define WM5100_ISRC2_DEC4_ENA_SHIFT                  6  /* ISRC2_DEC4_ENA */
+#define WM5100_ISRC2_DEC4_ENA_WIDTH                  1  /* ISRC2_DEC4_ENA */
+#define WM5100_ISRC2_NOTCH_ENA                  0x0001  /* ISRC2_NOTCH_ENA */
+#define WM5100_ISRC2_NOTCH_ENA_MASK             0x0001  /* ISRC2_NOTCH_ENA */
+#define WM5100_ISRC2_NOTCH_ENA_SHIFT                 0  /* ISRC2_NOTCH_ENA */
+#define WM5100_ISRC2_NOTCH_ENA_WIDTH                 1  /* ISRC2_NOTCH_ENA */
+
+/*
+ * R386 (0x182) - FLL1 Control 1
+ */
+#define WM5100_FLL1_ENA                         0x0001  /* FLL1_ENA */
+#define WM5100_FLL1_ENA_MASK                    0x0001  /* FLL1_ENA */
+#define WM5100_FLL1_ENA_SHIFT                        0  /* FLL1_ENA */
+#define WM5100_FLL1_ENA_WIDTH                        1  /* FLL1_ENA */
+
+/*
+ * R387 (0x183) - FLL1 Control 2
+ */
+#define WM5100_FLL1_OUTDIV_MASK                 0x3F00  /* FLL1_OUTDIV - [13:8] */
+#define WM5100_FLL1_OUTDIV_SHIFT                     8  /* FLL1_OUTDIV - [13:8] */
+#define WM5100_FLL1_OUTDIV_WIDTH                     6  /* FLL1_OUTDIV - [13:8] */
+#define WM5100_FLL1_FRATIO_MASK                 0x0007  /* FLL1_FRATIO - [2:0] */
+#define WM5100_FLL1_FRATIO_SHIFT                     0  /* FLL1_FRATIO - [2:0] */
+#define WM5100_FLL1_FRATIO_WIDTH                     3  /* FLL1_FRATIO - [2:0] */
+
+/*
+ * R388 (0x184) - FLL1 Control 3
+ */
+#define WM5100_FLL1_THETA_MASK                  0xFFFF  /* FLL1_THETA - [15:0] */
+#define WM5100_FLL1_THETA_SHIFT                      0  /* FLL1_THETA - [15:0] */
+#define WM5100_FLL1_THETA_WIDTH                     16  /* FLL1_THETA - [15:0] */
+
+/*
+ * R390 (0x186) - FLL1 Control 5
+ */
+#define WM5100_FLL1_N_MASK                      0x03FF  /* FLL1_N - [9:0] */
+#define WM5100_FLL1_N_SHIFT                          0  /* FLL1_N - [9:0] */
+#define WM5100_FLL1_N_WIDTH                         10  /* FLL1_N - [9:0] */
+
+/*
+ * R391 (0x187) - FLL1 Control 6
+ */
+#define WM5100_FLL1_REFCLK_DIV_MASK             0x00C0  /* FLL1_REFCLK_DIV - [7:6] */
+#define WM5100_FLL1_REFCLK_DIV_SHIFT                 6  /* FLL1_REFCLK_DIV - [7:6] */
+#define WM5100_FLL1_REFCLK_DIV_WIDTH                 2  /* FLL1_REFCLK_DIV - [7:6] */
+#define WM5100_FLL1_REFCLK_SRC_MASK             0x000F  /* FLL1_REFCLK_SRC - [3:0] */
+#define WM5100_FLL1_REFCLK_SRC_SHIFT                 0  /* FLL1_REFCLK_SRC - [3:0] */
+#define WM5100_FLL1_REFCLK_SRC_WIDTH                 4  /* FLL1_REFCLK_SRC - [3:0] */
+
+/*
+ * R392 (0x188) - FLL1 EFS 1
+ */
+#define WM5100_FLL1_LAMBDA_MASK                 0xFFFF  /* FLL1_LAMBDA - [15:0] */
+#define WM5100_FLL1_LAMBDA_SHIFT                     0  /* FLL1_LAMBDA - [15:0] */
+#define WM5100_FLL1_LAMBDA_WIDTH                    16  /* FLL1_LAMBDA - [15:0] */
+
+/*
+ * R418 (0x1A2) - FLL2 Control 1
+ */
+#define WM5100_FLL2_ENA                         0x0001  /* FLL2_ENA */
+#define WM5100_FLL2_ENA_MASK                    0x0001  /* FLL2_ENA */
+#define WM5100_FLL2_ENA_SHIFT                        0  /* FLL2_ENA */
+#define WM5100_FLL2_ENA_WIDTH                        1  /* FLL2_ENA */
+
+/*
+ * R419 (0x1A3) - FLL2 Control 2
+ */
+#define WM5100_FLL2_OUTDIV_MASK                 0x3F00  /* FLL2_OUTDIV - [13:8] */
+#define WM5100_FLL2_OUTDIV_SHIFT                     8  /* FLL2_OUTDIV - [13:8] */
+#define WM5100_FLL2_OUTDIV_WIDTH                     6  /* FLL2_OUTDIV - [13:8] */
+#define WM5100_FLL2_FRATIO_MASK                 0x0007  /* FLL2_FRATIO - [2:0] */
+#define WM5100_FLL2_FRATIO_SHIFT                     0  /* FLL2_FRATIO - [2:0] */
+#define WM5100_FLL2_FRATIO_WIDTH                     3  /* FLL2_FRATIO - [2:0] */
+
+/*
+ * R420 (0x1A4) - FLL2 Control 3
+ */
+#define WM5100_FLL2_THETA_MASK                  0xFFFF  /* FLL2_THETA - [15:0] */
+#define WM5100_FLL2_THETA_SHIFT                      0  /* FLL2_THETA - [15:0] */
+#define WM5100_FLL2_THETA_WIDTH                     16  /* FLL2_THETA - [15:0] */
+
+/*
+ * R422 (0x1A6) - FLL2 Control 5
+ */
+#define WM5100_FLL2_N_MASK                      0x03FF  /* FLL2_N - [9:0] */
+#define WM5100_FLL2_N_SHIFT                          0  /* FLL2_N - [9:0] */
+#define WM5100_FLL2_N_WIDTH                         10  /* FLL2_N - [9:0] */
+
+/*
+ * R423 (0x1A7) - FLL2 Control 6
+ */
+#define WM5100_FLL2_REFCLK_DIV_MASK             0x00C0  /* FLL2_REFCLK_DIV - [7:6] */
+#define WM5100_FLL2_REFCLK_DIV_SHIFT                 6  /* FLL2_REFCLK_DIV - [7:6] */
+#define WM5100_FLL2_REFCLK_DIV_WIDTH                 2  /* FLL2_REFCLK_DIV - [7:6] */
+#define WM5100_FLL2_REFCLK_SRC_MASK             0x000F  /* FLL2_REFCLK_SRC - [3:0] */
+#define WM5100_FLL2_REFCLK_SRC_SHIFT                 0  /* FLL2_REFCLK_SRC - [3:0] */
+#define WM5100_FLL2_REFCLK_SRC_WIDTH                 4  /* FLL2_REFCLK_SRC - [3:0] */
+
+/*
+ * R424 (0x1A8) - FLL2 EFS 1
+ */
+#define WM5100_FLL2_LAMBDA_MASK                 0xFFFF  /* FLL2_LAMBDA - [15:0] */
+#define WM5100_FLL2_LAMBDA_SHIFT                     0  /* FLL2_LAMBDA - [15:0] */
+#define WM5100_FLL2_LAMBDA_WIDTH                    16  /* FLL2_LAMBDA - [15:0] */
+
+/*
+ * R512 (0x200) - Mic Charge Pump 1
+ */
+#define WM5100_CP2_BYPASS                       0x0020  /* CP2_BYPASS */
+#define WM5100_CP2_BYPASS_MASK                  0x0020  /* CP2_BYPASS */
+#define WM5100_CP2_BYPASS_SHIFT                      5  /* CP2_BYPASS */
+#define WM5100_CP2_BYPASS_WIDTH                      1  /* CP2_BYPASS */
+#define WM5100_CP2_ENA                          0x0001  /* CP2_ENA */
+#define WM5100_CP2_ENA_MASK                     0x0001  /* CP2_ENA */
+#define WM5100_CP2_ENA_SHIFT                         0  /* CP2_ENA */
+#define WM5100_CP2_ENA_WIDTH                         1  /* CP2_ENA */
+
+/*
+ * R513 (0x201) - Mic Charge Pump 2
+ */
+#define WM5100_LDO2_VSEL_MASK                   0xF800  /* LDO2_VSEL - [15:11] */
+#define WM5100_LDO2_VSEL_SHIFT                      11  /* LDO2_VSEL - [15:11] */
+#define WM5100_LDO2_VSEL_WIDTH                       5  /* LDO2_VSEL - [15:11] */
+
+/*
+ * R514 (0x202) - HP Charge Pump 1
+ */
+#define WM5100_CP1_ENA                          0x0001  /* CP1_ENA */
+#define WM5100_CP1_ENA_MASK                     0x0001  /* CP1_ENA */
+#define WM5100_CP1_ENA_SHIFT                         0  /* CP1_ENA */
+#define WM5100_CP1_ENA_WIDTH                         1  /* CP1_ENA */
+
+/*
+ * R529 (0x211) - LDO1 Control
+ */
+#define WM5100_LDO1_BYPASS                      0x0002  /* LDO1_BYPASS */
+#define WM5100_LDO1_BYPASS_MASK                 0x0002  /* LDO1_BYPASS */
+#define WM5100_LDO1_BYPASS_SHIFT                     1  /* LDO1_BYPASS */
+#define WM5100_LDO1_BYPASS_WIDTH                     1  /* LDO1_BYPASS */
+
+/*
+ * R533 (0x215) - Mic Bias Ctrl 1
+ */
+#define WM5100_MICB1_DISCH                      0x0040  /* MICB1_DISCH */
+#define WM5100_MICB1_DISCH_MASK                 0x0040  /* MICB1_DISCH */
+#define WM5100_MICB1_DISCH_SHIFT                     6  /* MICB1_DISCH */
+#define WM5100_MICB1_DISCH_WIDTH                     1  /* MICB1_DISCH */
+#define WM5100_MICB1_RATE                       0x0020  /* MICB1_RATE */
+#define WM5100_MICB1_RATE_MASK                  0x0020  /* MICB1_RATE */
+#define WM5100_MICB1_RATE_SHIFT                      5  /* MICB1_RATE */
+#define WM5100_MICB1_RATE_WIDTH                      1  /* MICB1_RATE */
+#define WM5100_MICB1_LVL_MASK                   0x001C  /* MICB1_LVL - [4:2] */
+#define WM5100_MICB1_LVL_SHIFT                       2  /* MICB1_LVL - [4:2] */
+#define WM5100_MICB1_LVL_WIDTH                       3  /* MICB1_LVL - [4:2] */
+#define WM5100_MICB1_BYPASS                     0x0002  /* MICB1_BYPASS */
+#define WM5100_MICB1_BYPASS_MASK                0x0002  /* MICB1_BYPASS */
+#define WM5100_MICB1_BYPASS_SHIFT                    1  /* MICB1_BYPASS */
+#define WM5100_MICB1_BYPASS_WIDTH                    1  /* MICB1_BYPASS */
+#define WM5100_MICB1_ENA                        0x0001  /* MICB1_ENA */
+#define WM5100_MICB1_ENA_MASK                   0x0001  /* MICB1_ENA */
+#define WM5100_MICB1_ENA_SHIFT                       0  /* MICB1_ENA */
+#define WM5100_MICB1_ENA_WIDTH                       1  /* MICB1_ENA */
+
+/*
+ * R534 (0x216) - Mic Bias Ctrl 2
+ */
+#define WM5100_MICB2_DISCH                      0x0040  /* MICB2_DISCH */
+#define WM5100_MICB2_DISCH_MASK                 0x0040  /* MICB2_DISCH */
+#define WM5100_MICB2_DISCH_SHIFT                     6  /* MICB2_DISCH */
+#define WM5100_MICB2_DISCH_WIDTH                     1  /* MICB2_DISCH */
+#define WM5100_MICB2_RATE                       0x0020  /* MICB2_RATE */
+#define WM5100_MICB2_RATE_MASK                  0x0020  /* MICB2_RATE */
+#define WM5100_MICB2_RATE_SHIFT                      5  /* MICB2_RATE */
+#define WM5100_MICB2_RATE_WIDTH                      1  /* MICB2_RATE */
+#define WM5100_MICB2_LVL_MASK                   0x001C  /* MICB2_LVL - [4:2] */
+#define WM5100_MICB2_LVL_SHIFT                       2  /* MICB2_LVL - [4:2] */
+#define WM5100_MICB2_LVL_WIDTH                       3  /* MICB2_LVL - [4:2] */
+#define WM5100_MICB2_BYPASS                     0x0002  /* MICB2_BYPASS */
+#define WM5100_MICB2_BYPASS_MASK                0x0002  /* MICB2_BYPASS */
+#define WM5100_MICB2_BYPASS_SHIFT                    1  /* MICB2_BYPASS */
+#define WM5100_MICB2_BYPASS_WIDTH                    1  /* MICB2_BYPASS */
+#define WM5100_MICB2_ENA                        0x0001  /* MICB2_ENA */
+#define WM5100_MICB2_ENA_MASK                   0x0001  /* MICB2_ENA */
+#define WM5100_MICB2_ENA_SHIFT                       0  /* MICB2_ENA */
+#define WM5100_MICB2_ENA_WIDTH                       1  /* MICB2_ENA */
+
+/*
+ * R535 (0x217) - Mic Bias Ctrl 3
+ */
+#define WM5100_MICB3_DISCH                      0x0040  /* MICB3_DISCH */
+#define WM5100_MICB3_DISCH_MASK                 0x0040  /* MICB3_DISCH */
+#define WM5100_MICB3_DISCH_SHIFT                     6  /* MICB3_DISCH */
+#define WM5100_MICB3_DISCH_WIDTH                     1  /* MICB3_DISCH */
+#define WM5100_MICB3_RATE                       0x0020  /* MICB3_RATE */
+#define WM5100_MICB3_RATE_MASK                  0x0020  /* MICB3_RATE */
+#define WM5100_MICB3_RATE_SHIFT                      5  /* MICB3_RATE */
+#define WM5100_MICB3_RATE_WIDTH                      1  /* MICB3_RATE */
+#define WM5100_MICB3_LVL_MASK                   0x001C  /* MICB3_LVL - [4:2] */
+#define WM5100_MICB3_LVL_SHIFT                       2  /* MICB3_LVL - [4:2] */
+#define WM5100_MICB3_LVL_WIDTH                       3  /* MICB3_LVL - [4:2] */
+#define WM5100_MICB3_BYPASS                     0x0002  /* MICB3_BYPASS */
+#define WM5100_MICB3_BYPASS_MASK                0x0002  /* MICB3_BYPASS */
+#define WM5100_MICB3_BYPASS_SHIFT                    1  /* MICB3_BYPASS */
+#define WM5100_MICB3_BYPASS_WIDTH                    1  /* MICB3_BYPASS */
+#define WM5100_MICB3_ENA                        0x0001  /* MICB3_ENA */
+#define WM5100_MICB3_ENA_MASK                   0x0001  /* MICB3_ENA */
+#define WM5100_MICB3_ENA_SHIFT                       0  /* MICB3_ENA */
+#define WM5100_MICB3_ENA_WIDTH                       1  /* MICB3_ENA */
+
+/*
+ * R640 (0x280) - Accessory Detect Mode 1
+ */
+#define WM5100_ACCDET_BIAS_SRC_MASK             0xC000  /* ACCDET_BIAS_SRC - [15:14] */
+#define WM5100_ACCDET_BIAS_SRC_SHIFT                14  /* ACCDET_BIAS_SRC - [15:14] */
+#define WM5100_ACCDET_BIAS_SRC_WIDTH                 2  /* ACCDET_BIAS_SRC - [15:14] */
+#define WM5100_ACCDET_SRC                       0x2000  /* ACCDET_SRC */
+#define WM5100_ACCDET_SRC_MASK                  0x2000  /* ACCDET_SRC */
+#define WM5100_ACCDET_SRC_SHIFT                     13  /* ACCDET_SRC */
+#define WM5100_ACCDET_SRC_WIDTH                      1  /* ACCDET_SRC */
+#define WM5100_ACCDET_MODE_MASK                 0x0003  /* ACCDET_MODE - [1:0] */
+#define WM5100_ACCDET_MODE_SHIFT                     0  /* ACCDET_MODE - [1:0] */
+#define WM5100_ACCDET_MODE_WIDTH                     2  /* ACCDET_MODE - [1:0] */
+
+/*
+ * R648 (0x288) - Headphone Detect 1
+ */
+#define WM5100_HP_HOLDTIME_MASK                 0x00E0  /* HP_HOLDTIME - [7:5] */
+#define WM5100_HP_HOLDTIME_SHIFT                     5  /* HP_HOLDTIME - [7:5] */
+#define WM5100_HP_HOLDTIME_WIDTH                     3  /* HP_HOLDTIME - [7:5] */
+#define WM5100_HP_CLK_DIV_MASK                  0x0018  /* HP_CLK_DIV - [4:3] */
+#define WM5100_HP_CLK_DIV_SHIFT                      3  /* HP_CLK_DIV - [4:3] */
+#define WM5100_HP_CLK_DIV_WIDTH                      2  /* HP_CLK_DIV - [4:3] */
+#define WM5100_HP_STEP_SIZE                     0x0002  /* HP_STEP_SIZE */
+#define WM5100_HP_STEP_SIZE_MASK                0x0002  /* HP_STEP_SIZE */
+#define WM5100_HP_STEP_SIZE_SHIFT                    1  /* HP_STEP_SIZE */
+#define WM5100_HP_STEP_SIZE_WIDTH                    1  /* HP_STEP_SIZE */
+#define WM5100_HP_POLL                          0x0001  /* HP_POLL */
+#define WM5100_HP_POLL_MASK                     0x0001  /* HP_POLL */
+#define WM5100_HP_POLL_SHIFT                         0  /* HP_POLL */
+#define WM5100_HP_POLL_WIDTH                         1  /* HP_POLL */
+
+/*
+ * R649 (0x289) - Headphone Detect 2
+ */
+#define WM5100_HP_DONE                          0x0080  /* HP_DONE */
+#define WM5100_HP_DONE_MASK                     0x0080  /* HP_DONE */
+#define WM5100_HP_DONE_SHIFT                         7  /* HP_DONE */
+#define WM5100_HP_DONE_WIDTH                         1  /* HP_DONE */
+#define WM5100_HP_LVL_MASK                      0x007F  /* HP_LVL - [6:0] */
+#define WM5100_HP_LVL_SHIFT                          0  /* HP_LVL - [6:0] */
+#define WM5100_HP_LVL_WIDTH                          7  /* HP_LVL - [6:0] */
+
+/*
+ * R656 (0x290) - Mic Detect 1
+ */
+#define WM5100_ACCDET_BIAS_STARTTIME_MASK       0xF000  /* ACCDET_BIAS_STARTTIME - [15:12] */
+#define WM5100_ACCDET_BIAS_STARTTIME_SHIFT          12  /* ACCDET_BIAS_STARTTIME - [15:12] */
+#define WM5100_ACCDET_BIAS_STARTTIME_WIDTH           4  /* ACCDET_BIAS_STARTTIME - [15:12] */
+#define WM5100_ACCDET_RATE_MASK                 0x0F00  /* ACCDET_RATE - [11:8] */
+#define WM5100_ACCDET_RATE_SHIFT                     8  /* ACCDET_RATE - [11:8] */
+#define WM5100_ACCDET_RATE_WIDTH                     4  /* ACCDET_RATE - [11:8] */
+#define WM5100_ACCDET_DBTIME                    0x0002  /* ACCDET_DBTIME */
+#define WM5100_ACCDET_DBTIME_MASK               0x0002  /* ACCDET_DBTIME */
+#define WM5100_ACCDET_DBTIME_SHIFT                   1  /* ACCDET_DBTIME */
+#define WM5100_ACCDET_DBTIME_WIDTH                   1  /* ACCDET_DBTIME */
+#define WM5100_ACCDET_ENA                       0x0001  /* ACCDET_ENA */
+#define WM5100_ACCDET_ENA_MASK                  0x0001  /* ACCDET_ENA */
+#define WM5100_ACCDET_ENA_SHIFT                      0  /* ACCDET_ENA */
+#define WM5100_ACCDET_ENA_WIDTH                      1  /* ACCDET_ENA */
+
+/*
+ * R657 (0x291) - Mic Detect 2
+ */
+#define WM5100_ACCDET_LVL_SEL_MASK              0x00FF  /* ACCDET_LVL_SEL - [7:0] */
+#define WM5100_ACCDET_LVL_SEL_SHIFT                  0  /* ACCDET_LVL_SEL - [7:0] */
+#define WM5100_ACCDET_LVL_SEL_WIDTH                  8  /* ACCDET_LVL_SEL - [7:0] */
+
+/*
+ * R658 (0x292) - Mic Detect 3
+ */
+#define WM5100_ACCDET_LVL_MASK                  0x07FC  /* ACCDET_LVL - [10:2] */
+#define WM5100_ACCDET_LVL_SHIFT                      2  /* ACCDET_LVL - [10:2] */
+#define WM5100_ACCDET_LVL_WIDTH                      9  /* ACCDET_LVL - [10:2] */
+#define WM5100_ACCDET_VALID                     0x0002  /* ACCDET_VALID */
+#define WM5100_ACCDET_VALID_MASK                0x0002  /* ACCDET_VALID */
+#define WM5100_ACCDET_VALID_SHIFT                    1  /* ACCDET_VALID */
+#define WM5100_ACCDET_VALID_WIDTH                    1  /* ACCDET_VALID */
+#define WM5100_ACCDET_STS                       0x0001  /* ACCDET_STS */
+#define WM5100_ACCDET_STS_MASK                  0x0001  /* ACCDET_STS */
+#define WM5100_ACCDET_STS_SHIFT                      0  /* ACCDET_STS */
+#define WM5100_ACCDET_STS_WIDTH                      1  /* ACCDET_STS */
+
+/*
+ * R699 (0x2BB) - Misc Control
+ */
+#define WM5100_HPCOM_SRC                         0x200  /* HPCOM_SRC */
+#define WM5100_HPCOM_SRC_SHIFT                       9  /* HPCOM_SRC */
+
+/*
+ * R769 (0x301) - Input Enables
+ */
+#define WM5100_IN4L_ENA                         0x0080  /* IN4L_ENA */
+#define WM5100_IN4L_ENA_MASK                    0x0080  /* IN4L_ENA */
+#define WM5100_IN4L_ENA_SHIFT                        7  /* IN4L_ENA */
+#define WM5100_IN4L_ENA_WIDTH                        1  /* IN4L_ENA */
+#define WM5100_IN4R_ENA                         0x0040  /* IN4R_ENA */
+#define WM5100_IN4R_ENA_MASK                    0x0040  /* IN4R_ENA */
+#define WM5100_IN4R_ENA_SHIFT                        6  /* IN4R_ENA */
+#define WM5100_IN4R_ENA_WIDTH                        1  /* IN4R_ENA */
+#define WM5100_IN3L_ENA                         0x0020  /* IN3L_ENA */
+#define WM5100_IN3L_ENA_MASK                    0x0020  /* IN3L_ENA */
+#define WM5100_IN3L_ENA_SHIFT                        5  /* IN3L_ENA */
+#define WM5100_IN3L_ENA_WIDTH                        1  /* IN3L_ENA */
+#define WM5100_IN3R_ENA                         0x0010  /* IN3R_ENA */
+#define WM5100_IN3R_ENA_MASK                    0x0010  /* IN3R_ENA */
+#define WM5100_IN3R_ENA_SHIFT                        4  /* IN3R_ENA */
+#define WM5100_IN3R_ENA_WIDTH                        1  /* IN3R_ENA */
+#define WM5100_IN2L_ENA                         0x0008  /* IN2L_ENA */
+#define WM5100_IN2L_ENA_MASK                    0x0008  /* IN2L_ENA */
+#define WM5100_IN2L_ENA_SHIFT                        3  /* IN2L_ENA */
+#define WM5100_IN2L_ENA_WIDTH                        1  /* IN2L_ENA */
+#define WM5100_IN2R_ENA                         0x0004  /* IN2R_ENA */
+#define WM5100_IN2R_ENA_MASK                    0x0004  /* IN2R_ENA */
+#define WM5100_IN2R_ENA_SHIFT                        2  /* IN2R_ENA */
+#define WM5100_IN2R_ENA_WIDTH                        1  /* IN2R_ENA */
+#define WM5100_IN1L_ENA                         0x0002  /* IN1L_ENA */
+#define WM5100_IN1L_ENA_MASK                    0x0002  /* IN1L_ENA */
+#define WM5100_IN1L_ENA_SHIFT                        1  /* IN1L_ENA */
+#define WM5100_IN1L_ENA_WIDTH                        1  /* IN1L_ENA */
+#define WM5100_IN1R_ENA                         0x0001  /* IN1R_ENA */
+#define WM5100_IN1R_ENA_MASK                    0x0001  /* IN1R_ENA */
+#define WM5100_IN1R_ENA_SHIFT                        0  /* IN1R_ENA */
+#define WM5100_IN1R_ENA_WIDTH                        1  /* IN1R_ENA */
+
+/*
+ * R770 (0x302) - Input Enables Status
+ */
+#define WM5100_IN4L_ENA_STS                     0x0080  /* IN4L_ENA_STS */
+#define WM5100_IN4L_ENA_STS_MASK                0x0080  /* IN4L_ENA_STS */
+#define WM5100_IN4L_ENA_STS_SHIFT                    7  /* IN4L_ENA_STS */
+#define WM5100_IN4L_ENA_STS_WIDTH                    1  /* IN4L_ENA_STS */
+#define WM5100_IN4R_ENA_STS                     0x0040  /* IN4R_ENA_STS */
+#define WM5100_IN4R_ENA_STS_MASK                0x0040  /* IN4R_ENA_STS */
+#define WM5100_IN4R_ENA_STS_SHIFT                    6  /* IN4R_ENA_STS */
+#define WM5100_IN4R_ENA_STS_WIDTH                    1  /* IN4R_ENA_STS */
+#define WM5100_IN3L_ENA_STS                     0x0020  /* IN3L_ENA_STS */
+#define WM5100_IN3L_ENA_STS_MASK                0x0020  /* IN3L_ENA_STS */
+#define WM5100_IN3L_ENA_STS_SHIFT                    5  /* IN3L_ENA_STS */
+#define WM5100_IN3L_ENA_STS_WIDTH                    1  /* IN3L_ENA_STS */
+#define WM5100_IN3R_ENA_STS                     0x0010  /* IN3R_ENA_STS */
+#define WM5100_IN3R_ENA_STS_MASK                0x0010  /* IN3R_ENA_STS */
+#define WM5100_IN3R_ENA_STS_SHIFT                    4  /* IN3R_ENA_STS */
+#define WM5100_IN3R_ENA_STS_WIDTH                    1  /* IN3R_ENA_STS */
+#define WM5100_IN2L_ENA_STS                     0x0008  /* IN2L_ENA_STS */
+#define WM5100_IN2L_ENA_STS_MASK                0x0008  /* IN2L_ENA_STS */
+#define WM5100_IN2L_ENA_STS_SHIFT                    3  /* IN2L_ENA_STS */
+#define WM5100_IN2L_ENA_STS_WIDTH                    1  /* IN2L_ENA_STS */
+#define WM5100_IN2R_ENA_STS                     0x0004  /* IN2R_ENA_STS */
+#define WM5100_IN2R_ENA_STS_MASK                0x0004  /* IN2R_ENA_STS */
+#define WM5100_IN2R_ENA_STS_SHIFT                    2  /* IN2R_ENA_STS */
+#define WM5100_IN2R_ENA_STS_WIDTH                    1  /* IN2R_ENA_STS */
+#define WM5100_IN1L_ENA_STS                     0x0002  /* IN1L_ENA_STS */
+#define WM5100_IN1L_ENA_STS_MASK                0x0002  /* IN1L_ENA_STS */
+#define WM5100_IN1L_ENA_STS_SHIFT                    1  /* IN1L_ENA_STS */
+#define WM5100_IN1L_ENA_STS_WIDTH                    1  /* IN1L_ENA_STS */
+#define WM5100_IN1R_ENA_STS                     0x0001  /* IN1R_ENA_STS */
+#define WM5100_IN1R_ENA_STS_MASK                0x0001  /* IN1R_ENA_STS */
+#define WM5100_IN1R_ENA_STS_SHIFT                    0  /* IN1R_ENA_STS */
+#define WM5100_IN1R_ENA_STS_WIDTH                    1  /* IN1R_ENA_STS */
+
+/*
+ * R784 (0x310) - IN1L Control
+ */
+#define WM5100_IN_RATE_MASK                     0xC000  /* IN_RATE - [15:14] */
+#define WM5100_IN_RATE_SHIFT                        14  /* IN_RATE - [15:14] */
+#define WM5100_IN_RATE_WIDTH                         2  /* IN_RATE - [15:14] */
+#define WM5100_IN1_OSR                          0x2000  /* IN1_OSR */
+#define WM5100_IN1_OSR_MASK                     0x2000  /* IN1_OSR */
+#define WM5100_IN1_OSR_SHIFT                        13  /* IN1_OSR */
+#define WM5100_IN1_OSR_WIDTH                         1  /* IN1_OSR */
+#define WM5100_IN1_DMIC_SUP_MASK                0x1800  /* IN1_DMIC_SUP - [12:11] */
+#define WM5100_IN1_DMIC_SUP_SHIFT                   11  /* IN1_DMIC_SUP - [12:11] */
+#define WM5100_IN1_DMIC_SUP_WIDTH                    2  /* IN1_DMIC_SUP - [12:11] */
+#define WM5100_IN1_MODE_MASK                    0x0600  /* IN1_MODE - [10:9] */
+#define WM5100_IN1_MODE_SHIFT                        9  /* IN1_MODE - [10:9] */
+#define WM5100_IN1_MODE_WIDTH                        2  /* IN1_MODE - [10:9] */
+#define WM5100_IN1L_PGA_VOL_MASK                0x00FE  /* IN1L_PGA_VOL - [7:1] */
+#define WM5100_IN1L_PGA_VOL_SHIFT                    1  /* IN1L_PGA_VOL - [7:1] */
+#define WM5100_IN1L_PGA_VOL_WIDTH                    7  /* IN1L_PGA_VOL - [7:1] */
+
+/*
+ * R785 (0x311) - IN1R Control
+ */
+#define WM5100_IN1R_PGA_VOL_MASK                0x00FE  /* IN1R_PGA_VOL - [7:1] */
+#define WM5100_IN1R_PGA_VOL_SHIFT                    1  /* IN1R_PGA_VOL - [7:1] */
+#define WM5100_IN1R_PGA_VOL_WIDTH                    7  /* IN1R_PGA_VOL - [7:1] */
+
+/*
+ * R786 (0x312) - IN2L Control
+ */
+#define WM5100_IN2_OSR                          0x2000  /* IN2_OSR */
+#define WM5100_IN2_OSR_MASK                     0x2000  /* IN2_OSR */
+#define WM5100_IN2_OSR_SHIFT                        13  /* IN2_OSR */
+#define WM5100_IN2_OSR_WIDTH                         1  /* IN2_OSR */
+#define WM5100_IN2_DMIC_SUP_MASK                0x1800  /* IN2_DMIC_SUP - [12:11] */
+#define WM5100_IN2_DMIC_SUP_SHIFT                   11  /* IN2_DMIC_SUP - [12:11] */
+#define WM5100_IN2_DMIC_SUP_WIDTH                    2  /* IN2_DMIC_SUP - [12:11] */
+#define WM5100_IN2_MODE_MASK                    0x0600  /* IN2_MODE - [10:9] */
+#define WM5100_IN2_MODE_SHIFT                        9  /* IN2_MODE - [10:9] */
+#define WM5100_IN2_MODE_WIDTH                        2  /* IN2_MODE - [10:9] */
+#define WM5100_IN2L_PGA_VOL_MASK                0x00FE  /* IN2L_PGA_VOL - [7:1] */
+#define WM5100_IN2L_PGA_VOL_SHIFT                    1  /* IN2L_PGA_VOL - [7:1] */
+#define WM5100_IN2L_PGA_VOL_WIDTH                    7  /* IN2L_PGA_VOL - [7:1] */
+
+/*
+ * R787 (0x313) - IN2R Control
+ */
+#define WM5100_IN2R_PGA_VOL_MASK                0x00FE  /* IN2R_PGA_VOL - [7:1] */
+#define WM5100_IN2R_PGA_VOL_SHIFT                    1  /* IN2R_PGA_VOL - [7:1] */
+#define WM5100_IN2R_PGA_VOL_WIDTH                    7  /* IN2R_PGA_VOL - [7:1] */
+
+/*
+ * R788 (0x314) - IN3L Control
+ */
+#define WM5100_IN3_OSR                          0x2000  /* IN3_OSR */
+#define WM5100_IN3_OSR_MASK                     0x2000  /* IN3_OSR */
+#define WM5100_IN3_OSR_SHIFT                        13  /* IN3_OSR */
+#define WM5100_IN3_OSR_WIDTH                         1  /* IN3_OSR */
+#define WM5100_IN3_DMIC_SUP_MASK                0x1800  /* IN3_DMIC_SUP - [12:11] */
+#define WM5100_IN3_DMIC_SUP_SHIFT                   11  /* IN3_DMIC_SUP - [12:11] */
+#define WM5100_IN3_DMIC_SUP_WIDTH                    2  /* IN3_DMIC_SUP - [12:11] */
+#define WM5100_IN3_MODE_MASK                    0x0600  /* IN3_MODE - [10:9] */
+#define WM5100_IN3_MODE_SHIFT                        9  /* IN3_MODE - [10:9] */
+#define WM5100_IN3_MODE_WIDTH                        2  /* IN3_MODE - [10:9] */
+#define WM5100_IN3L_PGA_VOL_MASK                0x00FE  /* IN3L_PGA_VOL - [7:1] */
+#define WM5100_IN3L_PGA_VOL_SHIFT                    1  /* IN3L_PGA_VOL - [7:1] */
+#define WM5100_IN3L_PGA_VOL_WIDTH                    7  /* IN3L_PGA_VOL - [7:1] */
+
+/*
+ * R789 (0x315) - IN3R Control
+ */
+#define WM5100_IN3R_PGA_VOL_MASK                0x00FE  /* IN3R_PGA_VOL - [7:1] */
+#define WM5100_IN3R_PGA_VOL_SHIFT                    1  /* IN3R_PGA_VOL - [7:1] */
+#define WM5100_IN3R_PGA_VOL_WIDTH                    7  /* IN3R_PGA_VOL - [7:1] */
+
+/*
+ * R790 (0x316) - IN4L Control
+ */
+#define WM5100_IN4_OSR                          0x2000  /* IN4_OSR */
+#define WM5100_IN4_OSR_MASK                     0x2000  /* IN4_OSR */
+#define WM5100_IN4_OSR_SHIFT                        13  /* IN4_OSR */
+#define WM5100_IN4_OSR_WIDTH                         1  /* IN4_OSR */
+#define WM5100_IN4_DMIC_SUP_MASK                0x1800  /* IN4_DMIC_SUP - [12:11] */
+#define WM5100_IN4_DMIC_SUP_SHIFT                   11  /* IN4_DMIC_SUP - [12:11] */
+#define WM5100_IN4_DMIC_SUP_WIDTH                    2  /* IN4_DMIC_SUP - [12:11] */
+#define WM5100_IN4_MODE_MASK                    0x0600  /* IN4_MODE - [10:9] */
+#define WM5100_IN4_MODE_SHIFT                        9  /* IN4_MODE - [10:9] */
+#define WM5100_IN4_MODE_WIDTH                        2  /* IN4_MODE - [10:9] */
+#define WM5100_IN4L_PGA_VOL_MASK                0x00FE  /* IN4L_PGA_VOL - [7:1] */
+#define WM5100_IN4L_PGA_VOL_SHIFT                    1  /* IN4L_PGA_VOL - [7:1] */
+#define WM5100_IN4L_PGA_VOL_WIDTH                    7  /* IN4L_PGA_VOL - [7:1] */
+
+/*
+ * R791 (0x317) - IN4R Control
+ */
+#define WM5100_IN4R_PGA_VOL_MASK                0x00FE  /* IN4R_PGA_VOL - [7:1] */
+#define WM5100_IN4R_PGA_VOL_SHIFT                    1  /* IN4R_PGA_VOL - [7:1] */
+#define WM5100_IN4R_PGA_VOL_WIDTH                    7  /* IN4R_PGA_VOL - [7:1] */
+
+/*
+ * R792 (0x318) - RXANC_SRC
+ */
+#define WM5100_IN_RXANC_SEL_MASK                0x0007  /* IN_RXANC_SEL - [2:0] */
+#define WM5100_IN_RXANC_SEL_SHIFT                    0  /* IN_RXANC_SEL - [2:0] */
+#define WM5100_IN_RXANC_SEL_WIDTH                    3  /* IN_RXANC_SEL - [2:0] */
+
+/*
+ * R793 (0x319) - Input Volume Ramp
+ */
+#define WM5100_IN_VD_RAMP_MASK                  0x0070  /* IN_VD_RAMP - [6:4] */
+#define WM5100_IN_VD_RAMP_SHIFT                      4  /* IN_VD_RAMP - [6:4] */
+#define WM5100_IN_VD_RAMP_WIDTH                      3  /* IN_VD_RAMP - [6:4] */
+#define WM5100_IN_VI_RAMP_MASK                  0x0007  /* IN_VI_RAMP - [2:0] */
+#define WM5100_IN_VI_RAMP_SHIFT                      0  /* IN_VI_RAMP - [2:0] */
+#define WM5100_IN_VI_RAMP_WIDTH                      3  /* IN_VI_RAMP - [2:0] */
+
+/*
+ * R800 (0x320) - ADC Digital Volume 1L
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN1L_MUTE                        0x0100  /* IN1L_MUTE */
+#define WM5100_IN1L_MUTE_MASK                   0x0100  /* IN1L_MUTE */
+#define WM5100_IN1L_MUTE_SHIFT                       8  /* IN1L_MUTE */
+#define WM5100_IN1L_MUTE_WIDTH                       1  /* IN1L_MUTE */
+#define WM5100_IN1L_VOL_MASK                    0x00FF  /* IN1L_VOL - [7:0] */
+#define WM5100_IN1L_VOL_SHIFT                        0  /* IN1L_VOL - [7:0] */
+#define WM5100_IN1L_VOL_WIDTH                        8  /* IN1L_VOL - [7:0] */
+
+/*
+ * R801 (0x321) - ADC Digital Volume 1R
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN1R_MUTE                        0x0100  /* IN1R_MUTE */
+#define WM5100_IN1R_MUTE_MASK                   0x0100  /* IN1R_MUTE */
+#define WM5100_IN1R_MUTE_SHIFT                       8  /* IN1R_MUTE */
+#define WM5100_IN1R_MUTE_WIDTH                       1  /* IN1R_MUTE */
+#define WM5100_IN1R_VOL_MASK                    0x00FF  /* IN1R_VOL - [7:0] */
+#define WM5100_IN1R_VOL_SHIFT                        0  /* IN1R_VOL - [7:0] */
+#define WM5100_IN1R_VOL_WIDTH                        8  /* IN1R_VOL - [7:0] */
+
+/*
+ * R802 (0x322) - ADC Digital Volume 2L
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN2L_MUTE                        0x0100  /* IN2L_MUTE */
+#define WM5100_IN2L_MUTE_MASK                   0x0100  /* IN2L_MUTE */
+#define WM5100_IN2L_MUTE_SHIFT                       8  /* IN2L_MUTE */
+#define WM5100_IN2L_MUTE_WIDTH                       1  /* IN2L_MUTE */
+#define WM5100_IN2L_VOL_MASK                    0x00FF  /* IN2L_VOL - [7:0] */
+#define WM5100_IN2L_VOL_SHIFT                        0  /* IN2L_VOL - [7:0] */
+#define WM5100_IN2L_VOL_WIDTH                        8  /* IN2L_VOL - [7:0] */
+
+/*
+ * R803 (0x323) - ADC Digital Volume 2R
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN2R_MUTE                        0x0100  /* IN2R_MUTE */
+#define WM5100_IN2R_MUTE_MASK                   0x0100  /* IN2R_MUTE */
+#define WM5100_IN2R_MUTE_SHIFT                       8  /* IN2R_MUTE */
+#define WM5100_IN2R_MUTE_WIDTH                       1  /* IN2R_MUTE */
+#define WM5100_IN2R_VOL_MASK                    0x00FF  /* IN2R_VOL - [7:0] */
+#define WM5100_IN2R_VOL_SHIFT                        0  /* IN2R_VOL - [7:0] */
+#define WM5100_IN2R_VOL_WIDTH                        8  /* IN2R_VOL - [7:0] */
+
+/*
+ * R804 (0x324) - ADC Digital Volume 3L
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN3L_MUTE                        0x0100  /* IN3L_MUTE */
+#define WM5100_IN3L_MUTE_MASK                   0x0100  /* IN3L_MUTE */
+#define WM5100_IN3L_MUTE_SHIFT                       8  /* IN3L_MUTE */
+#define WM5100_IN3L_MUTE_WIDTH                       1  /* IN3L_MUTE */
+#define WM5100_IN3L_VOL_MASK                    0x00FF  /* IN3L_VOL - [7:0] */
+#define WM5100_IN3L_VOL_SHIFT                        0  /* IN3L_VOL - [7:0] */
+#define WM5100_IN3L_VOL_WIDTH                        8  /* IN3L_VOL - [7:0] */
+
+/*
+ * R805 (0x325) - ADC Digital Volume 3R
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN3R_MUTE                        0x0100  /* IN3R_MUTE */
+#define WM5100_IN3R_MUTE_MASK                   0x0100  /* IN3R_MUTE */
+#define WM5100_IN3R_MUTE_SHIFT                       8  /* IN3R_MUTE */
+#define WM5100_IN3R_MUTE_WIDTH                       1  /* IN3R_MUTE */
+#define WM5100_IN3R_VOL_MASK                    0x00FF  /* IN3R_VOL - [7:0] */
+#define WM5100_IN3R_VOL_SHIFT                        0  /* IN3R_VOL - [7:0] */
+#define WM5100_IN3R_VOL_WIDTH                        8  /* IN3R_VOL - [7:0] */
+
+/*
+ * R806 (0x326) - ADC Digital Volume 4L
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN4L_MUTE                        0x0100  /* IN4L_MUTE */
+#define WM5100_IN4L_MUTE_MASK                   0x0100  /* IN4L_MUTE */
+#define WM5100_IN4L_MUTE_SHIFT                       8  /* IN4L_MUTE */
+#define WM5100_IN4L_MUTE_WIDTH                       1  /* IN4L_MUTE */
+#define WM5100_IN4L_VOL_MASK                    0x00FF  /* IN4L_VOL - [7:0] */
+#define WM5100_IN4L_VOL_SHIFT                        0  /* IN4L_VOL - [7:0] */
+#define WM5100_IN4L_VOL_WIDTH                        8  /* IN4L_VOL - [7:0] */
+
+/*
+ * R807 (0x327) - ADC Digital Volume 4R
+ */
+#define WM5100_IN_VU                            0x0200  /* IN_VU */
+#define WM5100_IN_VU_MASK                       0x0200  /* IN_VU */
+#define WM5100_IN_VU_SHIFT                           9  /* IN_VU */
+#define WM5100_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM5100_IN4R_MUTE                        0x0100  /* IN4R_MUTE */
+#define WM5100_IN4R_MUTE_MASK                   0x0100  /* IN4R_MUTE */
+#define WM5100_IN4R_MUTE_SHIFT                       8  /* IN4R_MUTE */
+#define WM5100_IN4R_MUTE_WIDTH                       1  /* IN4R_MUTE */
+#define WM5100_IN4R_VOL_MASK                    0x00FF  /* IN4R_VOL - [7:0] */
+#define WM5100_IN4R_VOL_SHIFT                        0  /* IN4R_VOL - [7:0] */
+#define WM5100_IN4R_VOL_WIDTH                        8  /* IN4R_VOL - [7:0] */
+
+/*
+ * R1025 (0x401) - Output Enables 2
+ */
+#define WM5100_OUT6L_ENA                        0x0800  /* OUT6L_ENA */
+#define WM5100_OUT6L_ENA_MASK                   0x0800  /* OUT6L_ENA */
+#define WM5100_OUT6L_ENA_SHIFT                      11  /* OUT6L_ENA */
+#define WM5100_OUT6L_ENA_WIDTH                       1  /* OUT6L_ENA */
+#define WM5100_OUT6R_ENA                        0x0400  /* OUT6R_ENA */
+#define WM5100_OUT6R_ENA_MASK                   0x0400  /* OUT6R_ENA */
+#define WM5100_OUT6R_ENA_SHIFT                      10  /* OUT6R_ENA */
+#define WM5100_OUT6R_ENA_WIDTH                       1  /* OUT6R_ENA */
+#define WM5100_OUT5L_ENA                        0x0200  /* OUT5L_ENA */
+#define WM5100_OUT5L_ENA_MASK                   0x0200  /* OUT5L_ENA */
+#define WM5100_OUT5L_ENA_SHIFT                       9  /* OUT5L_ENA */
+#define WM5100_OUT5L_ENA_WIDTH                       1  /* OUT5L_ENA */
+#define WM5100_OUT5R_ENA                        0x0100  /* OUT5R_ENA */
+#define WM5100_OUT5R_ENA_MASK                   0x0100  /* OUT5R_ENA */
+#define WM5100_OUT5R_ENA_SHIFT                       8  /* OUT5R_ENA */
+#define WM5100_OUT5R_ENA_WIDTH                       1  /* OUT5R_ENA */
+#define WM5100_OUT4L_ENA                        0x0080  /* OUT4L_ENA */
+#define WM5100_OUT4L_ENA_MASK                   0x0080  /* OUT4L_ENA */
+#define WM5100_OUT4L_ENA_SHIFT                       7  /* OUT4L_ENA */
+#define WM5100_OUT4L_ENA_WIDTH                       1  /* OUT4L_ENA */
+#define WM5100_OUT4R_ENA                        0x0040  /* OUT4R_ENA */
+#define WM5100_OUT4R_ENA_MASK                   0x0040  /* OUT4R_ENA */
+#define WM5100_OUT4R_ENA_SHIFT                       6  /* OUT4R_ENA */
+#define WM5100_OUT4R_ENA_WIDTH                       1  /* OUT4R_ENA */
+
+/*
+ * R1026 (0x402) - Output Status 1
+ */
+#define WM5100_OUT3L_ENA_STS                    0x0020  /* OUT3L_ENA_STS */
+#define WM5100_OUT3L_ENA_STS_MASK               0x0020  /* OUT3L_ENA_STS */
+#define WM5100_OUT3L_ENA_STS_SHIFT                   5  /* OUT3L_ENA_STS */
+#define WM5100_OUT3L_ENA_STS_WIDTH                   1  /* OUT3L_ENA_STS */
+#define WM5100_OUT3R_ENA_STS                    0x0010  /* OUT3R_ENA_STS */
+#define WM5100_OUT3R_ENA_STS_MASK               0x0010  /* OUT3R_ENA_STS */
+#define WM5100_OUT3R_ENA_STS_SHIFT                   4  /* OUT3R_ENA_STS */
+#define WM5100_OUT3R_ENA_STS_WIDTH                   1  /* OUT3R_ENA_STS */
+#define WM5100_OUT2L_ENA_STS                    0x0008  /* OUT2L_ENA_STS */
+#define WM5100_OUT2L_ENA_STS_MASK               0x0008  /* OUT2L_ENA_STS */
+#define WM5100_OUT2L_ENA_STS_SHIFT                   3  /* OUT2L_ENA_STS */
+#define WM5100_OUT2L_ENA_STS_WIDTH                   1  /* OUT2L_ENA_STS */
+#define WM5100_OUT2R_ENA_STS                    0x0004  /* OUT2R_ENA_STS */
+#define WM5100_OUT2R_ENA_STS_MASK               0x0004  /* OUT2R_ENA_STS */
+#define WM5100_OUT2R_ENA_STS_SHIFT                   2  /* OUT2R_ENA_STS */
+#define WM5100_OUT2R_ENA_STS_WIDTH                   1  /* OUT2R_ENA_STS */
+#define WM5100_OUT1L_ENA_STS                    0x0002  /* OUT1L_ENA_STS */
+#define WM5100_OUT1L_ENA_STS_MASK               0x0002  /* OUT1L_ENA_STS */
+#define WM5100_OUT1L_ENA_STS_SHIFT                   1  /* OUT1L_ENA_STS */
+#define WM5100_OUT1L_ENA_STS_WIDTH                   1  /* OUT1L_ENA_STS */
+#define WM5100_OUT1R_ENA_STS                    0x0001  /* OUT1R_ENA_STS */
+#define WM5100_OUT1R_ENA_STS_MASK               0x0001  /* OUT1R_ENA_STS */
+#define WM5100_OUT1R_ENA_STS_SHIFT                   0  /* OUT1R_ENA_STS */
+#define WM5100_OUT1R_ENA_STS_WIDTH                   1  /* OUT1R_ENA_STS */
+
+/*
+ * R1027 (0x403) - Output Status 2
+ */
+#define WM5100_OUT6L_ENA_STS                    0x0800  /* OUT6L_ENA_STS */
+#define WM5100_OUT6L_ENA_STS_MASK               0x0800  /* OUT6L_ENA_STS */
+#define WM5100_OUT6L_ENA_STS_SHIFT                  11  /* OUT6L_ENA_STS */
+#define WM5100_OUT6L_ENA_STS_WIDTH                   1  /* OUT6L_ENA_STS */
+#define WM5100_OUT6R_ENA_STS                    0x0400  /* OUT6R_ENA_STS */
+#define WM5100_OUT6R_ENA_STS_MASK               0x0400  /* OUT6R_ENA_STS */
+#define WM5100_OUT6R_ENA_STS_SHIFT                  10  /* OUT6R_ENA_STS */
+#define WM5100_OUT6R_ENA_STS_WIDTH                   1  /* OUT6R_ENA_STS */
+#define WM5100_OUT5L_ENA_STS                    0x0200  /* OUT5L_ENA_STS */
+#define WM5100_OUT5L_ENA_STS_MASK               0x0200  /* OUT5L_ENA_STS */
+#define WM5100_OUT5L_ENA_STS_SHIFT                   9  /* OUT5L_ENA_STS */
+#define WM5100_OUT5L_ENA_STS_WIDTH                   1  /* OUT5L_ENA_STS */
+#define WM5100_OUT5R_ENA_STS                    0x0100  /* OUT5R_ENA_STS */
+#define WM5100_OUT5R_ENA_STS_MASK               0x0100  /* OUT5R_ENA_STS */
+#define WM5100_OUT5R_ENA_STS_SHIFT                   8  /* OUT5R_ENA_STS */
+#define WM5100_OUT5R_ENA_STS_WIDTH                   1  /* OUT5R_ENA_STS */
+#define WM5100_OUT4L_ENA_STS                    0x0080  /* OUT4L_ENA_STS */
+#define WM5100_OUT4L_ENA_STS_MASK               0x0080  /* OUT4L_ENA_STS */
+#define WM5100_OUT4L_ENA_STS_SHIFT                   7  /* OUT4L_ENA_STS */
+#define WM5100_OUT4L_ENA_STS_WIDTH                   1  /* OUT4L_ENA_STS */
+#define WM5100_OUT4R_ENA_STS                    0x0040  /* OUT4R_ENA_STS */
+#define WM5100_OUT4R_ENA_STS_MASK               0x0040  /* OUT4R_ENA_STS */
+#define WM5100_OUT4R_ENA_STS_SHIFT                   6  /* OUT4R_ENA_STS */
+#define WM5100_OUT4R_ENA_STS_WIDTH                   1  /* OUT4R_ENA_STS */
+
+/*
+ * R1032 (0x408) - Channel Enables 1
+ */
+#define WM5100_HP3L_ENA                         0x0020  /* HP3L_ENA */
+#define WM5100_HP3L_ENA_MASK                    0x0020  /* HP3L_ENA */
+#define WM5100_HP3L_ENA_SHIFT                        5  /* HP3L_ENA */
+#define WM5100_HP3L_ENA_WIDTH                        1  /* HP3L_ENA */
+#define WM5100_HP3R_ENA                         0x0010  /* HP3R_ENA */
+#define WM5100_HP3R_ENA_MASK                    0x0010  /* HP3R_ENA */
+#define WM5100_HP3R_ENA_SHIFT                        4  /* HP3R_ENA */
+#define WM5100_HP3R_ENA_WIDTH                        1  /* HP3R_ENA */
+#define WM5100_HP2L_ENA                         0x0008  /* HP2L_ENA */
+#define WM5100_HP2L_ENA_MASK                    0x0008  /* HP2L_ENA */
+#define WM5100_HP2L_ENA_SHIFT                        3  /* HP2L_ENA */
+#define WM5100_HP2L_ENA_WIDTH                        1  /* HP2L_ENA */
+#define WM5100_HP2R_ENA                         0x0004  /* HP2R_ENA */
+#define WM5100_HP2R_ENA_MASK                    0x0004  /* HP2R_ENA */
+#define WM5100_HP2R_ENA_SHIFT                        2  /* HP2R_ENA */
+#define WM5100_HP2R_ENA_WIDTH                        1  /* HP2R_ENA */
+#define WM5100_HP1L_ENA                         0x0002  /* HP1L_ENA */
+#define WM5100_HP1L_ENA_MASK                    0x0002  /* HP1L_ENA */
+#define WM5100_HP1L_ENA_SHIFT                        1  /* HP1L_ENA */
+#define WM5100_HP1L_ENA_WIDTH                        1  /* HP1L_ENA */
+#define WM5100_HP1R_ENA                         0x0001  /* HP1R_ENA */
+#define WM5100_HP1R_ENA_MASK                    0x0001  /* HP1R_ENA */
+#define WM5100_HP1R_ENA_SHIFT                        0  /* HP1R_ENA */
+#define WM5100_HP1R_ENA_WIDTH                        1  /* HP1R_ENA */
+
+/*
+ * R1040 (0x410) - Out Volume 1L
+ */
+#define WM5100_OUT_RATE_MASK                    0xC000  /* OUT_RATE - [15:14] */
+#define WM5100_OUT_RATE_SHIFT                       14  /* OUT_RATE - [15:14] */
+#define WM5100_OUT_RATE_WIDTH                        2  /* OUT_RATE - [15:14] */
+#define WM5100_OUT1_OSR                         0x2000  /* OUT1_OSR */
+#define WM5100_OUT1_OSR_MASK                    0x2000  /* OUT1_OSR */
+#define WM5100_OUT1_OSR_SHIFT                       13  /* OUT1_OSR */
+#define WM5100_OUT1_OSR_WIDTH                        1  /* OUT1_OSR */
+#define WM5100_OUT1_MONO                        0x1000  /* OUT1_MONO */
+#define WM5100_OUT1_MONO_MASK                   0x1000  /* OUT1_MONO */
+#define WM5100_OUT1_MONO_SHIFT                      12  /* OUT1_MONO */
+#define WM5100_OUT1_MONO_WIDTH                       1  /* OUT1_MONO */
+#define WM5100_OUT1L_ANC_SRC                    0x0800  /* OUT1L_ANC_SRC */
+#define WM5100_OUT1L_ANC_SRC_MASK               0x0800  /* OUT1L_ANC_SRC */
+#define WM5100_OUT1L_ANC_SRC_SHIFT                  11  /* OUT1L_ANC_SRC */
+#define WM5100_OUT1L_ANC_SRC_WIDTH                   1  /* OUT1L_ANC_SRC */
+#define WM5100_OUT1L_PGA_VOL_MASK               0x00FE  /* OUT1L_PGA_VOL - [7:1] */
+#define WM5100_OUT1L_PGA_VOL_SHIFT                   1  /* OUT1L_PGA_VOL - [7:1] */
+#define WM5100_OUT1L_PGA_VOL_WIDTH                   7  /* OUT1L_PGA_VOL - [7:1] */
+
+/*
+ * R1041 (0x411) - Out Volume 1R
+ */
+#define WM5100_OUT1R_ANC_SRC                    0x0800  /* OUT1R_ANC_SRC */
+#define WM5100_OUT1R_ANC_SRC_MASK               0x0800  /* OUT1R_ANC_SRC */
+#define WM5100_OUT1R_ANC_SRC_SHIFT                  11  /* OUT1R_ANC_SRC */
+#define WM5100_OUT1R_ANC_SRC_WIDTH                   1  /* OUT1R_ANC_SRC */
+#define WM5100_OUT1R_PGA_VOL_MASK               0x00FE  /* OUT1R_PGA_VOL - [7:1] */
+#define WM5100_OUT1R_PGA_VOL_SHIFT                   1  /* OUT1R_PGA_VOL - [7:1] */
+#define WM5100_OUT1R_PGA_VOL_WIDTH                   7  /* OUT1R_PGA_VOL - [7:1] */
+
+/*
+ * R1042 (0x412) - DAC Volume Limit 1L
+ */
+#define WM5100_OUT1L_VOL_LIM_MASK               0x00FF  /* OUT1L_VOL_LIM - [7:0] */
+#define WM5100_OUT1L_VOL_LIM_SHIFT                   0  /* OUT1L_VOL_LIM - [7:0] */
+#define WM5100_OUT1L_VOL_LIM_WIDTH                   8  /* OUT1L_VOL_LIM - [7:0] */
+
+/*
+ * R1043 (0x413) - DAC Volume Limit 1R
+ */
+#define WM5100_OUT1R_VOL_LIM_MASK               0x00FF  /* OUT1R_VOL_LIM - [7:0] */
+#define WM5100_OUT1R_VOL_LIM_SHIFT                   0  /* OUT1R_VOL_LIM - [7:0] */
+#define WM5100_OUT1R_VOL_LIM_WIDTH                   8  /* OUT1R_VOL_LIM - [7:0] */
+
+/*
+ * R1044 (0x414) - Out Volume 2L
+ */
+#define WM5100_OUT2_OSR                         0x2000  /* OUT2_OSR */
+#define WM5100_OUT2_OSR_MASK                    0x2000  /* OUT2_OSR */
+#define WM5100_OUT2_OSR_SHIFT                       13  /* OUT2_OSR */
+#define WM5100_OUT2_OSR_WIDTH                        1  /* OUT2_OSR */
+#define WM5100_OUT2_MONO                        0x1000  /* OUT2_MONO */
+#define WM5100_OUT2_MONO_MASK                   0x1000  /* OUT2_MONO */
+#define WM5100_OUT2_MONO_SHIFT                      12  /* OUT2_MONO */
+#define WM5100_OUT2_MONO_WIDTH                       1  /* OUT2_MONO */
+#define WM5100_OUT2L_ANC_SRC                    0x0800  /* OUT2L_ANC_SRC */
+#define WM5100_OUT2L_ANC_SRC_MASK               0x0800  /* OUT2L_ANC_SRC */
+#define WM5100_OUT2L_ANC_SRC_SHIFT                  11  /* OUT2L_ANC_SRC */
+#define WM5100_OUT2L_ANC_SRC_WIDTH                   1  /* OUT2L_ANC_SRC */
+#define WM5100_OUT2L_PGA_VOL_MASK               0x00FE  /* OUT2L_PGA_VOL - [7:1] */
+#define WM5100_OUT2L_PGA_VOL_SHIFT                   1  /* OUT2L_PGA_VOL - [7:1] */
+#define WM5100_OUT2L_PGA_VOL_WIDTH                   7  /* OUT2L_PGA_VOL - [7:1] */
+
+/*
+ * R1045 (0x415) - Out Volume 2R
+ */
+#define WM5100_OUT2R_ANC_SRC                    0x0800  /* OUT2R_ANC_SRC */
+#define WM5100_OUT2R_ANC_SRC_MASK               0x0800  /* OUT2R_ANC_SRC */
+#define WM5100_OUT2R_ANC_SRC_SHIFT                  11  /* OUT2R_ANC_SRC */
+#define WM5100_OUT2R_ANC_SRC_WIDTH                   1  /* OUT2R_ANC_SRC */
+#define WM5100_OUT2R_PGA_VOL_MASK               0x00FE  /* OUT2R_PGA_VOL - [7:1] */
+#define WM5100_OUT2R_PGA_VOL_SHIFT                   1  /* OUT2R_PGA_VOL - [7:1] */
+#define WM5100_OUT2R_PGA_VOL_WIDTH                   7  /* OUT2R_PGA_VOL - [7:1] */
+
+/*
+ * R1046 (0x416) - DAC Volume Limit 2L
+ */
+#define WM5100_OUT2L_VOL_LIM_MASK               0x00FF  /* OUT2L_VOL_LIM - [7:0] */
+#define WM5100_OUT2L_VOL_LIM_SHIFT                   0  /* OUT2L_VOL_LIM - [7:0] */
+#define WM5100_OUT2L_VOL_LIM_WIDTH                   8  /* OUT2L_VOL_LIM - [7:0] */
+
+/*
+ * R1047 (0x417) - DAC Volume Limit 2R
+ */
+#define WM5100_OUT2R_VOL_LIM_MASK               0x00FF  /* OUT2R_VOL_LIM - [7:0] */
+#define WM5100_OUT2R_VOL_LIM_SHIFT                   0  /* OUT2R_VOL_LIM - [7:0] */
+#define WM5100_OUT2R_VOL_LIM_WIDTH                   8  /* OUT2R_VOL_LIM - [7:0] */
+
+/*
+ * R1048 (0x418) - Out Volume 3L
+ */
+#define WM5100_OUT3_OSR                         0x2000  /* OUT3_OSR */
+#define WM5100_OUT3_OSR_MASK                    0x2000  /* OUT3_OSR */
+#define WM5100_OUT3_OSR_SHIFT                       13  /* OUT3_OSR */
+#define WM5100_OUT3_OSR_WIDTH                        1  /* OUT3_OSR */
+#define WM5100_OUT3_MONO                        0x1000  /* OUT3_MONO */
+#define WM5100_OUT3_MONO_MASK                   0x1000  /* OUT3_MONO */
+#define WM5100_OUT3_MONO_SHIFT                      12  /* OUT3_MONO */
+#define WM5100_OUT3_MONO_WIDTH                       1  /* OUT3_MONO */
+#define WM5100_OUT3L_ANC_SRC                    0x0800  /* OUT3L_ANC_SRC */
+#define WM5100_OUT3L_ANC_SRC_MASK               0x0800  /* OUT3L_ANC_SRC */
+#define WM5100_OUT3L_ANC_SRC_SHIFT                  11  /* OUT3L_ANC_SRC */
+#define WM5100_OUT3L_ANC_SRC_WIDTH                   1  /* OUT3L_ANC_SRC */
+#define WM5100_OUT3L_PGA_VOL_MASK               0x00FE  /* OUT3L_PGA_VOL - [7:1] */
+#define WM5100_OUT3L_PGA_VOL_SHIFT                   1  /* OUT3L_PGA_VOL - [7:1] */
+#define WM5100_OUT3L_PGA_VOL_WIDTH                   7  /* OUT3L_PGA_VOL - [7:1] */
+
+/*
+ * R1049 (0x419) - Out Volume 3R
+ */
+#define WM5100_OUT3R_ANC_SRC                    0x0800  /* OUT3R_ANC_SRC */
+#define WM5100_OUT3R_ANC_SRC_MASK               0x0800  /* OUT3R_ANC_SRC */
+#define WM5100_OUT3R_ANC_SRC_SHIFT                  11  /* OUT3R_ANC_SRC */
+#define WM5100_OUT3R_ANC_SRC_WIDTH                   1  /* OUT3R_ANC_SRC */
+#define WM5100_OUT3R_PGA_VOL_MASK               0x00FE  /* OUT3R_PGA_VOL - [7:1] */
+#define WM5100_OUT3R_PGA_VOL_SHIFT                   1  /* OUT3R_PGA_VOL - [7:1] */
+#define WM5100_OUT3R_PGA_VOL_WIDTH                   7  /* OUT3R_PGA_VOL - [7:1] */
+
+/*
+ * R1050 (0x41A) - DAC Volume Limit 3L
+ */
+#define WM5100_OUT3L_VOL_LIM_MASK               0x00FF  /* OUT3L_VOL_LIM - [7:0] */
+#define WM5100_OUT3L_VOL_LIM_SHIFT                   0  /* OUT3L_VOL_LIM - [7:0] */
+#define WM5100_OUT3L_VOL_LIM_WIDTH                   8  /* OUT3L_VOL_LIM - [7:0] */
+
+/*
+ * R1051 (0x41B) - DAC Volume Limit 3R
+ */
+#define WM5100_OUT3R_VOL_LIM_MASK               0x00FF  /* OUT3R_VOL_LIM - [7:0] */
+#define WM5100_OUT3R_VOL_LIM_SHIFT                   0  /* OUT3R_VOL_LIM - [7:0] */
+#define WM5100_OUT3R_VOL_LIM_WIDTH                   8  /* OUT3R_VOL_LIM - [7:0] */
+
+/*
+ * R1052 (0x41C) - Out Volume 4L
+ */
+#define WM5100_OUT4_OSR                         0x2000  /* OUT4_OSR */
+#define WM5100_OUT4_OSR_MASK                    0x2000  /* OUT4_OSR */
+#define WM5100_OUT4_OSR_SHIFT                       13  /* OUT4_OSR */
+#define WM5100_OUT4_OSR_WIDTH                        1  /* OUT4_OSR */
+#define WM5100_OUT4L_ANC_SRC                    0x0800  /* OUT4L_ANC_SRC */
+#define WM5100_OUT4L_ANC_SRC_MASK               0x0800  /* OUT4L_ANC_SRC */
+#define WM5100_OUT4L_ANC_SRC_SHIFT                  11  /* OUT4L_ANC_SRC */
+#define WM5100_OUT4L_ANC_SRC_WIDTH                   1  /* OUT4L_ANC_SRC */
+#define WM5100_OUT4L_VOL_LIM_MASK               0x00FF  /* OUT4L_VOL_LIM - [7:0] */
+#define WM5100_OUT4L_VOL_LIM_SHIFT                   0  /* OUT4L_VOL_LIM - [7:0] */
+#define WM5100_OUT4L_VOL_LIM_WIDTH                   8  /* OUT4L_VOL_LIM - [7:0] */
+
+/*
+ * R1053 (0x41D) - Out Volume 4R
+ */
+#define WM5100_OUT4R_ANC_SRC                    0x0800  /* OUT4R_ANC_SRC */
+#define WM5100_OUT4R_ANC_SRC_MASK               0x0800  /* OUT4R_ANC_SRC */
+#define WM5100_OUT4R_ANC_SRC_SHIFT                  11  /* OUT4R_ANC_SRC */
+#define WM5100_OUT4R_ANC_SRC_WIDTH                   1  /* OUT4R_ANC_SRC */
+#define WM5100_OUT4R_VOL_LIM_MASK               0x00FF  /* OUT4R_VOL_LIM - [7:0] */
+#define WM5100_OUT4R_VOL_LIM_SHIFT                   0  /* OUT4R_VOL_LIM - [7:0] */
+#define WM5100_OUT4R_VOL_LIM_WIDTH                   8  /* OUT4R_VOL_LIM - [7:0] */
+
+/*
+ * R1054 (0x41E) - DAC Volume Limit 5L
+ */
+#define WM5100_OUT5_OSR                         0x2000  /* OUT5_OSR */
+#define WM5100_OUT5_OSR_MASK                    0x2000  /* OUT5_OSR */
+#define WM5100_OUT5_OSR_SHIFT                       13  /* OUT5_OSR */
+#define WM5100_OUT5_OSR_WIDTH                        1  /* OUT5_OSR */
+#define WM5100_OUT5L_ANC_SRC                    0x0800  /* OUT5L_ANC_SRC */
+#define WM5100_OUT5L_ANC_SRC_MASK               0x0800  /* OUT5L_ANC_SRC */
+#define WM5100_OUT5L_ANC_SRC_SHIFT                  11  /* OUT5L_ANC_SRC */
+#define WM5100_OUT5L_ANC_SRC_WIDTH                   1  /* OUT5L_ANC_SRC */
+#define WM5100_OUT5L_VOL_LIM_MASK               0x00FF  /* OUT5L_VOL_LIM - [7:0] */
+#define WM5100_OUT5L_VOL_LIM_SHIFT                   0  /* OUT5L_VOL_LIM - [7:0] */
+#define WM5100_OUT5L_VOL_LIM_WIDTH                   8  /* OUT5L_VOL_LIM - [7:0] */
+
+/*
+ * R1055 (0x41F) - DAC Volume Limit 5R
+ */
+#define WM5100_OUT5R_ANC_SRC                    0x0800  /* OUT5R_ANC_SRC */
+#define WM5100_OUT5R_ANC_SRC_MASK               0x0800  /* OUT5R_ANC_SRC */
+#define WM5100_OUT5R_ANC_SRC_SHIFT                  11  /* OUT5R_ANC_SRC */
+#define WM5100_OUT5R_ANC_SRC_WIDTH                   1  /* OUT5R_ANC_SRC */
+#define WM5100_OUT5R_VOL_LIM_MASK               0x00FF  /* OUT5R_VOL_LIM - [7:0] */
+#define WM5100_OUT5R_VOL_LIM_SHIFT                   0  /* OUT5R_VOL_LIM - [7:0] */
+#define WM5100_OUT5R_VOL_LIM_WIDTH                   8  /* OUT5R_VOL_LIM - [7:0] */
+
+/*
+ * R1056 (0x420) - DAC Volume Limit 6L
+ */
+#define WM5100_OUT6_OSR                         0x2000  /* OUT6_OSR */
+#define WM5100_OUT6_OSR_MASK                    0x2000  /* OUT6_OSR */
+#define WM5100_OUT6_OSR_SHIFT                       13  /* OUT6_OSR */
+#define WM5100_OUT6_OSR_WIDTH                        1  /* OUT6_OSR */
+#define WM5100_OUT6L_ANC_SRC                    0x0800  /* OUT6L_ANC_SRC */
+#define WM5100_OUT6L_ANC_SRC_MASK               0x0800  /* OUT6L_ANC_SRC */
+#define WM5100_OUT6L_ANC_SRC_SHIFT                  11  /* OUT6L_ANC_SRC */
+#define WM5100_OUT6L_ANC_SRC_WIDTH                   1  /* OUT6L_ANC_SRC */
+#define WM5100_OUT6L_VOL_LIM_MASK               0x00FF  /* OUT6L_VOL_LIM - [7:0] */
+#define WM5100_OUT6L_VOL_LIM_SHIFT                   0  /* OUT6L_VOL_LIM - [7:0] */
+#define WM5100_OUT6L_VOL_LIM_WIDTH                   8  /* OUT6L_VOL_LIM - [7:0] */
+
+/*
+ * R1057 (0x421) - DAC Volume Limit 6R
+ */
+#define WM5100_OUT6R_ANC_SRC                    0x0800  /* OUT6R_ANC_SRC */
+#define WM5100_OUT6R_ANC_SRC_MASK               0x0800  /* OUT6R_ANC_SRC */
+#define WM5100_OUT6R_ANC_SRC_SHIFT                  11  /* OUT6R_ANC_SRC */
+#define WM5100_OUT6R_ANC_SRC_WIDTH                   1  /* OUT6R_ANC_SRC */
+#define WM5100_OUT6R_VOL_LIM_MASK               0x00FF  /* OUT6R_VOL_LIM - [7:0] */
+#define WM5100_OUT6R_VOL_LIM_SHIFT                   0  /* OUT6R_VOL_LIM - [7:0] */
+#define WM5100_OUT6R_VOL_LIM_WIDTH                   8  /* OUT6R_VOL_LIM - [7:0] */
+
+/*
+ * R1088 (0x440) - DAC AEC Control 1
+ */
+#define WM5100_AEC_LOOPBACK_SRC_MASK            0x003C  /* AEC_LOOPBACK_SRC - [5:2] */
+#define WM5100_AEC_LOOPBACK_SRC_SHIFT                2  /* AEC_LOOPBACK_SRC - [5:2] */
+#define WM5100_AEC_LOOPBACK_SRC_WIDTH                4  /* AEC_LOOPBACK_SRC - [5:2] */
+#define WM5100_AEC_ENA_STS                      0x0002  /* AEC_ENA_STS */
+#define WM5100_AEC_ENA_STS_MASK                 0x0002  /* AEC_ENA_STS */
+#define WM5100_AEC_ENA_STS_SHIFT                     1  /* AEC_ENA_STS */
+#define WM5100_AEC_ENA_STS_WIDTH                     1  /* AEC_ENA_STS */
+#define WM5100_AEC_LOOPBACK_ENA                 0x0001  /* AEC_LOOPBACK_ENA */
+#define WM5100_AEC_LOOPBACK_ENA_MASK            0x0001  /* AEC_LOOPBACK_ENA */
+#define WM5100_AEC_LOOPBACK_ENA_SHIFT                0  /* AEC_LOOPBACK_ENA */
+#define WM5100_AEC_LOOPBACK_ENA_WIDTH                1  /* AEC_LOOPBACK_ENA */
+
+/*
+ * R1089 (0x441) - Output Volume Ramp
+ */
+#define WM5100_OUT_VD_RAMP_MASK                 0x0070  /* OUT_VD_RAMP - [6:4] */
+#define WM5100_OUT_VD_RAMP_SHIFT                     4  /* OUT_VD_RAMP - [6:4] */
+#define WM5100_OUT_VD_RAMP_WIDTH                     3  /* OUT_VD_RAMP - [6:4] */
+#define WM5100_OUT_VI_RAMP_MASK                 0x0007  /* OUT_VI_RAMP - [2:0] */
+#define WM5100_OUT_VI_RAMP_SHIFT                     0  /* OUT_VI_RAMP - [2:0] */
+#define WM5100_OUT_VI_RAMP_WIDTH                     3  /* OUT_VI_RAMP - [2:0] */
+
+/*
+ * R1152 (0x480) - DAC Digital Volume 1L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT1L_MUTE                       0x0100  /* OUT1L_MUTE */
+#define WM5100_OUT1L_MUTE_MASK                  0x0100  /* OUT1L_MUTE */
+#define WM5100_OUT1L_MUTE_SHIFT                      8  /* OUT1L_MUTE */
+#define WM5100_OUT1L_MUTE_WIDTH                      1  /* OUT1L_MUTE */
+#define WM5100_OUT1L_VOL_MASK                   0x00FF  /* OUT1L_VOL - [7:0] */
+#define WM5100_OUT1L_VOL_SHIFT                       0  /* OUT1L_VOL - [7:0] */
+#define WM5100_OUT1L_VOL_WIDTH                       8  /* OUT1L_VOL - [7:0] */
+
+/*
+ * R1153 (0x481) - DAC Digital Volume 1R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT1R_MUTE                       0x0100  /* OUT1R_MUTE */
+#define WM5100_OUT1R_MUTE_MASK                  0x0100  /* OUT1R_MUTE */
+#define WM5100_OUT1R_MUTE_SHIFT                      8  /* OUT1R_MUTE */
+#define WM5100_OUT1R_MUTE_WIDTH                      1  /* OUT1R_MUTE */
+#define WM5100_OUT1R_VOL_MASK                   0x00FF  /* OUT1R_VOL - [7:0] */
+#define WM5100_OUT1R_VOL_SHIFT                       0  /* OUT1R_VOL - [7:0] */
+#define WM5100_OUT1R_VOL_WIDTH                       8  /* OUT1R_VOL - [7:0] */
+
+/*
+ * R1154 (0x482) - DAC Digital Volume 2L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT2L_MUTE                       0x0100  /* OUT2L_MUTE */
+#define WM5100_OUT2L_MUTE_MASK                  0x0100  /* OUT2L_MUTE */
+#define WM5100_OUT2L_MUTE_SHIFT                      8  /* OUT2L_MUTE */
+#define WM5100_OUT2L_MUTE_WIDTH                      1  /* OUT2L_MUTE */
+#define WM5100_OUT2L_VOL_MASK                   0x00FF  /* OUT2L_VOL - [7:0] */
+#define WM5100_OUT2L_VOL_SHIFT                       0  /* OUT2L_VOL - [7:0] */
+#define WM5100_OUT2L_VOL_WIDTH                       8  /* OUT2L_VOL - [7:0] */
+
+/*
+ * R1155 (0x483) - DAC Digital Volume 2R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT2R_MUTE                       0x0100  /* OUT2R_MUTE */
+#define WM5100_OUT2R_MUTE_MASK                  0x0100  /* OUT2R_MUTE */
+#define WM5100_OUT2R_MUTE_SHIFT                      8  /* OUT2R_MUTE */
+#define WM5100_OUT2R_MUTE_WIDTH                      1  /* OUT2R_MUTE */
+#define WM5100_OUT2R_VOL_MASK                   0x00FF  /* OUT2R_VOL - [7:0] */
+#define WM5100_OUT2R_VOL_SHIFT                       0  /* OUT2R_VOL - [7:0] */
+#define WM5100_OUT2R_VOL_WIDTH                       8  /* OUT2R_VOL - [7:0] */
+
+/*
+ * R1156 (0x484) - DAC Digital Volume 3L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT3L_MUTE                       0x0100  /* OUT3L_MUTE */
+#define WM5100_OUT3L_MUTE_MASK                  0x0100  /* OUT3L_MUTE */
+#define WM5100_OUT3L_MUTE_SHIFT                      8  /* OUT3L_MUTE */
+#define WM5100_OUT3L_MUTE_WIDTH                      1  /* OUT3L_MUTE */
+#define WM5100_OUT3L_VOL_MASK                   0x00FF  /* OUT3L_VOL - [7:0] */
+#define WM5100_OUT3L_VOL_SHIFT                       0  /* OUT3L_VOL - [7:0] */
+#define WM5100_OUT3L_VOL_WIDTH                       8  /* OUT3L_VOL - [7:0] */
+
+/*
+ * R1157 (0x485) - DAC Digital Volume 3R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT3R_MUTE                       0x0100  /* OUT3R_MUTE */
+#define WM5100_OUT3R_MUTE_MASK                  0x0100  /* OUT3R_MUTE */
+#define WM5100_OUT3R_MUTE_SHIFT                      8  /* OUT3R_MUTE */
+#define WM5100_OUT3R_MUTE_WIDTH                      1  /* OUT3R_MUTE */
+#define WM5100_OUT3R_VOL_MASK                   0x00FF  /* OUT3R_VOL - [7:0] */
+#define WM5100_OUT3R_VOL_SHIFT                       0  /* OUT3R_VOL - [7:0] */
+#define WM5100_OUT3R_VOL_WIDTH                       8  /* OUT3R_VOL - [7:0] */
+
+/*
+ * R1158 (0x486) - DAC Digital Volume 4L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT4L_MUTE                       0x0100  /* OUT4L_MUTE */
+#define WM5100_OUT4L_MUTE_MASK                  0x0100  /* OUT4L_MUTE */
+#define WM5100_OUT4L_MUTE_SHIFT                      8  /* OUT4L_MUTE */
+#define WM5100_OUT4L_MUTE_WIDTH                      1  /* OUT4L_MUTE */
+#define WM5100_OUT4L_VOL_MASK                   0x00FF  /* OUT4L_VOL - [7:0] */
+#define WM5100_OUT4L_VOL_SHIFT                       0  /* OUT4L_VOL - [7:0] */
+#define WM5100_OUT4L_VOL_WIDTH                       8  /* OUT4L_VOL - [7:0] */
+
+/*
+ * R1159 (0x487) - DAC Digital Volume 4R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT4R_MUTE                       0x0100  /* OUT4R_MUTE */
+#define WM5100_OUT4R_MUTE_MASK                  0x0100  /* OUT4R_MUTE */
+#define WM5100_OUT4R_MUTE_SHIFT                      8  /* OUT4R_MUTE */
+#define WM5100_OUT4R_MUTE_WIDTH                      1  /* OUT4R_MUTE */
+#define WM5100_OUT4R_VOL_MASK                   0x00FF  /* OUT4R_VOL - [7:0] */
+#define WM5100_OUT4R_VOL_SHIFT                       0  /* OUT4R_VOL - [7:0] */
+#define WM5100_OUT4R_VOL_WIDTH                       8  /* OUT4R_VOL - [7:0] */
+
+/*
+ * R1160 (0x488) - DAC Digital Volume 5L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT5L_MUTE                       0x0100  /* OUT5L_MUTE */
+#define WM5100_OUT5L_MUTE_MASK                  0x0100  /* OUT5L_MUTE */
+#define WM5100_OUT5L_MUTE_SHIFT                      8  /* OUT5L_MUTE */
+#define WM5100_OUT5L_MUTE_WIDTH                      1  /* OUT5L_MUTE */
+#define WM5100_OUT5L_VOL_MASK                   0x00FF  /* OUT5L_VOL - [7:0] */
+#define WM5100_OUT5L_VOL_SHIFT                       0  /* OUT5L_VOL - [7:0] */
+#define WM5100_OUT5L_VOL_WIDTH                       8  /* OUT5L_VOL - [7:0] */
+
+/*
+ * R1161 (0x489) - DAC Digital Volume 5R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT5R_MUTE                       0x0100  /* OUT5R_MUTE */
+#define WM5100_OUT5R_MUTE_MASK                  0x0100  /* OUT5R_MUTE */
+#define WM5100_OUT5R_MUTE_SHIFT                      8  /* OUT5R_MUTE */
+#define WM5100_OUT5R_MUTE_WIDTH                      1  /* OUT5R_MUTE */
+#define WM5100_OUT5R_VOL_MASK                   0x00FF  /* OUT5R_VOL - [7:0] */
+#define WM5100_OUT5R_VOL_SHIFT                       0  /* OUT5R_VOL - [7:0] */
+#define WM5100_OUT5R_VOL_WIDTH                       8  /* OUT5R_VOL - [7:0] */
+
+/*
+ * R1162 (0x48A) - DAC Digital Volume 6L
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT6L_MUTE                       0x0100  /* OUT6L_MUTE */
+#define WM5100_OUT6L_MUTE_MASK                  0x0100  /* OUT6L_MUTE */
+#define WM5100_OUT6L_MUTE_SHIFT                      8  /* OUT6L_MUTE */
+#define WM5100_OUT6L_MUTE_WIDTH                      1  /* OUT6L_MUTE */
+#define WM5100_OUT6L_VOL_MASK                   0x00FF  /* OUT6L_VOL - [7:0] */
+#define WM5100_OUT6L_VOL_SHIFT                       0  /* OUT6L_VOL - [7:0] */
+#define WM5100_OUT6L_VOL_WIDTH                       8  /* OUT6L_VOL - [7:0] */
+
+/*
+ * R1163 (0x48B) - DAC Digital Volume 6R
+ */
+#define WM5100_OUT_VU                           0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_MASK                      0x0200  /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT                          9  /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH                          1  /* OUT_VU */
+#define WM5100_OUT6R_MUTE                       0x0100  /* OUT6R_MUTE */
+#define WM5100_OUT6R_MUTE_MASK                  0x0100  /* OUT6R_MUTE */
+#define WM5100_OUT6R_MUTE_SHIFT                      8  /* OUT6R_MUTE */
+#define WM5100_OUT6R_MUTE_WIDTH                      1  /* OUT6R_MUTE */
+#define WM5100_OUT6R_VOL_MASK                   0x00FF  /* OUT6R_VOL - [7:0] */
+#define WM5100_OUT6R_VOL_SHIFT                       0  /* OUT6R_VOL - [7:0] */
+#define WM5100_OUT6R_VOL_WIDTH                       8  /* OUT6R_VOL - [7:0] */
+
+/*
+ * R1216 (0x4C0) - PDM SPK1 CTRL 1
+ */
+#define WM5100_SPK1R_MUTE                       0x2000  /* SPK1R_MUTE */
+#define WM5100_SPK1R_MUTE_MASK                  0x2000  /* SPK1R_MUTE */
+#define WM5100_SPK1R_MUTE_SHIFT                     13  /* SPK1R_MUTE */
+#define WM5100_SPK1R_MUTE_WIDTH                      1  /* SPK1R_MUTE */
+#define WM5100_SPK1L_MUTE                       0x1000  /* SPK1L_MUTE */
+#define WM5100_SPK1L_MUTE_MASK                  0x1000  /* SPK1L_MUTE */
+#define WM5100_SPK1L_MUTE_SHIFT                     12  /* SPK1L_MUTE */
+#define WM5100_SPK1L_MUTE_WIDTH                      1  /* SPK1L_MUTE */
+#define WM5100_SPK1_MUTE_ENDIAN                 0x0100  /* SPK1_MUTE_ENDIAN */
+#define WM5100_SPK1_MUTE_ENDIAN_MASK            0x0100  /* SPK1_MUTE_ENDIAN */
+#define WM5100_SPK1_MUTE_ENDIAN_SHIFT                8  /* SPK1_MUTE_ENDIAN */
+#define WM5100_SPK1_MUTE_ENDIAN_WIDTH                1  /* SPK1_MUTE_ENDIAN */
+#define WM5100_SPK1_MUTE_SEQ1_MASK              0x00FF  /* SPK1_MUTE_SEQ1 - [7:0] */
+#define WM5100_SPK1_MUTE_SEQ1_SHIFT                  0  /* SPK1_MUTE_SEQ1 - [7:0] */
+#define WM5100_SPK1_MUTE_SEQ1_WIDTH                  8  /* SPK1_MUTE_SEQ1 - [7:0] */
+
+/*
+ * R1217 (0x4C1) - PDM SPK1 CTRL 2
+ */
+#define WM5100_SPK1_FMT                         0x0001  /* SPK1_FMT */
+#define WM5100_SPK1_FMT_MASK                    0x0001  /* SPK1_FMT */
+#define WM5100_SPK1_FMT_SHIFT                        0  /* SPK1_FMT */
+#define WM5100_SPK1_FMT_WIDTH                        1  /* SPK1_FMT */
+
+/*
+ * R1218 (0x4C2) - PDM SPK2 CTRL 1
+ */
+#define WM5100_SPK2R_MUTE                       0x2000  /* SPK2R_MUTE */
+#define WM5100_SPK2R_MUTE_MASK                  0x2000  /* SPK2R_MUTE */
+#define WM5100_SPK2R_MUTE_SHIFT                     13  /* SPK2R_MUTE */
+#define WM5100_SPK2R_MUTE_WIDTH                      1  /* SPK2R_MUTE */
+#define WM5100_SPK2L_MUTE                       0x1000  /* SPK2L_MUTE */
+#define WM5100_SPK2L_MUTE_MASK                  0x1000  /* SPK2L_MUTE */
+#define WM5100_SPK2L_MUTE_SHIFT                     12  /* SPK2L_MUTE */
+#define WM5100_SPK2L_MUTE_WIDTH                      1  /* SPK2L_MUTE */
+#define WM5100_SPK2_MUTE_ENDIAN                 0x0100  /* SPK2_MUTE_ENDIAN */
+#define WM5100_SPK2_MUTE_ENDIAN_MASK            0x0100  /* SPK2_MUTE_ENDIAN */
+#define WM5100_SPK2_MUTE_ENDIAN_SHIFT                8  /* SPK2_MUTE_ENDIAN */
+#define WM5100_SPK2_MUTE_ENDIAN_WIDTH                1  /* SPK2_MUTE_ENDIAN */
+#define WM5100_SPK2_MUTE_SEQ1_MASK              0x00FF  /* SPK2_MUTE_SEQ1 - [7:0] */
+#define WM5100_SPK2_MUTE_SEQ1_SHIFT                  0  /* SPK2_MUTE_SEQ1 - [7:0] */
+#define WM5100_SPK2_MUTE_SEQ1_WIDTH                  8  /* SPK2_MUTE_SEQ1 - [7:0] */
+
+/*
+ * R1219 (0x4C3) - PDM SPK2 CTRL 2
+ */
+#define WM5100_SPK2_FMT                         0x0001  /* SPK2_FMT */
+#define WM5100_SPK2_FMT_MASK                    0x0001  /* SPK2_FMT */
+#define WM5100_SPK2_FMT_SHIFT                        0  /* SPK2_FMT */
+#define WM5100_SPK2_FMT_WIDTH                        1  /* SPK2_FMT */
+
+/*
+ * R1280 (0x500) - Audio IF 1_1
+ */
+#define WM5100_AIF1_BCLK_INV                    0x0080  /* AIF1_BCLK_INV */
+#define WM5100_AIF1_BCLK_INV_MASK               0x0080  /* AIF1_BCLK_INV */
+#define WM5100_AIF1_BCLK_INV_SHIFT                   7  /* AIF1_BCLK_INV */
+#define WM5100_AIF1_BCLK_INV_WIDTH                   1  /* AIF1_BCLK_INV */
+#define WM5100_AIF1_BCLK_FRC                    0x0040  /* AIF1_BCLK_FRC */
+#define WM5100_AIF1_BCLK_FRC_MASK               0x0040  /* AIF1_BCLK_FRC */
+#define WM5100_AIF1_BCLK_FRC_SHIFT                   6  /* AIF1_BCLK_FRC */
+#define WM5100_AIF1_BCLK_FRC_WIDTH                   1  /* AIF1_BCLK_FRC */
+#define WM5100_AIF1_BCLK_MSTR                   0x0020  /* AIF1_BCLK_MSTR */
+#define WM5100_AIF1_BCLK_MSTR_MASK              0x0020  /* AIF1_BCLK_MSTR */
+#define WM5100_AIF1_BCLK_MSTR_SHIFT                  5  /* AIF1_BCLK_MSTR */
+#define WM5100_AIF1_BCLK_MSTR_WIDTH                  1  /* AIF1_BCLK_MSTR */
+#define WM5100_AIF1_BCLK_FREQ_MASK              0x001F  /* AIF1_BCLK_FREQ - [4:0] */
+#define WM5100_AIF1_BCLK_FREQ_SHIFT                  0  /* AIF1_BCLK_FREQ - [4:0] */
+#define WM5100_AIF1_BCLK_FREQ_WIDTH                  5  /* AIF1_BCLK_FREQ - [4:0] */
+
+/*
+ * R1281 (0x501) - Audio IF 1_2
+ */
+#define WM5100_AIF1TX_DAT_TRI                   0x0020  /* AIF1TX_DAT_TRI */
+#define WM5100_AIF1TX_DAT_TRI_MASK              0x0020  /* AIF1TX_DAT_TRI */
+#define WM5100_AIF1TX_DAT_TRI_SHIFT                  5  /* AIF1TX_DAT_TRI */
+#define WM5100_AIF1TX_DAT_TRI_WIDTH                  1  /* AIF1TX_DAT_TRI */
+#define WM5100_AIF1TX_LRCLK_SRC                 0x0008  /* AIF1TX_LRCLK_SRC */
+#define WM5100_AIF1TX_LRCLK_SRC_MASK            0x0008  /* AIF1TX_LRCLK_SRC */
+#define WM5100_AIF1TX_LRCLK_SRC_SHIFT                3  /* AIF1TX_LRCLK_SRC */
+#define WM5100_AIF1TX_LRCLK_SRC_WIDTH                1  /* AIF1TX_LRCLK_SRC */
+#define WM5100_AIF1TX_LRCLK_INV                 0x0004  /* AIF1TX_LRCLK_INV */
+#define WM5100_AIF1TX_LRCLK_INV_MASK            0x0004  /* AIF1TX_LRCLK_INV */
+#define WM5100_AIF1TX_LRCLK_INV_SHIFT                2  /* AIF1TX_LRCLK_INV */
+#define WM5100_AIF1TX_LRCLK_INV_WIDTH                1  /* AIF1TX_LRCLK_INV */
+#define WM5100_AIF1TX_LRCLK_FRC                 0x0002  /* AIF1TX_LRCLK_FRC */
+#define WM5100_AIF1TX_LRCLK_FRC_MASK            0x0002  /* AIF1TX_LRCLK_FRC */
+#define WM5100_AIF1TX_LRCLK_FRC_SHIFT                1  /* AIF1TX_LRCLK_FRC */
+#define WM5100_AIF1TX_LRCLK_FRC_WIDTH                1  /* AIF1TX_LRCLK_FRC */
+#define WM5100_AIF1TX_LRCLK_MSTR                0x0001  /* AIF1TX_LRCLK_MSTR */
+#define WM5100_AIF1TX_LRCLK_MSTR_MASK           0x0001  /* AIF1TX_LRCLK_MSTR */
+#define WM5100_AIF1TX_LRCLK_MSTR_SHIFT               0  /* AIF1TX_LRCLK_MSTR */
+#define WM5100_AIF1TX_LRCLK_MSTR_WIDTH               1  /* AIF1TX_LRCLK_MSTR */
+
+/*
+ * R1282 (0x502) - Audio IF 1_3
+ */
+#define WM5100_AIF1RX_LRCLK_INV                 0x0004  /* AIF1RX_LRCLK_INV */
+#define WM5100_AIF1RX_LRCLK_INV_MASK            0x0004  /* AIF1RX_LRCLK_INV */
+#define WM5100_AIF1RX_LRCLK_INV_SHIFT                2  /* AIF1RX_LRCLK_INV */
+#define WM5100_AIF1RX_LRCLK_INV_WIDTH                1  /* AIF1RX_LRCLK_INV */
+#define WM5100_AIF1RX_LRCLK_FRC                 0x0002  /* AIF1RX_LRCLK_FRC */
+#define WM5100_AIF1RX_LRCLK_FRC_MASK            0x0002  /* AIF1RX_LRCLK_FRC */
+#define WM5100_AIF1RX_LRCLK_FRC_SHIFT                1  /* AIF1RX_LRCLK_FRC */
+#define WM5100_AIF1RX_LRCLK_FRC_WIDTH                1  /* AIF1RX_LRCLK_FRC */
+#define WM5100_AIF1RX_LRCLK_MSTR                0x0001  /* AIF1RX_LRCLK_MSTR */
+#define WM5100_AIF1RX_LRCLK_MSTR_MASK           0x0001  /* AIF1RX_LRCLK_MSTR */
+#define WM5100_AIF1RX_LRCLK_MSTR_SHIFT               0  /* AIF1RX_LRCLK_MSTR */
+#define WM5100_AIF1RX_LRCLK_MSTR_WIDTH               1  /* AIF1RX_LRCLK_MSTR */
+
+/*
+ * R1283 (0x503) - Audio IF 1_4
+ */
+#define WM5100_AIF1_TRI                         0x0040  /* AIF1_TRI */
+#define WM5100_AIF1_TRI_MASK                    0x0040  /* AIF1_TRI */
+#define WM5100_AIF1_TRI_SHIFT                        6  /* AIF1_TRI */
+#define WM5100_AIF1_TRI_WIDTH                        1  /* AIF1_TRI */
+#define WM5100_AIF1_RATE_MASK                   0x0003  /* AIF1_RATE - [1:0] */
+#define WM5100_AIF1_RATE_SHIFT                       0  /* AIF1_RATE - [1:0] */
+#define WM5100_AIF1_RATE_WIDTH                       2  /* AIF1_RATE - [1:0] */
+
+/*
+ * R1284 (0x504) - Audio IF 1_5
+ */
+#define WM5100_AIF1_FMT_MASK                    0x0007  /* AIF1_FMT - [2:0] */
+#define WM5100_AIF1_FMT_SHIFT                        0  /* AIF1_FMT - [2:0] */
+#define WM5100_AIF1_FMT_WIDTH                        3  /* AIF1_FMT - [2:0] */
+
+/*
+ * R1285 (0x505) - Audio IF 1_6
+ */
+#define WM5100_AIF1TX_BCPF_MASK                 0x1FFF  /* AIF1TX_BCPF - [12:0] */
+#define WM5100_AIF1TX_BCPF_SHIFT                     0  /* AIF1TX_BCPF - [12:0] */
+#define WM5100_AIF1TX_BCPF_WIDTH                    13  /* AIF1TX_BCPF - [12:0] */
+
+/*
+ * R1286 (0x506) - Audio IF 1_7
+ */
+#define WM5100_AIF1RX_BCPF_MASK                 0x1FFF  /* AIF1RX_BCPF - [12:0] */
+#define WM5100_AIF1RX_BCPF_SHIFT                     0  /* AIF1RX_BCPF - [12:0] */
+#define WM5100_AIF1RX_BCPF_WIDTH                    13  /* AIF1RX_BCPF - [12:0] */
+
+/*
+ * R1287 (0x507) - Audio IF 1_8
+ */
+#define WM5100_AIF1TX_WL_MASK                   0x3F00  /* AIF1TX_WL - [13:8] */
+#define WM5100_AIF1TX_WL_SHIFT                       8  /* AIF1TX_WL - [13:8] */
+#define WM5100_AIF1TX_WL_WIDTH                       6  /* AIF1TX_WL - [13:8] */
+#define WM5100_AIF1TX_SLOT_LEN_MASK             0x00FF  /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF1TX_SLOT_LEN_SHIFT                 0  /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF1TX_SLOT_LEN_WIDTH                 8  /* AIF1TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1288 (0x508) - Audio IF 1_9
+ */
+#define WM5100_AIF1RX_WL_MASK                   0x3F00  /* AIF1RX_WL - [13:8] */
+#define WM5100_AIF1RX_WL_SHIFT                       8  /* AIF1RX_WL - [13:8] */
+#define WM5100_AIF1RX_WL_WIDTH                       6  /* AIF1RX_WL - [13:8] */
+#define WM5100_AIF1RX_SLOT_LEN_MASK             0x00FF  /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF1RX_SLOT_LEN_SHIFT                 0  /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF1RX_SLOT_LEN_WIDTH                 8  /* AIF1RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1289 (0x509) - Audio IF 1_10
+ */
+#define WM5100_AIF1TX1_SLOT_MASK                0x003F  /* AIF1TX1_SLOT - [5:0] */
+#define WM5100_AIF1TX1_SLOT_SHIFT                    0  /* AIF1TX1_SLOT - [5:0] */
+#define WM5100_AIF1TX1_SLOT_WIDTH                    6  /* AIF1TX1_SLOT - [5:0] */
+
+/*
+ * R1290 (0x50A) - Audio IF 1_11
+ */
+#define WM5100_AIF1TX2_SLOT_MASK                0x003F  /* AIF1TX2_SLOT - [5:0] */
+#define WM5100_AIF1TX2_SLOT_SHIFT                    0  /* AIF1TX2_SLOT - [5:0] */
+#define WM5100_AIF1TX2_SLOT_WIDTH                    6  /* AIF1TX2_SLOT - [5:0] */
+
+/*
+ * R1291 (0x50B) - Audio IF 1_12
+ */
+#define WM5100_AIF1TX3_SLOT_MASK                0x003F  /* AIF1TX3_SLOT - [5:0] */
+#define WM5100_AIF1TX3_SLOT_SHIFT                    0  /* AIF1TX3_SLOT - [5:0] */
+#define WM5100_AIF1TX3_SLOT_WIDTH                    6  /* AIF1TX3_SLOT - [5:0] */
+
+/*
+ * R1292 (0x50C) - Audio IF 1_13
+ */
+#define WM5100_AIF1TX4_SLOT_MASK                0x003F  /* AIF1TX4_SLOT - [5:0] */
+#define WM5100_AIF1TX4_SLOT_SHIFT                    0  /* AIF1TX4_SLOT - [5:0] */
+#define WM5100_AIF1TX4_SLOT_WIDTH                    6  /* AIF1TX4_SLOT - [5:0] */
+
+/*
+ * R1293 (0x50D) - Audio IF 1_14
+ */
+#define WM5100_AIF1TX5_SLOT_MASK                0x003F  /* AIF1TX5_SLOT - [5:0] */
+#define WM5100_AIF1TX5_SLOT_SHIFT                    0  /* AIF1TX5_SLOT - [5:0] */
+#define WM5100_AIF1TX5_SLOT_WIDTH                    6  /* AIF1TX5_SLOT - [5:0] */
+
+/*
+ * R1294 (0x50E) - Audio IF 1_15
+ */
+#define WM5100_AIF1TX6_SLOT_MASK                0x003F  /* AIF1TX6_SLOT - [5:0] */
+#define WM5100_AIF1TX6_SLOT_SHIFT                    0  /* AIF1TX6_SLOT - [5:0] */
+#define WM5100_AIF1TX6_SLOT_WIDTH                    6  /* AIF1TX6_SLOT - [5:0] */
+
+/*
+ * R1295 (0x50F) - Audio IF 1_16
+ */
+#define WM5100_AIF1TX7_SLOT_MASK                0x003F  /* AIF1TX7_SLOT - [5:0] */
+#define WM5100_AIF1TX7_SLOT_SHIFT                    0  /* AIF1TX7_SLOT - [5:0] */
+#define WM5100_AIF1TX7_SLOT_WIDTH                    6  /* AIF1TX7_SLOT - [5:0] */
+
+/*
+ * R1296 (0x510) - Audio IF 1_17
+ */
+#define WM5100_AIF1TX8_SLOT_MASK                0x003F  /* AIF1TX8_SLOT - [5:0] */
+#define WM5100_AIF1TX8_SLOT_SHIFT                    0  /* AIF1TX8_SLOT - [5:0] */
+#define WM5100_AIF1TX8_SLOT_WIDTH                    6  /* AIF1TX8_SLOT - [5:0] */
+
+/*
+ * R1297 (0x511) - Audio IF 1_18
+ */
+#define WM5100_AIF1RX1_SLOT_MASK                0x003F  /* AIF1RX1_SLOT - [5:0] */
+#define WM5100_AIF1RX1_SLOT_SHIFT                    0  /* AIF1RX1_SLOT - [5:0] */
+#define WM5100_AIF1RX1_SLOT_WIDTH                    6  /* AIF1RX1_SLOT - [5:0] */
+
+/*
+ * R1298 (0x512) - Audio IF 1_19
+ */
+#define WM5100_AIF1RX2_SLOT_MASK                0x003F  /* AIF1RX2_SLOT - [5:0] */
+#define WM5100_AIF1RX2_SLOT_SHIFT                    0  /* AIF1RX2_SLOT - [5:0] */
+#define WM5100_AIF1RX2_SLOT_WIDTH                    6  /* AIF1RX2_SLOT - [5:0] */
+
+/*
+ * R1299 (0x513) - Audio IF 1_20
+ */
+#define WM5100_AIF1RX3_SLOT_MASK                0x003F  /* AIF1RX3_SLOT - [5:0] */
+#define WM5100_AIF1RX3_SLOT_SHIFT                    0  /* AIF1RX3_SLOT - [5:0] */
+#define WM5100_AIF1RX3_SLOT_WIDTH                    6  /* AIF1RX3_SLOT - [5:0] */
+
+/*
+ * R1300 (0x514) - Audio IF 1_21
+ */
+#define WM5100_AIF1RX4_SLOT_MASK                0x003F  /* AIF1RX4_SLOT - [5:0] */
+#define WM5100_AIF1RX4_SLOT_SHIFT                    0  /* AIF1RX4_SLOT - [5:0] */
+#define WM5100_AIF1RX4_SLOT_WIDTH                    6  /* AIF1RX4_SLOT - [5:0] */
+
+/*
+ * R1301 (0x515) - Audio IF 1_22
+ */
+#define WM5100_AIF1RX5_SLOT_MASK                0x003F  /* AIF1RX5_SLOT - [5:0] */
+#define WM5100_AIF1RX5_SLOT_SHIFT                    0  /* AIF1RX5_SLOT - [5:0] */
+#define WM5100_AIF1RX5_SLOT_WIDTH                    6  /* AIF1RX5_SLOT - [5:0] */
+
+/*
+ * R1302 (0x516) - Audio IF 1_23
+ */
+#define WM5100_AIF1RX6_SLOT_MASK                0x003F  /* AIF1RX6_SLOT - [5:0] */
+#define WM5100_AIF1RX6_SLOT_SHIFT                    0  /* AIF1RX6_SLOT - [5:0] */
+#define WM5100_AIF1RX6_SLOT_WIDTH                    6  /* AIF1RX6_SLOT - [5:0] */
+
+/*
+ * R1303 (0x517) - Audio IF 1_24
+ */
+#define WM5100_AIF1RX7_SLOT_MASK                0x003F  /* AIF1RX7_SLOT - [5:0] */
+#define WM5100_AIF1RX7_SLOT_SHIFT                    0  /* AIF1RX7_SLOT - [5:0] */
+#define WM5100_AIF1RX7_SLOT_WIDTH                    6  /* AIF1RX7_SLOT - [5:0] */
+
+/*
+ * R1304 (0x518) - Audio IF 1_25
+ */
+#define WM5100_AIF1RX8_SLOT_MASK                0x003F  /* AIF1RX8_SLOT - [5:0] */
+#define WM5100_AIF1RX8_SLOT_SHIFT                    0  /* AIF1RX8_SLOT - [5:0] */
+#define WM5100_AIF1RX8_SLOT_WIDTH                    6  /* AIF1RX8_SLOT - [5:0] */
+
+/*
+ * R1305 (0x519) - Audio IF 1_26
+ */
+#define WM5100_AIF1TX8_ENA                      0x0080  /* AIF1TX8_ENA */
+#define WM5100_AIF1TX8_ENA_MASK                 0x0080  /* AIF1TX8_ENA */
+#define WM5100_AIF1TX8_ENA_SHIFT                     7  /* AIF1TX8_ENA */
+#define WM5100_AIF1TX8_ENA_WIDTH                     1  /* AIF1TX8_ENA */
+#define WM5100_AIF1TX7_ENA                      0x0040  /* AIF1TX7_ENA */
+#define WM5100_AIF1TX7_ENA_MASK                 0x0040  /* AIF1TX7_ENA */
+#define WM5100_AIF1TX7_ENA_SHIFT                     6  /* AIF1TX7_ENA */
+#define WM5100_AIF1TX7_ENA_WIDTH                     1  /* AIF1TX7_ENA */
+#define WM5100_AIF1TX6_ENA                      0x0020  /* AIF1TX6_ENA */
+#define WM5100_AIF1TX6_ENA_MASK                 0x0020  /* AIF1TX6_ENA */
+#define WM5100_AIF1TX6_ENA_SHIFT                     5  /* AIF1TX6_ENA */
+#define WM5100_AIF1TX6_ENA_WIDTH                     1  /* AIF1TX6_ENA */
+#define WM5100_AIF1TX5_ENA                      0x0010  /* AIF1TX5_ENA */
+#define WM5100_AIF1TX5_ENA_MASK                 0x0010  /* AIF1TX5_ENA */
+#define WM5100_AIF1TX5_ENA_SHIFT                     4  /* AIF1TX5_ENA */
+#define WM5100_AIF1TX5_ENA_WIDTH                     1  /* AIF1TX5_ENA */
+#define WM5100_AIF1TX4_ENA                      0x0008  /* AIF1TX4_ENA */
+#define WM5100_AIF1TX4_ENA_MASK                 0x0008  /* AIF1TX4_ENA */
+#define WM5100_AIF1TX4_ENA_SHIFT                     3  /* AIF1TX4_ENA */
+#define WM5100_AIF1TX4_ENA_WIDTH                     1  /* AIF1TX4_ENA */
+#define WM5100_AIF1TX3_ENA                      0x0004  /* AIF1TX3_ENA */
+#define WM5100_AIF1TX3_ENA_MASK                 0x0004  /* AIF1TX3_ENA */
+#define WM5100_AIF1TX3_ENA_SHIFT                     2  /* AIF1TX3_ENA */
+#define WM5100_AIF1TX3_ENA_WIDTH                     1  /* AIF1TX3_ENA */
+#define WM5100_AIF1TX2_ENA                      0x0002  /* AIF1TX2_ENA */
+#define WM5100_AIF1TX2_ENA_MASK                 0x0002  /* AIF1TX2_ENA */
+#define WM5100_AIF1TX2_ENA_SHIFT                     1  /* AIF1TX2_ENA */
+#define WM5100_AIF1TX2_ENA_WIDTH                     1  /* AIF1TX2_ENA */
+#define WM5100_AIF1TX1_ENA                      0x0001  /* AIF1TX1_ENA */
+#define WM5100_AIF1TX1_ENA_MASK                 0x0001  /* AIF1TX1_ENA */
+#define WM5100_AIF1TX1_ENA_SHIFT                     0  /* AIF1TX1_ENA */
+#define WM5100_AIF1TX1_ENA_WIDTH                     1  /* AIF1TX1_ENA */
+
+/*
+ * R1306 (0x51A) - Audio IF 1_27
+ */
+#define WM5100_AIF1RX8_ENA                      0x0080  /* AIF1RX8_ENA */
+#define WM5100_AIF1RX8_ENA_MASK                 0x0080  /* AIF1RX8_ENA */
+#define WM5100_AIF1RX8_ENA_SHIFT                     7  /* AIF1RX8_ENA */
+#define WM5100_AIF1RX8_ENA_WIDTH                     1  /* AIF1RX8_ENA */
+#define WM5100_AIF1RX7_ENA                      0x0040  /* AIF1RX7_ENA */
+#define WM5100_AIF1RX7_ENA_MASK                 0x0040  /* AIF1RX7_ENA */
+#define WM5100_AIF1RX7_ENA_SHIFT                     6  /* AIF1RX7_ENA */
+#define WM5100_AIF1RX7_ENA_WIDTH                     1  /* AIF1RX7_ENA */
+#define WM5100_AIF1RX6_ENA                      0x0020  /* AIF1RX6_ENA */
+#define WM5100_AIF1RX6_ENA_MASK                 0x0020  /* AIF1RX6_ENA */
+#define WM5100_AIF1RX6_ENA_SHIFT                     5  /* AIF1RX6_ENA */
+#define WM5100_AIF1RX6_ENA_WIDTH                     1  /* AIF1RX6_ENA */
+#define WM5100_AIF1RX5_ENA                      0x0010  /* AIF1RX5_ENA */
+#define WM5100_AIF1RX5_ENA_MASK                 0x0010  /* AIF1RX5_ENA */
+#define WM5100_AIF1RX5_ENA_SHIFT                     4  /* AIF1RX5_ENA */
+#define WM5100_AIF1RX5_ENA_WIDTH                     1  /* AIF1RX5_ENA */
+#define WM5100_AIF1RX4_ENA                      0x0008  /* AIF1RX4_ENA */
+#define WM5100_AIF1RX4_ENA_MASK                 0x0008  /* AIF1RX4_ENA */
+#define WM5100_AIF1RX4_ENA_SHIFT                     3  /* AIF1RX4_ENA */
+#define WM5100_AIF1RX4_ENA_WIDTH                     1  /* AIF1RX4_ENA */
+#define WM5100_AIF1RX3_ENA                      0x0004  /* AIF1RX3_ENA */
+#define WM5100_AIF1RX3_ENA_MASK                 0x0004  /* AIF1RX3_ENA */
+#define WM5100_AIF1RX3_ENA_SHIFT                     2  /* AIF1RX3_ENA */
+#define WM5100_AIF1RX3_ENA_WIDTH                     1  /* AIF1RX3_ENA */
+#define WM5100_AIF1RX2_ENA                      0x0002  /* AIF1RX2_ENA */
+#define WM5100_AIF1RX2_ENA_MASK                 0x0002  /* AIF1RX2_ENA */
+#define WM5100_AIF1RX2_ENA_SHIFT                     1  /* AIF1RX2_ENA */
+#define WM5100_AIF1RX2_ENA_WIDTH                     1  /* AIF1RX2_ENA */
+#define WM5100_AIF1RX1_ENA                      0x0001  /* AIF1RX1_ENA */
+#define WM5100_AIF1RX1_ENA_MASK                 0x0001  /* AIF1RX1_ENA */
+#define WM5100_AIF1RX1_ENA_SHIFT                     0  /* AIF1RX1_ENA */
+#define WM5100_AIF1RX1_ENA_WIDTH                     1  /* AIF1RX1_ENA */
+
+/*
+ * R1344 (0x540) - Audio IF 2_1
+ */
+#define WM5100_AIF2_BCLK_INV                    0x0080  /* AIF2_BCLK_INV */
+#define WM5100_AIF2_BCLK_INV_MASK               0x0080  /* AIF2_BCLK_INV */
+#define WM5100_AIF2_BCLK_INV_SHIFT                   7  /* AIF2_BCLK_INV */
+#define WM5100_AIF2_BCLK_INV_WIDTH                   1  /* AIF2_BCLK_INV */
+#define WM5100_AIF2_BCLK_FRC                    0x0040  /* AIF2_BCLK_FRC */
+#define WM5100_AIF2_BCLK_FRC_MASK               0x0040  /* AIF2_BCLK_FRC */
+#define WM5100_AIF2_BCLK_FRC_SHIFT                   6  /* AIF2_BCLK_FRC */
+#define WM5100_AIF2_BCLK_FRC_WIDTH                   1  /* AIF2_BCLK_FRC */
+#define WM5100_AIF2_BCLK_MSTR                   0x0020  /* AIF2_BCLK_MSTR */
+#define WM5100_AIF2_BCLK_MSTR_MASK              0x0020  /* AIF2_BCLK_MSTR */
+#define WM5100_AIF2_BCLK_MSTR_SHIFT                  5  /* AIF2_BCLK_MSTR */
+#define WM5100_AIF2_BCLK_MSTR_WIDTH                  1  /* AIF2_BCLK_MSTR */
+#define WM5100_AIF2_BCLK_FREQ_MASK              0x001F  /* AIF2_BCLK_FREQ - [4:0] */
+#define WM5100_AIF2_BCLK_FREQ_SHIFT                  0  /* AIF2_BCLK_FREQ - [4:0] */
+#define WM5100_AIF2_BCLK_FREQ_WIDTH                  5  /* AIF2_BCLK_FREQ - [4:0] */
+
+/*
+ * R1345 (0x541) - Audio IF 2_2
+ */
+#define WM5100_AIF2TX_DAT_TRI                   0x0020  /* AIF2TX_DAT_TRI */
+#define WM5100_AIF2TX_DAT_TRI_MASK              0x0020  /* AIF2TX_DAT_TRI */
+#define WM5100_AIF2TX_DAT_TRI_SHIFT                  5  /* AIF2TX_DAT_TRI */
+#define WM5100_AIF2TX_DAT_TRI_WIDTH                  1  /* AIF2TX_DAT_TRI */
+#define WM5100_AIF2TX_LRCLK_SRC                 0x0008  /* AIF2TX_LRCLK_SRC */
+#define WM5100_AIF2TX_LRCLK_SRC_MASK            0x0008  /* AIF2TX_LRCLK_SRC */
+#define WM5100_AIF2TX_LRCLK_SRC_SHIFT                3  /* AIF2TX_LRCLK_SRC */
+#define WM5100_AIF2TX_LRCLK_SRC_WIDTH                1  /* AIF2TX_LRCLK_SRC */
+#define WM5100_AIF2TX_LRCLK_INV                 0x0004  /* AIF2TX_LRCLK_INV */
+#define WM5100_AIF2TX_LRCLK_INV_MASK            0x0004  /* AIF2TX_LRCLK_INV */
+#define WM5100_AIF2TX_LRCLK_INV_SHIFT                2  /* AIF2TX_LRCLK_INV */
+#define WM5100_AIF2TX_LRCLK_INV_WIDTH                1  /* AIF2TX_LRCLK_INV */
+#define WM5100_AIF2TX_LRCLK_FRC                 0x0002  /* AIF2TX_LRCLK_FRC */
+#define WM5100_AIF2TX_LRCLK_FRC_MASK            0x0002  /* AIF2TX_LRCLK_FRC */
+#define WM5100_AIF2TX_LRCLK_FRC_SHIFT                1  /* AIF2TX_LRCLK_FRC */
+#define WM5100_AIF2TX_LRCLK_FRC_WIDTH                1  /* AIF2TX_LRCLK_FRC */
+#define WM5100_AIF2TX_LRCLK_MSTR                0x0001  /* AIF2TX_LRCLK_MSTR */
+#define WM5100_AIF2TX_LRCLK_MSTR_MASK           0x0001  /* AIF2TX_LRCLK_MSTR */
+#define WM5100_AIF2TX_LRCLK_MSTR_SHIFT               0  /* AIF2TX_LRCLK_MSTR */
+#define WM5100_AIF2TX_LRCLK_MSTR_WIDTH               1  /* AIF2TX_LRCLK_MSTR */
+
+/*
+ * R1346 (0x542) - Audio IF 2_3
+ */
+#define WM5100_AIF2RX_LRCLK_INV                 0x0004  /* AIF2RX_LRCLK_INV */
+#define WM5100_AIF2RX_LRCLK_INV_MASK            0x0004  /* AIF2RX_LRCLK_INV */
+#define WM5100_AIF2RX_LRCLK_INV_SHIFT                2  /* AIF2RX_LRCLK_INV */
+#define WM5100_AIF2RX_LRCLK_INV_WIDTH                1  /* AIF2RX_LRCLK_INV */
+#define WM5100_AIF2RX_LRCLK_FRC                 0x0002  /* AIF2RX_LRCLK_FRC */
+#define WM5100_AIF2RX_LRCLK_FRC_MASK            0x0002  /* AIF2RX_LRCLK_FRC */
+#define WM5100_AIF2RX_LRCLK_FRC_SHIFT                1  /* AIF2RX_LRCLK_FRC */
+#define WM5100_AIF2RX_LRCLK_FRC_WIDTH                1  /* AIF2RX_LRCLK_FRC */
+#define WM5100_AIF2RX_LRCLK_MSTR                0x0001  /* AIF2RX_LRCLK_MSTR */
+#define WM5100_AIF2RX_LRCLK_MSTR_MASK           0x0001  /* AIF2RX_LRCLK_MSTR */
+#define WM5100_AIF2RX_LRCLK_MSTR_SHIFT               0  /* AIF2RX_LRCLK_MSTR */
+#define WM5100_AIF2RX_LRCLK_MSTR_WIDTH               1  /* AIF2RX_LRCLK_MSTR */
+
+/*
+ * R1347 (0x543) - Audio IF 2_4
+ */
+#define WM5100_AIF2_TRI                         0x0040  /* AIF2_TRI */
+#define WM5100_AIF2_TRI_MASK                    0x0040  /* AIF2_TRI */
+#define WM5100_AIF2_TRI_SHIFT                        6  /* AIF2_TRI */
+#define WM5100_AIF2_TRI_WIDTH                        1  /* AIF2_TRI */
+#define WM5100_AIF2_RATE_MASK                   0x0003  /* AIF2_RATE - [1:0] */
+#define WM5100_AIF2_RATE_SHIFT                       0  /* AIF2_RATE - [1:0] */
+#define WM5100_AIF2_RATE_WIDTH                       2  /* AIF2_RATE - [1:0] */
+
+/*
+ * R1348 (0x544) - Audio IF 2_5
+ */
+#define WM5100_AIF2_FMT_MASK                    0x0007  /* AIF2_FMT - [2:0] */
+#define WM5100_AIF2_FMT_SHIFT                        0  /* AIF2_FMT - [2:0] */
+#define WM5100_AIF2_FMT_WIDTH                        3  /* AIF2_FMT - [2:0] */
+
+/*
+ * R1349 (0x545) - Audio IF 2_6
+ */
+#define WM5100_AIF2TX_BCPF_MASK                 0x1FFF  /* AIF2TX_BCPF - [12:0] */
+#define WM5100_AIF2TX_BCPF_SHIFT                     0  /* AIF2TX_BCPF - [12:0] */
+#define WM5100_AIF2TX_BCPF_WIDTH                    13  /* AIF2TX_BCPF - [12:0] */
+
+/*
+ * R1350 (0x546) - Audio IF 2_7
+ */
+#define WM5100_AIF2RX_BCPF_MASK                 0x1FFF  /* AIF2RX_BCPF - [12:0] */
+#define WM5100_AIF2RX_BCPF_SHIFT                     0  /* AIF2RX_BCPF - [12:0] */
+#define WM5100_AIF2RX_BCPF_WIDTH                    13  /* AIF2RX_BCPF - [12:0] */
+
+/*
+ * R1351 (0x547) - Audio IF 2_8
+ */
+#define WM5100_AIF2TX_WL_MASK                   0x3F00  /* AIF2TX_WL - [13:8] */
+#define WM5100_AIF2TX_WL_SHIFT                       8  /* AIF2TX_WL - [13:8] */
+#define WM5100_AIF2TX_WL_WIDTH                       6  /* AIF2TX_WL - [13:8] */
+#define WM5100_AIF2TX_SLOT_LEN_MASK             0x00FF  /* AIF2TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF2TX_SLOT_LEN_SHIFT                 0  /* AIF2TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF2TX_SLOT_LEN_WIDTH                 8  /* AIF2TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1352 (0x548) - Audio IF 2_9
+ */
+#define WM5100_AIF2RX_WL_MASK                   0x3F00  /* AIF2RX_WL - [13:8] */
+#define WM5100_AIF2RX_WL_SHIFT                       8  /* AIF2RX_WL - [13:8] */
+#define WM5100_AIF2RX_WL_WIDTH                       6  /* AIF2RX_WL - [13:8] */
+#define WM5100_AIF2RX_SLOT_LEN_MASK             0x00FF  /* AIF2RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF2RX_SLOT_LEN_SHIFT                 0  /* AIF2RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF2RX_SLOT_LEN_WIDTH                 8  /* AIF2RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1353 (0x549) - Audio IF 2_10
+ */
+#define WM5100_AIF2TX1_SLOT_MASK                0x003F  /* AIF2TX1_SLOT - [5:0] */
+#define WM5100_AIF2TX1_SLOT_SHIFT                    0  /* AIF2TX1_SLOT - [5:0] */
+#define WM5100_AIF2TX1_SLOT_WIDTH                    6  /* AIF2TX1_SLOT - [5:0] */
+
+/*
+ * R1354 (0x54A) - Audio IF 2_11
+ */
+#define WM5100_AIF2TX2_SLOT_MASK                0x003F  /* AIF2TX2_SLOT - [5:0] */
+#define WM5100_AIF2TX2_SLOT_SHIFT                    0  /* AIF2TX2_SLOT - [5:0] */
+#define WM5100_AIF2TX2_SLOT_WIDTH                    6  /* AIF2TX2_SLOT - [5:0] */
+
+/*
+ * R1361 (0x551) - Audio IF 2_18
+ */
+#define WM5100_AIF2RX1_SLOT_MASK                0x003F  /* AIF2RX1_SLOT - [5:0] */
+#define WM5100_AIF2RX1_SLOT_SHIFT                    0  /* AIF2RX1_SLOT - [5:0] */
+#define WM5100_AIF2RX1_SLOT_WIDTH                    6  /* AIF2RX1_SLOT - [5:0] */
+
+/*
+ * R1362 (0x552) - Audio IF 2_19
+ */
+#define WM5100_AIF2RX2_SLOT_MASK                0x003F  /* AIF2RX2_SLOT - [5:0] */
+#define WM5100_AIF2RX2_SLOT_SHIFT                    0  /* AIF2RX2_SLOT - [5:0] */
+#define WM5100_AIF2RX2_SLOT_WIDTH                    6  /* AIF2RX2_SLOT - [5:0] */
+
+/*
+ * R1369 (0x559) - Audio IF 2_26
+ */
+#define WM5100_AIF2TX2_ENA                      0x0002  /* AIF2TX2_ENA */
+#define WM5100_AIF2TX2_ENA_MASK                 0x0002  /* AIF2TX2_ENA */
+#define WM5100_AIF2TX2_ENA_SHIFT                     1  /* AIF2TX2_ENA */
+#define WM5100_AIF2TX2_ENA_WIDTH                     1  /* AIF2TX2_ENA */
+#define WM5100_AIF2TX1_ENA                      0x0001  /* AIF2TX1_ENA */
+#define WM5100_AIF2TX1_ENA_MASK                 0x0001  /* AIF2TX1_ENA */
+#define WM5100_AIF2TX1_ENA_SHIFT                     0  /* AIF2TX1_ENA */
+#define WM5100_AIF2TX1_ENA_WIDTH                     1  /* AIF2TX1_ENA */
+
+/*
+ * R1370 (0x55A) - Audio IF 2_27
+ */
+#define WM5100_AIF2RX2_ENA                      0x0002  /* AIF2RX2_ENA */
+#define WM5100_AIF2RX2_ENA_MASK                 0x0002  /* AIF2RX2_ENA */
+#define WM5100_AIF2RX2_ENA_SHIFT                     1  /* AIF2RX2_ENA */
+#define WM5100_AIF2RX2_ENA_WIDTH                     1  /* AIF2RX2_ENA */
+#define WM5100_AIF2RX1_ENA                      0x0001  /* AIF2RX1_ENA */
+#define WM5100_AIF2RX1_ENA_MASK                 0x0001  /* AIF2RX1_ENA */
+#define WM5100_AIF2RX1_ENA_SHIFT                     0  /* AIF2RX1_ENA */
+#define WM5100_AIF2RX1_ENA_WIDTH                     1  /* AIF2RX1_ENA */
+
+/*
+ * R1408 (0x580) - Audio IF 3_1
+ */
+#define WM5100_AIF3_BCLK_INV                    0x0080  /* AIF3_BCLK_INV */
+#define WM5100_AIF3_BCLK_INV_MASK               0x0080  /* AIF3_BCLK_INV */
+#define WM5100_AIF3_BCLK_INV_SHIFT                   7  /* AIF3_BCLK_INV */
+#define WM5100_AIF3_BCLK_INV_WIDTH                   1  /* AIF3_BCLK_INV */
+#define WM5100_AIF3_BCLK_FRC                    0x0040  /* AIF3_BCLK_FRC */
+#define WM5100_AIF3_BCLK_FRC_MASK               0x0040  /* AIF3_BCLK_FRC */
+#define WM5100_AIF3_BCLK_FRC_SHIFT                   6  /* AIF3_BCLK_FRC */
+#define WM5100_AIF3_BCLK_FRC_WIDTH                   1  /* AIF3_BCLK_FRC */
+#define WM5100_AIF3_BCLK_MSTR                   0x0020  /* AIF3_BCLK_MSTR */
+#define WM5100_AIF3_BCLK_MSTR_MASK              0x0020  /* AIF3_BCLK_MSTR */
+#define WM5100_AIF3_BCLK_MSTR_SHIFT                  5  /* AIF3_BCLK_MSTR */
+#define WM5100_AIF3_BCLK_MSTR_WIDTH                  1  /* AIF3_BCLK_MSTR */
+#define WM5100_AIF3_BCLK_FREQ_MASK              0x001F  /* AIF3_BCLK_FREQ - [4:0] */
+#define WM5100_AIF3_BCLK_FREQ_SHIFT                  0  /* AIF3_BCLK_FREQ - [4:0] */
+#define WM5100_AIF3_BCLK_FREQ_WIDTH                  5  /* AIF3_BCLK_FREQ - [4:0] */
+
+/*
+ * R1409 (0x581) - Audio IF 3_2
+ */
+#define WM5100_AIF3TX_DAT_TRI                   0x0020  /* AIF3TX_DAT_TRI */
+#define WM5100_AIF3TX_DAT_TRI_MASK              0x0020  /* AIF3TX_DAT_TRI */
+#define WM5100_AIF3TX_DAT_TRI_SHIFT                  5  /* AIF3TX_DAT_TRI */
+#define WM5100_AIF3TX_DAT_TRI_WIDTH                  1  /* AIF3TX_DAT_TRI */
+#define WM5100_AIF3TX_LRCLK_SRC                 0x0008  /* AIF3TX_LRCLK_SRC */
+#define WM5100_AIF3TX_LRCLK_SRC_MASK            0x0008  /* AIF3TX_LRCLK_SRC */
+#define WM5100_AIF3TX_LRCLK_SRC_SHIFT                3  /* AIF3TX_LRCLK_SRC */
+#define WM5100_AIF3TX_LRCLK_SRC_WIDTH                1  /* AIF3TX_LRCLK_SRC */
+#define WM5100_AIF3TX_LRCLK_INV                 0x0004  /* AIF3TX_LRCLK_INV */
+#define WM5100_AIF3TX_LRCLK_INV_MASK            0x0004  /* AIF3TX_LRCLK_INV */
+#define WM5100_AIF3TX_LRCLK_INV_SHIFT                2  /* AIF3TX_LRCLK_INV */
+#define WM5100_AIF3TX_LRCLK_INV_WIDTH                1  /* AIF3TX_LRCLK_INV */
+#define WM5100_AIF3TX_LRCLK_FRC                 0x0002  /* AIF3TX_LRCLK_FRC */
+#define WM5100_AIF3TX_LRCLK_FRC_MASK            0x0002  /* AIF3TX_LRCLK_FRC */
+#define WM5100_AIF3TX_LRCLK_FRC_SHIFT                1  /* AIF3TX_LRCLK_FRC */
+#define WM5100_AIF3TX_LRCLK_FRC_WIDTH                1  /* AIF3TX_LRCLK_FRC */
+#define WM5100_AIF3TX_LRCLK_MSTR                0x0001  /* AIF3TX_LRCLK_MSTR */
+#define WM5100_AIF3TX_LRCLK_MSTR_MASK           0x0001  /* AIF3TX_LRCLK_MSTR */
+#define WM5100_AIF3TX_LRCLK_MSTR_SHIFT               0  /* AIF3TX_LRCLK_MSTR */
+#define WM5100_AIF3TX_LRCLK_MSTR_WIDTH               1  /* AIF3TX_LRCLK_MSTR */
+
+/*
+ * R1410 (0x582) - Audio IF 3_3
+ */
+#define WM5100_AIF3RX_LRCLK_INV                 0x0004  /* AIF3RX_LRCLK_INV */
+#define WM5100_AIF3RX_LRCLK_INV_MASK            0x0004  /* AIF3RX_LRCLK_INV */
+#define WM5100_AIF3RX_LRCLK_INV_SHIFT                2  /* AIF3RX_LRCLK_INV */
+#define WM5100_AIF3RX_LRCLK_INV_WIDTH                1  /* AIF3RX_LRCLK_INV */
+#define WM5100_AIF3RX_LRCLK_FRC                 0x0002  /* AIF3RX_LRCLK_FRC */
+#define WM5100_AIF3RX_LRCLK_FRC_MASK            0x0002  /* AIF3RX_LRCLK_FRC */
+#define WM5100_AIF3RX_LRCLK_FRC_SHIFT                1  /* AIF3RX_LRCLK_FRC */
+#define WM5100_AIF3RX_LRCLK_FRC_WIDTH                1  /* AIF3RX_LRCLK_FRC */
+#define WM5100_AIF3RX_LRCLK_MSTR                0x0001  /* AIF3RX_LRCLK_MSTR */
+#define WM5100_AIF3RX_LRCLK_MSTR_MASK           0x0001  /* AIF3RX_LRCLK_MSTR */
+#define WM5100_AIF3RX_LRCLK_MSTR_SHIFT               0  /* AIF3RX_LRCLK_MSTR */
+#define WM5100_AIF3RX_LRCLK_MSTR_WIDTH               1  /* AIF3RX_LRCLK_MSTR */
+
+/*
+ * R1411 (0x583) - Audio IF 3_4
+ */
+#define WM5100_AIF3_TRI                         0x0040  /* AIF3_TRI */
+#define WM5100_AIF3_TRI_MASK                    0x0040  /* AIF3_TRI */
+#define WM5100_AIF3_TRI_SHIFT                        6  /* AIF3_TRI */
+#define WM5100_AIF3_TRI_WIDTH                        1  /* AIF3_TRI */
+#define WM5100_AIF3_RATE_MASK                   0x0003  /* AIF3_RATE - [1:0] */
+#define WM5100_AIF3_RATE_SHIFT                       0  /* AIF3_RATE - [1:0] */
+#define WM5100_AIF3_RATE_WIDTH                       2  /* AIF3_RATE - [1:0] */
+
+/*
+ * R1412 (0x584) - Audio IF 3_5
+ */
+#define WM5100_AIF3_FMT_MASK                    0x0007  /* AIF3_FMT - [2:0] */
+#define WM5100_AIF3_FMT_SHIFT                        0  /* AIF3_FMT - [2:0] */
+#define WM5100_AIF3_FMT_WIDTH                        3  /* AIF3_FMT - [2:0] */
+
+/*
+ * R1413 (0x585) - Audio IF 3_6
+ */
+#define WM5100_AIF3TX_BCPF_MASK                 0x1FFF  /* AIF3TX_BCPF - [12:0] */
+#define WM5100_AIF3TX_BCPF_SHIFT                     0  /* AIF3TX_BCPF - [12:0] */
+#define WM5100_AIF3TX_BCPF_WIDTH                    13  /* AIF3TX_BCPF - [12:0] */
+
+/*
+ * R1414 (0x586) - Audio IF 3_7
+ */
+#define WM5100_AIF3RX_BCPF_MASK                 0x1FFF  /* AIF3RX_BCPF - [12:0] */
+#define WM5100_AIF3RX_BCPF_SHIFT                     0  /* AIF3RX_BCPF - [12:0] */
+#define WM5100_AIF3RX_BCPF_WIDTH                    13  /* AIF3RX_BCPF - [12:0] */
+
+/*
+ * R1415 (0x587) - Audio IF 3_8
+ */
+#define WM5100_AIF3TX_WL_MASK                   0x3F00  /* AIF3TX_WL - [13:8] */
+#define WM5100_AIF3TX_WL_SHIFT                       8  /* AIF3TX_WL - [13:8] */
+#define WM5100_AIF3TX_WL_WIDTH                       6  /* AIF3TX_WL - [13:8] */
+#define WM5100_AIF3TX_SLOT_LEN_MASK             0x00FF  /* AIF3TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF3TX_SLOT_LEN_SHIFT                 0  /* AIF3TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF3TX_SLOT_LEN_WIDTH                 8  /* AIF3TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1416 (0x588) - Audio IF 3_9
+ */
+#define WM5100_AIF3RX_WL_MASK                   0x3F00  /* AIF3RX_WL - [13:8] */
+#define WM5100_AIF3RX_WL_SHIFT                       8  /* AIF3RX_WL - [13:8] */
+#define WM5100_AIF3RX_WL_WIDTH                       6  /* AIF3RX_WL - [13:8] */
+#define WM5100_AIF3RX_SLOT_LEN_MASK             0x00FF  /* AIF3RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF3RX_SLOT_LEN_SHIFT                 0  /* AIF3RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF3RX_SLOT_LEN_WIDTH                 8  /* AIF3RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1417 (0x589) - Audio IF 3_10
+ */
+#define WM5100_AIF3TX1_SLOT_MASK                0x003F  /* AIF3TX1_SLOT - [5:0] */
+#define WM5100_AIF3TX1_SLOT_SHIFT                    0  /* AIF3TX1_SLOT - [5:0] */
+#define WM5100_AIF3TX1_SLOT_WIDTH                    6  /* AIF3TX1_SLOT - [5:0] */
+
+/*
+ * R1418 (0x58A) - Audio IF 3_11
+ */
+#define WM5100_AIF3TX2_SLOT_MASK                0x003F  /* AIF3TX2_SLOT - [5:0] */
+#define WM5100_AIF3TX2_SLOT_SHIFT                    0  /* AIF3TX2_SLOT - [5:0] */
+#define WM5100_AIF3TX2_SLOT_WIDTH                    6  /* AIF3TX2_SLOT - [5:0] */
+
+/*
+ * R1425 (0x591) - Audio IF 3_18
+ */
+#define WM5100_AIF3RX1_SLOT_MASK                0x003F  /* AIF3RX1_SLOT - [5:0] */
+#define WM5100_AIF3RX1_SLOT_SHIFT                    0  /* AIF3RX1_SLOT - [5:0] */
+#define WM5100_AIF3RX1_SLOT_WIDTH                    6  /* AIF3RX1_SLOT - [5:0] */
+
+/*
+ * R1426 (0x592) - Audio IF 3_19
+ */
+#define WM5100_AIF3RX2_SLOT_MASK                0x003F  /* AIF3RX2_SLOT - [5:0] */
+#define WM5100_AIF3RX2_SLOT_SHIFT                    0  /* AIF3RX2_SLOT - [5:0] */
+#define WM5100_AIF3RX2_SLOT_WIDTH                    6  /* AIF3RX2_SLOT - [5:0] */
+
+/*
+ * R1433 (0x599) - Audio IF 3_26
+ */
+#define WM5100_AIF3TX2_ENA                      0x0002  /* AIF3TX2_ENA */
+#define WM5100_AIF3TX2_ENA_MASK                 0x0002  /* AIF3TX2_ENA */
+#define WM5100_AIF3TX2_ENA_SHIFT                     1  /* AIF3TX2_ENA */
+#define WM5100_AIF3TX2_ENA_WIDTH                     1  /* AIF3TX2_ENA */
+#define WM5100_AIF3TX1_ENA                      0x0001  /* AIF3TX1_ENA */
+#define WM5100_AIF3TX1_ENA_MASK                 0x0001  /* AIF3TX1_ENA */
+#define WM5100_AIF3TX1_ENA_SHIFT                     0  /* AIF3TX1_ENA */
+#define WM5100_AIF3TX1_ENA_WIDTH                     1  /* AIF3TX1_ENA */
+
+/*
+ * R1434 (0x59A) - Audio IF 3_27
+ */
+#define WM5100_AIF3RX2_ENA                      0x0002  /* AIF3RX2_ENA */
+#define WM5100_AIF3RX2_ENA_MASK                 0x0002  /* AIF3RX2_ENA */
+#define WM5100_AIF3RX2_ENA_SHIFT                     1  /* AIF3RX2_ENA */
+#define WM5100_AIF3RX2_ENA_WIDTH                     1  /* AIF3RX2_ENA */
+#define WM5100_AIF3RX1_ENA                      0x0001  /* AIF3RX1_ENA */
+#define WM5100_AIF3RX1_ENA_MASK                 0x0001  /* AIF3RX1_ENA */
+#define WM5100_AIF3RX1_ENA_SHIFT                     0  /* AIF3RX1_ENA */
+#define WM5100_AIF3RX1_ENA_WIDTH                     1  /* AIF3RX1_ENA */
+
+#define WM5100_MIXER_VOL_MASK                0x00FE  /* MIXER_VOL - [7:1] */
+#define WM5100_MIXER_VOL_SHIFT                    1  /* MIXER_VOL - [7:1] */
+#define WM5100_MIXER_VOL_WIDTH                    7  /* MIXER_VOL - [7:1] */
+
+/*
+ * R3072 (0xC00) - GPIO CTRL 1
+ */
+#define WM5100_GP1_DIR                          0x8000  /* GP1_DIR */
+#define WM5100_GP1_DIR_MASK                     0x8000  /* GP1_DIR */
+#define WM5100_GP1_DIR_SHIFT                        15  /* GP1_DIR */
+#define WM5100_GP1_DIR_WIDTH                         1  /* GP1_DIR */
+#define WM5100_GP1_PU                           0x4000  /* GP1_PU */
+#define WM5100_GP1_PU_MASK                      0x4000  /* GP1_PU */
+#define WM5100_GP1_PU_SHIFT                         14  /* GP1_PU */
+#define WM5100_GP1_PU_WIDTH                          1  /* GP1_PU */
+#define WM5100_GP1_PD                           0x2000  /* GP1_PD */
+#define WM5100_GP1_PD_MASK                      0x2000  /* GP1_PD */
+#define WM5100_GP1_PD_SHIFT                         13  /* GP1_PD */
+#define WM5100_GP1_PD_WIDTH                          1  /* GP1_PD */
+#define WM5100_GP1_POL                          0x0400  /* GP1_POL */
+#define WM5100_GP1_POL_MASK                     0x0400  /* GP1_POL */
+#define WM5100_GP1_POL_SHIFT                        10  /* GP1_POL */
+#define WM5100_GP1_POL_WIDTH                         1  /* GP1_POL */
+#define WM5100_GP1_OP_CFG                       0x0200  /* GP1_OP_CFG */
+#define WM5100_GP1_OP_CFG_MASK                  0x0200  /* GP1_OP_CFG */
+#define WM5100_GP1_OP_CFG_SHIFT                      9  /* GP1_OP_CFG */
+#define WM5100_GP1_OP_CFG_WIDTH                      1  /* GP1_OP_CFG */
+#define WM5100_GP1_DB                           0x0100  /* GP1_DB */
+#define WM5100_GP1_DB_MASK                      0x0100  /* GP1_DB */
+#define WM5100_GP1_DB_SHIFT                          8  /* GP1_DB */
+#define WM5100_GP1_DB_WIDTH                          1  /* GP1_DB */
+#define WM5100_GP1_LVL                          0x0040  /* GP1_LVL */
+#define WM5100_GP1_LVL_MASK                     0x0040  /* GP1_LVL */
+#define WM5100_GP1_LVL_SHIFT                         6  /* GP1_LVL */
+#define WM5100_GP1_LVL_WIDTH                         1  /* GP1_LVL */
+#define WM5100_GP1_FN_MASK                      0x003F  /* GP1_FN - [5:0] */
+#define WM5100_GP1_FN_SHIFT                          0  /* GP1_FN - [5:0] */
+#define WM5100_GP1_FN_WIDTH                          6  /* GP1_FN - [5:0] */
+
+/*
+ * R3073 (0xC01) - GPIO CTRL 2
+ */
+#define WM5100_GP2_DIR                          0x8000  /* GP2_DIR */
+#define WM5100_GP2_DIR_MASK                     0x8000  /* GP2_DIR */
+#define WM5100_GP2_DIR_SHIFT                        15  /* GP2_DIR */
+#define WM5100_GP2_DIR_WIDTH                         1  /* GP2_DIR */
+#define WM5100_GP2_PU                           0x4000  /* GP2_PU */
+#define WM5100_GP2_PU_MASK                      0x4000  /* GP2_PU */
+#define WM5100_GP2_PU_SHIFT                         14  /* GP2_PU */
+#define WM5100_GP2_PU_WIDTH                          1  /* GP2_PU */
+#define WM5100_GP2_PD                           0x2000  /* GP2_PD */
+#define WM5100_GP2_PD_MASK                      0x2000  /* GP2_PD */
+#define WM5100_GP2_PD_SHIFT                         13  /* GP2_PD */
+#define WM5100_GP2_PD_WIDTH                          1  /* GP2_PD */
+#define WM5100_GP2_POL                          0x0400  /* GP2_POL */
+#define WM5100_GP2_POL_MASK                     0x0400  /* GP2_POL */
+#define WM5100_GP2_POL_SHIFT                        10  /* GP2_POL */
+#define WM5100_GP2_POL_WIDTH                         1  /* GP2_POL */
+#define WM5100_GP2_OP_CFG                       0x0200  /* GP2_OP_CFG */
+#define WM5100_GP2_OP_CFG_MASK                  0x0200  /* GP2_OP_CFG */
+#define WM5100_GP2_OP_CFG_SHIFT                      9  /* GP2_OP_CFG */
+#define WM5100_GP2_OP_CFG_WIDTH                      1  /* GP2_OP_CFG */
+#define WM5100_GP2_DB                           0x0100  /* GP2_DB */
+#define WM5100_GP2_DB_MASK                      0x0100  /* GP2_DB */
+#define WM5100_GP2_DB_SHIFT                          8  /* GP2_DB */
+#define WM5100_GP2_DB_WIDTH                          1  /* GP2_DB */
+#define WM5100_GP2_LVL                          0x0040  /* GP2_LVL */
+#define WM5100_GP2_LVL_MASK                     0x0040  /* GP2_LVL */
+#define WM5100_GP2_LVL_SHIFT                         6  /* GP2_LVL */
+#define WM5100_GP2_LVL_WIDTH                         1  /* GP2_LVL */
+#define WM5100_GP2_FN_MASK                      0x003F  /* GP2_FN - [5:0] */
+#define WM5100_GP2_FN_SHIFT                          0  /* GP2_FN - [5:0] */
+#define WM5100_GP2_FN_WIDTH                          6  /* GP2_FN - [5:0] */
+
+/*
+ * R3074 (0xC02) - GPIO CTRL 3
+ */
+#define WM5100_GP3_DIR                          0x8000  /* GP3_DIR */
+#define WM5100_GP3_DIR_MASK                     0x8000  /* GP3_DIR */
+#define WM5100_GP3_DIR_SHIFT                        15  /* GP3_DIR */
+#define WM5100_GP3_DIR_WIDTH                         1  /* GP3_DIR */
+#define WM5100_GP3_PU                           0x4000  /* GP3_PU */
+#define WM5100_GP3_PU_MASK                      0x4000  /* GP3_PU */
+#define WM5100_GP3_PU_SHIFT                         14  /* GP3_PU */
+#define WM5100_GP3_PU_WIDTH                          1  /* GP3_PU */
+#define WM5100_GP3_PD                           0x2000  /* GP3_PD */
+#define WM5100_GP3_PD_MASK                      0x2000  /* GP3_PD */
+#define WM5100_GP3_PD_SHIFT                         13  /* GP3_PD */
+#define WM5100_GP3_PD_WIDTH                          1  /* GP3_PD */
+#define WM5100_GP3_POL                          0x0400  /* GP3_POL */
+#define WM5100_GP3_POL_MASK                     0x0400  /* GP3_POL */
+#define WM5100_GP3_POL_SHIFT                        10  /* GP3_POL */
+#define WM5100_GP3_POL_WIDTH                         1  /* GP3_POL */
+#define WM5100_GP3_OP_CFG                       0x0200  /* GP3_OP_CFG */
+#define WM5100_GP3_OP_CFG_MASK                  0x0200  /* GP3_OP_CFG */
+#define WM5100_GP3_OP_CFG_SHIFT                      9  /* GP3_OP_CFG */
+#define WM5100_GP3_OP_CFG_WIDTH                      1  /* GP3_OP_CFG */
+#define WM5100_GP3_DB                           0x0100  /* GP3_DB */
+#define WM5100_GP3_DB_MASK                      0x0100  /* GP3_DB */
+#define WM5100_GP3_DB_SHIFT                          8  /* GP3_DB */
+#define WM5100_GP3_DB_WIDTH                          1  /* GP3_DB */
+#define WM5100_GP3_LVL                          0x0040  /* GP3_LVL */
+#define WM5100_GP3_LVL_MASK                     0x0040  /* GP3_LVL */
+#define WM5100_GP3_LVL_SHIFT                         6  /* GP3_LVL */
+#define WM5100_GP3_LVL_WIDTH                         1  /* GP3_LVL */
+#define WM5100_GP3_FN_MASK                      0x003F  /* GP3_FN - [5:0] */
+#define WM5100_GP3_FN_SHIFT                          0  /* GP3_FN - [5:0] */
+#define WM5100_GP3_FN_WIDTH                          6  /* GP3_FN - [5:0] */
+
+/*
+ * R3075 (0xC03) - GPIO CTRL 4
+ */
+#define WM5100_GP4_DIR                          0x8000  /* GP4_DIR */
+#define WM5100_GP4_DIR_MASK                     0x8000  /* GP4_DIR */
+#define WM5100_GP4_DIR_SHIFT                        15  /* GP4_DIR */
+#define WM5100_GP4_DIR_WIDTH                         1  /* GP4_DIR */
+#define WM5100_GP4_PU                           0x4000  /* GP4_PU */
+#define WM5100_GP4_PU_MASK                      0x4000  /* GP4_PU */
+#define WM5100_GP4_PU_SHIFT                         14  /* GP4_PU */
+#define WM5100_GP4_PU_WIDTH                          1  /* GP4_PU */
+#define WM5100_GP4_PD                           0x2000  /* GP4_PD */
+#define WM5100_GP4_PD_MASK                      0x2000  /* GP4_PD */
+#define WM5100_GP4_PD_SHIFT                         13  /* GP4_PD */
+#define WM5100_GP4_PD_WIDTH                          1  /* GP4_PD */
+#define WM5100_GP4_POL                          0x0400  /* GP4_POL */
+#define WM5100_GP4_POL_MASK                     0x0400  /* GP4_POL */
+#define WM5100_GP4_POL_SHIFT                        10  /* GP4_POL */
+#define WM5100_GP4_POL_WIDTH                         1  /* GP4_POL */
+#define WM5100_GP4_OP_CFG                       0x0200  /* GP4_OP_CFG */
+#define WM5100_GP4_OP_CFG_MASK                  0x0200  /* GP4_OP_CFG */
+#define WM5100_GP4_OP_CFG_SHIFT                      9  /* GP4_OP_CFG */
+#define WM5100_GP4_OP_CFG_WIDTH                      1  /* GP4_OP_CFG */
+#define WM5100_GP4_DB                           0x0100  /* GP4_DB */
+#define WM5100_GP4_DB_MASK                      0x0100  /* GP4_DB */
+#define WM5100_GP4_DB_SHIFT                          8  /* GP4_DB */
+#define WM5100_GP4_DB_WIDTH                          1  /* GP4_DB */
+#define WM5100_GP4_LVL                          0x0040  /* GP4_LVL */
+#define WM5100_GP4_LVL_MASK                     0x0040  /* GP4_LVL */
+#define WM5100_GP4_LVL_SHIFT                         6  /* GP4_LVL */
+#define WM5100_GP4_LVL_WIDTH                         1  /* GP4_LVL */
+#define WM5100_GP4_FN_MASK                      0x003F  /* GP4_FN - [5:0] */
+#define WM5100_GP4_FN_SHIFT                          0  /* GP4_FN - [5:0] */
+#define WM5100_GP4_FN_WIDTH                          6  /* GP4_FN - [5:0] */
+
+/*
+ * R3076 (0xC04) - GPIO CTRL 5
+ */
+#define WM5100_GP5_DIR                          0x8000  /* GP5_DIR */
+#define WM5100_GP5_DIR_MASK                     0x8000  /* GP5_DIR */
+#define WM5100_GP5_DIR_SHIFT                        15  /* GP5_DIR */
+#define WM5100_GP5_DIR_WIDTH                         1  /* GP5_DIR */
+#define WM5100_GP5_PU                           0x4000  /* GP5_PU */
+#define WM5100_GP5_PU_MASK                      0x4000  /* GP5_PU */
+#define WM5100_GP5_PU_SHIFT                         14  /* GP5_PU */
+#define WM5100_GP5_PU_WIDTH                          1  /* GP5_PU */
+#define WM5100_GP5_PD                           0x2000  /* GP5_PD */
+#define WM5100_GP5_PD_MASK                      0x2000  /* GP5_PD */
+#define WM5100_GP5_PD_SHIFT                         13  /* GP5_PD */
+#define WM5100_GP5_PD_WIDTH                          1  /* GP5_PD */
+#define WM5100_GP5_POL                          0x0400  /* GP5_POL */
+#define WM5100_GP5_POL_MASK                     0x0400  /* GP5_POL */
+#define WM5100_GP5_POL_SHIFT                        10  /* GP5_POL */
+#define WM5100_GP5_POL_WIDTH                         1  /* GP5_POL */
+#define WM5100_GP5_OP_CFG                       0x0200  /* GP5_OP_CFG */
+#define WM5100_GP5_OP_CFG_MASK                  0x0200  /* GP5_OP_CFG */
+#define WM5100_GP5_OP_CFG_SHIFT                      9  /* GP5_OP_CFG */
+#define WM5100_GP5_OP_CFG_WIDTH                      1  /* GP5_OP_CFG */
+#define WM5100_GP5_DB                           0x0100  /* GP5_DB */
+#define WM5100_GP5_DB_MASK                      0x0100  /* GP5_DB */
+#define WM5100_GP5_DB_SHIFT                          8  /* GP5_DB */
+#define WM5100_GP5_DB_WIDTH                          1  /* GP5_DB */
+#define WM5100_GP5_LVL                          0x0040  /* GP5_LVL */
+#define WM5100_GP5_LVL_MASK                     0x0040  /* GP5_LVL */
+#define WM5100_GP5_LVL_SHIFT                         6  /* GP5_LVL */
+#define WM5100_GP5_LVL_WIDTH                         1  /* GP5_LVL */
+#define WM5100_GP5_FN_MASK                      0x003F  /* GP5_FN - [5:0] */
+#define WM5100_GP5_FN_SHIFT                          0  /* GP5_FN - [5:0] */
+#define WM5100_GP5_FN_WIDTH                          6  /* GP5_FN - [5:0] */
+
+/*
+ * R3077 (0xC05) - GPIO CTRL 6
+ */
+#define WM5100_GP6_DIR                          0x8000  /* GP6_DIR */
+#define WM5100_GP6_DIR_MASK                     0x8000  /* GP6_DIR */
+#define WM5100_GP6_DIR_SHIFT                        15  /* GP6_DIR */
+#define WM5100_GP6_DIR_WIDTH                         1  /* GP6_DIR */
+#define WM5100_GP6_PU                           0x4000  /* GP6_PU */
+#define WM5100_GP6_PU_MASK                      0x4000  /* GP6_PU */
+#define WM5100_GP6_PU_SHIFT                         14  /* GP6_PU */
+#define WM5100_GP6_PU_WIDTH                          1  /* GP6_PU */
+#define WM5100_GP6_PD                           0x2000  /* GP6_PD */
+#define WM5100_GP6_PD_MASK                      0x2000  /* GP6_PD */
+#define WM5100_GP6_PD_SHIFT                         13  /* GP6_PD */
+#define WM5100_GP6_PD_WIDTH                          1  /* GP6_PD */
+#define WM5100_GP6_POL                          0x0400  /* GP6_POL */
+#define WM5100_GP6_POL_MASK                     0x0400  /* GP6_POL */
+#define WM5100_GP6_POL_SHIFT                        10  /* GP6_POL */
+#define WM5100_GP6_POL_WIDTH                         1  /* GP6_POL */
+#define WM5100_GP6_OP_CFG                       0x0200  /* GP6_OP_CFG */
+#define WM5100_GP6_OP_CFG_MASK                  0x0200  /* GP6_OP_CFG */
+#define WM5100_GP6_OP_CFG_SHIFT                      9  /* GP6_OP_CFG */
+#define WM5100_GP6_OP_CFG_WIDTH                      1  /* GP6_OP_CFG */
+#define WM5100_GP6_DB                           0x0100  /* GP6_DB */
+#define WM5100_GP6_DB_MASK                      0x0100  /* GP6_DB */
+#define WM5100_GP6_DB_SHIFT                          8  /* GP6_DB */
+#define WM5100_GP6_DB_WIDTH                          1  /* GP6_DB */
+#define WM5100_GP6_LVL                          0x0040  /* GP6_LVL */
+#define WM5100_GP6_LVL_MASK                     0x0040  /* GP6_LVL */
+#define WM5100_GP6_LVL_SHIFT                         6  /* GP6_LVL */
+#define WM5100_GP6_LVL_WIDTH                         1  /* GP6_LVL */
+#define WM5100_GP6_FN_MASK                      0x003F  /* GP6_FN - [5:0] */
+#define WM5100_GP6_FN_SHIFT                          0  /* GP6_FN - [5:0] */
+#define WM5100_GP6_FN_WIDTH                          6  /* GP6_FN - [5:0] */
+
+/*
+ * R3107 (0xC23) - Misc Pad Ctrl 1
+ */
+#define WM5100_LDO1ENA_PD                       0x8000  /* LDO1ENA_PD */
+#define WM5100_LDO1ENA_PD_MASK                  0x8000  /* LDO1ENA_PD */
+#define WM5100_LDO1ENA_PD_SHIFT                     15  /* LDO1ENA_PD */
+#define WM5100_LDO1ENA_PD_WIDTH                      1  /* LDO1ENA_PD */
+#define WM5100_MCLK2_PD                         0x2000  /* MCLK2_PD */
+#define WM5100_MCLK2_PD_MASK                    0x2000  /* MCLK2_PD */
+#define WM5100_MCLK2_PD_SHIFT                       13  /* MCLK2_PD */
+#define WM5100_MCLK2_PD_WIDTH                        1  /* MCLK2_PD */
+#define WM5100_MCLK1_PD                         0x1000  /* MCLK1_PD */
+#define WM5100_MCLK1_PD_MASK                    0x1000  /* MCLK1_PD */
+#define WM5100_MCLK1_PD_SHIFT                       12  /* MCLK1_PD */
+#define WM5100_MCLK1_PD_WIDTH                        1  /* MCLK1_PD */
+#define WM5100_RESET_PU                         0x0002  /* RESET_PU */
+#define WM5100_RESET_PU_MASK                    0x0002  /* RESET_PU */
+#define WM5100_RESET_PU_SHIFT                        1  /* RESET_PU */
+#define WM5100_RESET_PU_WIDTH                        1  /* RESET_PU */
+#define WM5100_ADDR_PD                          0x0001  /* ADDR_PD */
+#define WM5100_ADDR_PD_MASK                     0x0001  /* ADDR_PD */
+#define WM5100_ADDR_PD_SHIFT                         0  /* ADDR_PD */
+#define WM5100_ADDR_PD_WIDTH                         1  /* ADDR_PD */
+
+/*
+ * R3108 (0xC24) - Misc Pad Ctrl 2
+ */
+#define WM5100_DMICDAT4_PD                      0x0008  /* DMICDAT4_PD */
+#define WM5100_DMICDAT4_PD_MASK                 0x0008  /* DMICDAT4_PD */
+#define WM5100_DMICDAT4_PD_SHIFT                     3  /* DMICDAT4_PD */
+#define WM5100_DMICDAT4_PD_WIDTH                     1  /* DMICDAT4_PD */
+#define WM5100_DMICDAT3_PD                      0x0004  /* DMICDAT3_PD */
+#define WM5100_DMICDAT3_PD_MASK                 0x0004  /* DMICDAT3_PD */
+#define WM5100_DMICDAT3_PD_SHIFT                     2  /* DMICDAT3_PD */
+#define WM5100_DMICDAT3_PD_WIDTH                     1  /* DMICDAT3_PD */
+#define WM5100_DMICDAT2_PD                      0x0002  /* DMICDAT2_PD */
+#define WM5100_DMICDAT2_PD_MASK                 0x0002  /* DMICDAT2_PD */
+#define WM5100_DMICDAT2_PD_SHIFT                     1  /* DMICDAT2_PD */
+#define WM5100_DMICDAT2_PD_WIDTH                     1  /* DMICDAT2_PD */
+#define WM5100_DMICDAT1_PD                      0x0001  /* DMICDAT1_PD */
+#define WM5100_DMICDAT1_PD_MASK                 0x0001  /* DMICDAT1_PD */
+#define WM5100_DMICDAT1_PD_SHIFT                     0  /* DMICDAT1_PD */
+#define WM5100_DMICDAT1_PD_WIDTH                     1  /* DMICDAT1_PD */
+
+/*
+ * R3109 (0xC25) - Misc Pad Ctrl 3
+ */
+#define WM5100_AIF1RXLRCLK_PU                   0x0020  /* AIF1RXLRCLK_PU */
+#define WM5100_AIF1RXLRCLK_PU_MASK              0x0020  /* AIF1RXLRCLK_PU */
+#define WM5100_AIF1RXLRCLK_PU_SHIFT                  5  /* AIF1RXLRCLK_PU */
+#define WM5100_AIF1RXLRCLK_PU_WIDTH                  1  /* AIF1RXLRCLK_PU */
+#define WM5100_AIF1RXLRCLK_PD                   0x0010  /* AIF1RXLRCLK_PD */
+#define WM5100_AIF1RXLRCLK_PD_MASK              0x0010  /* AIF1RXLRCLK_PD */
+#define WM5100_AIF1RXLRCLK_PD_SHIFT                  4  /* AIF1RXLRCLK_PD */
+#define WM5100_AIF1RXLRCLK_PD_WIDTH                  1  /* AIF1RXLRCLK_PD */
+#define WM5100_AIF1BCLK_PU                      0x0008  /* AIF1BCLK_PU */
+#define WM5100_AIF1BCLK_PU_MASK                 0x0008  /* AIF1BCLK_PU */
+#define WM5100_AIF1BCLK_PU_SHIFT                     3  /* AIF1BCLK_PU */
+#define WM5100_AIF1BCLK_PU_WIDTH                     1  /* AIF1BCLK_PU */
+#define WM5100_AIF1BCLK_PD                      0x0004  /* AIF1BCLK_PD */
+#define WM5100_AIF1BCLK_PD_MASK                 0x0004  /* AIF1BCLK_PD */
+#define WM5100_AIF1BCLK_PD_SHIFT                     2  /* AIF1BCLK_PD */
+#define WM5100_AIF1BCLK_PD_WIDTH                     1  /* AIF1BCLK_PD */
+#define WM5100_AIF1RXDAT_PU                     0x0002  /* AIF1RXDAT_PU */
+#define WM5100_AIF1RXDAT_PU_MASK                0x0002  /* AIF1RXDAT_PU */
+#define WM5100_AIF1RXDAT_PU_SHIFT                    1  /* AIF1RXDAT_PU */
+#define WM5100_AIF1RXDAT_PU_WIDTH                    1  /* AIF1RXDAT_PU */
+#define WM5100_AIF1RXDAT_PD                     0x0001  /* AIF1RXDAT_PD */
+#define WM5100_AIF1RXDAT_PD_MASK                0x0001  /* AIF1RXDAT_PD */
+#define WM5100_AIF1RXDAT_PD_SHIFT                    0  /* AIF1RXDAT_PD */
+#define WM5100_AIF1RXDAT_PD_WIDTH                    1  /* AIF1RXDAT_PD */
+
+/*
+ * R3110 (0xC26) - Misc Pad Ctrl 4
+ */
+#define WM5100_AIF2RXLRCLK_PU                   0x0020  /* AIF2RXLRCLK_PU */
+#define WM5100_AIF2RXLRCLK_PU_MASK              0x0020  /* AIF2RXLRCLK_PU */
+#define WM5100_AIF2RXLRCLK_PU_SHIFT                  5  /* AIF2RXLRCLK_PU */
+#define WM5100_AIF2RXLRCLK_PU_WIDTH                  1  /* AIF2RXLRCLK_PU */
+#define WM5100_AIF2RXLRCLK_PD                   0x0010  /* AIF2RXLRCLK_PD */
+#define WM5100_AIF2RXLRCLK_PD_MASK              0x0010  /* AIF2RXLRCLK_PD */
+#define WM5100_AIF2RXLRCLK_PD_SHIFT                  4  /* AIF2RXLRCLK_PD */
+#define WM5100_AIF2RXLRCLK_PD_WIDTH                  1  /* AIF2RXLRCLK_PD */
+#define WM5100_AIF2BCLK_PU                      0x0008  /* AIF2BCLK_PU */
+#define WM5100_AIF2BCLK_PU_MASK                 0x0008  /* AIF2BCLK_PU */
+#define WM5100_AIF2BCLK_PU_SHIFT                     3  /* AIF2BCLK_PU */
+#define WM5100_AIF2BCLK_PU_WIDTH                     1  /* AIF2BCLK_PU */
+#define WM5100_AIF2BCLK_PD                      0x0004  /* AIF2BCLK_PD */
+#define WM5100_AIF2BCLK_PD_MASK                 0x0004  /* AIF2BCLK_PD */
+#define WM5100_AIF2BCLK_PD_SHIFT                     2  /* AIF2BCLK_PD */
+#define WM5100_AIF2BCLK_PD_WIDTH                     1  /* AIF2BCLK_PD */
+#define WM5100_AIF2RXDAT_PU                     0x0002  /* AIF2RXDAT_PU */
+#define WM5100_AIF2RXDAT_PU_MASK                0x0002  /* AIF2RXDAT_PU */
+#define WM5100_AIF2RXDAT_PU_SHIFT                    1  /* AIF2RXDAT_PU */
+#define WM5100_AIF2RXDAT_PU_WIDTH                    1  /* AIF2RXDAT_PU */
+#define WM5100_AIF2RXDAT_PD                     0x0001  /* AIF2RXDAT_PD */
+#define WM5100_AIF2RXDAT_PD_MASK                0x0001  /* AIF2RXDAT_PD */
+#define WM5100_AIF2RXDAT_PD_SHIFT                    0  /* AIF2RXDAT_PD */
+#define WM5100_AIF2RXDAT_PD_WIDTH                    1  /* AIF2RXDAT_PD */
+
+/*
+ * R3111 (0xC27) - Misc Pad Ctrl 5
+ */
+#define WM5100_AIF3RXLRCLK_PU                   0x0020  /* AIF3RXLRCLK_PU */
+#define WM5100_AIF3RXLRCLK_PU_MASK              0x0020  /* AIF3RXLRCLK_PU */
+#define WM5100_AIF3RXLRCLK_PU_SHIFT                  5  /* AIF3RXLRCLK_PU */
+#define WM5100_AIF3RXLRCLK_PU_WIDTH                  1  /* AIF3RXLRCLK_PU */
+#define WM5100_AIF3RXLRCLK_PD                   0x0010  /* AIF3RXLRCLK_PD */
+#define WM5100_AIF3RXLRCLK_PD_MASK              0x0010  /* AIF3RXLRCLK_PD */
+#define WM5100_AIF3RXLRCLK_PD_SHIFT                  4  /* AIF3RXLRCLK_PD */
+#define WM5100_AIF3RXLRCLK_PD_WIDTH                  1  /* AIF3RXLRCLK_PD */
+#define WM5100_AIF3BCLK_PU                      0x0008  /* AIF3BCLK_PU */
+#define WM5100_AIF3BCLK_PU_MASK                 0x0008  /* AIF3BCLK_PU */
+#define WM5100_AIF3BCLK_PU_SHIFT                     3  /* AIF3BCLK_PU */
+#define WM5100_AIF3BCLK_PU_WIDTH                     1  /* AIF3BCLK_PU */
+#define WM5100_AIF3BCLK_PD                      0x0004  /* AIF3BCLK_PD */
+#define WM5100_AIF3BCLK_PD_MASK                 0x0004  /* AIF3BCLK_PD */
+#define WM5100_AIF3BCLK_PD_SHIFT                     2  /* AIF3BCLK_PD */
+#define WM5100_AIF3BCLK_PD_WIDTH                     1  /* AIF3BCLK_PD */
+#define WM5100_AIF3RXDAT_PU                     0x0002  /* AIF3RXDAT_PU */
+#define WM5100_AIF3RXDAT_PU_MASK                0x0002  /* AIF3RXDAT_PU */
+#define WM5100_AIF3RXDAT_PU_SHIFT                    1  /* AIF3RXDAT_PU */
+#define WM5100_AIF3RXDAT_PU_WIDTH                    1  /* AIF3RXDAT_PU */
+#define WM5100_AIF3RXDAT_PD                     0x0001  /* AIF3RXDAT_PD */
+#define WM5100_AIF3RXDAT_PD_MASK                0x0001  /* AIF3RXDAT_PD */
+#define WM5100_AIF3RXDAT_PD_SHIFT                    0  /* AIF3RXDAT_PD */
+#define WM5100_AIF3RXDAT_PD_WIDTH                    1  /* AIF3RXDAT_PD */
+
+/*
+ * R3112 (0xC28) - Misc GPIO 1
+ */
+#define WM5100_OPCLK_SEL_MASK                   0x0003  /* OPCLK_SEL - [1:0] */
+#define WM5100_OPCLK_SEL_SHIFT                       0  /* OPCLK_SEL - [1:0] */
+#define WM5100_OPCLK_SEL_WIDTH                       2  /* OPCLK_SEL - [1:0] */
+
+/*
+ * R3328 (0xD00) - Interrupt Status 1
+ */
+#define WM5100_GP6_EINT                         0x0020  /* GP6_EINT */
+#define WM5100_GP6_EINT_MASK                    0x0020  /* GP6_EINT */
+#define WM5100_GP6_EINT_SHIFT                        5  /* GP6_EINT */
+#define WM5100_GP6_EINT_WIDTH                        1  /* GP6_EINT */
+#define WM5100_GP5_EINT                         0x0010  /* GP5_EINT */
+#define WM5100_GP5_EINT_MASK                    0x0010  /* GP5_EINT */
+#define WM5100_GP5_EINT_SHIFT                        4  /* GP5_EINT */
+#define WM5100_GP5_EINT_WIDTH                        1  /* GP5_EINT */
+#define WM5100_GP4_EINT                         0x0008  /* GP4_EINT */
+#define WM5100_GP4_EINT_MASK                    0x0008  /* GP4_EINT */
+#define WM5100_GP4_EINT_SHIFT                        3  /* GP4_EINT */
+#define WM5100_GP4_EINT_WIDTH                        1  /* GP4_EINT */
+#define WM5100_GP3_EINT                         0x0004  /* GP3_EINT */
+#define WM5100_GP3_EINT_MASK                    0x0004  /* GP3_EINT */
+#define WM5100_GP3_EINT_SHIFT                        2  /* GP3_EINT */
+#define WM5100_GP3_EINT_WIDTH                        1  /* GP3_EINT */
+#define WM5100_GP2_EINT                         0x0002  /* GP2_EINT */
+#define WM5100_GP2_EINT_MASK                    0x0002  /* GP2_EINT */
+#define WM5100_GP2_EINT_SHIFT                        1  /* GP2_EINT */
+#define WM5100_GP2_EINT_WIDTH                        1  /* GP2_EINT */
+#define WM5100_GP1_EINT                         0x0001  /* GP1_EINT */
+#define WM5100_GP1_EINT_MASK                    0x0001  /* GP1_EINT */
+#define WM5100_GP1_EINT_SHIFT                        0  /* GP1_EINT */
+#define WM5100_GP1_EINT_WIDTH                        1  /* GP1_EINT */
+
+/*
+ * R3329 (0xD01) - Interrupt Status 2
+ */
+#define WM5100_DSP_IRQ6_EINT                    0x0020  /* DSP_IRQ6_EINT */
+#define WM5100_DSP_IRQ6_EINT_MASK               0x0020  /* DSP_IRQ6_EINT */
+#define WM5100_DSP_IRQ6_EINT_SHIFT                   5  /* DSP_IRQ6_EINT */
+#define WM5100_DSP_IRQ6_EINT_WIDTH                   1  /* DSP_IRQ6_EINT */
+#define WM5100_DSP_IRQ5_EINT                    0x0010  /* DSP_IRQ5_EINT */
+#define WM5100_DSP_IRQ5_EINT_MASK               0x0010  /* DSP_IRQ5_EINT */
+#define WM5100_DSP_IRQ5_EINT_SHIFT                   4  /* DSP_IRQ5_EINT */
+#define WM5100_DSP_IRQ5_EINT_WIDTH                   1  /* DSP_IRQ5_EINT */
+#define WM5100_DSP_IRQ4_EINT                    0x0008  /* DSP_IRQ4_EINT */
+#define WM5100_DSP_IRQ4_EINT_MASK               0x0008  /* DSP_IRQ4_EINT */
+#define WM5100_DSP_IRQ4_EINT_SHIFT                   3  /* DSP_IRQ4_EINT */
+#define WM5100_DSP_IRQ4_EINT_WIDTH                   1  /* DSP_IRQ4_EINT */
+#define WM5100_DSP_IRQ3_EINT                    0x0004  /* DSP_IRQ3_EINT */
+#define WM5100_DSP_IRQ3_EINT_MASK               0x0004  /* DSP_IRQ3_EINT */
+#define WM5100_DSP_IRQ3_EINT_SHIFT                   2  /* DSP_IRQ3_EINT */
+#define WM5100_DSP_IRQ3_EINT_WIDTH                   1  /* DSP_IRQ3_EINT */
+#define WM5100_DSP_IRQ2_EINT                    0x0002  /* DSP_IRQ2_EINT */
+#define WM5100_DSP_IRQ2_EINT_MASK               0x0002  /* DSP_IRQ2_EINT */
+#define WM5100_DSP_IRQ2_EINT_SHIFT                   1  /* DSP_IRQ2_EINT */
+#define WM5100_DSP_IRQ2_EINT_WIDTH                   1  /* DSP_IRQ2_EINT */
+#define WM5100_DSP_IRQ1_EINT                    0x0001  /* DSP_IRQ1_EINT */
+#define WM5100_DSP_IRQ1_EINT_MASK               0x0001  /* DSP_IRQ1_EINT */
+#define WM5100_DSP_IRQ1_EINT_SHIFT                   0  /* DSP_IRQ1_EINT */
+#define WM5100_DSP_IRQ1_EINT_WIDTH                   1  /* DSP_IRQ1_EINT */
+
+/*
+ * R3330 (0xD02) - Interrupt Status 3
+ */
+#define WM5100_SPK_SHUTDOWN_WARN_EINT           0x8000  /* SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_SPK_SHUTDOWN_WARN_EINT_MASK      0x8000  /* SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_SPK_SHUTDOWN_WARN_EINT_SHIFT         15  /* SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_SPK_SHUTDOWN_WARN_EINT_WIDTH          1  /* SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_SPK_SHUTDOWN_EINT                0x4000  /* SPK_SHUTDOWN_EINT */
+#define WM5100_SPK_SHUTDOWN_EINT_MASK           0x4000  /* SPK_SHUTDOWN_EINT */
+#define WM5100_SPK_SHUTDOWN_EINT_SHIFT              14  /* SPK_SHUTDOWN_EINT */
+#define WM5100_SPK_SHUTDOWN_EINT_WIDTH               1  /* SPK_SHUTDOWN_EINT */
+#define WM5100_HPDET_EINT                       0x2000  /* HPDET_EINT */
+#define WM5100_HPDET_EINT_MASK                  0x2000  /* HPDET_EINT */
+#define WM5100_HPDET_EINT_SHIFT                     13  /* HPDET_EINT */
+#define WM5100_HPDET_EINT_WIDTH                      1  /* HPDET_EINT */
+#define WM5100_ACCDET_EINT                      0x1000  /* ACCDET_EINT */
+#define WM5100_ACCDET_EINT_MASK                 0x1000  /* ACCDET_EINT */
+#define WM5100_ACCDET_EINT_SHIFT                    12  /* ACCDET_EINT */
+#define WM5100_ACCDET_EINT_WIDTH                     1  /* ACCDET_EINT */
+#define WM5100_DRC_SIG_DET_EINT                 0x0200  /* DRC_SIG_DET_EINT */
+#define WM5100_DRC_SIG_DET_EINT_MASK            0x0200  /* DRC_SIG_DET_EINT */
+#define WM5100_DRC_SIG_DET_EINT_SHIFT                9  /* DRC_SIG_DET_EINT */
+#define WM5100_DRC_SIG_DET_EINT_WIDTH                1  /* DRC_SIG_DET_EINT */
+#define WM5100_ASRC2_LOCK_EINT                  0x0100  /* ASRC2_LOCK_EINT */
+#define WM5100_ASRC2_LOCK_EINT_MASK             0x0100  /* ASRC2_LOCK_EINT */
+#define WM5100_ASRC2_LOCK_EINT_SHIFT                 8  /* ASRC2_LOCK_EINT */
+#define WM5100_ASRC2_LOCK_EINT_WIDTH                 1  /* ASRC2_LOCK_EINT */
+#define WM5100_ASRC1_LOCK_EINT                  0x0080  /* ASRC1_LOCK_EINT */
+#define WM5100_ASRC1_LOCK_EINT_MASK             0x0080  /* ASRC1_LOCK_EINT */
+#define WM5100_ASRC1_LOCK_EINT_SHIFT                 7  /* ASRC1_LOCK_EINT */
+#define WM5100_ASRC1_LOCK_EINT_WIDTH                 1  /* ASRC1_LOCK_EINT */
+#define WM5100_FLL2_LOCK_EINT                   0x0008  /* FLL2_LOCK_EINT */
+#define WM5100_FLL2_LOCK_EINT_MASK              0x0008  /* FLL2_LOCK_EINT */
+#define WM5100_FLL2_LOCK_EINT_SHIFT                  3  /* FLL2_LOCK_EINT */
+#define WM5100_FLL2_LOCK_EINT_WIDTH                  1  /* FLL2_LOCK_EINT */
+#define WM5100_FLL1_LOCK_EINT                   0x0004  /* FLL1_LOCK_EINT */
+#define WM5100_FLL1_LOCK_EINT_MASK              0x0004  /* FLL1_LOCK_EINT */
+#define WM5100_FLL1_LOCK_EINT_SHIFT                  2  /* FLL1_LOCK_EINT */
+#define WM5100_FLL1_LOCK_EINT_WIDTH                  1  /* FLL1_LOCK_EINT */
+#define WM5100_CLKGEN_ERR_EINT                  0x0002  /* CLKGEN_ERR_EINT */
+#define WM5100_CLKGEN_ERR_EINT_MASK             0x0002  /* CLKGEN_ERR_EINT */
+#define WM5100_CLKGEN_ERR_EINT_SHIFT                 1  /* CLKGEN_ERR_EINT */
+#define WM5100_CLKGEN_ERR_EINT_WIDTH                 1  /* CLKGEN_ERR_EINT */
+#define WM5100_CLKGEN_ERR_ASYNC_EINT            0x0001  /* CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_CLKGEN_ERR_ASYNC_EINT_MASK       0x0001  /* CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_CLKGEN_ERR_ASYNC_EINT_SHIFT           0  /* CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_CLKGEN_ERR_ASYNC_EINT_WIDTH           1  /* CLKGEN_ERR_ASYNC_EINT */
+
+/*
+ * R3331 (0xD03) - Interrupt Status 4
+ */
+#define WM5100_AIF3_ERR_EINT                    0x2000  /* AIF3_ERR_EINT */
+#define WM5100_AIF3_ERR_EINT_MASK               0x2000  /* AIF3_ERR_EINT */
+#define WM5100_AIF3_ERR_EINT_SHIFT                  13  /* AIF3_ERR_EINT */
+#define WM5100_AIF3_ERR_EINT_WIDTH                   1  /* AIF3_ERR_EINT */
+#define WM5100_AIF2_ERR_EINT                    0x1000  /* AIF2_ERR_EINT */
+#define WM5100_AIF2_ERR_EINT_MASK               0x1000  /* AIF2_ERR_EINT */
+#define WM5100_AIF2_ERR_EINT_SHIFT                  12  /* AIF2_ERR_EINT */
+#define WM5100_AIF2_ERR_EINT_WIDTH                   1  /* AIF2_ERR_EINT */
+#define WM5100_AIF1_ERR_EINT                    0x0800  /* AIF1_ERR_EINT */
+#define WM5100_AIF1_ERR_EINT_MASK               0x0800  /* AIF1_ERR_EINT */
+#define WM5100_AIF1_ERR_EINT_SHIFT                  11  /* AIF1_ERR_EINT */
+#define WM5100_AIF1_ERR_EINT_WIDTH                   1  /* AIF1_ERR_EINT */
+#define WM5100_CTRLIF_ERR_EINT                  0x0400  /* CTRLIF_ERR_EINT */
+#define WM5100_CTRLIF_ERR_EINT_MASK             0x0400  /* CTRLIF_ERR_EINT */
+#define WM5100_CTRLIF_ERR_EINT_SHIFT                10  /* CTRLIF_ERR_EINT */
+#define WM5100_CTRLIF_ERR_EINT_WIDTH                 1  /* CTRLIF_ERR_EINT */
+#define WM5100_ISRC2_UNDERCLOCKED_EINT          0x0200  /* ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_ISRC2_UNDERCLOCKED_EINT_MASK     0x0200  /* ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_ISRC2_UNDERCLOCKED_EINT_SHIFT         9  /* ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_ISRC2_UNDERCLOCKED_EINT_WIDTH         1  /* ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_ISRC1_UNDERCLOCKED_EINT          0x0100  /* ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_ISRC1_UNDERCLOCKED_EINT_MASK     0x0100  /* ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_ISRC1_UNDERCLOCKED_EINT_SHIFT         8  /* ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_ISRC1_UNDERCLOCKED_EINT_WIDTH         1  /* ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_FX_UNDERCLOCKED_EINT             0x0080  /* FX_UNDERCLOCKED_EINT */
+#define WM5100_FX_UNDERCLOCKED_EINT_MASK        0x0080  /* FX_UNDERCLOCKED_EINT */
+#define WM5100_FX_UNDERCLOCKED_EINT_SHIFT            7  /* FX_UNDERCLOCKED_EINT */
+#define WM5100_FX_UNDERCLOCKED_EINT_WIDTH            1  /* FX_UNDERCLOCKED_EINT */
+#define WM5100_AIF3_UNDERCLOCKED_EINT           0x0040  /* AIF3_UNDERCLOCKED_EINT */
+#define WM5100_AIF3_UNDERCLOCKED_EINT_MASK      0x0040  /* AIF3_UNDERCLOCKED_EINT */
+#define WM5100_AIF3_UNDERCLOCKED_EINT_SHIFT          6  /* AIF3_UNDERCLOCKED_EINT */
+#define WM5100_AIF3_UNDERCLOCKED_EINT_WIDTH          1  /* AIF3_UNDERCLOCKED_EINT */
+#define WM5100_AIF2_UNDERCLOCKED_EINT           0x0020  /* AIF2_UNDERCLOCKED_EINT */
+#define WM5100_AIF2_UNDERCLOCKED_EINT_MASK      0x0020  /* AIF2_UNDERCLOCKED_EINT */
+#define WM5100_AIF2_UNDERCLOCKED_EINT_SHIFT          5  /* AIF2_UNDERCLOCKED_EINT */
+#define WM5100_AIF2_UNDERCLOCKED_EINT_WIDTH          1  /* AIF2_UNDERCLOCKED_EINT */
+#define WM5100_AIF1_UNDERCLOCKED_EINT           0x0010  /* AIF1_UNDERCLOCKED_EINT */
+#define WM5100_AIF1_UNDERCLOCKED_EINT_MASK      0x0010  /* AIF1_UNDERCLOCKED_EINT */
+#define WM5100_AIF1_UNDERCLOCKED_EINT_SHIFT          4  /* AIF1_UNDERCLOCKED_EINT */
+#define WM5100_AIF1_UNDERCLOCKED_EINT_WIDTH          1  /* AIF1_UNDERCLOCKED_EINT */
+#define WM5100_ASRC_UNDERCLOCKED_EINT           0x0008  /* ASRC_UNDERCLOCKED_EINT */
+#define WM5100_ASRC_UNDERCLOCKED_EINT_MASK      0x0008  /* ASRC_UNDERCLOCKED_EINT */
+#define WM5100_ASRC_UNDERCLOCKED_EINT_SHIFT          3  /* ASRC_UNDERCLOCKED_EINT */
+#define WM5100_ASRC_UNDERCLOCKED_EINT_WIDTH          1  /* ASRC_UNDERCLOCKED_EINT */
+#define WM5100_DAC_UNDERCLOCKED_EINT            0x0004  /* DAC_UNDERCLOCKED_EINT */
+#define WM5100_DAC_UNDERCLOCKED_EINT_MASK       0x0004  /* DAC_UNDERCLOCKED_EINT */
+#define WM5100_DAC_UNDERCLOCKED_EINT_SHIFT           2  /* DAC_UNDERCLOCKED_EINT */
+#define WM5100_DAC_UNDERCLOCKED_EINT_WIDTH           1  /* DAC_UNDERCLOCKED_EINT */
+#define WM5100_ADC_UNDERCLOCKED_EINT            0x0002  /* ADC_UNDERCLOCKED_EINT */
+#define WM5100_ADC_UNDERCLOCKED_EINT_MASK       0x0002  /* ADC_UNDERCLOCKED_EINT */
+#define WM5100_ADC_UNDERCLOCKED_EINT_SHIFT           1  /* ADC_UNDERCLOCKED_EINT */
+#define WM5100_ADC_UNDERCLOCKED_EINT_WIDTH           1  /* ADC_UNDERCLOCKED_EINT */
+#define WM5100_MIXER_UNDERCLOCKED_EINT          0x0001  /* MIXER_UNDERCLOCKED_EINT */
+#define WM5100_MIXER_UNDERCLOCKED_EINT_MASK     0x0001  /* MIXER_UNDERCLOCKED_EINT */
+#define WM5100_MIXER_UNDERCLOCKED_EINT_SHIFT         0  /* MIXER_UNDERCLOCKED_EINT */
+#define WM5100_MIXER_UNDERCLOCKED_EINT_WIDTH         1  /* MIXER_UNDERCLOCKED_EINT */
+
+/*
+ * R3332 (0xD04) - Interrupt Raw Status 2
+ */
+#define WM5100_DSP_IRQ6_STS                     0x0020  /* DSP_IRQ6_STS */
+#define WM5100_DSP_IRQ6_STS_MASK                0x0020  /* DSP_IRQ6_STS */
+#define WM5100_DSP_IRQ6_STS_SHIFT                    5  /* DSP_IRQ6_STS */
+#define WM5100_DSP_IRQ6_STS_WIDTH                    1  /* DSP_IRQ6_STS */
+#define WM5100_DSP_IRQ5_STS                     0x0010  /* DSP_IRQ5_STS */
+#define WM5100_DSP_IRQ5_STS_MASK                0x0010  /* DSP_IRQ5_STS */
+#define WM5100_DSP_IRQ5_STS_SHIFT                    4  /* DSP_IRQ5_STS */
+#define WM5100_DSP_IRQ5_STS_WIDTH                    1  /* DSP_IRQ5_STS */
+#define WM5100_DSP_IRQ4_STS                     0x0008  /* DSP_IRQ4_STS */
+#define WM5100_DSP_IRQ4_STS_MASK                0x0008  /* DSP_IRQ4_STS */
+#define WM5100_DSP_IRQ4_STS_SHIFT                    3  /* DSP_IRQ4_STS */
+#define WM5100_DSP_IRQ4_STS_WIDTH                    1  /* DSP_IRQ4_STS */
+#define WM5100_DSP_IRQ3_STS                     0x0004  /* DSP_IRQ3_STS */
+#define WM5100_DSP_IRQ3_STS_MASK                0x0004  /* DSP_IRQ3_STS */
+#define WM5100_DSP_IRQ3_STS_SHIFT                    2  /* DSP_IRQ3_STS */
+#define WM5100_DSP_IRQ3_STS_WIDTH                    1  /* DSP_IRQ3_STS */
+#define WM5100_DSP_IRQ2_STS                     0x0002  /* DSP_IRQ2_STS */
+#define WM5100_DSP_IRQ2_STS_MASK                0x0002  /* DSP_IRQ2_STS */
+#define WM5100_DSP_IRQ2_STS_SHIFT                    1  /* DSP_IRQ2_STS */
+#define WM5100_DSP_IRQ2_STS_WIDTH                    1  /* DSP_IRQ2_STS */
+#define WM5100_DSP_IRQ1_STS                     0x0001  /* DSP_IRQ1_STS */
+#define WM5100_DSP_IRQ1_STS_MASK                0x0001  /* DSP_IRQ1_STS */
+#define WM5100_DSP_IRQ1_STS_SHIFT                    0  /* DSP_IRQ1_STS */
+#define WM5100_DSP_IRQ1_STS_WIDTH                    1  /* DSP_IRQ1_STS */
+
+/*
+ * R3333 (0xD05) - Interrupt Raw Status 3
+ */
+#define WM5100_SPK_SHUTDOWN_WARN_STS            0x8000  /* SPK_SHUTDOWN_WARN_STS */
+#define WM5100_SPK_SHUTDOWN_WARN_STS_MASK       0x8000  /* SPK_SHUTDOWN_WARN_STS */
+#define WM5100_SPK_SHUTDOWN_WARN_STS_SHIFT          15  /* SPK_SHUTDOWN_WARN_STS */
+#define WM5100_SPK_SHUTDOWN_WARN_STS_WIDTH           1  /* SPK_SHUTDOWN_WARN_STS */
+#define WM5100_SPK_SHUTDOWN_STS                 0x4000  /* SPK_SHUTDOWN_STS */
+#define WM5100_SPK_SHUTDOWN_STS_MASK            0x4000  /* SPK_SHUTDOWN_STS */
+#define WM5100_SPK_SHUTDOWN_STS_SHIFT               14  /* SPK_SHUTDOWN_STS */
+#define WM5100_SPK_SHUTDOWN_STS_WIDTH                1  /* SPK_SHUTDOWN_STS */
+#define WM5100_HPDET_STS                        0x2000  /* HPDET_STS */
+#define WM5100_HPDET_STS_MASK                   0x2000  /* HPDET_STS */
+#define WM5100_HPDET_STS_SHIFT                      13  /* HPDET_STS */
+#define WM5100_HPDET_STS_WIDTH                       1  /* HPDET_STS */
+#define WM5100_DRC_SID_DET_STS                  0x0200  /* DRC_SID_DET_STS */
+#define WM5100_DRC_SID_DET_STS_MASK             0x0200  /* DRC_SID_DET_STS */
+#define WM5100_DRC_SID_DET_STS_SHIFT                 9  /* DRC_SID_DET_STS */
+#define WM5100_DRC_SID_DET_STS_WIDTH                 1  /* DRC_SID_DET_STS */
+#define WM5100_ASRC2_LOCK_STS                   0x0100  /* ASRC2_LOCK_STS */
+#define WM5100_ASRC2_LOCK_STS_MASK              0x0100  /* ASRC2_LOCK_STS */
+#define WM5100_ASRC2_LOCK_STS_SHIFT                  8  /* ASRC2_LOCK_STS */
+#define WM5100_ASRC2_LOCK_STS_WIDTH                  1  /* ASRC2_LOCK_STS */
+#define WM5100_ASRC1_LOCK_STS                   0x0080  /* ASRC1_LOCK_STS */
+#define WM5100_ASRC1_LOCK_STS_MASK              0x0080  /* ASRC1_LOCK_STS */
+#define WM5100_ASRC1_LOCK_STS_SHIFT                  7  /* ASRC1_LOCK_STS */
+#define WM5100_ASRC1_LOCK_STS_WIDTH                  1  /* ASRC1_LOCK_STS */
+#define WM5100_FLL2_LOCK_STS                    0x0008  /* FLL2_LOCK_STS */
+#define WM5100_FLL2_LOCK_STS_MASK               0x0008  /* FLL2_LOCK_STS */
+#define WM5100_FLL2_LOCK_STS_SHIFT                   3  /* FLL2_LOCK_STS */
+#define WM5100_FLL2_LOCK_STS_WIDTH                   1  /* FLL2_LOCK_STS */
+#define WM5100_FLL1_LOCK_STS                    0x0004  /* FLL1_LOCK_STS */
+#define WM5100_FLL1_LOCK_STS_MASK               0x0004  /* FLL1_LOCK_STS */
+#define WM5100_FLL1_LOCK_STS_SHIFT                   2  /* FLL1_LOCK_STS */
+#define WM5100_FLL1_LOCK_STS_WIDTH                   1  /* FLL1_LOCK_STS */
+#define WM5100_CLKGEN_ERR_STS                   0x0002  /* CLKGEN_ERR_STS */
+#define WM5100_CLKGEN_ERR_STS_MASK              0x0002  /* CLKGEN_ERR_STS */
+#define WM5100_CLKGEN_ERR_STS_SHIFT                  1  /* CLKGEN_ERR_STS */
+#define WM5100_CLKGEN_ERR_STS_WIDTH                  1  /* CLKGEN_ERR_STS */
+#define WM5100_CLKGEN_ERR_ASYNC_STS             0x0001  /* CLKGEN_ERR_ASYNC_STS */
+#define WM5100_CLKGEN_ERR_ASYNC_STS_MASK        0x0001  /* CLKGEN_ERR_ASYNC_STS */
+#define WM5100_CLKGEN_ERR_ASYNC_STS_SHIFT            0  /* CLKGEN_ERR_ASYNC_STS */
+#define WM5100_CLKGEN_ERR_ASYNC_STS_WIDTH            1  /* CLKGEN_ERR_ASYNC_STS */
+
+/*
+ * R3334 (0xD06) - Interrupt Raw Status 4
+ */
+#define WM5100_AIF3_ERR_STS                     0x2000  /* AIF3_ERR_STS */
+#define WM5100_AIF3_ERR_STS_MASK                0x2000  /* AIF3_ERR_STS */
+#define WM5100_AIF3_ERR_STS_SHIFT                   13  /* AIF3_ERR_STS */
+#define WM5100_AIF3_ERR_STS_WIDTH                    1  /* AIF3_ERR_STS */
+#define WM5100_AIF2_ERR_STS                     0x1000  /* AIF2_ERR_STS */
+#define WM5100_AIF2_ERR_STS_MASK                0x1000  /* AIF2_ERR_STS */
+#define WM5100_AIF2_ERR_STS_SHIFT                   12  /* AIF2_ERR_STS */
+#define WM5100_AIF2_ERR_STS_WIDTH                    1  /* AIF2_ERR_STS */
+#define WM5100_AIF1_ERR_STS                     0x0800  /* AIF1_ERR_STS */
+#define WM5100_AIF1_ERR_STS_MASK                0x0800  /* AIF1_ERR_STS */
+#define WM5100_AIF1_ERR_STS_SHIFT                   11  /* AIF1_ERR_STS */
+#define WM5100_AIF1_ERR_STS_WIDTH                    1  /* AIF1_ERR_STS */
+#define WM5100_CTRLIF_ERR_STS                   0x0400  /* CTRLIF_ERR_STS */
+#define WM5100_CTRLIF_ERR_STS_MASK              0x0400  /* CTRLIF_ERR_STS */
+#define WM5100_CTRLIF_ERR_STS_SHIFT                 10  /* CTRLIF_ERR_STS */
+#define WM5100_CTRLIF_ERR_STS_WIDTH                  1  /* CTRLIF_ERR_STS */
+#define WM5100_ISRC2_UNDERCLOCKED_STS           0x0200  /* ISRC2_UNDERCLOCKED_STS */
+#define WM5100_ISRC2_UNDERCLOCKED_STS_MASK      0x0200  /* ISRC2_UNDERCLOCKED_STS */
+#define WM5100_ISRC2_UNDERCLOCKED_STS_SHIFT          9  /* ISRC2_UNDERCLOCKED_STS */
+#define WM5100_ISRC2_UNDERCLOCKED_STS_WIDTH          1  /* ISRC2_UNDERCLOCKED_STS */
+#define WM5100_ISRC1_UNDERCLOCKED_STS           0x0100  /* ISRC1_UNDERCLOCKED_STS */
+#define WM5100_ISRC1_UNDERCLOCKED_STS_MASK      0x0100  /* ISRC1_UNDERCLOCKED_STS */
+#define WM5100_ISRC1_UNDERCLOCKED_STS_SHIFT          8  /* ISRC1_UNDERCLOCKED_STS */
+#define WM5100_ISRC1_UNDERCLOCKED_STS_WIDTH          1  /* ISRC1_UNDERCLOCKED_STS */
+#define WM5100_FX_UNDERCLOCKED_STS              0x0080  /* FX_UNDERCLOCKED_STS */
+#define WM5100_FX_UNDERCLOCKED_STS_MASK         0x0080  /* FX_UNDERCLOCKED_STS */
+#define WM5100_FX_UNDERCLOCKED_STS_SHIFT             7  /* FX_UNDERCLOCKED_STS */
+#define WM5100_FX_UNDERCLOCKED_STS_WIDTH             1  /* FX_UNDERCLOCKED_STS */
+#define WM5100_AIF3_UNDERCLOCKED_STS            0x0040  /* AIF3_UNDERCLOCKED_STS */
+#define WM5100_AIF3_UNDERCLOCKED_STS_MASK       0x0040  /* AIF3_UNDERCLOCKED_STS */
+#define WM5100_AIF3_UNDERCLOCKED_STS_SHIFT           6  /* AIF3_UNDERCLOCKED_STS */
+#define WM5100_AIF3_UNDERCLOCKED_STS_WIDTH           1  /* AIF3_UNDERCLOCKED_STS */
+#define WM5100_AIF2_UNDERCLOCKED_STS            0x0020  /* AIF2_UNDERCLOCKED_STS */
+#define WM5100_AIF2_UNDERCLOCKED_STS_MASK       0x0020  /* AIF2_UNDERCLOCKED_STS */
+#define WM5100_AIF2_UNDERCLOCKED_STS_SHIFT           5  /* AIF2_UNDERCLOCKED_STS */
+#define WM5100_AIF2_UNDERCLOCKED_STS_WIDTH           1  /* AIF2_UNDERCLOCKED_STS */
+#define WM5100_AIF1_UNDERCLOCKED_STS            0x0010  /* AIF1_UNDERCLOCKED_STS */
+#define WM5100_AIF1_UNDERCLOCKED_STS_MASK       0x0010  /* AIF1_UNDERCLOCKED_STS */
+#define WM5100_AIF1_UNDERCLOCKED_STS_SHIFT           4  /* AIF1_UNDERCLOCKED_STS */
+#define WM5100_AIF1_UNDERCLOCKED_STS_WIDTH           1  /* AIF1_UNDERCLOCKED_STS */
+#define WM5100_ASRC_UNDERCLOCKED_STS            0x0008  /* ASRC_UNDERCLOCKED_STS */
+#define WM5100_ASRC_UNDERCLOCKED_STS_MASK       0x0008  /* ASRC_UNDERCLOCKED_STS */
+#define WM5100_ASRC_UNDERCLOCKED_STS_SHIFT           3  /* ASRC_UNDERCLOCKED_STS */
+#define WM5100_ASRC_UNDERCLOCKED_STS_WIDTH           1  /* ASRC_UNDERCLOCKED_STS */
+#define WM5100_DAC_UNDERCLOCKED_STS             0x0004  /* DAC_UNDERCLOCKED_STS */
+#define WM5100_DAC_UNDERCLOCKED_STS_MASK        0x0004  /* DAC_UNDERCLOCKED_STS */
+#define WM5100_DAC_UNDERCLOCKED_STS_SHIFT            2  /* DAC_UNDERCLOCKED_STS */
+#define WM5100_DAC_UNDERCLOCKED_STS_WIDTH            1  /* DAC_UNDERCLOCKED_STS */
+#define WM5100_ADC_UNDERCLOCKED_STS             0x0002  /* ADC_UNDERCLOCKED_STS */
+#define WM5100_ADC_UNDERCLOCKED_STS_MASK        0x0002  /* ADC_UNDERCLOCKED_STS */
+#define WM5100_ADC_UNDERCLOCKED_STS_SHIFT            1  /* ADC_UNDERCLOCKED_STS */
+#define WM5100_ADC_UNDERCLOCKED_STS_WIDTH            1  /* ADC_UNDERCLOCKED_STS */
+#define WM5100_MIXER_UNDERCLOCKED_STS           0x0001  /* MIXER_UNDERCLOCKED_STS */
+#define WM5100_MIXER_UNDERCLOCKED_STS_MASK      0x0001  /* MIXER_UNDERCLOCKED_STS */
+#define WM5100_MIXER_UNDERCLOCKED_STS_SHIFT          0  /* MIXER_UNDERCLOCKED_STS */
+#define WM5100_MIXER_UNDERCLOCKED_STS_WIDTH          1  /* MIXER_UNDERCLOCKED_STS */
+
+/*
+ * R3335 (0xD07) - Interrupt Status 1 Mask
+ */
+#define WM5100_IM_GP6_EINT                      0x0020  /* IM_GP6_EINT */
+#define WM5100_IM_GP6_EINT_MASK                 0x0020  /* IM_GP6_EINT */
+#define WM5100_IM_GP6_EINT_SHIFT                     5  /* IM_GP6_EINT */
+#define WM5100_IM_GP6_EINT_WIDTH                     1  /* IM_GP6_EINT */
+#define WM5100_IM_GP5_EINT                      0x0010  /* IM_GP5_EINT */
+#define WM5100_IM_GP5_EINT_MASK                 0x0010  /* IM_GP5_EINT */
+#define WM5100_IM_GP5_EINT_SHIFT                     4  /* IM_GP5_EINT */
+#define WM5100_IM_GP5_EINT_WIDTH                     1  /* IM_GP5_EINT */
+#define WM5100_IM_GP4_EINT                      0x0008  /* IM_GP4_EINT */
+#define WM5100_IM_GP4_EINT_MASK                 0x0008  /* IM_GP4_EINT */
+#define WM5100_IM_GP4_EINT_SHIFT                     3  /* IM_GP4_EINT */
+#define WM5100_IM_GP4_EINT_WIDTH                     1  /* IM_GP4_EINT */
+#define WM5100_IM_GP3_EINT                      0x0004  /* IM_GP3_EINT */
+#define WM5100_IM_GP3_EINT_MASK                 0x0004  /* IM_GP3_EINT */
+#define WM5100_IM_GP3_EINT_SHIFT                     2  /* IM_GP3_EINT */
+#define WM5100_IM_GP3_EINT_WIDTH                     1  /* IM_GP3_EINT */
+#define WM5100_IM_GP2_EINT                      0x0002  /* IM_GP2_EINT */
+#define WM5100_IM_GP2_EINT_MASK                 0x0002  /* IM_GP2_EINT */
+#define WM5100_IM_GP2_EINT_SHIFT                     1  /* IM_GP2_EINT */
+#define WM5100_IM_GP2_EINT_WIDTH                     1  /* IM_GP2_EINT */
+#define WM5100_IM_GP1_EINT                      0x0001  /* IM_GP1_EINT */
+#define WM5100_IM_GP1_EINT_MASK                 0x0001  /* IM_GP1_EINT */
+#define WM5100_IM_GP1_EINT_SHIFT                     0  /* IM_GP1_EINT */
+#define WM5100_IM_GP1_EINT_WIDTH                     1  /* IM_GP1_EINT */
+
+/*
+ * R3336 (0xD08) - Interrupt Status 2 Mask
+ */
+#define WM5100_IM_DSP_IRQ6_EINT                 0x0020  /* IM_DSP_IRQ6_EINT */
+#define WM5100_IM_DSP_IRQ6_EINT_MASK            0x0020  /* IM_DSP_IRQ6_EINT */
+#define WM5100_IM_DSP_IRQ6_EINT_SHIFT                5  /* IM_DSP_IRQ6_EINT */
+#define WM5100_IM_DSP_IRQ6_EINT_WIDTH                1  /* IM_DSP_IRQ6_EINT */
+#define WM5100_IM_DSP_IRQ5_EINT                 0x0010  /* IM_DSP_IRQ5_EINT */
+#define WM5100_IM_DSP_IRQ5_EINT_MASK            0x0010  /* IM_DSP_IRQ5_EINT */
+#define WM5100_IM_DSP_IRQ5_EINT_SHIFT                4  /* IM_DSP_IRQ5_EINT */
+#define WM5100_IM_DSP_IRQ5_EINT_WIDTH                1  /* IM_DSP_IRQ5_EINT */
+#define WM5100_IM_DSP_IRQ4_EINT                 0x0008  /* IM_DSP_IRQ4_EINT */
+#define WM5100_IM_DSP_IRQ4_EINT_MASK            0x0008  /* IM_DSP_IRQ4_EINT */
+#define WM5100_IM_DSP_IRQ4_EINT_SHIFT                3  /* IM_DSP_IRQ4_EINT */
+#define WM5100_IM_DSP_IRQ4_EINT_WIDTH                1  /* IM_DSP_IRQ4_EINT */
+#define WM5100_IM_DSP_IRQ3_EINT                 0x0004  /* IM_DSP_IRQ3_EINT */
+#define WM5100_IM_DSP_IRQ3_EINT_MASK            0x0004  /* IM_DSP_IRQ3_EINT */
+#define WM5100_IM_DSP_IRQ3_EINT_SHIFT                2  /* IM_DSP_IRQ3_EINT */
+#define WM5100_IM_DSP_IRQ3_EINT_WIDTH                1  /* IM_DSP_IRQ3_EINT */
+#define WM5100_IM_DSP_IRQ2_EINT                 0x0002  /* IM_DSP_IRQ2_EINT */
+#define WM5100_IM_DSP_IRQ2_EINT_MASK            0x0002  /* IM_DSP_IRQ2_EINT */
+#define WM5100_IM_DSP_IRQ2_EINT_SHIFT                1  /* IM_DSP_IRQ2_EINT */
+#define WM5100_IM_DSP_IRQ2_EINT_WIDTH                1  /* IM_DSP_IRQ2_EINT */
+#define WM5100_IM_DSP_IRQ1_EINT                 0x0001  /* IM_DSP_IRQ1_EINT */
+#define WM5100_IM_DSP_IRQ1_EINT_MASK            0x0001  /* IM_DSP_IRQ1_EINT */
+#define WM5100_IM_DSP_IRQ1_EINT_SHIFT                0  /* IM_DSP_IRQ1_EINT */
+#define WM5100_IM_DSP_IRQ1_EINT_WIDTH                1  /* IM_DSP_IRQ1_EINT */
+
+/*
+ * R3337 (0xD09) - Interrupt Status 3 Mask
+ */
+#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT        0x8000  /* IM_SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_MASK   0x8000  /* IM_SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_SHIFT      15  /* IM_SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_WIDTH       1  /* IM_SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_EINT             0x4000  /* IM_SPK_SHUTDOWN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_EINT_MASK        0x4000  /* IM_SPK_SHUTDOWN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_EINT_SHIFT           14  /* IM_SPK_SHUTDOWN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_EINT_WIDTH            1  /* IM_SPK_SHUTDOWN_EINT */
+#define WM5100_IM_HPDET_EINT                    0x2000  /* IM_HPDET_EINT */
+#define WM5100_IM_HPDET_EINT_MASK               0x2000  /* IM_HPDET_EINT */
+#define WM5100_IM_HPDET_EINT_SHIFT                  13  /* IM_HPDET_EINT */
+#define WM5100_IM_HPDET_EINT_WIDTH                   1  /* IM_HPDET_EINT */
+#define WM5100_IM_ACCDET_EINT                   0x1000  /* IM_ACCDET_EINT */
+#define WM5100_IM_ACCDET_EINT_MASK              0x1000  /* IM_ACCDET_EINT */
+#define WM5100_IM_ACCDET_EINT_SHIFT                 12  /* IM_ACCDET_EINT */
+#define WM5100_IM_ACCDET_EINT_WIDTH                  1  /* IM_ACCDET_EINT */
+#define WM5100_IM_DRC_SIG_DET_EINT              0x0200  /* IM_DRC_SIG_DET_EINT */
+#define WM5100_IM_DRC_SIG_DET_EINT_MASK         0x0200  /* IM_DRC_SIG_DET_EINT */
+#define WM5100_IM_DRC_SIG_DET_EINT_SHIFT             9  /* IM_DRC_SIG_DET_EINT */
+#define WM5100_IM_DRC_SIG_DET_EINT_WIDTH             1  /* IM_DRC_SIG_DET_EINT */
+#define WM5100_IM_ASRC2_LOCK_EINT               0x0100  /* IM_ASRC2_LOCK_EINT */
+#define WM5100_IM_ASRC2_LOCK_EINT_MASK          0x0100  /* IM_ASRC2_LOCK_EINT */
+#define WM5100_IM_ASRC2_LOCK_EINT_SHIFT              8  /* IM_ASRC2_LOCK_EINT */
+#define WM5100_IM_ASRC2_LOCK_EINT_WIDTH              1  /* IM_ASRC2_LOCK_EINT */
+#define WM5100_IM_ASRC1_LOCK_EINT               0x0080  /* IM_ASRC1_LOCK_EINT */
+#define WM5100_IM_ASRC1_LOCK_EINT_MASK          0x0080  /* IM_ASRC1_LOCK_EINT */
+#define WM5100_IM_ASRC1_LOCK_EINT_SHIFT              7  /* IM_ASRC1_LOCK_EINT */
+#define WM5100_IM_ASRC1_LOCK_EINT_WIDTH              1  /* IM_ASRC1_LOCK_EINT */
+#define WM5100_IM_FLL2_LOCK_EINT                0x0008  /* IM_FLL2_LOCK_EINT */
+#define WM5100_IM_FLL2_LOCK_EINT_MASK           0x0008  /* IM_FLL2_LOCK_EINT */
+#define WM5100_IM_FLL2_LOCK_EINT_SHIFT               3  /* IM_FLL2_LOCK_EINT */
+#define WM5100_IM_FLL2_LOCK_EINT_WIDTH               1  /* IM_FLL2_LOCK_EINT */
+#define WM5100_IM_FLL1_LOCK_EINT                0x0004  /* IM_FLL1_LOCK_EINT */
+#define WM5100_IM_FLL1_LOCK_EINT_MASK           0x0004  /* IM_FLL1_LOCK_EINT */
+#define WM5100_IM_FLL1_LOCK_EINT_SHIFT               2  /* IM_FLL1_LOCK_EINT */
+#define WM5100_IM_FLL1_LOCK_EINT_WIDTH               1  /* IM_FLL1_LOCK_EINT */
+#define WM5100_IM_CLKGEN_ERR_EINT               0x0002  /* IM_CLKGEN_ERR_EINT */
+#define WM5100_IM_CLKGEN_ERR_EINT_MASK          0x0002  /* IM_CLKGEN_ERR_EINT */
+#define WM5100_IM_CLKGEN_ERR_EINT_SHIFT              1  /* IM_CLKGEN_ERR_EINT */
+#define WM5100_IM_CLKGEN_ERR_EINT_WIDTH              1  /* IM_CLKGEN_ERR_EINT */
+#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT         0x0001  /* IM_CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_MASK    0x0001  /* IM_CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_SHIFT        0  /* IM_CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_WIDTH        1  /* IM_CLKGEN_ERR_ASYNC_EINT */
+
+/*
+ * R3338 (0xD0A) - Interrupt Status 4 Mask
+ */
+#define WM5100_IM_AIF3_ERR_EINT                 0x2000  /* IM_AIF3_ERR_EINT */
+#define WM5100_IM_AIF3_ERR_EINT_MASK            0x2000  /* IM_AIF3_ERR_EINT */
+#define WM5100_IM_AIF3_ERR_EINT_SHIFT               13  /* IM_AIF3_ERR_EINT */
+#define WM5100_IM_AIF3_ERR_EINT_WIDTH                1  /* IM_AIF3_ERR_EINT */
+#define WM5100_IM_AIF2_ERR_EINT                 0x1000  /* IM_AIF2_ERR_EINT */
+#define WM5100_IM_AIF2_ERR_EINT_MASK            0x1000  /* IM_AIF2_ERR_EINT */
+#define WM5100_IM_AIF2_ERR_EINT_SHIFT               12  /* IM_AIF2_ERR_EINT */
+#define WM5100_IM_AIF2_ERR_EINT_WIDTH                1  /* IM_AIF2_ERR_EINT */
+#define WM5100_IM_AIF1_ERR_EINT                 0x0800  /* IM_AIF1_ERR_EINT */
+#define WM5100_IM_AIF1_ERR_EINT_MASK            0x0800  /* IM_AIF1_ERR_EINT */
+#define WM5100_IM_AIF1_ERR_EINT_SHIFT               11  /* IM_AIF1_ERR_EINT */
+#define WM5100_IM_AIF1_ERR_EINT_WIDTH                1  /* IM_AIF1_ERR_EINT */
+#define WM5100_IM_CTRLIF_ERR_EINT               0x0400  /* IM_CTRLIF_ERR_EINT */
+#define WM5100_IM_CTRLIF_ERR_EINT_MASK          0x0400  /* IM_CTRLIF_ERR_EINT */
+#define WM5100_IM_CTRLIF_ERR_EINT_SHIFT             10  /* IM_CTRLIF_ERR_EINT */
+#define WM5100_IM_CTRLIF_ERR_EINT_WIDTH              1  /* IM_CTRLIF_ERR_EINT */
+#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT       0x0200  /* IM_ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_MASK  0x0200  /* IM_ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_SHIFT      9  /* IM_ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_WIDTH      1  /* IM_ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT       0x0100  /* IM_ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_MASK  0x0100  /* IM_ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_SHIFT      8  /* IM_ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_WIDTH      1  /* IM_ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_IM_FX_UNDERCLOCKED_EINT          0x0080  /* IM_FX_UNDERCLOCKED_EINT */
+#define WM5100_IM_FX_UNDERCLOCKED_EINT_MASK     0x0080  /* IM_FX_UNDERCLOCKED_EINT */
+#define WM5100_IM_FX_UNDERCLOCKED_EINT_SHIFT         7  /* IM_FX_UNDERCLOCKED_EINT */
+#define WM5100_IM_FX_UNDERCLOCKED_EINT_WIDTH         1  /* IM_FX_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF3_UNDERCLOCKED_EINT        0x0040  /* IM_AIF3_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_MASK   0x0040  /* IM_AIF3_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_SHIFT       6  /* IM_AIF3_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_WIDTH       1  /* IM_AIF3_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF2_UNDERCLOCKED_EINT        0x0020  /* IM_AIF2_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_MASK   0x0020  /* IM_AIF2_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_SHIFT       5  /* IM_AIF2_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_WIDTH       1  /* IM_AIF2_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF1_UNDERCLOCKED_EINT        0x0010  /* IM_AIF1_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_MASK   0x0010  /* IM_AIF1_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_SHIFT       4  /* IM_AIF1_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_WIDTH       1  /* IM_AIF1_UNDERCLOCKED_EINT */
+#define WM5100_IM_ASRC_UNDERCLOCKED_EINT        0x0008  /* IM_ASRC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_MASK   0x0008  /* IM_ASRC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_SHIFT       3  /* IM_ASRC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_WIDTH       1  /* IM_ASRC_UNDERCLOCKED_EINT */
+#define WM5100_IM_DAC_UNDERCLOCKED_EINT         0x0004  /* IM_DAC_UNDERCLOCKED_EINT */
+#define WM5100_IM_DAC_UNDERCLOCKED_EINT_MASK    0x0004  /* IM_DAC_UNDERCLOCKED_EINT */
+#define WM5100_IM_DAC_UNDERCLOCKED_EINT_SHIFT        2  /* IM_DAC_UNDERCLOCKED_EINT */
+#define WM5100_IM_DAC_UNDERCLOCKED_EINT_WIDTH        1  /* IM_DAC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ADC_UNDERCLOCKED_EINT         0x0002  /* IM_ADC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ADC_UNDERCLOCKED_EINT_MASK    0x0002  /* IM_ADC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ADC_UNDERCLOCKED_EINT_SHIFT        1  /* IM_ADC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ADC_UNDERCLOCKED_EINT_WIDTH        1  /* IM_ADC_UNDERCLOCKED_EINT */
+#define WM5100_IM_MIXER_UNDERCLOCKED_EINT       0x0001  /* IM_MIXER_UNDERCLOCKED_EINT */
+#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_MASK  0x0001  /* IM_MIXER_UNDERCLOCKED_EINT */
+#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_SHIFT      0  /* IM_MIXER_UNDERCLOCKED_EINT */
+#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_WIDTH      1  /* IM_MIXER_UNDERCLOCKED_EINT */
+
+/*
+ * R3359 (0xD1F) - Interrupt Control
+ */
+#define WM5100_IM_IRQ                           0x0001  /* IM_IRQ */
+#define WM5100_IM_IRQ_MASK                      0x0001  /* IM_IRQ */
+#define WM5100_IM_IRQ_SHIFT                          0  /* IM_IRQ */
+#define WM5100_IM_IRQ_WIDTH                          1  /* IM_IRQ */
+
+/*
+ * R3360 (0xD20) - IRQ Debounce 1
+ */
+#define WM5100_SPK_SHUTDOWN_WARN_DB             0x0200  /* SPK_SHUTDOWN_WARN_DB */
+#define WM5100_SPK_SHUTDOWN_WARN_DB_MASK        0x0200  /* SPK_SHUTDOWN_WARN_DB */
+#define WM5100_SPK_SHUTDOWN_WARN_DB_SHIFT            9  /* SPK_SHUTDOWN_WARN_DB */
+#define WM5100_SPK_SHUTDOWN_WARN_DB_WIDTH            1  /* SPK_SHUTDOWN_WARN_DB */
+#define WM5100_SPK_SHUTDOWN_DB                  0x0100  /* SPK_SHUTDOWN_DB */
+#define WM5100_SPK_SHUTDOWN_DB_MASK             0x0100  /* SPK_SHUTDOWN_DB */
+#define WM5100_SPK_SHUTDOWN_DB_SHIFT                 8  /* SPK_SHUTDOWN_DB */
+#define WM5100_SPK_SHUTDOWN_DB_WIDTH                 1  /* SPK_SHUTDOWN_DB */
+#define WM5100_FLL1_LOCK_IRQ_DB                 0x0008  /* FLL1_LOCK_IRQ_DB */
+#define WM5100_FLL1_LOCK_IRQ_DB_MASK            0x0008  /* FLL1_LOCK_IRQ_DB */
+#define WM5100_FLL1_LOCK_IRQ_DB_SHIFT                3  /* FLL1_LOCK_IRQ_DB */
+#define WM5100_FLL1_LOCK_IRQ_DB_WIDTH                1  /* FLL1_LOCK_IRQ_DB */
+#define WM5100_FLL2_LOCK_IRQ_DB                 0x0004  /* FLL2_LOCK_IRQ_DB */
+#define WM5100_FLL2_LOCK_IRQ_DB_MASK            0x0004  /* FLL2_LOCK_IRQ_DB */
+#define WM5100_FLL2_LOCK_IRQ_DB_SHIFT                2  /* FLL2_LOCK_IRQ_DB */
+#define WM5100_FLL2_LOCK_IRQ_DB_WIDTH                1  /* FLL2_LOCK_IRQ_DB */
+#define WM5100_CLKGEN_ERR_IRQ_DB                0x0002  /* CLKGEN_ERR_IRQ_DB */
+#define WM5100_CLKGEN_ERR_IRQ_DB_MASK           0x0002  /* CLKGEN_ERR_IRQ_DB */
+#define WM5100_CLKGEN_ERR_IRQ_DB_SHIFT               1  /* CLKGEN_ERR_IRQ_DB */
+#define WM5100_CLKGEN_ERR_IRQ_DB_WIDTH               1  /* CLKGEN_ERR_IRQ_DB */
+#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB          0x0001  /* CLKGEN_ERR_ASYNC_IRQ_DB */
+#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_MASK     0x0001  /* CLKGEN_ERR_ASYNC_IRQ_DB */
+#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_SHIFT         0  /* CLKGEN_ERR_ASYNC_IRQ_DB */
+#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_WIDTH         1  /* CLKGEN_ERR_ASYNC_IRQ_DB */
+
+/*
+ * R3361 (0xD21) - IRQ Debounce 2
+ */
+#define WM5100_AIF_ERR_DB                       0x0001  /* AIF_ERR_DB */
+#define WM5100_AIF_ERR_DB_MASK                  0x0001  /* AIF_ERR_DB */
+#define WM5100_AIF_ERR_DB_SHIFT                      0  /* AIF_ERR_DB */
+#define WM5100_AIF_ERR_DB_WIDTH                      1  /* AIF_ERR_DB */
+
+/*
+ * R3584 (0xE00) - FX_Ctrl
+ */
+#define WM5100_FX_STS_MASK                      0xFFC0  /* FX_STS - [15:6] */
+#define WM5100_FX_STS_SHIFT                          6  /* FX_STS - [15:6] */
+#define WM5100_FX_STS_WIDTH                         10  /* FX_STS - [15:6] */
+#define WM5100_FX_RATE_MASK                     0x0003  /* FX_RATE - [1:0] */
+#define WM5100_FX_RATE_SHIFT                         0  /* FX_RATE - [1:0] */
+#define WM5100_FX_RATE_WIDTH                         2  /* FX_RATE - [1:0] */
+
+/*
+ * R3600 (0xE10) - EQ1_1
+ */
+#define WM5100_EQ1_B1_GAIN_MASK                 0xF800  /* EQ1_B1_GAIN - [15:11] */
+#define WM5100_EQ1_B1_GAIN_SHIFT                    11  /* EQ1_B1_GAIN - [15:11] */
+#define WM5100_EQ1_B1_GAIN_WIDTH                     5  /* EQ1_B1_GAIN - [15:11] */
+#define WM5100_EQ1_B2_GAIN_MASK                 0x07C0  /* EQ1_B2_GAIN - [10:6] */
+#define WM5100_EQ1_B2_GAIN_SHIFT                     6  /* EQ1_B2_GAIN - [10:6] */
+#define WM5100_EQ1_B2_GAIN_WIDTH                     5  /* EQ1_B2_GAIN - [10:6] */
+#define WM5100_EQ1_B3_GAIN_MASK                 0x003E  /* EQ1_B3_GAIN - [5:1] */
+#define WM5100_EQ1_B3_GAIN_SHIFT                     1  /* EQ1_B3_GAIN - [5:1] */
+#define WM5100_EQ1_B3_GAIN_WIDTH                     5  /* EQ1_B3_GAIN - [5:1] */
+#define WM5100_EQ1_ENA                          0x0001  /* EQ1_ENA */
+#define WM5100_EQ1_ENA_MASK                     0x0001  /* EQ1_ENA */
+#define WM5100_EQ1_ENA_SHIFT                         0  /* EQ1_ENA */
+#define WM5100_EQ1_ENA_WIDTH                         1  /* EQ1_ENA */
+
+/*
+ * R3601 (0xE11) - EQ1_2
+ */
+#define WM5100_EQ1_B4_GAIN_MASK                 0xF800  /* EQ1_B4_GAIN - [15:11] */
+#define WM5100_EQ1_B4_GAIN_SHIFT                    11  /* EQ1_B4_GAIN - [15:11] */
+#define WM5100_EQ1_B4_GAIN_WIDTH                     5  /* EQ1_B4_GAIN - [15:11] */
+#define WM5100_EQ1_B5_GAIN_MASK                 0x07C0  /* EQ1_B5_GAIN - [10:6] */
+#define WM5100_EQ1_B5_GAIN_SHIFT                     6  /* EQ1_B5_GAIN - [10:6] */
+#define WM5100_EQ1_B5_GAIN_WIDTH                     5  /* EQ1_B5_GAIN - [10:6] */
+
+/*
+ * R3602 (0xE12) - EQ1_3
+ */
+#define WM5100_EQ1_B1_A_MASK                    0xFFFF  /* EQ1_B1_A - [15:0] */
+#define WM5100_EQ1_B1_A_SHIFT                        0  /* EQ1_B1_A - [15:0] */
+#define WM5100_EQ1_B1_A_WIDTH                       16  /* EQ1_B1_A - [15:0] */
+
+/*
+ * R3603 (0xE13) - EQ1_4
+ */
+#define WM5100_EQ1_B1_B_MASK                    0xFFFF  /* EQ1_B1_B - [15:0] */
+#define WM5100_EQ1_B1_B_SHIFT                        0  /* EQ1_B1_B - [15:0] */
+#define WM5100_EQ1_B1_B_WIDTH                       16  /* EQ1_B1_B - [15:0] */
+
+/*
+ * R3604 (0xE14) - EQ1_5
+ */
+#define WM5100_EQ1_B1_PG_MASK                   0xFFFF  /* EQ1_B1_PG - [15:0] */
+#define WM5100_EQ1_B1_PG_SHIFT                       0  /* EQ1_B1_PG - [15:0] */
+#define WM5100_EQ1_B1_PG_WIDTH                      16  /* EQ1_B1_PG - [15:0] */
+
+/*
+ * R3605 (0xE15) - EQ1_6
+ */
+#define WM5100_EQ1_B2_A_MASK                    0xFFFF  /* EQ1_B2_A - [15:0] */
+#define WM5100_EQ1_B2_A_SHIFT                        0  /* EQ1_B2_A - [15:0] */
+#define WM5100_EQ1_B2_A_WIDTH                       16  /* EQ1_B2_A - [15:0] */
+
+/*
+ * R3606 (0xE16) - EQ1_7
+ */
+#define WM5100_EQ1_B2_B_MASK                    0xFFFF  /* EQ1_B2_B - [15:0] */
+#define WM5100_EQ1_B2_B_SHIFT                        0  /* EQ1_B2_B - [15:0] */
+#define WM5100_EQ1_B2_B_WIDTH                       16  /* EQ1_B2_B - [15:0] */
+
+/*
+ * R3607 (0xE17) - EQ1_8
+ */
+#define WM5100_EQ1_B2_C_MASK                    0xFFFF  /* EQ1_B2_C - [15:0] */
+#define WM5100_EQ1_B2_C_SHIFT                        0  /* EQ1_B2_C - [15:0] */
+#define WM5100_EQ1_B2_C_WIDTH                       16  /* EQ1_B2_C - [15:0] */
+
+/*
+ * R3608 (0xE18) - EQ1_9
+ */
+#define WM5100_EQ1_B2_PG_MASK                   0xFFFF  /* EQ1_B2_PG - [15:0] */
+#define WM5100_EQ1_B2_PG_SHIFT                       0  /* EQ1_B2_PG - [15:0] */
+#define WM5100_EQ1_B2_PG_WIDTH                      16  /* EQ1_B2_PG - [15:0] */
+
+/*
+ * R3609 (0xE19) - EQ1_10
+ */
+#define WM5100_EQ1_B3_A_MASK                    0xFFFF  /* EQ1_B3_A - [15:0] */
+#define WM5100_EQ1_B3_A_SHIFT                        0  /* EQ1_B3_A - [15:0] */
+#define WM5100_EQ1_B3_A_WIDTH                       16  /* EQ1_B3_A - [15:0] */
+
+/*
+ * R3610 (0xE1A) - EQ1_11
+ */
+#define WM5100_EQ1_B3_B_MASK                    0xFFFF  /* EQ1_B3_B - [15:0] */
+#define WM5100_EQ1_B3_B_SHIFT                        0  /* EQ1_B3_B - [15:0] */
+#define WM5100_EQ1_B3_B_WIDTH                       16  /* EQ1_B3_B - [15:0] */
+
+/*
+ * R3611 (0xE1B) - EQ1_12
+ */
+#define WM5100_EQ1_B3_C_MASK                    0xFFFF  /* EQ1_B3_C - [15:0] */
+#define WM5100_EQ1_B3_C_SHIFT                        0  /* EQ1_B3_C - [15:0] */
+#define WM5100_EQ1_B3_C_WIDTH                       16  /* EQ1_B3_C - [15:0] */
+
+/*
+ * R3612 (0xE1C) - EQ1_13
+ */
+#define WM5100_EQ1_B3_PG_MASK                   0xFFFF  /* EQ1_B3_PG - [15:0] */
+#define WM5100_EQ1_B3_PG_SHIFT                       0  /* EQ1_B3_PG - [15:0] */
+#define WM5100_EQ1_B3_PG_WIDTH                      16  /* EQ1_B3_PG - [15:0] */
+
+/*
+ * R3613 (0xE1D) - EQ1_14
+ */
+#define WM5100_EQ1_B4_A_MASK                    0xFFFF  /* EQ1_B4_A - [15:0] */
+#define WM5100_EQ1_B4_A_SHIFT                        0  /* EQ1_B4_A - [15:0] */
+#define WM5100_EQ1_B4_A_WIDTH                       16  /* EQ1_B4_A - [15:0] */
+
+/*
+ * R3614 (0xE1E) - EQ1_15
+ */
+#define WM5100_EQ1_B4_B_MASK                    0xFFFF  /* EQ1_B4_B - [15:0] */
+#define WM5100_EQ1_B4_B_SHIFT                        0  /* EQ1_B4_B - [15:0] */
+#define WM5100_EQ1_B4_B_WIDTH                       16  /* EQ1_B4_B - [15:0] */
+
+/*
+ * R3615 (0xE1F) - EQ1_16
+ */
+#define WM5100_EQ1_B4_C_MASK                    0xFFFF  /* EQ1_B4_C - [15:0] */
+#define WM5100_EQ1_B4_C_SHIFT                        0  /* EQ1_B4_C - [15:0] */
+#define WM5100_EQ1_B4_C_WIDTH                       16  /* EQ1_B4_C - [15:0] */
+
+/*
+ * R3616 (0xE20) - EQ1_17
+ */
+#define WM5100_EQ1_B4_PG_MASK                   0xFFFF  /* EQ1_B4_PG - [15:0] */
+#define WM5100_EQ1_B4_PG_SHIFT                       0  /* EQ1_B4_PG - [15:0] */
+#define WM5100_EQ1_B4_PG_WIDTH                      16  /* EQ1_B4_PG - [15:0] */
+
+/*
+ * R3617 (0xE21) - EQ1_18
+ */
+#define WM5100_EQ1_B5_A_MASK                    0xFFFF  /* EQ1_B5_A - [15:0] */
+#define WM5100_EQ1_B5_A_SHIFT                        0  /* EQ1_B5_A - [15:0] */
+#define WM5100_EQ1_B5_A_WIDTH                       16  /* EQ1_B5_A - [15:0] */
+
+/*
+ * R3618 (0xE22) - EQ1_19
+ */
+#define WM5100_EQ1_B5_B_MASK                    0xFFFF  /* EQ1_B5_B - [15:0] */
+#define WM5100_EQ1_B5_B_SHIFT                        0  /* EQ1_B5_B - [15:0] */
+#define WM5100_EQ1_B5_B_WIDTH                       16  /* EQ1_B5_B - [15:0] */
+
+/*
+ * R3619 (0xE23) - EQ1_20
+ */
+#define WM5100_EQ1_B5_PG_MASK                   0xFFFF  /* EQ1_B5_PG - [15:0] */
+#define WM5100_EQ1_B5_PG_SHIFT                       0  /* EQ1_B5_PG - [15:0] */
+#define WM5100_EQ1_B5_PG_WIDTH                      16  /* EQ1_B5_PG - [15:0] */
+
+/*
+ * R3622 (0xE26) - EQ2_1
+ */
+#define WM5100_EQ2_B1_GAIN_MASK                 0xF800  /* EQ2_B1_GAIN - [15:11] */
+#define WM5100_EQ2_B1_GAIN_SHIFT                    11  /* EQ2_B1_GAIN - [15:11] */
+#define WM5100_EQ2_B1_GAIN_WIDTH                     5  /* EQ2_B1_GAIN - [15:11] */
+#define WM5100_EQ2_B2_GAIN_MASK                 0x07C0  /* EQ2_B2_GAIN - [10:6] */
+#define WM5100_EQ2_B2_GAIN_SHIFT                     6  /* EQ2_B2_GAIN - [10:6] */
+#define WM5100_EQ2_B2_GAIN_WIDTH                     5  /* EQ2_B2_GAIN - [10:6] */
+#define WM5100_EQ2_B3_GAIN_MASK                 0x003E  /* EQ2_B3_GAIN - [5:1] */
+#define WM5100_EQ2_B3_GAIN_SHIFT                     1  /* EQ2_B3_GAIN - [5:1] */
+#define WM5100_EQ2_B3_GAIN_WIDTH                     5  /* EQ2_B3_GAIN - [5:1] */
+#define WM5100_EQ2_ENA                          0x0001  /* EQ2_ENA */
+#define WM5100_EQ2_ENA_MASK                     0x0001  /* EQ2_ENA */
+#define WM5100_EQ2_ENA_SHIFT                         0  /* EQ2_ENA */
+#define WM5100_EQ2_ENA_WIDTH                         1  /* EQ2_ENA */
+
+/*
+ * R3623 (0xE27) - EQ2_2
+ */
+#define WM5100_EQ2_B4_GAIN_MASK                 0xF800  /* EQ2_B4_GAIN - [15:11] */
+#define WM5100_EQ2_B4_GAIN_SHIFT                    11  /* EQ2_B4_GAIN - [15:11] */
+#define WM5100_EQ2_B4_GAIN_WIDTH                     5  /* EQ2_B4_GAIN - [15:11] */
+#define WM5100_EQ2_B5_GAIN_MASK                 0x07C0  /* EQ2_B5_GAIN - [10:6] */
+#define WM5100_EQ2_B5_GAIN_SHIFT                     6  /* EQ2_B5_GAIN - [10:6] */
+#define WM5100_EQ2_B5_GAIN_WIDTH                     5  /* EQ2_B5_GAIN - [10:6] */
+
+/*
+ * R3624 (0xE28) - EQ2_3
+ */
+#define WM5100_EQ2_B1_A_MASK                    0xFFFF  /* EQ2_B1_A - [15:0] */
+#define WM5100_EQ2_B1_A_SHIFT                        0  /* EQ2_B1_A - [15:0] */
+#define WM5100_EQ2_B1_A_WIDTH                       16  /* EQ2_B1_A - [15:0] */
+
+/*
+ * R3625 (0xE29) - EQ2_4
+ */
+#define WM5100_EQ2_B1_B_MASK                    0xFFFF  /* EQ2_B1_B - [15:0] */
+#define WM5100_EQ2_B1_B_SHIFT                        0  /* EQ2_B1_B - [15:0] */
+#define WM5100_EQ2_B1_B_WIDTH                       16  /* EQ2_B1_B - [15:0] */
+
+/*
+ * R3626 (0xE2A) - EQ2_5
+ */
+#define WM5100_EQ2_B1_PG_MASK                   0xFFFF  /* EQ2_B1_PG - [15:0] */
+#define WM5100_EQ2_B1_PG_SHIFT                       0  /* EQ2_B1_PG - [15:0] */
+#define WM5100_EQ2_B1_PG_WIDTH                      16  /* EQ2_B1_PG - [15:0] */
+
+/*
+ * R3627 (0xE2B) - EQ2_6
+ */
+#define WM5100_EQ2_B2_A_MASK                    0xFFFF  /* EQ2_B2_A - [15:0] */
+#define WM5100_EQ2_B2_A_SHIFT                        0  /* EQ2_B2_A - [15:0] */
+#define WM5100_EQ2_B2_A_WIDTH                       16  /* EQ2_B2_A - [15:0] */
+
+/*
+ * R3628 (0xE2C) - EQ2_7
+ */
+#define WM5100_EQ2_B2_B_MASK                    0xFFFF  /* EQ2_B2_B - [15:0] */
+#define WM5100_EQ2_B2_B_SHIFT                        0  /* EQ2_B2_B - [15:0] */
+#define WM5100_EQ2_B2_B_WIDTH                       16  /* EQ2_B2_B - [15:0] */
+
+/*
+ * R3629 (0xE2D) - EQ2_8
+ */
+#define WM5100_EQ2_B2_C_MASK                    0xFFFF  /* EQ2_B2_C - [15:0] */
+#define WM5100_EQ2_B2_C_SHIFT                        0  /* EQ2_B2_C - [15:0] */
+#define WM5100_EQ2_B2_C_WIDTH                       16  /* EQ2_B2_C - [15:0] */
+
+/*
+ * R3630 (0xE2E) - EQ2_9
+ */
+#define WM5100_EQ2_B2_PG_MASK                   0xFFFF  /* EQ2_B2_PG - [15:0] */
+#define WM5100_EQ2_B2_PG_SHIFT                       0  /* EQ2_B2_PG - [15:0] */
+#define WM5100_EQ2_B2_PG_WIDTH                      16  /* EQ2_B2_PG - [15:0] */
+
+/*
+ * R3631 (0xE2F) - EQ2_10
+ */
+#define WM5100_EQ2_B3_A_MASK                    0xFFFF  /* EQ2_B3_A - [15:0] */
+#define WM5100_EQ2_B3_A_SHIFT                        0  /* EQ2_B3_A - [15:0] */
+#define WM5100_EQ2_B3_A_WIDTH                       16  /* EQ2_B3_A - [15:0] */
+
+/*
+ * R3632 (0xE30) - EQ2_11
+ */
+#define WM5100_EQ2_B3_B_MASK                    0xFFFF  /* EQ2_B3_B - [15:0] */
+#define WM5100_EQ2_B3_B_SHIFT                        0  /* EQ2_B3_B - [15:0] */
+#define WM5100_EQ2_B3_B_WIDTH                       16  /* EQ2_B3_B - [15:0] */
+
+/*
+ * R3633 (0xE31) - EQ2_12
+ */
+#define WM5100_EQ2_B3_C_MASK                    0xFFFF  /* EQ2_B3_C - [15:0] */
+#define WM5100_EQ2_B3_C_SHIFT                        0  /* EQ2_B3_C - [15:0] */
+#define WM5100_EQ2_B3_C_WIDTH                       16  /* EQ2_B3_C - [15:0] */
+
+/*
+ * R3634 (0xE32) - EQ2_13
+ */
+#define WM5100_EQ2_B3_PG_MASK                   0xFFFF  /* EQ2_B3_PG - [15:0] */
+#define WM5100_EQ2_B3_PG_SHIFT                       0  /* EQ2_B3_PG - [15:0] */
+#define WM5100_EQ2_B3_PG_WIDTH                      16  /* EQ2_B3_PG - [15:0] */
+
+/*
+ * R3635 (0xE33) - EQ2_14
+ */
+#define WM5100_EQ2_B4_A_MASK                    0xFFFF  /* EQ2_B4_A - [15:0] */
+#define WM5100_EQ2_B4_A_SHIFT                        0  /* EQ2_B4_A - [15:0] */
+#define WM5100_EQ2_B4_A_WIDTH                       16  /* EQ2_B4_A - [15:0] */
+
+/*
+ * R3636 (0xE34) - EQ2_15
+ */
+#define WM5100_EQ2_B4_B_MASK                    0xFFFF  /* EQ2_B4_B - [15:0] */
+#define WM5100_EQ2_B4_B_SHIFT                        0  /* EQ2_B4_B - [15:0] */
+#define WM5100_EQ2_B4_B_WIDTH                       16  /* EQ2_B4_B - [15:0] */
+
+/*
+ * R3637 (0xE35) - EQ2_16
+ */
+#define WM5100_EQ2_B4_C_MASK                    0xFFFF  /* EQ2_B4_C - [15:0] */
+#define WM5100_EQ2_B4_C_SHIFT                        0  /* EQ2_B4_C - [15:0] */
+#define WM5100_EQ2_B4_C_WIDTH                       16  /* EQ2_B4_C - [15:0] */
+
+/*
+ * R3638 (0xE36) - EQ2_17
+ */
+#define WM5100_EQ2_B4_PG_MASK                   0xFFFF  /* EQ2_B4_PG - [15:0] */
+#define WM5100_EQ2_B4_PG_SHIFT                       0  /* EQ2_B4_PG - [15:0] */
+#define WM5100_EQ2_B4_PG_WIDTH                      16  /* EQ2_B4_PG - [15:0] */
+
+/*
+ * R3639 (0xE37) - EQ2_18
+ */
+#define WM5100_EQ2_B5_A_MASK                    0xFFFF  /* EQ2_B5_A - [15:0] */
+#define WM5100_EQ2_B5_A_SHIFT                        0  /* EQ2_B5_A - [15:0] */
+#define WM5100_EQ2_B5_A_WIDTH                       16  /* EQ2_B5_A - [15:0] */
+
+/*
+ * R3640 (0xE38) - EQ2_19
+ */
+#define WM5100_EQ2_B5_B_MASK                    0xFFFF  /* EQ2_B5_B - [15:0] */
+#define WM5100_EQ2_B5_B_SHIFT                        0  /* EQ2_B5_B - [15:0] */
+#define WM5100_EQ2_B5_B_WIDTH                       16  /* EQ2_B5_B - [15:0] */
+
+/*
+ * R3641 (0xE39) - EQ2_20
+ */
+#define WM5100_EQ2_B5_PG_MASK                   0xFFFF  /* EQ2_B5_PG - [15:0] */
+#define WM5100_EQ2_B5_PG_SHIFT                       0  /* EQ2_B5_PG - [15:0] */
+#define WM5100_EQ2_B5_PG_WIDTH                      16  /* EQ2_B5_PG - [15:0] */
+
+/*
+ * R3644 (0xE3C) - EQ3_1
+ */
+#define WM5100_EQ3_B1_GAIN_MASK                 0xF800  /* EQ3_B1_GAIN - [15:11] */
+#define WM5100_EQ3_B1_GAIN_SHIFT                    11  /* EQ3_B1_GAIN - [15:11] */
+#define WM5100_EQ3_B1_GAIN_WIDTH                     5  /* EQ3_B1_GAIN - [15:11] */
+#define WM5100_EQ3_B2_GAIN_MASK                 0x07C0  /* EQ3_B2_GAIN - [10:6] */
+#define WM5100_EQ3_B2_GAIN_SHIFT                     6  /* EQ3_B2_GAIN - [10:6] */
+#define WM5100_EQ3_B2_GAIN_WIDTH                     5  /* EQ3_B2_GAIN - [10:6] */
+#define WM5100_EQ3_B3_GAIN_MASK                 0x003E  /* EQ3_B3_GAIN - [5:1] */
+#define WM5100_EQ3_B3_GAIN_SHIFT                     1  /* EQ3_B3_GAIN - [5:1] */
+#define WM5100_EQ3_B3_GAIN_WIDTH                     5  /* EQ3_B3_GAIN - [5:1] */
+#define WM5100_EQ3_ENA                          0x0001  /* EQ3_ENA */
+#define WM5100_EQ3_ENA_MASK                     0x0001  /* EQ3_ENA */
+#define WM5100_EQ3_ENA_SHIFT                         0  /* EQ3_ENA */
+#define WM5100_EQ3_ENA_WIDTH                         1  /* EQ3_ENA */
+
+/*
+ * R3645 (0xE3D) - EQ3_2
+ */
+#define WM5100_EQ3_B4_GAIN_MASK                 0xF800  /* EQ3_B4_GAIN - [15:11] */
+#define WM5100_EQ3_B4_GAIN_SHIFT                    11  /* EQ3_B4_GAIN - [15:11] */
+#define WM5100_EQ3_B4_GAIN_WIDTH                     5  /* EQ3_B4_GAIN - [15:11] */
+#define WM5100_EQ3_B5_GAIN_MASK                 0x07C0  /* EQ3_B5_GAIN - [10:6] */
+#define WM5100_EQ3_B5_GAIN_SHIFT                     6  /* EQ3_B5_GAIN - [10:6] */
+#define WM5100_EQ3_B5_GAIN_WIDTH                     5  /* EQ3_B5_GAIN - [10:6] */
+
+/*
+ * R3646 (0xE3E) - EQ3_3
+ */
+#define WM5100_EQ3_B1_A_MASK                    0xFFFF  /* EQ3_B1_A - [15:0] */
+#define WM5100_EQ3_B1_A_SHIFT                        0  /* EQ3_B1_A - [15:0] */
+#define WM5100_EQ3_B1_A_WIDTH                       16  /* EQ3_B1_A - [15:0] */
+
+/*
+ * R3647 (0xE3F) - EQ3_4
+ */
+#define WM5100_EQ3_B1_B_MASK                    0xFFFF  /* EQ3_B1_B - [15:0] */
+#define WM5100_EQ3_B1_B_SHIFT                        0  /* EQ3_B1_B - [15:0] */
+#define WM5100_EQ3_B1_B_WIDTH                       16  /* EQ3_B1_B - [15:0] */
+
+/*
+ * R3648 (0xE40) - EQ3_5
+ */
+#define WM5100_EQ3_B1_PG_MASK                   0xFFFF  /* EQ3_B1_PG - [15:0] */
+#define WM5100_EQ3_B1_PG_SHIFT                       0  /* EQ3_B1_PG - [15:0] */
+#define WM5100_EQ3_B1_PG_WIDTH                      16  /* EQ3_B1_PG - [15:0] */
+
+/*
+ * R3649 (0xE41) - EQ3_6
+ */
+#define WM5100_EQ3_B2_A_MASK                    0xFFFF  /* EQ3_B2_A - [15:0] */
+#define WM5100_EQ3_B2_A_SHIFT                        0  /* EQ3_B2_A - [15:0] */
+#define WM5100_EQ3_B2_A_WIDTH                       16  /* EQ3_B2_A - [15:0] */
+
+/*
+ * R3650 (0xE42) - EQ3_7
+ */
+#define WM5100_EQ3_B2_B_MASK                    0xFFFF  /* EQ3_B2_B - [15:0] */
+#define WM5100_EQ3_B2_B_SHIFT                        0  /* EQ3_B2_B - [15:0] */
+#define WM5100_EQ3_B2_B_WIDTH                       16  /* EQ3_B2_B - [15:0] */
+
+/*
+ * R3651 (0xE43) - EQ3_8
+ */
+#define WM5100_EQ3_B2_C_MASK                    0xFFFF  /* EQ3_B2_C - [15:0] */
+#define WM5100_EQ3_B2_C_SHIFT                        0  /* EQ3_B2_C - [15:0] */
+#define WM5100_EQ3_B2_C_WIDTH                       16  /* EQ3_B2_C - [15:0] */
+
+/*
+ * R3652 (0xE44) - EQ3_9
+ */
+#define WM5100_EQ3_B2_PG_MASK                   0xFFFF  /* EQ3_B2_PG - [15:0] */
+#define WM5100_EQ3_B2_PG_SHIFT                       0  /* EQ3_B2_PG - [15:0] */
+#define WM5100_EQ3_B2_PG_WIDTH                      16  /* EQ3_B2_PG - [15:0] */
+
+/*
+ * R3653 (0xE45) - EQ3_10
+ */
+#define WM5100_EQ3_B3_A_MASK                    0xFFFF  /* EQ3_B3_A - [15:0] */
+#define WM5100_EQ3_B3_A_SHIFT                        0  /* EQ3_B3_A - [15:0] */
+#define WM5100_EQ3_B3_A_WIDTH                       16  /* EQ3_B3_A - [15:0] */
+
+/*
+ * R3654 (0xE46) - EQ3_11
+ */
+#define WM5100_EQ3_B3_B_MASK                    0xFFFF  /* EQ3_B3_B - [15:0] */
+#define WM5100_EQ3_B3_B_SHIFT                        0  /* EQ3_B3_B - [15:0] */
+#define WM5100_EQ3_B3_B_WIDTH                       16  /* EQ3_B3_B - [15:0] */
+
+/*
+ * R3655 (0xE47) - EQ3_12
+ */
+#define WM5100_EQ3_B3_C_MASK                    0xFFFF  /* EQ3_B3_C - [15:0] */
+#define WM5100_EQ3_B3_C_SHIFT                        0  /* EQ3_B3_C - [15:0] */
+#define WM5100_EQ3_B3_C_WIDTH                       16  /* EQ3_B3_C - [15:0] */
+
+/*
+ * R3656 (0xE48) - EQ3_13
+ */
+#define WM5100_EQ3_B3_PG_MASK                   0xFFFF  /* EQ3_B3_PG - [15:0] */
+#define WM5100_EQ3_B3_PG_SHIFT                       0  /* EQ3_B3_PG - [15:0] */
+#define WM5100_EQ3_B3_PG_WIDTH                      16  /* EQ3_B3_PG - [15:0] */
+
+/*
+ * R3657 (0xE49) - EQ3_14
+ */
+#define WM5100_EQ3_B4_A_MASK                    0xFFFF  /* EQ3_B4_A - [15:0] */
+#define WM5100_EQ3_B4_A_SHIFT                        0  /* EQ3_B4_A - [15:0] */
+#define WM5100_EQ3_B4_A_WIDTH                       16  /* EQ3_B4_A - [15:0] */
+
+/*
+ * R3658 (0xE4A) - EQ3_15
+ */
+#define WM5100_EQ3_B4_B_MASK                    0xFFFF  /* EQ3_B4_B - [15:0] */
+#define WM5100_EQ3_B4_B_SHIFT                        0  /* EQ3_B4_B - [15:0] */
+#define WM5100_EQ3_B4_B_WIDTH                       16  /* EQ3_B4_B - [15:0] */
+
+/*
+ * R3659 (0xE4B) - EQ3_16
+ */
+#define WM5100_EQ3_B4_C_MASK                    0xFFFF  /* EQ3_B4_C - [15:0] */
+#define WM5100_EQ3_B4_C_SHIFT                        0  /* EQ3_B4_C - [15:0] */
+#define WM5100_EQ3_B4_C_WIDTH                       16  /* EQ3_B4_C - [15:0] */
+
+/*
+ * R3660 (0xE4C) - EQ3_17
+ */
+#define WM5100_EQ3_B4_PG_MASK                   0xFFFF  /* EQ3_B4_PG - [15:0] */
+#define WM5100_EQ3_B4_PG_SHIFT                       0  /* EQ3_B4_PG - [15:0] */
+#define WM5100_EQ3_B4_PG_WIDTH                      16  /* EQ3_B4_PG - [15:0] */
+
+/*
+ * R3661 (0xE4D) - EQ3_18
+ */
+#define WM5100_EQ3_B5_A_MASK                    0xFFFF  /* EQ3_B5_A - [15:0] */
+#define WM5100_EQ3_B5_A_SHIFT                        0  /* EQ3_B5_A - [15:0] */
+#define WM5100_EQ3_B5_A_WIDTH                       16  /* EQ3_B5_A - [15:0] */
+
+/*
+ * R3662 (0xE4E) - EQ3_19
+ */
+#define WM5100_EQ3_B5_B_MASK                    0xFFFF  /* EQ3_B5_B - [15:0] */
+#define WM5100_EQ3_B5_B_SHIFT                        0  /* EQ3_B5_B - [15:0] */
+#define WM5100_EQ3_B5_B_WIDTH                       16  /* EQ3_B5_B - [15:0] */
+
+/*
+ * R3663 (0xE4F) - EQ3_20
+ */
+#define WM5100_EQ3_B5_PG_MASK                   0xFFFF  /* EQ3_B5_PG - [15:0] */
+#define WM5100_EQ3_B5_PG_SHIFT                       0  /* EQ3_B5_PG - [15:0] */
+#define WM5100_EQ3_B5_PG_WIDTH                      16  /* EQ3_B5_PG - [15:0] */
+
+/*
+ * R3666 (0xE52) - EQ4_1
+ */
+#define WM5100_EQ4_B1_GAIN_MASK                 0xF800  /* EQ4_B1_GAIN - [15:11] */
+#define WM5100_EQ4_B1_GAIN_SHIFT                    11  /* EQ4_B1_GAIN - [15:11] */
+#define WM5100_EQ4_B1_GAIN_WIDTH                     5  /* EQ4_B1_GAIN - [15:11] */
+#define WM5100_EQ4_B2_GAIN_MASK                 0x07C0  /* EQ4_B2_GAIN - [10:6] */
+#define WM5100_EQ4_B2_GAIN_SHIFT                     6  /* EQ4_B2_GAIN - [10:6] */
+#define WM5100_EQ4_B2_GAIN_WIDTH                     5  /* EQ4_B2_GAIN - [10:6] */
+#define WM5100_EQ4_B3_GAIN_MASK                 0x003E  /* EQ4_B3_GAIN - [5:1] */
+#define WM5100_EQ4_B3_GAIN_SHIFT                     1  /* EQ4_B3_GAIN - [5:1] */
+#define WM5100_EQ4_B3_GAIN_WIDTH                     5  /* EQ4_B3_GAIN - [5:1] */
+#define WM5100_EQ4_ENA                          0x0001  /* EQ4_ENA */
+#define WM5100_EQ4_ENA_MASK                     0x0001  /* EQ4_ENA */
+#define WM5100_EQ4_ENA_SHIFT                         0  /* EQ4_ENA */
+#define WM5100_EQ4_ENA_WIDTH                         1  /* EQ4_ENA */
+
+/*
+ * R3667 (0xE53) - EQ4_2
+ */
+#define WM5100_EQ4_B4_GAIN_MASK                 0xF800  /* EQ4_B4_GAIN - [15:11] */
+#define WM5100_EQ4_B4_GAIN_SHIFT                    11  /* EQ4_B4_GAIN - [15:11] */
+#define WM5100_EQ4_B4_GAIN_WIDTH                     5  /* EQ4_B4_GAIN - [15:11] */
+#define WM5100_EQ4_B5_GAIN_MASK                 0x07C0  /* EQ4_B5_GAIN - [10:6] */
+#define WM5100_EQ4_B5_GAIN_SHIFT                     6  /* EQ4_B5_GAIN - [10:6] */
+#define WM5100_EQ4_B5_GAIN_WIDTH                     5  /* EQ4_B5_GAIN - [10:6] */
+
+/*
+ * R3668 (0xE54) - EQ4_3
+ */
+#define WM5100_EQ4_B1_A_MASK                    0xFFFF  /* EQ4_B1_A - [15:0] */
+#define WM5100_EQ4_B1_A_SHIFT                        0  /* EQ4_B1_A - [15:0] */
+#define WM5100_EQ4_B1_A_WIDTH                       16  /* EQ4_B1_A - [15:0] */
+
+/*
+ * R3669 (0xE55) - EQ4_4
+ */
+#define WM5100_EQ4_B1_B_MASK                    0xFFFF  /* EQ4_B1_B - [15:0] */
+#define WM5100_EQ4_B1_B_SHIFT                        0  /* EQ4_B1_B - [15:0] */
+#define WM5100_EQ4_B1_B_WIDTH                       16  /* EQ4_B1_B - [15:0] */
+
+/*
+ * R3670 (0xE56) - EQ4_5
+ */
+#define WM5100_EQ4_B1_PG_MASK                   0xFFFF  /* EQ4_B1_PG - [15:0] */
+#define WM5100_EQ4_B1_PG_SHIFT                       0  /* EQ4_B1_PG - [15:0] */
+#define WM5100_EQ4_B1_PG_WIDTH                      16  /* EQ4_B1_PG - [15:0] */
+
+/*
+ * R3671 (0xE57) - EQ4_6
+ */
+#define WM5100_EQ4_B2_A_MASK                    0xFFFF  /* EQ4_B2_A - [15:0] */
+#define WM5100_EQ4_B2_A_SHIFT                        0  /* EQ4_B2_A - [15:0] */
+#define WM5100_EQ4_B2_A_WIDTH                       16  /* EQ4_B2_A - [15:0] */
+
+/*
+ * R3672 (0xE58) - EQ4_7
+ */
+#define WM5100_EQ4_B2_B_MASK                    0xFFFF  /* EQ4_B2_B - [15:0] */
+#define WM5100_EQ4_B2_B_SHIFT                        0  /* EQ4_B2_B - [15:0] */
+#define WM5100_EQ4_B2_B_WIDTH                       16  /* EQ4_B2_B - [15:0] */
+
+/*
+ * R3673 (0xE59) - EQ4_8
+ */
+#define WM5100_EQ4_B2_C_MASK                    0xFFFF  /* EQ4_B2_C - [15:0] */
+#define WM5100_EQ4_B2_C_SHIFT                        0  /* EQ4_B2_C - [15:0] */
+#define WM5100_EQ4_B2_C_WIDTH                       16  /* EQ4_B2_C - [15:0] */
+
+/*
+ * R3674 (0xE5A) - EQ4_9
+ */
+#define WM5100_EQ4_B2_PG_MASK                   0xFFFF  /* EQ4_B2_PG - [15:0] */
+#define WM5100_EQ4_B2_PG_SHIFT                       0  /* EQ4_B2_PG - [15:0] */
+#define WM5100_EQ4_B2_PG_WIDTH                      16  /* EQ4_B2_PG - [15:0] */
+
+/*
+ * R3675 (0xE5B) - EQ4_10
+ */
+#define WM5100_EQ4_B3_A_MASK                    0xFFFF  /* EQ4_B3_A - [15:0] */
+#define WM5100_EQ4_B3_A_SHIFT                        0  /* EQ4_B3_A - [15:0] */
+#define WM5100_EQ4_B3_A_WIDTH                       16  /* EQ4_B3_A - [15:0] */
+
+/*
+ * R3676 (0xE5C) - EQ4_11
+ */
+#define WM5100_EQ4_B3_B_MASK                    0xFFFF  /* EQ4_B3_B - [15:0] */
+#define WM5100_EQ4_B3_B_SHIFT                        0  /* EQ4_B3_B - [15:0] */
+#define WM5100_EQ4_B3_B_WIDTH                       16  /* EQ4_B3_B - [15:0] */
+
+/*
+ * R3677 (0xE5D) - EQ4_12
+ */
+#define WM5100_EQ4_B3_C_MASK                    0xFFFF  /* EQ4_B3_C - [15:0] */
+#define WM5100_EQ4_B3_C_SHIFT                        0  /* EQ4_B3_C - [15:0] */
+#define WM5100_EQ4_B3_C_WIDTH                       16  /* EQ4_B3_C - [15:0] */
+
+/*
+ * R3678 (0xE5E) - EQ4_13
+ */
+#define WM5100_EQ4_B3_PG_MASK                   0xFFFF  /* EQ4_B3_PG - [15:0] */
+#define WM5100_EQ4_B3_PG_SHIFT                       0  /* EQ4_B3_PG - [15:0] */
+#define WM5100_EQ4_B3_PG_WIDTH                      16  /* EQ4_B3_PG - [15:0] */
+
+/*
+ * R3679 (0xE5F) - EQ4_14
+ */
+#define WM5100_EQ4_B4_A_MASK                    0xFFFF  /* EQ4_B4_A - [15:0] */
+#define WM5100_EQ4_B4_A_SHIFT                        0  /* EQ4_B4_A - [15:0] */
+#define WM5100_EQ4_B4_A_WIDTH                       16  /* EQ4_B4_A - [15:0] */
+
+/*
+ * R3680 (0xE60) - EQ4_15
+ */
+#define WM5100_EQ4_B4_B_MASK                    0xFFFF  /* EQ4_B4_B - [15:0] */
+#define WM5100_EQ4_B4_B_SHIFT                        0  /* EQ4_B4_B - [15:0] */
+#define WM5100_EQ4_B4_B_WIDTH                       16  /* EQ4_B4_B - [15:0] */
+
+/*
+ * R3681 (0xE61) - EQ4_16
+ */
+#define WM5100_EQ4_B4_C_MASK                    0xFFFF  /* EQ4_B4_C - [15:0] */
+#define WM5100_EQ4_B4_C_SHIFT                        0  /* EQ4_B4_C - [15:0] */
+#define WM5100_EQ4_B4_C_WIDTH                       16  /* EQ4_B4_C - [15:0] */
+
+/*
+ * R3682 (0xE62) - EQ4_17
+ */
+#define WM5100_EQ4_B4_PG_MASK                   0xFFFF  /* EQ4_B4_PG - [15:0] */
+#define WM5100_EQ4_B4_PG_SHIFT                       0  /* EQ4_B4_PG - [15:0] */
+#define WM5100_EQ4_B4_PG_WIDTH                      16  /* EQ4_B4_PG - [15:0] */
+
+/*
+ * R3683 (0xE63) - EQ4_18
+ */
+#define WM5100_EQ4_B5_A_MASK                    0xFFFF  /* EQ4_B5_A - [15:0] */
+#define WM5100_EQ4_B5_A_SHIFT                        0  /* EQ4_B5_A - [15:0] */
+#define WM5100_EQ4_B5_A_WIDTH                       16  /* EQ4_B5_A - [15:0] */
+
+/*
+ * R3684 (0xE64) - EQ4_19
+ */
+#define WM5100_EQ4_B5_B_MASK                    0xFFFF  /* EQ4_B5_B - [15:0] */
+#define WM5100_EQ4_B5_B_SHIFT                        0  /* EQ4_B5_B - [15:0] */
+#define WM5100_EQ4_B5_B_WIDTH                       16  /* EQ4_B5_B - [15:0] */
+
+/*
+ * R3685 (0xE65) - EQ4_20
+ */
+#define WM5100_EQ4_B5_PG_MASK                   0xFFFF  /* EQ4_B5_PG - [15:0] */
+#define WM5100_EQ4_B5_PG_SHIFT                       0  /* EQ4_B5_PG - [15:0] */
+#define WM5100_EQ4_B5_PG_WIDTH                      16  /* EQ4_B5_PG - [15:0] */
+
+/*
+ * R3712 (0xE80) - DRC1 ctrl1
+ */
+#define WM5100_DRC_SIG_DET_RMS_MASK             0xF800  /* DRC_SIG_DET_RMS - [15:11] */
+#define WM5100_DRC_SIG_DET_RMS_SHIFT                11  /* DRC_SIG_DET_RMS - [15:11] */
+#define WM5100_DRC_SIG_DET_RMS_WIDTH                 5  /* DRC_SIG_DET_RMS - [15:11] */
+#define WM5100_DRC_SIG_DET_PK_MASK              0x0600  /* DRC_SIG_DET_PK - [10:9] */
+#define WM5100_DRC_SIG_DET_PK_SHIFT                  9  /* DRC_SIG_DET_PK - [10:9] */
+#define WM5100_DRC_SIG_DET_PK_WIDTH                  2  /* DRC_SIG_DET_PK - [10:9] */
+#define WM5100_DRC_NG_ENA                       0x0100  /* DRC_NG_ENA */
+#define WM5100_DRC_NG_ENA_MASK                  0x0100  /* DRC_NG_ENA */
+#define WM5100_DRC_NG_ENA_SHIFT                      8  /* DRC_NG_ENA */
+#define WM5100_DRC_NG_ENA_WIDTH                      1  /* DRC_NG_ENA */
+#define WM5100_DRC_SIG_DET_MODE                 0x0080  /* DRC_SIG_DET_MODE */
+#define WM5100_DRC_SIG_DET_MODE_MASK            0x0080  /* DRC_SIG_DET_MODE */
+#define WM5100_DRC_SIG_DET_MODE_SHIFT                7  /* DRC_SIG_DET_MODE */
+#define WM5100_DRC_SIG_DET_MODE_WIDTH                1  /* DRC_SIG_DET_MODE */
+#define WM5100_DRC_SIG_DET                      0x0040  /* DRC_SIG_DET */
+#define WM5100_DRC_SIG_DET_MASK                 0x0040  /* DRC_SIG_DET */
+#define WM5100_DRC_SIG_DET_SHIFT                     6  /* DRC_SIG_DET */
+#define WM5100_DRC_SIG_DET_WIDTH                     1  /* DRC_SIG_DET */
+#define WM5100_DRC_KNEE2_OP_ENA                 0x0020  /* DRC_KNEE2_OP_ENA */
+#define WM5100_DRC_KNEE2_OP_ENA_MASK            0x0020  /* DRC_KNEE2_OP_ENA */
+#define WM5100_DRC_KNEE2_OP_ENA_SHIFT                5  /* DRC_KNEE2_OP_ENA */
+#define WM5100_DRC_KNEE2_OP_ENA_WIDTH                1  /* DRC_KNEE2_OP_ENA */
+#define WM5100_DRC_QR                           0x0010  /* DRC_QR */
+#define WM5100_DRC_QR_MASK                      0x0010  /* DRC_QR */
+#define WM5100_DRC_QR_SHIFT                          4  /* DRC_QR */
+#define WM5100_DRC_QR_WIDTH                          1  /* DRC_QR */
+#define WM5100_DRC_ANTICLIP                     0x0008  /* DRC_ANTICLIP */
+#define WM5100_DRC_ANTICLIP_MASK                0x0008  /* DRC_ANTICLIP */
+#define WM5100_DRC_ANTICLIP_SHIFT                    3  /* DRC_ANTICLIP */
+#define WM5100_DRC_ANTICLIP_WIDTH                    1  /* DRC_ANTICLIP */
+#define WM5100_DRCL_ENA                         0x0002  /* DRCL_ENA */
+#define WM5100_DRCL_ENA_MASK                    0x0002  /* DRCL_ENA */
+#define WM5100_DRCL_ENA_SHIFT                        1  /* DRCL_ENA */
+#define WM5100_DRCL_ENA_WIDTH                        1  /* DRCL_ENA */
+#define WM5100_DRCR_ENA                         0x0001  /* DRCR_ENA */
+#define WM5100_DRCR_ENA_MASK                    0x0001  /* DRCR_ENA */
+#define WM5100_DRCR_ENA_SHIFT                        0  /* DRCR_ENA */
+#define WM5100_DRCR_ENA_WIDTH                        1  /* DRCR_ENA */
+
+/*
+ * R3713 (0xE81) - DRC1 ctrl2
+ */
+#define WM5100_DRC_ATK_MASK                     0x1E00  /* DRC_ATK - [12:9] */
+#define WM5100_DRC_ATK_SHIFT                         9  /* DRC_ATK - [12:9] */
+#define WM5100_DRC_ATK_WIDTH                         4  /* DRC_ATK - [12:9] */
+#define WM5100_DRC_DCY_MASK                     0x01E0  /* DRC_DCY - [8:5] */
+#define WM5100_DRC_DCY_SHIFT                         5  /* DRC_DCY - [8:5] */
+#define WM5100_DRC_DCY_WIDTH                         4  /* DRC_DCY - [8:5] */
+#define WM5100_DRC_MINGAIN_MASK                 0x001C  /* DRC_MINGAIN - [4:2] */
+#define WM5100_DRC_MINGAIN_SHIFT                     2  /* DRC_MINGAIN - [4:2] */
+#define WM5100_DRC_MINGAIN_WIDTH                     3  /* DRC_MINGAIN - [4:2] */
+#define WM5100_DRC_MAXGAIN_MASK                 0x0003  /* DRC_MAXGAIN - [1:0] */
+#define WM5100_DRC_MAXGAIN_SHIFT                     0  /* DRC_MAXGAIN - [1:0] */
+#define WM5100_DRC_MAXGAIN_WIDTH                     2  /* DRC_MAXGAIN - [1:0] */
+
+/*
+ * R3714 (0xE82) - DRC1 ctrl3
+ */
+#define WM5100_DRC_NG_MINGAIN_MASK              0xF000  /* DRC_NG_MINGAIN - [15:12] */
+#define WM5100_DRC_NG_MINGAIN_SHIFT                 12  /* DRC_NG_MINGAIN - [15:12] */
+#define WM5100_DRC_NG_MINGAIN_WIDTH                  4  /* DRC_NG_MINGAIN - [15:12] */
+#define WM5100_DRC_NG_EXP_MASK                  0x0C00  /* DRC_NG_EXP - [11:10] */
+#define WM5100_DRC_NG_EXP_SHIFT                     10  /* DRC_NG_EXP - [11:10] */
+#define WM5100_DRC_NG_EXP_WIDTH                      2  /* DRC_NG_EXP - [11:10] */
+#define WM5100_DRC_QR_THR_MASK                  0x0300  /* DRC_QR_THR - [9:8] */
+#define WM5100_DRC_QR_THR_SHIFT                      8  /* DRC_QR_THR - [9:8] */
+#define WM5100_DRC_QR_THR_WIDTH                      2  /* DRC_QR_THR - [9:8] */
+#define WM5100_DRC_QR_DCY_MASK                  0x00C0  /* DRC_QR_DCY - [7:6] */
+#define WM5100_DRC_QR_DCY_SHIFT                      6  /* DRC_QR_DCY - [7:6] */
+#define WM5100_DRC_QR_DCY_WIDTH                      2  /* DRC_QR_DCY - [7:6] */
+#define WM5100_DRC_HI_COMP_MASK                 0x0038  /* DRC_HI_COMP - [5:3] */
+#define WM5100_DRC_HI_COMP_SHIFT                     3  /* DRC_HI_COMP - [5:3] */
+#define WM5100_DRC_HI_COMP_WIDTH                     3  /* DRC_HI_COMP - [5:3] */
+#define WM5100_DRC_LO_COMP_MASK                 0x0007  /* DRC_LO_COMP - [2:0] */
+#define WM5100_DRC_LO_COMP_SHIFT                     0  /* DRC_LO_COMP - [2:0] */
+#define WM5100_DRC_LO_COMP_WIDTH                     3  /* DRC_LO_COMP - [2:0] */
+
+/*
+ * R3715 (0xE83) - DRC1 ctrl4
+ */
+#define WM5100_DRC_KNEE_IP_MASK                 0x07E0  /* DRC_KNEE_IP - [10:5] */
+#define WM5100_DRC_KNEE_IP_SHIFT                     5  /* DRC_KNEE_IP - [10:5] */
+#define WM5100_DRC_KNEE_IP_WIDTH                     6  /* DRC_KNEE_IP - [10:5] */
+#define WM5100_DRC_KNEE_OP_MASK                 0x001F  /* DRC_KNEE_OP - [4:0] */
+#define WM5100_DRC_KNEE_OP_SHIFT                     0  /* DRC_KNEE_OP - [4:0] */
+#define WM5100_DRC_KNEE_OP_WIDTH                     5  /* DRC_KNEE_OP - [4:0] */
+
+/*
+ * R3716 (0xE84) - DRC1 ctrl5
+ */
+#define WM5100_DRC_KNEE2_IP_MASK                0x03E0  /* DRC_KNEE2_IP - [9:5] */
+#define WM5100_DRC_KNEE2_IP_SHIFT                    5  /* DRC_KNEE2_IP - [9:5] */
+#define WM5100_DRC_KNEE2_IP_WIDTH                    5  /* DRC_KNEE2_IP - [9:5] */
+#define WM5100_DRC_KNEE2_OP_MASK                0x001F  /* DRC_KNEE2_OP - [4:0] */
+#define WM5100_DRC_KNEE2_OP_SHIFT                    0  /* DRC_KNEE2_OP - [4:0] */
+#define WM5100_DRC_KNEE2_OP_WIDTH                    5  /* DRC_KNEE2_OP - [4:0] */
+
+/*
+ * R3776 (0xEC0) - HPLPF1_1
+ */
+#define WM5100_LHPF1_MODE                       0x0002  /* LHPF1_MODE */
+#define WM5100_LHPF1_MODE_MASK                  0x0002  /* LHPF1_MODE */
+#define WM5100_LHPF1_MODE_SHIFT                      1  /* LHPF1_MODE */
+#define WM5100_LHPF1_MODE_WIDTH                      1  /* LHPF1_MODE */
+#define WM5100_LHPF1_ENA                        0x0001  /* LHPF1_ENA */
+#define WM5100_LHPF1_ENA_MASK                   0x0001  /* LHPF1_ENA */
+#define WM5100_LHPF1_ENA_SHIFT                       0  /* LHPF1_ENA */
+#define WM5100_LHPF1_ENA_WIDTH                       1  /* LHPF1_ENA */
+
+/*
+ * R3777 (0xEC1) - HPLPF1_2
+ */
+#define WM5100_LHPF1_COEFF_MASK                 0xFFFF  /* LHPF1_COEFF - [15:0] */
+#define WM5100_LHPF1_COEFF_SHIFT                     0  /* LHPF1_COEFF - [15:0] */
+#define WM5100_LHPF1_COEFF_WIDTH                    16  /* LHPF1_COEFF - [15:0] */
+
+/*
+ * R3780 (0xEC4) - HPLPF2_1
+ */
+#define WM5100_LHPF2_MODE                       0x0002  /* LHPF2_MODE */
+#define WM5100_LHPF2_MODE_MASK                  0x0002  /* LHPF2_MODE */
+#define WM5100_LHPF2_MODE_SHIFT                      1  /* LHPF2_MODE */
+#define WM5100_LHPF2_MODE_WIDTH                      1  /* LHPF2_MODE */
+#define WM5100_LHPF2_ENA                        0x0001  /* LHPF2_ENA */
+#define WM5100_LHPF2_ENA_MASK                   0x0001  /* LHPF2_ENA */
+#define WM5100_LHPF2_ENA_SHIFT                       0  /* LHPF2_ENA */
+#define WM5100_LHPF2_ENA_WIDTH                       1  /* LHPF2_ENA */
+
+/*
+ * R3781 (0xEC5) - HPLPF2_2
+ */
+#define WM5100_LHPF2_COEFF_MASK                 0xFFFF  /* LHPF2_COEFF - [15:0] */
+#define WM5100_LHPF2_COEFF_SHIFT                     0  /* LHPF2_COEFF - [15:0] */
+#define WM5100_LHPF2_COEFF_WIDTH                    16  /* LHPF2_COEFF - [15:0] */
+
+/*
+ * R3784 (0xEC8) - HPLPF3_1
+ */
+#define WM5100_LHPF3_MODE                       0x0002  /* LHPF3_MODE */
+#define WM5100_LHPF3_MODE_MASK                  0x0002  /* LHPF3_MODE */
+#define WM5100_LHPF3_MODE_SHIFT                      1  /* LHPF3_MODE */
+#define WM5100_LHPF3_MODE_WIDTH                      1  /* LHPF3_MODE */
+#define WM5100_LHPF3_ENA                        0x0001  /* LHPF3_ENA */
+#define WM5100_LHPF3_ENA_MASK                   0x0001  /* LHPF3_ENA */
+#define WM5100_LHPF3_ENA_SHIFT                       0  /* LHPF3_ENA */
+#define WM5100_LHPF3_ENA_WIDTH                       1  /* LHPF3_ENA */
+
+/*
+ * R3785 (0xEC9) - HPLPF3_2
+ */
+#define WM5100_LHPF3_COEFF_MASK                 0xFFFF  /* LHPF3_COEFF - [15:0] */
+#define WM5100_LHPF3_COEFF_SHIFT                     0  /* LHPF3_COEFF - [15:0] */
+#define WM5100_LHPF3_COEFF_WIDTH                    16  /* LHPF3_COEFF - [15:0] */
+
+/*
+ * R3788 (0xECC) - HPLPF4_1
+ */
+#define WM5100_LHPF4_MODE                       0x0002  /* LHPF4_MODE */
+#define WM5100_LHPF4_MODE_MASK                  0x0002  /* LHPF4_MODE */
+#define WM5100_LHPF4_MODE_SHIFT                      1  /* LHPF4_MODE */
+#define WM5100_LHPF4_MODE_WIDTH                      1  /* LHPF4_MODE */
+#define WM5100_LHPF4_ENA                        0x0001  /* LHPF4_ENA */
+#define WM5100_LHPF4_ENA_MASK                   0x0001  /* LHPF4_ENA */
+#define WM5100_LHPF4_ENA_SHIFT                       0  /* LHPF4_ENA */
+#define WM5100_LHPF4_ENA_WIDTH                       1  /* LHPF4_ENA */
+
+/*
+ * R3789 (0xECD) - HPLPF4_2
+ */
+#define WM5100_LHPF4_COEFF_MASK                 0xFFFF  /* LHPF4_COEFF - [15:0] */
+#define WM5100_LHPF4_COEFF_SHIFT                     0  /* LHPF4_COEFF - [15:0] */
+#define WM5100_LHPF4_COEFF_WIDTH                    16  /* LHPF4_COEFF - [15:0] */
+
+/*
+ * R16384 (0x4000) - DSP1 DM 0
+ */
+#define WM5100_DSP1_DM_START_1_MASK             0x00FF  /* DSP1_DM_START - [7:0] */
+#define WM5100_DSP1_DM_START_1_SHIFT                 0  /* DSP1_DM_START - [7:0] */
+#define WM5100_DSP1_DM_START_1_WIDTH                 8  /* DSP1_DM_START - [7:0] */
+
+/*
+ * R16385 (0x4001) - DSP1 DM 1
+ */
+#define WM5100_DSP1_DM_START_MASK               0xFFFF  /* DSP1_DM_START - [15:0] */
+#define WM5100_DSP1_DM_START_SHIFT                   0  /* DSP1_DM_START - [15:0] */
+#define WM5100_DSP1_DM_START_WIDTH                  16  /* DSP1_DM_START - [15:0] */
+
+/*
+ * R16386 (0x4002) - DSP1 DM 2
+ */
+#define WM5100_DSP1_DM_1_1_MASK                 0x00FF  /* DSP1_DM_1 - [7:0] */
+#define WM5100_DSP1_DM_1_1_SHIFT                     0  /* DSP1_DM_1 - [7:0] */
+#define WM5100_DSP1_DM_1_1_WIDTH                     8  /* DSP1_DM_1 - [7:0] */
+
+/*
+ * R16387 (0x4003) - DSP1 DM 3
+ */
+#define WM5100_DSP1_DM_1_MASK                   0xFFFF  /* DSP1_DM_1 - [15:0] */
+#define WM5100_DSP1_DM_1_SHIFT                       0  /* DSP1_DM_1 - [15:0] */
+#define WM5100_DSP1_DM_1_WIDTH                      16  /* DSP1_DM_1 - [15:0] */
+
+/*
+ * R16892 (0x41FC) - DSP1 DM 508
+ */
+#define WM5100_DSP1_DM_254_1_MASK               0x00FF  /* DSP1_DM_254 - [7:0] */
+#define WM5100_DSP1_DM_254_1_SHIFT                   0  /* DSP1_DM_254 - [7:0] */
+#define WM5100_DSP1_DM_254_1_WIDTH                   8  /* DSP1_DM_254 - [7:0] */
+
+/*
+ * R16893 (0x41FD) - DSP1 DM 509
+ */
+#define WM5100_DSP1_DM_254_MASK                 0xFFFF  /* DSP1_DM_254 - [15:0] */
+#define WM5100_DSP1_DM_254_SHIFT                     0  /* DSP1_DM_254 - [15:0] */
+#define WM5100_DSP1_DM_254_WIDTH                    16  /* DSP1_DM_254 - [15:0] */
+
+/*
+ * R16894 (0x41FE) - DSP1 DM 510
+ */
+#define WM5100_DSP1_DM_END_1_MASK               0x00FF  /* DSP1_DM_END - [7:0] */
+#define WM5100_DSP1_DM_END_1_SHIFT                   0  /* DSP1_DM_END - [7:0] */
+#define WM5100_DSP1_DM_END_1_WIDTH                   8  /* DSP1_DM_END - [7:0] */
+
+/*
+ * R16895 (0x41FF) - DSP1 DM 511
+ */
+#define WM5100_DSP1_DM_END_MASK                 0xFFFF  /* DSP1_DM_END - [15:0] */
+#define WM5100_DSP1_DM_END_SHIFT                     0  /* DSP1_DM_END - [15:0] */
+#define WM5100_DSP1_DM_END_WIDTH                    16  /* DSP1_DM_END - [15:0] */
+
+/*
+ * R18432 (0x4800) - DSP1 PM 0
+ */
+#define WM5100_DSP1_PM_START_2_MASK             0x00FF  /* DSP1_PM_START - [7:0] */
+#define WM5100_DSP1_PM_START_2_SHIFT                 0  /* DSP1_PM_START - [7:0] */
+#define WM5100_DSP1_PM_START_2_WIDTH                 8  /* DSP1_PM_START - [7:0] */
+
+/*
+ * R18433 (0x4801) - DSP1 PM 1
+ */
+#define WM5100_DSP1_PM_START_1_MASK             0xFFFF  /* DSP1_PM_START - [15:0] */
+#define WM5100_DSP1_PM_START_1_SHIFT                 0  /* DSP1_PM_START - [15:0] */
+#define WM5100_DSP1_PM_START_1_WIDTH                16  /* DSP1_PM_START - [15:0] */
+
+/*
+ * R18434 (0x4802) - DSP1 PM 2
+ */
+#define WM5100_DSP1_PM_START_MASK               0xFFFF  /* DSP1_PM_START - [15:0] */
+#define WM5100_DSP1_PM_START_SHIFT                   0  /* DSP1_PM_START - [15:0] */
+#define WM5100_DSP1_PM_START_WIDTH                  16  /* DSP1_PM_START - [15:0] */
+
+/*
+ * R18435 (0x4803) - DSP1 PM 3
+ */
+#define WM5100_DSP1_PM_1_2_MASK                 0x00FF  /* DSP1_PM_1 - [7:0] */
+#define WM5100_DSP1_PM_1_2_SHIFT                     0  /* DSP1_PM_1 - [7:0] */
+#define WM5100_DSP1_PM_1_2_WIDTH                     8  /* DSP1_PM_1 - [7:0] */
+
+/*
+ * R18436 (0x4804) - DSP1 PM 4
+ */
+#define WM5100_DSP1_PM_1_1_MASK                 0xFFFF  /* DSP1_PM_1 - [15:0] */
+#define WM5100_DSP1_PM_1_1_SHIFT                     0  /* DSP1_PM_1 - [15:0] */
+#define WM5100_DSP1_PM_1_1_WIDTH                    16  /* DSP1_PM_1 - [15:0] */
+
+/*
+ * R18437 (0x4805) - DSP1 PM 5
+ */
+#define WM5100_DSP1_PM_1_MASK                   0xFFFF  /* DSP1_PM_1 - [15:0] */
+#define WM5100_DSP1_PM_1_SHIFT                       0  /* DSP1_PM_1 - [15:0] */
+#define WM5100_DSP1_PM_1_WIDTH                      16  /* DSP1_PM_1 - [15:0] */
+
+/*
+ * R19962 (0x4DFA) - DSP1 PM 1530
+ */
+#define WM5100_DSP1_PM_510_2_MASK               0x00FF  /* DSP1_PM_510 - [7:0] */
+#define WM5100_DSP1_PM_510_2_SHIFT                   0  /* DSP1_PM_510 - [7:0] */
+#define WM5100_DSP1_PM_510_2_WIDTH                   8  /* DSP1_PM_510 - [7:0] */
+
+/*
+ * R19963 (0x4DFB) - DSP1 PM 1531
+ */
+#define WM5100_DSP1_PM_510_1_MASK               0xFFFF  /* DSP1_PM_510 - [15:0] */
+#define WM5100_DSP1_PM_510_1_SHIFT                   0  /* DSP1_PM_510 - [15:0] */
+#define WM5100_DSP1_PM_510_1_WIDTH                  16  /* DSP1_PM_510 - [15:0] */
+
+/*
+ * R19964 (0x4DFC) - DSP1 PM 1532
+ */
+#define WM5100_DSP1_PM_510_MASK                 0xFFFF  /* DSP1_PM_510 - [15:0] */
+#define WM5100_DSP1_PM_510_SHIFT                     0  /* DSP1_PM_510 - [15:0] */
+#define WM5100_DSP1_PM_510_WIDTH                    16  /* DSP1_PM_510 - [15:0] */
+
+/*
+ * R19965 (0x4DFD) - DSP1 PM 1533
+ */
+#define WM5100_DSP1_PM_END_2_MASK               0x00FF  /* DSP1_PM_END - [7:0] */
+#define WM5100_DSP1_PM_END_2_SHIFT                   0  /* DSP1_PM_END - [7:0] */
+#define WM5100_DSP1_PM_END_2_WIDTH                   8  /* DSP1_PM_END - [7:0] */
+
+/*
+ * R19966 (0x4DFE) - DSP1 PM 1534
+ */
+#define WM5100_DSP1_PM_END_1_MASK               0xFFFF  /* DSP1_PM_END - [15:0] */
+#define WM5100_DSP1_PM_END_1_SHIFT                   0  /* DSP1_PM_END - [15:0] */
+#define WM5100_DSP1_PM_END_1_WIDTH                  16  /* DSP1_PM_END - [15:0] */
+
+/*
+ * R19967 (0x4DFF) - DSP1 PM 1535
+ */
+#define WM5100_DSP1_PM_END_MASK                 0xFFFF  /* DSP1_PM_END - [15:0] */
+#define WM5100_DSP1_PM_END_SHIFT                     0  /* DSP1_PM_END - [15:0] */
+#define WM5100_DSP1_PM_END_WIDTH                    16  /* DSP1_PM_END - [15:0] */
+
+/*
+ * R20480 (0x5000) - DSP1 ZM 0
+ */
+#define WM5100_DSP1_ZM_START_1_MASK             0x00FF  /* DSP1_ZM_START - [7:0] */
+#define WM5100_DSP1_ZM_START_1_SHIFT                 0  /* DSP1_ZM_START - [7:0] */
+#define WM5100_DSP1_ZM_START_1_WIDTH                 8  /* DSP1_ZM_START - [7:0] */
+
+/*
+ * R20481 (0x5001) - DSP1 ZM 1
+ */
+#define WM5100_DSP1_ZM_START_MASK               0xFFFF  /* DSP1_ZM_START - [15:0] */
+#define WM5100_DSP1_ZM_START_SHIFT                   0  /* DSP1_ZM_START - [15:0] */
+#define WM5100_DSP1_ZM_START_WIDTH                  16  /* DSP1_ZM_START - [15:0] */
+
+/*
+ * R20482 (0x5002) - DSP1 ZM 2
+ */
+#define WM5100_DSP1_ZM_1_1_MASK                 0x00FF  /* DSP1_ZM_1 - [7:0] */
+#define WM5100_DSP1_ZM_1_1_SHIFT                     0  /* DSP1_ZM_1 - [7:0] */
+#define WM5100_DSP1_ZM_1_1_WIDTH                     8  /* DSP1_ZM_1 - [7:0] */
+
+/*
+ * R20483 (0x5003) - DSP1 ZM 3
+ */
+#define WM5100_DSP1_ZM_1_MASK                   0xFFFF  /* DSP1_ZM_1 - [15:0] */
+#define WM5100_DSP1_ZM_1_SHIFT                       0  /* DSP1_ZM_1 - [15:0] */
+#define WM5100_DSP1_ZM_1_WIDTH                      16  /* DSP1_ZM_1 - [15:0] */
+
+/*
+ * R22524 (0x57FC) - DSP1 ZM 2044
+ */
+#define WM5100_DSP1_ZM_1022_1_MASK              0x00FF  /* DSP1_ZM_1022 - [7:0] */
+#define WM5100_DSP1_ZM_1022_1_SHIFT                  0  /* DSP1_ZM_1022 - [7:0] */
+#define WM5100_DSP1_ZM_1022_1_WIDTH                  8  /* DSP1_ZM_1022 - [7:0] */
+
+/*
+ * R22525 (0x57FD) - DSP1 ZM 2045
+ */
+#define WM5100_DSP1_ZM_1022_MASK                0xFFFF  /* DSP1_ZM_1022 - [15:0] */
+#define WM5100_DSP1_ZM_1022_SHIFT                    0  /* DSP1_ZM_1022 - [15:0] */
+#define WM5100_DSP1_ZM_1022_WIDTH                   16  /* DSP1_ZM_1022 - [15:0] */
+
+/*
+ * R22526 (0x57FE) - DSP1 ZM 2046
+ */
+#define WM5100_DSP1_ZM_END_1_MASK               0x00FF  /* DSP1_ZM_END - [7:0] */
+#define WM5100_DSP1_ZM_END_1_SHIFT                   0  /* DSP1_ZM_END - [7:0] */
+#define WM5100_DSP1_ZM_END_1_WIDTH                   8  /* DSP1_ZM_END - [7:0] */
+
+/*
+ * R22527 (0x57FF) - DSP1 ZM 2047
+ */
+#define WM5100_DSP1_ZM_END_MASK                 0xFFFF  /* DSP1_ZM_END - [15:0] */
+#define WM5100_DSP1_ZM_END_SHIFT                     0  /* DSP1_ZM_END - [15:0] */
+#define WM5100_DSP1_ZM_END_WIDTH                    16  /* DSP1_ZM_END - [15:0] */
+
+/*
+ * R24576 (0x6000) - DSP2 DM 0
+ */
+#define WM5100_DSP2_DM_START_1_MASK             0x00FF  /* DSP2_DM_START - [7:0] */
+#define WM5100_DSP2_DM_START_1_SHIFT                 0  /* DSP2_DM_START - [7:0] */
+#define WM5100_DSP2_DM_START_1_WIDTH                 8  /* DSP2_DM_START - [7:0] */
+
+/*
+ * R24577 (0x6001) - DSP2 DM 1
+ */
+#define WM5100_DSP2_DM_START_MASK               0xFFFF  /* DSP2_DM_START - [15:0] */
+#define WM5100_DSP2_DM_START_SHIFT                   0  /* DSP2_DM_START - [15:0] */
+#define WM5100_DSP2_DM_START_WIDTH                  16  /* DSP2_DM_START - [15:0] */
+
+/*
+ * R24578 (0x6002) - DSP2 DM 2
+ */
+#define WM5100_DSP2_DM_1_1_MASK                 0x00FF  /* DSP2_DM_1 - [7:0] */
+#define WM5100_DSP2_DM_1_1_SHIFT                     0  /* DSP2_DM_1 - [7:0] */
+#define WM5100_DSP2_DM_1_1_WIDTH                     8  /* DSP2_DM_1 - [7:0] */
+
+/*
+ * R24579 (0x6003) - DSP2 DM 3
+ */
+#define WM5100_DSP2_DM_1_MASK                   0xFFFF  /* DSP2_DM_1 - [15:0] */
+#define WM5100_DSP2_DM_1_SHIFT                       0  /* DSP2_DM_1 - [15:0] */
+#define WM5100_DSP2_DM_1_WIDTH                      16  /* DSP2_DM_1 - [15:0] */
+
+/*
+ * R25084 (0x61FC) - DSP2 DM 508
+ */
+#define WM5100_DSP2_DM_254_1_MASK               0x00FF  /* DSP2_DM_254 - [7:0] */
+#define WM5100_DSP2_DM_254_1_SHIFT                   0  /* DSP2_DM_254 - [7:0] */
+#define WM5100_DSP2_DM_254_1_WIDTH                   8  /* DSP2_DM_254 - [7:0] */
+
+/*
+ * R25085 (0x61FD) - DSP2 DM 509
+ */
+#define WM5100_DSP2_DM_254_MASK                 0xFFFF  /* DSP2_DM_254 - [15:0] */
+#define WM5100_DSP2_DM_254_SHIFT                     0  /* DSP2_DM_254 - [15:0] */
+#define WM5100_DSP2_DM_254_WIDTH                    16  /* DSP2_DM_254 - [15:0] */
+
+/*
+ * R25086 (0x61FE) - DSP2 DM 510
+ */
+#define WM5100_DSP2_DM_END_1_MASK               0x00FF  /* DSP2_DM_END - [7:0] */
+#define WM5100_DSP2_DM_END_1_SHIFT                   0  /* DSP2_DM_END - [7:0] */
+#define WM5100_DSP2_DM_END_1_WIDTH                   8  /* DSP2_DM_END - [7:0] */
+
+/*
+ * R25087 (0x61FF) - DSP2 DM 511
+ */
+#define WM5100_DSP2_DM_END_MASK                 0xFFFF  /* DSP2_DM_END - [15:0] */
+#define WM5100_DSP2_DM_END_SHIFT                     0  /* DSP2_DM_END - [15:0] */
+#define WM5100_DSP2_DM_END_WIDTH                    16  /* DSP2_DM_END - [15:0] */
+
+/*
+ * R26624 (0x6800) - DSP2 PM 0
+ */
+#define WM5100_DSP2_PM_START_2_MASK             0x00FF  /* DSP2_PM_START - [7:0] */
+#define WM5100_DSP2_PM_START_2_SHIFT                 0  /* DSP2_PM_START - [7:0] */
+#define WM5100_DSP2_PM_START_2_WIDTH                 8  /* DSP2_PM_START - [7:0] */
+
+/*
+ * R26625 (0x6801) - DSP2 PM 1
+ */
+#define WM5100_DSP2_PM_START_1_MASK             0xFFFF  /* DSP2_PM_START - [15:0] */
+#define WM5100_DSP2_PM_START_1_SHIFT                 0  /* DSP2_PM_START - [15:0] */
+#define WM5100_DSP2_PM_START_1_WIDTH                16  /* DSP2_PM_START - [15:0] */
+
+/*
+ * R26626 (0x6802) - DSP2 PM 2
+ */
+#define WM5100_DSP2_PM_START_MASK               0xFFFF  /* DSP2_PM_START - [15:0] */
+#define WM5100_DSP2_PM_START_SHIFT                   0  /* DSP2_PM_START - [15:0] */
+#define WM5100_DSP2_PM_START_WIDTH                  16  /* DSP2_PM_START - [15:0] */
+
+/*
+ * R26627 (0x6803) - DSP2 PM 3
+ */
+#define WM5100_DSP2_PM_1_2_MASK                 0x00FF  /* DSP2_PM_1 - [7:0] */
+#define WM5100_DSP2_PM_1_2_SHIFT                     0  /* DSP2_PM_1 - [7:0] */
+#define WM5100_DSP2_PM_1_2_WIDTH                     8  /* DSP2_PM_1 - [7:0] */
+
+/*
+ * R26628 (0x6804) - DSP2 PM 4
+ */
+#define WM5100_DSP2_PM_1_1_MASK                 0xFFFF  /* DSP2_PM_1 - [15:0] */
+#define WM5100_DSP2_PM_1_1_SHIFT                     0  /* DSP2_PM_1 - [15:0] */
+#define WM5100_DSP2_PM_1_1_WIDTH                    16  /* DSP2_PM_1 - [15:0] */
+
+/*
+ * R26629 (0x6805) - DSP2 PM 5
+ */
+#define WM5100_DSP2_PM_1_MASK                   0xFFFF  /* DSP2_PM_1 - [15:0] */
+#define WM5100_DSP2_PM_1_SHIFT                       0  /* DSP2_PM_1 - [15:0] */
+#define WM5100_DSP2_PM_1_WIDTH                      16  /* DSP2_PM_1 - [15:0] */
+
+/*
+ * R28154 (0x6DFA) - DSP2 PM 1530
+ */
+#define WM5100_DSP2_PM_510_2_MASK               0x00FF  /* DSP2_PM_510 - [7:0] */
+#define WM5100_DSP2_PM_510_2_SHIFT                   0  /* DSP2_PM_510 - [7:0] */
+#define WM5100_DSP2_PM_510_2_WIDTH                   8  /* DSP2_PM_510 - [7:0] */
+
+/*
+ * R28155 (0x6DFB) - DSP2 PM 1531
+ */
+#define WM5100_DSP2_PM_510_1_MASK               0xFFFF  /* DSP2_PM_510 - [15:0] */
+#define WM5100_DSP2_PM_510_1_SHIFT                   0  /* DSP2_PM_510 - [15:0] */
+#define WM5100_DSP2_PM_510_1_WIDTH                  16  /* DSP2_PM_510 - [15:0] */
+
+/*
+ * R28156 (0x6DFC) - DSP2 PM 1532
+ */
+#define WM5100_DSP2_PM_510_MASK                 0xFFFF  /* DSP2_PM_510 - [15:0] */
+#define WM5100_DSP2_PM_510_SHIFT                     0  /* DSP2_PM_510 - [15:0] */
+#define WM5100_DSP2_PM_510_WIDTH                    16  /* DSP2_PM_510 - [15:0] */
+
+/*
+ * R28157 (0x6DFD) - DSP2 PM 1533
+ */
+#define WM5100_DSP2_PM_END_2_MASK               0x00FF  /* DSP2_PM_END - [7:0] */
+#define WM5100_DSP2_PM_END_2_SHIFT                   0  /* DSP2_PM_END - [7:0] */
+#define WM5100_DSP2_PM_END_2_WIDTH                   8  /* DSP2_PM_END - [7:0] */
+
+/*
+ * R28158 (0x6DFE) - DSP2 PM 1534
+ */
+#define WM5100_DSP2_PM_END_1_MASK               0xFFFF  /* DSP2_PM_END - [15:0] */
+#define WM5100_DSP2_PM_END_1_SHIFT                   0  /* DSP2_PM_END - [15:0] */
+#define WM5100_DSP2_PM_END_1_WIDTH                  16  /* DSP2_PM_END - [15:0] */
+
+/*
+ * R28159 (0x6DFF) - DSP2 PM 1535
+ */
+#define WM5100_DSP2_PM_END_MASK                 0xFFFF  /* DSP2_PM_END - [15:0] */
+#define WM5100_DSP2_PM_END_SHIFT                     0  /* DSP2_PM_END - [15:0] */
+#define WM5100_DSP2_PM_END_WIDTH                    16  /* DSP2_PM_END - [15:0] */
+
+/*
+ * R28672 (0x7000) - DSP2 ZM 0
+ */
+#define WM5100_DSP2_ZM_START_1_MASK             0x00FF  /* DSP2_ZM_START - [7:0] */
+#define WM5100_DSP2_ZM_START_1_SHIFT                 0  /* DSP2_ZM_START - [7:0] */
+#define WM5100_DSP2_ZM_START_1_WIDTH                 8  /* DSP2_ZM_START - [7:0] */
+
+/*
+ * R28673 (0x7001) - DSP2 ZM 1
+ */
+#define WM5100_DSP2_ZM_START_MASK               0xFFFF  /* DSP2_ZM_START - [15:0] */
+#define WM5100_DSP2_ZM_START_SHIFT                   0  /* DSP2_ZM_START - [15:0] */
+#define WM5100_DSP2_ZM_START_WIDTH                  16  /* DSP2_ZM_START - [15:0] */
+
+/*
+ * R28674 (0x7002) - DSP2 ZM 2
+ */
+#define WM5100_DSP2_ZM_1_1_MASK                 0x00FF  /* DSP2_ZM_1 - [7:0] */
+#define WM5100_DSP2_ZM_1_1_SHIFT                     0  /* DSP2_ZM_1 - [7:0] */
+#define WM5100_DSP2_ZM_1_1_WIDTH                     8  /* DSP2_ZM_1 - [7:0] */
+
+/*
+ * R28675 (0x7003) - DSP2 ZM 3
+ */
+#define WM5100_DSP2_ZM_1_MASK                   0xFFFF  /* DSP2_ZM_1 - [15:0] */
+#define WM5100_DSP2_ZM_1_SHIFT                       0  /* DSP2_ZM_1 - [15:0] */
+#define WM5100_DSP2_ZM_1_WIDTH                      16  /* DSP2_ZM_1 - [15:0] */
+
+/*
+ * R30716 (0x77FC) - DSP2 ZM 2044
+ */
+#define WM5100_DSP2_ZM_1022_1_MASK              0x00FF  /* DSP2_ZM_1022 - [7:0] */
+#define WM5100_DSP2_ZM_1022_1_SHIFT                  0  /* DSP2_ZM_1022 - [7:0] */
+#define WM5100_DSP2_ZM_1022_1_WIDTH                  8  /* DSP2_ZM_1022 - [7:0] */
+
+/*
+ * R30717 (0x77FD) - DSP2 ZM 2045
+ */
+#define WM5100_DSP2_ZM_1022_MASK                0xFFFF  /* DSP2_ZM_1022 - [15:0] */
+#define WM5100_DSP2_ZM_1022_SHIFT                    0  /* DSP2_ZM_1022 - [15:0] */
+#define WM5100_DSP2_ZM_1022_WIDTH                   16  /* DSP2_ZM_1022 - [15:0] */
+
+/*
+ * R30718 (0x77FE) - DSP2 ZM 2046
+ */
+#define WM5100_DSP2_ZM_END_1_MASK               0x00FF  /* DSP2_ZM_END - [7:0] */
+#define WM5100_DSP2_ZM_END_1_SHIFT                   0  /* DSP2_ZM_END - [7:0] */
+#define WM5100_DSP2_ZM_END_1_WIDTH                   8  /* DSP2_ZM_END - [7:0] */
+
+/*
+ * R30719 (0x77FF) - DSP2 ZM 2047
+ */
+#define WM5100_DSP2_ZM_END_MASK                 0xFFFF  /* DSP2_ZM_END - [15:0] */
+#define WM5100_DSP2_ZM_END_SHIFT                     0  /* DSP2_ZM_END - [15:0] */
+#define WM5100_DSP2_ZM_END_WIDTH                    16  /* DSP2_ZM_END - [15:0] */
+
+/*
+ * R32768 (0x8000) - DSP3 DM 0
+ */
+#define WM5100_DSP3_DM_START_1_MASK             0x00FF  /* DSP3_DM_START - [7:0] */
+#define WM5100_DSP3_DM_START_1_SHIFT                 0  /* DSP3_DM_START - [7:0] */
+#define WM5100_DSP3_DM_START_1_WIDTH                 8  /* DSP3_DM_START - [7:0] */
+
+/*
+ * R32769 (0x8001) - DSP3 DM 1
+ */
+#define WM5100_DSP3_DM_START_MASK               0xFFFF  /* DSP3_DM_START - [15:0] */
+#define WM5100_DSP3_DM_START_SHIFT                   0  /* DSP3_DM_START - [15:0] */
+#define WM5100_DSP3_DM_START_WIDTH                  16  /* DSP3_DM_START - [15:0] */
+
+/*
+ * R32770 (0x8002) - DSP3 DM 2
+ */
+#define WM5100_DSP3_DM_1_1_MASK                 0x00FF  /* DSP3_DM_1 - [7:0] */
+#define WM5100_DSP3_DM_1_1_SHIFT                     0  /* DSP3_DM_1 - [7:0] */
+#define WM5100_DSP3_DM_1_1_WIDTH                     8  /* DSP3_DM_1 - [7:0] */
+
+/*
+ * R32771 (0x8003) - DSP3 DM 3
+ */
+#define WM5100_DSP3_DM_1_MASK                   0xFFFF  /* DSP3_DM_1 - [15:0] */
+#define WM5100_DSP3_DM_1_SHIFT                       0  /* DSP3_DM_1 - [15:0] */
+#define WM5100_DSP3_DM_1_WIDTH                      16  /* DSP3_DM_1 - [15:0] */
+
+/*
+ * R33276 (0x81FC) - DSP3 DM 508
+ */
+#define WM5100_DSP3_DM_254_1_MASK               0x00FF  /* DSP3_DM_254 - [7:0] */
+#define WM5100_DSP3_DM_254_1_SHIFT                   0  /* DSP3_DM_254 - [7:0] */
+#define WM5100_DSP3_DM_254_1_WIDTH                   8  /* DSP3_DM_254 - [7:0] */
+
+/*
+ * R33277 (0x81FD) - DSP3 DM 509
+ */
+#define WM5100_DSP3_DM_254_MASK                 0xFFFF  /* DSP3_DM_254 - [15:0] */
+#define WM5100_DSP3_DM_254_SHIFT                     0  /* DSP3_DM_254 - [15:0] */
+#define WM5100_DSP3_DM_254_WIDTH                    16  /* DSP3_DM_254 - [15:0] */
+
+/*
+ * R33278 (0x81FE) - DSP3 DM 510
+ */
+#define WM5100_DSP3_DM_END_1_MASK               0x00FF  /* DSP3_DM_END - [7:0] */
+#define WM5100_DSP3_DM_END_1_SHIFT                   0  /* DSP3_DM_END - [7:0] */
+#define WM5100_DSP3_DM_END_1_WIDTH                   8  /* DSP3_DM_END - [7:0] */
+
+/*
+ * R33279 (0x81FF) - DSP3 DM 511
+ */
+#define WM5100_DSP3_DM_END_MASK                 0xFFFF  /* DSP3_DM_END - [15:0] */
+#define WM5100_DSP3_DM_END_SHIFT                     0  /* DSP3_DM_END - [15:0] */
+#define WM5100_DSP3_DM_END_WIDTH                    16  /* DSP3_DM_END - [15:0] */
+
+/*
+ * R34816 (0x8800) - DSP3 PM 0
+ */
+#define WM5100_DSP3_PM_START_2_MASK             0x00FF  /* DSP3_PM_START - [7:0] */
+#define WM5100_DSP3_PM_START_2_SHIFT                 0  /* DSP3_PM_START - [7:0] */
+#define WM5100_DSP3_PM_START_2_WIDTH                 8  /* DSP3_PM_START - [7:0] */
+
+/*
+ * R34817 (0x8801) - DSP3 PM 1
+ */
+#define WM5100_DSP3_PM_START_1_MASK             0xFFFF  /* DSP3_PM_START - [15:0] */
+#define WM5100_DSP3_PM_START_1_SHIFT                 0  /* DSP3_PM_START - [15:0] */
+#define WM5100_DSP3_PM_START_1_WIDTH                16  /* DSP3_PM_START - [15:0] */
+
+/*
+ * R34818 (0x8802) - DSP3 PM 2
+ */
+#define WM5100_DSP3_PM_START_MASK               0xFFFF  /* DSP3_PM_START - [15:0] */
+#define WM5100_DSP3_PM_START_SHIFT                   0  /* DSP3_PM_START - [15:0] */
+#define WM5100_DSP3_PM_START_WIDTH                  16  /* DSP3_PM_START - [15:0] */
+
+/*
+ * R34819 (0x8803) - DSP3 PM 3
+ */
+#define WM5100_DSP3_PM_1_2_MASK                 0x00FF  /* DSP3_PM_1 - [7:0] */
+#define WM5100_DSP3_PM_1_2_SHIFT                     0  /* DSP3_PM_1 - [7:0] */
+#define WM5100_DSP3_PM_1_2_WIDTH                     8  /* DSP3_PM_1 - [7:0] */
+
+/*
+ * R34820 (0x8804) - DSP3 PM 4
+ */
+#define WM5100_DSP3_PM_1_1_MASK                 0xFFFF  /* DSP3_PM_1 - [15:0] */
+#define WM5100_DSP3_PM_1_1_SHIFT                     0  /* DSP3_PM_1 - [15:0] */
+#define WM5100_DSP3_PM_1_1_WIDTH                    16  /* DSP3_PM_1 - [15:0] */
+
+/*
+ * R34821 (0x8805) - DSP3 PM 5
+ */
+#define WM5100_DSP3_PM_1_MASK                   0xFFFF  /* DSP3_PM_1 - [15:0] */
+#define WM5100_DSP3_PM_1_SHIFT                       0  /* DSP3_PM_1 - [15:0] */
+#define WM5100_DSP3_PM_1_WIDTH                      16  /* DSP3_PM_1 - [15:0] */
+
+/*
+ * R36346 (0x8DFA) - DSP3 PM 1530
+ */
+#define WM5100_DSP3_PM_510_2_MASK               0x00FF  /* DSP3_PM_510 - [7:0] */
+#define WM5100_DSP3_PM_510_2_SHIFT                   0  /* DSP3_PM_510 - [7:0] */
+#define WM5100_DSP3_PM_510_2_WIDTH                   8  /* DSP3_PM_510 - [7:0] */
+
+/*
+ * R36347 (0x8DFB) - DSP3 PM 1531
+ */
+#define WM5100_DSP3_PM_510_1_MASK               0xFFFF  /* DSP3_PM_510 - [15:0] */
+#define WM5100_DSP3_PM_510_1_SHIFT                   0  /* DSP3_PM_510 - [15:0] */
+#define WM5100_DSP3_PM_510_1_WIDTH                  16  /* DSP3_PM_510 - [15:0] */
+
+/*
+ * R36348 (0x8DFC) - DSP3 PM 1532
+ */
+#define WM5100_DSP3_PM_510_MASK                 0xFFFF  /* DSP3_PM_510 - [15:0] */
+#define WM5100_DSP3_PM_510_SHIFT                     0  /* DSP3_PM_510 - [15:0] */
+#define WM5100_DSP3_PM_510_WIDTH                    16  /* DSP3_PM_510 - [15:0] */
+
+/*
+ * R36349 (0x8DFD) - DSP3 PM 1533
+ */
+#define WM5100_DSP3_PM_END_2_MASK               0x00FF  /* DSP3_PM_END - [7:0] */
+#define WM5100_DSP3_PM_END_2_SHIFT                   0  /* DSP3_PM_END - [7:0] */
+#define WM5100_DSP3_PM_END_2_WIDTH                   8  /* DSP3_PM_END - [7:0] */
+
+/*
+ * R36350 (0x8DFE) - DSP3 PM 1534
+ */
+#define WM5100_DSP3_PM_END_1_MASK               0xFFFF  /* DSP3_PM_END - [15:0] */
+#define WM5100_DSP3_PM_END_1_SHIFT                   0  /* DSP3_PM_END - [15:0] */
+#define WM5100_DSP3_PM_END_1_WIDTH                  16  /* DSP3_PM_END - [15:0] */
+
+/*
+ * R36351 (0x8DFF) - DSP3 PM 1535
+ */
+#define WM5100_DSP3_PM_END_MASK                 0xFFFF  /* DSP3_PM_END - [15:0] */
+#define WM5100_DSP3_PM_END_SHIFT                     0  /* DSP3_PM_END - [15:0] */
+#define WM5100_DSP3_PM_END_WIDTH                    16  /* DSP3_PM_END - [15:0] */
+
+/*
+ * R36864 (0x9000) - DSP3 ZM 0
+ */
+#define WM5100_DSP3_ZM_START_1_MASK             0x00FF  /* DSP3_ZM_START - [7:0] */
+#define WM5100_DSP3_ZM_START_1_SHIFT                 0  /* DSP3_ZM_START - [7:0] */
+#define WM5100_DSP3_ZM_START_1_WIDTH                 8  /* DSP3_ZM_START - [7:0] */
+
+/*
+ * R36865 (0x9001) - DSP3 ZM 1
+ */
+#define WM5100_DSP3_ZM_START_MASK               0xFFFF  /* DSP3_ZM_START - [15:0] */
+#define WM5100_DSP3_ZM_START_SHIFT                   0  /* DSP3_ZM_START - [15:0] */
+#define WM5100_DSP3_ZM_START_WIDTH                  16  /* DSP3_ZM_START - [15:0] */
+
+/*
+ * R36866 (0x9002) - DSP3 ZM 2
+ */
+#define WM5100_DSP3_ZM_1_1_MASK                 0x00FF  /* DSP3_ZM_1 - [7:0] */
+#define WM5100_DSP3_ZM_1_1_SHIFT                     0  /* DSP3_ZM_1 - [7:0] */
+#define WM5100_DSP3_ZM_1_1_WIDTH                     8  /* DSP3_ZM_1 - [7:0] */
+
+/*
+ * R36867 (0x9003) - DSP3 ZM 3
+ */
+#define WM5100_DSP3_ZM_1_MASK                   0xFFFF  /* DSP3_ZM_1 - [15:0] */
+#define WM5100_DSP3_ZM_1_SHIFT                       0  /* DSP3_ZM_1 - [15:0] */
+#define WM5100_DSP3_ZM_1_WIDTH                      16  /* DSP3_ZM_1 - [15:0] */
+
+/*
+ * R38908 (0x97FC) - DSP3 ZM 2044
+ */
+#define WM5100_DSP3_ZM_1022_1_MASK              0x00FF  /* DSP3_ZM_1022 - [7:0] */
+#define WM5100_DSP3_ZM_1022_1_SHIFT                  0  /* DSP3_ZM_1022 - [7:0] */
+#define WM5100_DSP3_ZM_1022_1_WIDTH                  8  /* DSP3_ZM_1022 - [7:0] */
+
+/*
+ * R38909 (0x97FD) - DSP3 ZM 2045
+ */
+#define WM5100_DSP3_ZM_1022_MASK                0xFFFF  /* DSP3_ZM_1022 - [15:0] */
+#define WM5100_DSP3_ZM_1022_SHIFT                    0  /* DSP3_ZM_1022 - [15:0] */
+#define WM5100_DSP3_ZM_1022_WIDTH                   16  /* DSP3_ZM_1022 - [15:0] */
+
+/*
+ * R38910 (0x97FE) - DSP3 ZM 2046
+ */
+#define WM5100_DSP3_ZM_END_1_MASK               0x00FF  /* DSP3_ZM_END - [7:0] */
+#define WM5100_DSP3_ZM_END_1_SHIFT                   0  /* DSP3_ZM_END - [7:0] */
+#define WM5100_DSP3_ZM_END_1_WIDTH                   8  /* DSP3_ZM_END - [7:0] */
+
+/*
+ * R38911 (0x97FF) - DSP3 ZM 2047
+ */
+#define WM5100_DSP3_ZM_END_MASK                 0xFFFF  /* DSP3_ZM_END - [15:0] */
+#define WM5100_DSP3_ZM_END_SHIFT                     0  /* DSP3_ZM_END - [15:0] */
+#define WM5100_DSP3_ZM_END_WIDTH                    16  /* DSP3_ZM_END - [15:0] */
+
+int wm5100_readable_register(struct snd_soc_codec *codec, unsigned int reg);
+int wm5100_volatile_register(struct snd_soc_codec *codec, unsigned int reg);
+
+extern u16 wm5100_reg_defaults[WM5100_MAX_REGISTER + 1];
+
+#endif
index 6d6dc9e..35f3ad8 100644 (file)
@@ -355,7 +355,7 @@ static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
                        return 1;
        }
 
-       ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
+       ret = snd_soc_put_volsw(kcontrol, ucontrol);
        if (ret < 0)
                return ret;
 
@@ -392,23 +392,9 @@ static int wm8350_get_volsw_2r(struct snd_kcontrol *kcontrol,
                break;
        }
 
-       return snd_soc_get_volsw_2r(kcontrol, ucontrol);
+       return snd_soc_get_volsw(kcontrol, ucontrol);
 }
 
-/* double control with volume update */
-#define SOC_WM8350_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \
-                               xinvert, tlv_array) \
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
-       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
-               SNDRV_CTL_ELEM_ACCESS_READWRITE | \
-               SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
-       .tlv.p = (tlv_array), \
-       .info = snd_soc_info_volsw_2r, \
-       .get = wm8350_get_volsw_2r, .put = wm8350_put_volsw_2r_vu, \
-       .private_value = (unsigned long)&(struct soc_mixer_control) \
-               {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
-                .rshift = xshift, .max = xmax, .invert = xinvert}, }
-
 static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
 static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" };
 static const char *wm8350_dacmutem[] = { "Normal", "Soft" };
@@ -443,26 +429,29 @@ static const unsigned int capture_sd_tlv[] = {
 static const struct snd_kcontrol_new wm8350_snd_controls[] = {
        SOC_ENUM("Playback Deemphasis", wm8350_enum[0]),
        SOC_ENUM("Playback DAC Inversion", wm8350_enum[1]),
-       SOC_WM8350_DOUBLE_R_TLV("Playback PCM Volume",
+       SOC_DOUBLE_R_EXT_TLV("Playback PCM Volume",
                                WM8350_DAC_DIGITAL_VOLUME_L,
                                WM8350_DAC_DIGITAL_VOLUME_R,
-                               0, 255, 0, dac_pcm_tlv),
+                               0, 255, 0, wm8350_get_volsw_2r,
+                               wm8350_put_volsw_2r_vu, dac_pcm_tlv),
        SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]),
        SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]),
        SOC_ENUM("Capture PCM Filter", wm8350_enum[4]),
        SOC_ENUM("Capture PCM HP Filter", wm8350_enum[5]),
        SOC_ENUM("Capture ADC Inversion", wm8350_enum[6]),
-       SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume",
+       SOC_DOUBLE_R_EXT_TLV("Capture PCM Volume",
                                WM8350_ADC_DIGITAL_VOLUME_L,
                                WM8350_ADC_DIGITAL_VOLUME_R,
-                               0, 255, 0, adc_pcm_tlv),
+                               0, 255, 0, wm8350_get_volsw_2r,
+                               wm8350_put_volsw_2r_vu, adc_pcm_tlv),
        SOC_DOUBLE_TLV("Capture Sidetone Volume",
                       WM8350_ADC_DIVIDER,
                       8, 4, 15, 1, capture_sd_tlv),
-       SOC_WM8350_DOUBLE_R_TLV("Capture Volume",
+       SOC_DOUBLE_R_EXT_TLV("Capture Volume",
                                WM8350_LEFT_INPUT_VOLUME,
                                WM8350_RIGHT_INPUT_VOLUME,
-                               2, 63, 0, pre_amp_tlv),
+                               2, 63, 0, wm8350_get_volsw_2r,
+                               wm8350_put_volsw_2r_vu, pre_amp_tlv),
        SOC_DOUBLE_R("Capture ZC Switch",
                     WM8350_LEFT_INPUT_VOLUME,
                     WM8350_RIGHT_INPUT_VOLUME, 13, 1, 0),
@@ -490,17 +479,19 @@ static const struct snd_kcontrol_new wm8350_snd_controls[] = {
        SOC_SINGLE_TLV("Out4 Capture Volume",
                       WM8350_INPUT_MIXER_VOLUME,
                       1, 7, 0, out_mix_tlv),
-       SOC_WM8350_DOUBLE_R_TLV("Out1 Playback Volume",
+       SOC_DOUBLE_R_EXT_TLV("Out1 Playback Volume",
                                WM8350_LOUT1_VOLUME,
                                WM8350_ROUT1_VOLUME,
-                               2, 63, 0, out_pga_tlv),
+                               2, 63, 0, wm8350_get_volsw_2r,
+                               wm8350_put_volsw_2r_vu, out_pga_tlv),
        SOC_DOUBLE_R("Out1 Playback ZC Switch",
                     WM8350_LOUT1_VOLUME,
                     WM8350_ROUT1_VOLUME, 13, 1, 0),
-       SOC_WM8350_DOUBLE_R_TLV("Out2 Playback Volume",
+       SOC_DOUBLE_R_EXT_TLV("Out2 Playback Volume",
                                WM8350_LOUT2_VOLUME,
                                WM8350_ROUT2_VOLUME,
-                               2, 63, 0, out_pga_tlv),
+                               2, 63, 0, wm8350_get_volsw_2r,
+                               wm8350_put_volsw_2r_vu, out_pga_tlv),
        SOC_DOUBLE_R("Out2 Playback ZC Switch", WM8350_LOUT2_VOLUME,
                     WM8350_ROUT2_VOLUME, 13, 1, 0),
        SOC_SINGLE("Out2 Right Invert Switch", WM8350_ROUT2_VOLUME, 10, 1, 0),
index fbee556..dc13be2 100644 (file)
@@ -383,7 +383,7 @@ static int inmixer_event (struct snd_soc_dapm_widget *w,
                (1 << WM8400_AINRMUX_PWR))) {
                reg |= WM8400_AINR_ENA;
        } else {
-               reg &= ~WM8400_AINL_ENA;
+               reg &= ~WM8400_AINR_ENA;
        }
        wm8400_write(w->codec, WM8400_POWER_MANAGEMENT_2, reg);
 
index 55a4c83..07c9cc7 100644 (file)
@@ -480,6 +480,8 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec,
                power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN;
 
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       snd_soc_cache_sync(codec);
+
                        /* Initial cap charge at VMID 5k */
                        snd_soc_write(codec, WM8510_POWER1, power1 | 0x3);
                        mdelay(100);
@@ -541,18 +543,7 @@ static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8510_resume(struct snd_soc_codec *codec)
 {
-       int i;
-       u8 data[2];
-       u16 *cache = codec->reg_cache;
-
-       /* Sync reg_cache with the hardware */
-       for (i = 0; i < ARRAY_SIZE(wm8510_reg); i++) {
-               data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-               data[1] = cache[i] & 0x00ff;
-               codec->hw_write(codec->control_data, data, 2);
-       }
        wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
        return 0;
 }
 
index 5355a7a..db7a681 100644 (file)
@@ -406,7 +406,6 @@ static int wm8523_probe(struct snd_soc_codec *codec)
        struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
        int ret, i;
 
-       codec->hw_write = (hw_write_t)i2c_master_send;
        wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
        wm8523->rate_constraint.count =
                ARRAY_SIZE(wm8523->rate_constraint_list);
index 4664c3a..8212b3c 100644 (file)
@@ -213,7 +213,7 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
        reg_cache[reg] = 0;
        reg_cache[reg2] = 0;
 
-       ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
+       ret = snd_soc_put_volsw(kcontrol, ucontrol);
        if (ret < 0)
                return ret;
 
@@ -224,31 +224,19 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-#define SOC_WM8580_OUT_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \
-                                   xinvert, tlv_array)                 \
-{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
-       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
-               SNDRV_CTL_ELEM_ACCESS_READWRITE,  \
-       .tlv.p = (tlv_array), \
-       .info = snd_soc_info_volsw_2r, \
-       .get = snd_soc_get_volsw_2r, .put = wm8580_out_vu, \
-       .private_value = (unsigned long)&(struct soc_mixer_control) \
-               {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
-               .max = xmax, .invert = xinvert} }
-
 static const struct snd_kcontrol_new wm8580_snd_controls[] = {
-SOC_WM8580_OUT_DOUBLE_R_TLV("DAC1 Playback Volume",
-                           WM8580_DIGITAL_ATTENUATION_DACL1,
-                           WM8580_DIGITAL_ATTENUATION_DACR1,
-                           0, 0xff, 0, dac_tlv),
-SOC_WM8580_OUT_DOUBLE_R_TLV("DAC2 Playback Volume",
-                           WM8580_DIGITAL_ATTENUATION_DACL2,
-                           WM8580_DIGITAL_ATTENUATION_DACR2,
-                           0, 0xff, 0, dac_tlv),
-SOC_WM8580_OUT_DOUBLE_R_TLV("DAC3 Playback Volume",
-                           WM8580_DIGITAL_ATTENUATION_DACL3,
-                           WM8580_DIGITAL_ATTENUATION_DACR3,
-                           0, 0xff, 0, dac_tlv),
+SOC_DOUBLE_R_EXT_TLV("DAC1 Playback Volume",
+                    WM8580_DIGITAL_ATTENUATION_DACL1,
+                    WM8580_DIGITAL_ATTENUATION_DACR1,
+                    0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),
+SOC_DOUBLE_R_EXT_TLV("DAC2 Playback Volume",
+                    WM8580_DIGITAL_ATTENUATION_DACL2,
+                    WM8580_DIGITAL_ATTENUATION_DACR2,
+                    0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),
+SOC_DOUBLE_R_EXT_TLV("DAC3 Playback Volume",
+                    WM8580_DIGITAL_ATTENUATION_DACL3,
+                    WM8580_DIGITAL_ATTENUATION_DACR3,
+                    0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),
 
 SOC_SINGLE("DAC1 Deemphasis Switch", WM8580_DAC_CONTROL3, 0, 1, 0),
 SOC_SINGLE("DAC2 Deemphasis Switch", WM8580_DAC_CONTROL3, 1, 1, 0),
@@ -442,8 +430,7 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
        /* Always disable the PLL - it is not safe to leave it running
         * while reprogramming it.
         */
-       reg = snd_soc_read(codec, WM8580_PWRDN2);
-       snd_soc_write(codec, WM8580_PWRDN2, reg | pwr_mask);
+       snd_soc_update_bits(codec, WM8580_PWRDN2, pwr_mask, pwr_mask);
 
        if (!freq_in || !freq_out)
                return 0;
@@ -461,8 +448,7 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
        snd_soc_write(codec, WM8580_PLLA4 + offset, reg);
 
        /* All done, turn it on */
-       reg = snd_soc_read(codec, WM8580_PWRDN2);
-       snd_soc_write(codec, WM8580_PWRDN2, reg & ~pwr_mask);
+       snd_soc_update_bits(codec, WM8580_PWRDN2, pwr_mask, 0);
 
        return 0;
 }
@@ -760,7 +746,6 @@ static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
 static int wm8580_set_bias_level(struct snd_soc_codec *codec,
        enum snd_soc_bias_level level)
 {
-       u16 reg;
        switch (level) {
        case SND_SOC_BIAS_ON:
        case SND_SOC_BIAS_PREPARE:
@@ -769,20 +754,19 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
        case SND_SOC_BIAS_STANDBY:
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
                        /* Power up and get individual control of the DACs */
-                       reg = snd_soc_read(codec, WM8580_PWRDN1);
-                       reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD);
-                       snd_soc_write(codec, WM8580_PWRDN1, reg);
+                       snd_soc_update_bits(codec, WM8580_PWRDN1,
+                                           WM8580_PWRDN1_PWDN |
+                                           WM8580_PWRDN1_ALLDACPD, 0);
 
                        /* Make VMID high impedance */
-                       reg = snd_soc_read(codec,  WM8580_ADC_CONTROL1);
-                       reg &= ~0x100;
-                       snd_soc_write(codec, WM8580_ADC_CONTROL1, reg);
+                       snd_soc_update_bits(codec, WM8580_ADC_CONTROL1,
+                                           0x100, 0);
                }
                break;
 
        case SND_SOC_BIAS_OFF:
-               reg = snd_soc_read(codec, WM8580_PWRDN1);
-               snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN);
+               snd_soc_update_bits(codec, WM8580_PWRDN1,
+                                   WM8580_PWRDN1_PWDN, WM8580_PWRDN1_PWDN);
                break;
        }
        codec->dapm.bias_level = level;
index 8457d3c..8d0347c 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2006 Wolfson Microelectronics
  *
- * Author: Mike Arthur <linux@wolfsonmicro.com>
+ * Author: Mike Arthur <Mike.Arthur@wolfsonmicro.com>
  *
  * Based on wm8731.c by Richard Purdie
  *
@@ -287,7 +287,6 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai,
        return 0;
 }
 
-
 static int wm8711_set_bias_level(struct snd_soc_codec *codec,
        enum snd_soc_bias_level level)
 {
@@ -300,6 +299,9 @@ static int wm8711_set_bias_level(struct snd_soc_codec *codec,
        case SND_SOC_BIAS_PREPARE:
                break;
        case SND_SOC_BIAS_STANDBY:
+               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
+                       snd_soc_cache_sync(codec);
+
                snd_soc_write(codec, WM8711_PWR, reg | 0x0040);
                break;
        case SND_SOC_BIAS_OFF:
@@ -346,25 +348,14 @@ static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8711_resume(struct snd_soc_codec *codec)
 {
-       int i;
-       u8 data[2];
-       u16 *cache = codec->reg_cache;
-
-       /* Sync reg_cache with the hardware */
-       for (i = 0; i < ARRAY_SIZE(wm8711_reg); i++) {
-               data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-               data[1] = cache[i] & 0x00ff;
-               codec->hw_write(codec->control_data, data, 2);
-       }
        wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
        return 0;
 }
 
 static int wm8711_probe(struct snd_soc_codec *codec)
 {
        struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
-       int ret, reg;
+       int ret;
 
        ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type);
        if (ret < 0) {
@@ -381,10 +372,8 @@ static int wm8711_probe(struct snd_soc_codec *codec)
        wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* Latch the update bits */
-       reg = snd_soc_read(codec, WM8711_LOUT1V);
-       snd_soc_write(codec, WM8711_LOUT1V, reg | 0x0100);
-       reg = snd_soc_read(codec, WM8711_ROUT1V);
-       snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100);
+       snd_soc_update_bits(codec, WM8711_LOUT1V, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8711_ROUT1V, 0x0100, 0x0100);
 
        snd_soc_add_controls(codec, wm8711_snd_controls,
                             ARRAY_SIZE(wm8711_snd_controls));
index f76b6fc..7e5ec03 100644 (file)
@@ -427,9 +427,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
        struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
-       int i, ret;
-       u8 data[2];
-       u16 *cache = codec->reg_cache;
+       int ret;
        u16 reg;
 
        switch (level) {
@@ -444,16 +442,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
                        if (ret != 0)
                                return ret;
 
-                       /* Sync reg_cache with the hardware */
-                       for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) {
-                               if (cache[i] == wm8731_reg[i])
-                                       continue;
-
-                               data[0] = (i << 1) | ((cache[i] >> 8)
-                                                     & 0x0001);
-                               data[1] = cache[i] & 0x00ff;
-                               codec->hw_write(codec->control_data, data, 2);
-                       }
+                       snd_soc_cache_sync(codec);
                }
 
                /* Clear PWROFF, gate CLKOUT, everything else as-is */
index 78c9e5a..57ad22a 100644 (file)
@@ -339,10 +339,10 @@ static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai,
                iface |= 0x0004;
                break;
        case SND_SOC_DAIFMT_DSP_A:
-               iface |= 0x0003;
+               iface |= 0x000C;
                break;
        case SND_SOC_DAIFMT_DSP_B:
-               iface |= 0x0013;
+               iface |= 0x001C;
                break;
        default:
                return -EINVAL;
@@ -404,15 +404,7 @@ static struct snd_soc_dai_driver wm8741_dai = {
 #ifdef CONFIG_PM
 static int wm8741_resume(struct snd_soc_codec *codec)
 {
-       u16 *cache = codec->reg_cache;
-       int i;
-
-       /* RESTORE REG Cache */
-       for (i = 0; i < WM8741_REGISTER_COUNT; i++) {
-               if (cache[i] == wm8741_reg_defaults[i] || WM8741_RESET == i)
-                       continue;
-               snd_soc_write(codec, i, cache[i]);
-       }
+       snd_soc_cache_sync(codec);
        return 0;
 }
 #else
@@ -462,7 +454,7 @@ static int wm8741_probe(struct snd_soc_codec *codec)
                            WM8741_UPDATELM, WM8741_UPDATELM);
        snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION,
                            WM8741_UPDATERL, WM8741_UPDATERL);
-       snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION,
+       snd_soc_update_bits(codec, WM8741_DACRMSB_ATTENUATION,
                            WM8741_UPDATERM, WM8741_UPDATERM);
 
        snd_soc_add_controls(codec, wm8741_snd_controls,
index 15f0372..ca75a81 100644 (file)
@@ -616,6 +616,8 @@ static int wm8750_set_bias_level(struct snd_soc_codec *codec,
                break;
        case SND_SOC_BIAS_STANDBY:
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       snd_soc_cache_sync(codec);
+
                        /* Set VMID to 5k */
                        snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
 
@@ -673,28 +675,14 @@ static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8750_resume(struct snd_soc_codec *codec)
 {
-       int i;
-       u8 data[2];
-       u16 *cache = codec->reg_cache;
-
-       /* Sync reg_cache with the hardware */
-       for (i = 0; i < ARRAY_SIZE(wm8750_reg); i++) {
-               if (i == WM8750_RESET)
-                       continue;
-               data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-               data[1] = cache[i] & 0x00ff;
-               codec->hw_write(codec->control_data, data, 2);
-       }
-
        wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
        return 0;
 }
 
 static int wm8750_probe(struct snd_soc_codec *codec)
 {
        struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
-       int reg, ret;
+       int ret;
 
        ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type);
        if (ret < 0) {
@@ -712,22 +700,14 @@ static int wm8750_probe(struct snd_soc_codec *codec)
        wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* set the update bits */
-       reg = snd_soc_read(codec, WM8750_LDAC);
-       snd_soc_write(codec, WM8750_LDAC, reg | 0x0100);
-       reg = snd_soc_read(codec, WM8750_RDAC);
-       snd_soc_write(codec, WM8750_RDAC, reg | 0x0100);
-       reg = snd_soc_read(codec, WM8750_LOUT1V);
-       snd_soc_write(codec, WM8750_LOUT1V, reg | 0x0100);
-       reg = snd_soc_read(codec, WM8750_ROUT1V);
-       snd_soc_write(codec, WM8750_ROUT1V, reg | 0x0100);
-       reg = snd_soc_read(codec, WM8750_LOUT2V);
-       snd_soc_write(codec, WM8750_LOUT2V, reg | 0x0100);
-       reg = snd_soc_read(codec, WM8750_ROUT2V);
-       snd_soc_write(codec, WM8750_ROUT2V, reg | 0x0100);
-       reg = snd_soc_read(codec, WM8750_LINVOL);
-       snd_soc_write(codec, WM8750_LINVOL, reg | 0x0100);
-       reg = snd_soc_read(codec, WM8750_RINVOL);
-       snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100);
+       snd_soc_update_bits(codec, WM8750_LDAC, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8750_RDAC, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8750_LOUT1V, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8750_ROUT1V, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8750_LOUT2V, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8750_ROUT2V, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8750_LINVOL, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8750_RINVOL, 0x0100, 0x0100);
 
        snd_soc_add_controls(codec, wm8750_snd_controls,
                                ARRAY_SIZE(wm8750_snd_controls));
index fe04a10..a950471 100644 (file)
@@ -1455,8 +1455,8 @@ static int wm8753_probe(struct snd_soc_codec *codec)
        /* set the update bits */
        snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
        snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
-       snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
-       snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8753_LADC, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8753_RADC, 0x0100, 0x0100);
        snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100);
        snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100);
        snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100);
index 00d8846..bfdc523 100644 (file)
@@ -308,6 +308,8 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec,
                break;
        case SND_SOC_BIAS_STANDBY:
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       snd_soc_cache_sync(codec);
+
                        /* Disable the global powerdown; DAPM does the rest */
                        snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0);
                }
@@ -379,21 +381,7 @@ static int wm8776_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8776_resume(struct snd_soc_codec *codec)
 {
-       int i;
-       u8 data[2];
-       u16 *cache = codec->reg_cache;
-
-       /* Sync reg_cache with the hardware */
-       for (i = 0; i < ARRAY_SIZE(wm8776_reg); i++) {
-               if (cache[i] == wm8776_reg[i])
-                       continue;
-               data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-               data[1] = cache[i] & 0x00ff;
-               codec->hw_write(codec->control_data, data, 2);
-       }
-
        wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
        return 0;
 }
 #else
index a2a09f8..f2ced71 100644 (file)
@@ -60,7 +60,7 @@ static struct platform_driver wm8782_codec_driver = {
                .owner = THIS_MODULE,
        },
        .probe = wm8782_probe,
-       .remove = wm8782_remove,
+       .remove = __devexit_p(wm8782_remove),
 };
 
 static int __init wm8782_init(void)
index 082040e..3d0dc15 100644 (file)
 
 #define WM8900_REG_CLOCKING1_BCLK_DIR   0x1
 #define WM8900_REG_CLOCKING1_MCLK_SRC   0x100
-#define WM8900_REG_CLOCKING1_BCLK_MASK  (~0x01e)
-#define WM8900_REG_CLOCKING1_OPCLK_MASK (~0x7000)
+#define WM8900_REG_CLOCKING1_BCLK_MASK  0x01e
+#define WM8900_REG_CLOCKING1_OPCLK_MASK 0x7000
 
 #define WM8900_REG_CLOCKING2_ADC_CLKDIV 0xe0
 #define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c
 #define WM8900_REG_HPCTL1_HP_SHORT       0x08
 #define WM8900_REG_HPCTL1_HP_SHORT2      0x04
 
-#define WM8900_LRC_MASK 0xfc00
+#define WM8900_LRC_MASK 0x03ff
 
 struct wm8900_priv {
        enum snd_soc_control_type control_type;
@@ -742,26 +742,20 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
 {
        struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
        struct _fll_div fll_div;
-       unsigned int reg;
 
        if (wm8900->fll_in == freq_in && wm8900->fll_out == freq_out)
                return 0;
 
        /* The digital side should be disabled during any change. */
-       reg = snd_soc_read(codec, WM8900_REG_POWER1);
-       snd_soc_write(codec, WM8900_REG_POWER1,
-                    reg & (~WM8900_REG_POWER1_FLL_ENA));
+       snd_soc_update_bits(codec, WM8900_REG_POWER1,
+                           WM8900_REG_POWER1_FLL_ENA, 0);
 
        /* Disable the FLL? */
        if (!freq_in || !freq_out) {
-               reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
-               snd_soc_write(codec, WM8900_REG_CLOCKING1,
-                            reg & (~WM8900_REG_CLOCKING1_MCLK_SRC));
-
-               reg = snd_soc_read(codec, WM8900_REG_FLLCTL1);
-               snd_soc_write(codec, WM8900_REG_FLLCTL1,
-                            reg & (~WM8900_REG_FLLCTL1_OSC_ENA));
-
+               snd_soc_update_bits(codec, WM8900_REG_CLOCKING1,
+                                   WM8900_REG_CLOCKING1_MCLK_SRC, 0);
+               snd_soc_update_bits(codec, WM8900_REG_FLLCTL1,
+                                   WM8900_REG_FLLCTL1_OSC_ENA, 0);
                wm8900->fll_in = freq_in;
                wm8900->fll_out = freq_out;
 
@@ -796,15 +790,14 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
        else
                snd_soc_write(codec, WM8900_REG_FLLCTL6, 0);
 
-       reg = snd_soc_read(codec, WM8900_REG_POWER1);
-       snd_soc_write(codec, WM8900_REG_POWER1,
-                    reg | WM8900_REG_POWER1_FLL_ENA);
+       snd_soc_update_bits(codec, WM8900_REG_POWER1,
+                           WM8900_REG_POWER1_FLL_ENA,
+                           WM8900_REG_POWER1_FLL_ENA);
 
 reenable:
-       reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
-       snd_soc_write(codec, WM8900_REG_CLOCKING1,
-                    reg | WM8900_REG_CLOCKING1_MCLK_SRC);
-
+       snd_soc_update_bits(codec, WM8900_REG_CLOCKING1,
+                           WM8900_REG_CLOCKING1_MCLK_SRC,
+                           WM8900_REG_CLOCKING1_MCLK_SRC);
        return 0;
 }
 
@@ -818,43 +811,35 @@ static int wm8900_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
                                 int div_id, int div)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
-       unsigned int reg;
 
        switch (div_id) {
        case WM8900_BCLK_DIV:
-               reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
-               snd_soc_write(codec, WM8900_REG_CLOCKING1,
-                            div | (reg & WM8900_REG_CLOCKING1_BCLK_MASK));
+               snd_soc_update_bits(codec, WM8900_REG_CLOCKING1,
+                                   WM8900_REG_CLOCKING1_BCLK_MASK, div);
                break;
        case WM8900_OPCLK_DIV:
-               reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
-               snd_soc_write(codec, WM8900_REG_CLOCKING1,
-                            div | (reg & WM8900_REG_CLOCKING1_OPCLK_MASK));
+               snd_soc_update_bits(codec, WM8900_REG_CLOCKING1,
+                                   WM8900_REG_CLOCKING1_OPCLK_MASK, div);
                break;
        case WM8900_DAC_LRCLK:
-               reg = snd_soc_read(codec, WM8900_REG_AUDIO4);
-               snd_soc_write(codec, WM8900_REG_AUDIO4,
-                            div | (reg & WM8900_LRC_MASK));
+               snd_soc_update_bits(codec, WM8900_REG_AUDIO4,
+                                   WM8900_LRC_MASK, div);
                break;
        case WM8900_ADC_LRCLK:
-               reg = snd_soc_read(codec, WM8900_REG_AUDIO3);
-               snd_soc_write(codec, WM8900_REG_AUDIO3,
-                            div | (reg & WM8900_LRC_MASK));
+               snd_soc_update_bits(codec, WM8900_REG_AUDIO3,
+                                   WM8900_LRC_MASK, div);
                break;
        case WM8900_DAC_CLKDIV:
-               reg = snd_soc_read(codec, WM8900_REG_CLOCKING2);
-               snd_soc_write(codec, WM8900_REG_CLOCKING2,
-                            div | (reg & WM8900_REG_CLOCKING2_DAC_CLKDIV));
+               snd_soc_update_bits(codec, WM8900_REG_CLOCKING2,
+                                   WM8900_REG_CLOCKING2_DAC_CLKDIV, div);
                break;
        case WM8900_ADC_CLKDIV:
-               reg = snd_soc_read(codec, WM8900_REG_CLOCKING2);
-               snd_soc_write(codec, WM8900_REG_CLOCKING2,
-                            div | (reg & WM8900_REG_CLOCKING2_ADC_CLKDIV));
+               snd_soc_update_bits(codec, WM8900_REG_CLOCKING2,
+                                   WM8900_REG_CLOCKING2_ADC_CLKDIV, div);
                break;
        case WM8900_LRCLK_MODE:
-               reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
-               snd_soc_write(codec, WM8900_REG_DACCTRL,
-                            div | (reg & WM8900_REG_DACCTRL_AIF_LRCLKRATE));
+               snd_soc_update_bits(codec, WM8900_REG_DACCTRL,
+                                   WM8900_REG_DACCTRL_AIF_LRCLKRATE, div);
                break;
        default:
                return -EINVAL;
@@ -1037,12 +1022,12 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
        switch (level) {
        case SND_SOC_BIAS_ON:
                /* Enable thermal shutdown */
-               reg = snd_soc_read(codec, WM8900_REG_GPIO);
-               snd_soc_write(codec, WM8900_REG_GPIO,
-                            reg | WM8900_REG_GPIO_TEMP_ENA);
-               reg = snd_soc_read(codec, WM8900_REG_ADDCTL);
-               snd_soc_write(codec, WM8900_REG_ADDCTL,
-                            reg | WM8900_REG_ADDCTL_TEMP_SD);
+               snd_soc_update_bits(codec, WM8900_REG_GPIO,
+                                   WM8900_REG_GPIO_TEMP_ENA,
+                                   WM8900_REG_GPIO_TEMP_ENA);
+               snd_soc_update_bits(codec, WM8900_REG_ADDCTL,
+                                   WM8900_REG_ADDCTL_TEMP_SD,
+                                   WM8900_REG_ADDCTL_TEMP_SD);
                break;
 
        case SND_SOC_BIAS_PREPARE:
@@ -1205,26 +1190,16 @@ static int wm8900_probe(struct snd_soc_codec *codec)
        wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* Latch the volume update bits */
-       snd_soc_write(codec, WM8900_REG_LINVOL,
-                     snd_soc_read(codec, WM8900_REG_LINVOL) | 0x100);
-       snd_soc_write(codec, WM8900_REG_RINVOL,
-                     snd_soc_read(codec, WM8900_REG_RINVOL) | 0x100);
-       snd_soc_write(codec, WM8900_REG_LOUT1CTL,
-                     snd_soc_read(codec, WM8900_REG_LOUT1CTL) | 0x100);
-       snd_soc_write(codec, WM8900_REG_ROUT1CTL,
-                     snd_soc_read(codec, WM8900_REG_ROUT1CTL) | 0x100);
-       snd_soc_write(codec, WM8900_REG_LOUT2CTL,
-                     snd_soc_read(codec, WM8900_REG_LOUT2CTL) | 0x100);
-       snd_soc_write(codec, WM8900_REG_ROUT2CTL,
-                     snd_soc_read(codec, WM8900_REG_ROUT2CTL) | 0x100);
-       snd_soc_write(codec, WM8900_REG_LDAC_DV,
-                     snd_soc_read(codec, WM8900_REG_LDAC_DV) | 0x100);
-       snd_soc_write(codec, WM8900_REG_RDAC_DV,
-                     snd_soc_read(codec, WM8900_REG_RDAC_DV) | 0x100);
-       snd_soc_write(codec, WM8900_REG_LADC_DV,
-                     snd_soc_read(codec, WM8900_REG_LADC_DV) | 0x100);
-       snd_soc_write(codec, WM8900_REG_RADC_DV,
-                     snd_soc_read(codec, WM8900_REG_RADC_DV) | 0x100);
+       snd_soc_update_bits(codec, WM8900_REG_LINVOL, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8900_REG_RINVOL, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8900_REG_LOUT1CTL, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8900_REG_ROUT1CTL, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8900_REG_LOUT2CTL, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8900_REG_ROUT2CTL, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8900_REG_LDAC_DV, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8900_REG_RDAC_DV, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8900_REG_LADC_DV, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8900_REG_RADC_DV, 0x100, 0x100);
 
        /* Set the DAC and mixer output bias */
        snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
index b085575..9fc8f4c 100644 (file)
@@ -50,7 +50,6 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
 struct wm8904_priv {
 
        enum wm8904_type devtype;
-       void *control_data;
 
        struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES];
 
@@ -2540,7 +2539,6 @@ static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
 
        wm8904->devtype = id->driver_data;
        i2c_set_clientdata(i2c, wm8904);
-       wm8904->control_data = i2c;
        wm8904->pdata = i2c->dev.platform_data;
 
        ret = snd_soc_register_codec(&i2c->dev,
index 056daa0..dc5cb31 100644 (file)
 struct wm8940_priv {
        unsigned int sysclk;
        enum snd_soc_control_type control_type;
-       void *control_data;
 };
 
+static int wm8940_volatile_register(struct snd_soc_codec *codec,
+                                   unsigned int reg)
+{
+       switch (reg) {
+       case WM8940_SOFTRESET:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
 static u16 wm8940_reg_defaults[] = {
        0x8940, /* Soft Reset */
        0x0000, /* Power 1 */
@@ -460,6 +470,14 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec,
                ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1);
                break;
        case SND_SOC_BIAS_STANDBY:
+               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       ret = snd_soc_cache_sync(codec);
+                       if (ret < 0) {
+                               dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
+                               return ret;
+                       }
+               }
+
                /* ensure bufioen and biasen */
                pwr_reg |= (1 << 2) | (1 << 3);
                /* set vmid to 300k for standby */
@@ -470,6 +488,8 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec,
                break;
        }
 
+       codec->dapm.bias_level = level;
+
        return ret;
 }
 
@@ -660,30 +680,8 @@ static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8940_resume(struct snd_soc_codec *codec)
 {
-       int i;
-       int ret;
-       u8 data[3];
-       u16 *cache = codec->reg_cache;
-
-       /* Sync reg_cache with the hardware
-        * Could use auto incremented writes to speed this up
-        */
-       for (i = 0; i < ARRAY_SIZE(wm8940_reg_defaults); i++) {
-               data[0] = i;
-               data[1] = (cache[i] & 0xFF00) >> 8;
-               data[2] = cache[i] & 0x00FF;
-               ret = codec->hw_write(codec->control_data, data, 3);
-               if (ret < 0)
-                       goto error_ret;
-               else if (ret != 3) {
-                       ret = -EIO;
-                       goto error_ret;
-               }
-       }
-       ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
-error_ret:
-       return ret;
+       wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       return 0;
 }
 
 static int wm8940_probe(struct snd_soc_codec *codec)
@@ -693,7 +691,6 @@ static int wm8940_probe(struct snd_soc_codec *codec)
        int ret;
        u16 reg;
 
-       codec->control_data = wm8940->control_data;
        ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -744,6 +741,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
        .reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults),
        .reg_word_size = sizeof(u16),
        .reg_cache_default = wm8940_reg_defaults,
+       .volatile_register = wm8940_volatile_register,
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
@@ -758,7 +756,6 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm8940);
-       wm8940->control_data = i2c;
        wm8940->control_type = SND_SOC_I2C;
 
        ret = snd_soc_register_codec(&i2c->dev,
index 4393394..2df253c 100644 (file)
@@ -72,7 +72,6 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = {
 
 struct wm8960_priv {
        enum snd_soc_control_type control_type;
-       void *control_data;
        int (*set_bias_level)(struct snd_soc_codec *,
                              enum snd_soc_bias_level level);
        struct snd_soc_dapm_widget *lout1;
@@ -575,6 +574,8 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec,
 
        case SND_SOC_BIAS_STANDBY:
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       snd_soc_cache_sync(codec);
+
                        /* Enable anti-pop features */
                        snd_soc_write(codec, WM8960_APOP1,
                                      WM8960_POBCTRL | WM8960_SOFT_ST |
@@ -677,6 +678,9 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec,
                                            WM8960_VREF | WM8960_VMID_MASK, 0);
                        break;
 
+               case SND_SOC_BIAS_OFF:
+                       snd_soc_cache_sync(codec);
+                       break;
                default:
                        break;
                }
@@ -902,16 +906,6 @@ static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state)
 static int wm8960_resume(struct snd_soc_codec *codec)
 {
        struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
-       int i;
-       u8 data[2];
-       u16 *cache = codec->reg_cache;
-
-       /* Sync reg_cache with the hardware */
-       for (i = 0; i < ARRAY_SIZE(wm8960_reg); i++) {
-               data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-               data[1] = cache[i] & 0x00ff;
-               codec->hw_write(codec->control_data, data, 2);
-       }
 
        wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        return 0;
@@ -925,7 +919,6 @@ static int wm8960_probe(struct snd_soc_codec *codec)
        u16 reg;
 
        wm8960->set_bias_level = wm8960_set_bias_level_out3;
-       codec->control_data = wm8960->control_data;
 
        if (!pdata) {
                dev_warn(codec->dev, "No platform data supplied\n");
@@ -1015,7 +1008,6 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
 
        i2c_set_clientdata(i2c, wm8960);
        wm8960->control_type = SND_SOC_I2C;
-       wm8960->control_data = i2c;
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8960, &wm8960_dai, 1);
index cdee810..9568c8a 100644 (file)
@@ -974,7 +974,9 @@ static int wm8961_probe(struct snd_soc_codec *codec)
        }
 
        /* This isn't volatile - readback doesn't correspond to write */
-       reg = codec->hw_read(codec, WM8961_RIGHT_INPUT_VOLUME);
+       codec->cache_bypass = 1;
+       reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME);
+       codec->cache_bypass = 0;
        dev_info(codec->dev, "WM8961 family %d revision %c\n",
                 (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT,
                 ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT)
index 3676b38..f60dfa1 100644 (file)
@@ -2139,7 +2139,6 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
                            struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       u16 *reg_cache = codec->reg_cache;
        int ret;
 
        /* Apply the update (if any) */
@@ -2148,16 +2147,19 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
                return 0;
 
        /* If the left PGA is enabled hit that VU bit... */
-       if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTL_PGA_ENA)
-               return snd_soc_write(codec, WM8962_SPKOUTL_VOLUME,
-                                    reg_cache[WM8962_SPKOUTL_VOLUME]);
+       ret = snd_soc_read(codec, WM8962_PWR_MGMT_2);
+       if (ret & WM8962_SPKOUTL_PGA_ENA) {
+               snd_soc_write(codec, WM8962_SPKOUTL_VOLUME,
+                             snd_soc_read(codec, WM8962_SPKOUTL_VOLUME));
+               return 1;
+       }
 
        /* ...otherwise the right.  The VU is stereo. */
-       if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTR_PGA_ENA)
-               return snd_soc_write(codec, WM8962_SPKOUTR_VOLUME,
-                                    reg_cache[WM8962_SPKOUTR_VOLUME]);
+       if (ret & WM8962_SPKOUTR_PGA_ENA)
+               snd_soc_write(codec, WM8962_SPKOUTR_VOLUME,
+                             snd_soc_read(codec, WM8962_SPKOUTR_VOLUME));
 
-       return 0;
+       return 1;
 }
 
 static const char *cap_hpf_mode_text[] = {
@@ -2498,7 +2500,6 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
                         struct snd_kcontrol *kcontrol, int event)
 {
        struct snd_soc_codec *codec = w->codec;
-       u16 *reg_cache = codec->reg_cache;
        int reg;
 
        switch (w->shift) {
@@ -2521,7 +2522,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
 
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
-               return snd_soc_write(codec, reg, reg_cache[reg]);
+               return snd_soc_write(codec, reg, snd_soc_read(codec, reg));
        default:
                BUG();
                return -EINVAL;
@@ -2667,7 +2668,7 @@ SND_SOC_DAPM_INPUT("IN4R"),
 SND_SOC_DAPM_INPUT("Beep"),
 SND_SOC_DAPM_INPUT("DMICDAT"),
 
-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8962_PWR_MGMT_1, 1, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8962_PWR_MGMT_1, 1, 0, NULL, 0),
 
 SND_SOC_DAPM_SUPPLY("Class G", WM8962_CHARGE_PUMP_B, 0, 1, NULL, 0),
 SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event,
@@ -2688,7 +2689,7 @@ SND_SOC_DAPM_MIXER("MIXINL", WM8962_PWR_MGMT_1, 5, 0,
 SND_SOC_DAPM_MIXER("MIXINR", WM8962_PWR_MGMT_1, 4, 0,
                   mixinr, ARRAY_SIZE(mixinr)),
 
-SND_SOC_DAPM_AIF_IN("DMIC", NULL, 0, WM8962_PWR_MGMT_1, 10, 0),
+SND_SOC_DAPM_AIF_IN("DMIC_ENA", NULL, 0, WM8962_PWR_MGMT_1, 10, 0),
 
 SND_SOC_DAPM_ADC("ADCL", "Capture", WM8962_PWR_MGMT_1, 3, 0),
 SND_SOC_DAPM_ADC("ADCR", "Capture", WM8962_PWR_MGMT_1, 2, 0),
@@ -2767,18 +2768,18 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = {
 
        { "MICBIAS", NULL, "SYSCLK" },
 
-       { "DMIC", NULL, "DMICDAT" },
+       { "DMIC_ENA", NULL, "DMICDAT" },
 
        { "ADCL", NULL, "SYSCLK" },
        { "ADCL", NULL, "TOCLK" },
        { "ADCL", NULL, "MIXINL" },
-       { "ADCL", NULL, "DMIC" },
+       { "ADCL", NULL, "DMIC_ENA" },
        { "ADCL", NULL, "DSP2" },
 
        { "ADCR", NULL, "SYSCLK" },
        { "ADCR", NULL, "TOCLK" },
        { "ADCR", NULL, "MIXINR" },
-       { "ADCR", NULL, "DMIC" },
+       { "ADCR", NULL, "DMIC_ENA" },
        { "ADCR", NULL, "DSP2" },
 
        { "STL", "Left", "ADCL" },
@@ -3223,9 +3224,9 @@ static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
        int aif0 = 0;
 
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-       case SND_SOC_DAIFMT_DSP_A:
-               aif0 |= WM8962_LRCLK_INV;
        case SND_SOC_DAIFMT_DSP_B:
+               aif0 |= WM8962_LRCLK_INV | 3;
+       case SND_SOC_DAIFMT_DSP_A:
                aif0 |= 3;
 
                switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
index 572bb80..b444b29 100644 (file)
@@ -546,6 +546,9 @@ static int wm8971_set_bias_level(struct snd_soc_codec *codec,
        case SND_SOC_BIAS_PREPARE:
                break;
        case SND_SOC_BIAS_STANDBY:
+               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
+                       snd_soc_cache_sync(codec);
+
                /* mute dac and set vmid to 500k, enable VREF */
                snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140);
                break;
@@ -605,20 +608,8 @@ static int wm8971_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8971_resume(struct snd_soc_codec *codec)
 {
-       int i;
-       u8 data[2];
-       u16 *cache = codec->reg_cache;
        u16 reg;
 
-       /* Sync reg_cache with the hardware */
-       for (i = 0; i < ARRAY_SIZE(wm8971_reg); i++) {
-               if (i + 1 == WM8971_RESET)
-                       continue;
-               data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-               data[1] = cache[i] & 0x00ff;
-               codec->hw_write(codec->control_data, data, 2);
-       }
-
        wm8971_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* charge wm8971 caps */
@@ -660,25 +651,14 @@ static int wm8971_probe(struct snd_soc_codec *codec)
                msecs_to_jiffies(1000));
 
        /* set the update bits */
-       reg = snd_soc_read(codec, WM8971_LDAC);
-       snd_soc_write(codec, WM8971_LDAC, reg | 0x0100);
-       reg = snd_soc_read(codec, WM8971_RDAC);
-       snd_soc_write(codec, WM8971_RDAC, reg | 0x0100);
-
-       reg = snd_soc_read(codec, WM8971_LOUT1V);
-       snd_soc_write(codec, WM8971_LOUT1V, reg | 0x0100);
-       reg = snd_soc_read(codec, WM8971_ROUT1V);
-       snd_soc_write(codec, WM8971_ROUT1V, reg | 0x0100);
-
-       reg = snd_soc_read(codec, WM8971_LOUT2V);
-       snd_soc_write(codec, WM8971_LOUT2V, reg | 0x0100);
-       reg = snd_soc_read(codec, WM8971_ROUT2V);
-       snd_soc_write(codec, WM8971_ROUT2V, reg | 0x0100);
-
-       reg = snd_soc_read(codec, WM8971_LINVOL);
-       snd_soc_write(codec, WM8971_LINVOL, reg | 0x0100);
-       reg = snd_soc_read(codec, WM8971_RINVOL);
-       snd_soc_write(codec, WM8971_RINVOL, reg | 0x0100);
+       snd_soc_update_bits(codec, WM8971_LDAC, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8971_RDAC, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8971_LOUT1V, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8971_ROUT1V, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8971_LOUT2V, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8971_ROUT2V, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8971_LINVOL, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8971_RINVOL, 0x0100, 0x0100);
 
        snd_soc_add_controls(codec, wm8971_snd_controls,
                                ARRAY_SIZE(wm8971_snd_controls));
index ca646a8..9352f1e 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2006-2009 Wolfson Microelectronics PLC.
  *
- * Author: Liam Girdwood <linux@wolfsonmicro.com>
+ * Author: Liam Girdwood <Liam.Girdwood@wolfsonmicro.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -530,6 +530,8 @@ static int wm8974_set_bias_level(struct snd_soc_codec *codec,
                power1 |= WM8974_POWER1_BIASEN | WM8974_POWER1_BUFIOEN;
 
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       snd_soc_cache_sync(codec);
+
                        /* Initial cap charge at VMID 5k */
                        snd_soc_write(codec, WM8974_POWER1, power1 | 0x3);
                        mdelay(100);
@@ -589,18 +591,7 @@ static int wm8974_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8974_resume(struct snd_soc_codec *codec)
 {
-       int i;
-       u8 data[2];
-       u16 *cache = codec->reg_cache;
-
-       /* Sync reg_cache with the hardware */
-       for (i = 0; i < ARRAY_SIZE(wm8974_reg); i++) {
-               data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-               data[1] = cache[i] & 0x00ff;
-               codec->hw_write(codec->control_data, data, 2);
-       }
        wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
        return 0;
 }
 
index 85e3e63..41ca4d9 100644 (file)
@@ -52,7 +52,6 @@ static const u16 wm8978_reg[WM8978_CACHEREGNUM] = {
 /* codec private data */
 struct wm8978_priv {
        enum snd_soc_control_type control_type;
-       void *control_data;
        unsigned int f_pllout;
        unsigned int f_mclk;
        unsigned int f_256fs;
@@ -955,7 +954,6 @@ static int wm8978_probe(struct snd_soc_codec *codec)
         * default hardware setting
         */
        wm8978->sysclk = WM8978_PLL;
-       codec->control_data = wm8978->control_data;
        ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -1016,7 +1014,6 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm8978);
-       wm8978->control_data = i2c;
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8978, &wm8978_dai, 1);
index 17f04ec..93ee284 100644 (file)
@@ -1007,7 +1007,7 @@ static int wm8983_probe(struct snd_soc_codec *codec)
                return ret;
        }
 
-       ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0x8983);
+       ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
                return ret;
index d7170f1..2e9eba7 100644 (file)
@@ -55,7 +55,6 @@ struct wm8988_priv {
        struct snd_pcm_hw_constraint_list *sysclk_constraints;
 };
 
-
 #define wm8988_reset(c)        snd_soc_write(c, WM8988_RESET, 0)
 
 /*
@@ -676,6 +675,8 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
 
        case SND_SOC_BIAS_STANDBY:
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       snd_soc_cache_sync(codec);
+
                        /* VREF, VMID=2x5k */
                        snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
 
@@ -736,21 +737,7 @@ static int wm8988_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8988_resume(struct snd_soc_codec *codec)
 {
-       int i;
-       u8 data[2];
-       u16 *cache = codec->reg_cache;
-
-       /* Sync reg_cache with the hardware */
-       for (i = 0; i < WM8988_NUM_REG; i++) {
-               if (i == WM8988_RESET)
-                       continue;
-               data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-               data[1] = cache[i] & 0x00ff;
-               codec->hw_write(codec->control_data, data, 2);
-       }
-
        wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
        return 0;
 }
 
@@ -759,7 +746,6 @@ static int wm8988_probe(struct snd_soc_codec *codec)
        struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
        struct snd_soc_dapm_context *dapm = &codec->dapm;
        int ret = 0;
-       u16 reg;
 
        ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type);
        if (ret < 0) {
@@ -774,16 +760,11 @@ static int wm8988_probe(struct snd_soc_codec *codec)
        }
 
        /* set the update bits (we always update left then right) */
-       reg = snd_soc_read(codec, WM8988_RADC);
-       snd_soc_write(codec, WM8988_RADC, reg | 0x100);
-       reg = snd_soc_read(codec, WM8988_RDAC);
-       snd_soc_write(codec, WM8988_RDAC, reg | 0x0100);
-       reg = snd_soc_read(codec, WM8988_ROUT1V);
-       snd_soc_write(codec, WM8988_ROUT1V, reg | 0x0100);
-       reg = snd_soc_read(codec, WM8988_ROUT2V);
-       snd_soc_write(codec, WM8988_ROUT2V, reg | 0x0100);
-       reg = snd_soc_read(codec, WM8988_RINVOL);
-       snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100);
+       snd_soc_update_bits(codec, WM8988_RADC, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8988_RDAC, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8988_ROUT1V, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8988_ROUT2V, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8988_RINVOL, 0x0100, 0x0100);
 
        wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
index 100aeee..d29a962 100644 (file)
@@ -36,10 +36,17 @@ struct wm8990_priv {
        unsigned int pcmclk;
 };
 
-/*
- * wm8990 register cache.  Note that register 0 is not included in the
- * cache.
- */
+static int wm8990_volatile_register(struct snd_soc_codec *codec,
+                                   unsigned int reg)
+{
+       switch (reg) {
+       case WM8990_RESET:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
 static const u16 wm8990_reg[] = {
        0x8990,     /* R0  - Reset */
        0x0000,     /* R1  - Power Management (1) */
@@ -394,7 +401,7 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
                (1 << WM8990_AINRMUX_PWR_BIT))) {
                reg |= WM8990_AINR_ENA;
        } else {
-               reg &= ~WM8990_AINL_ENA;
+               reg &= ~WM8990_AINR_ENA;
        }
        snd_soc_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg);
 
@@ -974,7 +981,6 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
 static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
                int source, unsigned int freq_in, unsigned int freq_out)
 {
-       u16 reg;
        struct snd_soc_codec *codec = codec_dai->codec;
        struct _pll_div pll_div;
 
@@ -982,13 +988,12 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
                pll_factors(&pll_div, freq_out * 4, freq_in);
 
                /* Turn on PLL */
-               reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
-               reg |= WM8990_PLL_ENA;
-               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
+               snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2,
+                                   WM8990_PLL_ENA, WM8990_PLL_ENA);
 
                /* sysclk comes from PLL */
-               reg = snd_soc_read(codec, WM8990_CLOCKING_2);
-               snd_soc_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC);
+               snd_soc_update_bits(codec, WM8990_CLOCKING_2,
+                                   WM8990_SYSCLK_SRC, WM8990_SYSCLK_SRC);
 
                /* set up N , fractional mode and pre-divisor if necessary */
                snd_soc_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM |
@@ -996,10 +1001,9 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
                snd_soc_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8));
                snd_soc_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF));
        } else {
-               /* Turn on PLL */
-               reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
-               reg &= ~WM8990_PLL_ENA;
-               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
+               /* Turn off PLL */
+               snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2,
+                                   WM8990_PLL_ENA, 0);
        }
        return 0;
 }
@@ -1077,28 +1081,23 @@ static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
                int div_id, int div)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
-       u16 reg;
 
        switch (div_id) {
        case WM8990_MCLK_DIV:
-               reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
-                       ~WM8990_MCLK_DIV_MASK;
-               snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
+               snd_soc_update_bits(codec, WM8990_CLOCKING_2,
+                                   WM8990_MCLK_DIV_MASK, div);
                break;
        case WM8990_DACCLK_DIV:
-               reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
-                       ~WM8990_DAC_CLKDIV_MASK;
-               snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
+               snd_soc_update_bits(codec, WM8990_CLOCKING_2,
+                                   WM8990_DAC_CLKDIV_MASK, div);
                break;
        case WM8990_ADCCLK_DIV:
-               reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
-                       ~WM8990_ADC_CLKDIV_MASK;
-               snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
+               snd_soc_update_bits(codec, WM8990_CLOCKING_2,
+                                   WM8990_ADC_CLKDIV_MASK, div);
                break;
        case WM8990_BCLK_DIV:
-               reg = snd_soc_read(codec, WM8990_CLOCKING_1) &
-                       ~WM8990_BCLK_DIV_MASK;
-               snd_soc_write(codec, WM8990_CLOCKING_1, reg | div);
+               snd_soc_update_bits(codec, WM8990_CLOCKING_1,
+                                   WM8990_BCLK_DIV_MASK, div);
                break;
        default:
                return -EINVAL;
@@ -1156,7 +1155,7 @@ static int wm8990_mute(struct snd_soc_dai *dai, int mute)
 static int wm8990_set_bias_level(struct snd_soc_codec *codec,
        enum snd_soc_bias_level level)
 {
-       u16 val;
+       int ret;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
@@ -1164,13 +1163,18 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
 
        case SND_SOC_BIAS_PREPARE:
                /* VMID=2*50k */
-               val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) &
-                       ~WM8990_VMID_MODE_MASK;
-               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2);
+               snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_1,
+                                   WM8990_VMID_MODE_MASK, 0x2);
                break;
 
        case SND_SOC_BIAS_STANDBY:
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       ret = snd_soc_cache_sync(codec);
+                       if (ret < 0) {
+                               dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
+                               return ret;
+                       }
+
                        /* Enable all output discharge bits */
                        snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
                                WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
@@ -1225,9 +1229,8 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
                }
 
                /* VMID=2*250k */
-               val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) &
-                       ~WM8990_VMID_MODE_MASK;
-               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4);
+               snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_1,
+                                   WM8990_VMID_MODE_MASK, 0x4);
                break;
 
        case SND_SOC_BIAS_OFF:
@@ -1241,8 +1244,8 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
                        WM8990_BUFIOEN);
 
                /* mute DAC */
-               val = snd_soc_read(codec, WM8990_DAC_CTRL);
-               snd_soc_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
+               snd_soc_update_bits(codec, WM8990_DAC_CTRL,
+                                   WM8990_DAC_MUTE, WM8990_DAC_MUTE);
 
                /* Enable any disabled outputs */
                snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
@@ -1319,19 +1322,6 @@ static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8990_resume(struct snd_soc_codec *codec)
 {
-       int i;
-       u8 data[2];
-       u16 *cache = codec->reg_cache;
-
-       /* Sync reg_cache with the hardware */
-       for (i = 0; i < ARRAY_SIZE(wm8990_reg); i++) {
-               if (i + 1 == WM8990_RESET)
-                       continue;
-               data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001);
-               data[1] = cache[i] & 0x00ff;
-               codec->hw_write(codec->control_data, data, 2);
-       }
-
        wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        return 0;
 }
@@ -1343,7 +1333,6 @@ static int wm8990_resume(struct snd_soc_codec *codec)
 static int wm8990_probe(struct snd_soc_codec *codec)
 {
        int ret;
-       u16 reg;
 
        ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
        if (ret < 0) {
@@ -1356,15 +1345,14 @@ static int wm8990_probe(struct snd_soc_codec *codec)
        /* charge output caps */
        wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       reg = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_4);
-       snd_soc_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1);
+       snd_soc_update_bits(codec, WM8990_AUDIO_INTERFACE_4,
+                           WM8990_ALRCGPIO1, WM8990_ALRCGPIO1);
 
-       reg = snd_soc_read(codec, WM8990_GPIO1_GPIO2) &
-               ~WM8990_GPIO1_SEL_MASK;
-       snd_soc_write(codec, WM8990_GPIO1_GPIO2, reg | 1);
+       snd_soc_update_bits(codec, WM8990_GPIO1_GPIO2,
+                           WM8990_GPIO1_SEL_MASK, 1);
 
-       reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
-       snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA);
+       snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2,
+                           WM8990_OPCLK_ENA, WM8990_OPCLK_ENA);
 
        snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
        snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
@@ -1392,6 +1380,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8990 = {
        .reg_cache_size = ARRAY_SIZE(wm8990_reg),
        .reg_word_size = sizeof(u16),
        .reg_cache_default = wm8990_reg,
+       .volatile_register = wm8990_volatile_register,
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
index 6af23d0..c9ab3ba 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2007-2010 Wolfson Microelectronics PLC.
  * Author: Graeme Gregory
- *         linux@wolfsonmicro.com
+ *         Graeme.Gregory@wolfsonmicro.com
  *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
@@ -393,7 +393,7 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
                         (1 << WM8991_AINRMUX_PWR_BIT)))
                reg |= WM8991_AINR_ENA;
        else
-               reg &= ~WM8991_AINL_ENA;
+               reg &= ~WM8991_AINR_ENA;
 
        snd_soc_write(w->codec, WM8991_POWER_MANAGEMENT_2, reg);
        return 0;
@@ -1264,7 +1264,6 @@ static int wm8991_probe(struct snd_soc_codec *codec)
 {
        struct wm8991_priv *wm8991;
        int ret;
-       unsigned int reg;
 
        wm8991 = snd_soc_codec_get_drvdata(codec);
 
@@ -1282,19 +1281,18 @@ static int wm8991_probe(struct snd_soc_codec *codec)
 
        wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       reg = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_4);
-       snd_soc_write(codec, WM8991_AUDIO_INTERFACE_4, reg | WM8991_ALRCGPIO1);
+       snd_soc_update_bits(codec, WM8991_AUDIO_INTERFACE_4,
+                           WM8991_ALRCGPIO1, WM8991_ALRCGPIO1);
 
-       reg = snd_soc_read(codec, WM8991_GPIO1_GPIO2) &
-             ~WM8991_GPIO1_SEL_MASK;
-       snd_soc_write(codec, WM8991_GPIO1_GPIO2, reg | 1);
+       snd_soc_update_bits(codec, WM8991_GPIO1_GPIO2,
+                           WM8991_GPIO1_SEL_MASK, 1);
 
-       reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_1);
-       snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, reg | WM8991_VREF_ENA|
-                     WM8991_VMID_MODE_MASK);
+       snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_1,
+                           WM8991_VREF_ENA | WM8991_VMID_MODE_MASK,
+                           WM8991_VREF_ENA | WM8991_VMID_MODE_MASK);
 
-       reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_2);
-       snd_soc_write(codec, WM8991_POWER_MANAGEMENT_2, reg | WM8991_OPCLK_ENA);
+       snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_2,
+                           WM8991_OPCLK_ENA, WM8991_OPCLK_ENA);
 
        snd_soc_write(codec, WM8991_DAC_CTRL, 0);
        snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
index e537267..6b73efd 100644 (file)
@@ -208,7 +208,7 @@ static int configure_aif_clock(struct snd_soc_codec *codec, int aif)
 static int configure_clock(struct snd_soc_codec *codec)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       int old, new;
+       int change, new;
 
        /* Bring up the AIF clocks first */
        configure_aif_clock(codec, 0);
@@ -229,14 +229,11 @@ static int configure_clock(struct snd_soc_codec *codec)
        else
                new = 0;
 
-       old = snd_soc_read(codec, WM8994_CLOCKING_1) & WM8994_SYSCLK_SRC;
-
-       /* If there's no change then we're done. */
-       if (old == new)
+       change = snd_soc_update_bits(codec, WM8994_CLOCKING_1,
+                                    WM8994_SYSCLK_SRC, new);
+       if (!change)
                return 0;
 
-       snd_soc_update_bits(codec, WM8994_CLOCKING_1, WM8994_SYSCLK_SRC, new);
-
        snd_soc_dapm_sync(&codec->dapm);
 
        return 0;
@@ -283,6 +280,7 @@ static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0);
 static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0);
 static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
 static const DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0);
+static const DECLARE_TLV_DB_SCALE(mixin_boost_tlv, 0, 900, 0);
 
 #define WM8994_DRC_SWITCH(xname, reg, shift) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -703,6 +701,13 @@ SOC_SINGLE_TLV("AIF2DAC Noise Gate Threshold Volume",
               7, 1, ng_tlv),
 };
 
+static const struct snd_kcontrol_new wm1811_snd_controls[] = {
+SOC_SINGLE_TLV("MIXINL IN1LP Boost Volume", WM8994_INPUT_MIXER_1, 7, 1, 0,
+              mixin_boost_tlv),
+SOC_SINGLE_TLV("MIXINL IN1RP Boost Volume", WM8994_INPUT_MIXER_1, 8, 1, 0,
+              mixin_boost_tlv),
+};
+
 static int clk_sys_event(struct snd_soc_dapm_widget *w,
                         struct snd_kcontrol *kcontrol, int event)
 {
@@ -1414,7 +1419,7 @@ SND_SOC_DAPM_MUX("AIF2DAC Mux", SND_SOC_NOPM, 0, 0, &aif2dac_mux),
 SND_SOC_DAPM_MUX("AIF2ADC Mux", SND_SOC_NOPM, 0, 0, &aif2adc_mux),
 
 SND_SOC_DAPM_AIF_IN("AIF3DACDAT", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_IN("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
 
 SND_SOC_DAPM_SUPPLY("TOCLK", WM8994_CLOCKING_1, 4, 0, NULL, 0),
 
@@ -2053,6 +2058,15 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
                                                            WM8958_CP_DISCH);
                                }
                                break;
+
+                       case WM1811:
+                               if (wm8994->revision < 2) {
+                                       snd_soc_write(codec, 0x102, 0x3);
+                                       snd_soc_write(codec, 0x5d, 0x7e);
+                                       snd_soc_write(codec, 0x5e, 0x0);
+                                       snd_soc_write(codec, 0x102, 0x0);
+                               }
+                               break;
                        }
 
                        /* Discharge LINEOUT1 & 2 */
@@ -2168,10 +2182,18 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 
        /* The AIF2 format configuration needs to be mirrored to AIF3
         * on WM8958 if it's in use so just do it all the time. */
-       if (control->type == WM8958 && dai->id == 2)
-               snd_soc_update_bits(codec, WM8958_AIF3_CONTROL_1,
-                                   WM8994_AIF1_LRCLK_INV |
-                                   WM8958_AIF3_FMT_MASK, aif1);
+       switch (control->type) {
+       case WM1811:
+       case WM8958:
+               if (dai->id == 2)
+                       snd_soc_update_bits(codec, WM8958_AIF3_CONTROL_1,
+                                           WM8994_AIF1_LRCLK_INV |
+                                           WM8958_AIF3_FMT_MASK, aif1);
+               break;
+
+       default:
+               break;
+       }
 
        snd_soc_update_bits(codec, aif1_reg,
                            WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV |
@@ -2213,7 +2235,6 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
                            struct snd_soc_dai *dai)
 {
        struct snd_soc_codec *codec = dai->codec;
-       struct wm8994 *control = codec->control_data;
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        int aif1_reg;
        int aif2_reg;
@@ -2256,14 +2277,6 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
                        dev_dbg(codec->dev, "AIF2 using split LRCLK\n");
                }
                break;
-       case 3:
-               switch (control->type) {
-               case WM8958:
-                       aif1_reg = WM8958_AIF3_CONTROL_1;
-                       break;
-               default:
-                       return 0;
-               }
        default:
                return -EINVAL;
        }
@@ -2384,6 +2397,7 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream,
        switch (dai->id) {
        case 3:
                switch (control->type) {
+               case WM1811:
                case WM8958:
                        aif1_reg = WM8958_AIF3_CONTROL_1;
                        break;
@@ -2424,7 +2438,7 @@ static void wm8994_aif_shutdown(struct snd_pcm_substream *substream,
                rate_reg = WM8994_AIF1_RATE;
                break;
        case 2:
-               rate_reg = WM8994_AIF1_RATE;
+               rate_reg = WM8994_AIF2_RATE;
                break;
        default:
                break;
@@ -2614,6 +2628,7 @@ static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
        case WM8994:
                snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0);
                break;
+       case WM1811:
        case WM8958:
                snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
                                    WM8958_MICD_ENA, 0);
@@ -2682,6 +2697,7 @@ static int wm8994_resume(struct snd_soc_codec *codec)
                        snd_soc_update_bits(codec, WM8994_MICBIAS,
                                            WM8994_MICD_ENA, WM8994_MICD_ENA);
                break;
+       case WM1811:
        case WM8958:
                if (wm8994->jack_cb)
                        snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
@@ -2980,8 +2996,13 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = codec->control_data;
 
-       if (control->type != WM8958)
+       switch (control->type) {
+       case WM1811:
+       case WM8958:
+               break;
+       default:
                return -EINVAL;
+       }
 
        if (jack) {
                if (!cb) {
@@ -3135,6 +3156,24 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                wm8994->hubs.dcs_readback_mode = 1;
                break;
 
+       case WM1811:
+               wm8994->hubs.dcs_readback_mode = 2;
+               wm8994->hubs.no_series_update = 1;
+
+               switch (wm8994->revision) {
+               case 0:
+               case 1:
+                       wm8994->hubs.dcs_codes_l = -9;
+                       wm8994->hubs.dcs_codes_r = -5;
+                       break;
+               default:
+                       break;
+               }
+
+               snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1,
+                                   WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN);
+               break;
+
        default:
                break;
        }
@@ -3195,6 +3234,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                break;
 
        case WM8958:
+       case WM1811:
                if (wm8994->micdet_irq) {
                        ret = request_threaded_irq(wm8994->micdet_irq, NULL,
                                                   wm8958_mic_irq,
@@ -3357,6 +3397,19 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                                                  ARRAY_SIZE(wm8994_dac_widgets));
                }
                break;
+
+       case WM1811:
+               snd_soc_add_controls(codec, wm8958_snd_controls,
+                                    ARRAY_SIZE(wm8958_snd_controls));
+               snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
+                                         ARRAY_SIZE(wm8958_dapm_widgets));
+               snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets,
+                                         ARRAY_SIZE(wm8994_lateclk_widgets));
+               snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets,
+                                         ARRAY_SIZE(wm8994_adc_widgets));
+               snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets,
+                                         ARRAY_SIZE(wm8994_dac_widgets));
+               break;
        }
                
 
@@ -3393,6 +3446,12 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 
                wm8958_dsp2_init(codec);
                break;
+       case WM1811:
+               snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon,
+                                       ARRAY_SIZE(wm8994_lateclk_intercon));
+               snd_soc_dapm_add_routes(dapm, wm8958_intercon,
+                                       ARRAY_SIZE(wm8958_intercon));
+               break;
        }
 
        return 0;
@@ -3448,6 +3507,7 @@ static int  wm8994_codec_remove(struct snd_soc_codec *codec)
                                wm8994);
                break;
 
+       case WM1811:
        case WM8958:
                if (wm8994->micdet_irq)
                        free_irq(wm8994->micdet_irq, wm8994);
index 74ae599..78eeb21 100644 (file)
@@ -485,7 +485,7 @@ static int configure_aif_clock(struct snd_soc_codec *codec, int aif)
 static int configure_clock(struct snd_soc_codec *codec)
 {
        struct wm8995_priv *wm8995;
-       int old, new;
+       int change, new;
 
        wm8995 = snd_soc_codec_get_drvdata(codec);
 
@@ -509,15 +509,11 @@ static int configure_clock(struct snd_soc_codec *codec)
        else
                new = 0;
 
-       old = snd_soc_read(codec, WM8995_CLOCKING_1) & WM8995_SYSCLK_SRC;
-
-       /* If there's no change then we're done. */
-       if (old == new)
+       change = snd_soc_update_bits(codec, WM8995_CLOCKING_1,
+                                    WM8995_SYSCLK_SRC_MASK, new);
+       if (!change)
                return 0;
 
-       snd_soc_update_bits(codec, WM8995_CLOCKING_1,
-                           WM8995_SYSCLK_SRC_MASK, new);
-
        snd_soc_dapm_sync(&codec->dapm);
 
        return 0;
@@ -1573,9 +1569,16 @@ static int wm8995_resume(struct snd_soc_codec *codec)
 static int wm8995_remove(struct snd_soc_codec *codec)
 {
        struct wm8995_priv *wm8995;
+       int i;
 
        wm8995 = snd_soc_codec_get_drvdata(codec);
        wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       for (i = 0; i < ARRAY_SIZE(wm8995->supplies); ++i)
+               regulator_unregister_notifier(wm8995->supplies[i].consumer,
+                                             &wm8995->disable_nb[i]);
+
+       regulator_bulk_free(ARRAY_SIZE(wm8995->supplies), wm8995->supplies);
        return 0;
 }
 
index 833df74..645c980 100644 (file)
@@ -641,6 +641,14 @@ SOC_DOUBLE_R("Speaker ZC Switch", WM8996_LEFT_PDM_SPEAKER,
 
 SOC_SINGLE("DSP1 EQ Switch", WM8996_DSP1_RX_EQ_GAINS_1, 0, 1, 0),
 SOC_SINGLE("DSP2 EQ Switch", WM8996_DSP2_RX_EQ_GAINS_1, 0, 1, 0),
+
+SOC_SINGLE("DSP1 DRC TXL Switch", WM8996_DSP1_DRC_1, 0, 1, 0),
+SOC_SINGLE("DSP1 DRC TXR Switch", WM8996_DSP1_DRC_1, 1, 1, 0),
+SOC_SINGLE("DSP1 DRC RX Switch", WM8996_DSP1_DRC_1, 2, 1, 0),
+
+SOC_SINGLE("DSP2 DRC TXL Switch", WM8996_DSP2_DRC_1, 0, 1, 0),
+SOC_SINGLE("DSP2 DRC TXR Switch", WM8996_DSP2_DRC_1, 1, 1, 0),
+SOC_SINGLE("DSP2 DRC RX Switch", WM8996_DSP2_DRC_1, 2, 1, 0),
 };
 
 static const struct snd_kcontrol_new wm8996_eq_controls[] = {
@@ -1105,9 +1113,9 @@ SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0,
 SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 1,
                    WM8996_POWER_MANAGEMENT_4, 8, 0),
 
-SND_SOC_DAPM_AIF_IN("AIF2TX1", "AIF2 Capture", 0,
+SND_SOC_DAPM_AIF_OUT("AIF2TX1", "AIF2 Capture", 0,
                    WM8996_POWER_MANAGEMENT_6, 9, 0),
-SND_SOC_DAPM_AIF_IN("AIF2TX0", "AIF2 Capture", 1,
+SND_SOC_DAPM_AIF_OUT("AIF2TX0", "AIF2 Capture", 1,
                    WM8996_POWER_MANAGEMENT_6, 8, 0),
 
 SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5,
@@ -1912,7 +1920,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream,
        snd_soc_update_bits(codec, lrclk_reg, WM8996_AIF1RX_RATE_MASK,
                            lrclk);
        snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_2,
-                           WM8996_DSP1_DIV_SHIFT << dsp_shift, dsp);
+                           WM8996_DSP1_DIV_MASK << dsp_shift, dsp);
 
        return 0;
 }
@@ -2698,7 +2706,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
        init_completion(&wm8996->fll_lock);
 
        dapm->idle_bias_off = true;
-       dapm->bias_level = SND_SOC_BIAS_OFF;
 
        ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
        if (ret != 0) {
index f32ab1e..3cd35a0 100644 (file)
@@ -157,7 +157,6 @@ static struct {
 
 struct wm9081_priv {
        enum snd_soc_control_type control_type;
-       void *control_data;
        int sysclk_source;
        int mclk_rate;
        int sysclk_rate;
@@ -174,6 +173,7 @@ static int wm9081_volatile_register(struct snd_soc_codec *codec, unsigned int re
 {
        switch (reg) {
        case WM9081_SOFTWARE_RESET:
+       case WM9081_INTERRUPT_STATUS:
                return 1;
        default:
                return 0;
@@ -820,7 +820,7 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec,
                /* VMID 2*240k */
                reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
                reg &= ~WM9081_VMID_SEL_MASK;
-               reg |= 0x40;
+               reg |= 0x04;
                snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
 
                /* Standby bias current on */
@@ -1213,7 +1213,6 @@ static int wm9081_probe(struct snd_soc_codec *codec)
        int ret;
        u16 reg;
 
-       codec->control_data = wm9081->control_data;
        ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm9081->control_type);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -1250,8 +1249,6 @@ static int wm9081_probe(struct snd_soc_codec *codec)
        snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA,
                     reg | WM9081_SPKPGAZC);
 
-       snd_soc_add_controls(codec, wm9081_snd_controls,
-                            ARRAY_SIZE(wm9081_snd_controls));
        if (!wm9081->pdata.num_retune_configs) {
                dev_dbg(codec->dev,
                        "No ReTune Mobile data, using normal EQ\n");
@@ -1311,6 +1308,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9081 = {
        .reg_cache_default = wm9081_reg_defaults,
        .volatile_register = wm9081_volatile_register,
 
+       .controls         = wm9081_snd_controls,
+       .num_controls     = ARRAY_SIZE(wm9081_snd_controls),
        .dapm_widgets     = wm9081_dapm_widgets,
        .num_dapm_widgets = ARRAY_SIZE(wm9081_dapm_widgets),
        .dapm_routes     = wm9081_audio_paths,
@@ -1330,7 +1329,6 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
 
        i2c_set_clientdata(i2c, wm9081);
        wm9081->control_type = SND_SOC_I2C;
-       wm9081->control_data = i2c;
 
        if (dev_get_platdata(&i2c->dev))
                memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev),
index f2f3077..2b5252c 100644 (file)
@@ -140,7 +140,6 @@ static const u16 wm9090_reg_defaults[] = {
 /* This struct is used to save the context */
 struct wm9090_priv {
        struct wm9090_platform_data pdata;
-       void *control_data;
 };
 
 static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg)
@@ -549,10 +548,8 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
 
 static int wm9090_probe(struct snd_soc_codec *codec)
 {
-       struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
-       codec->control_data = wm9090->control_data;
        ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -661,7 +658,6 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
                       sizeof(wm9090->pdata));
 
        i2c_set_clientdata(i2c, wm9090);
-       wm9090->control_data = i2c;
 
        ret =  snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm9090,  NULL, 0);
@@ -682,6 +678,7 @@ static int __devexit wm9090_i2c_remove(struct i2c_client *i2c)
 
 static const struct i2c_device_id wm9090_id[] = {
        { "wm9090", 0 },
+       { "wm9093", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, wm9090_id);
index ca8ce03..84f33d4 100644 (file)
@@ -222,7 +222,7 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
        struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
        int ret;
 
-       ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
+       ret = snd_soc_put_volsw(kcontrol, ucontrol);
 
        /* Updating the analogue gains invalidates the DC servo cache */
        hubs->class_w_dcs = 0;
@@ -362,19 +362,11 @@ SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 3, 0, 7, 0,
 SOC_ENUM("Speaker Reference", speaker_ref),
 SOC_ENUM("Speaker Mode", speaker_mode),
 
-{
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Volume",
-       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
-                SNDRV_CTL_ELEM_ACCESS_READWRITE,
-       .tlv.p = outpga_tlv,
-       .info = snd_soc_info_volsw_2r,
-       .get = snd_soc_get_volsw_2r, .put = wm8993_put_dc_servo,
-       .private_value = (unsigned long)&(struct soc_mixer_control) {
-               .reg = WM8993_LEFT_OUTPUT_VOLUME,
-               .rreg = WM8993_RIGHT_OUTPUT_VOLUME,
-               .shift = 0, .max = 63
-       },
-},
+SOC_DOUBLE_R_EXT_TLV("Headphone Volume",
+                    WM8993_LEFT_OUTPUT_VOLUME, WM8993_RIGHT_OUTPUT_VOLUME,
+                    0, 63, 0, snd_soc_get_volsw, wm8993_put_dc_servo,
+                    outpga_tlv),
+
 SOC_DOUBLE_R("Headphone Switch", WM8993_LEFT_OUTPUT_VOLUME,
             WM8993_RIGHT_OUTPUT_VOLUME, 6, 1, 0),
 SOC_DOUBLE_R("Headphone ZC Switch", WM8993_LEFT_OUTPUT_VOLUME,
index fe79842..f78c3f0 100644 (file)
@@ -150,8 +150,6 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_enable_pin(dapm, "Mic Jack");
        snd_soc_dapm_enable_pin(dapm, "Line In");
 
-       snd_soc_dapm_sync(dapm);
-
        return 0;
 }
 
index d0d60b8..300e121 100644 (file)
@@ -265,6 +265,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
        unsigned int pcr;
        unsigned int srgr;
+       bool inv_fs = false;
        /* Attention srgr is updated by hw_params! */
        srgr = DAVINCI_MCBSP_SRGR_FSGM |
                DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |
@@ -330,7 +331,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                 * more empty bit clock slots between channels as the sample
                 * rate is lowered.
                 */
-               fmt ^= SND_SOC_DAIFMT_NB_IF;
+               inv_fs = true;
        case SND_SOC_DAIFMT_DSP_A:
                dev->mode = MOD_DSP_A;
                break;
@@ -394,6 +395,8 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        default:
                return -EINVAL;
        }
+       if (inv_fs == true)
+               pcr ^= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP);
        davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
        dev->pcr = pcr;
        davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr);
index c7417c7..3cd6158 100644 (file)
@@ -335,7 +335,7 @@ static struct snd_soc_dai_ops ep93xx_ac97_dai_ops = {
        .trigger        = ep93xx_ac97_trigger,
 };
 
-struct snd_soc_dai_driver ep93xx_ac97_dai = {
+static struct snd_soc_dai_driver ep93xx_ac97_dai = {
        .name           = "ep93xx-ac97",
        .id             = 0,
        .ac97_control   = 1,
index bb699bb..b133bfc 100644 (file)
@@ -29,7 +29,7 @@ config SND_MXC_SOC_WM1133_EV1
 config SND_SOC_MX27VIS_AIC32X4
        tristate "SoC audio support for Visstrim M10 boards"
        depends on MACH_IMX27_VISSTRIM_M10
-       select SND_SOC_TVL320AIC32X4
+       select SND_SOC_TLV320AIC32X4
        select SND_MXC_SOC_MX2
        help
          Say Y if you want to add support for SoC audio on Visstrim SM10
@@ -50,6 +50,7 @@ config SND_SOC_EUKREA_TLV320
                || MACH_EUKREA_MBIMXSD25_BASEBOARD \
                || MACH_EUKREA_MBIMXSD35_BASEBOARD \
                || MACH_EUKREA_MBIMXSD51_BASEBOARD
+       depends on I2C
        select SND_SOC_TLV320AIC23
        select SND_MXC_SOC_FIQ
        help
index c8527ea..8df0fae 100644 (file)
@@ -240,7 +240,6 @@ static int ssi_irq = 0;
 
 static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd)
 {
-       struct snd_soc_dai *dai = rtd->cpu_dai;
        struct snd_pcm *pcm = rtd->pcm;
        struct snd_pcm_substream *substream;
        int ret;
index 4297cb6..4c05e2b 100644 (file)
@@ -391,7 +391,6 @@ static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
 int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
-       struct snd_soc_dai *dai = rtd->cpu_dai;
        struct snd_pcm *pcm = rtd->pcm;
        int ret = 0;
 
index 0a84cec..1072dfb 100644 (file)
@@ -218,12 +218,6 @@ struct imx_ssi {
        struct platform_device *soc_platform_pdev_fiq;
 };
 
-struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev,
-               struct imx_ssi *ssi);
-void imx_ssi_fiq_exit(struct platform_device *pdev, struct imx_ssi *ssi);
-struct snd_soc_platform *imx_ssi_dma_mx2_init(struct platform_device *pdev,
-               struct imx_ssi *ssi);
-
 int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma);
 int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);
 void imx_pcm_free(struct snd_pcm *pcm);
index a7c9578..d1989cd 100644 (file)
@@ -299,7 +299,7 @@ static void jz4740_pcm_free(struct snd_pcm *pcm)
 
 static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32);
 
-int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd)
+static int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_soc_dai *dai = rtd->cpu_dai;
index d0bcf3f..715e841 100644 (file)
@@ -476,7 +476,7 @@ static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev)
 
 static struct platform_driver kirkwood_i2s_driver = {
        .probe  = kirkwood_i2s_dev_probe,
-       .remove = kirkwood_i2s_dev_remove,
+       .remove = __devexit_p(kirkwood_i2s_dev_remove),
        .driver = {
                .name = DRV_NAME,
                .owner = THIS_MODULE,
index c8d2195..c772b3c 100644 (file)
@@ -79,8 +79,6 @@ static int t5325_dai_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
        snd_soc_dapm_enable_pin(dapm, "Speaker");
 
-       snd_soc_dapm_sync(dapm);
-
        return 0;
 }
 
index 429aa1b..598f48c 100644 (file)
@@ -54,9 +54,7 @@ static unsigned int   hs_switch;
 static unsigned int    lo_dac;
 
 struct mfld_mc_private {
-       struct platform_device *socdev;
        void __iomem *int_base;
-       struct snd_soc_codec *codec;
        u8 interrupt_status;
 };
 
@@ -235,7 +233,6 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
        /* always connected */
        snd_soc_dapm_enable_pin(dapm, "Headphones");
        snd_soc_dapm_enable_pin(dapm, "Mic");
-       snd_soc_dapm_sync(dapm);
 
        ret_val = snd_soc_add_controls(codec, mfld_snd_controls,
                                ARRAY_SIZE(mfld_snd_controls));
@@ -253,7 +250,6 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
        /* we dont use linein in this so set to NC */
        snd_soc_dapm_disable_pin(dapm, "LINEINL");
        snd_soc_dapm_disable_pin(dapm, "LINEINR");
-       snd_soc_dapm_sync(dapm);
 
        /* Headset and button jack detection */
        ret_val = snd_soc_jack_new(codec, "Intel(R) MID Audio Jack",
index 9925d20..7df8c58 100644 (file)
@@ -63,7 +63,7 @@ static struct snd_pcm_hardware sst_platform_pcm_hw = {
 };
 
 /* MFLD - MSIC */
-struct snd_soc_dai_driver sst_platform_dai[] = {
+static struct snd_soc_dai_driver sst_platform_dai[] = {
 {
        .name = "Headset-cpu-dai",
        .id = 0,
index 401944c..76dc74d 100644 (file)
@@ -617,7 +617,7 @@ static irqreturn_t mxs_saif_irq(int irq, void *dev_id)
 
 static int mxs_saif_probe(struct platform_device *pdev)
 {
-       struct resource *res;
+       struct resource *iores, *dmares;
        struct mxs_saif *saif;
        struct mxs_saif_platform_data *pdata;
        int ret = 0;
@@ -655,35 +655,36 @@ static int mxs_saif_probe(struct platform_device *pdev)
                goto failed_clk;
        }
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
+       iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!iores) {
                ret = -ENODEV;
                dev_err(&pdev->dev, "failed to get io resource: %d\n",
                        ret);
                goto failed_get_resource;
        }
 
-       if (!request_mem_region(res->start, resource_size(res), "mxs-saif")) {
+       if (!request_mem_region(iores->start, resource_size(iores),
+                               "mxs-saif")) {
                dev_err(&pdev->dev, "request_mem_region failed\n");
                ret = -EBUSY;
                goto failed_get_resource;
        }
 
-       saif->base = ioremap(res->start, resource_size(res));
+       saif->base = ioremap(iores->start, resource_size(iores));
        if (!saif->base) {
                dev_err(&pdev->dev, "ioremap failed\n");
                ret = -ENODEV;
                goto failed_ioremap;
        }
 
-       res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-       if (!res) {
+       dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!dmares) {
                ret = -ENODEV;
                dev_err(&pdev->dev, "failed to get dma resource: %d\n",
                        ret);
                goto failed_ioremap;
        }
-       saif->dma_param.chan_num = res->start;
+       saif->dma_param.chan_num = dmares->start;
 
        saif->irq = platform_get_irq(pdev, 0);
        if (saif->irq < 0) {
@@ -742,7 +743,7 @@ failed_get_irq2:
 failed_get_irq1:
        iounmap(saif->base);
 failed_ioremap:
-       release_mem_region(res->start, resource_size(res));
+       release_mem_region(iores->start, resource_size(iores));
 failed_get_resource:
        clk_put(saif->clk);
 failed_clk:
index 865b288..ae8d680 100644 (file)
@@ -227,7 +227,7 @@ static int nuc900_dma_trigger(struct snd_pcm_substream *substream, int cmd)
        return ret;
 }
 
-int nuc900_dma_getposition(struct snd_pcm_substream *substream,
+static int nuc900_dma_getposition(struct snd_pcm_substream *substream,
                                        dma_addr_t *src, dma_addr_t *dst)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
index 59e2c8d..052fd75 100644 (file)
@@ -1,7 +1,7 @@
 # OMAP Platform Support
 snd-soc-omap-objs := omap-pcm.o
 snd-soc-omap-mcbsp-objs := omap-mcbsp.o
-snd-soc-omap-mcpdm-objs := omap-mcpdm.o mcpdm.o
+snd-soc-omap-mcpdm-objs := omap-mcpdm.o
 snd-soc-omap-hdmi-objs := omap-hdmi.o
 
 obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o
index 73dde4a..8da55e9 100644 (file)
@@ -43,26 +43,6 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_DSP_B |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_DSP_B |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return ret;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0,
                        CODEC_CLOCK, SND_SOC_CLOCK_IN);
@@ -110,28 +90,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"MICIN", NULL, "Mic In"},
 };
 
-static int am3517evm_aic23_init(struct snd_soc_pcm_runtime *rtd)
-{
-       struct snd_soc_codec *codec = rtd->codec;
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       /* Add am3517-evm specific widgets */
-       snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
-                                 ARRAY_SIZE(tlv320aic23_dapm_widgets));
-
-       /* Set up davinci-evm specific audio path audio_map */
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-       /* always connected */
-       snd_soc_dapm_enable_pin(dapm, "Line Out");
-       snd_soc_dapm_enable_pin(dapm, "Line In");
-       snd_soc_dapm_enable_pin(dapm, "Mic In");
-
-       snd_soc_dapm_sync(dapm);
-
-       return 0;
-}
-
 /* Digital audio interface glue - connects codec <--> CPU */
 static struct snd_soc_dai_link am3517evm_dai = {
        .name = "TLV320AIC23",
@@ -140,7 +98,8 @@ static struct snd_soc_dai_link am3517evm_dai = {
        .codec_dai_name = "tlv320aic23-hifi",
        .platform_name = "omap-pcm-audio",
        .codec_name = "tlv320aic23-codec.2-001a",
-       .init = am3517evm_aic23_init,
+       .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
+                  SND_SOC_DAIFMT_CBM_CFM,
        .ops = &am3517evm_ops,
 };
 
@@ -149,6 +108,11 @@ static struct snd_soc_card snd_soc_am3517evm = {
        .name = "am3517evm",
        .dai_link = &am3517evm_dai,
        .num_links = 1,
+
+       .dapm_widgets = tlv320aic23_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
+       .dapm_routes = audio_map,
+       .num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static struct platform_device *am3517evm_snd_device;
index 0aa475f..dcb7b68 100644 (file)
@@ -569,7 +569,6 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_disable_pin(dapm, "Speaker");
        snd_soc_dapm_disable_pin(dapm, "AGCIN");
        snd_soc_dapm_disable_pin(dapm, "AGCOUT");
-       snd_soc_dapm_sync(dapm);
 
        /* Add virtual switch */
        ret = snd_soc_add_controls(codec, ams_delta_audio_controls,
index 0ae3470..84615a7 100644 (file)
@@ -38,29 +38,8 @@ static int igep2_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return ret;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
                                            SND_SOC_CLOCK_IN);
@@ -84,6 +63,8 @@ static struct snd_soc_dai_link igep2_dai = {
        .codec_dai_name = "twl4030-hifi",
        .platform_name = "omap-pcm-audio",
        .codec_name = "twl4030-codec",
+       .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                  SND_SOC_DAIFMT_CBM_CFM,
        .ops = &igep2_ops,
 };
 
diff --git a/sound/soc/omap/mcpdm.c b/sound/soc/omap/mcpdm.c
deleted file mode 100644 (file)
index 928f037..0000000
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * mcpdm.c  -- McPDM interface driver
- *
- * Author: Jorge Eduardo Candelaria <x0107209@ti.com>
- * Copyright (C) 2009 - Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/wait.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-
-#include "mcpdm.h"
-
-static struct omap_mcpdm *mcpdm;
-
-static inline void omap_mcpdm_write(u16 reg, u32 val)
-{
-       __raw_writel(val, mcpdm->io_base + reg);
-}
-
-static inline int omap_mcpdm_read(u16 reg)
-{
-       return __raw_readl(mcpdm->io_base + reg);
-}
-
-static void omap_mcpdm_reg_dump(void)
-{
-       dev_dbg(mcpdm->dev, "***********************\n");
-       dev_dbg(mcpdm->dev, "IRQSTATUS_RAW:  0x%04x\n",
-                       omap_mcpdm_read(MCPDM_IRQSTATUS_RAW));
-       dev_dbg(mcpdm->dev, "IRQSTATUS: 0x%04x\n",
-                       omap_mcpdm_read(MCPDM_IRQSTATUS));
-       dev_dbg(mcpdm->dev, "IRQENABLE_SET:  0x%04x\n",
-                       omap_mcpdm_read(MCPDM_IRQENABLE_SET));
-       dev_dbg(mcpdm->dev, "IRQENABLE_CLR:  0x%04x\n",
-                       omap_mcpdm_read(MCPDM_IRQENABLE_CLR));
-       dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n",
-                       omap_mcpdm_read(MCPDM_IRQWAKE_EN));
-       dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n",
-                       omap_mcpdm_read(MCPDM_DMAENABLE_SET));
-       dev_dbg(mcpdm->dev, "DMAENABLE_CLR:  0x%04x\n",
-                       omap_mcpdm_read(MCPDM_DMAENABLE_CLR));
-       dev_dbg(mcpdm->dev, "DMAWAKEEN: 0x%04x\n",
-                       omap_mcpdm_read(MCPDM_DMAWAKEEN));
-       dev_dbg(mcpdm->dev, "CTRL:      0x%04x\n",
-                       omap_mcpdm_read(MCPDM_CTRL));
-       dev_dbg(mcpdm->dev, "DN_DATA:  0x%04x\n",
-                       omap_mcpdm_read(MCPDM_DN_DATA));
-       dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n",
-                       omap_mcpdm_read(MCPDM_UP_DATA));
-       dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n",
-                       omap_mcpdm_read(MCPDM_FIFO_CTRL_DN));
-       dev_dbg(mcpdm->dev, "FIFO_CTRL_UP:  0x%04x\n",
-                       omap_mcpdm_read(MCPDM_FIFO_CTRL_UP));
-       dev_dbg(mcpdm->dev, "DN_OFFSET: 0x%04x\n",
-                       omap_mcpdm_read(MCPDM_DN_OFFSET));
-       dev_dbg(mcpdm->dev, "***********************\n");
-}
-
-/*
- * Takes the McPDM module in and out of reset state.
- * Uplink and downlink can be reset individually.
- */
-static void omap_mcpdm_reset_capture(int reset)
-{
-       int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
-       if (reset)
-               ctrl |= SW_UP_RST;
-       else
-               ctrl &= ~SW_UP_RST;
-
-       omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-static void omap_mcpdm_reset_playback(int reset)
-{
-       int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
-       if (reset)
-               ctrl |= SW_DN_RST;
-       else
-               ctrl &= ~SW_DN_RST;
-
-       omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-/*
- * Enables the transfer through the PDM interface to/from the Phoenix
- * codec by enabling the corresponding UP or DN channels.
- */
-void omap_mcpdm_start(int stream)
-{
-       int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
-       if (stream)
-               ctrl |= mcpdm->up_channels;
-       else
-               ctrl |= mcpdm->dn_channels;
-
-       omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-/*
- * Disables the transfer through the PDM interface to/from the Phoenix
- * codec by disabling the corresponding UP or DN channels.
- */
-void omap_mcpdm_stop(int stream)
-{
-       int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
-       if (stream)
-               ctrl &= ~mcpdm->up_channels;
-       else
-               ctrl &= ~mcpdm->dn_channels;
-
-       omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-/*
- * Configures McPDM uplink for audio recording.
- * This function should be called before omap_mcpdm_start.
- */
-int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink)
-{
-       int irq_mask = 0;
-       int ctrl;
-
-       if (!uplink)
-               return -EINVAL;
-
-       mcpdm->uplink = uplink;
-
-       /* Enable irq request generation */
-       irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK;
-       omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
-
-       /* Configure uplink threshold */
-       if (uplink->threshold > UP_THRES_MAX)
-               uplink->threshold = UP_THRES_MAX;
-
-       omap_mcpdm_write(MCPDM_FIFO_CTRL_UP, uplink->threshold);
-
-       /* Configure DMA controller */
-       omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_UP_ENABLE);
-
-       /* Set pdm out format */
-       ctrl = omap_mcpdm_read(MCPDM_CTRL);
-       ctrl &= ~PDMOUTFORMAT;
-       ctrl |= uplink->format & PDMOUTFORMAT;
-
-       /* Uplink channels */
-       mcpdm->up_channels = uplink->channels & (PDM_UP_MASK | PDM_STATUS_MASK);
-
-       omap_mcpdm_write(MCPDM_CTRL, ctrl);
-
-       return 0;
-}
-
-/*
- * Configures McPDM downlink for audio playback.
- * This function should be called before omap_mcpdm_start.
- */
-int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink)
-{
-       int irq_mask = 0;
-       int ctrl;
-
-       if (!downlink)
-               return -EINVAL;
-
-       mcpdm->downlink = downlink;
-
-       /* Enable irq request generation */
-       irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK;
-       omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
-
-       /* Configure uplink threshold */
-       if (downlink->threshold > DN_THRES_MAX)
-               downlink->threshold = DN_THRES_MAX;
-
-       omap_mcpdm_write(MCPDM_FIFO_CTRL_DN, downlink->threshold);
-
-       /* Enable DMA request generation */
-       omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_DN_ENABLE);
-
-       /* Set pdm out format */
-       ctrl = omap_mcpdm_read(MCPDM_CTRL);
-       ctrl &= ~PDMOUTFORMAT;
-       ctrl |= downlink->format & PDMOUTFORMAT;
-
-       /* Downlink channels */
-       mcpdm->dn_channels = downlink->channels & (PDM_DN_MASK | PDM_CMD_MASK);
-
-       omap_mcpdm_write(MCPDM_CTRL, ctrl);
-
-       return 0;
-}
-
-/*
- * Cleans McPDM uplink configuration.
- * This function should be called when the stream is closed.
- */
-int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink)
-{
-       int irq_mask = 0;
-
-       if (!uplink)
-               return -EINVAL;
-
-       /* Disable irq request generation */
-       irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK;
-       omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
-
-       /* Disable DMA request generation */
-       omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_UP_ENABLE);
-
-       /* Clear Downlink channels */
-       mcpdm->up_channels = 0;
-
-       mcpdm->uplink = NULL;
-
-       return 0;
-}
-
-/*
- * Cleans McPDM downlink configuration.
- * This function should be called when the stream is closed.
- */
-int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink)
-{
-       int irq_mask = 0;
-
-       if (!downlink)
-               return -EINVAL;
-
-       /* Disable irq request generation */
-       irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK;
-       omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
-
-       /* Disable DMA request generation */
-       omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_DN_ENABLE);
-
-       /* clear Downlink channels */
-       mcpdm->dn_channels = 0;
-
-       mcpdm->downlink = NULL;
-
-       return 0;
-}
-
-static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id)
-{
-       struct omap_mcpdm *mcpdm_irq = dev_id;
-       int irq_status;
-
-       irq_status = omap_mcpdm_read(MCPDM_IRQSTATUS);
-
-       /* Acknowledge irq event */
-       omap_mcpdm_write(MCPDM_IRQSTATUS, irq_status);
-
-       if (irq & MCPDM_DN_IRQ_FULL) {
-               dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
-               omap_mcpdm_reset_playback(1);
-               omap_mcpdm_playback_open(mcpdm_irq->downlink);
-               omap_mcpdm_reset_playback(0);
-       }
-
-       if (irq & MCPDM_DN_IRQ_EMPTY) {
-               dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
-               omap_mcpdm_reset_playback(1);
-               omap_mcpdm_playback_open(mcpdm_irq->downlink);
-               omap_mcpdm_reset_playback(0);
-       }
-
-       if (irq & MCPDM_DN_IRQ) {
-               dev_dbg(mcpdm_irq->dev, "DN write request\n");
-       }
-
-       if (irq & MCPDM_UP_IRQ_FULL) {
-               dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
-               omap_mcpdm_reset_capture(1);
-               omap_mcpdm_capture_open(mcpdm_irq->uplink);
-               omap_mcpdm_reset_capture(0);
-       }
-
-       if (irq & MCPDM_UP_IRQ_EMPTY) {
-               dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
-               omap_mcpdm_reset_capture(1);
-               omap_mcpdm_capture_open(mcpdm_irq->uplink);
-               omap_mcpdm_reset_capture(0);
-       }
-
-       if (irq & MCPDM_UP_IRQ) {
-               dev_dbg(mcpdm_irq->dev, "UP write request\n");
-       }
-
-       return IRQ_HANDLED;
-}
-
-int omap_mcpdm_request(void)
-{
-       int ret;
-
-       clk_enable(mcpdm->clk);
-
-       spin_lock(&mcpdm->lock);
-
-       if (!mcpdm->free) {
-               dev_err(mcpdm->dev, "McPDM interface is in use\n");
-               spin_unlock(&mcpdm->lock);
-               ret = -EBUSY;
-               goto err;
-       }
-       mcpdm->free = 0;
-
-       spin_unlock(&mcpdm->lock);
-
-       /* Disable lines while request is ongoing */
-       omap_mcpdm_write(MCPDM_CTRL, 0x00);
-
-       ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler,
-                               0, "McPDM", (void *)mcpdm);
-       if (ret) {
-               dev_err(mcpdm->dev, "Request for McPDM IRQ failed\n");
-               goto err;
-       }
-
-       return 0;
-
-err:
-       clk_disable(mcpdm->clk);
-       return ret;
-}
-
-void omap_mcpdm_free(void)
-{
-       spin_lock(&mcpdm->lock);
-       if (mcpdm->free) {
-               dev_err(mcpdm->dev, "McPDM interface is already free\n");
-               spin_unlock(&mcpdm->lock);
-               return;
-       }
-       mcpdm->free = 1;
-       spin_unlock(&mcpdm->lock);
-
-       clk_disable(mcpdm->clk);
-
-       free_irq(mcpdm->irq, (void *)mcpdm);
-}
-
-/* Enable/disable DC offset cancelation for the analog
- * headset path (PDM channels 1 and 2).
- */
-int omap_mcpdm_set_offset(int offset1, int offset2)
-{
-       int offset;
-
-       if ((offset1 > DN_OFST_MAX) || (offset2 > DN_OFST_MAX))
-               return -EINVAL;
-
-       offset = (offset1 << DN_OFST_RX1) | (offset2 << DN_OFST_RX2);
-
-       /* offset cancellation for channel 1 */
-       if (offset1)
-               offset |= DN_OFST_RX1_EN;
-       else
-               offset &= ~DN_OFST_RX1_EN;
-
-       /* offset cancellation for channel 2 */
-       if (offset2)
-               offset |= DN_OFST_RX2_EN;
-       else
-               offset &= ~DN_OFST_RX2_EN;
-
-       omap_mcpdm_write(MCPDM_DN_OFFSET, offset);
-
-       return 0;
-}
-
-int __devinit omap_mcpdm_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       int ret = 0;
-
-       mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL);
-       if (!mcpdm) {
-               ret = -ENOMEM;
-               goto exit;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "no resource\n");
-               goto err_resource;
-       }
-
-       spin_lock_init(&mcpdm->lock);
-       mcpdm->free = 1;
-       mcpdm->io_base = ioremap(res->start, resource_size(res));
-       if (!mcpdm->io_base) {
-               ret = -ENOMEM;
-               goto err_resource;
-       }
-
-       mcpdm->irq = platform_get_irq(pdev, 0);
-
-       mcpdm->clk = clk_get(&pdev->dev, "pdm_ck");
-       if (IS_ERR(mcpdm->clk)) {
-               ret = PTR_ERR(mcpdm->clk);
-               dev_err(&pdev->dev, "unable to get pdm_ck: %d\n", ret);
-               goto err_clk;
-       }
-
-       mcpdm->dev = &pdev->dev;
-       platform_set_drvdata(pdev, mcpdm);
-
-       return 0;
-
-err_clk:
-       iounmap(mcpdm->io_base);
-err_resource:
-       kfree(mcpdm);
-exit:
-       return ret;
-}
-
-int __devexit omap_mcpdm_remove(struct platform_device *pdev)
-{
-       struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev);
-
-       platform_set_drvdata(pdev, NULL);
-
-       clk_put(mcpdm_ptr->clk);
-
-       iounmap(mcpdm_ptr->io_base);
-
-       mcpdm_ptr->clk = NULL;
-       mcpdm_ptr->free = 0;
-       mcpdm_ptr->dev = NULL;
-
-       kfree(mcpdm_ptr);
-
-       return 0;
-}
-
diff --git a/sound/soc/omap/mcpdm.h b/sound/soc/omap/mcpdm.h
deleted file mode 100644 (file)
index df3e16f..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * mcpdm.h -- Defines for McPDM driver
- *
- * Author: Jorge Eduardo Candelaria <x0107209@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-/* McPDM registers */
-
-#define MCPDM_REVISION         0x00
-#define MCPDM_SYSCONFIG                0x10
-#define MCPDM_IRQSTATUS_RAW    0x24
-#define MCPDM_IRQSTATUS                0x28
-#define MCPDM_IRQENABLE_SET    0x2C
-#define MCPDM_IRQENABLE_CLR    0x30
-#define MCPDM_IRQWAKE_EN       0x34
-#define MCPDM_DMAENABLE_SET    0x38
-#define MCPDM_DMAENABLE_CLR    0x3C
-#define MCPDM_DMAWAKEEN                0x40
-#define MCPDM_CTRL             0x44
-#define MCPDM_DN_DATA          0x48
-#define MCPDM_UP_DATA          0x4C
-#define MCPDM_FIFO_CTRL_DN     0x50
-#define MCPDM_FIFO_CTRL_UP     0x54
-#define MCPDM_DN_OFFSET                0x58
-
-/*
- * MCPDM_IRQ bit fields
- * IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR
- */
-
-#define MCPDM_DN_IRQ                   (1 << 0)
-#define MCPDM_DN_IRQ_EMPTY             (1 << 1)
-#define MCPDM_DN_IRQ_ALMST_EMPTY       (1 << 2)
-#define MCPDM_DN_IRQ_FULL              (1 << 3)
-
-#define MCPDM_UP_IRQ                   (1 << 8)
-#define MCPDM_UP_IRQ_EMPTY             (1 << 9)
-#define MCPDM_UP_IRQ_ALMST_FULL                (1 << 10)
-#define MCPDM_UP_IRQ_FULL              (1 << 11)
-
-#define MCPDM_DOWNLINK_IRQ_MASK                0x00F
-#define MCPDM_UPLINK_IRQ_MASK          0xF00
-
-/*
- * MCPDM_DMAENABLE bit fields
- */
-
-#define DMA_DN_ENABLE          0x1
-#define DMA_UP_ENABLE          0x2
-
-/*
- * MCPDM_CTRL bit fields
- */
-
-#define PDM_UP1_EN             0x0001
-#define PDM_UP2_EN             0x0002
-#define PDM_UP3_EN             0x0004
-#define PDM_DN1_EN             0x0008
-#define PDM_DN2_EN             0x0010
-#define PDM_DN3_EN             0x0020
-#define PDM_DN4_EN             0x0040
-#define PDM_DN5_EN             0x0080
-#define PDMOUTFORMAT           0x0100
-#define CMD_INT                        0x0200
-#define STATUS_INT             0x0400
-#define SW_UP_RST              0x0800
-#define SW_DN_RST              0x1000
-#define PDM_UP_MASK            0x007
-#define PDM_DN_MASK            0x0F8
-#define PDM_CMD_MASK           0x200
-#define PDM_STATUS_MASK                0x400
-
-
-#define PDMOUTFORMAT_LJUST     (0 << 8)
-#define PDMOUTFORMAT_RJUST     (1 << 8)
-
-/*
- * MCPDM_FIFO_CTRL bit fields
- */
-
-#define UP_THRES_MAX           0xF
-#define DN_THRES_MAX           0xF
-
-/*
- * MCPDM_DN_OFFSET bit fields
- */
-
-#define DN_OFST_RX1_EN         0x0001
-#define DN_OFST_RX2_EN         0x0100
-
-#define DN_OFST_RX1            1
-#define DN_OFST_RX2            9
-#define DN_OFST_MAX            0x1F
-
-#define MCPDM_UPLINK           1
-#define MCPDM_DOWNLINK         2
-
-struct omap_mcpdm_link {
-       int irq_mask;
-       int threshold;
-       int format;
-       int channels;
-};
-
-struct omap_mcpdm_platform_data {
-       unsigned long phys_base;
-       u16 irq;
-};
-
-struct omap_mcpdm {
-       struct device *dev;
-       unsigned long phys_base;
-       void __iomem *io_base;
-       u8 free;
-       int irq;
-
-       spinlock_t lock;
-       struct omap_mcpdm_platform_data *pdata;
-       struct clk *clk;
-       struct omap_mcpdm_link *downlink;
-       struct omap_mcpdm_link *uplink;
-       struct completion irq_completion;
-
-       int dn_channels;
-       int up_channels;
-};
-
-extern void omap_mcpdm_start(int stream);
-extern void omap_mcpdm_stop(int stream);
-extern int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink);
-extern int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink);
-extern int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink);
-extern int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink);
-extern int omap_mcpdm_request(void);
-extern void omap_mcpdm_free(void);
-extern int omap_mcpdm_set_offset(int offset1, int offset2);
-int __devinit omap_mcpdm_probe(struct platform_device *pdev);
-int __devexit omap_mcpdm_remove(struct platform_device *pdev);
index 62e292f..7e3c20c 100644 (file)
@@ -115,25 +115,8 @@ static int n810_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int err;
 
-       /* Set codec DAI configuration */
-       err = snd_soc_dai_set_fmt(codec_dai,
-                                        SND_SOC_DAIFMT_I2S |
-                                        SND_SOC_DAIFMT_NB_NF |
-                                        SND_SOC_DAIFMT_CBM_CFM);
-       if (err < 0)
-               return err;
-
-       /* Set cpu DAI configuration */
-       err = snd_soc_dai_set_fmt(cpu_dai,
-                                      SND_SOC_DAIFMT_I2S |
-                                      SND_SOC_DAIFMT_NB_NF |
-                                      SND_SOC_DAIFMT_CBM_CFM);
-       if (err < 0)
-               return err;
-
        /* Set the codec system clock for DAC and ADC */
        err = snd_soc_dai_set_sysclk(codec_dai, 0, 12000000,
                                            SND_SOC_CLOCK_IN);
@@ -274,7 +257,6 @@ static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_codec *codec = rtd->codec;
        struct snd_soc_dapm_context *dapm = &codec->dapm;
-       int err;
 
        /* Not connected */
        snd_soc_dapm_nc_pin(dapm, "MONO_LOUT");
@@ -286,21 +268,6 @@ static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_nc_pin(dapm, "LINE2L");
        snd_soc_dapm_nc_pin(dapm, "LINE2R");
 
-       /* Add N810 specific controls */
-       err = snd_soc_add_controls(codec, aic33_n810_controls,
-                               ARRAY_SIZE(aic33_n810_controls));
-       if (err < 0)
-               return err;
-
-       /* Add N810 specific widgets */
-       snd_soc_dapm_new_controls(dapm, aic33_dapm_widgets,
-                                 ARRAY_SIZE(aic33_dapm_widgets));
-
-       /* Set up N810 specific audio path audio_map */
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-       snd_soc_dapm_sync(dapm);
-
        return 0;
 }
 
@@ -312,6 +279,8 @@ static struct snd_soc_dai_link n810_dai = {
        .platform_name = "omap-pcm-audio",
        .codec_name = "tlv320aic3x-codec.2-0018",
        .codec_dai_name = "tlv320aic3x-hifi",
+       .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                  SND_SOC_DAIFMT_CBM_CFM,
        .init = n810_aic33_init,
        .ops = &n810_ops,
 };
@@ -321,6 +290,13 @@ static struct snd_soc_card snd_soc_n810 = {
        .name = "N810",
        .dai_link = &n810_dai,
        .num_links = 1,
+
+       .controls = aic33_n810_controls,
+       .num_controls = ARRAY_SIZE(aic33_n810_controls),
+       .dapm_widgets = aic33_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(aic33_dapm_widgets),
+       .dapm_routes = audio_map,
+       .num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static struct platform_device *n810_snd_device;
index 478d607..4314647 100644 (file)
@@ -317,6 +317,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
                return 0;
        }
 
+       regs->rcr2      &= ~(RPHASE | RFRLEN2(0x7f) | RWDLEN2(7));
+       regs->xcr2      &= ~(RPHASE | XFRLEN2(0x7f) | XWDLEN2(7));
+       regs->rcr1      &= ~(RFRLEN1(0x7f) | RWDLEN1(7));
+       regs->xcr1      &= ~(XFRLEN1(0x7f) | XWDLEN1(7));
        format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
        wpf = channels = params_channels(params);
        if (channels == 2 && (format == SND_SOC_DAIFMT_I2S ||
@@ -369,6 +373,8 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
                framesize = wlen * channels;
 
        /* Set FS period and length in terms of bit clock periods */
+       regs->srgr2     &= ~FPER(0xfff);
+       regs->srgr1     &= ~FWID(0xff);
        switch (format) {
        case SND_SOC_DAIFMT_I2S:
        case SND_SOC_DAIFMT_LEFT_J:
@@ -398,7 +404,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 {
        struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
        struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
-       unsigned int temp_fmt = fmt;
+       bool inv_fs = false;
 
        if (mcbsp_data->configured)
                return 0;
@@ -430,21 +436,21 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                regs->xcr2      |= XDATDLY(0);
                regs->spcr1     |= RJUST(2);
                /* Invert FS polarity configuration */
-               temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
+               inv_fs = true;
                break;
        case SND_SOC_DAIFMT_DSP_A:
                /* 1-bit data delay */
                regs->rcr2      |= RDATDLY(1);
                regs->xcr2      |= XDATDLY(1);
                /* Invert FS polarity configuration */
-               temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
+               inv_fs = true;
                break;
        case SND_SOC_DAIFMT_DSP_B:
                /* 0-bit data delay */
                regs->rcr2      |= RDATDLY(0);
                regs->xcr2      |= XDATDLY(0);
                /* Invert FS polarity configuration */
-               temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
+               inv_fs = true;
                break;
        default:
                /* Unsupported data format */
@@ -468,7 +474,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        }
 
        /* Set bit clock (CLKX/CLKR) and FS polarities */
-       switch (temp_fmt & SND_SOC_DAIFMT_INV_MASK) {
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
                /*
                 * Normal BCLK + FS.
@@ -489,6 +495,8 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        default:
                return -EINVAL;
        }
+       if (inv_fs == true)
+               regs->pcr0 ^= FSXP | FSRP;
 
        return 0;
 }
@@ -503,6 +511,7 @@ static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
                return -ENODEV;
 
        mcbsp_data->clk_div = div;
+       regs->srgr1     &= ~CLKGDV(0xff);
        regs->srgr1     |= CLKGDV(div - 1);
 
        return 0;
@@ -516,11 +525,12 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
        struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
        int err = 0;
 
-       if (mcbsp_data->active)
+       if (mcbsp_data->active) {
                if (freq == mcbsp_data->in_freq)
                        return 0;
                else
                        return -EBUSY;
+       }
 
        /* The McBSP signal muxing functions are only available on McBSP1 */
        if (clk_id == OMAP_MCBSP_CLKR_SRC_CLKR ||
@@ -531,6 +541,8 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
                        return -EINVAL;
 
        mcbsp_data->in_freq = freq;
+       regs->srgr2     &= ~CLKSM;
+       regs->pcr0      &= ~SCLKME;
 
        switch (clk_id) {
        case OMAP_MCBSP_SYSCLK_CLK:
@@ -605,8 +617,7 @@ static int mcbsp_dai_probe(struct snd_soc_dai *dai)
        return 0;
 }
 
-static struct snd_soc_dai_driver omap_mcbsp_dai =
-{
+static struct snd_soc_dai_driver omap_mcbsp_dai = {
        .probe = mcbsp_dai_probe,
        .playback = {
                .channels_min = 1,
index bed09c2..41d1706 100644 (file)
@@ -1,11 +1,12 @@
 /*
  * omap-mcpdm.c  --  OMAP ALSA SoC DAI driver using McPDM port
  *
- * Copyright (C) 2009 Texas Instruments
+ * Copyright (C) 2009 - 2011 Texas Instruments
  *
- * Author: Misael Lopez Cruz <x0052729@ti.com>
+ * Author: Misael Lopez Cruz <misael.lopez@ti.com>
  * Contact: Jorge Eduardo Candelaria <x0107209@ti.com>
  *          Margarita Olaya <magi.olaya@ti.com>
+ *          Peter Ujfalusi <peter.ujfalusi@ti.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
-#include <sound/initval.h>
 #include <sound/soc.h>
 
 #include <plat/dma.h>
-#include <plat/mcbsp.h>
-#include "mcpdm.h"
+#include <plat/omap_hwmod.h>
+#include "omap-mcpdm.h"
 #include "omap-pcm.h"
 
-struct omap_mcpdm_data {
-       struct omap_mcpdm_link *links;
-       int active;
-};
+struct omap_mcpdm {
+       struct device *dev;
+       unsigned long phys_base;
+       void __iomem *io_base;
+       int irq;
 
-static struct omap_mcpdm_link omap_mcpdm_links[] = {
-       /* downlink */
-       {
-               .irq_mask = MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL,
-               .threshold = 1,
-               .format = PDMOUTFORMAT_LJUST,
-       },
-       /* uplink */
-       {
-               .irq_mask = MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL,
-               .threshold = 1,
-               .format = PDMOUTFORMAT_LJUST,
-       },
-};
+       struct mutex mutex;
+
+       /* channel data */
+       u32 dn_channels;
+       u32 up_channels;
+
+       /* McPDM FIFO thresholds */
+       u32 dn_threshold;
+       u32 up_threshold;
 
-static struct omap_mcpdm_data mcpdm_data = {
-       .links = omap_mcpdm_links,
-       .active = 0,
+       /* McPDM dn offsets for rx1, and 2 channels */
+       u32 dn_rx_offset;
 };
 
 /*
@@ -71,88 +73,259 @@ static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = {
                .dma_req = OMAP44XX_DMA_MCPDM_DL,
                .data_type = OMAP_DMA_DATA_TYPE_S32,
                .sync_mode = OMAP_DMA_SYNC_PACKET,
-               .packet_size = 16,
-               .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_DN_DATA,
+               .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_DN_DATA,
        },
        {
                .name = "Audio capture",
                .dma_req = OMAP44XX_DMA_MCPDM_UP,
                .data_type = OMAP_DMA_DATA_TYPE_S32,
                .sync_mode = OMAP_DMA_SYNC_PACKET,
-               .packet_size = 16,
-               .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_UP_DATA,
+               .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_UP_DATA,
        },
 };
 
-static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
-                                 struct snd_soc_dai *dai)
+static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val)
 {
-       int err = 0;
+       __raw_writel(val, mcpdm->io_base + reg);
+}
 
-       if (!dai->active)
-               err = omap_mcpdm_request();
+static inline int omap_mcpdm_read(struct omap_mcpdm *mcpdm, u16 reg)
+{
+       return __raw_readl(mcpdm->io_base + reg);
+}
 
-       return err;
+#ifdef DEBUG
+static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm)
+{
+       dev_dbg(mcpdm->dev, "***********************\n");
+       dev_dbg(mcpdm->dev, "IRQSTATUS_RAW:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS_RAW));
+       dev_dbg(mcpdm->dev, "IRQSTATUS:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS));
+       dev_dbg(mcpdm->dev, "IRQENABLE_SET:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_IRQENABLE_SET));
+       dev_dbg(mcpdm->dev, "IRQENABLE_CLR:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_IRQENABLE_CLR));
+       dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_IRQWAKE_EN));
+       dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_DMAENABLE_SET));
+       dev_dbg(mcpdm->dev, "DMAENABLE_CLR:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_DMAENABLE_CLR));
+       dev_dbg(mcpdm->dev, "DMAWAKEEN:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_DMAWAKEEN));
+       dev_dbg(mcpdm->dev, "CTRL:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL));
+       dev_dbg(mcpdm->dev, "DN_DATA:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_DN_DATA));
+       dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_UP_DATA));
+       dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_FIFO_CTRL_DN));
+       dev_dbg(mcpdm->dev, "FIFO_CTRL_UP:  0x%04x\n",
+                       omap_mcpdm_read(mcpdm, MCPDM_REG_FIFO_CTRL_UP));
+       dev_dbg(mcpdm->dev, "***********************\n");
 }
+#else
+static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) {}
+#endif
 
-static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
-                                   struct snd_soc_dai *dai)
+/*
+ * Enables the transfer through the PDM interface to/from the Phoenix
+ * codec by enabling the corresponding UP or DN channels.
+ */
+static void omap_mcpdm_start(struct omap_mcpdm *mcpdm)
+{
+       u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+       ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+       ctrl |= mcpdm->dn_channels | mcpdm->up_channels;
+       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+       ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+}
+
+/*
+ * Disables the transfer through the PDM interface to/from the Phoenix
+ * codec by disabling the corresponding UP or DN channels.
+ */
+static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm)
+{
+       u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+       ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+       ctrl &= ~(mcpdm->dn_channels | mcpdm->up_channels);
+       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+       ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+}
+
+/*
+ * Is the physical McPDM interface active.
+ */
+static inline int omap_mcpdm_active(struct omap_mcpdm *mcpdm)
+{
+       return omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL) &
+                                       (MCPDM_PDM_DN_MASK | MCPDM_PDM_UP_MASK);
+}
+
+/*
+ * Configures McPDM uplink, and downlink for audio.
+ * This function should be called before omap_mcpdm_start.
+ */
+static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm)
+{
+       omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_SET,
+                       MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL |
+                       MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL);
+
+       /* Enable DN RX1/2 offset cancellation feature, if configured */
+       if (mcpdm->dn_rx_offset) {
+               u32 dn_offset = mcpdm->dn_rx_offset;
+
+               omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset);
+               dn_offset |= (MCPDM_DN_OFST_RX1_EN | MCPDM_DN_OFST_RX2_EN);
+               omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset);
+       }
+
+       omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN, mcpdm->dn_threshold);
+       omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP, mcpdm->up_threshold);
+
+       omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_SET,
+                       MCPDM_DMA_DN_ENABLE | MCPDM_DMA_UP_ENABLE);
+}
+
+/*
+ * Cleans McPDM uplink, and downlink configuration.
+ * This function should be called when the stream is closed.
+ */
+static void omap_mcpdm_close_streams(struct omap_mcpdm *mcpdm)
+{
+       /* Disable irq request generation for downlink */
+       omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_CLR,
+                       MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL);
+
+       /* Disable DMA request generation for downlink */
+       omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_CLR, MCPDM_DMA_DN_ENABLE);
+
+       /* Disable irq request generation for uplink */
+       omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_CLR,
+                       MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL);
+
+       /* Disable DMA request generation for uplink */
+       omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_CLR, MCPDM_DMA_UP_ENABLE);
+
+       /* Disable RX1/2 offset cancellation */
+       if (mcpdm->dn_rx_offset)
+               omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, 0);
+}
+
+static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id)
+{
+       struct omap_mcpdm *mcpdm = dev_id;
+       int irq_status;
+
+       irq_status = omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS);
+
+       /* Acknowledge irq event */
+       omap_mcpdm_write(mcpdm, MCPDM_REG_IRQSTATUS, irq_status);
+
+       if (irq_status & MCPDM_DN_IRQ_FULL)
+               dev_dbg(mcpdm->dev, "DN (playback) FIFO Full\n");
+
+       if (irq_status & MCPDM_DN_IRQ_EMPTY)
+               dev_dbg(mcpdm->dev, "DN (playback) FIFO Empty\n");
+
+       if (irq_status & MCPDM_DN_IRQ)
+               dev_dbg(mcpdm->dev, "DN (playback) write request\n");
+
+       if (irq_status & MCPDM_UP_IRQ_FULL)
+               dev_dbg(mcpdm->dev, "UP (capture) FIFO Full\n");
+
+       if (irq_status & MCPDM_UP_IRQ_EMPTY)
+               dev_dbg(mcpdm->dev, "UP (capture) FIFO Empty\n");
+
+       if (irq_status & MCPDM_UP_IRQ)
+               dev_dbg(mcpdm->dev, "UP (capture) write request\n");
+
+       return IRQ_HANDLED;
+}
+
+static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
+                                 struct snd_soc_dai *dai)
 {
-       if (!dai->active)
-               omap_mcpdm_free();
+       struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+       mutex_lock(&mcpdm->mutex);
+
+       if (!dai->active) {
+               pm_runtime_get_sync(mcpdm->dev);
+
+               /* Enable watch dog for ES above ES 1.0 to avoid saturation */
+               if (omap_rev() != OMAP4430_REV_ES1_0) {
+                       u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+                       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL,
+                                        ctrl | MCPDM_WD_EN);
+               }
+               omap_mcpdm_open_streams(mcpdm);
+       }
+
+       mutex_unlock(&mcpdm->mutex);
+
+       return 0;
 }
 
-static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
                                  struct snd_soc_dai *dai)
 {
-       struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
-       int stream = substream->stream;
-       int err = 0;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-       case SNDRV_PCM_TRIGGER_RESUME:
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               if (!mcpdm_priv->active++)
-                       omap_mcpdm_start(stream);
-               break;
+       struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
 
-       case SNDRV_PCM_TRIGGER_STOP:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               if (!--mcpdm_priv->active)
-                       omap_mcpdm_stop(stream);
-               break;
-       default:
-               err = -EINVAL;
+       mutex_lock(&mcpdm->mutex);
+
+       if (!dai->active) {
+               if (omap_mcpdm_active(mcpdm)) {
+                       omap_mcpdm_stop(mcpdm);
+                       omap_mcpdm_close_streams(mcpdm);
+               }
+
+               if (!omap_mcpdm_active(mcpdm))
+                       pm_runtime_put_sync(mcpdm->dev);
        }
 
-       return err;
+       mutex_unlock(&mcpdm->mutex);
 }
 
 static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
                                    struct snd_pcm_hw_params *params,
                                    struct snd_soc_dai *dai)
 {
-       struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
-       struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
+       struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
        int stream = substream->stream;
-       int channels, err, link_mask = 0;
-
-       snd_soc_dai_set_dma_data(dai, substream,
-                                &omap_mcpdm_dai_dma_params[stream]);
+       struct omap_pcm_dma_data *dma_data;
+       int channels;
+       int link_mask = 0;
 
        channels = params_channels(params);
        switch (channels) {
+       case 5:
+               if (stream == SNDRV_PCM_STREAM_CAPTURE)
+                       /* up to 3 channels for capture */
+                       return -EINVAL;
+               link_mask |= 1 << 4;
        case 4:
                if (stream == SNDRV_PCM_STREAM_CAPTURE)
-                       /* up to 2 channels for capture */
+                       /* up to 3 channels for capture */
                        return -EINVAL;
                link_mask |= 1 << 3;
        case 3:
-               if (stream == SNDRV_PCM_STREAM_CAPTURE)
-                       /* up to 2 channels for capture */
-                       return -EINVAL;
                link_mask |= 1 << 2;
        case 2:
                link_mask |= 1 << 1;
@@ -164,95 +337,187 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
+       dma_data = &omap_mcpdm_dai_dma_params[stream];
+
+       /* Configure McPDM channels, and DMA packet size */
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               mcpdm_links[stream].channels = link_mask << 3;
-               err = omap_mcpdm_playback_open(&mcpdm_links[stream]);
+               mcpdm->dn_channels = link_mask << 3;
+               dma_data->packet_size =
+                       (MCPDM_DN_THRES_MAX - mcpdm->dn_threshold) * channels;
        } else {
-               mcpdm_links[stream].channels = link_mask << 0;
-               err = omap_mcpdm_capture_open(&mcpdm_links[stream]);
+               mcpdm->up_channels = link_mask << 0;
+               dma_data->packet_size = mcpdm->up_threshold * channels;
        }
 
-       return err;
+       snd_soc_dai_set_dma_data(dai, substream, dma_data);
+
+       return 0;
 }
 
-static int omap_mcpdm_dai_hw_free(struct snd_pcm_substream *substream,
+static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
                                  struct snd_soc_dai *dai)
 {
-       struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
-       struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
-       int stream = substream->stream;
-       int err;
+       struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
 
-       if (substream->stream ==  SNDRV_PCM_STREAM_PLAYBACK)
-               err = omap_mcpdm_playback_close(&mcpdm_links[stream]);
-       else
-               err = omap_mcpdm_capture_close(&mcpdm_links[stream]);
+       if (!omap_mcpdm_active(mcpdm)) {
+               omap_mcpdm_start(mcpdm);
+               omap_mcpdm_reg_dump(mcpdm);
+       }
 
-       return err;
+       return 0;
 }
 
 static struct snd_soc_dai_ops omap_mcpdm_dai_ops = {
        .startup        = omap_mcpdm_dai_startup,
        .shutdown       = omap_mcpdm_dai_shutdown,
-       .trigger        = omap_mcpdm_dai_trigger,
        .hw_params      = omap_mcpdm_dai_hw_params,
-       .hw_free        = omap_mcpdm_dai_hw_free,
+       .prepare        = omap_mcpdm_prepare,
 };
 
-#define OMAP_MCPDM_RATES       (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
-#define OMAP_MCPDM_FORMATS     (SNDRV_PCM_FMTBIT_S32_LE)
+static int omap_mcpdm_probe(struct snd_soc_dai *dai)
+{
+       struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+       int ret;
 
-static int omap_mcpdm_dai_probe(struct snd_soc_dai *dai)
+       pm_runtime_enable(mcpdm->dev);
+
+       /* Disable lines while request is ongoing */
+       pm_runtime_get_sync(mcpdm->dev);
+       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00);
+
+       ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler,
+                               0, "McPDM", (void *)mcpdm);
+
+       pm_runtime_put_sync(mcpdm->dev);
+
+       if (ret) {
+               dev_err(mcpdm->dev, "Request for IRQ failed\n");
+               pm_runtime_disable(mcpdm->dev);
+       }
+
+       /* Configure McPDM threshold values */
+       mcpdm->dn_threshold = 2;
+       mcpdm->up_threshold = MCPDM_UP_THRES_MAX - 3;
+       return ret;
+}
+
+static int omap_mcpdm_remove(struct snd_soc_dai *dai)
 {
-       snd_soc_dai_set_drvdata(dai, &mcpdm_data);
+       struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+       free_irq(mcpdm->irq, (void *)mcpdm);
+       pm_runtime_disable(mcpdm->dev);
+
        return 0;
 }
 
+#define OMAP_MCPDM_RATES       (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+#define OMAP_MCPDM_FORMATS     SNDRV_PCM_FMTBIT_S32_LE
+
 static struct snd_soc_dai_driver omap_mcpdm_dai = {
-       .probe = omap_mcpdm_dai_probe,
+       .probe = omap_mcpdm_probe,
+       .remove = omap_mcpdm_remove,
+       .probe_order = SND_SOC_COMP_ORDER_LATE,
+       .remove_order = SND_SOC_COMP_ORDER_EARLY,
        .playback = {
                .channels_min = 1,
-               .channels_max = 4,
+               .channels_max = 5,
                .rates = OMAP_MCPDM_RATES,
                .formats = OMAP_MCPDM_FORMATS,
        },
        .capture = {
                .channels_min = 1,
-               .channels_max = 2,
+               .channels_max = 3,
                .rates = OMAP_MCPDM_RATES,
                .formats = OMAP_MCPDM_FORMATS,
        },
        .ops = &omap_mcpdm_dai_ops,
 };
 
+void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd,
+                                   u8 rx1, u8 rx2)
+{
+       struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(rtd->cpu_dai);
+
+       mcpdm->dn_rx_offset = MCPDM_DNOFST_RX1(rx1) | MCPDM_DNOFST_RX2(rx2);
+}
+EXPORT_SYMBOL_GPL(omap_mcpdm_configure_dn_offsets);
+
 static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
 {
-       int ret;
+       struct omap_mcpdm *mcpdm;
+       struct resource *res;
+       int ret = 0;
+
+       mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL);
+       if (!mcpdm)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, mcpdm);
+
+       mutex_init(&mcpdm->mutex);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "no resource\n");
+               goto err_res;
+       }
+
+       if (!request_mem_region(res->start, resource_size(res), "McPDM")) {
+               ret = -EBUSY;
+               goto err_res;
+       }
+
+       mcpdm->io_base = ioremap(res->start, resource_size(res));
+       if (!mcpdm->io_base) {
+               ret = -ENOMEM;
+               goto err_iomap;
+       }
+
+       mcpdm->irq = platform_get_irq(pdev, 0);
+       if (mcpdm->irq < 0) {
+               ret = mcpdm->irq;
+               goto err_irq;
+       }
+
+       mcpdm->dev = &pdev->dev;
 
-       ret = omap_mcpdm_probe(pdev);
-       if (ret < 0)
-               return ret;
        ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai);
-       if (ret < 0)
-               omap_mcpdm_remove(pdev);
+       if (!ret)
+               return 0;
+
+err_irq:
+       iounmap(mcpdm->io_base);
+err_iomap:
+       release_mem_region(res->start, resource_size(res));
+err_res:
+       kfree(mcpdm);
        return ret;
 }
 
 static int __devexit asoc_mcpdm_remove(struct platform_device *pdev)
 {
+       struct omap_mcpdm *mcpdm = platform_get_drvdata(pdev);
+       struct resource *res;
+
        snd_soc_unregister_dai(&pdev->dev);
-       omap_mcpdm_remove(pdev);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       iounmap(mcpdm->io_base);
+       release_mem_region(res->start, resource_size(res));
+
+       kfree(mcpdm);
        return 0;
 }
 
 static struct platform_driver asoc_mcpdm_driver = {
        .driver = {
-                       .name = "omap-mcpdm-dai",
-                       .owner = THIS_MODULE,
+               .name   = "omap-mcpdm",
+               .owner  = THIS_MODULE,
        },
 
-       .probe = asoc_mcpdm_probe,
-       .remove = __devexit_p(asoc_mcpdm_remove),
+       .probe  = asoc_mcpdm_probe,
+       .remove = __devexit_p(asoc_mcpdm_remove),
 };
 
 static int __init snd_omap_mcpdm_init(void)
@@ -267,6 +532,6 @@ static void __exit snd_omap_mcpdm_exit(void)
 }
 module_exit(snd_omap_mcpdm_exit);
 
-MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
 MODULE_DESCRIPTION("OMAP PDM SoC Interface");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-mcpdm.h b/sound/soc/omap/omap-mcpdm.h
new file mode 100644 (file)
index 0000000..de8cf26
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * omap-mcpdm.h
+ *
+ * Copyright (C) 2009 - 2011 Texas Instruments
+ *
+ * Contact: Misael Lopez Cruz <misael.lopez@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_MCPDM_H__
+#define __OMAP_MCPDM_H__
+
+#define MCPDM_REG_REVISION             0x00
+#define MCPDM_REG_SYSCONFIG            0x10
+#define MCPDM_REG_IRQSTATUS_RAW                0x24
+#define MCPDM_REG_IRQSTATUS            0x28
+#define MCPDM_REG_IRQENABLE_SET                0x2C
+#define MCPDM_REG_IRQENABLE_CLR                0x30
+#define MCPDM_REG_IRQWAKE_EN           0x34
+#define MCPDM_REG_DMAENABLE_SET                0x38
+#define MCPDM_REG_DMAENABLE_CLR                0x3C
+#define MCPDM_REG_DMAWAKEEN            0x40
+#define MCPDM_REG_CTRL                 0x44
+#define MCPDM_REG_DN_DATA              0x48
+#define MCPDM_REG_UP_DATA              0x4C
+#define MCPDM_REG_FIFO_CTRL_DN         0x50
+#define MCPDM_REG_FIFO_CTRL_UP         0x54
+#define MCPDM_REG_DN_OFFSET            0x58
+
+/*
+ * MCPDM_IRQ bit fields
+ * IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR
+ */
+
+#define MCPDM_DN_IRQ                   (1 << 0)
+#define MCPDM_DN_IRQ_EMPTY             (1 << 1)
+#define MCPDM_DN_IRQ_ALMST_EMPTY       (1 << 2)
+#define MCPDM_DN_IRQ_FULL              (1 << 3)
+
+#define MCPDM_UP_IRQ                   (1 << 8)
+#define MCPDM_UP_IRQ_EMPTY             (1 << 9)
+#define MCPDM_UP_IRQ_ALMST_FULL                (1 << 10)
+#define MCPDM_UP_IRQ_FULL              (1 << 11)
+
+#define MCPDM_DOWNLINK_IRQ_MASK                0x00F
+#define MCPDM_UPLINK_IRQ_MASK          0xF00
+
+/*
+ * MCPDM_DMAENABLE bit fields
+ */
+
+#define MCPDM_DMA_DN_ENABLE            (1 << 0)
+#define MCPDM_DMA_UP_ENABLE            (1 << 1)
+
+/*
+ * MCPDM_CTRL bit fields
+ */
+
+#define MCPDM_PDM_UPLINK_EN(x)         (1 << (x - 1)) /* ch1 is at bit 0 */
+#define MCPDM_PDM_DOWNLINK_EN(x)       (1 << (x + 2)) /* ch1 is at bit 3 */
+#define MCPDM_PDMOUTFORMAT             (1 << 8)
+#define MCPDM_CMD_INT                  (1 << 9)
+#define MCPDM_STATUS_INT               (1 << 10)
+#define MCPDM_SW_UP_RST                        (1 << 11)
+#define MCPDM_SW_DN_RST                        (1 << 12)
+#define MCPDM_WD_EN                    (1 << 14)
+#define MCPDM_PDM_UP_MASK              0x7
+#define MCPDM_PDM_DN_MASK              (0x1f << 3)
+
+
+#define MCPDM_PDMOUTFORMAT_LJUST       (0 << 8)
+#define MCPDM_PDMOUTFORMAT_RJUST       (1 << 8)
+
+/*
+ * MCPDM_FIFO_CTRL bit fields
+ */
+
+#define MCPDM_UP_THRES_MAX             0xF
+#define MCPDM_DN_THRES_MAX             0xF
+
+/*
+ * MCPDM_DN_OFFSET bit fields
+ */
+
+#define MCPDM_DN_OFST_RX1_EN           (1 << 0)
+#define MCPDM_DNOFST_RX1(x)            ((x & 0x1f) << 1)
+#define MCPDM_DN_OFST_RX2_EN           (1 << 8)
+#define MCPDM_DNOFST_RX2(x)            ((x & 0x1f) << 9)
+
+void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd,
+                                   u8 rx1, u8 rx2);
+
+#endif /* End of __OMAP_MCPDM_H__ */
index 9b5c88a..5e37ec9 100644 (file)
@@ -198,6 +198,14 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
                              OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ);
        else if (!substream->runtime->no_period_wakeup)
                omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
+       else {
+               /*
+                * No period wakeup:
+                * we need to disable BLOCK_IRQ, which is enabled by the omap
+                * dma core at request dma time.
+                */
+               omap_disable_dma_irq(prtd->dma_ch, OMAP_DMA_BLOCK_IRQ);
+       }
 
        if (!(cpu_class_is_omap1())) {
                omap_set_dma_src_burst_mode(prtd->dma_ch,
index 0daa044..bf9ae2a 100644 (file)
@@ -36,29 +36,8 @@ static int omap3evm_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "Can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "Can't set cpu DAI configuration\n");
-               return ret;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
                                     SND_SOC_CLOCK_IN);
@@ -82,6 +61,8 @@ static struct snd_soc_dai_link omap3evm_dai = {
        .codec_dai_name = "twl4030-hifi",
        .platform_name = "omap-pcm-audio",
        .codec_name = "twl4030-codec",
+       .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                  SND_SOC_DAIFMT_CBM_CFM,
        .ops            = &omap3evm_ops,
 };
 
index 8047c52..30a75b4 100644 (file)
@@ -48,24 +48,8 @@ static int omap3pandora_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       int fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-                 SND_SOC_DAIFMT_CBS_CFS;
        int ret;
 
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai, fmt);
-       if (ret < 0) {
-               pr_err(PREFIX "can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
-       if (ret < 0) {
-               pr_err(PREFIX "can't set cpu DAI configuration\n");
-               return ret;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
                                            SND_SOC_CLOCK_IN);
@@ -189,10 +173,8 @@ static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd)
        if (ret < 0)
                return ret;
 
-       snd_soc_dapm_add_routes(dapm, omap3pandora_out_map,
+       return snd_soc_dapm_add_routes(dapm, omap3pandora_out_map,
                ARRAY_SIZE(omap3pandora_out_map));
-
-       return snd_soc_dapm_sync(dapm);
 }
 
 static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd)
@@ -212,10 +194,8 @@ static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd)
        if (ret < 0)
                return ret;
 
-       snd_soc_dapm_add_routes(dapm, omap3pandora_in_map,
+       return snd_soc_dapm_add_routes(dapm, omap3pandora_in_map,
                ARRAY_SIZE(omap3pandora_in_map));
-
-       return snd_soc_dapm_sync(dapm);
 }
 
 static struct snd_soc_ops omap3pandora_ops = {
@@ -231,6 +211,8 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
                .codec_dai_name = "twl4030-hifi",
                .platform_name = "omap-pcm-audio",
                .codec_name = "twl4030-codec",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                          SND_SOC_DAIFMT_CBS_CFS,
                .ops = &omap3pandora_ops,
                .init = omap3pandora_out_init,
        }, {
@@ -240,6 +222,8 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
                .codec_dai_name = "twl4030-hifi",
                .platform_name = "omap-pcm-audio",
                .codec_name = "twl4030-codec",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                          SND_SOC_DAIFMT_CBS_CFS,
                .ops = &omap3pandora_ops,
                .init = omap3pandora_in_init,
        }
index 7e75e77..db91cca 100644 (file)
@@ -55,29 +55,8 @@ static int osk_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int err;
 
-       /* Set codec DAI configuration */
-       err = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_DSP_B |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (err < 0) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return err;
-       }
-
-       /* Set cpu DAI configuration */
-       err = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_DSP_B |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (err < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return err;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        err =
            snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
@@ -112,27 +91,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"MICIN", NULL, "Mic Jack"},
 };
 
-static int osk_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
-{
-       struct snd_soc_codec *codec = rtd->codec;
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       /* Add osk5912 specific widgets */
-       snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
-                                 ARRAY_SIZE(tlv320aic23_dapm_widgets));
-
-       /* Set up osk5912 specific audio path audio_map */
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-       snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
-       snd_soc_dapm_enable_pin(dapm, "Line In");
-       snd_soc_dapm_enable_pin(dapm, "Mic Jack");
-
-       snd_soc_dapm_sync(dapm);
-
-       return 0;
-}
-
 /* Digital audio interface glue - connects codec <--> CPU */
 static struct snd_soc_dai_link osk_dai = {
        .name = "TLV320AIC23",
@@ -141,7 +99,8 @@ static struct snd_soc_dai_link osk_dai = {
        .codec_dai_name = "tlv320aic23-hifi",
        .platform_name = "omap-pcm-audio",
        .codec_name = "tlv320aic23-codec",
-       .init = osk_tlv320aic23_init,
+       .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
+                  SND_SOC_DAIFMT_CBM_CFM,
        .ops = &osk_ops,
 };
 
@@ -150,6 +109,11 @@ static struct snd_soc_card snd_soc_card_osk = {
        .name = "OSK5912",
        .dai_link = &osk_dai,
        .num_links = 1,
+
+       .dapm_widgets = tlv320aic23_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
+       .dapm_routes = audio_map,
+       .num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static struct platform_device *osk_snd_device;
index bbcf380..739efe9 100644 (file)
@@ -38,29 +38,8 @@ static int overo_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return ret;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
                                            SND_SOC_CLOCK_IN);
@@ -84,6 +63,8 @@ static struct snd_soc_dai_link overo_dai = {
        .codec_dai_name = "twl4030-hifi",
        .platform_name = "omap-pcm-audio",
        .codec_name = "twl4030-codec",
+       .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                  SND_SOC_DAIFMT_CBM_CFM,
        .ops = &overo_ops,
 };
 
index 893300a..a568423 100644 (file)
@@ -115,24 +115,6 @@ static int rx51_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       int err;
-
-       /* Set codec DAI configuration */
-       err = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_DSP_A |
-                                 SND_SOC_DAIFMT_IB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (err < 0)
-               return err;
-
-       /* Set cpu DAI configuration */
-       err = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_DSP_A |
-                                 SND_SOC_DAIFMT_IB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (err < 0)
-               return err;
 
        /* Set the codec system clock for DAC and ADC */
        return snd_soc_dai_set_sysclk(codec_dai, 0, 19200000,
@@ -335,8 +317,6 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
        if (err < 0)
                return err;
 
-       snd_soc_dapm_sync(dapm);
-
        /* AV jack detection */
        err = snd_soc_jack_new(codec, "AV Jack",
                               SND_JACK_HEADSET | SND_JACK_VIDEOOUT,
@@ -377,6 +357,8 @@ static struct snd_soc_dai_link rx51_dai[] = {
                .codec_dai_name = "tlv320aic3x-hifi",
                .platform_name = "omap-pcm-audio",
                .codec_name = "tlv320aic3x-codec.2-0018",
+               .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
+                          SND_SOC_DAIFMT_CBM_CFM,
                .init = rx51_aic34_init,
                .ops = &rx51_ops,
        },
index 9f6a758..4f1969d 100644 (file)
@@ -53,29 +53,8 @@ static int sdp3430_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return ret;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
                                            SND_SOC_CLOCK_IN);
@@ -91,49 +70,6 @@ static struct snd_soc_ops sdp3430_ops = {
        .hw_params = sdp3430_hw_params,
 };
 
-static int sdp3430_hw_voice_params(struct snd_pcm_substream *substream,
-       struct snd_pcm_hw_params *params)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       int ret;
-
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai,
-                               SND_SOC_DAIFMT_DSP_A |
-                               SND_SOC_DAIFMT_IB_NF |
-                               SND_SOC_DAIFMT_CBM_CFM);
-       if (ret) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai,
-                               SND_SOC_DAIFMT_DSP_A |
-                               SND_SOC_DAIFMT_IB_NF |
-                               SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return ret;
-       }
-
-       /* Set the codec system clock for DAC and ADC */
-       ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
-                                           SND_SOC_CLOCK_IN);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set codec system clock\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-static struct snd_soc_ops sdp3430_voice_ops = {
-       .hw_params = sdp3430_hw_voice_params,
-};
-
 /* Headset jack */
 static struct snd_soc_jack hs_jack;
 
@@ -193,15 +129,6 @@ static int sdp3430_twl4030_init(struct snd_soc_pcm_runtime *rtd)
        struct snd_soc_dapm_context *dapm = &codec->dapm;
        int ret;
 
-       /* Add SDP3430 specific widgets */
-       ret = snd_soc_dapm_new_controls(dapm, sdp3430_twl4030_dapm_widgets,
-                               ARRAY_SIZE(sdp3430_twl4030_dapm_widgets));
-       if (ret)
-               return ret;
-
-       /* Set up SDP3430 specific audio path audio_map */
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
        /* SDP3430 connected pins */
        snd_soc_dapm_enable_pin(dapm, "Ext Mic");
        snd_soc_dapm_enable_pin(dapm, "Ext Spk");
@@ -223,10 +150,6 @@ static int sdp3430_twl4030_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_nc_pin(dapm, "CARKITL");
        snd_soc_dapm_nc_pin(dapm, "CARKITR");
 
-       ret = snd_soc_dapm_sync(dapm);
-       if (ret)
-               return ret;
-
        /* Headset jack detection */
        ret = snd_soc_jack_new(codec, "Headset Jack",
                                SND_JACK_HEADSET, &hs_jack);
@@ -267,6 +190,8 @@ static struct snd_soc_dai_link sdp3430_dai[] = {
                .codec_dai_name = "twl4030-hifi",
                .platform_name = "omap-pcm-audio",
                .codec_name = "twl4030-codec",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                          SND_SOC_DAIFMT_CBM_CFM,
                .init = sdp3430_twl4030_init,
                .ops = &sdp3430_ops,
        },
@@ -277,8 +202,10 @@ static struct snd_soc_dai_link sdp3430_dai[] = {
                .codec_dai_name = "twl4030-voice",
                .platform_name = "omap-pcm-audio",
                .codec_name = "twl4030-codec",
+               .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
+                          SND_SOC_DAIFMT_CBM_CFM,
                .init = sdp3430_twl4030_voice_init,
-               .ops = &sdp3430_voice_ops,
+               .ops = &sdp3430_ops,
        },
 };
 
@@ -287,6 +214,11 @@ static struct snd_soc_card snd_soc_sdp3430 = {
        .name = "SDP3430",
        .dai_link = sdp3430_dai,
        .num_links = ARRAY_SIZE(sdp3430_dai),
+
+       .dapm_widgets = sdp3430_twl4030_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(sdp3430_twl4030_dapm_widgets),
+       .dapm_routes = audio_map,
+       .num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static struct platform_device *sdp3430_snd_device;
index b80efb0..cc3d792 100644 (file)
@@ -32,7 +32,7 @@
 #include <plat/hardware.h>
 #include <plat/mux.h>
 
-#include "mcpdm.h"
+#include "omap-mcpdm.h"
 #include "omap-pcm.h"
 #include "../codecs/twl6040.h"
 
@@ -88,7 +88,7 @@ static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = {
        SND_SOC_DAPM_MIC("Headset Mic", NULL),
        SND_SOC_DAPM_HP("Headset Stereophone", NULL),
        SND_SOC_DAPM_SPK("Earphone Spk", NULL),
-       SND_SOC_DAPM_INPUT("Aux/FM Stereo In"),
+       SND_SOC_DAPM_INPUT("FM Stereo In"),
 };
 
 static const struct snd_soc_dapm_route audio_map[] = {
@@ -113,36 +113,22 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Earphone Spk", NULL, "EP"},
 
        /* Aux/FM Stereo In: AFML, AFMR */
-       {"AFML", NULL, "Aux/FM Stereo In"},
-       {"AFMR", NULL, "Aux/FM Stereo In"},
+       {"AFML", NULL, "FM Stereo In"},
+       {"AFMR", NULL, "FM Stereo In"},
 };
 
 static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_codec *codec = rtd->codec;
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-       int ret;
-
-       /* Add SDP4430 specific widgets */
-       ret = snd_soc_dapm_new_controls(dapm, sdp4430_twl6040_dapm_widgets,
-                               ARRAY_SIZE(sdp4430_twl6040_dapm_widgets));
-       if (ret)
-               return ret;
-
-       /* Set up SDP4430 specific audio path audio_map */
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
+       int ret, hs_trim;
 
-       /* SDP4430 connected pins */
-       snd_soc_dapm_enable_pin(dapm, "Ext Mic");
-       snd_soc_dapm_enable_pin(dapm, "Ext Spk");
-       snd_soc_dapm_enable_pin(dapm, "AFML");
-       snd_soc_dapm_enable_pin(dapm, "AFMR");
-       snd_soc_dapm_enable_pin(dapm, "Headset Mic");
-       snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
-
-       ret = snd_soc_dapm_sync(dapm);
-       if (ret)
-               return ret;
+       /*
+        * Configure McPDM offset cancellation based on the HSOTRIM value from
+        * twl6040.
+        */
+       hs_trim = twl6040_get_trim_value(codec, TWL6040_TRIM_HSOTRIM);
+       omap_mcpdm_configure_dn_offsets(rtd, TWL6040_HSF_TRIM_LEFT(hs_trim),
+                                       TWL6040_HSF_TRIM_RIGHT(hs_trim));
 
        /* Headset jack detection */
        ret = snd_soc_jack_new(codec, "Headset Jack",
@@ -165,8 +151,8 @@ static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
 static struct snd_soc_dai_link sdp4430_dai = {
        .name = "TWL6040",
        .stream_name = "TWL6040",
-       .cpu_dai_name ="omap-mcpdm-dai",
-       .codec_dai_name = "twl6040-hifi",
+       .cpu_dai_name = "omap-mcpdm",
+       .codec_dai_name = "twl6040-legacy",
        .platform_name = "omap-pcm-audio",
        .codec_name = "twl6040-codec",
        .init = sdp4430_twl6040_init,
@@ -178,6 +164,11 @@ static struct snd_soc_card snd_soc_sdp4430 = {
        .name = "SDP4430",
        .dai_link = &sdp4430_dai,
        .num_links = 1,
+
+       .dapm_widgets = sdp4430_twl6040_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(sdp4430_twl6040_dapm_widgets),
+       .dapm_routes = audio_map,
+       .num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static struct platform_device *sdp4430_snd_device;
index 9a2666f..7cf35c8 100644 (file)
@@ -44,29 +44,8 @@ static int zoom2_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai,
-                                 SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return ret;
-       }
-
        /* Set the codec system clock for DAC and ADC */
        ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
                                        SND_SOC_CLOCK_IN);
@@ -82,49 +61,6 @@ static struct snd_soc_ops zoom2_ops = {
        .hw_params = zoom2_hw_params,
 };
 
-static int zoom2_hw_voice_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *params)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       int ret;
-
-       /* Set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai,
-                               SND_SOC_DAIFMT_DSP_A |
-                               SND_SOC_DAIFMT_IB_NF |
-                               SND_SOC_DAIFMT_CBM_CFM);
-       if (ret) {
-               printk(KERN_ERR "can't set codec DAI configuration\n");
-               return ret;
-       }
-
-       /* Set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai,
-                               SND_SOC_DAIFMT_DSP_A |
-                               SND_SOC_DAIFMT_IB_NF |
-                               SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set cpu DAI configuration\n");
-               return ret;
-       }
-
-       /* Set the codec system clock for DAC and ADC */
-       ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
-                                       SND_SOC_CLOCK_IN);
-       if (ret < 0) {
-               printk(KERN_ERR "can't set codec system clock\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-static struct snd_soc_ops zoom2_voice_ops = {
-       .hw_params = zoom2_hw_voice_params,
-};
-
 /* Zoom2 machine DAPM */
 static const struct snd_soc_dapm_widget zoom2_twl4030_dapm_widgets[] = {
        SND_SOC_DAPM_MIC("Ext Mic", NULL),
@@ -162,23 +98,6 @@ static int zoom2_twl4030_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_codec *codec = rtd->codec;
        struct snd_soc_dapm_context *dapm = &codec->dapm;
-       int ret;
-
-       /* Add Zoom2 specific widgets */
-       ret = snd_soc_dapm_new_controls(dapm, zoom2_twl4030_dapm_widgets,
-                               ARRAY_SIZE(zoom2_twl4030_dapm_widgets));
-       if (ret)
-               return ret;
-
-       /* Set up Zoom2 specific audio path audio_map */
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-       /* Zoom2 connected pins */
-       snd_soc_dapm_enable_pin(dapm, "Ext Mic");
-       snd_soc_dapm_enable_pin(dapm, "Ext Spk");
-       snd_soc_dapm_enable_pin(dapm, "Headset Mic");
-       snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
-       snd_soc_dapm_enable_pin(dapm, "Aux In");
 
        /* TWL4030 not connected pins */
        snd_soc_dapm_nc_pin(dapm, "CARKITMIC");
@@ -190,9 +109,7 @@ static int zoom2_twl4030_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_nc_pin(dapm, "CARKITL");
        snd_soc_dapm_nc_pin(dapm, "CARKITR");
 
-       ret = snd_soc_dapm_sync(dapm);
-
-       return ret;
+       return 0;
 }
 
 static int zoom2_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd)
@@ -217,6 +134,8 @@ static struct snd_soc_dai_link zoom2_dai[] = {
                .codec_dai_name = "twl4030-hifi",
                .platform_name = "omap-pcm-audio",
                .codec_name = "twl4030-codec",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                          SND_SOC_DAIFMT_CBM_CFM,
                .init = zoom2_twl4030_init,
                .ops = &zoom2_ops,
        },
@@ -227,8 +146,10 @@ static struct snd_soc_dai_link zoom2_dai[] = {
                .codec_dai_name = "twl4030-voice",
                .platform_name = "omap-pcm-audio",
                .codec_name = "twl4030-codec",
+               .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
+                          SND_SOC_DAIFMT_CBM_CFM,
                .init = zoom2_twl4030_voice_init,
-               .ops = &zoom2_voice_ops,
+               .ops = &zoom2_ops,
        },
 };
 
@@ -237,6 +158,11 @@ static struct snd_soc_card snd_soc_zoom2 = {
        .name = "Zoom2",
        .dai_link = zoom2_dai,
        .num_links = ARRAY_SIZE(zoom2_dai),
+
+       .dapm_widgets = zoom2_twl4030_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(zoom2_twl4030_dapm_widgets),
+       .dapm_routes = audio_map,
+       .num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static struct platform_device *zoom2_snd_device;
index 33ebc46..ffd2242 100644 (file)
@@ -121,6 +121,7 @@ config SND_PXA2XX_SOC_PALM27X
 config SND_SOC_SAARB
        tristate "SoC Audio support for Marvell Saarb"
        depends on SND_PXA2XX_SOC && MACH_SAARB
+       select MFD_88PM860X
        select SND_PXA_SOC_SSP
        select SND_SOC_88PM860X
        help
@@ -130,6 +131,7 @@ config SND_SOC_SAARB
 config SND_SOC_TAVOREVB3
        tristate "SoC Audio support for Marvell Tavor EVB3"
        depends on SND_PXA2XX_SOC && MACH_TAVOREVB3
+       select MFD_88PM860X
        select SND_PXA_SOC_SSP
        select SND_SOC_88PM860X
        help
index 28757fb..b0e2fb7 100644 (file)
@@ -299,7 +299,6 @@ static int corgi_wm8731_init(struct snd_soc_pcm_runtime *rtd)
        /* Set up corgi specific audio path audio_map */
        snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-       snd_soc_dapm_sync(dapm);
        return 0;
 }
 
index dc65650..35ed7eb 100644 (file)
@@ -108,8 +108,6 @@ static int e740_ac97_init(struct snd_soc_pcm_runtime *rtd)
 
        snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-       snd_soc_dapm_sync(dapm);
-
        return 0;
 }
 
index 51897fc..ce5f056 100644 (file)
@@ -90,8 +90,6 @@ static int e750_ac97_init(struct snd_soc_pcm_runtime *rtd)
 
        snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-       snd_soc_dapm_sync(dapm);
-
        return 0;
 }
 
index 053ed20..6a8f38b 100644 (file)
@@ -80,7 +80,6 @@ static int e800_ac97_init(struct snd_soc_pcm_runtime *rtd)
                                        ARRAY_SIZE(e800_dapm_widgets));
 
        snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-       snd_soc_dapm_sync(dapm);
 
        return 0;
 }
index 67dcc36..e79f516 100644 (file)
@@ -92,11 +92,10 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       unsigned int acps, acds, width, rate;
+       unsigned int acps, acds, width;
        unsigned int div4 = PXA_SSP_CLK_SCDB_4;
        int ret = 0;
 
-       rate = params_rate(params);
        width = snd_pcm_format_physical_width(params_format(params));
 
        /*
@@ -424,7 +423,6 @@ static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd)
        /* Set up magician specific audio path interconnects */
        snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-       snd_soc_dapm_sync(dapm);
        return 0;
 }
 
index 38ca675..0b8d1ee 100644 (file)
@@ -151,7 +151,6 @@ static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_enable_pin(dapm, "Front Mic");
        snd_soc_dapm_enable_pin(dapm, "GSM Line In");
        snd_soc_dapm_enable_pin(dapm, "GSM Line Out");
-       snd_soc_dapm_sync(dapm);
 
        return 0;
 }
index 504e400..7edc1fb 100644 (file)
@@ -107,10 +107,6 @@ static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_nc_pin(dapm, "PHONE");
        snd_soc_dapm_nc_pin(dapm, "MIC2");
 
-       err = snd_soc_dapm_sync(dapm);
-       if (err)
-               return err;
-
        /* Jack detection API stuff */
        err = snd_soc_jack_new(codec, "Headphone Jack",
                                SND_JACK_HEADPHONE, &hs_jack);
index da3ae43..4c29bc1 100644 (file)
@@ -265,7 +265,6 @@ static int poodle_wm8731_init(struct snd_soc_pcm_runtime *rtd)
        /* Set up poodle specific audio path audio_map */
        snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-       snd_soc_dapm_sync(dapm);
        return 0;
 }
 
index 9595189..d9467a2 100644 (file)
@@ -146,10 +146,6 @@ static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_disable_pin(dapm, "Headset Mic 2");
        snd_soc_dapm_disable_pin(dapm, "Headset Stereophone");
 
-       ret = snd_soc_dapm_sync(dapm);
-       if (ret)
-               return ret;
-
        /* Headset jack detection */
        snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
                        | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
index ce920e3..c2d6ff9 100644 (file)
@@ -301,7 +301,6 @@ static int spitz_wm8750_init(struct snd_soc_pcm_runtime *rtd)
        /* Set up spitz specific audio paths */
        snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-       snd_soc_dapm_sync(dapm);
        return 0;
 }
 
index f881f65..eeec892 100644 (file)
@@ -146,10 +146,6 @@ static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_disable_pin(dapm, "Headset Mic 2");
        snd_soc_dapm_disable_pin(dapm, "Headset Stereophone");
 
-       ret = snd_soc_dapm_sync(dapm);
-       if (ret)
-               return ret;
-
        /* Headset jack detection */
        snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
                        | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
index 9a23513..620fc69 100644 (file)
@@ -211,7 +211,6 @@ static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd)
        /* set up tosa specific audio path audio_map */
        snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-       snd_soc_dapm_sync(dapm);
        return 0;
 }
 
index 4b81ffd..b311ffe 100644 (file)
@@ -161,10 +161,6 @@ static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd)
        /* Set up z2 specific audio paths */
        snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-       ret = snd_soc_dapm_sync(dapm);
-       if (ret)
-               goto err;
-
        /* Jack detection API stuff */
        ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
                                &hs_jack);
index b644575..580aae3 100644 (file)
@@ -87,7 +87,6 @@ static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_enable_pin(dapm, "Headphone");
        snd_soc_dapm_enable_pin(dapm, "Headset Earpiece");
 
-       snd_soc_dapm_sync(dapm);
        return 0;
 }
 
@@ -196,20 +195,20 @@ static int zylonite_probe(struct snd_soc_card *card)
        if (clk_pout) {
                pout = clk_get(NULL, "CLK_POUT");
                if (IS_ERR(pout)) {
-                       dev_err(&pdev->dev, "Unable to obtain CLK_POUT: %ld\n",
+                       dev_err(card->dev, "Unable to obtain CLK_POUT: %ld\n",
                                PTR_ERR(pout));
                        return PTR_ERR(pout);
                }
 
                ret = clk_enable(pout);
                if (ret != 0) {
-                       dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n",
+                       dev_err(card->dev, "Unable to enable CLK_POUT: %d\n",
                                ret);
                        clk_put(pout);
                        return ret;
                }
 
-               dev_dbg(&pdev->dev, "MCLK enabled at %luHz\n",
+               dev_dbg(card->dev, "MCLK enabled at %luHz\n",
                        clk_get_rate(pout));
        }
 
@@ -241,7 +240,7 @@ static int zylonite_resume_pre(struct snd_soc_card *card)
        if (clk_pout) {
                ret = clk_enable(pout);
                if (ret != 0)
-                       dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n",
+                       dev_err(card->dev, "Unable to enable CLK_POUT: %d\n",
                                ret);
        }
 
index dd3b3ea..53aaa69 100644 (file)
@@ -64,6 +64,8 @@ config SND_SOC_SAMSUNG_SMDK_WM8580
 config SND_SOC_SAMSUNG_SMDK_WM8994
        tristate "SoC I2S Audio support for WM8994 on SMDK"
        depends on SND_SOC_SAMSUNG && (MACH_SMDKV310 || MACH_SMDKC210 || MACH_SMDK4212)
+       depends on I2C=y && GENERIC_HARDIRQS
+       select MFD_WM8994
        select SND_SOC_WM8994
        select SND_SAMSUNG_I2S
        help
@@ -150,7 +152,9 @@ config SND_SOC_SMARTQ
 config SND_SOC_GONI_AQUILA_WM8994
        tristate "SoC I2S Audio support for AQUILA/GONI - WM8994"
        depends on SND_SOC_SAMSUNG && (MACH_GONI || MACH_AQUILA)
+       depends on I2C=y && GENERIC_HARDIRQS
        select SND_SAMSUNG_I2S
+       select MFD_WM8994
        select SND_SOC_WM8994
        help
          Say Y if you want to add support for SoC audio on goni or aquila
@@ -174,6 +178,8 @@ config SND_SOC_SMDK_WM8580_PCM
 config SND_SOC_SMDK_WM8994_PCM
        tristate "SoC PCM Audio support for WM8994 on SMDK"
        depends on SND_SOC_SAMSUNG && (MACH_SMDKC210 || MACH_SMDKV310 || MACH_SMDK4212)
+       depends on I2C=y && GENERIC_HARDIRQS
+       select MFD_WM8994
        select SND_SOC_WM8994
        select SND_SAMSUNG_PCM
        help
index 884c8a1..b5e922f 100644 (file)
@@ -495,7 +495,7 @@ static __devexit int s3c_ac97_remove(struct platform_device *pdev)
 
 static struct platform_driver s3c_ac97_driver = {
        .probe  = s3c_ac97_probe,
-       .remove = s3c_ac97_remove,
+       .remove = __devexit_p(s3c_ac97_remove),
        .driver = {
                .name = "samsung-ac97",
                .owner = THIS_MODULE,
index eb6d72e..4a34f60 100644 (file)
@@ -99,14 +99,6 @@ static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd)
        struct snd_soc_dapm_context *dapm = &codec->dapm;
        int ret;
 
-       /* add goni specific widgets */
-       snd_soc_dapm_new_controls(dapm, goni_dapm_widgets,
-                       ARRAY_SIZE(goni_dapm_widgets));
-
-       /* set up goni specific audio routes */
-       snd_soc_dapm_add_routes(dapm, goni_dapm_routes,
-                       ARRAY_SIZE(goni_dapm_routes));
-
        /* set endpoints to not connected */
        snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN");
        snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP");
@@ -120,8 +112,6 @@ static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd)
                snd_soc_dapm_nc_pin(dapm, "SPKOUTRP");
        }
 
-       snd_soc_dapm_sync(dapm);
-
        /* Headset jack detection */
        ret = snd_soc_jack_new(codec, "Headset Jack",
                        SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT,
@@ -255,6 +245,11 @@ static struct snd_soc_card goni = {
        .name = "goni",
        .dai_link = goni_dai,
        .num_links = ARRAY_SIZE(goni_dai),
+
+       .dapm_widgets = goni_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(goni_dapm_widgets),
+       .dapm_routes = goni_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(goni_dapm_routes),
 };
 
 static int __init goni_init(void)
index c6c6589..f75a4b6 100644 (file)
@@ -182,24 +182,10 @@ static int h1940_uda1380_init(struct snd_soc_pcm_runtime *rtd)
        struct snd_soc_dapm_context *dapm = &codec->dapm;
        int err;
 
-       /* Add h1940 specific widgets */
-       err = snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets,
-                                 ARRAY_SIZE(uda1380_dapm_widgets));
-       if (err)
-               return err;
-
-       /* Set up h1940 specific audio path audio_mapnects */
-       err = snd_soc_dapm_add_routes(dapm, audio_map,
-                                     ARRAY_SIZE(audio_map));
-       if (err)
-               return err;
-
        snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
        snd_soc_dapm_enable_pin(dapm, "Speaker");
        snd_soc_dapm_enable_pin(dapm, "Mic Jack");
 
-       snd_soc_dapm_sync(dapm);
-
        snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
                &hp_jack);
 
@@ -230,6 +216,11 @@ static struct snd_soc_card h1940_asoc = {
        .name = "h1940",
        .dai_link = h1940_uda1380_dai,
        .num_links = ARRAY_SIZE(h1940_uda1380_dai),
+
+       .dapm_widgets = uda1380_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets),
+       .dapm_routes = audio_map,
+       .num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static int __init h1940_init(void)
index c086b78..0c9ac20 100644 (file)
@@ -1136,7 +1136,7 @@ static __devexit int samsung_i2s_remove(struct platform_device *pdev)
 
 static struct platform_driver samsung_i2s_driver = {
        .probe  = samsung_i2s_probe,
-       .remove = samsung_i2s_remove,
+       .remove = __devexit_p(samsung_i2s_remove),
        .driver = {
                .name = "samsung-i2s",
                .owner = THIS_MODULE,
index ed8f13a..f5f7c6f 100644 (file)
@@ -110,18 +110,6 @@ static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_nc_pin(dapm, "OUT3");
        snd_soc_dapm_nc_pin(dapm, "MONO");
 
-       /* Add jive specific widgets */
-       err = snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets,
-                                       ARRAY_SIZE(wm8750_dapm_widgets));
-       if (err) {
-               printk(KERN_ERR "%s: failed to add widgets (%d)\n",
-                      __func__, err);
-               return err;
-       }
-
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-       snd_soc_dapm_sync(dapm);
-
        return 0;
 }
 
@@ -141,6 +129,11 @@ static struct snd_soc_card snd_soc_machine_jive = {
        .name           = "Jive",
        .dai_link       = &jive_dai,
        .num_links      = 1,
+
+       .dapm_widgtets  = wm8750_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets),
+       .dapm_routes    = audio_map,
+       .num_dapm_routes = ARRAY_SIZE(audio_map),
 };
 
 static struct platform_device *jive_snd_device;
index 16152ed..7207189 100644 (file)
@@ -367,8 +367,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
                        return ret;
        }
 
-       snd_soc_dapm_sync(dapm);
-
        return 0;
 }
 
@@ -409,8 +407,6 @@ static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm)
        snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
        snd_soc_dapm_ignore_suspend(dapm, "Headphone");
 
-       snd_soc_dapm_sync(dapm);
-
        return 0;
 }
 
index 9c7e8b4..e55d7a5 100644 (file)
@@ -624,7 +624,7 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
 
 static struct platform_driver s3c_pcm_driver = {
        .probe  = s3c_pcm_dev_probe,
-       .remove = s3c_pcm_dev_remove,
+       .remove = __devexit_p(s3c_pcm_dev_remove),
        .driver = {
                .name = "samsung-pcm",
                .owner = THIS_MODULE,
index bc8c167..aea7f1b 100644 (file)
@@ -90,12 +90,6 @@ static struct snd_soc_dai_link rx1950_uda1380_dai[] = {
        },
 };
 
-static struct snd_soc_card rx1950_asoc = {
-       .name = "rx1950",
-       .dai_link = rx1950_uda1380_dai,
-       .num_links = ARRAY_SIZE(rx1950_uda1380_dai),
-};
-
 /* rx1950 machine dapm widgets */
 static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
        SND_SOC_DAPM_HP("Headphone Jack", NULL),
@@ -117,6 +111,17 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"VINM", NULL, "Mic Jack"},
 };
 
+static struct snd_soc_card rx1950_asoc = {
+       .name = "rx1950",
+       .dai_link = rx1950_uda1380_dai,
+       .num_links = ARRAY_SIZE(rx1950_uda1380_dai),
+
+       .dapm_widgets = uda1380_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets),
+       .dapm_routes = audio_map,
+       .num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
 static struct platform_device *s3c24xx_snd_device;
 
 static int rx1950_startup(struct snd_pcm_substream *substream)
@@ -220,26 +225,10 @@ static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd)
        struct snd_soc_dapm_context *dapm = &codec->dapm;
        int err;
 
-       /* Add rx1950 specific widgets */
-       err = snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets,
-                                 ARRAY_SIZE(uda1380_dapm_widgets));
-
-       if (err)
-               return err;
-
-       /* Set up rx1950 specific audio path audio_mapnects */
-       err = snd_soc_dapm_add_routes(dapm, audio_map,
-                                     ARRAY_SIZE(audio_map));
-
-       if (err)
-               return err;
-
        snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
        snd_soc_dapm_enable_pin(dapm, "Speaker");
        snd_soc_dapm_enable_pin(dapm, "Mic Jack");
 
-       snd_soc_dapm_sync(dapm);
-
        snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
                &hp_jack);
 
index 52074a2..7a73380 100644 (file)
@@ -16,6 +16,7 @@
  * option) any later version.
  */
 
+#include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/io.h>
index 7ab8e2c..f26a8bf 100644 (file)
@@ -176,7 +176,7 @@ static __devexit int s3c2412_iis_dev_remove(struct platform_device *pdev)
 
 static struct platform_driver s3c2412_iis_driver = {
        .probe  = s3c2412_iis_dev_probe,
-       .remove = s3c2412_iis_dev_remove,
+       .remove = __devexit_p(s3c2412_iis_dev_remove),
        .driver = {
                .name = "s3c2412-iis",
                .owner = THIS_MODULE,
index 21c92e2..c08117e 100644 (file)
@@ -481,7 +481,7 @@ static __devexit int s3c24xx_iis_dev_remove(struct platform_device *pdev)
 
 static struct platform_driver s3c24xx_iis_driver = {
        .probe  = s3c24xx_iis_dev_probe,
-       .remove = s3c24xx_iis_dev_remove,
+       .remove = __devexit_p(s3c24xx_iis_dev_remove),
        .driver = {
                .name = "s3c24xx-iis",
                .owner = THIS_MODULE,
index 349566f..c8d525b 100644 (file)
@@ -300,7 +300,7 @@ static void detach_gpio_amp(struct s3c24xx_audio_simtec_pdata *pd)
 }
 
 #ifdef CONFIG_PM
-int simtec_audio_resume(struct device *dev)
+static int simtec_audio_resume(struct device *dev)
 {
        simtec_call_startup(pdata);
        return 0;
index ce6aef6..6bc5a36 100644 (file)
@@ -65,18 +65,12 @@ static int simtec_hermes_init(struct snd_soc_pcm_runtime *rtd)
        struct snd_soc_codec *codec = rtd->codec;
        struct snd_soc_dapm_context *dapm = &codec->dapm;
 
-       snd_soc_dapm_new_controls(dapm, dapm_widgets,
-                                 ARRAY_SIZE(dapm_widgets));
-
-       snd_soc_dapm_add_routes(dapm, base_map, ARRAY_SIZE(base_map));
-
        snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
        snd_soc_dapm_enable_pin(dapm, "Line In");
        snd_soc_dapm_enable_pin(dapm, "Line Out");
        snd_soc_dapm_enable_pin(dapm, "Mic Jack");
 
        simtec_audio_init(rtd);
-       snd_soc_dapm_sync(dapm);
 
        return 0;
 }
@@ -96,6 +90,11 @@ static struct snd_soc_card snd_soc_machine_simtec_aic33 = {
        .name           = "Simtec-Hermes",
        .dai_link       = &simtec_dai_aic33,
        .num_links      = 1,
+
+       .dapm_widgets   = dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(dapm_widgets),
+       .dapm_routes    = base_map,
+       .num_dapm_routes = ARRAY_SIZE(base_map),
 };
 
 static int __devinit simtec_audio_hermes_probe(struct platform_device *pd)
index a7ef7db..7bdda76 100644 (file)
@@ -54,18 +54,12 @@ static int simtec_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
        struct snd_soc_codec *codec = rtd->codec;
        struct snd_soc_dapm_context *dapm = &codec->dapm;
 
-       snd_soc_dapm_new_controls(dapm, dapm_widgets,
-                                 ARRAY_SIZE(dapm_widgets));
-
-       snd_soc_dapm_add_routes(dapm, base_map, ARRAY_SIZE(base_map));
-
        snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
        snd_soc_dapm_enable_pin(dapm, "Line In");
        snd_soc_dapm_enable_pin(dapm, "Line Out");
        snd_soc_dapm_enable_pin(dapm, "Mic Jack");
 
        simtec_audio_init(rtd);
-       snd_soc_dapm_sync(dapm);
 
        return 0;
 }
@@ -85,6 +79,11 @@ static struct snd_soc_card snd_soc_machine_simtec_aic23 = {
        .name           = "Simtec",
        .dai_link       = &simtec_dai_aic23,
        .num_links      = 1,
+
+       .dapm_widgets   = dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(dapm_widgets),
+       .dapm_routes    = base_map,
+       .num_dapm_routes = ARRAY_SIZE(base_map),
 };
 
 static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd)
index bbd1476..6ac6bc2 100644 (file)
@@ -153,20 +153,6 @@ static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd)
        struct snd_soc_dapm_context *dapm = &codec->dapm;
        int err = 0;
 
-       /* Add SmartQ specific widgets */
-       snd_soc_dapm_new_controls(dapm, wm8987_dapm_widgets,
-                                 ARRAY_SIZE(wm8987_dapm_widgets));
-
-       /* add SmartQ specific controls */
-       err = snd_soc_add_controls(codec, wm8987_smartq_controls,
-                                  ARRAY_SIZE(wm8987_smartq_controls));
-
-       if (err < 0)
-               return err;
-
-       /* setup SmartQ specific audio path */
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
        /* set endpoints to not connected */
        snd_soc_dapm_nc_pin(dapm, "LINPUT1");
        snd_soc_dapm_nc_pin(dapm, "RINPUT1");
@@ -178,10 +164,6 @@ static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_enable_pin(dapm, "Internal Mic");
        snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
 
-       err = snd_soc_dapm_sync(dapm);
-       if (err)
-               return err;
-
        /* Headphone jack detection */
        err = snd_soc_jack_new(codec, "Headphone Jack",
                               SND_JACK_HEADPHONE, &smartq_jack);
@@ -217,6 +199,13 @@ static struct snd_soc_card snd_soc_smartq = {
        .name = "SmartQ",
        .dai_link = smartq_dai,
        .num_links = ARRAY_SIZE(smartq_dai),
+
+       .dapm_widgets = wm8987_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8987_dapm_widgets),
+       .dapm_routes = audio_map,
+       .num_dapm_routes = ARRAY_SIZE(audio_map),
+       .controls = wm8987_smartq_controls,
+       .num_controls = ARRAY_SIZE(wm8987_smartq_controls),
 };
 
 static struct platform_device *smartq_snd_device;
index 20deecf..8f92ffc 100644 (file)
@@ -119,30 +119,24 @@ static struct snd_soc_ops smdk_ops = {
 };
 
 /* SMDK Playback widgets */
-static const struct snd_soc_dapm_widget wm8580_dapm_widgets_pbk[] = {
+static const struct snd_soc_dapm_widget smdk_wm8580_dapm_widgets[] = {
        SND_SOC_DAPM_HP("Front", NULL),
        SND_SOC_DAPM_HP("Center+Sub", NULL),
        SND_SOC_DAPM_HP("Rear", NULL),
-};
 
-/* SMDK Capture widgets */
-static const struct snd_soc_dapm_widget wm8580_dapm_widgets_cpt[] = {
        SND_SOC_DAPM_MIC("MicIn", NULL),
        SND_SOC_DAPM_LINE("LineIn", NULL),
 };
 
 /* SMDK-PAIFTX connections */
-static const struct snd_soc_dapm_route audio_map_tx[] = {
+static const struct snd_soc_dapm_route smdk_wm8580_audio_map[] = {
        /* MicIn feeds AINL */
        {"AINL", NULL, "MicIn"},
 
        /* LineIn feeds AINL/R */
        {"AINL", NULL, "LineIn"},
        {"AINR", NULL, "LineIn"},
-};
 
-/* SMDK-PAIFRX connections */
-static const struct snd_soc_dapm_route audio_map_rx[] = {
        /* Front Left/Right are fed VOUT1L/R */
        {"Front", NULL, "VOUT1L"},
        {"Front", NULL, "VOUT1R"},
@@ -161,39 +155,11 @@ static int smdk_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd)
        struct snd_soc_codec *codec = rtd->codec;
        struct snd_soc_dapm_context *dapm = &codec->dapm;
 
-       /* Add smdk specific Capture widgets */
-       snd_soc_dapm_new_controls(dapm, wm8580_dapm_widgets_cpt,
-                                 ARRAY_SIZE(wm8580_dapm_widgets_cpt));
-
-       /* Set up PAIFTX audio path */
-       snd_soc_dapm_add_routes(dapm, audio_map_tx, ARRAY_SIZE(audio_map_tx));
-
        /* Enabling the microphone requires the fitting of a 0R
         * resistor to connect the line from the microphone jack.
         */
        snd_soc_dapm_disable_pin(dapm, "MicIn");
 
-       /* signal a DAPM event */
-       snd_soc_dapm_sync(dapm);
-
-       return 0;
-}
-
-static int smdk_wm8580_init_paifrx(struct snd_soc_pcm_runtime *rtd)
-{
-       struct snd_soc_codec *codec = rtd->codec;
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       /* Add smdk specific Playback widgets */
-       snd_soc_dapm_new_controls(dapm, wm8580_dapm_widgets_pbk,
-                                 ARRAY_SIZE(wm8580_dapm_widgets_pbk));
-
-       /* Set up PAIFRX audio path */
-       snd_soc_dapm_add_routes(dapm, audio_map_rx, ARRAY_SIZE(audio_map_rx));
-
-       /* signal a DAPM event */
-       snd_soc_dapm_sync(dapm);
-
        return 0;
 }
 
@@ -211,7 +177,6 @@ static struct snd_soc_dai_link smdk_dai[] = {
                .codec_dai_name = "wm8580-hifi-playback",
                .platform_name = "samsung-audio",
                .codec_name = "wm8580.0-001b",
-               .init = smdk_wm8580_init_paifrx,
                .ops = &smdk_ops,
        },
        [PRI_CAPTURE] = { /* Primary Capture i/f */
@@ -231,7 +196,6 @@ static struct snd_soc_dai_link smdk_dai[] = {
                .codec_dai_name = "wm8580-hifi-playback",
                .platform_name = "samsung-audio",
                .codec_name = "wm8580.0-001b",
-               .init = smdk_wm8580_init_paifrx,
                .ops = &smdk_ops,
        },
 };
@@ -240,6 +204,11 @@ static struct snd_soc_card smdk = {
        .name = "SMDK-I2S",
        .dai_link = smdk_dai,
        .num_links = 2,
+
+       .dapm_widgets = smdk_wm8580_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(smdk_wm8580_dapm_widgets),
+       .dapm_routes = smdk_wm8580_audio_map,
+       .num_dapm_routes = ARRAY_SIZE(smdk_wm8580_audio_map),
 };
 
 static struct platform_device *smdk_snd_device;
index 45fbe2b..f75e439 100644 (file)
@@ -117,8 +117,6 @@ static int smdk_wm8994_init_paiftx(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_nc_pin(dapm, "IN1RP");
        snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP");
 
-       snd_soc_dapm_sync(dapm);
-
        return 0;
 }
 
index 28c491d..3122f31 100644 (file)
@@ -340,7 +340,7 @@ static struct snd_soc_dai_ops spdif_dai_ops = {
        .shutdown       = spdif_shutdown,
 };
 
-struct snd_soc_dai_driver samsung_spdif_dai = {
+static struct snd_soc_dai_driver samsung_spdif_dai = {
        .name = "samsung-spdif",
        .playback = {
                .stream_name = "S/PDIF Playback",
@@ -475,7 +475,7 @@ static __devexit int spdif_remove(struct platform_device *pdev)
 
 static struct platform_driver samsung_spdif_driver = {
        .probe  = spdif_probe,
-       .remove = spdif_remove,
+       .remove = __devexit_p(spdif_remove),
        .driver = {
                .name   = "samsung-spdif",
                .owner  = THIS_MODULE,
index 3820a6b..8a08204 100644 (file)
@@ -16,6 +16,8 @@
 
 #include "../codecs/wm8962.h"
 
+static int sample_rate = 44100;
+
 static int speyside_wm8962_set_bias_level(struct snd_soc_card *card,
                                          struct snd_soc_dapm_context *dapm,
                                          enum snd_soc_bias_level level)
@@ -31,13 +33,13 @@ static int speyside_wm8962_set_bias_level(struct snd_soc_card *card,
                if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
                        ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL,
                                                  WM8962_FLL_MCLK, 32768,
-                                                 44100 * 512);
+                                                 sample_rate * 512);
                        if (ret < 0)
                                pr_err("Failed to start FLL: %d\n", ret);
 
                        ret = snd_soc_dai_set_sysclk(codec_dai,
                                                     WM8962_SYSCLK_FLL,
-                                                    44100 * 512,
+                                                    sample_rate * 512,
                                                     SND_SOC_CLOCK_IN);
                        if (ret < 0) {
                                pr_err("Failed to set SYSCLK: %d\n", ret);
@@ -92,22 +94,7 @@ static int speyside_wm8962_set_bias_level_post(struct snd_soc_card *card,
 static int speyside_wm8962_hw_params(struct snd_pcm_substream *substream,
                              struct snd_pcm_hw_params *params)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       int ret;
-
-       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
-                                        | SND_SOC_DAIFMT_NB_NF
-                                        | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0)
-               return ret;
-
-       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
-                                        | SND_SOC_DAIFMT_NB_NF
-                                        | SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0)
-               return ret;
+       sample_rate = params_rate(params);
 
        return 0;
 }
@@ -124,12 +111,15 @@ static struct snd_soc_dai_link speyside_wm8962_dai[] = {
                .codec_dai_name = "wm8962",
                .platform_name = "samsung-audio",
                .codec_name = "wm8962.1-001a",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+                               | SND_SOC_DAIFMT_CBM_CFM,
                .ops = &speyside_wm8962_ops,
        },
 };
 
 static const struct snd_kcontrol_new controls[] = {
        SOC_DAPM_PIN_SWITCH("Main Speaker"),
+       SOC_DAPM_PIN_SWITCH("DMIC"),
 };
 
 static struct snd_soc_dapm_widget widgets[] = {
@@ -137,6 +127,7 @@ static struct snd_soc_dapm_widget widgets[] = {
        SND_SOC_DAPM_MIC("Headset Mic", NULL),
 
        SND_SOC_DAPM_MIC("DMIC", NULL),
+       SND_SOC_DAPM_MIC("AMIC", NULL),
 
        SND_SOC_DAPM_SPK("Main Speaker", NULL),
 };
@@ -148,12 +139,16 @@ static struct snd_soc_dapm_route audio_paths[] = {
        { "Main Speaker", NULL, "SPKOUTL" },
        { "Main Speaker", NULL, "SPKOUTR" },
 
-       { "MICBIAS", NULL, "Headset Mic" },
-       { "IN4L", NULL, "MICBIAS" },
-       { "IN4R", NULL, "MICBIAS" },
+       { "Headset Mic", NULL, "MICBIAS" },
+       { "IN4L", NULL, "Headset Mic" },
+       { "IN4R", NULL, "Headset Mic" },
+
+       { "AMIC", NULL, "MICBIAS" },
+       { "IN1L", NULL, "AMIC" },
+       { "IN1R", NULL, "AMIC" },
 
-       { "MICBIAS", NULL, "DMIC" },
-       { "DMICDAT", NULL, "MICBIAS" },
+       { "DMIC", NULL, "MICBIAS" },
+       { "DMICDAT", NULL, "DMIC" },
 };
 
 static struct snd_soc_jack speyside_wm8962_headset;
index 1493ebf..a32fd16 100644 (file)
@@ -210,7 +210,7 @@ struct fsi_master {
  *             basic read write function
  */
 
-static void __fsi_reg_write(u32 reg, u32 data)
+static void __fsi_reg_write(u32 __iomem *reg, u32 data)
 {
        /* valid data area is 24bit */
        data &= 0x00ffffff;
@@ -218,12 +218,12 @@ static void __fsi_reg_write(u32 reg, u32 data)
        __raw_writel(data, reg);
 }
 
-static u32 __fsi_reg_read(u32 reg)
+static u32 __fsi_reg_read(u32 __iomem *reg)
 {
        return __raw_readl(reg);
 }
 
-static void __fsi_reg_mask_set(u32 reg, u32 mask, u32 data)
+static void __fsi_reg_mask_set(u32 __iomem *reg, u32 mask, u32 data)
 {
        u32 val = __fsi_reg_read(reg);
 
@@ -250,7 +250,7 @@ static u32 _fsi_master_read(struct fsi_master *master, u32 reg)
        unsigned long flags;
 
        spin_lock_irqsave(&master->lock, flags);
-       ret = __fsi_reg_read((u32)(master->base + reg));
+       ret = __fsi_reg_read(master->base + reg);
        spin_unlock_irqrestore(&master->lock, flags);
 
        return ret;
@@ -264,7 +264,7 @@ static void _fsi_master_mask_set(struct fsi_master *master,
        unsigned long flags;
 
        spin_lock_irqsave(&master->lock, flags);
-       __fsi_reg_mask_set((u32)(master->base + reg), mask, data);
+       __fsi_reg_mask_set(master->base + reg, mask, data);
        spin_unlock_irqrestore(&master->lock, flags);
 }
 
index 917d3ce..c62ae68 100644 (file)
 extern struct snd_soc_dai_driver sh4_hac_dai[2];
 extern struct snd_soc_platform_driver sh7760_soc_platform;
 
-static int machine_init(struct snd_soc_pcm_runtime *rtd)
-{
-       snd_soc_dapm_sync(&rtd->codec->dapm);
-       return 0;
-}
-
 static struct snd_soc_dai_link sh7760_ac97_dai = {
        .name = "AC97",
        .stream_name = "AC97 HiFi",
@@ -33,7 +27,6 @@ static struct snd_soc_dai_link sh7760_ac97_dai = {
        .codec_dai_name = "ac97-hifi",
        .platform_name = "sh7760-pcm-audio",
        .codec_name = "ac97-codec",
-       .init = machine_init,
        .ops = NULL,
 };
 
index 05192d9..e0c621c 100644 (file)
@@ -342,7 +342,7 @@ static struct snd_soc_dai_ops ssi_dai_ops = {
        .set_fmt        = ssi_set_fmt,
 };
 
-struct snd_soc_dai_driver sh4_ssi_dai[] = {
+static struct snd_soc_dai_driver sh4_ssi_dai[] = {
 {
        .name                   = "ssi-dai.0",
        .playback = {
index bd20154..a5d3685 100644 (file)
@@ -1055,6 +1055,9 @@ static int soc_post_component_init(struct snd_soc_card *card,
        }
        rtd->card = card;
 
+       /* Make sure all DAPM widgets are instantiated */
+       snd_soc_dapm_new_widgets(&codec->dapm);
+
        /* machine controls, routes and widgets are not prefixed */
        temp = codec->name_prefix;
        codec->name_prefix = NULL;
@@ -1070,9 +1073,6 @@ static int soc_post_component_init(struct snd_soc_card *card,
        }
        codec->name_prefix = temp;
 
-       /* Make sure all DAPM widgets are instantiated */
-       snd_soc_dapm_new_widgets(&codec->dapm);
-
        /* register the rtd device */
        rtd->codec = codec;
        rtd->dev.parent = card->dev;
@@ -1317,6 +1317,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
        struct snd_soc_codec *codec;
        struct snd_soc_codec_conf *codec_conf;
        enum snd_soc_compress_type compress_type;
+       struct snd_soc_dai_link *dai_link;
        int ret, i, order;
 
        mutex_lock(&card->mutex);
@@ -1429,6 +1430,28 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
                snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes,
                                        card->num_dapm_routes);
 
+       snd_soc_dapm_new_widgets(&card->dapm);
+
+       for (i = 0; i < card->num_links; i++) {
+               dai_link = &card->dai_link[i];
+
+               if (dai_link->dai_fmt) {
+                       ret = snd_soc_dai_set_fmt(card->rtd[i].codec_dai,
+                                                 dai_link->dai_fmt);
+                       if (ret != 0)
+                               dev_warn(card->rtd[i].codec_dai->dev,
+                                        "Failed to set DAI format: %d\n",
+                                        ret);
+
+                       ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai,
+                                                 dai_link->dai_fmt);
+                       if (ret != 0)
+                               dev_warn(card->rtd[i].cpu_dai->dev,
+                                        "Failed to set DAI format: %d\n",
+                                        ret);
+               }
+       }
+
        snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname),
                 "%s", card->name);
        snprintf(card->snd_card->longname, sizeof(card->snd_card->longname),
@@ -1457,6 +1480,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
                }
        }
 
+       snd_soc_dapm_new_widgets(&card->dapm);
+
        ret = snd_card_register(card->snd_card);
        if (ret < 0) {
                printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name);
@@ -1477,6 +1502,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 #endif
 
        card->instantiated = 1;
+       snd_soc_dapm_sync(&card->dapm);
        mutex_unlock(&card->mutex);
        return;
 
@@ -2227,7 +2253,8 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);
  * @kcontrol: mixer control
  * @uinfo: control element information
  *
- * Callback to provide information about a single mixer control.
+ * Callback to provide information about a single mixer control, or a double
+ * mixer control that spans 2 registers.
  *
  * Returns 0 for success.
  */
@@ -2237,8 +2264,6 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
        int platform_max;
-       unsigned int shift = mc->shift;
-       unsigned int rshift = mc->rshift;
 
        if (!mc->platform_max)
                mc->platform_max = mc->max;
@@ -2249,7 +2274,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
        else
                uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 
-       uinfo->count = shift == rshift ? 1 : 2;
+       uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
        uinfo->value.integer.min = 0;
        uinfo->value.integer.max = platform_max;
        return 0;
@@ -2261,7 +2286,8 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
  * @kcontrol: mixer control
  * @ucontrol: control element information
  *
- * Callback to get the value of a single mixer control.
+ * Callback to get the value of a single mixer control, or a double mixer
+ * control that spans 2 registers.
  *
  * Returns 0 for success.
  */
@@ -2272,6 +2298,7 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
                (struct soc_mixer_control *)kcontrol->private_value;
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        unsigned int reg = mc->reg;
+       unsigned int reg2 = mc->rreg;
        unsigned int shift = mc->shift;
        unsigned int rshift = mc->rshift;
        int max = mc->max;
@@ -2280,13 +2307,18 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
 
        ucontrol->value.integer.value[0] =
                (snd_soc_read(codec, reg) >> shift) & mask;
-       if (shift != rshift)
-               ucontrol->value.integer.value[1] =
-                       (snd_soc_read(codec, reg) >> rshift) & mask;
-       if (invert) {
+       if (invert)
                ucontrol->value.integer.value[0] =
                        max - ucontrol->value.integer.value[0];
-               if (shift != rshift)
+
+       if (snd_soc_volsw_is_stereo(mc)) {
+               if (reg == reg2)
+                       ucontrol->value.integer.value[1] =
+                               (snd_soc_read(codec, reg) >> rshift) & mask;
+               else
+                       ucontrol->value.integer.value[1] =
+                               (snd_soc_read(codec, reg2) >> shift) & mask;
+               if (invert)
                        ucontrol->value.integer.value[1] =
                                max - ucontrol->value.integer.value[1];
        }
@@ -2300,7 +2332,8 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
  * @kcontrol: mixer control
  * @ucontrol: control element information
  *
- * Callback to set the value of a single mixer control.
+ * Callback to set the value of a single mixer control, or a double mixer
+ * control that spans 2 registers.
  *
  * Returns 0 for success.
  */
@@ -2311,143 +2344,44 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
                (struct soc_mixer_control *)kcontrol->private_value;
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        unsigned int reg = mc->reg;
+       unsigned int reg2 = mc->rreg;
        unsigned int shift = mc->shift;
        unsigned int rshift = mc->rshift;
        int max = mc->max;
        unsigned int mask = (1 << fls(max)) - 1;
        unsigned int invert = mc->invert;
-       unsigned int val, val2, val_mask;
+       int err;
+       bool type_2r = 0;
+       unsigned int val2 = 0;
+       unsigned int val, val_mask;
 
        val = (ucontrol->value.integer.value[0] & mask);
        if (invert)
                val = max - val;
        val_mask = mask << shift;
        val = val << shift;
-       if (shift != rshift) {
+       if (snd_soc_volsw_is_stereo(mc)) {
                val2 = (ucontrol->value.integer.value[1] & mask);
                if (invert)
                        val2 = max - val2;
-               val_mask |= mask << rshift;
-               val |= val2 << rshift;
-       }
-       return snd_soc_update_bits_locked(codec, reg, val_mask, val);
-}
-EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
-
-/**
- * snd_soc_info_volsw_2r - double mixer info callback
- * @kcontrol: mixer control
- * @uinfo: control element information
- *
- * Callback to provide information about a double mixer control that
- * spans 2 codec registers.
- *
- * Returns 0 for success.
- */
-int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_info *uinfo)
-{
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       int platform_max;
-
-       if (!mc->platform_max)
-               mc->platform_max = mc->max;
-       platform_max = mc->platform_max;
-
-       if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
-               uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-       else
-               uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-
-       uinfo->count = 2;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = platform_max;
-       return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r);
-
-/**
- * snd_soc_get_volsw_2r - double mixer get callback
- * @kcontrol: mixer control
- * @ucontrol: control element information
- *
- * Callback to get the value of a double mixer control that spans 2 registers.
- *
- * Returns 0 for success.
- */
-int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       unsigned int reg = mc->reg;
-       unsigned int reg2 = mc->rreg;
-       unsigned int shift = mc->shift;
-       int max = mc->max;
-       unsigned int mask = (1 << fls(max)) - 1;
-       unsigned int invert = mc->invert;
-
-       ucontrol->value.integer.value[0] =
-               (snd_soc_read(codec, reg) >> shift) & mask;
-       ucontrol->value.integer.value[1] =
-               (snd_soc_read(codec, reg2) >> shift) & mask;
-       if (invert) {
-               ucontrol->value.integer.value[0] =
-                       max - ucontrol->value.integer.value[0];
-               ucontrol->value.integer.value[1] =
-                       max - ucontrol->value.integer.value[1];
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r);
-
-/**
- * snd_soc_put_volsw_2r - double mixer set callback
- * @kcontrol: mixer control
- * @ucontrol: control element information
- *
- * Callback to set the value of a double mixer control that spans 2 registers.
- *
- * Returns 0 for success.
- */
-int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct soc_mixer_control *mc =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       unsigned int reg = mc->reg;
-       unsigned int reg2 = mc->rreg;
-       unsigned int shift = mc->shift;
-       int max = mc->max;
-       unsigned int mask = (1 << fls(max)) - 1;
-       unsigned int invert = mc->invert;
-       int err;
-       unsigned int val, val2, val_mask;
-
-       val_mask = mask << shift;
-       val = (ucontrol->value.integer.value[0] & mask);
-       val2 = (ucontrol->value.integer.value[1] & mask);
-
-       if (invert) {
-               val = max - val;
-               val2 = max - val2;
+               if (reg == reg2) {
+                       val_mask |= mask << rshift;
+                       val |= val2 << rshift;
+               } else {
+                       val2 = val2 << shift;
+                       type_2r = 1;
+               }
        }
-
-       val = val << shift;
-       val2 = val2 << shift;
-
        err = snd_soc_update_bits_locked(codec, reg, val_mask, val);
        if (err < 0)
                return err;
 
-       err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2);
+       if (type_2r)
+               err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2);
+
        return err;
 }
-EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r);
+EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
 
 /**
  * snd_soc_info_volsw_s8 - signed mixer info callback
@@ -2895,6 +2829,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
                card->rtd[i].dai_link = &card->dai_link[i];
 
        INIT_LIST_HEAD(&card->list);
+       INIT_LIST_HEAD(&card->dapm_dirty);
        card->instantiated = 0;
        mutex_init(&card->mutex);
 
index 4a440b5..f42e8b9 100644 (file)
@@ -48,6 +48,8 @@
 
 #include <trace/events/asoc.h>
 
+#define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++;
+
 /* dapm power sequences - make this per codec in the future */
 static int dapm_up_seq[] = {
        [snd_soc_dapm_pre] = 0,
@@ -117,6 +119,21 @@ static void pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...)
        kfree(buf);
 }
 
+static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w)
+{
+       return !list_empty(&w->dirty);
+}
+
+void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason)
+{
+       if (!dapm_dirty_widget(w)) {
+               dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n",
+                        w->name, reason);
+               list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty);
+       }
+}
+EXPORT_SYMBOL_GPL(dapm_mark_dirty);
+
 /* create a new dapm widget */
 static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
        const struct snd_soc_dapm_widget *_widget)
@@ -316,7 +333,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
                }
        }
        break;
-       /* does not effect routing - always connected */
+       /* does not affect routing - always connected */
        case snd_soc_dapm_pga:
        case snd_soc_dapm_out_drv:
        case snd_soc_dapm_output:
@@ -328,13 +345,13 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
        case snd_soc_dapm_supply:
        case snd_soc_dapm_aif_in:
        case snd_soc_dapm_aif_out:
-               p->connect = 1;
-       break;
-       /* does effect routing - dynamically connected */
        case snd_soc_dapm_hp:
        case snd_soc_dapm_mic:
        case snd_soc_dapm_spk:
        case snd_soc_dapm_line:
+               p->connect = 1;
+       break;
+       /* does affect routing - dynamically connected */
        case snd_soc_dapm_pre:
        case snd_soc_dapm_post:
                p->connect = 0;
@@ -649,30 +666,45 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
        struct snd_soc_dapm_path *path;
        int con = 0;
 
+       if (widget->outputs >= 0)
+               return widget->outputs;
+
+       DAPM_UPDATE_STAT(widget, path_checks);
+
        if (widget->id == snd_soc_dapm_supply)
                return 0;
 
        switch (widget->id) {
        case snd_soc_dapm_adc:
        case snd_soc_dapm_aif_out:
-               if (widget->active)
-                       return snd_soc_dapm_suspend_check(widget);
+               if (widget->active) {
+                       widget->outputs = snd_soc_dapm_suspend_check(widget);
+                       return widget->outputs;
+               }
        default:
                break;
        }
 
        if (widget->connected) {
                /* connected pin ? */
-               if (widget->id == snd_soc_dapm_output && !widget->ext)
-                       return snd_soc_dapm_suspend_check(widget);
+               if (widget->id == snd_soc_dapm_output && !widget->ext) {
+                       widget->outputs = snd_soc_dapm_suspend_check(widget);
+                       return widget->outputs;
+               }
 
                /* connected jack or spk ? */
-               if (widget->id == snd_soc_dapm_hp || widget->id == snd_soc_dapm_spk ||
-                   (widget->id == snd_soc_dapm_line && !list_empty(&widget->sources)))
-                       return snd_soc_dapm_suspend_check(widget);
+               if (widget->id == snd_soc_dapm_hp ||
+                   widget->id == snd_soc_dapm_spk ||
+                   (widget->id == snd_soc_dapm_line &&
+                    !list_empty(&widget->sources))) {
+                       widget->outputs = snd_soc_dapm_suspend_check(widget);
+                       return widget->outputs;
+               }
        }
 
        list_for_each_entry(path, &widget->sinks, list_source) {
+               DAPM_UPDATE_STAT(widget, neighbour_checks);
+
                if (path->weak)
                        continue;
 
@@ -685,6 +717,8 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
                }
        }
 
+       widget->outputs = con;
+
        return con;
 }
 
@@ -697,6 +731,11 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
        struct snd_soc_dapm_path *path;
        int con = 0;
 
+       if (widget->inputs >= 0)
+               return widget->inputs;
+
+       DAPM_UPDATE_STAT(widget, path_checks);
+
        if (widget->id == snd_soc_dapm_supply)
                return 0;
 
@@ -704,28 +743,40 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
        switch (widget->id) {
        case snd_soc_dapm_dac:
        case snd_soc_dapm_aif_in:
-               if (widget->active)
-                       return snd_soc_dapm_suspend_check(widget);
+               if (widget->active) {
+                       widget->inputs = snd_soc_dapm_suspend_check(widget);
+                       return widget->inputs;
+               }
        default:
                break;
        }
 
        if (widget->connected) {
                /* connected pin ? */
-               if (widget->id == snd_soc_dapm_input && !widget->ext)
-                       return snd_soc_dapm_suspend_check(widget);
+               if (widget->id == snd_soc_dapm_input && !widget->ext) {
+                       widget->inputs = snd_soc_dapm_suspend_check(widget);
+                       return widget->inputs;
+               }
 
                /* connected VMID/Bias for lower pops */
-               if (widget->id == snd_soc_dapm_vmid)
-                       return snd_soc_dapm_suspend_check(widget);
+               if (widget->id == snd_soc_dapm_vmid) {
+                       widget->inputs = snd_soc_dapm_suspend_check(widget);
+                       return widget->inputs;
+               }
 
                /* connected jack ? */
                if (widget->id == snd_soc_dapm_mic ||
-                   (widget->id == snd_soc_dapm_line && !list_empty(&widget->sinks)))
-                       return snd_soc_dapm_suspend_check(widget);
+                   (widget->id == snd_soc_dapm_line &&
+                    !list_empty(&widget->sinks))) {
+                       widget->inputs = snd_soc_dapm_suspend_check(widget);
+                       return widget->inputs;
+               }
+
        }
 
        list_for_each_entry(path, &widget->sources, list_sink) {
+               DAPM_UPDATE_STAT(widget, neighbour_checks);
+
                if (path->weak)
                        continue;
 
@@ -738,6 +789,8 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
                }
        }
 
+       widget->inputs = con;
+
        return con;
 }
 
@@ -761,12 +814,29 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
 }
 EXPORT_SYMBOL_GPL(dapm_reg_event);
 
+static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
+{
+       if (w->power_checked)
+               return w->new_power;
+
+       if (w->force)
+               w->new_power = 1;
+       else
+               w->new_power = w->power_check(w);
+
+       w->power_checked = true;
+
+       return w->new_power;
+}
+
 /* Generic check to see if a widget should be powered.
  */
 static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
 {
        int in, out;
 
+       DAPM_UPDATE_STAT(w, power_checks);
+
        in = is_connected_input_ep(w);
        dapm_clear_walk(w->dapm);
        out = is_connected_output_ep(w);
@@ -779,6 +849,8 @@ static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
 {
        int in;
 
+       DAPM_UPDATE_STAT(w, power_checks);
+
        if (w->active) {
                in = is_connected_input_ep(w);
                dapm_clear_walk(w->dapm);
@@ -793,6 +865,8 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
 {
        int out;
 
+       DAPM_UPDATE_STAT(w, power_checks);
+
        if (w->active) {
                out = is_connected_output_ep(w);
                dapm_clear_walk(w->dapm);
@@ -806,10 +880,13 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
 static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
 {
        struct snd_soc_dapm_path *path;
-       int power = 0;
+
+       DAPM_UPDATE_STAT(w, power_checks);
 
        /* Check if one of our outputs is connected */
        list_for_each_entry(path, &w->sinks, list_source) {
+               DAPM_UPDATE_STAT(w, neighbour_checks);
+
                if (path->weak)
                        continue;
 
@@ -820,21 +897,18 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
                if (!path->sink)
                        continue;
 
-               if (path->sink->force) {
-                       power = 1;
-                       break;
-               }
-
-               if (path->sink->power_check &&
-                   path->sink->power_check(path->sink)) {
-                       power = 1;
-                       break;
-               }
+               if (dapm_widget_power_check(path->sink))
+                       return 1;
        }
 
        dapm_clear_walk(w->dapm);
 
-       return power;
+       return 0;
+}
+
+static int dapm_always_on_check_power(struct snd_soc_dapm_widget *w)
+{
+       return 1;
 }
 
 static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
@@ -1177,6 +1251,85 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
        }
 }
 
+static void dapm_widget_set_peer_power(struct snd_soc_dapm_widget *peer,
+                                      bool power, bool connect)
+{
+       /* If a connection is being made or broken then that update
+        * will have marked the peer dirty, otherwise the widgets are
+        * not connected and this update has no impact. */
+       if (!connect)
+               return;
+
+       /* If the peer is already in the state we're moving to then we
+        * won't have an impact on it. */
+       if (power != peer->power)
+               dapm_mark_dirty(peer, "peer state change");
+}
+
+static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
+                                 struct list_head *up_list,
+                                 struct list_head *down_list)
+{
+       struct snd_soc_dapm_path *path;
+
+       if (w->power == power)
+               return;
+
+       trace_snd_soc_dapm_widget_power(w, power);
+
+       /* If we changed our power state perhaps our neigbours changed
+        * also.
+        */
+       list_for_each_entry(path, &w->sources, list_sink) {
+               if (path->source) {
+                       dapm_widget_set_peer_power(path->source, power,
+                                                  path->connect);
+               }
+       }
+       switch (w->id) {
+       case snd_soc_dapm_supply:
+               /* Supplies can't affect their outputs, only their inputs */
+               break;
+       default:
+               list_for_each_entry(path, &w->sinks, list_source) {
+                       if (path->sink) {
+                               dapm_widget_set_peer_power(path->sink, power,
+                                                          path->connect);
+                       }
+               }
+               break;
+       }
+
+       if (power)
+               dapm_seq_insert(w, up_list, true);
+       else
+               dapm_seq_insert(w, down_list, false);
+
+       w->power = power;
+}
+
+static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
+                                 struct list_head *up_list,
+                                 struct list_head *down_list)
+{
+       int power;
+
+       switch (w->id) {
+       case snd_soc_dapm_pre:
+               dapm_seq_insert(w, down_list, false);
+               break;
+       case snd_soc_dapm_post:
+               dapm_seq_insert(w, up_list, true);
+               break;
+
+       default:
+               power = dapm_widget_power_check(w);
+
+               dapm_widget_set_power(w, power, up_list, down_list);
+               break;
+       }
+}
+
 /*
  * Scan each dapm widget for complete audio path.
  * A complete path is a route that has valid endpoints i.e.:-
@@ -1195,7 +1348,6 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
        LIST_HEAD(down_list);
        LIST_HEAD(async_domain);
        enum snd_soc_bias_level bias;
-       int power;
 
        trace_snd_soc_dapm_start(card);
 
@@ -1208,61 +1360,47 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
                }
        }
 
-       /* Check which widgets we need to power and store them in
-        * lists indicating if they should be powered up or down.
-        */
+       memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
+
        list_for_each_entry(w, &card->widgets, list) {
-               switch (w->id) {
-               case snd_soc_dapm_pre:
-                       dapm_seq_insert(w, &down_list, false);
-                       break;
-               case snd_soc_dapm_post:
-                       dapm_seq_insert(w, &up_list, true);
-                       break;
+               w->power_checked = false;
+               w->inputs = -1;
+               w->outputs = -1;
+       }
 
-               default:
-                       if (!w->power_check)
-                               continue;
+       /* Check which widgets we need to power and store them in
+        * lists indicating if they should be powered up or down.  We
+        * only check widgets that have been flagged as dirty but note
+        * that new widgets may be added to the dirty list while we
+        * iterate.
+        */
+       list_for_each_entry(w, &card->dapm_dirty, dirty) {
+               dapm_power_one_widget(w, &up_list, &down_list);
+       }
 
-                       if (!w->force)
-                               power = w->power_check(w);
-                       else
-                               power = 1;
+       list_for_each_entry(w, &card->widgets, list) {
+               list_del_init(&w->dirty);
 
-                       if (power) {
-                               d = w->dapm;
+               if (w->power) {
+                       d = w->dapm;
 
-                               /* Supplies and micbiases only bring
-                                * the context up to STANDBY as unless
-                                * something else is active and
-                                * passing audio they generally don't
-                                * require full power.
-                                */
-                               switch (w->id) {
-                               case snd_soc_dapm_supply:
-                               case snd_soc_dapm_micbias:
-                                       if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
-                                               d->target_bias_level = SND_SOC_BIAS_STANDBY;
-                                       break;
-                               default:
-                                       d->target_bias_level = SND_SOC_BIAS_ON;
-                                       break;
-                               }
+                       /* Supplies and micbiases only bring the
+                        * context up to STANDBY as unless something
+                        * else is active and passing audio they
+                        * generally don't require full power.
+                        */
+                       switch (w->id) {
+                       case snd_soc_dapm_supply:
+                       case snd_soc_dapm_micbias:
+                               if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
+                                       d->target_bias_level = SND_SOC_BIAS_STANDBY;
+                               break;
+                       default:
+                               d->target_bias_level = SND_SOC_BIAS_ON;
+                               break;
                        }
-
-                       if (w->power == power)
-                               continue;
-
-                       trace_snd_soc_dapm_widget_power(w, power);
-
-                       if (power)
-                               dapm_seq_insert(w, &up_list, true);
-                       else
-                               dapm_seq_insert(w, &down_list, false);
-
-                       w->power = power;
-                       break;
                }
+
        }
 
        /* If there are no DAPM widgets then try to figure out power from the
@@ -1291,14 +1429,18 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
                }
        }
 
-       /* Force all contexts in the card to the same bias state */
+       /* Force all contexts in the card to the same bias state if
+        * they're not ground referenced.
+        */
        bias = SND_SOC_BIAS_OFF;
        list_for_each_entry(d, &card->dapm_list, list)
                if (d->target_bias_level > bias)
                        bias = d->target_bias_level;
        list_for_each_entry(d, &card->dapm_list, list)
-               d->target_bias_level = bias;
+               if (!d->idle_bias_off)
+                       d->target_bias_level = bias;
 
+       trace_snd_soc_dapm_walk_done(card);
 
        /* Run all the bias changes in parallel */
        list_for_each_entry(d, &dapm->card->dapm_list, list)
@@ -1529,14 +1671,21 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
 
                found = 1;
                /* we now need to match the string in the enum to the path */
-               if (!(strcmp(path->name, e->texts[mux])))
+               if (!(strcmp(path->name, e->texts[mux]))) {
                        path->connect = 1; /* new connection */
-               else
+                       dapm_mark_dirty(path->source, "mux connection");
+               } else {
+                       if (path->connect)
+                               dapm_mark_dirty(path->source,
+                                               "mux disconnection");
                        path->connect = 0; /* old connection must be powered down */
+               }
        }
 
-       if (found)
+       if (found) {
+               dapm_mark_dirty(widget, "mux change");
                dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
+       }
 
        return 0;
 }
@@ -1561,10 +1710,13 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
                /* found, now check type */
                found = 1;
                path->connect = connect;
+               dapm_mark_dirty(path->source, "mixer connection");
        }
 
-       if (found)
+       if (found) {
+               dapm_mark_dirty(widget, "mixer update");
                dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
+       }
 
        return 0;
 }
@@ -1708,6 +1860,7 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
        w->connected = status;
        if (status == 0)
                w->force = 0;
+       dapm_mark_dirty(w, "pin configuration");
 
        return 0;
 }
@@ -1723,6 +1876,13 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
  */
 int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
 {
+       /*
+        * Suppress early reports (eg, jacks syncing their state) to avoid
+        * silly DAPM runs during card startup.
+        */
+       if (!dapm->card || !dapm->card->instantiated)
+               return 0;
+
        return dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP);
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
@@ -2008,42 +2168,18 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
                case snd_soc_dapm_switch:
                case snd_soc_dapm_mixer:
                case snd_soc_dapm_mixer_named_ctl:
-                       w->power_check = dapm_generic_check_power;
                        dapm_new_mixer(w);
                        break;
                case snd_soc_dapm_mux:
                case snd_soc_dapm_virt_mux:
                case snd_soc_dapm_value_mux:
-                       w->power_check = dapm_generic_check_power;
                        dapm_new_mux(w);
                        break;
-               case snd_soc_dapm_adc:
-               case snd_soc_dapm_aif_out:
-                       w->power_check = dapm_adc_check_power;
-                       break;
-               case snd_soc_dapm_dac:
-               case snd_soc_dapm_aif_in:
-                       w->power_check = dapm_dac_check_power;
-                       break;
                case snd_soc_dapm_pga:
                case snd_soc_dapm_out_drv:
-                       w->power_check = dapm_generic_check_power;
                        dapm_new_pga(w);
                        break;
-               case snd_soc_dapm_input:
-               case snd_soc_dapm_output:
-               case snd_soc_dapm_micbias:
-               case snd_soc_dapm_spk:
-               case snd_soc_dapm_hp:
-               case snd_soc_dapm_mic:
-               case snd_soc_dapm_line:
-                       w->power_check = dapm_generic_check_power;
-                       break;
-               case snd_soc_dapm_supply:
-                       w->power_check = dapm_supply_check_power;
-               case snd_soc_dapm_vmid:
-               case snd_soc_dapm_pre:
-               case snd_soc_dapm_post:
+               default:
                        break;
                }
 
@@ -2060,6 +2196,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
 
                w->new = 1;
 
+               dapm_mark_dirty(w, "new widget");
                dapm_debugfs_add_widget(w);
        }
 
@@ -2534,6 +2671,44 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
        else
                snprintf(w->name, name_len, "%s", widget->name);
 
+       switch (w->id) {
+       case snd_soc_dapm_switch:
+       case snd_soc_dapm_mixer:
+       case snd_soc_dapm_mixer_named_ctl:
+               w->power_check = dapm_generic_check_power;
+               break;
+       case snd_soc_dapm_mux:
+       case snd_soc_dapm_virt_mux:
+       case snd_soc_dapm_value_mux:
+               w->power_check = dapm_generic_check_power;
+               break;
+       case snd_soc_dapm_adc:
+       case snd_soc_dapm_aif_out:
+               w->power_check = dapm_adc_check_power;
+               break;
+       case snd_soc_dapm_dac:
+       case snd_soc_dapm_aif_in:
+               w->power_check = dapm_dac_check_power;
+               break;
+       case snd_soc_dapm_pga:
+       case snd_soc_dapm_out_drv:
+       case snd_soc_dapm_input:
+       case snd_soc_dapm_output:
+       case snd_soc_dapm_micbias:
+       case snd_soc_dapm_spk:
+       case snd_soc_dapm_hp:
+       case snd_soc_dapm_mic:
+       case snd_soc_dapm_line:
+               w->power_check = dapm_generic_check_power;
+               break;
+       case snd_soc_dapm_supply:
+               w->power_check = dapm_supply_check_power;
+               break;
+       default:
+               w->power_check = dapm_always_on_check_power;
+               break;
+       }
+
        dapm->n_widgets++;
        w->dapm = dapm;
        w->codec = dapm->codec;
@@ -2541,6 +2716,7 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
        INIT_LIST_HEAD(&w->sources);
        INIT_LIST_HEAD(&w->sinks);
        INIT_LIST_HEAD(&w->list);
+       INIT_LIST_HEAD(&w->dirty);
        list_add(&w->list, &dapm->card->widgets);
 
        /* machine layer set ups unconnected pins and insertions */
@@ -2591,6 +2767,7 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
                dev_vdbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n",
                        w->name, w->sname, stream, event);
                if (strstr(w->sname, stream)) {
+                       dapm_mark_dirty(w, "stream event");
                        switch(event) {
                        case SND_SOC_DAPM_STREAM_START:
                                w->active = 1;
@@ -2680,6 +2857,7 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
        dev_dbg(w->dapm->dev, "dapm: force enable pin %s\n", pin);
        w->connected = 1;
        w->force = 1;
+       dapm_mark_dirty(w, "force enable");
 
        return 0;
 }
index 66fcccd..dd89933 100644 (file)
@@ -55,7 +55,7 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
                if (ret == 0)
                        return val;
                else
-                       return ret;
+                       return -1;
        }
 
        ret = snd_soc_cache_read(codec, reg, &val);
index fa31d9c..52db966 100644 (file)
@@ -188,6 +188,8 @@ int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
                list_add(&(pins[i].list), &jack->pins);
        }
 
+       snd_soc_dapm_new_widgets(&jack->codec->card->dapm);
+
        /* Update to reflect the last reported status; canned jack
         * implementations are likely to set their state before the
         * card has an opportunity to associate pins.
index 1aee9fc..ee15337 100644 (file)
 #include <sound/soc.h>
 #include <sound/initval.h>
 
-static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
+static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
+                                       struct snd_soc_dai *soc_dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       struct snd_soc_dai *codec_dai = rtd->codec_dai;
        int ret;
 
-       if (!codec_dai->driver->symmetric_rates &&
-           !cpu_dai->driver->symmetric_rates &&
+       if (!soc_dai->driver->symmetric_rates &&
            !rtd->dai_link->symmetric_rates)
                return 0;
 
@@ -43,19 +41,19 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
         * the second can need to get its constraints before the first has
         * picked a rate.  Complain and allow the application to carry on.
         */
-       if (!rtd->rate) {
-               dev_warn(&rtd->dev,
+       if (!soc_dai->rate) {
+               dev_warn(soc_dai->dev,
                         "Not enforcing symmetric_rates due to race\n");
                return 0;
        }
 
-       dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", rtd->rate);
+       dev_dbg(soc_dai->dev, "Symmetry forces %dHz rate\n", soc_dai->rate);
 
        ret = snd_pcm_hw_constraint_minmax(substream->runtime,
                                           SNDRV_PCM_HW_PARAM_RATE,
-                                          rtd->rate, rtd->rate);
+                                          soc_dai->rate, soc_dai->rate);
        if (ret < 0) {
-               dev_err(&rtd->dev,
+               dev_err(soc_dai->dev,
                        "Unable to apply rate symmetry constraint: %d\n", ret);
                return ret;
        }
@@ -185,8 +183,14 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        }
 
        /* Symmetry only applies if we've already got an active stream. */
-       if (cpu_dai->active || codec_dai->active) {
-               ret = soc_pcm_apply_symmetry(substream);
+       if (cpu_dai->active) {
+               ret = soc_pcm_apply_symmetry(substream, cpu_dai);
+               if (ret != 0)
+                       goto config_err;
+       }
+
+       if (codec_dai->active) {
+               ret = soc_pcm_apply_symmetry(substream, codec_dai);
                if (ret != 0)
                        goto config_err;
        }
@@ -288,8 +292,12 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
        codec_dai->active--;
        codec->active--;
 
-       if (!cpu_dai->active && !codec_dai->active)
-               rtd->rate = 0;
+       /* clear the corresponding DAIs rate when inactive */
+       if (!cpu_dai->active)
+               cpu_dai->rate = 0;
+
+       if (!codec_dai->active)
+               codec_dai->rate = 0;
 
        /* Muting the DAC suppresses artifacts caused during digital
         * shutdown, for example from stopping clocks.
@@ -311,10 +319,17 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
        cpu_dai->runtime = NULL;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               /* start delayed pop wq here for playback streams */
-               codec_dai->pop_wait = 1;
-               schedule_delayed_work(&rtd->delayed_work,
-                       msecs_to_jiffies(rtd->pmdown_time));
+               if (unlikely(codec->ignore_pmdown_time)) {
+                       /* powered down playback stream now */
+                       snd_soc_dapm_stream_event(rtd,
+                               codec_dai->driver->playback.stream_name,
+                               SND_SOC_DAPM_STREAM_STOP);
+               } else {
+                       /* start delayed pop wq here for playback streams */
+                       codec_dai->pop_wait = 1;
+                       schedule_delayed_work(&rtd->delayed_work,
+                               msecs_to_jiffies(rtd->pmdown_time));
+               }
        } else {
                /* capture streams can be powered down now */
                snd_soc_dapm_stream_event(rtd,
@@ -447,7 +462,9 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
                }
        }
 
-       rtd->rate = params_rate(params);
+       /* store the rate for each DAIs */
+       cpu_dai->rate = params_rate(params);
+       codec_dai->rate = params_rate(params);
 
 out:
        mutex_unlock(&rtd->pcm_mutex);
index 9f24ef7..3b55a44 100644 (file)
@@ -212,7 +212,7 @@ err_release:
        release_mem_region(res->start, resource_size(res));
 err_free:
        kfree(das);
-       das = 0;
+       das = NULL;
 exit:
        return ret;
 }
@@ -234,7 +234,7 @@ static int __devexit tegra_das_remove(struct platform_device *pdev)
        release_mem_region(res->start, resource_size(res));
 
        kfree(das);
-       das = 0;
+       das = NULL;
 
        return 0;
 }
index f36b996..6728fab 100644 (file)
@@ -312,7 +312,7 @@ static struct snd_soc_dai_ops tegra_i2s_dai_ops = {
        .trigger        = tegra_i2s_trigger,
 };
 
-struct snd_soc_dai_driver tegra_i2s_dai[] = {
+static struct snd_soc_dai_driver tegra_i2s_dai[] = {
        {
                .name = DRV_NAME ".0",
                .probe = tegra_i2s_probe,
index c7cfd96..436def1 100644 (file)
@@ -367,7 +367,7 @@ static void tegra_pcm_free(struct snd_pcm *pcm)
        tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
 }
 
-struct snd_soc_platform_driver tegra_pcm_platform = {
+static struct snd_soc_platform_driver tegra_pcm_platform = {
        .ops            = &tegra_pcm_ops,
        .pcm_new        = tegra_pcm_new,
        .pcm_free       = tegra_pcm_free,
index abe606b..dd11d0c 100644 (file)
@@ -127,7 +127,7 @@ static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
 {
        struct device *dev = substream->pcm->card->dev;
        struct tegra_spdif *spdif = snd_soc_dai_get_drvdata(dai);
-       int ret, srate, spdifclock;
+       int ret, spdifclock;
 
        spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_PACK;
        spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_BIT_MODE_MASK;
@@ -140,7 +140,6 @@ static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       srate = params_rate(params);
        switch (params_rate(params)) {
        case 32000:
                spdifclock = 4096000;
@@ -232,7 +231,7 @@ static struct snd_soc_dai_ops tegra_spdif_dai_ops = {
        .trigger        = tegra_spdif_trigger,
 };
 
-struct snd_soc_dai_driver tegra_spdif_dai = {
+static struct snd_soc_dai_driver tegra_spdif_dai = {
        .name = DRV_NAME,
        .probe = tegra_spdif_probe,
        .playback = {
index be27f1d..a81cf39 100644 (file)
@@ -339,8 +339,6 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
                snd_soc_dapm_nc_pin(dapm, "LINEOUTL");
        }
 
-       snd_soc_dapm_sync(dapm);
-
        return 0;
 }
 
index 8fc07e9..b3a7efa 100644 (file)
@@ -124,8 +124,6 @@ static int trimslice_asoc_init(struct snd_soc_pcm_runtime *rtd)
        snd_soc_dapm_nc_pin(dapm, "RHPOUT");
        snd_soc_dapm_nc_pin(dapm, "MICIN");
 
-       snd_soc_dapm_sync(dapm);
-
        return 0;
 }
 
index 6770e71..9b5e283 100644 (file)
@@ -62,7 +62,7 @@ static int __exit txx9aclc_generic_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver txx9aclc_generic_driver = {
-       .remove = txx9aclc_generic_remove,
+       .remove = __exit_p(txx9aclc_generic_remove),
        .driver = {
                .name = "txx9aclc-generic",
                .owner = THIS_MODULE,