Merge branch 'mfd/wm8994' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 12 Dec 2011 16:19:20 +0000 (00:19 +0800)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 12 Dec 2011 16:19:20 +0000 (00:19 +0800)
259 files changed:
Documentation/devicetree/bindings/sound/tegra20-das.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/tegra20-i2s.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/wm8903.txt [new file with mode: 0644]
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/sound/alsa/soc/machine.txt
MAINTAINERS
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-shmobile/board-ap4evb.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-tegra/board-harmony.c
arch/arm/mach-tegra/board-seaboard.c
arch/sh/boards/mach-se/7724/setup.c
drivers/firmware/Kconfig
drivers/firmware/Makefile
drivers/firmware/sigma.c [deleted file]
include/linux/mfd/wm8994/pdata.h
include/linux/mfd/wm8994/registers.h
include/linux/sigma.h [deleted file]
include/sound/sh_fsi.h
include/sound/soc-dapm.h
include/sound/soc.h
include/sound/sta32x.h [new file with mode: 0644]
include/sound/wm8903.h
sound/soc/Kconfig
sound/soc/atmel/Kconfig
sound/soc/atmel/Makefile
sound/soc/atmel/atmel-pcm.c
sound/soc/atmel/atmel_ssc_dai.c
sound/soc/atmel/playpaq_wm8510.c [deleted file]
sound/soc/au1x/ac97c.c
sound/soc/au1x/db1000.c
sound/soc/au1x/db1200.c
sound/soc/au1x/dbdma2.c
sound/soc/au1x/dma.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-ac97.c
sound/soc/blackfin/bf5xx-i2s-pcm.c
sound/soc/blackfin/bf5xx-i2s.c
sound/soc/blackfin/bf5xx-tdm-pcm.c
sound/soc/blackfin/bf5xx-tdm.c
sound/soc/blackfin/bfin-eval-adau1373.c
sound/soc/blackfin/bfin-eval-adau1701.c
sound/soc/blackfin/bfin-eval-adav80x.c
sound/soc/codecs/88pm860x-codec.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ac97.c
sound/soc/codecs/ad1836.c
sound/soc/codecs/ad1836.h
sound/soc/codecs/ad193x.c
sound/soc/codecs/ad193x.h
sound/soc/codecs/ad1980.c
sound/soc/codecs/ad73311.c
sound/soc/codecs/adau1373.c
sound/soc/codecs/adau1701.c
sound/soc/codecs/adav80x.c
sound/soc/codecs/ads117x.c
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/alc5632.c [new file with mode: 0644]
sound/soc/codecs/alc5632.h [new file with mode: 0644]
sound/soc/codecs/cq93vc.c
sound/soc/codecs/cs4270.c
sound/soc/codecs/cs4271.c
sound/soc/codecs/cs42l51.c
sound/soc/codecs/cs42l73.c [new file with mode: 0644]
sound/soc/codecs/cs42l73.h [new file with mode: 0644]
sound/soc/codecs/cx20442.c
sound/soc/codecs/da7210.c
sound/soc/codecs/dfbmcs320.c
sound/soc/codecs/dmic.c
sound/soc/codecs/jz4740.c
sound/soc/codecs/max98088.c
sound/soc/codecs/max98095.c
sound/soc/codecs/max9850.c
sound/soc/codecs/max9877.c
sound/soc/codecs/pcm3008.c
sound/soc/codecs/rt5631.c
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/sigmadsp.c [new file with mode: 0644]
sound/soc/codecs/sigmadsp.h [new file with mode: 0644]
sound/soc/codecs/sn95031.c
sound/soc/codecs/spdif_transciever.c
sound/soc/codecs/ssm2602.c
sound/soc/codecs/sta32x.c
sound/soc/codecs/sta32x.h
sound/soc/codecs/stac9766.c
sound/soc/codecs/tlv320aic23.c
sound/soc/codecs/tlv320aic26.c
sound/soc/codecs/tlv320aic32x4.c
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/tlv320dac33.c
sound/soc/codecs/twl4030.c
sound/soc/codecs/twl6040.c
sound/soc/codecs/uda134x.c
sound/soc/codecs/uda1380.c
sound/soc/codecs/wl1273.c
sound/soc/codecs/wm1250-ev1.c
sound/soc/codecs/wm2000.c
sound/soc/codecs/wm2000.h
sound/soc/codecs/wm5100-tables.c
sound/soc/codecs/wm5100.c
sound/soc/codecs/wm5100.h
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/wm8727.c
sound/soc/codecs/wm8728.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8737.c
sound/soc/codecs/wm8741.c
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8770.c
sound/soc/codecs/wm8776.c
sound/soc/codecs/wm8782.c
sound/soc/codecs/wm8804.c
sound/soc/codecs/wm8900.c
sound/soc/codecs/wm8903.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8940.c
sound/soc/codecs/wm8955.c
sound/soc/codecs/wm8958-dsp2.c
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm8961.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8971.c
sound/soc/codecs/wm8974.c
sound/soc/codecs/wm8978.c
sound/soc/codecs/wm8983.c
sound/soc/codecs/wm8985.c
sound/soc/codecs/wm8988.c
sound/soc/codecs/wm8990.c
sound/soc/codecs/wm8991.c
sound/soc/codecs/wm8993.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8994.h
sound/soc/codecs/wm8995.c
sound/soc/codecs/wm8996.c
sound/soc/codecs/wm9081.c
sound/soc/codecs/wm9090.c
sound/soc/codecs/wm9705.c
sound/soc/codecs/wm9712.c
sound/soc/codecs/wm9713.c
sound/soc/codecs/wm_hubs.c
sound/soc/davinci/davinci-i2s.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/davinci/davinci-pcm.c
sound/soc/davinci/davinci-vcif.c
sound/soc/ep93xx/edb93xx.c
sound/soc/ep93xx/ep93xx-ac97.c
sound/soc/ep93xx/ep93xx-i2s.c
sound/soc/ep93xx/ep93xx-pcm.c
sound/soc/ep93xx/simone.c
sound/soc/ep93xx/snappercl15.c
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/mpc5200_dma.c
sound/soc/fsl/mpc5200_psc_ac97.c
sound/soc/fsl/mpc5200_psc_i2s.c
sound/soc/fsl/mpc8610_hpcd.c
sound/soc/fsl/p1022_ds.c
sound/soc/imx/Kconfig
sound/soc/imx/imx-pcm-dma-mx2.c
sound/soc/imx/imx-pcm-fiq.c
sound/soc/imx/imx-ssi.c
sound/soc/jz4740/jz4740-i2s.c
sound/soc/jz4740/jz4740-pcm.c
sound/soc/kirkwood/Kconfig
sound/soc/kirkwood/kirkwood-dma.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/mid-x86/Kconfig
sound/soc/mid-x86/mfld_machine.c
sound/soc/mid-x86/sst_platform.c
sound/soc/mid-x86/sst_platform.h
sound/soc/mxs/mxs-pcm.c
sound/soc/mxs/mxs-saif.c
sound/soc/mxs/mxs-sgtl5000.c
sound/soc/nuc900/nuc900-ac97.c
sound/soc/nuc900/nuc900-pcm.c
sound/soc/omap/Kconfig
sound/soc/omap/Makefile
sound/soc/omap/ams-delta.c
sound/soc/omap/omap-dmic.c [new file with mode: 0644]
sound/soc/omap/omap-dmic.h [new file with mode: 0644]
sound/soc/omap/omap-hdmi.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcpdm.c
sound/soc/omap/omap-pcm.c
sound/soc/omap/omap4-hdmi-card.c
sound/soc/omap/sdp4430.c
sound/soc/pxa/Kconfig
sound/soc/pxa/e740_wm9705.c
sound/soc/pxa/e750_wm9705.c
sound/soc/pxa/e800_wm9712.c
sound/soc/pxa/hx4700.c
sound/soc/pxa/mioa701_wm9713.c
sound/soc/pxa/palm27x.c
sound/soc/pxa/pxa-ssp.c
sound/soc/pxa/pxa2xx-ac97.c
sound/soc/pxa/pxa2xx-i2s.c
sound/soc/pxa/pxa2xx-pcm.c
sound/soc/s6000/s6000-i2s.c
sound/soc/s6000/s6000-pcm.c
sound/soc/samsung/Kconfig
sound/soc/samsung/Makefile
sound/soc/samsung/ac97.c
sound/soc/samsung/dma.c
sound/soc/samsung/i2s.c
sound/soc/samsung/idma.c
sound/soc/samsung/idma.h
sound/soc/samsung/jive_wm8750.c
sound/soc/samsung/littlemill.c [new file with mode: 0644]
sound/soc/samsung/lowland.c [new file with mode: 0644]
sound/soc/samsung/pcm.c
sound/soc/samsung/s3c2412-i2s.c
sound/soc/samsung/s3c24xx-i2s.c
sound/soc/samsung/s3c24xx_simtec_hermes.c
sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
sound/soc/samsung/s3c24xx_uda134x.c
sound/soc/samsung/smdk2443_wm9710.c
sound/soc/samsung/smdk_wm8580pcm.c
sound/soc/samsung/smdk_wm8994.c
sound/soc/samsung/smdk_wm8994pcm.c
sound/soc/samsung/spdif.c
sound/soc/samsung/speyside.c
sound/soc/samsung/speyside_wm8962.c [deleted file]
sound/soc/samsung/tobermory.c [new file with mode: 0644]
sound/soc/sh/dma-sh7760.c
sound/soc/sh/fsi-ak4642.c
sound/soc/sh/fsi-hdmi.c
sound/soc/sh/fsi.c
sound/soc/sh/hac.c
sound/soc/sh/siu_dai.c
sound/soc/sh/ssi.c
sound/soc/soc-cache.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-pcm.c
sound/soc/soc-utils.c
sound/soc/tegra/tegra_das.c
sound/soc/tegra/tegra_i2s.c
sound/soc/tegra/tegra_i2s.h
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-ac97.c
sound/soc/txx9/txx9aclc.c

diff --git a/Documentation/devicetree/bindings/sound/tegra20-das.txt b/Documentation/devicetree/bindings/sound/tegra20-das.txt
new file mode 100644 (file)
index 0000000..6de3a7e
--- /dev/null
@@ -0,0 +1,12 @@
+NVIDIA Tegra 20 DAS (Digital Audio Switch) controller
+
+Required properties:
+- compatible : "nvidia,tegra20-das"
+- reg : Should contain DAS registers location and length
+
+Example:
+
+das@70000c00 {
+       compatible = "nvidia,tegra20-das";
+       reg = <0x70000c00 0x80>;
+};
diff --git a/Documentation/devicetree/bindings/sound/tegra20-i2s.txt b/Documentation/devicetree/bindings/sound/tegra20-i2s.txt
new file mode 100644 (file)
index 0000000..0df2b5c
--- /dev/null
@@ -0,0 +1,17 @@
+NVIDIA Tegra 20 I2S controller
+
+Required properties:
+- compatible : "nvidia,tegra20-i2s"
+- reg : Should contain I2S registers location and length
+- interrupts : Should contain I2S interrupt
+- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
+  request selector for this I2S controller
+
+Example:
+
+i2s@70002800 {
+       compatible = "nvidia,tegra20-i2s";
+       reg = <0x70002800 0x200>;
+       interrupts = < 45 >;
+       nvidia,dma-request-selector = < &apbdma 2 >;
+};
diff --git a/Documentation/devicetree/bindings/sound/wm8903.txt b/Documentation/devicetree/bindings/sound/wm8903.txt
new file mode 100644 (file)
index 0000000..f102cbc
--- /dev/null
@@ -0,0 +1,50 @@
+WM8903 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+  - compatible : "wlf,wm8903"
+
+  - reg : the I2C address of the device.
+
+  - gpio-controller : Indicates this device is a GPIO controller.
+
+  - #gpio-cells : Should be two. The first cell is the pin number and the
+    second cell is used to specify optional parameters (currently unused).
+
+Optional properties:
+
+  - interrupts : The interrupt line the codec is connected to.
+
+  - micdet-cfg : Default register value for R6 (Mic Bias). If absent, the
+    default is 0.
+
+  - micdet-delay : The debounce delay for microphone detection in mS. If
+    absent, the default is 100.
+
+  - gpio-cfg : A list of GPIO configuration register values. The list must
+    be 5 entries long. If absent, no configuration of these registers is
+    performed. If any entry has the value 0xffffffff, that GPIO's
+    configuration will not be modified.
+
+Example:
+
+codec: wm8903@1a {
+       compatible = "wlf,wm8903";
+       reg = <0x1a>;
+       interrupts = < 347 >;
+
+       gpio-controller;
+       #gpio-cells = <2>;
+
+       micdet-cfg = <0>;
+       micdet-delay = <100>;
+       gpio-cfg = <
+               0x0600 /* DMIC_LR, output */
+               0x0680 /* DMIC_DAT, input */
+               0x0000 /* GPIO, output, low */
+               0x0200 /* Interrupt, output */
+               0x01a0 /* BCLK, input, active high */
+       >;
+};
index e855278..2c1b2cb 100644 (file)
@@ -37,4 +37,5 @@ simtek
 sirf   SiRF Technology, Inc.
 stericsson     ST-Ericsson
 ti     Texas Instruments
+wlf    Wolfson Microelectronics
 xlnx   Xilinx
index 3e2ec9c..d50c14d 100644 (file)
@@ -50,8 +50,7 @@ Machine DAI Configuration
 The machine DAI configuration glues all the codec and CPU DAIs together. It can
 also be used to set up the DAI system clock and for any machine related DAI
 initialisation e.g. the machine audio map can be connected to the codec audio
-map, unconnected codec pins can be set as such. Please see corgi.c, spitz.c
-for examples.
+map, unconnected codec pins can be set as such.
 
 struct snd_soc_dai_link is used to set up each DAI in your machine. e.g.
 
@@ -83,8 +82,7 @@ Machine Power Map
 The machine driver can optionally extend the codec power map and to become an
 audio power map of the audio subsystem. This allows for automatic power up/down
 of speaker/HP amplifiers, etc. Codec pins can be connected to the machines jack
-sockets in the machine init function. See soc/pxa/spitz.c and dapm.txt for
-details.
+sockets in the machine init function.
 
 
 Machine Controls
index 3523ab0..0ad711e 100644 (file)
@@ -542,6 +542,7 @@ F:  sound/soc/codecs/adau*
 F:     sound/soc/codecs/adav*
 F:     sound/soc/codecs/ad1*
 F:     sound/soc/codecs/ssm*
+F:     sound/soc/codecs/sigmadsp.*
 
 ANALOG DEVICES INC ASOC DRIVERS
 L:     uclinux-dist-devel@blackfin.uclinux.org
@@ -5667,7 +5668,6 @@ F:        drivers/media/video/*7146*
 F:     include/media/*7146*
 
 SAMSUNG AUDIO (ASoC) DRIVERS
-M:     Jassi Brar <jassisinghbrar@gmail.com>
 M:     Sangbeom Kim <sbkim73@samsung.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Supported
index d04b654..55c0e75 100644 (file)
@@ -282,8 +282,8 @@ static struct platform_device lowland_device = {
        .id             = -1,
 };
 
-static struct platform_device speyside_wm8962_device = {
-       .name           = "speyside-wm8962",
+static struct platform_device tobermory_device = {
+       .name           = "tobermory",
        .id             = -1,
 };
 
@@ -338,7 +338,7 @@ static struct platform_device *crag6410_devices[] __initdata = {
        &crag6410_lcd_powerdev,
        &crag6410_backlight_device,
        &speyside_device,
-       &speyside_wm8962_device,
+       &tobermory_device,
        &lowland_device,
        &wallvdd_device,
 };
index 4c865ec..bb08d2d 100644 (file)
@@ -762,9 +762,22 @@ static struct platform_device fsi_device = {
        },
 };
 
+static struct fsi_ak4642_info fsi2_ak4643_info = {
+       .name           = "AK4643",
+       .card           = "FSI2A-AK4643",
+       .cpu_dai        = "fsia-dai",
+       .codec          = "ak4642-codec.0-0013",
+       .platform       = "sh_fsi2",
+       .id             = FSI_PORT_A,
+};
+
 static struct platform_device fsi_ak4643_device = {
-       .name           = "sh_fsi2_a_ak4643",
+       .name   = "fsi-ak4642-audio",
+       .dev    = {
+               .platform_data  = &fsi_info,
+       },
 };
+
 static struct sh_mobile_meram_cfg hdmi_meram_cfg = {
        .icb[0] = {
                .marker_icb     = 30,
index 9c5e598..a2908d4 100644 (file)
@@ -990,8 +990,20 @@ static struct platform_device fsi_device = {
        },
 };
 
+static struct fsi_ak4642_info fsi2_ak4643_info = {
+       .name           = "AK4643",
+       .card           = "FSI2A-AK4643",
+       .cpu_dai        = "fsia-dai",
+       .codec          = "ak4642-codec.0-0013",
+       .platform       = "sh_fsi2",
+       .id             = FSI_PORT_A,
+};
+
 static struct platform_device fsi_ak4643_device = {
-       .name           = "sh_fsi2_a_ak4643",
+       .name   = "fsi-ak4642-audio",
+       .dev    = {
+               .platform_data  = &fsi2_ak4643_info,
+       },
 };
 
 /*
index f0bdc5e..3c57cdc 100644 (file)
@@ -89,11 +89,11 @@ static struct wm8903_platform_data harmony_wm8903_pdata = {
        .micdet_delay = 100,
        .gpio_base = HARMONY_GPIO_WM8903(0),
        .gpio_cfg = {
-               WM8903_GPIO_NO_CONFIG,
-               WM8903_GPIO_NO_CONFIG,
                0,
-               WM8903_GPIO_NO_CONFIG,
-               WM8903_GPIO_NO_CONFIG,
+               0,
+               WM8903_GPIO_CONFIG_ZERO,
+               0,
+               0,
        },
 };
 
index bf13ea3..5c2f775 100644 (file)
@@ -171,11 +171,11 @@ static struct wm8903_platform_data wm8903_pdata = {
        .micdet_delay = 100,
        .gpio_base = SEABOARD_GPIO_WM8903(0),
        .gpio_cfg = {
-               WM8903_GPIO_NO_CONFIG,
-               WM8903_GPIO_NO_CONFIG,
                0,
-               WM8903_GPIO_NO_CONFIG,
-               WM8903_GPIO_NO_CONFIG,
+               0,
+               WM8903_GPIO_CONFIG_ZERO,
+               0,
+               0,
        },
 };
 
index b747c0a..b49723b 100644 (file)
@@ -315,8 +315,20 @@ static struct platform_device fsi_device = {
        },
 };
 
+static struct fsi_ak4642_info fsi_ak4642_info = {
+       .name           = "AK4642",
+       .card           = "FSIA-AK4642",
+       .cpu_dai        = "fsia-dai",
+       .codec          = "ak4642-codec.0-0012",
+       .platform       = "sh_fsi.0",
+       .id             = FSI_PORT_A,
+};
+
 static struct platform_device fsi_ak4642_device = {
-       .name           = "sh_fsi_a_ak4642",
+       .name   = "fsi-ak4642-audio",
+       .dev    = {
+               .platform_data  = &fsi_ak4642_info,
+       },
 };
 
 /* KEYSC in SoC (Needs SW33-2 set to ON) */
index efba163..9b00072 100644 (file)
@@ -145,18 +145,6 @@ config ISCSI_IBFT
          detect iSCSI boot parameters dynamically during system boot, say Y.
          Otherwise, say N.
 
-config SIGMA
-       tristate "SigmaStudio firmware loader"
-       depends on I2C
-       select CRC32
-       default n
-       help
-         Enable helper functions for working with Analog Devices SigmaDSP
-         parts and binary firmwares produced by Analog Devices SigmaStudio.
-
-         If unsure, say N here.  Drivers that need these helpers will select
-         this option automatically.
-
 source "drivers/firmware/google/Kconfig"
 
 endmenu
index 47338c9..5a7e273 100644 (file)
@@ -12,6 +12,5 @@ obj-$(CONFIG_DMIID)           += dmi-id.o
 obj-$(CONFIG_ISCSI_IBFT_FIND)  += iscsi_ibft_find.o
 obj-$(CONFIG_ISCSI_IBFT)       += iscsi_ibft.o
 obj-$(CONFIG_FIRMWARE_MEMMAP)  += memmap.o
-obj-$(CONFIG_SIGMA)            += sigma.o
 
 obj-$(CONFIG_GOOGLE_FIRMWARE)  += google/
diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c
deleted file mode 100644 (file)
index f10fc52..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Load Analog Devices SigmaStudio firmware files
- *
- * Copyright 2009-2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/crc32.h>
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/sigma.h>
-
-/* Return: 0==OK, <0==error, =1 ==no more actions */
-static int
-process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw)
-{
-       struct sigma_action *sa = (void *)(ssfw->fw->data + ssfw->pos);
-       size_t len = sigma_action_len(sa);
-       int ret = 0;
-
-       pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,
-               sa->instr, sa->addr, len);
-
-       switch (sa->instr) {
-       case SIGMA_ACTION_WRITEXBYTES:
-       case SIGMA_ACTION_WRITESINGLE:
-       case SIGMA_ACTION_WRITESAFELOAD:
-               if (ssfw->fw->size < ssfw->pos + len)
-                       return -EINVAL;
-               ret = i2c_master_send(client, (void *)&sa->addr, len);
-               if (ret < 0)
-                       return -EINVAL;
-               break;
-
-       case SIGMA_ACTION_DELAY:
-               ret = 0;
-               udelay(len);
-               len = 0;
-               break;
-
-       case SIGMA_ACTION_END:
-               return 1;
-
-       default:
-               return -EINVAL;
-       }
-
-       /* when arrive here ret=0 or sent data */
-       ssfw->pos += sigma_action_size(sa, len);
-       return ssfw->pos == ssfw->fw->size;
-}
-
-static int
-process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw)
-{
-       pr_debug("%s: processing %p\n", __func__, ssfw);
-
-       while (1) {
-               int ret = process_sigma_action(client, ssfw);
-               pr_debug("%s: action returned %i\n", __func__, ret);
-               if (ret == 1)
-                       return 0;
-               else if (ret)
-                       return ret;
-       }
-}
-
-int process_sigma_firmware(struct i2c_client *client, const char *name)
-{
-       int ret;
-       struct sigma_firmware_header *ssfw_head;
-       struct sigma_firmware ssfw;
-       const struct firmware *fw;
-       u32 crc;
-
-       pr_debug("%s: loading firmware %s\n", __func__, name);
-
-       /* first load the blob */
-       ret = request_firmware(&fw, name, &client->dev);
-       if (ret) {
-               pr_debug("%s: request_firmware() failed with %i\n", __func__, ret);
-               return ret;
-       }
-       ssfw.fw = fw;
-
-       /* then verify the header */
-       ret = -EINVAL;
-       if (fw->size < sizeof(*ssfw_head))
-               goto done;
-
-       ssfw_head = (void *)fw->data;
-       if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic)))
-               goto done;
-
-       crc = crc32(0, fw->data, fw->size);
-       pr_debug("%s: crc=%x\n", __func__, crc);
-       if (crc != ssfw_head->crc)
-               goto done;
-
-       ssfw.pos = sizeof(*ssfw_head);
-
-       /* finally process all of the actions */
-       ret = process_sigma_actions(client, &ssfw);
-
- done:
-       release_firmware(fw);
-
-       pr_debug("%s: loaded %s\n", __func__, name);
-
-       return ret;
-}
-EXPORT_SYMBOL(process_sigma_firmware);
-
-MODULE_LICENSE("GPL");
index b00897a..3fb1f40 100644 (file)
@@ -113,6 +113,23 @@ struct wm8958_enh_eq_cfg {
        u16 regs[WM8958_ENH_EQ_REGS];
 };
 
+/**
+ * Microphone detection rates, used to tune response rates and power
+ * consumption for WM8958/WM1811 microphone detection.
+ *
+ * @sysclk: System clock rate to use this configuration for.
+ * @idle: True if this configuration should use when no accessory is detected,
+ *        false otherwise.
+ * @start: Value for MICD_BIAS_START_TIME register field (not shifted).
+ * @rate: Value for MICD_RATE register field (not shifted).
+ */
+struct wm8958_micd_rate {
+       int sysclk;
+       bool idle;
+       int start;
+       int rate;
+};
+
 struct wm8994_pdata {
        int gpio_base;
 
@@ -144,6 +161,9 @@ struct wm8994_pdata {
        int num_enh_eq_cfgs;
        struct wm8958_enh_eq_cfg *enh_eq_cfgs;
 
+       int num_micd_rates;
+       struct wm8958_micd_rate *micd_rates;
+
         /* LINEOUT can be differential or single ended */
         unsigned int lineout1_diff:1;
         unsigned int lineout2_diff:1;
@@ -168,6 +188,9 @@ struct wm8994_pdata {
        /* WM8958 microphone bias configuration */
        int micbias[2];
 
+       /* WM8958 microphone detection ranges */
+       u16 micd_lvl_sel;
+
        /* Disable the internal pull downs on the LDOs if they are
         * always driven (eg, connected to an always on supply or
         * GPIO that always drives an output.  If they float power
index 8317b19..86e6a03 100644 (file)
 #define WM8994_GPIO_4                           0x703
 #define WM8994_GPIO_5                           0x704
 #define WM8994_GPIO_6                           0x705
+#define WM1811_JACKDET_CTRL                    0x705
 #define WM8994_GPIO_7                           0x706
 #define WM8994_GPIO_8                           0x707
 #define WM8994_GPIO_9                           0x708
 /*
  * R57 (0x39) - AntiPOP (2)
  */
+#define WM1811_JACKDET_MODE_MASK                0x0180  /* JACKDET_MODE - [8:7] */
+#define WM1811_JACKDET_MODE_SHIFT                    7  /* JACKDET_MODE - [8:7] */
+#define WM1811_JACKDET_MODE_WIDTH                    2  /* JACKDET_MODE - [8:7] */
 #define WM8994_MICB2_DISCH                      0x0100  /* MICB2_DISCH */
 #define WM8994_MICB2_DISCH_MASK                 0x0100  /* MICB2_DISCH */
 #define WM8994_MICB2_DISCH_SHIFT                     8  /* MICB2_DISCH */
 #define WM8994_STL_SEL_SHIFT                         0  /* STL_SEL */
 #define WM8994_STL_SEL_WIDTH                         1  /* STL_SEL */
 
+/*
+ * R1797 (0x705) - JACKDET Ctrl
+ */
+#define WM1811_JACKDET_DB                       0x0100  /* JACKDET_DB */
+#define WM1811_JACKDET_DB_MASK                  0x0100  /* JACKDET_DB */
+#define WM1811_JACKDET_DB_SHIFT                      8  /* JACKDET_DB */
+#define WM1811_JACKDET_DB_WIDTH                      1  /* JACKDET_DB */
+#define WM1811_JACKDET_LVL                      0x0040  /* JACKDET_LVL */
+#define WM1811_JACKDET_LVL_MASK                 0x0040  /* JACKDET_LVL */
+#define WM1811_JACKDET_LVL_SHIFT                     6  /* JACKDET_LVL */
+#define WM1811_JACKDET_LVL_WIDTH                     1  /* JACKDET_LVL */
+
 /*
  * R1824 (0x720) - Pull Control (1)
  */
diff --git a/include/linux/sigma.h b/include/linux/sigma.h
deleted file mode 100644 (file)
index e2accb3..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Load firmware files from Analog Devices SigmaStudio
- *
- * Copyright 2009-2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#ifndef __SIGMA_FIRMWARE_H__
-#define __SIGMA_FIRMWARE_H__
-
-#include <linux/firmware.h>
-#include <linux/types.h>
-
-struct i2c_client;
-
-#define SIGMA_MAGIC "ADISIGM"
-
-struct sigma_firmware {
-       const struct firmware *fw;
-       size_t pos;
-};
-
-struct sigma_firmware_header {
-       unsigned char magic[7];
-       u8 version;
-       u32 crc;
-};
-
-enum {
-       SIGMA_ACTION_WRITEXBYTES = 0,
-       SIGMA_ACTION_WRITESINGLE,
-       SIGMA_ACTION_WRITESAFELOAD,
-       SIGMA_ACTION_DELAY,
-       SIGMA_ACTION_PLLWAIT,
-       SIGMA_ACTION_NOOP,
-       SIGMA_ACTION_END,
-};
-
-struct sigma_action {
-       u8 instr;
-       u8 len_hi;
-       u16 len;
-       u16 addr;
-       unsigned char payload[];
-};
-
-static inline u32 sigma_action_len(struct sigma_action *sa)
-{
-       return (sa->len_hi << 16) | sa->len;
-}
-
-static inline size_t sigma_action_size(struct sigma_action *sa, u32 payload_len)
-{
-       return sizeof(*sa) + payload_len + (payload_len % 2);
-}
-
-extern int process_sigma_firmware(struct i2c_client *client, const char *name);
-
-#endif
index 9a155f9..9b1aaca 100644 (file)
@@ -78,4 +78,16 @@ struct sh_fsi_platform_info {
        int (*set_rate)(struct device *dev, int is_porta, int rate, int enable);
 };
 
+/*
+ * for fsi-ak4642
+ */
+struct fsi_ak4642_info {
+       const char *name;
+       const char *card;
+       const char *cpu_dai;
+       const char *codec;
+       const char *platform;
+       int id;
+};
+
 #endif /* __SOUND_FSI_H */
index 17a4c17..d26a9b7 100644 (file)
@@ -43,6 +43,9 @@
        .num_kcontrols = 0}
 
 /* platform domain */
+#define SND_SOC_DAPM_SIGGEN(wname) \
+{      .id = snd_soc_dapm_siggen, .name = wname, .kcontrol_news = NULL, \
+       .num_kcontrols = 0, .reg = SND_SOC_NOPM }
 #define SND_SOC_DAPM_INPUT(wname) \
 {      .id = snd_soc_dapm_input, .name = wname, .kcontrol_news = NULL, \
        .num_kcontrols = 0, .reg = SND_SOC_NOPM }
@@ -380,6 +383,7 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
                                  const char *pin);
 int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
                                const char *pin);
+void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec);
 
 /* Mostly internal - should not normally be used */
 void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason);
@@ -409,6 +413,7 @@ enum snd_soc_dapm_type {
        snd_soc_dapm_supply,            /* power/clock supply */
        snd_soc_dapm_aif_in,            /* audio interface input */
        snd_soc_dapm_aif_out,           /* audio interface output */
+       snd_soc_dapm_siggen,            /* signal generator */
 };
 
 /*
index 11cfb59..d9aa66b 100644 (file)
@@ -266,7 +266,6 @@ enum snd_soc_control_type {
 
 enum snd_soc_compress_type {
        SND_SOC_FLAT_COMPRESSION = 1,
-       SND_SOC_LZO_COMPRESSION,
        SND_SOC_RBTREE_COMPRESSION
 };
 
@@ -593,8 +592,7 @@ struct snd_soc_codec_driver {
        /* driver ops */
        int (*probe)(struct snd_soc_codec *);
        int (*remove)(struct snd_soc_codec *);
-       int (*suspend)(struct snd_soc_codec *,
-                       pm_message_t state);
+       int (*suspend)(struct snd_soc_codec *);
        int (*resume)(struct snd_soc_codec *);
 
        /* Default control and setup, added after probe() is run */
@@ -718,6 +716,9 @@ struct snd_soc_dai_link {
        /* Symmetry requirements */
        unsigned int symmetric_rates:1;
 
+       /* pmdown_time is ignored at stop */
+       unsigned int ignore_pmdown_time:1;
+
        /* codec/machine specific init - e.g. add machine controls */
        int (*init)(struct snd_soc_pcm_runtime *rtd);
 
@@ -813,6 +814,7 @@ struct snd_soc_card {
        int num_dapm_widgets;
        const struct snd_soc_dapm_route *dapm_routes;
        int num_dapm_routes;
+       bool fully_routed;
 
        struct work_struct deferred_resume_work;
 
@@ -840,7 +842,7 @@ struct snd_soc_card {
 };
 
 /* SoC machine DAI configuration, glues a codec and cpu DAI together */
-struct snd_soc_pcm_runtime  {
+struct snd_soc_pcm_runtime {
        struct device dev;
        struct snd_soc_card *card;
        struct snd_soc_dai_link *dai_link;
diff --git a/include/sound/sta32x.h b/include/sound/sta32x.h
new file mode 100644 (file)
index 0000000..8d93b03
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Platform data for ST STA32x ASoC codec driver.
+ *
+ * Copyright: 2011 Raumfeld GmbH
+ * Author: Johannes Stezenbach <js@sig21.net>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#ifndef __LINUX_SND__STA32X_H
+#define __LINUX_SND__STA32X_H
+
+#define STA32X_OCFG_2CH                0
+#define STA32X_OCFG_2_1CH      1
+#define STA32X_OCFG_1CH                3
+
+#define STA32X_OM_CH1          0
+#define STA32X_OM_CH2          1
+#define STA32X_OM_CH3          2
+
+#define STA32X_THERMAL_ADJUSTMENT_ENABLE       1
+#define STA32X_THERMAL_RECOVERY_ENABLE         2
+
+struct sta32x_platform_data {
+       int output_conf;
+       int ch1_output_mapping;
+       int ch2_output_mapping;
+       int ch3_output_mapping;
+       int thermal_conf;
+       int needs_esd_watchdog;
+};
+
+#endif /* __LINUX_SND__STA32X_H */
index cf7ccb7..b310c5a 100644 (file)
 #ifndef __LINUX_SND_WM8903_H
 #define __LINUX_SND_WM8903_H
 
-/* Used to enable configuration of a GPIO to all zeros */
-#define WM8903_GPIO_NO_CONFIG 0x8000
+/*
+ * Used to enable configuration of a GPIO to all zeros; a gpio_cfg value of
+ * zero in platform data means "don't touch this pin".
+ */
+#define WM8903_GPIO_CONFIG_ZERO 0x8000
 
 /*
  * R6 (0x06) - Mic Bias Control 0
index 1381db8..35e662d 100644 (file)
@@ -22,21 +22,6 @@ menuconfig SND_SOC
 
 if SND_SOC
 
-config SND_SOC_CACHE_LZO
-       bool "Support LZO compression for register caches"
-       select LZO_COMPRESS
-       select LZO_DECOMPRESS
-       ---help---
-          Select this to enable LZO compression for register caches.
-          This will allow machine or CODEC drivers to compress register
-          caches in memory, reducing the memory consumption at the
-          expense of performance.  If this is not present and is used
-          the system will fall back to uncompressed caches.
-
-          Usually it is safe to disable this option, where cache
-          compression in used the rbtree option will typically perform
-          better.
-
 config SND_SOC_AC97_BUS
        bool
 
index bee3c94..d1fcc81 100644 (file)
@@ -1,6 +1,6 @@
 config SND_ATMEL_SOC
        tristate "SoC Audio for the Atmel System-on-Chip"
-       depends on ARCH_AT91 || AVR32
+       depends on ARCH_AT91
        help
          Say Y or M if you want to add support for codecs attached to
          the ATMEL SSC interface. You will also need
@@ -24,25 +24,6 @@ config SND_AT91_SOC_SAM9G20_WM8731
          Say Y if you want to add support for SoC audio on WM8731-based
          AT91sam9g20 evaluation board.
 
-config SND_AT32_SOC_PLAYPAQ
-        tristate "SoC Audio support for PlayPaq with WM8510"
-        depends on SND_ATMEL_SOC && BOARD_PLAYPAQ && AT91_PROGRAMMABLE_CLOCKS
-        select SND_ATMEL_SOC_SSC
-        select SND_SOC_WM8510
-        help
-          Say Y or M here if you want to add support for SoC audio
-          on the LRS PlayPaq.
-
-config SND_AT32_SOC_PLAYPAQ_SLAVE
-        bool "Run CODEC on PlayPaq in slave mode"
-        depends on SND_AT32_SOC_PLAYPAQ
-        default n
-        help
-          Say Y if you want to run with the AT32 SSC generating the BCLK
-          and FRAME signals on the PlayPaq.  Unless you want to play
-          with the AT32 as the SSC master, you probably want to say N here,
-          as this will give you better sound quality.
-
 config SND_AT91_SOC_AFEB9260
        tristate "SoC Audio support for AFEB9260 board"
        depends on ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC
index e7ea56b..a5c0bf1 100644 (file)
@@ -8,9 +8,5 @@ obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
 # AT91 Machine Support
 snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
 
-# AT32 Machine Support
-snd-soc-playpaq-objs := playpaq_wm8510.o
-
 obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o
-obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o
 obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o
index f81d4c3..60de055 100644 (file)
@@ -495,17 +495,7 @@ static struct platform_driver atmel_pcm_driver = {
        .remove = __devexit_p(atmel_soc_platform_remove),
 };
 
-static int __init snd_atmel_pcm_init(void)
-{
-       return platform_driver_register(&atmel_pcm_driver);
-}
-module_init(snd_atmel_pcm_init);
-
-static void __exit snd_atmel_pcm_exit(void)
-{
-       platform_driver_unregister(&atmel_pcm_driver);
-}
-module_exit(snd_atmel_pcm_exit);
+module_platform_driver(atmel_pcm_driver);
 
 MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
 MODULE_DESCRIPTION("Atmel PCM module");
index 7122509..354341e 100644 (file)
@@ -719,7 +719,7 @@ static int atmel_ssc_remove(struct snd_soc_dai *dai)
 #define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8     | SNDRV_PCM_FMTBIT_S16_LE |\
                          SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops atmel_ssc_dai_ops = {
+static const struct snd_soc_dai_ops atmel_ssc_dai_ops = {
        .startup        = atmel_ssc_startup,
        .shutdown       = atmel_ssc_shutdown,
        .prepare        = atmel_ssc_prepare,
@@ -859,17 +859,7 @@ int atmel_ssc_set_audio(int ssc_id)
 }
 EXPORT_SYMBOL_GPL(atmel_ssc_set_audio);
 
-static int __init snd_atmel_ssc_init(void)
-{
-       return platform_driver_register(&asoc_ssc_driver);
-}
-module_init(snd_atmel_ssc_init);
-
-static void __exit snd_atmel_ssc_exit(void)
-{
-       platform_driver_unregister(&asoc_ssc_driver);
-}
-module_exit(snd_atmel_ssc_exit);
+module_platform_driver(asoc_ssc_driver);
 
 /* Module information */
 MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");
diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c
deleted file mode 100644 (file)
index 73ae99a..0000000
+++ /dev/null
@@ -1,473 +0,0 @@
-/* sound/soc/at32/playpaq_wm8510.c
- * ASoC machine driver for PlayPaq using WM8510 codec
- *
- * Copyright (C) 2008 Long Range Systems
- *    Geoffrey Wossum <gwossum@acm.org>
- *
- * 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 code is largely inspired by sound/soc/at91/eti_b1_wm8731.c
- *
- * NOTE: If you don't have the AT32 enhanced portmux configured (which
- * isn't currently in the mainline or Atmel patched kernel), you will
- * need to set the MCLK pin (PA30) to peripheral A in your board initialization
- * code.  Something like:
- *     at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0);
- *
- */
-
-/* #define DEBUG */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include <mach/at32ap700x.h>
-#include <mach/portmux.h>
-
-#include "../codecs/wm8510.h"
-#include "atmel-pcm.h"
-#include "atmel_ssc_dai.h"
-
-
-/*-------------------------------------------------------------------------*\
- * constants
-\*-------------------------------------------------------------------------*/
-#define MCLK_PIN               GPIO_PIN_PA(30)
-#define MCLK_PERIPH            GPIO_PERIPH_A
-
-
-/*-------------------------------------------------------------------------*\
- * data types
-\*-------------------------------------------------------------------------*/
-/* SSC clocking data */
-struct ssc_clock_data {
-       /* CMR div */
-       unsigned int cmr_div;
-
-       /* Frame period (as needed by xCMR.PERIOD) */
-       unsigned int period;
-
-       /* The SSC clock rate these settings where calculated for */
-       unsigned long ssc_rate;
-};
-
-
-/*-------------------------------------------------------------------------*\
- * module data
-\*-------------------------------------------------------------------------*/
-static struct clk *_gclk0;
-static struct clk *_pll0;
-
-#define CODEC_CLK (_gclk0)
-
-
-/*-------------------------------------------------------------------------*\
- * Sound SOC operations
-\*-------------------------------------------------------------------------*/
-#if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
-static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock(
-       struct snd_pcm_hw_params *params,
-       struct snd_soc_dai *cpu_dai)
-{
-       struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai);
-       struct ssc_device *ssc = ssc_p->ssc;
-       struct ssc_clock_data cd;
-       unsigned int rate, width_bits, channels;
-       unsigned int bitrate, ssc_div;
-       unsigned actual_rate;
-
-
-       /*
-        * Figure out required bitrate
-        */
-       rate = params_rate(params);
-       channels = params_channels(params);
-       width_bits = snd_pcm_format_physical_width(params_format(params));
-       bitrate = rate * width_bits * channels;
-
-
-       /*
-        * Figure out required SSC divider and period for required bitrate
-        */
-       cd.ssc_rate = clk_get_rate(ssc->clk);
-       ssc_div = cd.ssc_rate / bitrate;
-       cd.cmr_div = ssc_div / 2;
-       if (ssc_div & 1) {
-               /* round cmr_div up */
-               cd.cmr_div++;
-       }
-       cd.period = width_bits - 1;
-
-
-       /*
-        * Find actual rate, compare to requested rate
-        */
-       actual_rate = (cd.ssc_rate / (cd.cmr_div * 2)) / (2 * (cd.period + 1));
-       pr_debug("playpaq_wm8510: Request rate = %u, actual rate = %u\n",
-                rate, actual_rate);
-
-
-       return cd;
-}
-#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
-
-
-
-static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream,
-                                   struct snd_pcm_hw_params *params)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai);
-       struct ssc_device *ssc = ssc_p->ssc;
-       unsigned int pll_out = 0, bclk = 0, mclk_div = 0;
-       int ret;
-
-
-       /* Due to difficulties with getting the correct clocks from the AT32's
-        * PLL0, we're going to let the CODEC be in charge of all the clocks
-        */
-#if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
-       const unsigned int fmt = (SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBM_CFM);
-#else
-       struct ssc_clock_data cd;
-       const unsigned int fmt = (SND_SOC_DAIFMT_I2S |
-                                 SND_SOC_DAIFMT_NB_NF |
-                                 SND_SOC_DAIFMT_CBS_CFS);
-#endif
-
-       if (ssc == NULL) {
-               pr_warning("playpaq_wm8510_hw_params: ssc is NULL!\n");
-               return -EINVAL;
-       }
-
-
-       /*
-        * Figure out PLL and BCLK dividers for WM8510
-        */
-       switch (params_rate(params)) {
-       case 48000:
-               pll_out = 24576000;
-               mclk_div = WM8510_MCLKDIV_2;
-               bclk = WM8510_BCLKDIV_8;
-               break;
-
-       case 44100:
-               pll_out = 22579200;
-               mclk_div = WM8510_MCLKDIV_2;
-               bclk = WM8510_BCLKDIV_8;
-               break;
-
-       case 22050:
-               pll_out = 22579200;
-               mclk_div = WM8510_MCLKDIV_4;
-               bclk = WM8510_BCLKDIV_8;
-               break;
-
-       case 16000:
-               pll_out = 24576000;
-               mclk_div = WM8510_MCLKDIV_6;
-               bclk = WM8510_BCLKDIV_8;
-               break;
-
-       case 11025:
-               pll_out = 22579200;
-               mclk_div = WM8510_MCLKDIV_8;
-               bclk = WM8510_BCLKDIV_8;
-               break;
-
-       case 8000:
-               pll_out = 24576000;
-               mclk_div = WM8510_MCLKDIV_12;
-               bclk = WM8510_BCLKDIV_8;
-               break;
-
-       default:
-               pr_warning("playpaq_wm8510: Unsupported sample rate %d\n",
-                          params_rate(params));
-               return -EINVAL;
-       }
-
-
-       /*
-        * set CPU and CODEC DAI configuration
-        */
-       ret = snd_soc_dai_set_fmt(codec_dai, fmt);
-       if (ret < 0) {
-               pr_warning("playpaq_wm8510: "
-                          "Failed to set CODEC DAI format (%d)\n",
-                          ret);
-               return ret;
-       }
-       ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
-       if (ret < 0) {
-               pr_warning("playpaq_wm8510: "
-                          "Failed to set CPU DAI format (%d)\n",
-                          ret);
-               return ret;
-       }
-
-
-       /*
-        * Set CPU clock configuration
-        */
-#if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
-       cd = playpaq_wm8510_calc_ssc_clock(params, cpu_dai);
-       pr_debug("playpaq_wm8510: cmr_div = %d, period = %d\n",
-                cd.cmr_div, cd.period);
-       ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_CMR_DIV, cd.cmr_div);
-       if (ret < 0) {
-               pr_warning("playpaq_wm8510: Failed to set CPU CMR_DIV (%d)\n",
-                          ret);
-               return ret;
-       }
-       ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_TCMR_PERIOD,
-                                         cd.period);
-       if (ret < 0) {
-               pr_warning("playpaq_wm8510: "
-                          "Failed to set CPU transmit period (%d)\n",
-                          ret);
-               return ret;
-       }
-#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
-
-
-       /*
-        * Set CODEC clock configuration
-        */
-       pr_debug("playpaq_wm8510: "
-                "pll_in = %ld, pll_out = %u, bclk = %x, mclk = %x\n",
-                clk_get_rate(CODEC_CLK), pll_out, bclk, mclk_div);
-
-
-#if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
-       ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_BCLKDIV, bclk);
-       if (ret < 0) {
-               pr_warning
-                   ("playpaq_wm8510: Failed to set CODEC DAI BCLKDIV (%d)\n",
-                    ret);
-               return ret;
-       }
-#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
-
-
-       ret = snd_soc_dai_set_pll(codec_dai, 0, 0,
-                                        clk_get_rate(CODEC_CLK), pll_out);
-       if (ret < 0) {
-               pr_warning("playpaq_wm8510: Failed to set CODEC DAI PLL (%d)\n",
-                          ret);
-               return ret;
-       }
-
-
-       ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_MCLKDIV, mclk_div);
-       if (ret < 0) {
-               pr_warning("playpaq_wm8510: Failed to set CODEC MCLKDIV (%d)\n",
-                          ret);
-               return ret;
-       }
-
-
-       return 0;
-}
-
-
-
-static struct snd_soc_ops playpaq_wm8510_ops = {
-       .hw_params = playpaq_wm8510_hw_params,
-};
-
-
-
-static const struct snd_soc_dapm_widget playpaq_dapm_widgets[] = {
-       SND_SOC_DAPM_MIC("Int Mic", NULL),
-       SND_SOC_DAPM_SPK("Ext Spk", NULL),
-};
-
-
-
-static const struct snd_soc_dapm_route intercon[] = {
-       /* speaker connected to SPKOUT */
-       {"Ext Spk", NULL, "SPKOUTP"},
-       {"Ext Spk", NULL, "SPKOUTN"},
-
-       {"Mic Bias", NULL, "Int Mic"},
-       {"MICN", NULL, "Mic Bias"},
-       {"MICP", NULL, "Mic Bias"},
-};
-
-
-
-static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd)
-{
-       struct snd_soc_codec *codec = rtd->codec;
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-       int i;
-
-       /*
-        * Add DAPM widgets
-        */
-       for (i = 0; i < ARRAY_SIZE(playpaq_dapm_widgets); i++)
-               snd_soc_dapm_new_control(dapm, &playpaq_dapm_widgets[i]);
-
-
-
-       /*
-        * Setup audio path interconnects
-        */
-       snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
-
-
-
-       /* always connected pins */
-       snd_soc_dapm_enable_pin(dapm, "Int Mic");
-       snd_soc_dapm_enable_pin(dapm, "Ext Spk");
-
-
-
-       /* Make CSB show PLL rate */
-       snd_soc_dai_set_clkdiv(rtd->codec_dai, WM8510_OPCLKDIV,
-                                      WM8510_OPCLKDIV_1 | 4);
-
-       return 0;
-}
-
-
-
-static struct snd_soc_dai_link playpaq_wm8510_dai = {
-       .name = "WM8510",
-       .stream_name = "WM8510 PCM",
-       .cpu_dai_name= "atmel-ssc-dai.0",
-       .platform_name = "atmel-pcm-audio",
-       .codec_name = "wm8510-codec.0-0x1a",
-       .codec_dai_name = "wm8510-hifi",
-       .init = playpaq_wm8510_init,
-       .ops = &playpaq_wm8510_ops,
-};
-
-
-
-static struct snd_soc_card snd_soc_playpaq = {
-       .name = "LRS_PlayPaq_WM8510",
-       .dai_link = &playpaq_wm8510_dai,
-       .num_links = 1,
-};
-
-static struct platform_device *playpaq_snd_device;
-
-
-static int __init playpaq_asoc_init(void)
-{
-       int ret = 0;
-
-       /*
-        * Configure MCLK for WM8510
-        */
-       _gclk0 = clk_get(NULL, "gclk0");
-       if (IS_ERR(_gclk0)) {
-               _gclk0 = NULL;
-               ret = PTR_ERR(_gclk0);
-               goto err_gclk0;
-       }
-       _pll0 = clk_get(NULL, "pll0");
-       if (IS_ERR(_pll0)) {
-               _pll0 = NULL;
-               ret = PTR_ERR(_pll0);
-               goto err_pll0;
-       }
-       ret = clk_set_parent(_gclk0, _pll0);
-       if (ret) {
-               pr_warning("snd-soc-playpaq: "
-                          "Failed to set PLL0 as parent for DAC clock\n");
-               goto err_set_clk;
-       }
-       clk_set_rate(CODEC_CLK, 12000000);
-       clk_enable(CODEC_CLK);
-
-#if defined CONFIG_AT32_ENHANCED_PORTMUX
-       at32_select_periph(MCLK_PIN, MCLK_PERIPH, 0);
-#endif
-
-
-       /*
-        * Create and register platform device
-        */
-       playpaq_snd_device = platform_device_alloc("soc-audio", 0);
-       if (playpaq_snd_device == NULL) {
-               ret = -ENOMEM;
-               goto err_device_alloc;
-       }
-
-       platform_set_drvdata(playpaq_snd_device, &snd_soc_playpaq);
-
-       ret = platform_device_add(playpaq_snd_device);
-       if (ret) {
-               pr_warning("playpaq_wm8510: platform_device_add failed (%d)\n",
-                          ret);
-               goto err_device_add;
-       }
-
-       return 0;
-
-
-err_device_add:
-       if (playpaq_snd_device != NULL) {
-               platform_device_put(playpaq_snd_device);
-               playpaq_snd_device = NULL;
-       }
-err_device_alloc:
-err_set_clk:
-       if (_pll0 != NULL) {
-               clk_put(_pll0);
-               _pll0 = NULL;
-       }
-err_pll0:
-       if (_gclk0 != NULL) {
-               clk_put(_gclk0);
-               _gclk0 = NULL;
-       }
-       return ret;
-}
-
-
-static void __exit playpaq_asoc_exit(void)
-{
-       if (_gclk0 != NULL) {
-               clk_put(_gclk0);
-               _gclk0 = NULL;
-       }
-       if (_pll0 != NULL) {
-               clk_put(_pll0);
-               _pll0 = NULL;
-       }
-
-#if defined CONFIG_AT32_ENHANCED_PORTMUX
-       at32_free_pin(MCLK_PIN);
-#endif
-
-       platform_device_unregister(playpaq_snd_device);
-       playpaq_snd_device = NULL;
-}
-
-module_init(playpaq_asoc_init);
-module_exit(playpaq_asoc_exit);
-
-MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
-MODULE_DESCRIPTION("ASoC machine driver for LRS PlayPaq");
-MODULE_LICENSE("GPL");
index 726bd65..7771934 100644 (file)
@@ -195,7 +195,7 @@ static int alchemy_ac97c_startup(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_dai_ops alchemy_ac97c_ops = {
+static const struct snd_soc_dai_ops alchemy_ac97c_ops = {
        .startup                = alchemy_ac97c_startup,
 };
 
index 127477a..094a207 100644 (file)
@@ -57,18 +57,7 @@ static struct platform_driver db1000_audio_driver = {
        .remove         = __devexit_p(db1000_audio_remove),
 };
 
-static int __init db1000_audio_load(void)
-{
-       return platform_driver_register(&db1000_audio_driver);
-}
-
-static void __exit db1000_audio_unload(void)
-{
-       platform_driver_unregister(&db1000_audio_driver);
-}
-
-module_init(db1000_audio_load);
-module_exit(db1000_audio_unload);
+module_platform_driver(db1000_audio_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("DB1000/DB1500/DB1100 ASoC audio");
index 289312c..8073333 100644 (file)
@@ -133,18 +133,7 @@ static struct platform_driver db1200_audio_driver = {
        .remove         = __devexit_p(db1200_audio_remove),
 };
 
-static int __init db1200_audio_load(void)
-{
-       return platform_driver_register(&db1200_audio_driver);
-}
-
-static void __exit db1200_audio_unload(void)
-{
-       platform_driver_unregister(&db1200_audio_driver);
-}
-
-module_init(db1200_audio_load);
-module_exit(db1200_audio_unload);
+module_platform_driver(db1200_audio_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("DB1200 ASoC audio support");
index d7d04e2..09699de 100644 (file)
@@ -384,18 +384,7 @@ static struct platform_driver au1xpsc_pcm_driver = {
        .remove         = __devexit_p(au1xpsc_pcm_drvremove),
 };
 
-static int __init au1xpsc_audio_dbdma_load(void)
-{
-       return platform_driver_register(&au1xpsc_pcm_driver);
-}
-
-static void __exit au1xpsc_audio_dbdma_unload(void)
-{
-       platform_driver_unregister(&au1xpsc_pcm_driver);
-}
-
-module_init(au1xpsc_audio_dbdma_load);
-module_exit(au1xpsc_audio_dbdma_unload);
+module_platform_driver(au1xpsc_pcm_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver");
index 177f713..dc4dae4 100644 (file)
@@ -359,18 +359,7 @@ static struct platform_driver alchemy_pcmdma_driver = {
        .remove         = __devexit_p(alchemy_pcm_drvremove),
 };
 
-static int __init alchemy_pcmdma_load(void)
-{
-       return platform_driver_register(&alchemy_pcmdma_driver);
-}
-
-static void __exit alchemy_pcmdma_unload(void)
-{
-       platform_driver_unregister(&alchemy_pcmdma_driver);
-}
-
-module_init(alchemy_pcmdma_load);
-module_exit(alchemy_pcmdma_unload);
+module_platform_driver(alchemy_pcmdma_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Au1000/Au1500/Au1100 Audio DMA driver");
index 6bcf48f..cb53ad8 100644 (file)
@@ -331,18 +331,7 @@ static struct platform_driver au1xi2s_driver = {
        .remove         = __devexit_p(au1xi2s_drvremove),
 };
 
-static int __init au1xi2s_load(void)
-{
-       return platform_driver_register(&au1xi2s_driver);
-}
-
-static void __exit au1xi2s_unload(void)
-{
-       platform_driver_unregister(&au1xi2s_driver);
-}
-
-module_init(au1xi2s_load);
-module_exit(au1xi2s_unload);
+module_platform_driver(au1xi2s_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Au1000/1500/1100 I2S ASoC driver");
index 0c6acd5..87daf45 100644 (file)
@@ -337,7 +337,7 @@ static int au1xpsc_ac97_probe(struct snd_soc_dai *dai)
        return au1xpsc_ac97_workdata ? 0 : -ENODEV;
 }
 
-static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
+static const struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
        .startup        = au1xpsc_ac97_startup,
        .trigger        = au1xpsc_ac97_trigger,
        .hw_params      = au1xpsc_ac97_hw_params,
index e03c5ce..5c1dc8a 100644 (file)
@@ -265,7 +265,7 @@ static int au1xpsc_i2s_startup(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
+static const struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
        .startup        = au1xpsc_i2s_startup,
        .trigger        = au1xpsc_i2s_trigger,
        .hw_params      = au1xpsc_i2s_hw_params,
@@ -435,18 +435,7 @@ static struct platform_driver au1xpsc_i2s_driver = {
        .remove         = __devexit_p(au1xpsc_i2s_drvremove),
 };
 
-static int __init au1xpsc_i2s_load(void)
-{
-       return platform_driver_register(&au1xpsc_i2s_driver);
-}
-
-static void __exit au1xpsc_i2s_unload(void)
-{
-       platform_driver_unregister(&au1xpsc_i2s_driver);
-}
-
-module_init(au1xpsc_i2s_load);
-module_exit(au1xpsc_i2s_unload);
+module_platform_driver(au1xpsc_i2s_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Au12x0/Au1550 PSC I2S ALSA ASoC audio driver");
index 56815c1..fcff583 100644 (file)
@@ -475,17 +475,7 @@ static struct platform_driver bf5xx_pcm_driver = {
        .remove = __devexit_p(bf5xx_soc_platform_remove),
 };
 
-static int __init snd_bf5xx_pcm_init(void)
-{
-       return platform_driver_register(&bf5xx_pcm_driver);
-}
-module_init(snd_bf5xx_pcm_init);
-
-static void __exit snd_bf5xx_pcm_exit(void)
-{
-       platform_driver_unregister(&bf5xx_pcm_driver);
-}
-module_exit(snd_bf5xx_pcm_exit);
+module_platform_driver(bf5xx_pcm_driver);
 
 MODULE_AUTHOR("Cliff Cai");
 MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module");
index 6d21625..f4e9dc4 100644 (file)
@@ -375,18 +375,7 @@ static struct platform_driver asoc_bfin_ac97_driver = {
        .remove = __devexit_p(asoc_bfin_ac97_remove),
 };
 
-static int __init bfin_ac97_init(void)
-{
-       return platform_driver_register(&asoc_bfin_ac97_driver);
-}
-module_init(bfin_ac97_init);
-
-static void __exit bfin_ac97_exit(void)
-{
-       platform_driver_unregister(&asoc_bfin_ac97_driver);
-}
-module_exit(bfin_ac97_exit);
-
+module_platform_driver(asoc_bfin_ac97_driver);
 
 MODULE_AUTHOR("Roy Huang");
 MODULE_DESCRIPTION("AC97 driver for ADI Blackfin");
index 7565e15..6ec3d41 100644 (file)
@@ -314,17 +314,7 @@ static struct platform_driver bfin_i2s_pcm_driver = {
        .remove = __devexit_p(bfin_i2s_soc_platform_remove),
 };
 
-static int __init snd_bfin_i2s_pcm_init(void)
-{
-       return platform_driver_register(&bfin_i2s_pcm_driver);
-}
-module_init(snd_bfin_i2s_pcm_init);
-
-static void __exit snd_bfin_i2s_pcm_exit(void)
-{
-       platform_driver_unregister(&bfin_i2s_pcm_driver);
-}
-module_exit(snd_bfin_i2s_pcm_exit);
+module_platform_driver(bfin_i2s_pcm_driver);
 
 MODULE_AUTHOR("Cliff Cai");
 MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module");
index 00cc3e0..4dccf03 100644 (file)
@@ -223,7 +223,7 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
         SNDRV_PCM_FMTBIT_S24_LE | \
         SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
+static const struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
        .shutdown       = bf5xx_i2s_shutdown,
        .hw_params      = bf5xx_i2s_hw_params,
        .set_fmt        = bf5xx_i2s_set_dai_fmt,
@@ -288,18 +288,7 @@ static struct platform_driver bfin_i2s_driver = {
        },
 };
 
-static int __init bfin_i2s_init(void)
-{
-       return platform_driver_register(&bfin_i2s_driver);
-}
-
-static void __exit bfin_i2s_exit(void)
-{
-       platform_driver_unregister(&bfin_i2s_driver);
-}
-
-module_init(bfin_i2s_init);
-module_exit(bfin_i2s_exit);
+module_platform_driver(bfin_i2s_driver);
 
 /* Module information */
 MODULE_AUTHOR("Cliff Cai");
index c95cc03..4406f9a 100644 (file)
@@ -339,17 +339,7 @@ static struct platform_driver bfin_tdm_driver = {
        .remove = __devexit_p(bf5xx_soc_platform_remove),
 };
 
-static int __init snd_bfin_tdm_init(void)
-{
-       return platform_driver_register(&bfin_tdm_driver);
-}
-module_init(snd_bfin_tdm_init);
-
-static void __exit snd_bfin_tdm_exit(void)
-{
-       platform_driver_unregister(&bfin_tdm_driver);
-}
-module_exit(snd_bfin_tdm_exit);
+module_platform_driver(bfin_tdm_driver);
 
 MODULE_AUTHOR("Barry Song");
 MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module");
index a822d1e..594f882 100644 (file)
@@ -226,7 +226,7 @@ static int bf5xx_tdm_resume(struct snd_soc_dai *dai)
 #define bf5xx_tdm_resume       NULL
 #endif
 
-static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
+static const struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
        .hw_params      = bf5xx_tdm_hw_params,
        .set_fmt        = bf5xx_tdm_set_dai_fmt,
        .shutdown       = bf5xx_tdm_shutdown,
@@ -314,17 +314,7 @@ static struct platform_driver bfin_tdm_driver = {
        },
 };
 
-static int __init bfin_tdm_init(void)
-{
-       return platform_driver_register(&bfin_tdm_driver);
-}
-module_init(bfin_tdm_init);
-
-static void __exit bfin_tdm_exit(void)
-{
-       platform_driver_unregister(&bfin_tdm_driver);
-}
-module_exit(bfin_tdm_exit);
+module_platform_driver(bfin_tdm_driver);
 
 /* Module information */
 MODULE_AUTHOR("Barry Song");
index 8df2a3b..85ed39a 100644 (file)
@@ -184,17 +184,7 @@ static struct platform_driver bfin_eval_adau1373_driver = {
        .remove = __devexit_p(bfin_eval_adau1373_remove),
 };
 
-static int __init bfin_eval_adau1373_init(void)
-{
-       return platform_driver_register(&bfin_eval_adau1373_driver);
-}
-module_init(bfin_eval_adau1373_init);
-
-static void __exit bfin_eval_adau1373_exit(void)
-{
-       platform_driver_unregister(&bfin_eval_adau1373_driver);
-}
-module_exit(bfin_eval_adau1373_exit);
+module_platform_driver(bfin_eval_adau1373_driver);
 
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("ALSA SoC bfin adau1373 driver");
index e5550ac..1a88fe9 100644 (file)
@@ -121,17 +121,7 @@ static struct platform_driver bfin_eval_adau1701_driver = {
        .remove = __devexit_p(bfin_eval_adau1701_remove),
 };
 
-static int __init bfin_eval_adau1701_init(void)
-{
-       return platform_driver_register(&bfin_eval_adau1701_driver);
-}
-module_init(bfin_eval_adau1701_init);
-
-static void __exit bfin_eval_adau1701_exit(void)
-{
-       platform_driver_unregister(&bfin_eval_adau1701_driver);
-}
-module_exit(bfin_eval_adau1701_exit);
+module_platform_driver(bfin_eval_adau1701_driver);
 
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("ALSA SoC bfin ADAU1701 driver");
index 897cfa6..0bc995f 100644 (file)
@@ -157,17 +157,7 @@ static struct platform_driver bfin_eval_adav80x_driver = {
        .id_table = bfin_eval_adav80x_ids,
 };
 
-static int __init bfin_eval_adav80x_init(void)
-{
-       return platform_driver_register(&bfin_eval_adav80x_driver);
-}
-module_init(bfin_eval_adav80x_init);
-
-static void __exit bfin_eval_adav80x_exit(void)
-{
-       platform_driver_unregister(&bfin_eval_adav80x_driver);
-}
-module_exit(bfin_eval_adav80x_exit);
+module_platform_driver(bfin_eval_adav80x_driver);
 
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("ALSA SoC bfin adav80x driver");
index 5ca122e..2d39123 100644 (file)
@@ -1198,14 +1198,14 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-static struct snd_soc_dai_ops pm860x_pcm_dai_ops = {
+static const struct snd_soc_dai_ops pm860x_pcm_dai_ops = {
        .digital_mute   = pm860x_digital_mute,
        .hw_params      = pm860x_pcm_hw_params,
        .set_fmt        = pm860x_pcm_set_dai_fmt,
        .set_sysclk     = pm860x_set_dai_sysclk,
 };
 
-static struct snd_soc_dai_ops pm860x_i2s_dai_ops = {
+static const struct snd_soc_dai_ops pm860x_i2s_dai_ops = {
        .digital_mute   = pm860x_digital_mute,
        .hw_params      = pm860x_i2s_hw_params,
        .set_fmt        = pm860x_i2s_set_dai_fmt,
@@ -1481,17 +1481,7 @@ static struct platform_driver pm860x_codec_driver = {
        .remove = __devexit_p(pm860x_codec_remove),
 };
 
-static __init int pm860x_init(void)
-{
-       return platform_driver_register(&pm860x_codec_driver);
-}
-module_init(pm860x_init);
-
-static __exit void pm860x_exit(void)
-{
-       platform_driver_unregister(&pm860x_codec_driver);
-}
-module_exit(pm860x_exit);
+module_platform_driver(pm860x_codec_driver);
 
 MODULE_DESCRIPTION("ASoC 88PM860x driver");
 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
index 4584514..7c205e7 100644 (file)
@@ -26,14 +26,16 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_AK4642 if I2C
        select SND_SOC_AK4671 if I2C
        select SND_SOC_ALC5623 if I2C
+       select SND_SOC_ALC5632 if I2C
        select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
        select SND_SOC_CS42L51 if I2C
+       select SND_SOC_CS42L73 if I2C
        select SND_SOC_CS4270 if I2C
        select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
        select SND_SOC_CX20442
        select SND_SOC_DA7210 if I2C
        select SND_SOC_DFBMCS320
-       select SND_SOC_JZ4740_CODEC if SOC_JZ4740
+       select SND_SOC_JZ4740_CODEC
        select SND_SOC_LM4857 if I2C
        select SND_SOC_MAX98088 if I2C
        select SND_SOC_MAX98095 if I2C
@@ -139,7 +141,7 @@ config SND_SOC_AD73311
        tristate
 
 config SND_SOC_ADAU1701
-       select SIGMA
+       select SND_SOC_SIGMADSP
        tristate
 
 config SND_SOC_ADAU1373
@@ -168,6 +170,8 @@ config SND_SOC_AK4671
 
 config SND_SOC_ALC5623
        tristate
+config SND_SOC_ALC5632
+       tristate
 
 config SND_SOC_CQ0093VC
        tristate
@@ -175,6 +179,9 @@ config SND_SOC_CQ0093VC
 config SND_SOC_CS42L51
        tristate
 
+config SND_SOC_CS42L73
+       tristate
+
 # Cirrus Logic CS4270 Codec
 config SND_SOC_CS4270
        tristate
@@ -227,6 +234,10 @@ config SND_SOC_RT5631
 config SND_SOC_SGTL5000
        tristate
 
+config SND_SOC_SIGMADSP
+       tristate
+       select CRC32
+
 config SND_SOC_SN95031
        tristate
 
@@ -278,6 +289,9 @@ config SND_SOC_WL1273
 config SND_SOC_WM1250_EV1
        tristate
 
+config SND_SOC_WM2000
+       tristate
+
 config SND_SOC_WM5100
        tristate
 
@@ -395,6 +409,9 @@ config SND_SOC_WM8996
 config SND_SOC_WM9081
        tristate
 
+config SND_SOC_WM9090
+       tristate
+
 config SND_SOC_WM9705
        tristate
 
@@ -413,9 +430,3 @@ config SND_SOC_MAX9877
 
 config SND_SOC_TPA6130A2
        tristate
-
-config SND_SOC_WM2000
-       tristate
-
-config SND_SOC_WM9090
-       tristate
index a2c7842..9aa6e66 100644 (file)
@@ -15,13 +15,16 @@ snd-soc-ak4642-objs := ak4642.o
 snd-soc-ak4671-objs := ak4671.o
 snd-soc-cq93vc-objs := cq93vc.o
 snd-soc-cs42l51-objs := cs42l51.o
+snd-soc-cs42l73-objs := cs42l73.o
 snd-soc-cs4270-objs := cs4270.o
 snd-soc-cs4271-objs := cs4271.o
 snd-soc-cx20442-objs := cx20442.o
 snd-soc-da7210-objs := da7210.o
 snd-soc-dfbmcs320-objs := dfbmcs320.o
 snd-soc-dmic-objs := dmic.o
+snd-soc-jz4740-codec-objs := jz4740.o
 snd-soc-l3-objs := l3.o
+snd-soc-lm4857-objs := lm4857.o
 snd-soc-max98088-objs := max98088.o
 snd-soc-max98095-objs := max98095.o
 snd-soc-max9850-objs := max9850.o
@@ -29,6 +32,8 @@ snd-soc-pcm3008-objs := pcm3008.o
 snd-soc-rt5631-objs := rt5631.o
 snd-soc-sgtl5000-objs := sgtl5000.o
 snd-soc-alc5623-objs := alc5623.o
+snd-soc-alc5632-objs := alc5632.o
+snd-soc-sigmadsp-objs := sigmadsp.o
 snd-soc-sn95031-objs := sn95031.o
 snd-soc-spdif-objs := spdif_transciever.o
 snd-soc-ssm2602-objs := ssm2602.o
@@ -45,6 +50,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-wm2000-objs := wm2000.o
 snd-soc-wm5100-objs := wm5100.o wm5100-tables.o
 snd-soc-wm8350-objs := wm8350.o
 snd-soc-wm8400-objs := wm8400.o
@@ -84,18 +90,15 @@ snd-soc-wm8993-objs := wm8993.o
 snd-soc-wm8994-objs := wm8994.o wm8994-tables.o wm8958-dsp2.o
 snd-soc-wm8995-objs := wm8995.o
 snd-soc-wm9081-objs := wm9081.o
+snd-soc-wm9090-objs := wm9090.o
 snd-soc-wm9705-objs := wm9705.o
 snd-soc-wm9712-objs := wm9712.o
 snd-soc-wm9713-objs := wm9713.o
 snd-soc-wm-hubs-objs := wm_hubs.o
-snd-soc-jz4740-codec-objs := jz4740.o
 
 # Amp
-snd-soc-lm4857-objs := lm4857.o
 snd-soc-max9877-objs := max9877.o
 snd-soc-tpa6130a2-objs := tpa6130a2.o
-snd-soc-wm2000-objs := wm2000.o
-snd-soc-wm9090-objs := wm9090.o
 
 obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o
 obj-$(CONFIG_SND_SOC_AC97_CODEC)       += snd-soc-ac97.o
@@ -113,8 +116,10 @@ obj-$(CONFIG_SND_SOC_AK4641)       += snd-soc-ak4641.o
 obj-$(CONFIG_SND_SOC_AK4642)   += snd-soc-ak4642.o
 obj-$(CONFIG_SND_SOC_AK4671)   += snd-soc-ak4671.o
 obj-$(CONFIG_SND_SOC_ALC5623)    += snd-soc-alc5623.o
+obj-$(CONFIG_SND_SOC_ALC5632)  += snd-soc-alc5632.o
 obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
 obj-$(CONFIG_SND_SOC_CS42L51)  += snd-soc-cs42l51.o
+obj-$(CONFIG_SND_SOC_CS42L73)  += snd-soc-cs42l73.o
 obj-$(CONFIG_SND_SOC_CS4270)   += snd-soc-cs4270.o
 obj-$(CONFIG_SND_SOC_CS4271)   += snd-soc-cs4271.o
 obj-$(CONFIG_SND_SOC_CX20442)  += snd-soc-cx20442.o
@@ -122,6 +127,7 @@ obj-$(CONFIG_SND_SOC_DA7210)        += snd-soc-da7210.o
 obj-$(CONFIG_SND_SOC_DFBMCS320)        += snd-soc-dfbmcs320.o
 obj-$(CONFIG_SND_SOC_DMIC)     += snd-soc-dmic.o
 obj-$(CONFIG_SND_SOC_L3)       += snd-soc-l3.o
+obj-$(CONFIG_SND_SOC_LM4857)   += snd-soc-lm4857.o
 obj-$(CONFIG_SND_SOC_JZ4740_CODEC)     += snd-soc-jz4740-codec.o
 obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
 obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
@@ -129,6 +135,7 @@ obj-$(CONFIG_SND_SOC_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_SIGMADSP) += snd-soc-sigmadsp.o
 obj-$(CONFIG_SND_SOC_SN95031)  +=snd-soc-sn95031.o
 obj-$(CONFIG_SND_SOC_SPDIF)    += snd-soc-spdif.o
 obj-$(CONFIG_SND_SOC_SSM2602)  += snd-soc-ssm2602.o
@@ -145,6 +152,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_WM2000)   += snd-soc-wm2000.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
@@ -184,14 +192,12 @@ obj-$(CONFIG_SND_SOC_WM8993)      += snd-soc-wm8993.o
 obj-$(CONFIG_SND_SOC_WM8994)   += snd-soc-wm8994.o
 obj-$(CONFIG_SND_SOC_WM8995)   += snd-soc-wm8995.o
 obj-$(CONFIG_SND_SOC_WM9081)   += snd-soc-wm9081.o
+obj-$(CONFIG_SND_SOC_WM9090)   += snd-soc-wm9090.o
 obj-$(CONFIG_SND_SOC_WM9705)   += snd-soc-wm9705.o
 obj-$(CONFIG_SND_SOC_WM9712)   += snd-soc-wm9712.o
 obj-$(CONFIG_SND_SOC_WM9713)   += snd-soc-wm9713.o
 obj-$(CONFIG_SND_SOC_WM_HUBS)  += snd-soc-wm-hubs.o
 
 # Amp
-obj-$(CONFIG_SND_SOC_LM4857)   += snd-soc-lm4857.o
 obj-$(CONFIG_SND_SOC_MAX9877)  += snd-soc-max9877.o
 obj-$(CONFIG_SND_SOC_TPA6130A2)        += snd-soc-tpa6130a2.o
-obj-$(CONFIG_SND_SOC_WM2000)   += snd-soc-wm2000.o
-obj-$(CONFIG_SND_SOC_WM9090)   += snd-soc-wm9090.o
index e715186..1bbad4c 100644 (file)
@@ -39,7 +39,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
                SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
                SNDRV_PCM_RATE_48000)
 
-static struct snd_soc_dai_ops ac97_dai_ops = {
+static const struct snd_soc_dai_ops ac97_dai_ops = {
        .prepare        = ac97_prepare,
 };
 
@@ -99,7 +99,7 @@ static int ac97_soc_remove(struct snd_soc_codec *codec)
 }
 
 #ifdef CONFIG_PM
-static int ac97_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
+static int ac97_soc_suspend(struct snd_soc_codec *codec)
 {
        snd_ac97_suspend(codec->ac97);
 
@@ -148,17 +148,7 @@ static struct platform_driver ac97_codec_driver = {
        .remove = __devexit_p(ac97_remove),
 };
 
-static int __init ac97_init(void)
-{
-       return platform_driver_register(&ac97_codec_driver);
-}
-module_init(ac97_init);
-
-static void __exit ac97_exit(void)
-{
-       platform_driver_unregister(&ac97_codec_driver);
-}
-module_exit(ac97_exit);
+module_platform_driver(ac97_codec_driver);
 
 MODULE_DESCRIPTION("Soc Generic AC97 driver");
 MODULE_AUTHOR("Liam Girdwood");
index 4e5c572..919322d 100644 (file)
@@ -189,7 +189,7 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_dai_ops ad1836_dai_ops = {
+static const struct snd_soc_dai_ops ad1836_dai_ops = {
        .hw_params = ad1836_hw_params,
        .set_fmt = ad1836_set_dai_fmt,
 };
@@ -223,7 +223,7 @@ static struct snd_soc_dai_driver ad183x_dais[] = {
 };
 
 #ifdef CONFIG_PM
-static int ad1836_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int ad1836_suspend(struct snd_soc_codec *codec)
 {
        /* reset clock control mode */
        return snd_soc_update_bits(codec, AD1836_ADC_CTRL2,
index 444747f..dd7be0d 100644 (file)
@@ -34,7 +34,7 @@
 
 #define AD1836_ADC_CTRL2               13
 #define AD1836_ADC_WORD_LEN_MASK       0x30
-#define AD1836_ADC_WORD_OFFSET         5
+#define AD1836_ADC_WORD_OFFSET         4
 #define AD1836_ADC_SERFMT_MASK         (7 << 6)
 #define AD1836_ADC_SERFMT_PCK256       (0x4 << 6)
 #define AD1836_ADC_SERFMT_PCK128       (0x5 << 6)
index 1206021..c1b7d92 100644 (file)
@@ -30,21 +30,23 @@ struct ad193x_priv {
 /*
  * AD193X volume/mute/de-emphasis etc. controls
  */
-static const char *ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
+static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
 
 static const struct soc_enum ad193x_deemp_enum =
        SOC_ENUM_SINGLE(AD193X_DAC_CTRL2, 1, 4, ad193x_deemp);
 
+static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0);
+
 static const struct snd_kcontrol_new ad193x_snd_controls[] = {
        /* DAC volume control */
-       SOC_DOUBLE_R("DAC1 Volume", AD193X_DAC_L1_VOL,
-                       AD193X_DAC_R1_VOL, 0, 0xFF, 1),
-       SOC_DOUBLE_R("DAC2 Volume", AD193X_DAC_L2_VOL,
-                       AD193X_DAC_R2_VOL, 0, 0xFF, 1),
-       SOC_DOUBLE_R("DAC3 Volume", AD193X_DAC_L3_VOL,
-                       AD193X_DAC_R3_VOL, 0, 0xFF, 1),
-       SOC_DOUBLE_R("DAC4 Volume", AD193X_DAC_L4_VOL,
-                       AD193X_DAC_R4_VOL, 0, 0xFF, 1),
+       SOC_DOUBLE_R_TLV("DAC1 Volume", AD193X_DAC_L1_VOL,
+                       AD193X_DAC_R1_VOL, 0, 0xFF, 1, adau193x_tlv),
+       SOC_DOUBLE_R_TLV("DAC2 Volume", AD193X_DAC_L2_VOL,
+                       AD193X_DAC_R2_VOL, 0, 0xFF, 1, adau193x_tlv),
+       SOC_DOUBLE_R_TLV("DAC3 Volume", AD193X_DAC_L3_VOL,
+                       AD193X_DAC_R3_VOL, 0, 0xFF, 1, adau193x_tlv),
+       SOC_DOUBLE_R_TLV("DAC4 Volume", AD193X_DAC_L4_VOL,
+                       AD193X_DAC_R4_VOL, 0, 0xFF, 1, adau193x_tlv),
 
        /* ADC switch control */
        SOC_DOUBLE("ADC1 Switch", AD193X_ADC_CTRL0, AD193X_ADCL1_MUTE,
@@ -75,6 +77,7 @@ static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = {
        SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
        SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0),
        SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("SYSCLK", AD193X_PLL_CLK_CTRL0, 7, 0, NULL, 0),
        SND_SOC_DAPM_OUTPUT("DAC1OUT"),
        SND_SOC_DAPM_OUTPUT("DAC2OUT"),
        SND_SOC_DAPM_OUTPUT("DAC3OUT"),
@@ -84,16 +87,17 @@ static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = {
 };
 
 static const struct snd_soc_dapm_route audio_paths[] = {
-       { "DAC", NULL, "PLL_PWR" },
-       { "ADC", NULL, "PLL_PWR" },
+       { "DAC", NULL, "SYSCLK" },
+       { "ADC", NULL, "SYSCLK" },
        { "DAC", NULL, "ADC_PWR" },
        { "ADC", NULL, "ADC_PWR" },
-       { "DAC1OUT", "DAC1 Switch", "DAC" },
-       { "DAC2OUT", "DAC2 Switch", "DAC" },
-       { "DAC3OUT", "DAC3 Switch", "DAC" },
-       { "DAC4OUT", "DAC4 Switch", "DAC" },
-       { "ADC", "ADC1 Switch", "ADC1IN" },
-       { "ADC", "ADC2 Switch", "ADC2IN" },
+       { "DAC1OUT", NULL, "DAC" },
+       { "DAC2OUT", NULL, "DAC" },
+       { "DAC3OUT", NULL, "DAC" },
+       { "DAC4OUT", NULL, "DAC" },
+       { "ADC", NULL, "ADC1IN" },
+       { "ADC", NULL, "ADC2IN" },
+       { "SYSCLK", NULL, "PLL_PWR" },
 };
 
 /*
@@ -102,14 +106,14 @@ static 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;
+       struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(dai->codec);
 
        if (mute)
-               snd_soc_update_bits(codec, AD193X_DAC_CTRL2,
+               regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2,
                                    AD193X_DAC_MASTER_MUTE,
                                    AD193X_DAC_MASTER_MUTE);
        else
-               snd_soc_update_bits(codec, AD193X_DAC_CTRL2,
+               regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2,
                                    AD193X_DAC_MASTER_MUTE, 0);
 
        return 0;
@@ -118,36 +122,30 @@ static int ad193x_mute(struct snd_soc_dai *dai, int mute)
 static int ad193x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
                               unsigned int rx_mask, int slots, int width)
 {
-       struct snd_soc_codec *codec = dai->codec;
-       int dac_reg = snd_soc_read(codec, AD193X_DAC_CTRL1);
-       int adc_reg = snd_soc_read(codec, AD193X_ADC_CTRL2);
-
-       dac_reg &= ~AD193X_DAC_CHAN_MASK;
-       adc_reg &= ~AD193X_ADC_CHAN_MASK;
+       struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(dai->codec);
+       unsigned int channels;
 
        switch (slots) {
        case 2:
-               dac_reg |= AD193X_DAC_2_CHANNELS << AD193X_DAC_CHAN_SHFT;
-               adc_reg |= AD193X_ADC_2_CHANNELS << AD193X_ADC_CHAN_SHFT;
+               channels = AD193X_2_CHANNELS;
                break;
        case 4:
-               dac_reg |= AD193X_DAC_4_CHANNELS << AD193X_DAC_CHAN_SHFT;
-               adc_reg |= AD193X_ADC_4_CHANNELS << AD193X_ADC_CHAN_SHFT;
+               channels = AD193X_4_CHANNELS;
                break;
        case 8:
-               dac_reg |= AD193X_DAC_8_CHANNELS << AD193X_DAC_CHAN_SHFT;
-               adc_reg |= AD193X_ADC_8_CHANNELS << AD193X_ADC_CHAN_SHFT;
+               channels = AD193X_8_CHANNELS;
                break;
        case 16:
-               dac_reg |= AD193X_DAC_16_CHANNELS << AD193X_DAC_CHAN_SHFT;
-               adc_reg |= AD193X_ADC_16_CHANNELS << AD193X_ADC_CHAN_SHFT;
+               channels = AD193X_16_CHANNELS;
                break;
        default:
                return -EINVAL;
        }
 
-       snd_soc_write(codec, AD193X_DAC_CTRL1, dac_reg);
-       snd_soc_write(codec, AD193X_ADC_CTRL2, adc_reg);
+       regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1,
+               AD193X_DAC_CHAN_MASK, channels << AD193X_DAC_CHAN_SHFT);
+       regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2,
+               AD193X_ADC_CHAN_MASK, channels << AD193X_ADC_CHAN_SHFT);
 
        return 0;
 }
@@ -155,24 +153,20 @@ static int ad193x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
 static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
                unsigned int fmt)
 {
-       struct snd_soc_codec *codec = codec_dai->codec;
-       int adc_reg1, adc_reg2, dac_reg;
-
-       adc_reg1 = snd_soc_read(codec, AD193X_ADC_CTRL1);
-       adc_reg2 = snd_soc_read(codec, AD193X_ADC_CTRL2);
-       dac_reg = snd_soc_read(codec, AD193X_DAC_CTRL1);
+       struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec_dai->codec);
+       unsigned int adc_serfmt = 0;
+       unsigned int adc_fmt = 0;
+       unsigned int dac_fmt = 0;
 
        /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
         * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
         */
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
-               adc_reg1 &= ~AD193X_ADC_SERFMT_MASK;
-               adc_reg1 |= AD193X_ADC_SERFMT_TDM;
+               adc_serfmt |= AD193X_ADC_SERFMT_TDM;
                break;
        case SND_SOC_DAIFMT_DSP_A:
-               adc_reg1 &= ~AD193X_ADC_SERFMT_MASK;
-               adc_reg1 |= AD193X_ADC_SERFMT_AUX;
+               adc_serfmt |= AD193X_ADC_SERFMT_AUX;
                break;
        default:
                return -EINVAL;
@@ -180,29 +174,20 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
 
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */
-               adc_reg2 &= ~AD193X_ADC_LEFT_HIGH;
-               adc_reg2 &= ~AD193X_ADC_BCLK_INV;
-               dac_reg &= ~AD193X_DAC_LEFT_HIGH;
-               dac_reg &= ~AD193X_DAC_BCLK_INV;
                break;
        case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */
-               adc_reg2 |= AD193X_ADC_LEFT_HIGH;
-               adc_reg2 &= ~AD193X_ADC_BCLK_INV;
-               dac_reg |= AD193X_DAC_LEFT_HIGH;
-               dac_reg &= ~AD193X_DAC_BCLK_INV;
+               adc_fmt |= AD193X_ADC_LEFT_HIGH;
+               dac_fmt |= AD193X_DAC_LEFT_HIGH;
                break;
        case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */
-               adc_reg2 &= ~AD193X_ADC_LEFT_HIGH;
-               adc_reg2 |= AD193X_ADC_BCLK_INV;
-               dac_reg &= ~AD193X_DAC_LEFT_HIGH;
-               dac_reg |= AD193X_DAC_BCLK_INV;
+               adc_fmt |= AD193X_ADC_BCLK_INV;
+               dac_fmt |= AD193X_DAC_BCLK_INV;
                break;
-
        case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */
-               adc_reg2 |= AD193X_ADC_LEFT_HIGH;
-               adc_reg2 |= AD193X_ADC_BCLK_INV;
-               dac_reg |= AD193X_DAC_LEFT_HIGH;
-               dac_reg |= AD193X_DAC_BCLK_INV;
+               adc_fmt |= AD193X_ADC_LEFT_HIGH;
+               adc_fmt |= AD193X_ADC_BCLK_INV;
+               dac_fmt |= AD193X_DAC_LEFT_HIGH;
+               dac_fmt |= AD193X_DAC_BCLK_INV;
                break;
        default:
                return -EINVAL;
@@ -210,36 +195,31 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
 
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
-               adc_reg2 |= AD193X_ADC_LCR_MASTER;
-               adc_reg2 |= AD193X_ADC_BCLK_MASTER;
-               dac_reg |= AD193X_DAC_LCR_MASTER;
-               dac_reg |= AD193X_DAC_BCLK_MASTER;
+               adc_fmt |= AD193X_ADC_LCR_MASTER;
+               adc_fmt |= AD193X_ADC_BCLK_MASTER;
+               dac_fmt |= AD193X_DAC_LCR_MASTER;
+               dac_fmt |= AD193X_DAC_BCLK_MASTER;
                break;
        case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */
-               adc_reg2 |= AD193X_ADC_LCR_MASTER;
-               adc_reg2 &= ~AD193X_ADC_BCLK_MASTER;
-               dac_reg |= AD193X_DAC_LCR_MASTER;
-               dac_reg &= ~AD193X_DAC_BCLK_MASTER;
+               adc_fmt |= AD193X_ADC_LCR_MASTER;
+               dac_fmt |= AD193X_DAC_LCR_MASTER;
                break;
        case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */
-               adc_reg2 &= ~AD193X_ADC_LCR_MASTER;
-               adc_reg2 |= AD193X_ADC_BCLK_MASTER;
-               dac_reg &= ~AD193X_DAC_LCR_MASTER;
-               dac_reg |= AD193X_DAC_BCLK_MASTER;
+               adc_fmt |= AD193X_ADC_BCLK_MASTER;
+               dac_fmt |= AD193X_DAC_BCLK_MASTER;
                break;
        case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */
-               adc_reg2 &= ~AD193X_ADC_LCR_MASTER;
-               adc_reg2 &= ~AD193X_ADC_BCLK_MASTER;
-               dac_reg &= ~AD193X_DAC_LCR_MASTER;
-               dac_reg &= ~AD193X_DAC_BCLK_MASTER;
                break;
        default:
                return -EINVAL;
        }
 
-       snd_soc_write(codec, AD193X_ADC_CTRL1, adc_reg1);
-       snd_soc_write(codec, AD193X_ADC_CTRL2, adc_reg2);
-       snd_soc_write(codec, AD193X_DAC_CTRL1, dac_reg);
+       regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1,
+               AD193X_ADC_SERFMT_MASK, adc_serfmt);
+       regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2,
+               AD193X_ADC_FMT_MASK, adc_fmt);
+       regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1,
+               AD193X_DAC_FMT_MASK, dac_fmt);
 
        return 0;
 }
@@ -299,20 +279,20 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
                break;
        }
 
-       snd_soc_update_bits(codec, AD193X_PLL_CLK_CTRL0,
+       regmap_update_bits(ad193x->regmap, AD193X_PLL_CLK_CTRL0,
                            AD193X_PLL_INPUT_MASK, master_rate);
 
-       snd_soc_update_bits(codec, AD193X_DAC_CTRL2,
+       regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2,
                            AD193X_DAC_WORD_LEN_MASK,
                            word_len << AD193X_DAC_WORD_LEN_SHFT);
 
-       snd_soc_update_bits(codec, AD193X_ADC_CTRL1,
+       regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1,
                            AD193X_ADC_WORD_LEN_MASK, word_len);
 
        return 0;
 }
 
-static struct snd_soc_dai_ops ad193x_dai_ops = {
+static const struct snd_soc_dai_ops ad193x_dai_ops = {
        .hw_params = ad193x_hw_params,
        .digital_mute = ad193x_mute,
        .set_tdm_slot = ad193x_set_tdm_slot,
@@ -345,7 +325,6 @@ static struct snd_soc_dai_driver ad193x_dai = {
 static int ad193x_probe(struct snd_soc_codec *codec)
 {
        struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
        int ret;
 
        codec->control_data = ad193x->regmap;
@@ -358,32 +337,37 @@ static int ad193x_probe(struct snd_soc_codec *codec)
        /* default setting for ad193x */
 
        /* unmute dac channels */
-       snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0);
+       regmap_write(ad193x->regmap, AD193X_DAC_CHNL_MUTE, 0x0);
        /* de-emphasis: 48kHz, powedown dac */
-       snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A);
+       regmap_write(ad193x->regmap, AD193X_DAC_CTRL2, 0x1A);
        /* powerdown dac, dac in tdm mode */
-       snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41);
+       regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x41);
        /* high-pass filter enable */
-       snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3);
+       regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3);
        /* sata delay=1, adc aux mode */
-       snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43);
+       regmap_write(ad193x->regmap, AD193X_ADC_CTRL1, 0x43);
        /* pll input: mclki/xi */
-       snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
-       snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04);
-
-       snd_soc_add_controls(codec, ad193x_snd_controls,
-                            ARRAY_SIZE(ad193x_snd_controls));
-       snd_soc_dapm_new_controls(dapm, ad193x_dapm_widgets,
-                                 ARRAY_SIZE(ad193x_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths));
+       regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
+       regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04);
 
        return ret;
 }
 
 static struct snd_soc_codec_driver soc_codec_dev_ad193x = {
        .probe =        ad193x_probe,
+       .controls = ad193x_snd_controls,
+       .num_controls = ARRAY_SIZE(ad193x_snd_controls),
+       .dapm_widgets = ad193x_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(ad193x_dapm_widgets),
+       .dapm_routes = audio_paths,
+       .num_dapm_routes = ARRAY_SIZE(audio_paths),
 };
 
+static bool adau193x_reg_volatile(struct device *dev, unsigned int reg)
+{
+       return false;
+}
+
 #if defined(CONFIG_SPI_MASTER)
 
 static const struct regmap_config ad193x_spi_regmap_config = {
@@ -391,6 +375,9 @@ static const struct regmap_config ad193x_spi_regmap_config = {
        .reg_bits = 16,
        .read_flag_mask = 0x09,
        .write_flag_mask = 0x08,
+
+       .max_register = AD193X_NUM_REGS - 1,
+       .volatile_reg = adau193x_reg_volatile,
 };
 
 static int __devinit ad193x_spi_probe(struct spi_device *spi)
@@ -450,6 +437,9 @@ static struct spi_driver ad193x_spi_driver = {
 static const struct regmap_config ad193x_i2c_regmap_config = {
        .val_bits = 8,
        .reg_bits = 8,
+
+       .max_register = AD193X_NUM_REGS - 1,
+       .volatile_reg = adau193x_reg_volatile,
 };
 
 static const struct i2c_device_id ad193x_id[] = {
index 1507eaa..4733880 100644 (file)
 #define AD193X_DAC_SERFMT_STEREO       (0 << 6)
 #define AD193X_DAC_SERFMT_TDM          (1 << 6)
 #define AD193X_DAC_CTRL1        0x03
-#define AD193X_DAC_2_CHANNELS   0
-#define AD193X_DAC_4_CHANNELS   1
-#define AD193X_DAC_8_CHANNELS   2
-#define AD193X_DAC_16_CHANNELS  3
 #define AD193X_DAC_CHAN_SHFT    1
 #define AD193X_DAC_CHAN_MASK    (3 << AD193X_DAC_CHAN_SHFT)
 #define AD193X_DAC_LCR_MASTER   (1 << 4)
 #define AD193X_DAC_BCLK_MASTER  (1 << 5)
 #define AD193X_DAC_LEFT_HIGH    (1 << 3)
 #define AD193X_DAC_BCLK_INV     (1 << 7)
+#define AD193X_DAC_FMT_MASK    (AD193X_DAC_LCR_MASTER | \
+       AD193X_DAC_BCLK_MASTER | AD193X_DAC_LEFT_HIGH | AD193X_DAC_BCLK_INV)
 #define AD193X_DAC_CTRL2        0x04
 #define AD193X_DAC_WORD_LEN_SHFT        3
 #define AD193X_DAC_WORD_LEN_MASK        0x18
 #define AD193X_ADC_SERFMT_AUX          (2 << 5)
 #define AD193X_ADC_WORD_LEN_MASK       0x3
 #define AD193X_ADC_CTRL2        0x10
-#define AD193X_ADC_2_CHANNELS   0
-#define AD193X_ADC_4_CHANNELS   1
-#define AD193X_ADC_8_CHANNELS   2
-#define AD193X_ADC_16_CHANNELS  3
 #define AD193X_ADC_CHAN_SHFT    4
 #define AD193X_ADC_CHAN_MASK    (3 << AD193X_ADC_CHAN_SHFT)
 #define AD193X_ADC_LCR_MASTER   (1 << 3)
 #define AD193X_ADC_BCLK_MASTER  (1 << 6)
 #define AD193X_ADC_LEFT_HIGH    (1 << 2)
 #define AD193X_ADC_BCLK_INV     (1 << 1)
+#define AD193X_ADC_FMT_MASK    (AD193X_ADC_LCR_MASTER | \
+       AD193X_ADC_BCLK_MASTER | AD193X_ADC_LEFT_HIGH | AD193X_ADC_BCLK_INV)
+
+#define AD193X_2_CHANNELS   0
+#define AD193X_4_CHANNELS   1
+#define AD193X_8_CHANNELS   2
+#define AD193X_16_CHANNELS  3
 
 #define AD193X_NUM_REGS          17
 
index e3931cc..9bba7f8 100644 (file)
@@ -277,17 +277,7 @@ static struct platform_driver ad1980_codec_driver = {
        .remove = __devexit_p(ad1980_remove),
 };
 
-static int __init ad1980_init(void)
-{
-       return platform_driver_register(&ad1980_codec_driver);
-}
-module_init(ad1980_init);
-
-static void __exit ad1980_exit(void)
-{
-       platform_driver_unregister(&ad1980_codec_driver);
-}
-module_exit(ad1980_exit);
+module_platform_driver(ad1980_codec_driver);
 
 MODULE_DESCRIPTION("ASoC ad1980 driver (Obsolete)");
 MODULE_AUTHOR("Roy Huang, Cliff Cai");
index 8d793e9..ee7a68d 100644 (file)
@@ -63,17 +63,7 @@ static struct platform_driver ad73311_codec_driver = {
        .remove = __devexit_p(ad73311_remove),
 };
 
-static int __init ad73311_init(void)
-{
-       return platform_driver_register(&ad73311_codec_driver);
-}
-module_init(ad73311_init);
-
-static void __exit ad73311_exit(void)
-{
-       platform_driver_unregister(&ad73311_codec_driver);
-}
-module_exit(ad73311_exit);
+module_platform_driver(ad73311_codec_driver);
 
 MODULE_DESCRIPTION("ASoC ad73311 driver");
 MODULE_AUTHOR("Cliff Cai ");
index 1ccf8dd..637b114 100644 (file)
@@ -245,7 +245,7 @@ static const char *adau1373_bass_hpf_cutoff_text[] = {
 };
 
 static const unsigned int adau1373_bass_tlv[] = {
-       TLV_DB_RANGE_HEAD(4),
+       TLV_DB_RANGE_HEAD(3),
        0, 2, TLV_DB_SCALE_ITEM(-600, 600, 1),
        3, 4, TLV_DB_SCALE_ITEM(950, 250, 0),
        5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0),
@@ -1321,7 +1321,7 @@ static int adau1373_remove(struct snd_soc_codec *codec)
        return 0;
 }
 
-static int adau1373_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int adau1373_suspend(struct snd_soc_codec *codec)
 {
        return adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF);
 }
index 8b7e1c5..6a6af56 100644 (file)
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/delay.h>
-#include <linux/sigma.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 
+#include "sigmadsp.h"
 #include "adau1701.h"
 
 #define ADAU1701_DSPCTRL       0x1c
index f9f0894..ebd7b37 100644 (file)
@@ -798,7 +798,7 @@ static int adav80x_probe(struct snd_soc_codec *codec)
        return adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 }
 
-static int adav80x_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int adav80x_suspend(struct snd_soc_codec *codec)
 {
        return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF);
 }
index 9082e0f..8103b93 100644 (file)
@@ -58,17 +58,7 @@ static struct platform_driver ads117x_codec_driver = {
        .remove = __devexit_p(ads117x_remove),
 };
 
-static int __init ads117x_init(void)
-{
-       return platform_driver_register(&ads117x_codec_driver);
-}
-module_init(ads117x_init);
-
-static void __exit ads117x_exit(void)
-{
-       platform_driver_unregister(&ads117x_codec_driver);
-}
-module_exit(ads117x_exit);
+module_platform_driver(ads117x_codec_driver);
 
 MODULE_DESCRIPTION("ASoC ads117x driver");
 MODULE_AUTHOR("Graeme Gregory");
index d3b29dc..152420c 100644 (file)
@@ -170,7 +170,7 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
        return ak4104_spi_write(codec, AK4104_REG_CHN_STATUS(3), val);
 }
 
-static struct snd_soc_dai_ops ak4101_dai_ops = {
+static const struct snd_soc_dai_ops ak4101_dai_ops = {
        .hw_params = ak4104_hw_params,
        .set_fmt = ak4104_set_dai_fmt,
 };
index 95d782d..96296fd 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -331,7 +330,7 @@ static int ak4535_set_bias_level(struct snd_soc_codec *codec,
                SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
                SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
 
-static struct snd_soc_dai_ops ak4535_dai_ops = {
+static const struct snd_soc_dai_ops ak4535_dai_ops = {
        .hw_params      = ak4535_hw_params,
        .set_fmt        = ak4535_set_dai_fmt,
        .digital_mute   = ak4535_mute,
@@ -355,7 +354,7 @@ static struct snd_soc_dai_driver ak4535_dai = {
        .ops = &ak4535_dai_ops,
 };
 
-static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int ak4535_suspend(struct snd_soc_codec *codec)
 {
        ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
index 7783858..9018470 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/gpio.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -442,14 +441,14 @@ static int ak4641_set_bias_level(struct snd_soc_codec *codec,
                         SNDRV_PCM_RATE_16000)
 #define AK4641_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
 
-static struct snd_soc_dai_ops ak4641_i2s_dai_ops = {
+static const struct snd_soc_dai_ops ak4641_i2s_dai_ops = {
        .hw_params    = ak4641_i2s_hw_params,
        .set_fmt      = ak4641_i2s_set_dai_fmt,
        .digital_mute = ak4641_mute,
        .set_sysclk   = ak4641_set_dai_sysclk,
 };
 
-static struct snd_soc_dai_ops ak4641_pcm_dai_ops = {
+static const struct snd_soc_dai_ops ak4641_pcm_dai_ops = {
        .hw_params    = NULL, /* rates are controlled by BT chip */
        .set_fmt      = ak4641_pcm_set_dai_fmt,
        .digital_mute = ak4641_mute,
@@ -499,7 +498,7 @@ static struct snd_soc_dai_driver ak4641_dai[] = {
 },
 };
 
-static int ak4641_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int ak4641_suspend(struct snd_soc_codec *codec)
 {
        ak4641_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
index 12c1bde..9b4ee6c 100644 (file)
  * This is very simple driver.
  * It can use headphone output / stereo input only
  *
- * AK4642 is not tested.
+ * AK4642 is tested.
  * AK4643 is tested.
+ * AK4648 is tested.
  */
 
 #include <linux/delay.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <sound/soc.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
 
-#define AK4642_VERSION "0.0.1"
-
 #define PW_MGMT1       0x00
 #define PW_MGMT2       0x01
 #define SG_SL1         0x02
@@ -71,8 +69,6 @@
 #define HP_MS          0x23
 #define SPK_MS         0x24
 
-#define AK4642_CACHEREGNUM     0x25
-
 /* PW_MGMT1*/
 #define PMVCM          (1 << 6) /* VCOM Power Management */
 #define PMMIN          (1 << 5) /* MIN Input Power Management */
@@ -150,8 +146,52 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = {
 
        SOC_DOUBLE_R_TLV("Digital Playback Volume", L_DVC, R_DVC,
                         0, 0xFF, 1, out_tlv),
+
+       SOC_SINGLE("Headphone Switch", PW_MGMT2, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new ak4642_hpout_mixer_controls[] = {
+       SOC_DAPM_SINGLE("DACH", MD_CTL4, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new ak4642_lout_mixer_controls[] = {
+       SOC_DAPM_SINGLE("DACL", SG_SL1, 4, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = {
+
+       /* Outputs */
+       SND_SOC_DAPM_OUTPUT("HPOUTL"),
+       SND_SOC_DAPM_OUTPUT("HPOUTR"),
+       SND_SOC_DAPM_OUTPUT("LINEOUT"),
+
+       SND_SOC_DAPM_MIXER("HPOUTL Mixer", PW_MGMT2, 5, 0,
+                          &ak4642_hpout_mixer_controls[0],
+                          ARRAY_SIZE(ak4642_hpout_mixer_controls)),
+
+       SND_SOC_DAPM_MIXER("HPOUTR Mixer", PW_MGMT2, 4, 0,
+                          &ak4642_hpout_mixer_controls[0],
+                          ARRAY_SIZE(ak4642_hpout_mixer_controls)),
+
+       SND_SOC_DAPM_MIXER("LINEOUT Mixer", PW_MGMT1, 3, 0,
+                          &ak4642_lout_mixer_controls[0],
+                          ARRAY_SIZE(ak4642_lout_mixer_controls)),
+
+       /* DAC */
+       SND_SOC_DAPM_DAC("DAC", "HiFi Playback", PW_MGMT1, 2, 0),
 };
 
+static const struct snd_soc_dapm_route ak4642_intercon[] = {
+
+       /* Outputs */
+       {"HPOUTL", NULL, "HPOUTL Mixer"},
+       {"HPOUTR", NULL, "HPOUTR Mixer"},
+       {"LINEOUT", NULL, "LINEOUT Mixer"},
+
+       {"HPOUTL Mixer", "DACH", "DAC"},
+       {"HPOUTR Mixer", "DACH", "DAC"},
+       {"LINEOUT Mixer", "DACL", "DAC"},
+};
 
 /* codec private data */
 struct ak4642_priv {
@@ -162,7 +202,7 @@ struct ak4642_priv {
 /*
  * ak4642 register cache
  */
-static const u8 ak4642_reg[AK4642_CACHEREGNUM] = {
+static const u8 ak4642_reg[] = {
        0x00, 0x00, 0x01, 0x00,
        0x02, 0x00, 0x00, 0x00,
        0xe1, 0xe1, 0x18, 0x00,
@@ -175,6 +215,19 @@ static const u8 ak4642_reg[AK4642_CACHEREGNUM] = {
        0x00,
 };
 
+static const u8 ak4648_reg[] = {
+       0x00, 0x00, 0x01, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0xe1, 0xe1, 0x18, 0x00,
+       0xe1, 0x18, 0x11, 0xb8,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x88, 0x88, 0x08,
+};
+
 static int ak4642_dai_startup(struct snd_pcm_substream *substream,
                              struct snd_soc_dai *dai)
 {
@@ -192,14 +245,8 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
                 * This operation came from example code of
                 * "ASAHI KASEI AK4642" (japanese) manual p97.
                 */
-               snd_soc_update_bits(codec, MD_CTL4, DACH, DACH);
-               snd_soc_update_bits(codec, MD_CTL3, BST1, BST1);
                snd_soc_write(codec, L_IVC, 0x91); /* volume */
                snd_soc_write(codec, R_IVC, 0x91); /* volume */
-               snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMMIN | PMDAC,
-                                                    PMVCM | PMMIN | PMDAC);
-               snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP);
-               snd_soc_update_bits(codec, PW_MGMT2, HPMTN,     HPMTN);
        } else {
                /*
                 * start stereo input
@@ -217,8 +264,7 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
                snd_soc_write(codec, SG_SL1, PMMP | MGAIN0);
                snd_soc_write(codec, TIMER, ZTM(0x3) | WTM(0x3));
                snd_soc_write(codec, ALC_CTL1, ALC | LMTH0);
-               snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMADL,
-                                                    PMVCM | PMADL);
+               snd_soc_update_bits(codec, PW_MGMT1, PMADL, PMADL);
                snd_soc_update_bits(codec, PW_MGMT3, PMADR, PMADR);
        }
 
@@ -232,12 +278,6 @@ static void ak4642_dai_shutdown(struct snd_pcm_substream *substream,
        struct snd_soc_codec *codec = dai->codec;
 
        if (is_play) {
-               /* stop headphone output */
-               snd_soc_update_bits(codec, PW_MGMT2, HPMTN,     0);
-               snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, 0);
-               snd_soc_update_bits(codec, PW_MGMT1, PMMIN | PMDAC, 0);
-               snd_soc_update_bits(codec, MD_CTL3, BST1, 0);
-               snd_soc_update_bits(codec, MD_CTL4, DACH, 0);
        } else {
                /* stop stereo input */
                snd_soc_update_bits(codec, PW_MGMT1, PMADL, 0);
@@ -376,7 +416,23 @@ static int ak4642_dai_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_dai_ops ak4642_dai_ops = {
+static int ak4642_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
+{
+       switch (level) {
+       case SND_SOC_BIAS_OFF:
+               snd_soc_write(codec, PW_MGMT1, 0x00);
+               break;
+       default:
+               snd_soc_update_bits(codec, PW_MGMT1, PMVCM, PMVCM);
+               break;
+       }
+       codec->dapm.bias_level = level;
+
+       return 0;
+}
+
+static const struct snd_soc_dai_ops ak4642_dai_ops = {
        .startup        = ak4642_dai_startup,
        .shutdown       = ak4642_dai_shutdown,
        .set_sysclk     = ak4642_dai_set_sysclk,
@@ -414,8 +470,6 @@ 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);
-
        ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4642->control_type);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -425,15 +479,43 @@ static int ak4642_probe(struct snd_soc_codec *codec)
        snd_soc_add_controls(codec, ak4642_snd_controls,
                             ARRAY_SIZE(ak4642_snd_controls));
 
+       ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       return 0;
+}
+
+static int ak4642_remove(struct snd_soc_codec *codec)
+{
+       ak4642_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
 static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
        .probe                  = ak4642_probe,
+       .remove                 = ak4642_remove,
+       .resume                 = ak4642_resume,
+       .set_bias_level         = ak4642_set_bias_level,
+       .reg_cache_default      = ak4642_reg,                   /* ak4642 reg */
+       .reg_cache_size         = ARRAY_SIZE(ak4642_reg),       /* ak4642 reg */
+       .reg_word_size          = sizeof(u8),
+       .dapm_widgets           = ak4642_dapm_widgets,
+       .num_dapm_widgets       = ARRAY_SIZE(ak4642_dapm_widgets),
+       .dapm_routes            = ak4642_intercon,
+       .num_dapm_routes        = ARRAY_SIZE(ak4642_intercon),
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_ak4648 = {
+       .probe                  = ak4642_probe,
+       .remove                 = ak4642_remove,
        .resume                 = ak4642_resume,
-       .reg_cache_size         = ARRAY_SIZE(ak4642_reg),
+       .set_bias_level         = ak4642_set_bias_level,
+       .reg_cache_default      = ak4648_reg,                   /* ak4648 reg */
+       .reg_cache_size         = ARRAY_SIZE(ak4648_reg),       /* ak4648 reg */
        .reg_word_size          = sizeof(u8),
-       .reg_cache_default      = ak4642_reg,
+       .dapm_widgets           = ak4642_dapm_widgets,
+       .num_dapm_widgets       = ARRAY_SIZE(ak4642_dapm_widgets),
+       .dapm_routes            = ak4642_intercon,
+       .num_dapm_routes        = ARRAY_SIZE(ak4642_intercon),
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
@@ -451,7 +533,8 @@ static __devinit int ak4642_i2c_probe(struct i2c_client *i2c,
        ak4642->control_type = SND_SOC_I2C;
 
        ret =  snd_soc_register_codec(&i2c->dev,
-                       &soc_codec_dev_ak4642, &ak4642_dai, 1);
+                               (struct snd_soc_codec_driver *)id->driver_data,
+                               &ak4642_dai, 1);
        if (ret < 0)
                kfree(ak4642);
        return ret;
@@ -465,8 +548,9 @@ static __devexit int ak4642_i2c_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ak4642_i2c_id[] = {
-       { "ak4642", 0 },
-       { "ak4643", 0 },
+       { "ak4642", (kernel_ulong_t)&soc_codec_dev_ak4642 },
+       { "ak4643", (kernel_ulong_t)&soc_codec_dev_ak4642 },
+       { "ak4648", (kernel_ulong_t)&soc_codec_dev_ak4648 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);
index de9ff66..4f5c69f 100644 (file)
@@ -594,7 +594,7 @@ static int ak4671_set_bias_level(struct snd_soc_codec *codec,
 
 #define AK4671_FORMATS         SNDRV_PCM_FMTBIT_S16_LE
 
-static struct snd_soc_dai_ops ak4671_dai_ops = {
+static const struct snd_soc_dai_ops ak4671_dai_ops = {
        .hw_params      = ak4671_hw_params,
        .set_sysclk     = ak4671_set_dai_sysclk,
        .set_fmt        = ak4671_set_dai_fmt,
index 984b14b..da97f02 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
-#include <linux/platform_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -839,7 +838,7 @@ static int alc5623_set_bias_level(struct snd_soc_codec *codec,
                        | SNDRV_PCM_FMTBIT_S24_LE \
                        | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops alc5623_dai_ops = {
+static const struct snd_soc_dai_ops alc5623_dai_ops = {
                .hw_params = alc5623_pcm_hw_params,
                .digital_mute = alc5623_mute,
                .set_fmt = alc5623_set_dai_fmt,
@@ -869,7 +868,7 @@ static struct snd_soc_dai_driver alc5623_dai = {
        .ops = &alc5623_dai_ops,
 };
 
-static int alc5623_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
+static int alc5623_suspend(struct snd_soc_codec *codec)
 {
        alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c
new file mode 100644 (file)
index 0000000..08613c7
--- /dev/null
@@ -0,0 +1,1159 @@
+/*
+* alc5632.c  --  ALC5632 ALSA SoC Audio Codec
+*
+* Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
+*
+* Authors:  Leon Romanovsky <leon@leon.nu>
+*           Andrey Danin <danindrey@mail.ru>
+*           Ilya Petrov <ilya.muromec@gmail.com>
+*           Marc Dietrich <marvin24@gmx.de>
+*
+* Based on alc5623.c by Arnaud Patard
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+
+#include "alc5632.h"
+
+/*
+ * ALC5632 register cache
+ */
+static struct reg_default  alc5632_reg_defaults[] = {
+       {   2, 0x8080 },        /* R2   - Speaker Output Volume */
+       {   4, 0x8080 },        /* R4   - Headphone Output Volume */
+       {   6, 0x8080 },        /* R6   - AUXOUT Volume */
+       {   8, 0xC800 },        /* R8   - Phone Input */
+       {  10, 0xE808 },        /* R10  - LINE_IN Volume */
+       {  12, 0x1010 },        /* R12  - STEREO DAC Input Volume */
+       {  14, 0x0808 },        /* R14  - MIC Input Volume */
+       {  16, 0xEE0F },        /* R16  - Stereo DAC and MIC Routing Control */
+       {  18, 0xCBCB },        /* R18  - ADC Record Gain */
+       {  20, 0x7F7F },        /* R20  - ADC Record Mixer Control */
+       {  24, 0xE010 },        /* R24  - Voice DAC Volume */
+       {  28, 0x8008 },        /* R28  - Output Mixer Control */
+       {  34, 0x0000 },        /* R34  - Microphone Control */
+       {  36, 0x00C0 },    /* R36  - Codec Digital MIC/Digital Boost
+                                                  Control */
+       {  46, 0x0000 },        /* R46  - Stereo DAC/Voice DAC/Stereo ADC
+                                                  Function Select */
+       {  52, 0x8000 },        /* R52  - Main Serial Data Port Control
+                                                  (Stereo I2S) */
+       {  54, 0x0000 },        /* R54  - Extend Serial Data Port Control
+                                                  (VoDAC_I2S/PCM) */
+       {  58, 0x0000 },        /* R58  - Power Management Addition 1 */
+       {  60, 0x0000 },        /* R60  - Power Management Addition 2 */
+       {  62, 0x8000 },        /* R62  - Power Management Addition 3 */
+       {  64, 0x0C0A },        /* R64  - General Purpose Control Register 1 */
+       {  66, 0x0000 },        /* R66  - General Purpose Control Register 2 */
+       {  68, 0x0000 },        /* R68  - PLL1 Control */
+       {  70, 0x0000 },        /* R70  - PLL2 Control */
+       {  76, 0xBE3E },        /* R76  - GPIO Pin Configuration */
+       {  78, 0xBE3E },        /* R78  - GPIO Pin Polarity */
+       {  80, 0x0000 },        /* R80  - GPIO Pin Sticky */
+       {  82, 0x0000 },        /* R82  - GPIO Pin Wake Up */
+       {  86, 0x0000 },        /* R86  - Pin Sharing */
+       {  90, 0x0009 },        /* R90  - Soft Volume Control Setting */
+       {  92, 0x0000 },        /* R92  - GPIO_Output Pin Control */
+       {  94, 0x3000 },        /* R94  - MISC Control */
+       {  96, 0x3075 },        /* R96  - Stereo DAC Clock Control_1 */
+       {  98, 0x1010 },        /* R98  - Stereo DAC Clock Control_2 */
+       { 100, 0x3110 },        /* R100 - VoDAC_PCM Clock Control_1 */
+       { 104, 0x0553 },        /* R104 - Pseudo Stereo and Spatial Effect
+                                                  Block Control */
+       { 106, 0x0000 },        /* R106 - Private Register Address */
+};
+
+/* codec private data */
+struct alc5632_priv {
+       struct regmap *regmap;
+       u8 id;
+       unsigned int sysclk;
+};
+
+static bool alc5632_volatile_register(struct device *dev,
+                                                       unsigned int reg)
+{
+       switch (reg) {
+       case ALC5632_RESET:
+       case ALC5632_PWR_DOWN_CTRL_STATUS:
+       case ALC5632_GPIO_PIN_STATUS:
+       case ALC5632_OVER_CURR_STATUS:
+       case ALC5632_HID_CTRL_DATA:
+       case ALC5632_EQ_CTRL:
+       case ALC5632_VENDOR_ID1:
+       case ALC5632_VENDOR_ID2:
+               return true;
+
+       default:
+               break;
+       }
+
+       return false;
+}
+
+static inline int alc5632_reset(struct regmap *map)
+{
+       return regmap_write(map, ALC5632_RESET, 0x59B4);
+}
+
+static int amp_mixer_event(struct snd_soc_dapm_widget *w,
+       struct snd_kcontrol *kcontrol, int event)
+{
+       /* to power-on/off class-d amp generators/speaker */
+       /* need to write to 'index-46h' register :        */
+       /* so write index num (here 0x46) to reg 0x6a     */
+       /* and then 0xffff/0 to reg 0x6c                  */
+       snd_soc_write(w->codec, ALC5632_HID_CTRL_INDEX, 0x46);
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               snd_soc_write(w->codec, ALC5632_HID_CTRL_DATA, 0xFFFF);
+               break;
+       case SND_SOC_DAPM_POST_PMD:
+               snd_soc_write(w->codec, ALC5632_HID_CTRL_DATA, 0);
+               break;
+       }
+
+       return 0;
+}
+
+/*
+ * ALC5632 Controls
+ */
+
+/* -34.5db min scale, 1.5db steps, no mute */
+static const DECLARE_TLV_DB_SCALE(vol_tlv, -3450, 150, 0);
+/* -46.5db min scale, 1.5db steps, no mute */
+static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0);
+/* -16.5db min scale, 1.5db steps, no mute */
+static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0);
+static const unsigned int boost_tlv[] = {
+       TLV_DB_RANGE_HEAD(3),
+       0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+       1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
+       2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
+};
+/* 0db min scale, 6 db steps, no mute */
+static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0);
+/* 0db min scalem 0.75db steps, no mute */
+static const DECLARE_TLV_DB_SCALE(vdac_tlv, -3525, 075, 0);
+
+static const struct snd_kcontrol_new alc5632_vol_snd_controls[] = {
+       /* left starts at bit 8, right at bit 0 */
+       /* 31 steps (5 bit), -46.5db scale */
+       SOC_DOUBLE_TLV("Speaker Playback Volume",
+                       ALC5632_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),
+       /* bit 15 mutes left, bit 7 right */
+       SOC_DOUBLE("Speaker Playback Switch",
+                       ALC5632_SPK_OUT_VOL, 15, 7, 1, 1),
+       SOC_DOUBLE_TLV("Headphone Playback Volume",
+                       ALC5632_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv),
+       SOC_DOUBLE("Headphone Playback Switch",
+                       ALC5632_HP_OUT_VOL, 15, 7, 1, 1),
+};
+
+static const struct snd_kcontrol_new alc5632_snd_controls[] = {
+       SOC_DOUBLE_TLV("Auxout Playback Volume",
+                       ALC5632_AUX_OUT_VOL, 8, 0, 31, 1, hp_tlv),
+       SOC_DOUBLE("Auxout Playback Switch",
+                       ALC5632_AUX_OUT_VOL, 15, 7, 1, 1),
+       SOC_SINGLE_TLV("Voice DAC Playback Volume",
+                       ALC5632_VOICE_DAC_VOL, 0, 63, 0, vdac_tlv),
+       SOC_SINGLE_TLV("Phone Capture Volume",
+                       ALC5632_PHONE_IN_VOL, 8, 31, 1, vol_tlv),
+       SOC_DOUBLE_TLV("LineIn Capture Volume",
+                       ALC5632_LINE_IN_VOL, 8, 0, 31, 1, vol_tlv),
+       SOC_DOUBLE_TLV("Master Playback Volume",
+                       ALC5632_STEREO_DAC_IN_VOL, 8, 0, 63, 1, vdac_tlv),
+       SOC_DOUBLE("Master Playback Switch",
+                       ALC5632_STEREO_DAC_IN_VOL, 15, 7, 1, 1),
+       SOC_SINGLE_TLV("Mic1 Capture Volume",
+                       ALC5632_MIC_VOL, 8, 31, 1, vol_tlv),
+       SOC_SINGLE_TLV("Mic2 Capture Volume",
+                       ALC5632_MIC_VOL, 0, 31, 1, vol_tlv),
+       SOC_DOUBLE_TLV("Rec Capture Volume",
+                       ALC5632_ADC_REC_GAIN, 8, 0, 31, 0, adc_rec_tlv),
+       SOC_SINGLE_TLV("Mic 1 Boost Volume",
+                       ALC5632_MIC_CTRL, 10, 2, 0, boost_tlv),
+       SOC_SINGLE_TLV("Mic 2 Boost Volume",
+                       ALC5632_MIC_CTRL, 8, 2, 0, boost_tlv),
+       SOC_SINGLE_TLV("Digital Boost Volume",
+                       ALC5632_DIGI_BOOST_CTRL, 0, 7, 0, dig_tlv),
+};
+
+/*
+ * DAPM Controls
+ */
+static const struct snd_kcontrol_new alc5632_hp_mixer_controls[] = {
+SOC_DAPM_SINGLE("LI2HP Playback Switch", ALC5632_LINE_IN_VOL, 15, 1, 1),
+SOC_DAPM_SINGLE("PHONE2HP Playback Switch", ALC5632_PHONE_IN_VOL, 15, 1, 1),
+SOC_DAPM_SINGLE("MIC12HP Playback Switch", ALC5632_MIC_ROUTING_CTRL, 15, 1, 1),
+SOC_DAPM_SINGLE("MIC22HP Playback Switch", ALC5632_MIC_ROUTING_CTRL, 11, 1, 1),
+SOC_DAPM_SINGLE("VOICE2HP Playback Switch", ALC5632_VOICE_DAC_VOL, 15, 1, 1),
+};
+
+static const struct snd_kcontrol_new alc5632_hpl_mixer_controls[] = {
+SOC_DAPM_SINGLE("ADC2HP_L Playback Switch", ALC5632_ADC_REC_GAIN, 15, 1, 1),
+SOC_DAPM_SINGLE("DACL2HP Playback Switch", ALC5632_MIC_ROUTING_CTRL, 3, 1, 1),
+};
+
+static const struct snd_kcontrol_new alc5632_hpr_mixer_controls[] = {
+SOC_DAPM_SINGLE("ADC2HP_R Playback Switch", ALC5632_ADC_REC_GAIN, 7, 1, 1),
+SOC_DAPM_SINGLE("DACR2HP Playback Switch", ALC5632_MIC_ROUTING_CTRL, 2, 1, 1),
+};
+
+static const struct snd_kcontrol_new alc5632_mono_mixer_controls[] = {
+SOC_DAPM_SINGLE("ADC2MONO_L Playback Switch", ALC5632_ADC_REC_GAIN, 14, 1, 1),
+SOC_DAPM_SINGLE("ADC2MONO_R Playback Switch", ALC5632_ADC_REC_GAIN, 6, 1, 1),
+SOC_DAPM_SINGLE("LI2MONO Playback Switch", ALC5632_LINE_IN_VOL, 13, 1, 1),
+SOC_DAPM_SINGLE("MIC12MONO Playback Switch",
+                                       ALC5632_MIC_ROUTING_CTRL, 13, 1, 1),
+SOC_DAPM_SINGLE("MIC22MONO Playback Switch",
+                                       ALC5632_MIC_ROUTING_CTRL, 9, 1, 1),
+SOC_DAPM_SINGLE("DAC2MONO Playback Switch", ALC5632_MIC_ROUTING_CTRL, 0, 1, 1),
+SOC_DAPM_SINGLE("VOICE2MONO Playback Switch", ALC5632_VOICE_DAC_VOL, 13, 1, 1),
+};
+
+static const struct snd_kcontrol_new alc5632_speaker_mixer_controls[] = {
+SOC_DAPM_SINGLE("LI2SPK Playback Switch", ALC5632_LINE_IN_VOL, 14, 1, 1),
+SOC_DAPM_SINGLE("PHONE2SPK Playback Switch", ALC5632_PHONE_IN_VOL, 14, 1, 1),
+SOC_DAPM_SINGLE("MIC12SPK Playback Switch",
+                                       ALC5632_MIC_ROUTING_CTRL, 14, 1, 1),
+SOC_DAPM_SINGLE("MIC22SPK Playback Switch",
+                                       ALC5632_MIC_ROUTING_CTRL, 10, 1, 1),
+SOC_DAPM_SINGLE("DAC2SPK Playback Switch", ALC5632_MIC_ROUTING_CTRL, 1, 1, 1),
+SOC_DAPM_SINGLE("VOICE2SPK Playback Switch", ALC5632_VOICE_DAC_VOL, 14, 1, 1),
+};
+
+/* Left Record Mixer */
+static const struct snd_kcontrol_new alc5632_captureL_mixer_controls[] = {
+SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5632_ADC_REC_MIXER, 14, 1, 1),
+SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5632_ADC_REC_MIXER, 13, 1, 1),
+SOC_DAPM_SINGLE("LineInL Capture Switch", ALC5632_ADC_REC_MIXER, 12, 1, 1),
+SOC_DAPM_SINGLE("Left Phone Capture Switch", ALC5632_ADC_REC_MIXER, 11, 1, 1),
+SOC_DAPM_SINGLE("HPMixerL Capture Switch", ALC5632_ADC_REC_MIXER, 10, 1, 1),
+SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5632_ADC_REC_MIXER, 9, 1, 1),
+SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5632_ADC_REC_MIXER, 8, 1, 1),
+};
+
+/* Right Record Mixer */
+static const struct snd_kcontrol_new alc5632_captureR_mixer_controls[] = {
+SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5632_ADC_REC_MIXER, 6, 1, 1),
+SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5632_ADC_REC_MIXER, 5, 1, 1),
+SOC_DAPM_SINGLE("LineInR Capture Switch", ALC5632_ADC_REC_MIXER, 4, 1, 1),
+SOC_DAPM_SINGLE("Right Phone Capture Switch", ALC5632_ADC_REC_MIXER, 3, 1, 1),
+SOC_DAPM_SINGLE("HPMixerR Capture Switch", ALC5632_ADC_REC_MIXER, 2, 1, 1),
+SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5632_ADC_REC_MIXER, 1, 1, 1),
+SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5632_ADC_REC_MIXER, 0, 1, 1),
+};
+
+static const char *alc5632_spk_n_sour_sel[] = {
+               "RN/-R", "RP/+R", "LN/-R", "Mute"};
+static const char *alc5632_hpl_out_input_sel[] = {
+               "Vmid", "HP Left Mix"};
+static const char *alc5632_hpr_out_input_sel[] = {
+               "Vmid", "HP Right Mix"};
+static const char *alc5632_spkout_input_sel[] = {
+               "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
+static const char *alc5632_aux_out_input_sel[] = {
+               "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
+
+/* auxout output mux */
+static const struct soc_enum alc5632_aux_out_input_enum =
+SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 6, 4, alc5632_aux_out_input_sel);
+static const struct snd_kcontrol_new alc5632_auxout_mux_controls =
+SOC_DAPM_ENUM("AuxOut Mux", alc5632_aux_out_input_enum);
+
+/* speaker output mux */
+static const struct soc_enum alc5632_spkout_input_enum =
+SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 10, 4, alc5632_spkout_input_sel);
+static const struct snd_kcontrol_new alc5632_spkout_mux_controls =
+SOC_DAPM_ENUM("SpeakerOut Mux", alc5632_spkout_input_enum);
+
+/* headphone left output mux */
+static const struct soc_enum alc5632_hpl_out_input_enum =
+SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 9, 2, alc5632_hpl_out_input_sel);
+static const struct snd_kcontrol_new alc5632_hpl_out_mux_controls =
+SOC_DAPM_ENUM("Left Headphone Mux", alc5632_hpl_out_input_enum);
+
+/* headphone right output mux */
+static const struct soc_enum alc5632_hpr_out_input_enum =
+SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 8, 2, alc5632_hpr_out_input_sel);
+static const struct snd_kcontrol_new alc5632_hpr_out_mux_controls =
+SOC_DAPM_ENUM("Right Headphone Mux", alc5632_hpr_out_input_enum);
+
+/* speaker output N select */
+static const struct soc_enum alc5632_spk_n_sour_enum =
+SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 14, 4, alc5632_spk_n_sour_sel);
+static const struct snd_kcontrol_new alc5632_spkoutn_mux_controls =
+SOC_DAPM_ENUM("SpeakerOut N Mux", alc5632_spk_n_sour_enum);
+
+/* speaker amplifier */
+static const char *alc5632_amp_names[] = {"AB Amp", "D Amp"};
+static const struct soc_enum alc5632_amp_enum =
+       SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 13, 2, alc5632_amp_names);
+static const struct snd_kcontrol_new alc5632_amp_mux_controls =
+       SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum);
+
+
+static const struct snd_soc_dapm_widget alc5632_dapm_widgets[] = {
+/* Muxes */
+SND_SOC_DAPM_MUX("AuxOut Mux", SND_SOC_NOPM, 0, 0,
+       &alc5632_auxout_mux_controls),
+SND_SOC_DAPM_MUX("SpeakerOut Mux", SND_SOC_NOPM, 0, 0,
+       &alc5632_spkout_mux_controls),
+SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0,
+       &alc5632_hpl_out_mux_controls),
+SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0,
+       &alc5632_hpr_out_mux_controls),
+SND_SOC_DAPM_MUX("SpeakerOut N Mux", SND_SOC_NOPM, 0, 0,
+       &alc5632_spkoutn_mux_controls),
+
+/* output mixers */
+SND_SOC_DAPM_MIXER("HP Mix", SND_SOC_NOPM, 0, 0,
+       &alc5632_hp_mixer_controls[0],
+       ARRAY_SIZE(alc5632_hp_mixer_controls)),
+SND_SOC_DAPM_MIXER("HPR Mix", ALC5632_PWR_MANAG_ADD2, 4, 0,
+       &alc5632_hpr_mixer_controls[0],
+       ARRAY_SIZE(alc5632_hpr_mixer_controls)),
+SND_SOC_DAPM_MIXER("HPL Mix", ALC5632_PWR_MANAG_ADD2, 5, 0,
+       &alc5632_hpl_mixer_controls[0],
+       ARRAY_SIZE(alc5632_hpl_mixer_controls)),
+SND_SOC_DAPM_MIXER("HPOut Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("Mono Mix", ALC5632_PWR_MANAG_ADD2, 2, 0,
+       &alc5632_mono_mixer_controls[0],
+       ARRAY_SIZE(alc5632_mono_mixer_controls)),
+SND_SOC_DAPM_MIXER("Speaker Mix", ALC5632_PWR_MANAG_ADD2, 3, 0,
+       &alc5632_speaker_mixer_controls[0],
+       ARRAY_SIZE(alc5632_speaker_mixer_controls)),
+
+/* input mixers */
+SND_SOC_DAPM_MIXER("Left Capture Mix", ALC5632_PWR_MANAG_ADD2, 1, 0,
+       &alc5632_captureL_mixer_controls[0],
+       ARRAY_SIZE(alc5632_captureL_mixer_controls)),
+SND_SOC_DAPM_MIXER("Right Capture Mix", ALC5632_PWR_MANAG_ADD2, 0, 0,
+       &alc5632_captureR_mixer_controls[0],
+       ARRAY_SIZE(alc5632_captureR_mixer_controls)),
+
+SND_SOC_DAPM_DAC("Left DAC", "HiFi Playback",
+       ALC5632_PWR_MANAG_ADD2, 9, 0),
+SND_SOC_DAPM_DAC("Right DAC", "HiFi Playback",
+       ALC5632_PWR_MANAG_ADD2, 8, 0),
+SND_SOC_DAPM_MIXER("DAC Left Channel", ALC5632_PWR_MANAG_ADD1, 15, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("DAC Right Channel",
+       ALC5632_PWR_MANAG_ADD1, 14, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("I2S Mix", ALC5632_PWR_MANAG_ADD1, 11, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("Phone Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("Line Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_ADC("Left ADC", "HiFi Capture",
+       ALC5632_PWR_MANAG_ADD2, 7, 0),
+SND_SOC_DAPM_ADC("Right ADC", "HiFi Capture",
+       ALC5632_PWR_MANAG_ADD2, 6, 0),
+SND_SOC_DAPM_PGA("Left Headphone", ALC5632_PWR_MANAG_ADD3, 11, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right Headphone", ALC5632_PWR_MANAG_ADD3, 10, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Left Speaker", ALC5632_PWR_MANAG_ADD3, 13, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right Speaker", ALC5632_PWR_MANAG_ADD3, 12, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Aux Out", ALC5632_PWR_MANAG_ADD3, 14, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Left LineIn", ALC5632_PWR_MANAG_ADD3, 7, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right LineIn", ALC5632_PWR_MANAG_ADD3, 6, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Phone", ALC5632_PWR_MANAG_ADD3, 5, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Phone ADMix", ALC5632_PWR_MANAG_ADD3, 4, 0, NULL, 0),
+SND_SOC_DAPM_PGA("MIC1 PGA", ALC5632_PWR_MANAG_ADD3, 3, 0, NULL, 0),
+SND_SOC_DAPM_PGA("MIC2 PGA", ALC5632_PWR_MANAG_ADD3, 2, 0, NULL, 0),
+SND_SOC_DAPM_PGA("MIC1 Pre Amp", ALC5632_PWR_MANAG_ADD3, 1, 0, NULL, 0),
+SND_SOC_DAPM_PGA("MIC2 Pre Amp", ALC5632_PWR_MANAG_ADD3, 0, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("Mic Bias1", ALC5632_PWR_MANAG_ADD1, 3, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("Mic Bias2", ALC5632_PWR_MANAG_ADD1, 2, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_E("D Amp", ALC5632_PWR_MANAG_ADD2, 14, 0, NULL, 0,
+       amp_mixer_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_PGA("AB Amp", ALC5632_PWR_MANAG_ADD2, 15, 0, NULL, 0),
+SND_SOC_DAPM_MUX("AB-D Amp Mux", ALC5632_PWR_MANAG_ADD1, 10, 0,
+       &alc5632_amp_mux_controls),
+
+SND_SOC_DAPM_OUTPUT("AUXOUT"),
+SND_SOC_DAPM_OUTPUT("HPL"),
+SND_SOC_DAPM_OUTPUT("HPR"),
+SND_SOC_DAPM_OUTPUT("SPKOUT"),
+SND_SOC_DAPM_OUTPUT("SPKOUTN"),
+SND_SOC_DAPM_INPUT("LINEINL"),
+SND_SOC_DAPM_INPUT("LINEINR"),
+SND_SOC_DAPM_INPUT("PHONEP"),
+SND_SOC_DAPM_INPUT("PHONEN"),
+SND_SOC_DAPM_INPUT("MIC1"),
+SND_SOC_DAPM_INPUT("MIC2"),
+SND_SOC_DAPM_VMID("Vmid"),
+};
+
+
+static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
+       /* virtual mixer - mixes left & right channels */
+       {"I2S Mix",     NULL,   "Left DAC"},
+       {"I2S Mix",     NULL,   "Right DAC"},
+       {"Line Mix",    NULL,   "Right LineIn"},
+       {"Line Mix",    NULL,   "Left LineIn"},
+       {"Phone Mix",   NULL,   "Phone"},
+       {"Phone Mix",   NULL,   "Phone ADMix"},
+       {"AUXOUT",              NULL,   "Aux Out"},
+
+       /* DAC */
+       {"DAC Right Channel",   NULL,   "I2S Mix"},
+       {"DAC Left Channel",    NULL,   "I2S Mix"},
+
+       /* HP mixer */
+       {"HPL Mix",     "ADC2HP_L Playback Switch",     "Left Capture Mix"},
+       {"HPL Mix", NULL,                                       "HP Mix"},
+       {"HPR Mix", "ADC2HP_R Playback Switch", "Right Capture Mix"},
+       {"HPR Mix", NULL,                                       "HP Mix"},
+       {"HP Mix",      "LI2HP Playback Switch",        "Line Mix"},
+       {"HP Mix",      "PHONE2HP Playback Switch",     "Phone Mix"},
+       {"HP Mix",      "MIC12HP Playback Switch",      "MIC1 PGA"},
+       {"HP Mix",      "MIC22HP Playback Switch",      "MIC2 PGA"},
+
+       {"HPR Mix", "DACR2HP Playback Switch",  "DAC Right Channel"},
+       {"HPL Mix", "DACL2HP Playback Switch",  "DAC Left Channel"},
+
+       /* speaker mixer */
+       {"Speaker Mix", "LI2SPK Playback Switch",       "Line Mix"},
+       {"Speaker Mix", "PHONE2SPK Playback Switch", "Phone Mix"},
+       {"Speaker Mix", "MIC12SPK Playback Switch",     "MIC1 PGA"},
+       {"Speaker Mix", "MIC22SPK Playback Switch",     "MIC2 PGA"},
+       {"Speaker Mix", "DAC2SPK Playback Switch",      "DAC Left Channel"},
+
+
+
+       /* mono mixer */
+       {"Mono Mix", "ADC2MONO_L Playback Switch",      "Left Capture Mix"},
+       {"Mono Mix", "ADC2MONO_R Playback Switch",      "Right Capture Mix"},
+       {"Mono Mix", "LI2MONO Playback Switch",         "Line Mix"},
+       {"Mono Mix", "VOICE2MONO Playback Switch",      "Phone Mix"},
+       {"Mono Mix", "MIC12MONO Playback Switch",       "MIC1 PGA"},
+       {"Mono Mix", "MIC22MONO Playback Switch",       "MIC2 PGA"},
+       {"Mono Mix", "DAC2MONO Playback Switch",        "DAC Left Channel"},
+
+       /* Left record mixer */
+       {"Left Capture Mix", "LineInL Capture Switch",  "LINEINL"},
+       {"Left Capture Mix", "Left Phone Capture Switch", "PHONEN"},
+       {"Left Capture Mix", "Mic1 Capture Switch",     "MIC1 Pre Amp"},
+       {"Left Capture Mix", "Mic2 Capture Switch",     "MIC2 Pre Amp"},
+       {"Left Capture Mix", "HPMixerL Capture Switch", "HPL Mix"},
+       {"Left Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
+       {"Left Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
+
+       /*Right record mixer */
+       {"Right Capture Mix", "LineInR Capture Switch", "LINEINR"},
+       {"Right Capture Mix", "Right Phone Capture Switch",     "PHONEP"},
+       {"Right Capture Mix", "Mic1 Capture Switch",    "MIC1 Pre Amp"},
+       {"Right Capture Mix", "Mic2 Capture Switch",    "MIC2 Pre Amp"},
+       {"Right Capture Mix", "HPMixerR Capture Switch", "HPR Mix"},
+       {"Right Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
+       {"Right Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
+
+       /* headphone left mux */
+       {"Left Headphone Mux", "HP Left Mix",           "HPL Mix"},
+       {"Left Headphone Mux", "Vmid",                  "Vmid"},
+
+       /* headphone right mux */
+       {"Right Headphone Mux", "HP Right Mix",         "HPR Mix"},
+       {"Right Headphone Mux", "Vmid",                 "Vmid"},
+
+       /* speaker out mux */
+       {"SpeakerOut Mux", "Vmid",                      "Vmid"},
+       {"SpeakerOut Mux", "HPOut Mix",                 "HPOut Mix"},
+       {"SpeakerOut Mux", "Speaker Mix",               "Speaker Mix"},
+       {"SpeakerOut Mux", "Mono Mix",                  "Mono Mix"},
+
+       /* Mono/Aux Out mux */
+       {"AuxOut Mux", "Vmid",                          "Vmid"},
+       {"AuxOut Mux", "HPOut Mix",                     "HPOut Mix"},
+       {"AuxOut Mux", "Speaker Mix",                   "Speaker Mix"},
+       {"AuxOut Mux", "Mono Mix",                      "Mono Mix"},
+
+       /* output pga */
+       {"HPL", NULL,                                   "Left Headphone"},
+       {"Left Headphone", NULL,                        "Left Headphone Mux"},
+       {"HPR", NULL,                                   "Right Headphone"},
+       {"Right Headphone", NULL,                       "Right Headphone Mux"},
+       {"Aux Out", NULL,                               "AuxOut Mux"},
+
+       /* input pga */
+       {"Left LineIn", NULL,                           "LINEINL"},
+       {"Right LineIn", NULL,                          "LINEINR"},
+       {"Phone", NULL,                         "PHONEP"},
+       {"MIC1 Pre Amp", NULL,                          "MIC1"},
+       {"MIC2 Pre Amp", NULL,                          "MIC2"},
+       {"MIC1 PGA", NULL,                              "MIC1 Pre Amp"},
+       {"MIC2 PGA", NULL,                              "MIC2 Pre Amp"},
+
+       /* left ADC */
+       {"Left ADC", NULL,                              "Left Capture Mix"},
+
+       /* right ADC */
+       {"Right ADC", NULL,                             "Right Capture Mix"},
+
+       {"SpeakerOut N Mux", "RN/-R",                   "Left Speaker"},
+       {"SpeakerOut N Mux", "RP/+R",                   "Left Speaker"},
+       {"SpeakerOut N Mux", "LN/-R",                   "Left Speaker"},
+       {"SpeakerOut N Mux", "Mute",                    "Vmid"},
+
+       {"SpeakerOut N Mux", "RN/-R",                   "Right Speaker"},
+       {"SpeakerOut N Mux", "RP/+R",                   "Right Speaker"},
+       {"SpeakerOut N Mux", "LN/-R",                   "Right Speaker"},
+       {"SpeakerOut N Mux", "Mute",                    "Vmid"},
+
+       {"AB Amp", NULL,                                "SpeakerOut Mux"},
+       {"D Amp", NULL,                                 "SpeakerOut Mux"},
+       {"AB-D Amp Mux", "AB Amp",                      "AB Amp"},
+       {"AB-D Amp Mux", "D Amp",                       "D Amp"},
+       {"Left Speaker", NULL,                          "AB-D Amp Mux"},
+       {"Right Speaker", NULL,                         "AB-D Amp Mux"},
+
+       {"SPKOUT", NULL,                                "Left Speaker"},
+       {"SPKOUT", NULL,                                "Right Speaker"},
+
+       {"SPKOUTN", NULL,                               "SpeakerOut N Mux"},
+
+};
+
+/* PLL divisors */
+struct _pll_div {
+       u32 pll_in;
+       u32 pll_out;
+       u16 regvalue;
+};
+
+/* Note : pll code from original alc5632 driver. Not sure of how good it is */
+/* usefull only for master mode */
+static const struct _pll_div codec_master_pll_div[] = {
+
+       {  2048000,  8192000,   0x0ea0},
+       {  3686400,  8192000,   0x4e27},
+       { 12000000,  8192000,   0x456b},
+       { 13000000,  8192000,   0x495f},
+       { 13100000,  8192000,   0x0320},
+       {  2048000,  11289600,  0xf637},
+       {  3686400,  11289600,  0x2f22},
+       { 12000000,  11289600,  0x3e2f},
+       { 13000000,  11289600,  0x4d5b},
+       { 13100000,  11289600,  0x363b},
+       {  2048000,  16384000,  0x1ea0},
+       {  3686400,  16384000,  0x9e27},
+       { 12000000,  16384000,  0x452b},
+       { 13000000,  16384000,  0x542f},
+       { 13100000,  16384000,  0x03a0},
+       {  2048000,  16934400,  0xe625},
+       {  3686400,  16934400,  0x9126},
+       { 12000000,  16934400,  0x4d2c},
+       { 13000000,  16934400,  0x742f},
+       { 13100000,  16934400,  0x3c27},
+       {  2048000,  22579200,  0x2aa0},
+       {  3686400,  22579200,  0x2f20},
+       { 12000000,  22579200,  0x7e2f},
+       { 13000000,  22579200,  0x742f},
+       { 13100000,  22579200,  0x3c27},
+       {  2048000,  24576000,  0x2ea0},
+       {  3686400,  24576000,  0xee27},
+       { 12000000,  24576000,  0x2915},
+       { 13000000,  24576000,  0x772e},
+       { 13100000,  24576000,  0x0d20},
+};
+
+/* FOUT = MCLK*(N+2)/((M+2)*(K+2))
+   N: bit 15:8 (div 2 .. div 257)
+   K: bit  6:4 typical 2
+   M: bit  3:0 (div 2 .. div 17)
+
+   same as for 5623 - thanks!
+*/
+
+static const struct _pll_div codec_slave_pll_div[] = {
+
+       {  1024000,  16384000,  0x3ea0},
+       {  1411200,  22579200,  0x3ea0},
+       {  1536000,  24576000,  0x3ea0},
+       {  2048000,  16384000,  0x1ea0},
+       {  2822400,  22579200,  0x1ea0},
+       {  3072000,  24576000,  0x1ea0},
+
+};
+
+static int alc5632_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
+               int source, unsigned int freq_in, unsigned int freq_out)
+{
+       int i;
+       struct snd_soc_codec *codec = codec_dai->codec;
+       int gbl_clk = 0, pll_div = 0;
+       u16 reg;
+
+       if (pll_id < ALC5632_PLL_FR_MCLK || pll_id > ALC5632_PLL_FR_VBCLK)
+               return -EINVAL;
+
+       /* Disable PLL power */
+       snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+                               ALC5632_PWR_ADD2_PLL1,
+                               0);
+       snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+                               ALC5632_PWR_ADD2_PLL2,
+                               0);
+
+       /* pll is not used in slave mode */
+       reg = snd_soc_read(codec, ALC5632_DAI_CONTROL);
+       if (reg & ALC5632_DAI_SDP_SLAVE_MODE)
+               return 0;
+
+       if (!freq_in || !freq_out)
+               return 0;
+
+       switch (pll_id) {
+       case ALC5632_PLL_FR_MCLK:
+               for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++) {
+                       if (codec_master_pll_div[i].pll_in == freq_in
+                          && codec_master_pll_div[i].pll_out == freq_out) {
+                               /* PLL source from MCLK */
+                               pll_div  = codec_master_pll_div[i].regvalue;
+                               break;
+                       }
+               }
+               break;
+       case ALC5632_PLL_FR_BCLK:
+               for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) {
+                       if (codec_slave_pll_div[i].pll_in == freq_in
+                          && codec_slave_pll_div[i].pll_out == freq_out) {
+                               /* PLL source from Bitclk */
+                               gbl_clk = ALC5632_PLL_FR_BCLK;
+                               pll_div = codec_slave_pll_div[i].regvalue;
+                               break;
+                       }
+               }
+               break;
+       case ALC5632_PLL_FR_VBCLK:
+               for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) {
+                       if (codec_slave_pll_div[i].pll_in == freq_in
+                          && codec_slave_pll_div[i].pll_out == freq_out) {
+                               /* PLL source from voice clock */
+                               gbl_clk = ALC5632_PLL_FR_VBCLK;
+                               pll_div = codec_slave_pll_div[i].regvalue;
+                               break;
+                       }
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (!pll_div)
+               return -EINVAL;
+
+       /* choose MCLK/BCLK/VBCLK */
+       snd_soc_write(codec, ALC5632_GPCR2, gbl_clk);
+       /* choose PLL1 clock rate */
+       snd_soc_write(codec, ALC5632_PLL1_CTRL, pll_div);
+       /* enable PLL1 */
+       snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+                               ALC5632_PWR_ADD2_PLL1,
+                               ALC5632_PWR_ADD2_PLL1);
+       /* enable PLL2 */
+       snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+                               ALC5632_PWR_ADD2_PLL2,
+                               ALC5632_PWR_ADD2_PLL2);
+       /* use PLL1 as main SYSCLK */
+       snd_soc_update_bits(codec, ALC5632_GPCR1,
+                       ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1,
+                       ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1);
+
+       return 0;
+}
+
+struct _coeff_div {
+       u16 fs;
+       u16 regvalue;
+};
+
+/* codec hifi mclk (after PLL) clock divider coefficients */
+/* values inspired from column BCLK=32Fs of Appendix A table */
+static const struct _coeff_div coeff_div[] = {
+       {512*1, 0x3075},
+};
+
+static int get_coeff(struct snd_soc_codec *codec, int rate)
+{
+       struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
+               if (coeff_div[i].fs * rate == alc5632->sysclk)
+                       return i;
+       }
+       return -EINVAL;
+}
+
+/*
+ * Clock after PLL and dividers
+ */
+static int alc5632_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+               int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
+
+       switch (freq) {
+       case  8192000:
+       case 11289600:
+       case 12288000:
+       case 16384000:
+       case 16934400:
+       case 18432000:
+       case 22579200:
+       case 24576000:
+               alc5632->sysclk = freq;
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int alc5632_set_dai_fmt(struct snd_soc_dai *codec_dai,
+               unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 iface = 0;
+
+       /* set master/slave audio interface */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               iface = ALC5632_DAI_SDP_MASTER_MODE;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               iface = ALC5632_DAI_SDP_SLAVE_MODE;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* interface format */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               iface |= ALC5632_DAI_I2S_DF_I2S;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               iface |= ALC5632_DAI_I2S_DF_LEFT;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               iface |= ALC5632_DAI_I2S_DF_PCM_A;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               iface |= ALC5632_DAI_I2S_DF_PCM_B;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* clock inversion */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               iface |= ALC5632_DAI_MAIN_I2S_BCLK_POL_CTRL;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               iface |= ALC5632_DAI_MAIN_I2S_BCLK_POL_CTRL;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return snd_soc_write(codec, ALC5632_DAI_CONTROL, iface);
+}
+
+static int alc5632_pcm_hw_params(struct snd_pcm_substream *substream,
+               struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_codec *codec = rtd->codec;
+       int coeff, rate;
+       u16 iface;
+
+       iface = snd_soc_read(codec, ALC5632_DAI_CONTROL);
+       iface &= ~ALC5632_DAI_I2S_DL_MASK;
+
+       /* bit size */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               iface |= ALC5632_DAI_I2S_DL_16;
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               iface |= ALC5632_DAI_I2S_DL_20;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               iface |= ALC5632_DAI_I2S_DL_24;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* set iface & srate */
+       snd_soc_write(codec, ALC5632_DAI_CONTROL, iface);
+       rate = params_rate(params);
+       coeff = get_coeff(codec, rate);
+       if (coeff < 0)
+               return -EINVAL;
+
+       coeff = coeff_div[coeff].regvalue;
+       snd_soc_write(codec, ALC5632_DAC_CLK_CTRL1, coeff);
+
+       return 0;
+}
+
+static int alc5632_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       u16 hp_mute = ALC5632_MISC_HP_DEPOP_MUTE_L
+                                               |ALC5632_MISC_HP_DEPOP_MUTE_R;
+       u16 mute_reg = snd_soc_read(codec, ALC5632_MISC_CTRL) & ~hp_mute;
+
+       if (mute)
+               mute_reg |= hp_mute;
+
+       return snd_soc_write(codec, ALC5632_MISC_CTRL, mute_reg);
+}
+
+#define ALC5632_ADD2_POWER_EN (ALC5632_PWR_ADD2_VREF)
+
+#define ALC5632_ADD3_POWER_EN (ALC5632_PWR_ADD3_MIC1_BOOST_AD)
+
+#define ALC5632_ADD1_POWER_EN \
+               (ALC5632_PWR_ADD1_DAC_REF \
+               | ALC5632_PWR_ADD1_SOFTGEN_EN \
+               | ALC5632_PWR_ADD1_HP_OUT_AMP \
+               | ALC5632_PWR_ADD1_HP_OUT_ENH_AMP \
+               | ALC5632_PWR_ADD1_MAIN_BIAS)
+
+static void enable_power_depop(struct snd_soc_codec *codec)
+{
+       snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1,
+                               ALC5632_PWR_ADD1_SOFTGEN_EN,
+                               ALC5632_PWR_ADD1_SOFTGEN_EN);
+
+       snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD3,
+                               ALC5632_ADD3_POWER_EN,
+                               ALC5632_ADD3_POWER_EN);
+
+       snd_soc_update_bits(codec, ALC5632_MISC_CTRL,
+                               ALC5632_MISC_HP_DEPOP_MODE2_EN,
+                               ALC5632_MISC_HP_DEPOP_MODE2_EN);
+
+       /* "normal" mode: 0 @ 26 */
+       /* set all PR0-7 mixers to 0 */
+       snd_soc_update_bits(codec, ALC5632_PWR_DOWN_CTRL_STATUS,
+                               ALC5632_PWR_DOWN_CTRL_STATUS_MASK,
+                               0);
+
+       msleep(500);
+
+       snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+                               ALC5632_ADD2_POWER_EN,
+                               ALC5632_ADD2_POWER_EN);
+
+       snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1,
+                               ALC5632_ADD1_POWER_EN,
+                               ALC5632_ADD1_POWER_EN);
+
+       /* disable HP Depop2 */
+       snd_soc_update_bits(codec, ALC5632_MISC_CTRL,
+                               ALC5632_MISC_HP_DEPOP_MODE2_EN,
+                               0);
+
+}
+
+static int alc5632_set_bias_level(struct snd_soc_codec *codec,
+                                     enum snd_soc_bias_level level)
+{
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               enable_power_depop(codec);
+               break;
+       case SND_SOC_BIAS_PREPARE:
+               break;
+       case SND_SOC_BIAS_STANDBY:
+               /* everything off except vref/vmid, */
+               snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1,
+                               ALC5632_PWR_MANAG_ADD1_MASK,
+                               ALC5632_PWR_ADD1_MAIN_BIAS);
+               snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+                               ALC5632_PWR_MANAG_ADD2_MASK,
+                               ALC5632_PWR_ADD2_VREF);
+               /* "normal" mode: 0 @ 26 */
+               snd_soc_update_bits(codec, ALC5632_PWR_DOWN_CTRL_STATUS,
+                               ALC5632_PWR_DOWN_CTRL_STATUS_MASK,
+                               0xffff ^ (ALC5632_PWR_VREF_PR3
+                               | ALC5632_PWR_VREF_PR2));
+               break;
+       case SND_SOC_BIAS_OFF:
+               /* everything off, dac mute, inactive */
+               snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+                               ALC5632_PWR_MANAG_ADD2_MASK, 0);
+               snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD3,
+                               ALC5632_PWR_MANAG_ADD3_MASK, 0);
+               snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1,
+                               ALC5632_PWR_MANAG_ADD1_MASK, 0);
+               break;
+       }
+       codec->dapm.bias_level = level;
+       return 0;
+}
+
+#define ALC5632_FORMATS        (SNDRV_PCM_FMTBIT_S16_LE \
+                       | SNDRV_PCM_FMTBIT_S24_LE \
+                       | SNDRV_PCM_FMTBIT_S32_LE)
+
+static const struct snd_soc_dai_ops alc5632_dai_ops = {
+               .hw_params = alc5632_pcm_hw_params,
+               .digital_mute = alc5632_mute,
+               .set_fmt = alc5632_set_dai_fmt,
+               .set_sysclk = alc5632_set_dai_sysclk,
+               .set_pll = alc5632_set_dai_pll,
+};
+
+static struct snd_soc_dai_driver alc5632_dai = {
+       .name = "alc5632-hifi",
+       .playback = {
+               .stream_name = "HiFi Playback",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rate_min =     8000,
+               .rate_max =     48000,
+               .rates = SNDRV_PCM_RATE_8000_48000,
+               .formats = ALC5632_FORMATS,},
+       .capture = {
+               .stream_name = "HiFi Capture",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rate_min =     8000,
+               .rate_max =     48000,
+               .rates = SNDRV_PCM_RATE_8000_48000,
+               .formats = ALC5632_FORMATS,},
+
+       .ops = &alc5632_dai_ops,
+       .symmetric_rates = 1,
+};
+
+#ifdef CONFIG_PM
+static int alc5632_suspend(struct snd_soc_codec *codec)
+{
+       alc5632_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static int alc5632_resume(struct snd_soc_codec *codec)
+{
+       struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
+
+       regcache_sync(alc5632->regmap);
+
+       alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       return 0;
+}
+#else
+#define        alc5632_suspend NULL
+#define        alc5632_resume  NULL
+#endif
+
+static int alc5632_probe(struct snd_soc_codec *codec)
+{
+       struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+       codec->control_data = alc5632->regmap;
+
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
+
+       /* power on device  */
+       alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       switch (alc5632->id) {
+       case 0x5c:
+               snd_soc_add_controls(codec, alc5632_vol_snd_controls,
+                       ARRAY_SIZE(alc5632_vol_snd_controls));
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+/* power down chip */
+static int alc5632_remove(struct snd_soc_codec *codec)
+{
+       alc5632_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_device_alc5632 = {
+       .probe = alc5632_probe,
+       .remove = alc5632_remove,
+       .suspend = alc5632_suspend,
+       .resume = alc5632_resume,
+       .set_bias_level = alc5632_set_bias_level,
+       .controls = alc5632_snd_controls,
+       .num_controls = ARRAY_SIZE(alc5632_snd_controls),
+       .dapm_widgets = alc5632_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(alc5632_dapm_widgets),
+       .dapm_routes = alc5632_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(alc5632_dapm_routes),
+};
+
+static struct regmap_config alc5632_regmap = {
+       .reg_bits = 8,
+       .val_bits = 16,
+
+       .max_register = ALC5632_MAX_REGISTER,
+       .reg_defaults = alc5632_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(alc5632_reg_defaults),
+       .volatile_reg = alc5632_volatile_register,
+       .cache_type = REGCACHE_RBTREE,
+};
+
+/*
+ * alc5632 2 wire address is determined by A1 pin
+ * state during powerup.
+ *    low  = 0x1a
+ *    high = 0x1b
+ */
+static __devinit int alc5632_i2c_probe(struct i2c_client *client,
+                               const struct i2c_device_id *id)
+{
+       struct alc5632_priv *alc5632;
+       int ret, ret1, ret2;
+       unsigned int vid1, vid2;
+
+       alc5632 = devm_kzalloc(&client->dev,
+                        sizeof(struct alc5632_priv), GFP_KERNEL);
+       if (alc5632 == NULL)
+               return -ENOMEM;
+
+       i2c_set_clientdata(client, alc5632);
+
+       alc5632->regmap = regmap_init_i2c(client, &alc5632_regmap);
+       if (IS_ERR(alc5632->regmap)) {
+               ret = PTR_ERR(alc5632->regmap);
+               dev_err(&client->dev, "regmap_init() failed: %d\n", ret);
+               return ret;
+       }
+
+       ret1 = regmap_read(alc5632->regmap, ALC5632_VENDOR_ID1, &vid1);
+       ret2 = regmap_read(alc5632->regmap, ALC5632_VENDOR_ID2, &vid2);
+       if (ret1 != 0 || ret2 != 0) {
+               dev_err(&client->dev,
+               "Failed to read chip ID: ret1=%d, ret2=%d\n", ret1, ret2);
+               regmap_exit(alc5632->regmap);
+               return -EIO;
+       }
+
+       vid2 >>= 8;
+
+       if ((vid1 != 0x10EC) || (vid2 != id->driver_data)) {
+               dev_err(&client->dev,
+               "Device is not a ALC5632: VID1=0x%x, VID2=0x%x\n", vid1, vid2);
+               regmap_exit(alc5632->regmap);
+               return -EINVAL;
+       }
+
+       ret = alc5632_reset(alc5632->regmap);
+       if (ret < 0) {
+               dev_err(&client->dev, "Failed to issue reset\n");
+               regmap_exit(alc5632->regmap);
+               return ret;
+       }
+
+       alc5632->id = vid2;
+       switch (alc5632->id) {
+       case 0x5c:
+               alc5632_dai.name = "alc5632-hifi";
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = snd_soc_register_codec(&client->dev,
+               &soc_codec_device_alc5632, &alc5632_dai, 1);
+
+       if (ret < 0) {
+               dev_err(&client->dev, "Failed to register codec: %d\n", ret);
+               regmap_exit(alc5632->regmap);
+               return ret;
+       }
+
+       return ret;
+}
+
+static int alc5632_i2c_remove(struct i2c_client *client)
+{
+       struct alc5632_priv *alc5632 = i2c_get_clientdata(client);
+       snd_soc_unregister_codec(&client->dev);
+       regmap_exit(alc5632->regmap);
+       return 0;
+}
+
+static const struct i2c_device_id alc5632_i2c_table[] = {
+       {"alc5632", 0x5c},
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, alc5632_i2c_table);
+
+/* i2c codec control layer */
+static struct i2c_driver alc5632_i2c_driver = {
+       .driver = {
+               .name = "alc5632",
+               .owner = THIS_MODULE,
+       },
+       .probe = alc5632_i2c_probe,
+       .remove =  __devexit_p(alc5632_i2c_remove),
+       .id_table = alc5632_i2c_table,
+};
+
+static int __init alc5632_modinit(void)
+{
+       int ret;
+
+       ret = i2c_add_driver(&alc5632_i2c_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "%s: can't add i2c driver", __func__);
+               return ret;
+       }
+
+       return ret;
+}
+module_init(alc5632_modinit);
+
+static void __exit alc5632_modexit(void)
+{
+       i2c_del_driver(&alc5632_i2c_driver);
+}
+module_exit(alc5632_modexit);
+
+MODULE_DESCRIPTION("ASoC ALC5632 driver");
+MODULE_AUTHOR("Leon Romanovsky <leon@leon.nu>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/alc5632.h b/sound/soc/codecs/alc5632.h
new file mode 100644 (file)
index 0000000..357651e
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+* alc5632.h  --  ALC5632 ALSA SoC Audio Codec
+*
+* Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
+*
+* Authors:  Leon Romanovsky <leon@leon.nu>
+*           Andrey Danin <danindrey@mail.ru>
+*           Ilya Petrov <ilya.muromec@gmail.com>
+*           Marc Dietrich <marvin24@gmx.de>
+*
+* Based on alc5623.h by Arnaud Patard
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*/
+
+#ifndef _ALC5632_H
+#define _ALC5632_H
+
+#define ALC5632_RESET                          0x00
+/* speaker output vol             2    2           */
+/* line output vol                      4    2      */
+/* HP output vol                  4    0    4      */
+#define ALC5632_SPK_OUT_VOL                    0x02 /* spe out vol */
+#define ALC5632_SPK_OUT_VOL_STEP               1.5
+#define ALC5632_HP_OUT_VOL                     0x04 /* hp out vol */
+#define ALC5632_AUX_OUT_VOL                    0x06 /* aux out vol */
+#define ALC5632_PHONE_IN_VOL                   0x08 /* phone in vol */
+#define ALC5632_LINE_IN_VOL                    0x0A /* line in vol */
+#define ALC5632_STEREO_DAC_IN_VOL              0x0C /* stereo dac in vol */
+#define ALC5632_MIC_VOL                                0x0E /* mic in vol */
+/* stero dac/mic routing */
+#define ALC5632_MIC_ROUTING_CTRL               0x10
+#define ALC5632_MIC_ROUTE_MONOMIX              (1 << 0)
+#define ALC5632_MIC_ROUTE_SPK                  (1 << 1)
+#define ALC5632_MIC_ROUTE_HP                   (1 << 2)
+
+#define ALC5632_ADC_REC_GAIN                   0x12 /* rec gain */
+#define ALC5632_ADC_REC_GAIN_RANGE             0x1F1F
+#define ALC5632_ADC_REC_GAIN_BASE              (-16.5)
+#define ALC5632_ADC_REC_GAIN_STEP              1.5
+
+#define ALC5632_ADC_REC_MIXER                  0x14 /* mixer control */
+#define ALC5632_ADC_REC_MIC1                   (1 << 6)
+#define ALC5632_ADC_REC_MIC2                   (1 << 5)
+#define ALC5632_ADC_REC_LINE_IN                        (1 << 4)
+#define ALC5632_ADC_REC_AUX                    (1 << 3)
+#define ALC5632_ADC_REC_HP                     (1 << 2)
+#define ALC5632_ADC_REC_SPK                    (1 << 1)
+#define ALC5632_ADC_REC_MONOMIX                        (1 << 0)
+
+#define ALC5632_VOICE_DAC_VOL                  0x18 /* voice dac vol */
+/* ALC5632_OUTPUT_MIXER_CTRL :                 */
+/* same remark as for reg 2 line vs speaker    */
+#define ALC5632_OUTPUT_MIXER_CTRL              0x1C /* out mix ctrl */
+#define ALC5632_OUTPUT_MIXER_RP                        (1 << 14)
+#define ALC5632_OUTPUT_MIXER_WEEK              (1 << 12)
+#define ALC5632_OUTPUT_MIXER_HP                        (1 << 10)
+#define ALC5632_OUTPUT_MIXER_AUX_SPK           (2 <<  6)
+#define ALC5632_OUTPUT_MIXER_AUX_HP_LR          (1 << 6)
+#define ALC5632_OUTPUT_MIXER_HP_R               (1 << 8)
+#define ALC5632_OUTPUT_MIXER_HP_L               (1 << 9)
+
+#define ALC5632_MIC_CTRL                       0x22 /* mic phone ctrl */
+#define ALC5632_MIC_BOOST_BYPASS               0
+#define ALC5632_MIC_BOOST_20DB                 1
+#define ALC5632_MIC_BOOST_30DB                 2
+#define ALC5632_MIC_BOOST_40DB                 3
+
+#define ALC5632_DIGI_BOOST_CTRL                        0x24 /* digi mic / bost ctl */
+#define ALC5632_MIC_BOOST_RANGE                        7
+#define ALC5632_MIC_BOOST_STEP                 6
+#define ALC5632_PWR_DOWN_CTRL_STATUS           0x26
+#define ALC5632_PWR_DOWN_CTRL_STATUS_MASK      0xEF00
+#define ALC5632_PWR_VREF_PR3                   (1 << 11)
+#define ALC5632_PWR_VREF_PR2                   (1 << 10)
+#define ALC5632_PWR_VREF_STATUS                        (1 << 3)
+#define ALC5632_PWR_AMIX_STATUS                        (1 << 2)
+#define ALC5632_PWR_DAC_STATUS                 (1 << 1)
+#define ALC5632_PWR_ADC_STATUS                 (1 << 0)
+/* stereo/voice DAC / stereo adc func ctrl */
+#define ALC5632_DAC_FUNC_SELECT                        0x2E
+
+/* Main serial data port ctrl (i2s) */
+#define ALC5632_DAI_CONTROL                    0x34
+
+#define ALC5632_DAI_SDP_MASTER_MODE            (0 << 15)
+#define ALC5632_DAI_SDP_SLAVE_MODE             (1 << 15)
+#define ALC5632_DAI_SADLRCK_MODE               (1 << 14)
+/* 0:voice, 1:main */
+#define ALC5632_DAI_MAIN_I2S_SYSCLK_SEL                (1 <<  8)
+#define ALC5632_DAI_MAIN_I2S_BCLK_POL_CTRL     (1 <<  7)
+/* 0:normal, 1:invert */
+#define ALC5632_DAI_MAIN_I2S_LRCK_INV          (1 <<  6)
+#define ALC5632_DAI_I2S_DL_MASK                        (3 <<  2)
+#define ALC5632_DAI_I2S_DL_8                   (3 <<  2)
+#define        ALC5632_DAI_I2S_DL_24                   (2 <<  2)
+#define        ALC5632_DAI_I2S_DL_20                   (1 <<  2)
+#define ALC5632_DAI_I2S_DL_16                  (0 <<  2)
+#define ALC5632_DAI_I2S_DF_MASK                        (3 <<  0)
+#define ALC5632_DAI_I2S_DF_PCM_B               (3 <<  0)
+#define        ALC5632_DAI_I2S_DF_PCM_A                (2 <<  0)
+#define ALC5632_DAI_I2S_DF_LEFT                        (1 <<  0)
+#define ALC5632_DAI_I2S_DF_I2S                 (0 <<  0)
+/* extend serial data port control (VoDAC_i2c/pcm) */
+#define ALC5632_DAI_CONTROL2                   0x36
+/* 0:gpio func, 1:voice pcm */
+#define ALC5632_DAI_VOICE_PCM_ENABLE           (1 << 15)
+/* 0:master, 1:slave */
+#define ALC5632_DAI_VOICE_MODE_SEL             (1 << 14)
+/* 0:disable, 1:enable */
+#define ALC5632_DAI_HPF_CLK_CTRL               (1 << 13)
+/* 0:main, 1:voice */
+#define ALC5632_DAI_VOICE_I2S_SYSCLK_SEL       (1 <<  8)
+/* 0:normal, 1:invert */
+#define ALC5632_DAI_VOICE_VBCLK_SYSCLK_SEL     (1 <<  7)
+/* 0:normal, 1:invert */
+#define ALC5632_DAI_VOICE_I2S_LR_INV           (1 <<  6)
+#define ALC5632_DAI_VOICE_DL_MASK              (3 <<  2)
+#define ALC5632_DAI_VOICE_DL_16                        (0 <<  2)
+#define ALC5632_DAI_VOICE_DL_20                        (1 <<  2)
+#define ALC5632_DAI_VOICE_DL_24                        (2 <<  2)
+#define ALC5632_DAI_VOICE_DL_8                 (3 <<  2)
+#define ALC5632_DAI_VOICE_DF_MASK              (3 <<  0)
+#define ALC5632_DAI_VOICE_DF_I2S               (0 <<  0)
+#define ALC5632_DAI_VOICE_DF_LEFT              (1 <<  0)
+#define ALC5632_DAI_VOICE_DF_PCM_A             (2 <<  0)
+#define ALC5632_DAI_VOICE_DF_PCM_B             (3 <<  0)
+
+#define        ALC5632_PWR_MANAG_ADD1                  0x3A
+#define        ALC5632_PWR_MANAG_ADD1_MASK             0xEFFF
+#define ALC5632_PWR_ADD1_DAC_L_EN              (1 << 15)
+#define ALC5632_PWR_ADD1_DAC_R_EN              (1 << 14)
+#define ALC5632_PWR_ADD1_ZERO_CROSS            (1 << 13)
+#define ALC5632_PWR_ADD1_MAIN_I2S_EN           (1 << 11)
+#define ALC5632_PWR_ADD1_SPK_AMP_EN            (1 << 10)
+#define ALC5632_PWR_ADD1_HP_OUT_AMP            (1 <<  9)
+#define ALC5632_PWR_ADD1_HP_OUT_ENH_AMP                (1 <<  8)
+#define ALC5632_PWR_ADD1_VOICE_DAC_MIX         (1 <<  7)
+#define        ALC5632_PWR_ADD1_SOFTGEN_EN             (1 <<  6)
+#define        ALC5632_PWR_ADD1_MIC1_SHORT_CURR        (1 <<  5)
+#define        ALC5632_PWR_ADD1_MIC2_SHORT_CURR        (1 <<  4)
+#define        ALC5632_PWR_ADD1_MIC1_EN                (1 <<  3)
+#define        ALC5632_PWR_ADD1_MIC2_EN                (1 <<  2)
+#define ALC5632_PWR_ADD1_MAIN_BIAS             (1 <<  1)
+#define ALC5632_PWR_ADD1_DAC_REF               (1 <<  0)
+
+#define ALC5632_PWR_MANAG_ADD2                 0x3C
+#define ALC5632_PWR_MANAG_ADD2_MASK            0x7FFF
+#define ALC5632_PWR_ADD2_PLL1                  (1 << 15)
+#define ALC5632_PWR_ADD2_PLL2                  (1 << 14)
+#define ALC5632_PWR_ADD2_VREF                  (1 << 13)
+#define ALC5632_PWR_ADD2_OVT_DET               (1 << 12)
+#define ALC5632_PWR_ADD2_VOICE_DAC             (1 << 10)
+#define ALC5632_PWR_ADD2_L_DAC_CLK             (1 <<  9)
+#define ALC5632_PWR_ADD2_R_DAC_CLK             (1 <<  8)
+#define ALC5632_PWR_ADD2_L_ADC_CLK_GAIN                (1 <<  7)
+#define ALC5632_PWR_ADD2_R_ADC_CLK_GAIN                (1 <<  6)
+#define ALC5632_PWR_ADD2_L_HP_MIXER            (1 <<  5)
+#define ALC5632_PWR_ADD2_R_HP_MIXER            (1 <<  4)
+#define ALC5632_PWR_ADD2_SPK_MIXER             (1 <<  3)
+#define ALC5632_PWR_ADD2_MONO_MIXER            (1 <<  2)
+#define ALC5632_PWR_ADD2_L_ADC_REC_MIXER       (1 <<  1)
+#define ALC5632_PWR_ADD2_R_ADC_REC_MIXER       (1 <<  0)
+
+#define ALC5632_PWR_MANAG_ADD3                 0x3E
+#define ALC5632_PWR_MANAG_ADD3_MASK            0x7CFF
+#define ALC5632_PWR_ADD3_AUXOUT_VOL            (1 << 14)
+#define ALC5632_PWR_ADD3_SPK_L_OUT             (1 << 13)
+#define ALC5632_PWR_ADD3_SPK_R_OUT             (1 << 12)
+#define ALC5632_PWR_ADD3_HP_L_OUT_VOL          (1 << 11)
+#define ALC5632_PWR_ADD3_HP_R_OUT_VOL          (1 << 10)
+#define ALC5632_PWR_ADD3_LINEIN_L_VOL          (1 <<  7)
+#define ALC5632_PWR_ADD3_LINEIN_R_VOL          (1 <<  6)
+#define ALC5632_PWR_ADD3_AUXIN_VOL             (1 <<  5)
+#define ALC5632_PWR_ADD3_AUXIN_MIX             (1 <<  4)
+#define ALC5632_PWR_ADD3_MIC1_VOL              (1 <<  3)
+#define ALC5632_PWR_ADD3_MIC2_VOL              (1 <<  2)
+#define ALC5632_PWR_ADD3_MIC1_BOOST_AD         (1 <<  1)
+#define ALC5632_PWR_ADD3_MIC2_BOOST_AD         (1 <<  0)
+
+#define ALC5632_GPCR1                          0x40
+#define ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1     (1 << 15)
+#define ALC5632_GPCR1_CLK_SYS_SRC_SEL_MCLK     (0 << 15)
+#define ALC5632_GPCR1_DAC_HI_FLT_EN            (1 << 10)
+#define ALC5632_GPCR1_SPK_AMP_CTRL             (7 <<  1)
+#define ALC5632_GPCR1_VDD_100                  (5 <<  1)
+#define ALC5632_GPCR1_VDD_125                  (4 <<  1)
+#define ALC5632_GPCR1_VDD_150                  (3 <<  1)
+#define ALC5632_GPCR1_VDD_175                  (2 <<  1)
+#define ALC5632_GPCR1_VDD_200                  (1 <<  1)
+#define ALC5632_GPCR1_VDD_225                  (0 <<  1)
+
+#define        ALC5632_GPCR2                           0x42
+#define ALC5632_GPCR2_PLL1_SOUR_SEL            (3 << 12)
+#define ALC5632_PLL_FR_MCLK                    (0 << 12)
+#define ALC5632_PLL_FR_BCLK                    (2 << 12)
+#define ALC5632_PLL_FR_VBCLK                   (3 << 12)
+#define ALC5632_GPCR2_CLK_PLL_PRE_DIV1         (0 <<  0)
+
+#define ALC5632_PLL1_CTRL                      0x44
+#define ALC5632_PLL1_CTRL_N_VAL(n)             (((n) & 0x0f) << 8)
+#define ALC5632_PLL1_M_BYPASS                  (1 <<  7)
+#define ALC5632_PLL1_CTRL_K_VAL(k)             (((k) & 0x07) << 4)
+#define ALC5632_PLL1_CTRL_M_VAL(m)             (((m) & 0x0f) << 0)
+
+#define ALC5632_PLL2_CTRL                      0x46
+#define ALC5632_PLL2_EN                                (1 << 15)
+#define ALC5632_PLL2_RATIO                     (0 << 15)
+
+#define ALC5632_GPIO_PIN_CONFIG                        0x4C
+#define ALC5632_GPIO_PIN_POLARITY              0x4E
+#define ALC5632_GPIO_PIN_STICKY                        0x50
+#define ALC5632_GPIO_PIN_WAKEUP                        0x52
+#define ALC5632_GPIO_PIN_STATUS                        0x54
+#define ALC5632_GPIO_PIN_SHARING               0x56
+#define        ALC5632_OVER_CURR_STATUS                0x58
+#define ALC5632_SOFTVOL_CTRL                   0x5A
+#define ALC5632_GPIO_OUPUT_PIN_CTRL            0x5C
+
+#define ALC5632_MISC_CTRL                      0x5E
+#define ALC5632_MISC_DISABLE_FAST_VREG         (1 << 15)
+#define ALC5632_MISC_AVC_TRGT_SEL              (3 << 12)
+#define ALC5632_MISC_AVC_TRGT_RIGHT            (1 << 12)
+#define ALC5632_MISC_AVC_TRGT_LEFT             (2 << 12)
+#define ALC5632_MISC_AVC_TRGT_BOTH             (3 << 12)
+#define ALC5632_MISC_HP_DEPOP_MODE1_EN         (1 <<  9)
+#define ALC5632_MISC_HP_DEPOP_MODE2_EN         (1 <<  8)
+#define ALC5632_MISC_HP_DEPOP_MUTE_L           (1 <<  7)
+#define ALC5632_MISC_HP_DEPOP_MUTE_R           (1 <<  6)
+#define ALC5632_MISC_HP_DEPOP_MUTE             (1 <<  5)
+#define ALC5632_MISC_GPIO_WAKEUP_CTRL          (1 <<  1)
+#define ALC5632_MISC_IRQOUT_INV_CTRL           (1 <<  0)
+
+#define ALC5632_DAC_CLK_CTRL1                  0x60
+#define ALC5632_DAC_CLK_CTRL2                  0x62
+#define ALC5632_DAC_CLK_CTRL2_DIV1_2           (1 << 0)
+#define ALC5632_VOICE_DAC_PCM_CLK_CTRL1                0x64
+#define ALC5632_PSEUDO_SPATIAL_CTRL            0x68
+#define ALC5632_HID_CTRL_INDEX                 0x6A
+#define ALC5632_HID_CTRL_DATA                  0x6C
+#define ALC5632_EQ_CTRL                                0x6E
+
+/* undocumented */
+#define ALC5632_VENDOR_ID1                     0x7C
+#define ALC5632_VENDOR_ID2                     0x7E
+
+#define ALC5632_MAX_REGISTER        0x7E
+
+#endif
index 46dbfd0..4854b47 100644 (file)
@@ -122,7 +122,7 @@ static int cq93vc_set_bias_level(struct snd_soc_codec *codec,
 #define CQ93VC_RATES   (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000)
 #define CQ93VC_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
 
-static struct snd_soc_dai_ops cq93vc_dai_ops = {
+static const struct snd_soc_dai_ops cq93vc_dai_ops = {
        .digital_mute   = cq93vc_mute,
        .set_sysclk     = cq93vc_set_dai_sysclk,
 };
@@ -206,17 +206,7 @@ static struct platform_driver cq93vc_codec_driver = {
        .remove = __devexit_p(cq93vc_platform_remove),
 };
 
-static int __init cq93vc_init(void)
-{
-       return platform_driver_register(&cq93vc_codec_driver);
-}
-module_init(cq93vc_init);
-
-static void __exit cq93vc_exit(void)
-{
-       platform_driver_unregister(&cq93vc_codec_driver);
-}
-module_exit(cq93vc_exit);
+module_platform_driver(cq93vc_codec_driver);
 
 MODULE_DESCRIPTION("Texas Instruments DaVinci ASoC CQ0093 Voice Codec Driver");
 MODULE_AUTHOR("Miguel Aguilar");
index f1f237e..fef0f48 100644 (file)
@@ -22,7 +22,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/soc.h>
@@ -447,7 +446,7 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {
                snd_soc_get_volsw, cs4270_soc_put_mute),
 };
 
-static struct snd_soc_dai_ops cs4270_dai_ops = {
+static const struct snd_soc_dai_ops cs4270_dai_ops = {
        .hw_params      = cs4270_hw_params,
        .set_sysclk     = cs4270_set_dai_sysclk,
        .set_fmt        = cs4270_set_dai_fmt,
@@ -579,7 +578,7 @@ static int cs4270_remove(struct snd_soc_codec *codec)
  * and all registers are written back to the hardware when resuming.
  */
 
-static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
+static int cs4270_soc_suspend(struct snd_soc_codec *codec)
 {
        struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
        int reg, ret;
@@ -601,7 +600,6 @@ 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 = to_i2c_client(codec->dev);
        int reg;
 
        regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
@@ -612,14 +610,7 @@ static int cs4270_soc_resume(struct snd_soc_codec *codec)
        ndelay(500);
 
        /* first restore the entire register cache ... */
-       for (reg = CS4270_FIRSTREG; reg <= CS4270_LASTREG; reg++) {
-               u8 val = snd_soc_read(codec, reg);
-
-               if (i2c_smbus_write_byte_data(i2c_client, reg, val)) {
-                       dev_err(codec->dev, "i2c write failed\n");
-                       return -EIO;
-               }
-       }
+       snd_soc_cache_sync(codec);
 
        /* ... then disable the power-down bits */
        reg = snd_soc_read(codec, CS4270_PWRCTL);
index 23d1bd5..f6fe846 100644 (file)
@@ -402,7 +402,7 @@ static const struct snd_kcontrol_new cs4271_snd_controls[] = {
                7, 1, 1),
 };
 
-static struct snd_soc_dai_ops cs4271_dai_ops = {
+static const struct snd_soc_dai_ops cs4271_dai_ops = {
        .hw_params      = cs4271_hw_params,
        .set_sysclk     = cs4271_set_dai_sysclk,
        .set_fmt        = cs4271_set_dai_fmt,
@@ -430,11 +430,12 @@ static struct snd_soc_dai_driver cs4271_dai = {
 };
 
 #ifdef CONFIG_PM
-static int cs4271_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
+static int cs4271_soc_suspend(struct snd_soc_codec *codec)
 {
        int ret;
        /* Set power-down bit */
-       ret = snd_soc_update_bits(codec, CS4271_MODE2, 0, CS4271_MODE2_PDN);
+       ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN,
+                                 CS4271_MODE2_PDN);
        if (ret < 0)
                return ret;
        return 0;
@@ -501,8 +502,9 @@ static int cs4271_probe(struct snd_soc_codec *codec)
                return ret;
        }
 
-       ret = snd_soc_update_bits(codec, CS4271_MODE2, 0,
-               CS4271_MODE2_PDN | CS4271_MODE2_CPEN);
+       ret = snd_soc_update_bits(codec, CS4271_MODE2,
+                                 CS4271_MODE2_PDN | CS4271_MODE2_CPEN,
+                                 CS4271_MODE2_PDN | CS4271_MODE2_CPEN);
        if (ret < 0)
                return ret;
        ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0);
index 8c3c820..528510b 100644 (file)
@@ -22,7 +22,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/soc.h>
@@ -175,21 +174,18 @@ static const struct snd_kcontrol_new cs42l51_snd_controls[] = {
 static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w,
                struct snd_kcontrol *kcontrol, int event)
 {
-       unsigned long value;
-
-       value = snd_soc_read(w->codec, CS42L51_POWER_CTL1);
-       value &= ~CS42L51_POWER_CTL1_PDN;
-
        switch (event) {
        case SND_SOC_DAPM_PRE_PMD:
-               value |= CS42L51_POWER_CTL1_PDN;
+               snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1,
+                                   CS42L51_POWER_CTL1_PDN,
+                                   CS42L51_POWER_CTL1_PDN);
                break;
        default:
        case SND_SOC_DAPM_POST_PMD:
+               snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1,
+                                   CS42L51_POWER_CTL1_PDN, 0);
                break;
        }
-       snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1,
-               CS42L51_POWER_CTL1_PDN, value);
 
        return 0;
 }
@@ -486,7 +482,7 @@ static int cs42l51_dai_mute(struct snd_soc_dai *dai, int mute)
        return snd_soc_write(codec, CS42L51_DAC_OUT_CTL, reg);
 }
 
-static struct snd_soc_dai_ops cs42l51_dai_ops = {
+static const struct snd_soc_dai_ops cs42l51_dai_ops = {
        .hw_params      = cs42l51_hw_params,
        .set_sysclk     = cs42l51_set_dai_sysclk,
        .set_fmt        = cs42l51_set_dai_fmt,
@@ -555,7 +551,7 @@ static int cs42l51_probe(struct snd_soc_codec *codec)
 
 static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
        .probe =        cs42l51_probe,
-       .reg_cache_size = CS42L51_NUMREGS,
+       .reg_cache_size = CS42L51_NUMREGS + 1,
        .reg_word_size = sizeof(u8),
 };
 
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
new file mode 100644 (file)
index 0000000..9d38db8
--- /dev/null
@@ -0,0 +1,1453 @@
+/*
+ * cs42l73.c  --  CS42L73 ALSA Soc Audio driver
+ *
+ * Copyright 2011 Cirrus Logic, Inc.
+ *
+ * Authors: Georgi Vlaev, Nucleus Systems Ltd, <joe@nucleusys.com>
+ *         Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include "cs42l73.h"
+
+struct sp_config {
+       u8 spc, mmcc, spfs;
+       u32 srate;
+};
+struct  cs42l73_private {
+       struct sp_config config[3];
+       struct regmap *regmap;
+       u32 sysclk;
+       u8 mclksel;
+       u32 mclk;
+};
+
+static const struct reg_default cs42l73_reg_defaults[] = {
+       { 1, 0x42 },    /* r01  - Device ID A&B */
+       { 2, 0xA7 },    /* r02  - Device ID C&D */
+       { 3, 0x30 },    /* r03  - Device ID E */
+       { 6, 0xF1 },    /* r06  - Power Ctl 1 */
+       { 7, 0xDF },    /* r07  - Power Ctl 2 */
+       { 8, 0x3F },    /* r08  - Power Ctl 3 */
+       { 9, 0x50 },    /* r09  - Charge Pump Freq */
+       { 10, 0x53 },   /* r0A  - Output Load MicBias Short Detect */
+       { 11, 0x00 },   /* r0B  - DMIC Master Clock Ctl */
+       { 12, 0x00 },   /* r0C  - Aux PCM Ctl */
+       { 13, 0x15 },   /* r0D  - Aux PCM Master Clock Ctl */
+       { 14, 0x00 },   /* r0E  - Audio PCM Ctl */
+       { 15, 0x15 },   /* r0F  - Audio PCM Master Clock Ctl */
+       { 16, 0x00 },   /* r10  - Voice PCM Ctl */
+       { 17, 0x15 },   /* r11  - Voice PCM Master Clock Ctl */
+       { 18, 0x00 },   /* r12  - Voice/Aux Sample Rate */
+       { 19, 0x06 },   /* r13  - Misc I/O Path Ctl */
+       { 20, 0x00 },   /* r14  - ADC Input Path Ctl */
+       { 21, 0x00 },   /* r15  - MICA Preamp, PGA Volume */
+       { 22, 0x00 },   /* r16  - MICB Preamp, PGA Volume */
+       { 23, 0x00 },   /* r17  - Input Path A Digital Volume */
+       { 24, 0x00 },   /* r18  - Input Path B Digital Volume */
+       { 25, 0x00 },   /* r19  - Playback Digital Ctl */
+       { 26, 0x00 },   /* r1A  - HP/LO Left Digital Volume */
+       { 27, 0x00 },   /* r1B  - HP/LO Right Digital Volume */
+       { 28, 0x00 },   /* r1C  - Speakerphone Digital Volume */
+       { 29, 0x00 },   /* r1D  - Ear/SPKLO Digital Volume */
+       { 30, 0x00 },   /* r1E  - HP Left Analog Volume */
+       { 31, 0x00 },   /* r1F  - HP Right Analog Volume */
+       { 32, 0x00 },   /* r20  - LO Left Analog Volume */
+       { 33, 0x00 },   /* r21  - LO Right Analog Volume */
+       { 34, 0x00 },   /* r22  - Stereo Input Path Advisory Volume */
+       { 35, 0x00 },   /* r23  - Aux PCM Input Advisory Volume */
+       { 36, 0x00 },   /* r24  - Audio PCM Input Advisory Volume */
+       { 37, 0x00 },   /* r25  - Voice PCM Input Advisory Volume */
+       { 38, 0x00 },   /* r26  - Limiter Attack Rate HP/LO */
+       { 39, 0x7F },   /* r27  - Limter Ctl, Release Rate HP/LO */
+       { 40, 0x00 },   /* r28  - Limter Threshold HP/LO */
+       { 41, 0x00 },   /* r29  - Limiter Attack Rate Speakerphone */
+       { 42, 0x3F },   /* r2A  - Limter Ctl, Release Rate Speakerphone */
+       { 43, 0x00 },   /* r2B  - Limter Threshold Speakerphone */
+       { 44, 0x00 },   /* r2C  - Limiter Attack Rate Ear/SPKLO */
+       { 45, 0x3F },   /* r2D  - Limter Ctl, Release Rate Ear/SPKLO */
+       { 46, 0x00 },   /* r2E  - Limter Threshold Ear/SPKLO */
+       { 47, 0x00 },   /* r2F  - ALC Enable, Attack Rate Left/Right */
+       { 48, 0x3F },   /* r30  - ALC Release Rate Left/Right */
+       { 49, 0x00 },   /* r31  - ALC Threshold Left/Right */
+       { 50, 0x00 },   /* r32  - Noise Gate Ctl Left/Right */
+       { 51, 0x00 },   /* r33  - ALC/NG Misc Ctl */
+       { 52, 0x18 },   /* r34  - Mixer Ctl */
+       { 53, 0x3F },   /* r35  - HP/LO Left Mixer Input Path Volume */
+       { 54, 0x3F },   /* r36  - HP/LO Right Mixer Input Path Volume */
+       { 55, 0x3F },   /* r37  - HP/LO Left Mixer Aux PCM Volume */
+       { 56, 0x3F },   /* r38  - HP/LO Right Mixer Aux PCM Volume */
+       { 57, 0x3F },   /* r39  - HP/LO Left Mixer Audio PCM Volume */
+       { 58, 0x3F },   /* r3A  - HP/LO Right Mixer Audio PCM Volume */
+       { 59, 0x3F },   /* r3B  - HP/LO Left Mixer Voice PCM Mono Volume */
+       { 60, 0x3F },   /* r3C  - HP/LO Right Mixer Voice PCM Mono Volume */
+       { 61, 0x3F },   /* r3D  - Aux PCM Left Mixer Input Path Volume */
+       { 62, 0x3F },   /* r3E  - Aux PCM Right Mixer Input Path Volume */
+       { 63, 0x3F },   /* r3F  - Aux PCM Left Mixer Volume */
+       { 64, 0x3F },   /* r40  - Aux PCM Left Mixer Volume */
+       { 65, 0x3F },   /* r41  - Aux PCM Left Mixer Audio PCM L Volume */
+       { 66, 0x3F },   /* r42  - Aux PCM Right Mixer Audio PCM R Volume */
+       { 67, 0x3F },   /* r43  - Aux PCM Left Mixer Voice PCM Volume */
+       { 68, 0x3F },   /* r44  - Aux PCM Right Mixer Voice PCM Volume */
+       { 69, 0x3F },   /* r45  - Audio PCM Left Input Path Volume */
+       { 70, 0x3F },   /* r46  - Audio PCM Right Input Path Volume */
+       { 71, 0x3F },   /* r47  - Audio PCM Left Mixer Aux PCM L Volume */
+       { 72, 0x3F },   /* r48  - Audio PCM Right Mixer Aux PCM R Volume */
+       { 73, 0x3F },   /* r49  - Audio PCM Left Mixer Volume */
+       { 74, 0x3F },   /* r4A  - Audio PCM Right Mixer Volume */
+       { 75, 0x3F },   /* r4B  - Audio PCM Left Mixer Voice PCM Volume */
+       { 76, 0x3F },   /* r4C  - Audio PCM Right Mixer Voice PCM Volume */
+       { 77, 0x3F },   /* r4D  - Voice PCM Left Input Path Volume */
+       { 78, 0x3F },   /* r4E  - Voice PCM Right Input Path Volume */
+       { 79, 0x3F },   /* r4F  - Voice PCM Left Mixer Aux PCM L Volume */
+       { 80, 0x3F },   /* r50  - Voice PCM Right Mixer Aux PCM R Volume */
+       { 81, 0x3F },   /* r51  - Voice PCM Left Mixer Audio PCM L Volume */
+       { 82, 0x3F },   /* r52  - Voice PCM Right Mixer Audio PCM R Volume */
+       { 83, 0x3F },   /* r53  - Voice PCM Left Mixer Voice PCM Volume */
+       { 84, 0x3F },   /* r54  - Voice PCM Right Mixer Voice PCM Volume */
+       { 85, 0xAA },   /* r55  - Mono Mixer Ctl */
+       { 86, 0x3F },   /* r56  - SPK Mono Mixer Input Path Volume */
+       { 87, 0x3F },   /* r57  - SPK Mono Mixer Aux PCM Mono/L/R Volume */
+       { 88, 0x3F },   /* r58  - SPK Mono Mixer Audio PCM Mono/L/R Volume */
+       { 89, 0x3F },   /* r59  - SPK Mono Mixer Voice PCM Mono Volume */
+       { 90, 0x3F },   /* r5A  - SPKLO Mono Mixer Input Path Mono Volume */
+       { 91, 0x3F },   /* r5B  - SPKLO Mono Mixer Aux Mono/L/R Volume */
+       { 92, 0x3F },   /* r5C  - SPKLO Mono Mixer Audio Mono/L/R Volume */
+       { 93, 0x3F },   /* r5D  - SPKLO Mono Mixer Voice Mono Volume */
+       { 94, 0x00 },   /* r5E  - Interrupt Mask 1 */
+       { 95, 0x00 },   /* r5F  - Interrupt Mask 2 */
+};
+
+static bool cs42l73_volatile_register(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case CS42L73_IS1:
+       case CS42L73_IS2:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool cs42l73_readable_register(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case CS42L73_DEVID_AB:
+       case CS42L73_DEVID_CD:
+       case CS42L73_DEVID_E:
+       case CS42L73_REVID:
+       case CS42L73_PWRCTL1:
+       case CS42L73_PWRCTL2:
+       case CS42L73_PWRCTL3:
+       case CS42L73_CPFCHC:
+       case CS42L73_OLMBMSDC:
+       case CS42L73_DMMCC:
+       case CS42L73_XSPC:
+       case CS42L73_XSPMMCC:
+       case CS42L73_ASPC:
+       case CS42L73_ASPMMCC:
+       case CS42L73_VSPC:
+       case CS42L73_VSPMMCC:
+       case CS42L73_VXSPFS:
+       case CS42L73_MIOPC:
+       case CS42L73_ADCIPC:
+       case CS42L73_MICAPREPGAAVOL:
+       case CS42L73_MICBPREPGABVOL:
+       case CS42L73_IPADVOL:
+       case CS42L73_IPBDVOL:
+       case CS42L73_PBDC:
+       case CS42L73_HLADVOL:
+       case CS42L73_HLBDVOL:
+       case CS42L73_SPKDVOL:
+       case CS42L73_ESLDVOL:
+       case CS42L73_HPAAVOL:
+       case CS42L73_HPBAVOL:
+       case CS42L73_LOAAVOL:
+       case CS42L73_LOBAVOL:
+       case CS42L73_STRINV:
+       case CS42L73_XSPINV:
+       case CS42L73_ASPINV:
+       case CS42L73_VSPINV:
+       case CS42L73_LIMARATEHL:
+       case CS42L73_LIMRRATEHL:
+       case CS42L73_LMAXHL:
+       case CS42L73_LIMARATESPK:
+       case CS42L73_LIMRRATESPK:
+       case CS42L73_LMAXSPK:
+       case CS42L73_LIMARATEESL:
+       case CS42L73_LIMRRATEESL:
+       case CS42L73_LMAXESL:
+       case CS42L73_ALCARATE:
+       case CS42L73_ALCRRATE:
+       case CS42L73_ALCMINMAX:
+       case CS42L73_NGCAB:
+       case CS42L73_ALCNGMC:
+       case CS42L73_MIXERCTL:
+       case CS42L73_HLAIPAA:
+       case CS42L73_HLBIPBA:
+       case CS42L73_HLAXSPAA:
+       case CS42L73_HLBXSPBA:
+       case CS42L73_HLAASPAA:
+       case CS42L73_HLBASPBA:
+       case CS42L73_HLAVSPMA:
+       case CS42L73_HLBVSPMA:
+       case CS42L73_XSPAIPAA:
+       case CS42L73_XSPBIPBA:
+       case CS42L73_XSPAXSPAA:
+       case CS42L73_XSPBXSPBA:
+       case CS42L73_XSPAASPAA:
+       case CS42L73_XSPAASPBA:
+       case CS42L73_XSPAVSPMA:
+       case CS42L73_XSPBVSPMA:
+       case CS42L73_ASPAIPAA:
+       case CS42L73_ASPBIPBA:
+       case CS42L73_ASPAXSPAA:
+       case CS42L73_ASPBXSPBA:
+       case CS42L73_ASPAASPAA:
+       case CS42L73_ASPBASPBA:
+       case CS42L73_ASPAVSPMA:
+       case CS42L73_ASPBVSPMA:
+       case CS42L73_VSPAIPAA:
+       case CS42L73_VSPBIPBA:
+       case CS42L73_VSPAXSPAA:
+       case CS42L73_VSPBXSPBA:
+       case CS42L73_VSPAASPAA:
+       case CS42L73_VSPBASPBA:
+       case CS42L73_VSPAVSPMA:
+       case CS42L73_VSPBVSPMA:
+       case CS42L73_MMIXCTL:
+       case CS42L73_SPKMIPMA:
+       case CS42L73_SPKMXSPA:
+       case CS42L73_SPKMASPA:
+       case CS42L73_SPKMVSPMA:
+       case CS42L73_ESLMIPMA:
+       case CS42L73_ESLMXSPA:
+       case CS42L73_ESLMASPA:
+       case CS42L73_ESLMVSPMA:
+       case CS42L73_IM1:
+       case CS42L73_IM2:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static const unsigned int hpaloa_tlv[] = {
+       TLV_DB_RANGE_HEAD(2),
+       0, 13, TLV_DB_SCALE_ITEM(-7600, 200, 0),
+       14, 75, TLV_DB_SCALE_ITEM(-4900, 100, 0),
+};
+
+static DECLARE_TLV_DB_SCALE(adc_boost_tlv, 0, 2500, 0);
+
+static DECLARE_TLV_DB_SCALE(hl_tlv, -10200, 50, 0);
+
+static DECLARE_TLV_DB_SCALE(ipd_tlv, -9600, 100, 0);
+
+static DECLARE_TLV_DB_SCALE(micpga_tlv, -600, 50, 0);
+
+static const unsigned int limiter_tlv[] = {
+       TLV_DB_RANGE_HEAD(2),
+       0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0),
+       3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0),
+};
+
+static const DECLARE_TLV_DB_SCALE(attn_tlv, -6300, 100, 1);
+
+static const char * const cs42l73_pgaa_text[] = { "Line A", "Mic 1" };
+static const char * const cs42l73_pgab_text[] = { "Line B", "Mic 2" };
+
+static const struct soc_enum pgaa_enum =
+       SOC_ENUM_SINGLE(CS42L73_ADCIPC, 3,
+               ARRAY_SIZE(cs42l73_pgaa_text), cs42l73_pgaa_text);
+
+static const struct soc_enum pgab_enum =
+       SOC_ENUM_SINGLE(CS42L73_ADCIPC, 7,
+               ARRAY_SIZE(cs42l73_pgab_text), cs42l73_pgab_text);
+
+static const struct snd_kcontrol_new pgaa_mux =
+       SOC_DAPM_ENUM("Left Analog Input Capture Mux", pgaa_enum);
+
+static const struct snd_kcontrol_new pgab_mux =
+       SOC_DAPM_ENUM("Right Analog Input Capture Mux", pgab_enum);
+
+static const struct snd_kcontrol_new input_left_mixer[] = {
+       SOC_DAPM_SINGLE("ADC Left Input", CS42L73_PWRCTL1,
+                       5, 1, 1),
+       SOC_DAPM_SINGLE("DMIC Left Input", CS42L73_PWRCTL1,
+                       4, 1, 1),
+};
+
+static const struct snd_kcontrol_new input_right_mixer[] = {
+       SOC_DAPM_SINGLE("ADC Right Input", CS42L73_PWRCTL1,
+                       7, 1, 1),
+       SOC_DAPM_SINGLE("DMIC Right Input", CS42L73_PWRCTL1,
+                       6, 1, 1),
+};
+
+static const char * const cs42l73_ng_delay_text[] = {
+       "50ms", "100ms", "150ms", "200ms" };
+
+static const struct soc_enum ng_delay_enum =
+       SOC_ENUM_SINGLE(CS42L73_NGCAB, 0,
+               ARRAY_SIZE(cs42l73_ng_delay_text), cs42l73_ng_delay_text);
+
+static const char * const charge_pump_freq_text[] = {
+       "0", "1", "2", "3", "4",
+       "5", "6", "7", "8", "9",
+       "10", "11", "12", "13", "14", "15" };
+
+static const struct soc_enum charge_pump_enum =
+       SOC_ENUM_SINGLE(CS42L73_CPFCHC, 4,
+               ARRAY_SIZE(charge_pump_freq_text), charge_pump_freq_text);
+
+static const char * const cs42l73_mono_mix_texts[] = {
+       "Left", "Right", "Mono Mix"};
+
+static const unsigned int cs42l73_mono_mix_values[] = { 0, 1, 2 };
+
+static const struct soc_enum spk_asp_enum =
+       SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 1,
+                             ARRAY_SIZE(cs42l73_mono_mix_texts),
+                             cs42l73_mono_mix_texts,
+                             cs42l73_mono_mix_values);
+
+static const struct snd_kcontrol_new spk_asp_mixer =
+       SOC_DAPM_ENUM("Route", spk_asp_enum);
+
+static const struct soc_enum spk_xsp_enum =
+       SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 4, 3,
+                             ARRAY_SIZE(cs42l73_mono_mix_texts),
+                             cs42l73_mono_mix_texts,
+                             cs42l73_mono_mix_values);
+
+static const struct snd_kcontrol_new spk_xsp_mixer =
+       SOC_DAPM_ENUM("Route", spk_xsp_enum);
+
+static const struct soc_enum esl_asp_enum =
+       SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 5,
+                             ARRAY_SIZE(cs42l73_mono_mix_texts),
+                             cs42l73_mono_mix_texts,
+                             cs42l73_mono_mix_values);
+
+static const struct snd_kcontrol_new esl_asp_mixer =
+       SOC_DAPM_ENUM("Route", esl_asp_enum);
+
+static const struct soc_enum esl_xsp_enum =
+       SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 7,
+                             ARRAY_SIZE(cs42l73_mono_mix_texts),
+                             cs42l73_mono_mix_texts,
+                             cs42l73_mono_mix_values);
+
+static const struct snd_kcontrol_new esl_xsp_mixer =
+       SOC_DAPM_ENUM("Route", esl_xsp_enum);
+
+static const char * const cs42l73_ip_swap_text[] = {
+       "Stereo", "Mono A", "Mono B", "Swap A-B"};
+
+static const struct soc_enum ip_swap_enum =
+       SOC_ENUM_SINGLE(CS42L73_MIOPC, 6,
+               ARRAY_SIZE(cs42l73_ip_swap_text), cs42l73_ip_swap_text);
+
+static const char * const cs42l73_spo_mixer_text[] = {"Mono", "Stereo"};
+
+static const struct soc_enum vsp_output_mux_enum =
+       SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 5,
+               ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text);
+
+static const struct soc_enum xsp_output_mux_enum =
+       SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 4,
+               ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text);
+
+static const struct snd_kcontrol_new vsp_output_mux =
+       SOC_DAPM_ENUM("Route", vsp_output_mux_enum);
+
+static const struct snd_kcontrol_new xsp_output_mux =
+       SOC_DAPM_ENUM("Route", xsp_output_mux_enum);
+
+static const struct snd_kcontrol_new hp_amp_ctl =
+       SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 0, 1, 1);
+
+static const struct snd_kcontrol_new lo_amp_ctl =
+       SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 1, 1, 1);
+
+static const struct snd_kcontrol_new spk_amp_ctl =
+       SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 2, 1, 1);
+
+static const struct snd_kcontrol_new spklo_amp_ctl =
+       SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 4, 1, 1);
+
+static const struct snd_kcontrol_new ear_amp_ctl =
+       SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 3, 1, 1);
+
+static const struct snd_kcontrol_new cs42l73_snd_controls[] = {
+       SOC_DOUBLE_R_SX_TLV("Headphone Analog Playback Volume",
+                       CS42L73_HPAAVOL, CS42L73_HPBAVOL, 7,
+                       0xffffffC1, 0x0C, hpaloa_tlv),
+
+       SOC_DOUBLE_R_SX_TLV("LineOut Analog Playback Volume", CS42L73_LOAAVOL,
+                       CS42L73_LOBAVOL, 7, 0xffffffC1, 0x0C, hpaloa_tlv),
+
+       SOC_DOUBLE_R_SX_TLV("Input PGA Analog Volume", CS42L73_MICAPREPGAAVOL,
+                       CS42L73_MICBPREPGABVOL, 5, 0xffffff35,
+                       0x34, micpga_tlv),
+
+       SOC_DOUBLE_R("MIC Preamp Switch", CS42L73_MICAPREPGAAVOL,
+                       CS42L73_MICBPREPGABVOL, 6, 1, 1),
+
+       SOC_DOUBLE_R_SX_TLV("Input Path Digital Volume", CS42L73_IPADVOL,
+                       CS42L73_IPBDVOL, 7, 0xffffffA0, 0xA0, ipd_tlv),
+
+       SOC_DOUBLE_R_SX_TLV("HL Digital Playback Volume",
+                       CS42L73_HLADVOL, CS42L73_HLBDVOL, 7, 0xffffffE5,
+                       0xE4, hl_tlv),
+
+       SOC_SINGLE_TLV("ADC A Boost Volume",
+                       CS42L73_ADCIPC, 2, 0x01, 1, adc_boost_tlv),
+
+       SOC_SINGLE_TLV("ADC B Boost Volume",
+                       CS42L73_ADCIPC, 6, 0x01, 1, adc_boost_tlv),
+
+       SOC_SINGLE_TLV("Speakerphone Digital Playback Volume",
+                       CS42L73_SPKDVOL, 0, 0xE4, 1, hl_tlv),
+
+       SOC_SINGLE_TLV("Ear Speaker Digital Playback Volume",
+                       CS42L73_ESLDVOL, 0, 0xE4, 1, hl_tlv),
+
+       SOC_DOUBLE_R("Headphone Analog Playback Switch", CS42L73_HPAAVOL,
+                       CS42L73_HPBAVOL, 7, 1, 1),
+
+       SOC_DOUBLE_R("LineOut Analog Playback Switch", CS42L73_LOAAVOL,
+                       CS42L73_LOBAVOL, 7, 1, 1),
+       SOC_DOUBLE("Input Path Digital Switch", CS42L73_ADCIPC, 0, 4, 1, 1),
+       SOC_DOUBLE("HL Digital Playback Switch", CS42L73_PBDC, 0,
+                       1, 1, 1),
+       SOC_SINGLE("Speakerphone Digital Playback Switch", CS42L73_PBDC, 2, 1,
+                       1),
+       SOC_SINGLE("Ear Speaker Digital Playback Switch", CS42L73_PBDC, 3, 1,
+                       1),
+
+       SOC_SINGLE("PGA Soft-Ramp Switch", CS42L73_MIOPC, 3, 1, 0),
+       SOC_SINGLE("Analog Zero Cross Switch", CS42L73_MIOPC, 2, 1, 0),
+       SOC_SINGLE("Digital Soft-Ramp Switch", CS42L73_MIOPC, 1, 1, 0),
+       SOC_SINGLE("Analog Output Soft-Ramp Switch", CS42L73_MIOPC, 0, 1, 0),
+
+       SOC_DOUBLE("ADC Signal Polarity Switch", CS42L73_ADCIPC, 1, 5, 1,
+                       0),
+
+       SOC_SINGLE("HL Limiter Attack Rate", CS42L73_LIMARATEHL, 0, 0x3F,
+                       0),
+       SOC_SINGLE("HL Limiter Release Rate", CS42L73_LIMRRATEHL, 0,
+                       0x3F, 0),
+
+
+       SOC_SINGLE("HL Limiter Switch", CS42L73_LIMRRATEHL, 7, 1, 0),
+       SOC_SINGLE("HL Limiter All Channels Switch", CS42L73_LIMRRATEHL, 6, 1,
+                       0),
+
+       SOC_SINGLE_TLV("HL Limiter Max Threshold Volume", CS42L73_LMAXHL, 5, 7,
+                       1, limiter_tlv),
+
+       SOC_SINGLE_TLV("HL Limiter Cushion Volume", CS42L73_LMAXHL, 2, 7, 1,
+                       limiter_tlv),
+
+       SOC_SINGLE("SPK Limiter Attack Rate Volume", CS42L73_LIMARATESPK, 0,
+                       0x3F, 0),
+       SOC_SINGLE("SPK Limiter Release Rate Volume", CS42L73_LIMRRATESPK, 0,
+                       0x3F, 0),
+       SOC_SINGLE("SPK Limiter Switch", CS42L73_LIMRRATESPK, 7, 1, 0),
+       SOC_SINGLE("SPK Limiter All Channels Switch", CS42L73_LIMRRATESPK,
+                       6, 1, 0),
+       SOC_SINGLE_TLV("SPK Limiter Max Threshold Volume", CS42L73_LMAXSPK, 5,
+                       7, 1, limiter_tlv),
+
+       SOC_SINGLE_TLV("SPK Limiter Cushion Volume", CS42L73_LMAXSPK, 2, 7, 1,
+                       limiter_tlv),
+
+       SOC_SINGLE("ESL Limiter Attack Rate Volume", CS42L73_LIMARATEESL, 0,
+                       0x3F, 0),
+       SOC_SINGLE("ESL Limiter Release Rate Volume", CS42L73_LIMRRATEESL, 0,
+                       0x3F, 0),
+       SOC_SINGLE("ESL Limiter Switch", CS42L73_LIMRRATEESL, 7, 1, 0),
+       SOC_SINGLE_TLV("ESL Limiter Max Threshold Volume", CS42L73_LMAXESL, 5,
+                       7, 1, limiter_tlv),
+
+       SOC_SINGLE_TLV("ESL Limiter Cushion Volume", CS42L73_LMAXESL, 2, 7, 1,
+                       limiter_tlv),
+
+       SOC_SINGLE("ALC Attack Rate Volume", CS42L73_ALCARATE, 0, 0x3F, 0),
+       SOC_SINGLE("ALC Release Rate Volume", CS42L73_ALCRRATE, 0, 0x3F, 0),
+       SOC_DOUBLE("ALC Switch", CS42L73_ALCARATE, 6, 7, 1, 0),
+       SOC_SINGLE_TLV("ALC Max Threshold Volume", CS42L73_ALCMINMAX, 5, 7, 0,
+                       limiter_tlv),
+       SOC_SINGLE_TLV("ALC Min Threshold Volume", CS42L73_ALCMINMAX, 2, 7, 0,
+                       limiter_tlv),
+
+       SOC_DOUBLE("NG Enable Switch", CS42L73_NGCAB, 6, 7, 1, 0),
+       SOC_SINGLE("NG Boost Switch", CS42L73_NGCAB, 5, 1, 0),
+       /*
+           NG Threshold depends on NG_BOOTSAB, which selects
+           between two threshold scales in decibels.
+           Set linear values for now ..
+       */
+       SOC_SINGLE("NG Threshold", CS42L73_NGCAB, 2, 7, 0),
+       SOC_ENUM("NG Delay", ng_delay_enum),
+
+       SOC_ENUM("Charge Pump Frequency", charge_pump_enum),
+
+       SOC_DOUBLE_R_TLV("XSP-IP Volume",
+                       CS42L73_XSPAIPAA, CS42L73_XSPBIPBA, 0, 0x3F, 1,
+                       attn_tlv),
+       SOC_DOUBLE_R_TLV("XSP-XSP Volume",
+                       CS42L73_XSPAXSPAA, CS42L73_XSPBXSPBA, 0, 0x3F, 1,
+                       attn_tlv),
+       SOC_DOUBLE_R_TLV("XSP-ASP Volume",
+                       CS42L73_XSPAASPAA, CS42L73_XSPAASPBA, 0, 0x3F, 1,
+                       attn_tlv),
+       SOC_DOUBLE_R_TLV("XSP-VSP Volume",
+                       CS42L73_XSPAVSPMA, CS42L73_XSPBVSPMA, 0, 0x3F, 1,
+                       attn_tlv),
+
+       SOC_DOUBLE_R_TLV("ASP-IP Volume",
+                       CS42L73_ASPAIPAA, CS42L73_ASPBIPBA, 0, 0x3F, 1,
+                       attn_tlv),
+       SOC_DOUBLE_R_TLV("ASP-XSP Volume",
+                       CS42L73_ASPAXSPAA, CS42L73_ASPBXSPBA, 0, 0x3F, 1,
+                       attn_tlv),
+       SOC_DOUBLE_R_TLV("ASP-ASP Volume",
+                       CS42L73_ASPAASPAA, CS42L73_ASPBASPBA, 0, 0x3F, 1,
+                       attn_tlv),
+       SOC_DOUBLE_R_TLV("ASP-VSP Volume",
+                       CS42L73_ASPAVSPMA, CS42L73_ASPBVSPMA, 0, 0x3F, 1,
+                       attn_tlv),
+
+       SOC_DOUBLE_R_TLV("VSP-IP Volume",
+                       CS42L73_VSPAIPAA, CS42L73_VSPBIPBA, 0, 0x3F, 1,
+                       attn_tlv),
+       SOC_DOUBLE_R_TLV("VSP-XSP Volume",
+                       CS42L73_VSPAXSPAA, CS42L73_VSPBXSPBA, 0, 0x3F, 1,
+                       attn_tlv),
+       SOC_DOUBLE_R_TLV("VSP-ASP Volume",
+                       CS42L73_VSPAASPAA, CS42L73_VSPBASPBA, 0, 0x3F, 1,
+                       attn_tlv),
+       SOC_DOUBLE_R_TLV("VSP-VSP Volume",
+                       CS42L73_VSPAVSPMA, CS42L73_VSPBVSPMA, 0, 0x3F, 1,
+                       attn_tlv),
+
+       SOC_DOUBLE_R_TLV("HL-IP Volume",
+                       CS42L73_HLAIPAA, CS42L73_HLBIPBA, 0, 0x3F, 1,
+                       attn_tlv),
+       SOC_DOUBLE_R_TLV("HL-XSP Volume",
+                       CS42L73_HLAXSPAA, CS42L73_HLBXSPBA, 0, 0x3F, 1,
+                       attn_tlv),
+       SOC_DOUBLE_R_TLV("HL-ASP Volume",
+                       CS42L73_HLAASPAA, CS42L73_HLBASPBA, 0, 0x3F, 1,
+                       attn_tlv),
+       SOC_DOUBLE_R_TLV("HL-VSP Volume",
+                       CS42L73_HLAVSPMA, CS42L73_HLBVSPMA, 0, 0x3F, 1,
+                       attn_tlv),
+
+       SOC_SINGLE_TLV("SPK-IP Mono Volume",
+                       CS42L73_SPKMIPMA, 0, 0x3E, 1, attn_tlv),
+       SOC_SINGLE_TLV("SPK-XSP Mono Volume",
+                       CS42L73_SPKMXSPA, 0, 0x3E, 1, attn_tlv),
+       SOC_SINGLE_TLV("SPK-ASP Mono Volume",
+                       CS42L73_SPKMASPA, 0, 0x3E, 1, attn_tlv),
+       SOC_SINGLE_TLV("SPK-VSP Mono Volume",
+                       CS42L73_SPKMVSPMA, 0, 0x3E, 1, attn_tlv),
+
+       SOC_SINGLE_TLV("ESL-IP Mono Volume",
+                       CS42L73_ESLMIPMA, 0, 0x3E, 1, attn_tlv),
+       SOC_SINGLE_TLV("ESL-XSP Mono Volume",
+                       CS42L73_ESLMXSPA, 0, 0x3E, 1, attn_tlv),
+       SOC_SINGLE_TLV("ESL-ASP Mono Volume",
+                       CS42L73_ESLMASPA, 0, 0x3E, 1, attn_tlv),
+       SOC_SINGLE_TLV("ESL-VSP Mono Volume",
+                       CS42L73_ESLMVSPMA, 0, 0x3E, 1, attn_tlv),
+
+       SOC_ENUM("IP Digital Swap/Mono Select", ip_swap_enum),
+
+       SOC_ENUM("VSPOUT Mono/Stereo Select", vsp_output_mux_enum),
+       SOC_ENUM("XSPOUT Mono/Stereo Select", xsp_output_mux_enum),
+};
+
+static const struct snd_soc_dapm_widget cs42l73_dapm_widgets[] = {
+       SND_SOC_DAPM_INPUT("LINEINA"),
+       SND_SOC_DAPM_INPUT("LINEINB"),
+       SND_SOC_DAPM_INPUT("MIC1"),
+       SND_SOC_DAPM_SUPPLY("MIC1 Bias", CS42L73_PWRCTL2, 6, 1, NULL, 0),
+       SND_SOC_DAPM_INPUT("MIC2"),
+       SND_SOC_DAPM_SUPPLY("MIC2 Bias", CS42L73_PWRCTL2, 7, 1, NULL, 0),
+
+       SND_SOC_DAPM_AIF_OUT("XSPOUTL", "XSP Capture",  0,
+                       CS42L73_PWRCTL2, 1, 1),
+       SND_SOC_DAPM_AIF_OUT("XSPOUTR", "XSP Capture",  0,
+                       CS42L73_PWRCTL2, 1, 1),
+       SND_SOC_DAPM_AIF_OUT("ASPOUTL", "ASP Capture",  0,
+                       CS42L73_PWRCTL2, 3, 1),
+       SND_SOC_DAPM_AIF_OUT("ASPOUTR", "ASP Capture",  0,
+                       CS42L73_PWRCTL2, 3, 1),
+       SND_SOC_DAPM_AIF_OUT("VSPOUTL", "VSP Capture",  0,
+                       CS42L73_PWRCTL2, 4, 1),
+       SND_SOC_DAPM_AIF_OUT("VSPOUTR", "VSP Capture",  0,
+                       CS42L73_PWRCTL2, 4, 1),
+
+       SND_SOC_DAPM_PGA("PGA Left", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("PGA Right", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       SND_SOC_DAPM_MUX("PGA Left Mux", SND_SOC_NOPM, 0, 0, &pgaa_mux),
+       SND_SOC_DAPM_MUX("PGA Right Mux", SND_SOC_NOPM, 0, 0, &pgab_mux),
+
+       SND_SOC_DAPM_ADC("ADC Left", NULL, CS42L73_PWRCTL1, 7, 1),
+       SND_SOC_DAPM_ADC("ADC Right", NULL, CS42L73_PWRCTL1, 5, 1),
+       SND_SOC_DAPM_ADC("DMIC Left", NULL, CS42L73_PWRCTL1, 6, 1),
+       SND_SOC_DAPM_ADC("DMIC Right", NULL, CS42L73_PWRCTL1, 4, 1),
+
+       SND_SOC_DAPM_MIXER_NAMED_CTL("Input Left Capture", SND_SOC_NOPM,
+                        0, 0, input_left_mixer,
+                        ARRAY_SIZE(input_left_mixer)),
+
+       SND_SOC_DAPM_MIXER_NAMED_CTL("Input Right Capture", SND_SOC_NOPM,
+                       0, 0, input_right_mixer,
+                       ARRAY_SIZE(input_right_mixer)),
+
+       SND_SOC_DAPM_MIXER("ASPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("ASPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("XSPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("XSPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("VSPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("VSPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       SND_SOC_DAPM_AIF_IN("XSPINL", "XSP Playback", 0,
+                               CS42L73_PWRCTL2, 0, 1),
+       SND_SOC_DAPM_AIF_IN("XSPINR", "XSP Playback", 0,
+                               CS42L73_PWRCTL2, 0, 1),
+       SND_SOC_DAPM_AIF_IN("XSPINM", "XSP Playback", 0,
+                               CS42L73_PWRCTL2, 0, 1),
+
+       SND_SOC_DAPM_AIF_IN("ASPINL", "ASP Playback", 0,
+                               CS42L73_PWRCTL2, 2, 1),
+       SND_SOC_DAPM_AIF_IN("ASPINR", "ASP Playback", 0,
+                               CS42L73_PWRCTL2, 2, 1),
+       SND_SOC_DAPM_AIF_IN("ASPINM", "ASP Playback", 0,
+                               CS42L73_PWRCTL2, 2, 1),
+
+       SND_SOC_DAPM_AIF_IN("VSPIN", "VSP Playback", 0,
+                               CS42L73_PWRCTL2, 4, 1),
+
+       SND_SOC_DAPM_MIXER("HL Left Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("HL Right Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("SPK Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("ESL Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       SND_SOC_DAPM_MUX("ESL-XSP Mux", SND_SOC_NOPM,
+                        0, 0, &esl_xsp_mixer),
+
+       SND_SOC_DAPM_MUX("ESL-ASP Mux", SND_SOC_NOPM,
+                        0, 0, &esl_asp_mixer),
+
+       SND_SOC_DAPM_MUX("SPK-ASP Mux", SND_SOC_NOPM,
+                        0, 0, &spk_asp_mixer),
+
+       SND_SOC_DAPM_MUX("SPK-XSP Mux", SND_SOC_NOPM,
+                        0, 0, &spk_xsp_mixer),
+
+       SND_SOC_DAPM_PGA("HL Left DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("HL Right DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("SPK DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("ESL DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       SND_SOC_DAPM_SWITCH("HP Amp", CS42L73_PWRCTL3, 0, 1,
+                           &hp_amp_ctl),
+       SND_SOC_DAPM_SWITCH("LO Amp", CS42L73_PWRCTL3, 1, 1,
+                           &lo_amp_ctl),
+       SND_SOC_DAPM_SWITCH("SPK Amp", CS42L73_PWRCTL3, 2, 1,
+                           &spk_amp_ctl),
+       SND_SOC_DAPM_SWITCH("EAR Amp", CS42L73_PWRCTL3, 3, 1,
+                           &ear_amp_ctl),
+       SND_SOC_DAPM_SWITCH("SPKLO Amp", CS42L73_PWRCTL3, 4, 1,
+                           &spklo_amp_ctl),
+
+       SND_SOC_DAPM_OUTPUT("HPOUTA"),
+       SND_SOC_DAPM_OUTPUT("HPOUTB"),
+       SND_SOC_DAPM_OUTPUT("LINEOUTA"),
+       SND_SOC_DAPM_OUTPUT("LINEOUTB"),
+       SND_SOC_DAPM_OUTPUT("EAROUT"),
+       SND_SOC_DAPM_OUTPUT("SPKOUT"),
+       SND_SOC_DAPM_OUTPUT("SPKLINEOUT"),
+};
+
+static const struct snd_soc_dapm_route cs42l73_audio_map[] = {
+
+       /* SPKLO EARSPK Paths */
+       {"EAROUT", NULL, "EAR Amp"},
+       {"SPKLINEOUT", NULL, "SPKLO Amp"},
+
+       {"EAR Amp", "Switch", "ESL DAC"},
+       {"SPKLO Amp", "Switch", "ESL DAC"},
+
+       {"ESL DAC", "ESL-ASP Mono Volume", "ESL Mixer"},
+       {"ESL DAC", "ESL-XSP Mono Volume", "ESL Mixer"},
+       {"ESL DAC", "ESL-VSP Mono Volume", "VSPIN"},
+       /* Loopback */
+       {"ESL DAC", "ESL-IP Mono Volume", "Input Left Capture"},
+       {"ESL DAC", "ESL-IP Mono Volume", "Input Right Capture"},
+
+       {"ESL Mixer", NULL, "ESL-ASP Mux"},
+       {"ESL Mixer", NULL, "ESL-XSP Mux"},
+
+       {"ESL-ASP Mux", "Left", "ASPINL"},
+       {"ESL-ASP Mux", "Right", "ASPINR"},
+       {"ESL-ASP Mux", "Mono Mix", "ASPINM"},
+
+       {"ESL-XSP Mux", "Left", "XSPINL"},
+       {"ESL-XSP Mux", "Right", "XSPINR"},
+       {"ESL-XSP Mux", "Mono Mix", "XSPINM"},
+
+       /* Speakerphone Paths */
+       {"SPKOUT", NULL, "SPK Amp"},
+       {"SPK Amp", "Switch", "SPK DAC"},
+
+       {"SPK DAC", "SPK-ASP Mono Volume", "SPK Mixer"},
+       {"SPK DAC", "SPK-XSP Mono Volume", "SPK Mixer"},
+       {"SPK DAC", "SPK-VSP Mono Volume", "VSPIN"},
+       /* Loopback */
+       {"SPK DAC", "SPK-IP Mono Volume", "Input Left Capture"},
+       {"SPK DAC", "SPK-IP Mono Volume", "Input Right Capture"},
+
+       {"SPK Mixer", NULL, "SPK-ASP Mux"},
+       {"SPK Mixer", NULL, "SPK-XSP Mux"},
+
+       {"SPK-ASP Mux", "Left", "ASPINL"},
+       {"SPK-ASP Mux", "Mono Mix", "ASPINM"},
+       {"SPK-ASP Mux", "Right", "ASPINR"},
+
+       {"SPK-XSP Mux", "Left", "XSPINL"},
+       {"SPK-XSP Mux", "Mono Mix", "XSPINM"},
+       {"SPK-XSP Mux", "Right", "XSPINR"},
+
+       /* HP LineOUT Paths */
+       {"HPOUTA", NULL, "HP Amp"},
+       {"HPOUTB", NULL, "HP Amp"},
+       {"LINEOUTA", NULL, "LO Amp"},
+       {"LINEOUTB", NULL, "LO Amp"},
+
+       {"HP Amp", "Switch", "HL Left DAC"},
+       {"HP Amp", "Switch", "HL Right DAC"},
+       {"LO Amp", "Switch", "HL Left DAC"},
+       {"LO Amp", "Switch", "HL Right DAC"},
+
+       {"HL Left DAC", "HL-XSP Volume", "HL Left Mixer"},
+       {"HL Right DAC", "HL-XSP Volume", "HL Right Mixer"},
+       {"HL Left DAC", "HL-ASP Volume", "HL Left Mixer"},
+       {"HL Right DAC", "HL-ASP Volume", "HL Right Mixer"},
+       {"HL Left DAC", "HL-VSP Volume", "HL Left Mixer"},
+       {"HL Right DAC", "HL-VSP Volume", "HL Right Mixer"},
+       /* Loopback */
+       {"HL Left DAC", "HL-IP Volume", "HL Left Mixer"},
+       {"HL Right DAC", "HL-IP Volume", "HL Right Mixer"},
+       {"HL Left Mixer", NULL, "Input Left Capture"},
+       {"HL Right Mixer", NULL, "Input Right Capture"},
+
+       {"HL Left Mixer", NULL, "ASPINL"},
+       {"HL Right Mixer", NULL, "ASPINR"},
+       {"HL Left Mixer", NULL, "XSPINL"},
+       {"HL Right Mixer", NULL, "XSPINR"},
+       {"HL Left Mixer", NULL, "VSPIN"},
+       {"HL Right Mixer", NULL, "VSPIN"},
+
+       /* Capture Paths */
+       {"MIC1", NULL, "MIC1 Bias"},
+       {"PGA Left Mux", "Mic 1", "MIC1"},
+       {"MIC2", NULL, "MIC2 Bias"},
+       {"PGA Right Mux", "Mic 2", "MIC2"},
+
+       {"PGA Left Mux", "Line A", "LINEINA"},
+       {"PGA Right Mux", "Line B", "LINEINB"},
+
+       {"PGA Left", NULL, "PGA Left Mux"},
+       {"PGA Right", NULL, "PGA Right Mux"},
+
+       {"ADC Left", NULL, "PGA Left"},
+       {"ADC Right", NULL, "PGA Right"},
+
+       {"Input Left Capture", "ADC Left Input", "ADC Left"},
+       {"Input Right Capture", "ADC Right Input", "ADC Right"},
+       {"Input Left Capture", "DMIC Left Input", "DMIC Left"},
+       {"Input Right Capture", "DMIC Right Input", "DMIC Right"},
+
+       /* Audio Capture */
+       {"ASPL Output Mixer", NULL, "Input Left Capture"},
+       {"ASPR Output Mixer", NULL, "Input Right Capture"},
+
+       {"ASPOUTL", "ASP-IP Volume", "ASPL Output Mixer"},
+       {"ASPOUTR", "ASP-IP Volume", "ASPR Output Mixer"},
+
+       /* Auxillary Capture */
+       {"XSPL Output Mixer", NULL, "Input Left Capture"},
+       {"XSPR Output Mixer", NULL, "Input Right Capture"},
+
+       {"XSPOUTL", "XSP-IP Volume", "XSPL Output Mixer"},
+       {"XSPOUTR", "XSP-IP Volume", "XSPR Output Mixer"},
+
+       {"XSPOUTL", NULL, "XSPL Output Mixer"},
+       {"XSPOUTR", NULL, "XSPR Output Mixer"},
+
+       /* Voice Capture */
+       {"VSPL Output Mixer", NULL, "Input Left Capture"},
+       {"VSPR Output Mixer", NULL, "Input Left Capture"},
+
+       {"VSPOUTL", "VSP-IP Volume", "VSPL Output Mixer"},
+       {"VSPOUTR", "VSP-IP Volume", "VSPR Output Mixer"},
+
+       {"VSPOUTL", NULL, "VSPL Output Mixer"},
+       {"VSPOUTR", NULL, "VSPR Output Mixer"},
+};
+
+struct cs42l73_mclk_div {
+       u32 mclk;
+       u32 srate;
+       u8 mmcc;
+};
+
+static struct cs42l73_mclk_div cs42l73_mclk_coeffs[] = {
+       /* MCLK, Sample Rate, xMMCC[5:0] */
+       {5644800, 11025, 0x30},
+       {5644800, 22050, 0x20},
+       {5644800, 44100, 0x10},
+
+       {6000000,  8000, 0x39},
+       {6000000, 11025, 0x33},
+       {6000000, 12000, 0x31},
+       {6000000, 16000, 0x29},
+       {6000000, 22050, 0x23},
+       {6000000, 24000, 0x21},
+       {6000000, 32000, 0x19},
+       {6000000, 44100, 0x13},
+       {6000000, 48000, 0x11},
+
+       {6144000,  8000, 0x38},
+       {6144000, 12000, 0x30},
+       {6144000, 16000, 0x28},
+       {6144000, 24000, 0x20},
+       {6144000, 32000, 0x18},
+       {6144000, 48000, 0x10},
+
+       {6500000,  8000, 0x3C},
+       {6500000, 11025, 0x35},
+       {6500000, 12000, 0x34},
+       {6500000, 16000, 0x2C},
+       {6500000, 22050, 0x25},
+       {6500000, 24000, 0x24},
+       {6500000, 32000, 0x1C},
+       {6500000, 44100, 0x15},
+       {6500000, 48000, 0x14},
+
+       {6400000,  8000, 0x3E},
+       {6400000, 11025, 0x37},
+       {6400000, 12000, 0x36},
+       {6400000, 16000, 0x2E},
+       {6400000, 22050, 0x27},
+       {6400000, 24000, 0x26},
+       {6400000, 32000, 0x1E},
+       {6400000, 44100, 0x17},
+       {6400000, 48000, 0x16},
+};
+
+struct cs42l73_mclkx_div {
+       u32 mclkx;
+       u8 ratio;
+       u8 mclkdiv;
+};
+
+static struct cs42l73_mclkx_div cs42l73_mclkx_coeffs[] = {
+       {5644800,  1, 0},       /* 5644800 */
+       {6000000,  1, 0},       /* 6000000 */
+       {6144000,  1, 0},       /* 6144000 */
+       {11289600, 2, 2},       /* 5644800 */
+       {12288000, 2, 2},       /* 6144000 */
+       {12000000, 2, 2},       /* 6000000 */
+       {13000000, 2, 2},       /* 6500000 */
+       {19200000, 3, 3},       /* 6400000 */
+       {24000000, 4, 4},       /* 6000000 */
+       {26000000, 4, 4},       /* 6500000 */
+       {38400000, 6, 5}        /* 6400000 */
+};
+
+static int cs42l73_get_mclkx_coeff(int mclkx)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(cs42l73_mclkx_coeffs); i++) {
+               if (cs42l73_mclkx_coeffs[i].mclkx == mclkx)
+                       return i;
+       }
+       return -EINVAL;
+}
+
+static int cs42l73_get_mclk_coeff(int mclk, int srate)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(cs42l73_mclk_coeffs); i++) {
+               if (cs42l73_mclk_coeffs[i].mclk == mclk &&
+                   cs42l73_mclk_coeffs[i].srate == srate)
+                       return i;
+       }
+       return -EINVAL;
+
+}
+
+static int cs42l73_set_mclk(struct snd_soc_dai *dai, unsigned int freq)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
+
+       int mclkx_coeff;
+       u32 mclk = 0;
+       u8 dmmcc = 0;
+
+       /* MCLKX -> MCLK */
+       mclkx_coeff = cs42l73_get_mclkx_coeff(freq);
+
+       mclk = cs42l73_mclkx_coeffs[mclkx_coeff].mclkx /
+               cs42l73_mclkx_coeffs[mclkx_coeff].ratio;
+
+       dev_dbg(codec->dev, "MCLK%u %u  <-> internal MCLK %u\n",
+                priv->mclksel + 1, cs42l73_mclkx_coeffs[mclkx_coeff].mclkx,
+                mclk);
+
+       dmmcc = (priv->mclksel << 4) |
+               (cs42l73_mclkx_coeffs[mclkx_coeff].mclkdiv << 1);
+
+       snd_soc_write(codec, CS42L73_DMMCC, dmmcc);
+
+       priv->sysclk = mclkx_coeff;
+       priv->mclk = mclk;
+
+       return 0;
+}
+
+static int cs42l73_set_sysclk(struct snd_soc_dai *dai,
+                             int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
+
+       switch (clk_id) {
+       case CS42L73_CLKID_MCLK1:
+               break;
+       case CS42L73_CLKID_MCLK2:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if ((cs42l73_set_mclk(dai, freq)) < 0) {
+               dev_err(codec->dev, "Unable to set MCLK for dai %s\n",
+                       dai->name);
+               return -EINVAL;
+       }
+
+       priv->mclksel = clk_id;
+
+       return 0;
+}
+
+static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
+       u8 id = codec_dai->id;
+       unsigned int inv, format;
+       u8 spc, mmcc;
+
+       spc = snd_soc_read(codec, CS42L73_SPC(id));
+       mmcc = snd_soc_read(codec, CS42L73_MMCC(id));
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               mmcc |= MS_MASTER;
+               break;
+
+       case SND_SOC_DAIFMT_CBS_CFS:
+               mmcc &= ~MS_MASTER;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       format = (fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+       inv = (fmt & SND_SOC_DAIFMT_INV_MASK);
+
+       switch (format) {
+       case SND_SOC_DAIFMT_I2S:
+               spc &= ~SPDIF_PCM;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+       case SND_SOC_DAIFMT_DSP_B:
+               if (mmcc & MS_MASTER) {
+                       dev_err(codec->dev,
+                               "PCM format in slave mode only\n");
+                       return -EINVAL;
+               }
+               if (id == CS42L73_ASP) {
+                       dev_err(codec->dev,
+                               "PCM format is not supported on ASP port\n");
+                       return -EINVAL;
+               }
+               spc |= SPDIF_PCM;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (spc & SPDIF_PCM) {
+               /* Clear PCM mode, clear PCM_BIT_ORDER bit for MSB->LSB */
+               spc &= ~(PCM_MODE_MASK | PCM_BIT_ORDER);
+               switch (format) {
+               case SND_SOC_DAIFMT_DSP_B:
+                       if (inv == SND_SOC_DAIFMT_IB_IF)
+                               spc |= PCM_MODE0;
+                       if (inv == SND_SOC_DAIFMT_IB_NF)
+                               spc |= PCM_MODE1;
+               break;
+               case SND_SOC_DAIFMT_DSP_A:
+                       if (inv == SND_SOC_DAIFMT_IB_IF)
+                               spc |= PCM_MODE1;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
+
+       priv->config[id].spc = spc;
+       priv->config[id].mmcc = mmcc;
+
+       return 0;
+}
+
+static u32 cs42l73_asrc_rates[] = {
+       8000, 11025, 12000, 16000, 22050,
+       24000, 32000, 44100, 48000
+};
+
+static unsigned int cs42l73_get_xspfs_coeff(u32 rate)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(cs42l73_asrc_rates); i++) {
+               if (cs42l73_asrc_rates[i] == rate)
+                       return i + 1;
+       }
+       return 0;               /* 0 = Don't know */
+}
+
+static void cs42l73_update_asrc(struct snd_soc_codec *codec, int id, int srate)
+{
+       u8 spfs = 0;
+
+       if (srate > 0)
+               spfs = cs42l73_get_xspfs_coeff(srate);
+
+       switch (id) {
+       case CS42L73_XSP:
+               snd_soc_update_bits(codec, CS42L73_VXSPFS, 0x0f, spfs);
+       break;
+       case CS42L73_ASP:
+               snd_soc_update_bits(codec, CS42L73_ASPC, 0x3c, spfs << 2);
+       break;
+       case CS42L73_VSP:
+               snd_soc_update_bits(codec, CS42L73_VXSPFS, 0xf0, spfs << 4);
+       break;
+       default:
+       break;
+       }
+}
+
+static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream,
+                                struct snd_pcm_hw_params *params,
+                                struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_codec *codec = rtd->codec;
+       struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
+       int id = dai->id;
+       int mclk_coeff;
+       int srate = params_rate(params);
+
+       if (priv->config[id].mmcc & MS_MASTER) {
+               /* CS42L73 Master */
+               /* MCLK -> srate */
+               mclk_coeff =
+                   cs42l73_get_mclk_coeff(priv->mclk, srate);
+
+               if (mclk_coeff < 0)
+                       return -EINVAL;
+
+               dev_dbg(codec->dev,
+                        "DAI[%d]: MCLK %u, srate %u, MMCC[5:0] = %x\n",
+                        id, priv->mclk, srate,
+                        cs42l73_mclk_coeffs[mclk_coeff].mmcc);
+
+               priv->config[id].mmcc &= 0xC0;
+               priv->config[id].mmcc |= cs42l73_mclk_coeffs[mclk_coeff].mmcc;
+               priv->config[id].spc &= 0xFC;
+               priv->config[id].spc &= MCK_SCLK_64FS;
+       } else {
+               /* CS42L73 Slave */
+               priv->config[id].spc &= 0xFC;
+               priv->config[id].spc |= MCK_SCLK_64FS;
+       }
+       /* Update ASRCs */
+       priv->config[id].srate = srate;
+
+       snd_soc_write(codec, CS42L73_SPC(id), priv->config[id].spc);
+       snd_soc_write(codec, CS42L73_MMCC(id), priv->config[id].mmcc);
+
+       cs42l73_update_asrc(codec, id, srate);
+
+       return 0;
+}
+
+static int cs42l73_set_bias_level(struct snd_soc_codec *codec,
+                                 enum snd_soc_bias_level level)
+{
+       struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec);
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 0);
+               snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 0);
+               break;
+
+       case SND_SOC_BIAS_PREPARE:
+               break;
+
+       case SND_SOC_BIAS_STANDBY:
+               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+                       regcache_cache_only(cs42l73->regmap, false);
+                       regcache_sync(cs42l73->regmap);
+               }
+               snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1);
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1);
+               snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 1);
+               break;
+       }
+       codec->dapm.bias_level = level;
+       return 0;
+}
+
+static int cs42l73_set_tristate(struct snd_soc_dai *dai, int tristate)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       int id = dai->id;
+
+       return snd_soc_update_bits(codec, CS42L73_SPC(id),
+                                       0x7F, tristate << 7);
+}
+
+static struct snd_pcm_hw_constraint_list constraints_12_24 = {
+       .count  = ARRAY_SIZE(cs42l73_asrc_rates),
+       .list   = cs42l73_asrc_rates,
+};
+
+static int cs42l73_pcm_startup(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       snd_pcm_hw_constraint_list(substream->runtime, 0,
+                                       SNDRV_PCM_HW_PARAM_RATE,
+                                       &constraints_12_24);
+       return 0;
+}
+
+/* SNDRV_PCM_RATE_KNOT -> 12000, 24000 Hz, limit with constraint list */
+#define CS42L73_RATES (SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT)
+
+
+#define CS42L73_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+       SNDRV_PCM_FMTBIT_S24_LE)
+
+static const struct snd_soc_dai_ops cs42l73_ops = {
+       .startup = cs42l73_pcm_startup,
+       .hw_params = cs42l73_pcm_hw_params,
+       .set_fmt = cs42l73_set_dai_fmt,
+       .set_sysclk = cs42l73_set_sysclk,
+       .set_tristate = cs42l73_set_tristate,
+};
+
+static struct snd_soc_dai_driver cs42l73_dai[] = {
+       {
+               .name = "cs42l73-xsp",
+               .id = CS42L73_XSP,
+               .playback = {
+                       .stream_name = "XSP Playback",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = CS42L73_RATES,
+                       .formats = CS42L73_FORMATS,
+               },
+               .capture = {
+                       .stream_name = "XSP Capture",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = CS42L73_RATES,
+                       .formats = CS42L73_FORMATS,
+               },
+               .ops = &cs42l73_ops,
+               .symmetric_rates = 1,
+        },
+       {
+               .name = "cs42l73-asp",
+               .id = CS42L73_ASP,
+               .playback = {
+                       .stream_name = "ASP Playback",
+                       .channels_min = 2,
+                       .channels_max = 2,
+                       .rates = CS42L73_RATES,
+                       .formats = CS42L73_FORMATS,
+               },
+               .capture = {
+                       .stream_name = "ASP Capture",
+                       .channels_min = 2,
+                       .channels_max = 2,
+                       .rates = CS42L73_RATES,
+                       .formats = CS42L73_FORMATS,
+               },
+               .ops = &cs42l73_ops,
+               .symmetric_rates = 1,
+        },
+       {
+               .name = "cs42l73-vsp",
+               .id = CS42L73_VSP,
+               .playback = {
+                       .stream_name = "VSP Playback",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = CS42L73_RATES,
+                       .formats = CS42L73_FORMATS,
+               },
+               .capture = {
+                       .stream_name = "VSP Capture",
+                       .channels_min = 1,
+                       .channels_max = 2,
+                       .rates = CS42L73_RATES,
+                       .formats = CS42L73_FORMATS,
+               },
+               .ops = &cs42l73_ops,
+               .symmetric_rates = 1,
+        }
+};
+
+static int cs42l73_suspend(struct snd_soc_codec *codec)
+{
+       cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       return 0;
+}
+
+static int cs42l73_resume(struct snd_soc_codec *codec)
+{
+       cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       return 0;
+}
+
+static int cs42l73_probe(struct snd_soc_codec *codec)
+{
+       int ret;
+       struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec);
+
+       codec->control_data = cs42l73->regmap;
+
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
+
+       regcache_cache_only(cs42l73->regmap, true);
+
+       cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       cs42l73->mclksel = CS42L73_CLKID_MCLK1; /* MCLK1 as master clk */
+       cs42l73->mclk = 0;
+
+       return ret;
+}
+
+static int cs42l73_remove(struct snd_soc_codec *codec)
+{
+       cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_cs42l73 = {
+       .probe = cs42l73_probe,
+       .remove = cs42l73_remove,
+       .suspend = cs42l73_suspend,
+       .resume = cs42l73_resume,
+       .set_bias_level = cs42l73_set_bias_level,
+
+       .dapm_widgets = cs42l73_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(cs42l73_dapm_widgets),
+       .dapm_routes = cs42l73_audio_map,
+       .num_dapm_routes = ARRAY_SIZE(cs42l73_audio_map),
+
+       .controls = cs42l73_snd_controls,
+       .num_controls = ARRAY_SIZE(cs42l73_snd_controls),
+};
+
+static struct regmap_config cs42l73_regmap = {
+       .reg_bits = 8,
+       .val_bits = 8,
+
+       .max_register = CS42L73_MAX_REGISTER,
+       .reg_defaults = cs42l73_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(cs42l73_reg_defaults),
+       .volatile_reg = cs42l73_volatile_register,
+       .readable_reg = cs42l73_readable_register,
+       .cache_type = REGCACHE_RBTREE,
+};
+
+static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
+                                      const struct i2c_device_id *id)
+{
+       struct cs42l73_private *cs42l73;
+       int ret;
+       unsigned int devid = 0;
+       unsigned int reg;
+
+       cs42l73 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l73_private),
+                              GFP_KERNEL);
+       if (!cs42l73) {
+               dev_err(&i2c_client->dev, "could not allocate codec\n");
+               return -ENOMEM;
+       }
+
+       i2c_set_clientdata(i2c_client, cs42l73);
+
+       cs42l73->regmap = regmap_init_i2c(i2c_client, &cs42l73_regmap);
+       if (IS_ERR(cs42l73->regmap)) {
+               ret = PTR_ERR(cs42l73->regmap);
+               dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+               goto err;
+       }
+       /* initialize codec */
+       ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, &reg);
+       devid = (reg & 0xFF) << 12;
+
+       ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_CD, &reg);
+       devid |= (reg & 0xFF) << 4;
+
+       ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_E, &reg);
+       devid |= (reg & 0xF0) >> 4;
+
+
+       if (devid != CS42L73_DEVID) {
+               ret = -ENODEV;
+               dev_err(&i2c_client->dev,
+                       "CS42L73 Device ID (%X). Expected %X\n",
+                       devid, CS42L73_DEVID);
+               goto err_regmap;
+       }
+
+       ret = regmap_read(cs42l73->regmap, CS42L73_REVID, &reg);
+       if (ret < 0) {
+               dev_err(&i2c_client->dev, "Get Revision ID failed\n");
+               goto err_regmap;
+       }
+
+       dev_info(&i2c_client->dev,
+                "Cirrus Logic CS42L73, Revision: %02X\n", reg & 0xFF);
+
+       regcache_cache_only(cs42l73->regmap, true);
+
+       ret =  snd_soc_register_codec(&i2c_client->dev,
+                       &soc_codec_dev_cs42l73, cs42l73_dai,
+                       ARRAY_SIZE(cs42l73_dai));
+       if (ret < 0)
+               goto err_regmap;
+       return 0;
+
+err_regmap:
+       regmap_exit(cs42l73->regmap);
+
+err:
+       return ret;
+}
+
+static __devexit int cs42l73_i2c_remove(struct i2c_client *client)
+{
+       struct cs42l73_private *cs42l73 = i2c_get_clientdata(client);
+
+       snd_soc_unregister_codec(&client->dev);
+       regmap_exit(cs42l73->regmap);
+
+       return 0;
+}
+
+static const struct i2c_device_id cs42l73_id[] = {
+       {"cs42l73", 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, cs42l73_id);
+
+static struct i2c_driver cs42l73_i2c_driver = {
+       .driver = {
+                  .name = "cs42l73",
+                  .owner = THIS_MODULE,
+                  },
+       .id_table = cs42l73_id,
+       .probe = cs42l73_i2c_probe,
+       .remove = __devexit_p(cs42l73_i2c_remove),
+
+};
+
+static int __init cs42l73_modinit(void)
+{
+       int ret;
+       ret = i2c_add_driver(&cs42l73_i2c_driver);
+       if (ret != 0) {
+               pr_err("Failed to register CS42L73 I2C driver: %d\n", ret);
+               return ret;
+       }
+       return 0;
+}
+
+module_init(cs42l73_modinit);
+
+static void __exit cs42l73_exit(void)
+{
+       i2c_del_driver(&cs42l73_i2c_driver);
+}
+
+module_exit(cs42l73_exit);
+
+MODULE_DESCRIPTION("ASoC CS42L73 driver");
+MODULE_AUTHOR("Georgi Vlaev, Nucleus Systems Ltd, <joe@nucleusys.com>");
+MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42l73.h b/sound/soc/codecs/cs42l73.h
new file mode 100644 (file)
index 0000000..f30a4c4
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * ALSA SoC CS42L73 codec driver
+ *
+ * Copyright 2011 Cirrus Logic, Inc.
+ *
+ * Author: Georgi Vlaev <joe@nucleusys.com>
+ *        Brian Austin <brian.austin@cirrus.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __CS42L73_H__
+#define __CS42L73_H__
+
+/* I2C Registers */
+/* I2C Address: 1001010[R/W] - 10010100 = 0x94(Write); 10010101 = 0x95(Read) */
+#define CS42L73_CHIP_ID                0x4a
+#define CS42L73_DEVID_AB       0x01    /* Device ID A & B [RO]. */
+#define CS42L73_DEVID_CD       0x02    /* Device ID C & D [RO]. */
+#define CS42L73_DEVID_E                0x03    /* Device ID E [RO]. */
+#define CS42L73_REVID          0x05    /* Revision ID [RO]. */
+#define CS42L73_PWRCTL1                0x06    /* Power Control 1. */
+#define CS42L73_PWRCTL2                0x07    /* Power Control 2. */
+#define CS42L73_PWRCTL3                0x08    /* Power Control 3. */
+#define CS42L73_CPFCHC         0x09    /* Charge Pump Freq. Class H Ctl. */
+#define CS42L73_OLMBMSDC       0x0A    /* Output Load, MIC Bias, MIC2 SDT */
+#define CS42L73_DMMCC          0x0B    /* Digital MIC & Master Clock Ctl. */
+#define CS42L73_XSPC           0x0C    /* Auxiliary Serial Port (XSP) Ctl. */
+#define CS42L73_XSPMMCC                0x0D    /* XSP Master Mode Clocking Control. */
+#define CS42L73_ASPC           0x0E    /* Audio Serial Port (ASP) Control. */
+#define CS42L73_ASPMMCC                0x0F    /* ASP Master Mode Clocking Control. */
+#define CS42L73_VSPC           0x10    /* Voice Serial Port (VSP) Control. */
+#define CS42L73_VSPMMCC                0x11    /* VSP Master Mode Clocking Control. */
+#define CS42L73_VXSPFS         0x12    /* VSP & XSP Sample Rate. */
+#define CS42L73_MIOPC          0x13    /* Misc. Input & Output Path Control. */
+#define CS42L73_ADCIPC         0x14    /* ADC/IP Control. */
+#define CS42L73_MICAPREPGAAVOL 0x15    /* MIC 1 [A] PreAmp, PGAA Vol. */
+#define CS42L73_MICBPREPGABVOL 0x16    /* MIC 2 [B] PreAmp, PGAB Vol. */
+#define CS42L73_IPADVOL                0x17    /* Input Pat7h A Digital Volume. */
+#define CS42L73_IPBDVOL                0x18    /* Input Path B Digital Volume. */
+#define CS42L73_PBDC           0x19    /* Playback Digital Control. */
+#define CS42L73_HLADVOL                0x1A    /* HP/Line A Out Digital Vol. */
+#define CS42L73_HLBDVOL                0x1B    /* HP/Line B Out Digital Vol. */
+#define CS42L73_SPKDVOL                0x1C    /* Spkphone Out [A] Digital Vol. */
+#define CS42L73_ESLDVOL                0x1D    /* Ear/Spkphone LO [B] Digital */
+#define CS42L73_HPAAVOL                0x1E    /* HP A Analog Volume. */
+#define CS42L73_HPBAVOL                0x1F    /* HP B Analog Volume. */
+#define CS42L73_LOAAVOL                0x20    /* Line Out A Analog Volume. */
+#define CS42L73_LOBAVOL                0x21    /* Line Out B Analog Volume. */
+#define CS42L73_STRINV         0x22    /* Stereo Input Path Adv. Vol. */
+#define CS42L73_XSPINV         0x23    /* Auxiliary Port Input Advisory Vol. */
+#define CS42L73_ASPINV         0x24    /* Audio Port Input Advisory Vol. */
+#define CS42L73_VSPINV         0x25    /* Voice Port Input Advisory Vol. */
+#define CS42L73_LIMARATEHL     0x26    /* Lmtr Attack Rate HP/Line. */
+#define CS42L73_LIMRRATEHL     0x27    /* Lmtr Ctl, Rel.Rate HP/Line. */
+#define CS42L73_LMAXHL         0x28    /* Lmtr Thresholds HP/Line. */
+#define CS42L73_LIMARATESPK    0x29    /* Lmtr Attack Rate Spkphone [A]. */
+#define CS42L73_LIMRRATESPK    0x2A    /* Lmtr Ctl,Release Rate Spk. [A]. */
+#define CS42L73_LMAXSPK                0x2B    /* Lmtr Thresholds Spkphone [A]. */
+#define CS42L73_LIMARATEESL    0x2C    /* Lmtr Attack Rate  */
+#define CS42L73_LIMRRATEESL    0x2D    /* Lmtr Ctl,Release Rate */
+#define CS42L73_LMAXESL                0x2E    /* Lmtr Thresholds */
+#define CS42L73_ALCARATE       0x2F    /* ALC Enable, Attack Rate AB. */
+#define CS42L73_ALCRRATE       0x30    /* ALC Release Rate AB.  */
+#define CS42L73_ALCMINMAX      0x31    /* ALC Thresholds AB. */
+#define CS42L73_NGCAB          0x32    /* Noise Gate Ctl AB. */
+#define CS42L73_ALCNGMC                0x33    /* ALC & Noise Gate Misc Ctl. */
+#define CS42L73_MIXERCTL       0x34    /* Mixer Control. */
+#define CS42L73_HLAIPAA                0x35    /* HP/LO Left Mixer: L. */
+#define CS42L73_HLBIPBA                0x36    /* HP/LO Right Mixer: R.  */
+#define CS42L73_HLAXSPAA       0x37    /* HP/LO Left Mixer: XSP L */
+#define CS42L73_HLBXSPBA       0x38    /* HP/LO Right Mixer: XSP R */
+#define CS42L73_HLAASPAA       0x39    /* HP/LO Left Mixer: ASP L */
+#define CS42L73_HLBASPBA       0x3A    /* HP/LO Right Mixer: ASP R */
+#define CS42L73_HLAVSPMA       0x3B    /* HP/LO Left Mixer: VSP. */
+#define CS42L73_HLBVSPMA       0x3C    /* HP/LO Right Mixer: VSP */
+#define CS42L73_XSPAIPAA       0x3D    /* XSP Left Mixer: Left */
+#define CS42L73_XSPBIPBA       0x3E    /* XSP Rt. Mixer: Right */
+#define CS42L73_XSPAXSPAA      0x3F    /* XSP Left Mixer: XSP L */
+#define CS42L73_XSPBXSPBA      0x40    /* XSP Rt. Mixer: XSP R */
+#define CS42L73_XSPAASPAA      0x41    /* XSP Left Mixer: ASP L */
+#define CS42L73_XSPAASPBA      0x42    /* XSP Rt. Mixer: ASP R */
+#define CS42L73_XSPAVSPMA      0x43    /* XSP Left Mixer: VSP */
+#define CS42L73_XSPBVSPMA      0x44    /* XSP Rt. Mixer: VSP */
+#define CS42L73_ASPAIPAA       0x45    /* ASP Left Mixer: Left */
+#define CS42L73_ASPBIPBA       0x46    /* ASP Rt. Mixer: Right */
+#define CS42L73_ASPAXSPAA      0x47    /* ASP Left Mixer: XSP L */
+#define CS42L73_ASPBXSPBA      0x48    /* ASP Rt. Mixer: XSP R */
+#define CS42L73_ASPAASPAA      0x49    /* ASP Left Mixer: ASP L */
+#define CS42L73_ASPBASPBA      0x4A    /* ASP Rt. Mixer: ASP R */
+#define CS42L73_ASPAVSPMA      0x4B    /* ASP Left Mixer: VSP */
+#define CS42L73_ASPBVSPMA      0x4C    /* ASP Rt. Mixer: VSP */
+#define CS42L73_VSPAIPAA       0x4D    /* VSP Left Mixer: Left */
+#define CS42L73_VSPBIPBA       0x4E    /* VSP Rt. Mixer: Right */
+#define CS42L73_VSPAXSPAA      0x4F    /* VSP Left Mixer: XSP L */
+#define CS42L73_VSPBXSPBA      0x50    /* VSP Rt. Mixer: XSP R */
+#define CS42L73_VSPAASPAA      0x51    /* VSP Left Mixer: ASP Left */
+#define CS42L73_VSPBASPBA      0x52    /* VSP Rt. Mixer: ASP Right */
+#define CS42L73_VSPAVSPMA      0x53    /* VSP Left Mixer: VSP */
+#define CS42L73_VSPBVSPMA      0x54    /* VSP Rt. Mixer: VSP */
+#define CS42L73_MMIXCTL                0x55    /* Mono Mixer Controls. */
+#define CS42L73_SPKMIPMA       0x56    /* SPK Mono Mixer: In. Path */
+#define CS42L73_SPKMXSPA       0x57    /* SPK Mono Mixer: XSP Mono/L/R Att. */
+#define CS42L73_SPKMASPA       0x58    /* SPK Mono Mixer: ASP Mono/L/R Att. */
+#define CS42L73_SPKMVSPMA      0x59    /* SPK Mono Mixer: VSP Mono Atten. */
+#define CS42L73_ESLMIPMA       0x5A    /* Ear/SpLO Mono Mixer: */
+#define CS42L73_ESLMXSPA       0x5B    /* Ear/SpLO Mono Mixer: XSP */
+#define CS42L73_ESLMASPA       0x5C    /* Ear/SpLO Mono Mixer: ASP */
+#define CS42L73_ESLMVSPMA      0x5D    /* Ear/SpLO Mono Mixer: VSP */
+#define CS42L73_IM1            0x5E    /* Interrupt Mask 1.  */
+#define CS42L73_IM2            0x5F    /* Interrupt Mask 2. */
+#define CS42L73_IS1            0x60    /* Interrupt Status 1 [RO]. */
+#define CS42L73_IS2            0x61    /* Interrupt Status 2 [RO]. */
+#define CS42L73_MAX_REGISTER   0x61    /* Total Registers */
+/* Bitfield Definitions */
+
+/* CS42L73_PWRCTL1 */
+#define PDN_ADCB               (1 << 7)
+#define PDN_DMICB              (1 << 6)
+#define PDN_ADCA               (1 << 5)
+#define PDN_DMICA              (1 << 4)
+#define PDN_LDO                        (1 << 2)
+#define DISCHG_FILT            (1 << 1)
+#define PDN                    (1 << 0)
+
+/* CS42L73_PWRCTL2 */
+#define PDN_MIC2_BIAS          (1 << 7)
+#define PDN_MIC1_BIAS          (1 << 6)
+#define PDN_VSP                        (1 << 4)
+#define PDN_ASP_SDOUT          (1 << 3)
+#define PDN_ASP_SDIN           (1 << 2)
+#define PDN_XSP_SDOUT          (1 << 1)
+#define PDN_XSP_SDIN           (1 << 0)
+
+/* CS42L73_PWRCTL3 */
+#define PDN_THMS               (1 << 5)
+#define PDN_SPKLO              (1 << 4)
+#define PDN_EAR                        (1 << 3)
+#define PDN_SPK                        (1 << 2)
+#define PDN_LO                 (1 << 1)
+#define PDN_HP                 (1 << 0)
+
+/* Thermal Overload Detect. Requires interrupt ... */
+#define THMOVLD_150C           0
+#define THMOVLD_132C           1
+#define THMOVLD_115C           2
+#define THMOVLD_098C           3
+
+
+/* CS42L73_ASPC, CS42L73_XSPC, CS42L73_VSPC */
+#define        SP_3ST                  (1 << 7)
+#define SPDIF_I2S              (0 << 6)
+#define SPDIF_PCM              (1 << 6)
+#define PCM_MODE0              (0 << 4)
+#define PCM_MODE1              (1 << 4)
+#define PCM_MODE2              (2 << 4)
+#define PCM_MODE_MASK          (3 << 4)
+#define PCM_BIT_ORDER          (1 << 3)
+#define MCK_SCLK_64FS          (0 << 0)
+#define MCK_SCLK_MCLK          (2 << 0)
+#define MCK_SCLK_PREMCLK       (3 << 0)
+
+/* CS42L73_xSPMMCC */
+#define MS_MASTER              (1 << 7)
+
+
+/* CS42L73_DMMCC */
+#define MCLKDIS                        (1 << 0)
+#define MCLKSEL_MCLK2          (1 << 4)
+#define MCLKSEL_MCLK1          (0 << 4)
+
+/* CS42L73 MCLK derived from MCLK1 or MCLK2 */
+#define CS42L73_CLKID_MCLK1     0
+#define CS42L73_CLKID_MCLK2     1
+
+#define CS42L73_MCLKXDIV       0
+#define CS42L73_MMCCDIV         1
+
+#define CS42L73_XSP            0
+#define CS42L73_ASP            1
+#define CS42L73_VSP            2
+
+/* IS1, IM1 */
+#define MIC2_SDET              (1 << 6)
+#define THMOVLD                        (1 << 4)
+#define DIGMIXOVFL             (1 << 3)
+#define IPBOVFL                        (1 << 1)
+#define IPAOVFL                        (1 << 0)
+
+/* Analog Softramp */
+#define ANLGOSFT               (1 << 0)
+
+/* HP A/B Analog Mute */
+#define HPA_MUTE               (1 << 7)
+/* LO A/B Analog Mute  */
+#define LOA_MUTE               (1 << 7)
+/* Digital Mute */
+#define HLAD_MUTE              (1 << 0)
+#define HLBD_MUTE              (1 << 1)
+#define SPKD_MUTE              (1 << 2)
+#define ESLD_MUTE              (1 << 3)
+
+/* Misc defines for codec */
+#define CS42L73_RESET_GPIO 143
+
+#define CS42L73_DEVID          0x00042A73
+#define CS42L73_MCLKX_MIN      5644800
+#define CS42L73_MCLKX_MAX      38400000
+
+#define CS42L73_SPC(id)                (CS42L73_XSPC + (id << 1))
+#define CS42L73_MMCC(id)       (CS42L73_XSPMMCC + (id << 1))
+#define CS42L73_SPFS(id)       ((id == CS42L73_ASP) ? CS42L73_ASPC : CS42L73_VXSPFS)
+
+#endif /* __CS42L73_H__ */
index bc7067d..ae55e31 100644 (file)
@@ -391,17 +391,7 @@ static struct platform_driver cx20442_platform_driver = {
        .remove = __exit_p(cx20442_platform_remove),
 };
 
-static int __init cx20442_init(void)
-{
-       return platform_driver_register(&cx20442_platform_driver);
-}
-module_init(cx20442_init);
-
-static void __exit cx20442_exit(void)
-{
-       platform_driver_unregister(&cx20442_platform_driver);
-}
-module_exit(cx20442_exit);
+module_platform_driver(cx20442_platform_driver);
 
 MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver");
 MODULE_AUTHOR("Janusz Krzysztofik");
index b545b7d..e4ca61c 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <linux/delay.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <sound/pcm.h>
@@ -240,7 +239,7 @@ static const DECLARE_TLV_DB_SCALE(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[] = {
+static const char * const da7210_hpf_cutoff_txt[] = {
        "Fs/8192*pi", "Fs/4096*pi", "Fs/2048*pi", "Fs/1024*pi"
 };
 
@@ -251,7 +250,7 @@ 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[] = {
+static const char * const da7210_vf_cutoff_txt[] = {
        "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
 };
 
@@ -761,7 +760,7 @@ static int da7210_mute(struct snd_soc_dai *dai, int mute)
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
 /* DAI operations */
-static struct snd_soc_dai_ops da7210_dai_ops = {
+static const struct snd_soc_dai_ops da7210_dai_ops = {
        .hw_params      = da7210_hw_params,
        .set_fmt        = da7210_set_dai_fmt,
        .digital_mute   = da7210_mute,
index 704bbde..bfe46aa 100644 (file)
@@ -55,17 +55,7 @@ static struct platform_driver dfmcs320_driver = {
        .remove = __devexit_p(dfbmcs320_remove),
 };
 
-static int __init dfbmcs320_init(void)
-{
-       return platform_driver_register(&dfmcs320_driver);
-}
-module_init(dfbmcs320_init);
-
-static void __exit dfbmcs320_exit(void)
-{
-       platform_driver_unregister(&dfmcs320_driver);
-}
-module_exit(dfbmcs320_exit);
+module_platform_driver(dfmcs320_driver);
 
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("ASoC DFBM-CS320 bluethooth module driver");
index 6fae765..3e929f0 100644 (file)
@@ -89,17 +89,7 @@ static struct platform_driver dmic_driver = {
        .remove = __devexit_p(dmic_dev_remove),
 };
 
-static int __init dmic_init(void)
-{
-       return platform_driver_register(&dmic_driver);
-}
-module_init(dmic_init);
-
-static void __exit dmic_exit(void)
-{
-       platform_driver_unregister(&dmic_driver);
-}
-module_exit(dmic_exit);
+module_platform_driver(dmic_driver);
 
 MODULE_DESCRIPTION("Generic DMIC driver");
 MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
index e373f8f..d73d283 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 
 #include <linux/delay.h>
 
@@ -206,7 +207,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_dai_ops jz4740_codec_dai_ops = {
+static const struct snd_soc_dai_ops jz4740_codec_dai_ops = {
        .hw_params = jz4740_codec_hw_params,
 };
 
@@ -311,7 +312,7 @@ static int jz4740_codec_dev_remove(struct snd_soc_codec *codec)
 
 #ifdef CONFIG_PM_SLEEP
 
-static int jz4740_codec_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int jz4740_codec_suspend(struct snd_soc_codec *codec)
 {
        return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
 }
@@ -424,17 +425,7 @@ static struct platform_driver jz4740_codec_driver = {
        },
 };
 
-static int __init jz4740_codec_init(void)
-{
-       return platform_driver_register(&jz4740_codec_driver);
-}
-module_init(jz4740_codec_init);
-
-static void __exit jz4740_codec_exit(void)
-{
-       platform_driver_unregister(&jz4740_codec_driver);
-}
-module_exit(jz4740_codec_exit);
+module_platform_driver(jz4740_codec_driver);
 
 MODULE_DESCRIPTION("JZ4740 SoC internal codec driver");
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
index ebbf63c..ba4f6f1 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -1650,14 +1649,14 @@ static int max98088_set_bias_level(struct snd_soc_codec *codec,
 #define MAX98088_RATES SNDRV_PCM_RATE_8000_96000
 #define MAX98088_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops max98088_dai1_ops = {
+static const struct snd_soc_dai_ops max98088_dai1_ops = {
        .set_sysclk = max98088_dai_set_sysclk,
        .set_fmt = max98088_dai1_set_fmt,
        .hw_params = max98088_dai1_hw_params,
        .digital_mute = max98088_dai1_digital_mute,
 };
 
-static struct snd_soc_dai_ops max98088_dai2_ops = {
+static const struct snd_soc_dai_ops max98088_dai2_ops = {
        .set_sysclk = max98088_dai_set_sysclk,
        .set_fmt = max98088_dai2_set_fmt,
        .hw_params = max98088_dai2_hw_params,
@@ -1947,7 +1946,7 @@ static void max98088_handle_pdata(struct snd_soc_codec *codec)
 }
 
 #ifdef CONFIG_PM
-static int max98088_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int max98088_suspend(struct snd_soc_codec *codec)
 {
        max98088_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
index 26d7b08..c69dd02 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -1782,19 +1781,19 @@ static int max98095_set_bias_level(struct snd_soc_codec *codec,
 #define MAX98095_RATES SNDRV_PCM_RATE_8000_96000
 #define MAX98095_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops max98095_dai1_ops = {
+static const struct snd_soc_dai_ops max98095_dai1_ops = {
        .set_sysclk = max98095_dai_set_sysclk,
        .set_fmt = max98095_dai1_set_fmt,
        .hw_params = max98095_dai1_hw_params,
 };
 
-static struct snd_soc_dai_ops max98095_dai2_ops = {
+static const struct snd_soc_dai_ops max98095_dai2_ops = {
        .set_sysclk = max98095_dai_set_sysclk,
        .set_fmt = max98095_dai2_set_fmt,
        .hw_params = max98095_dai2_hw_params,
 };
 
-static struct snd_soc_dai_ops max98095_dai3_ops = {
+static const struct snd_soc_dai_ops max98095_dai3_ops = {
        .set_sysclk = max98095_dai_set_sysclk,
        .set_fmt = max98095_dai3_set_fmt,
        .hw_params = max98095_dai3_hw_params,
@@ -2175,7 +2174,7 @@ static void max98095_handle_pdata(struct snd_soc_codec *codec)
 }
 
 #ifdef CONFIG_PM
-static int max98095_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int max98095_suspend(struct snd_soc_codec *codec)
 {
        max98095_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
index 208d2ee..7dfd6e8 100644 (file)
@@ -254,7 +254,7 @@ static int max9850_set_bias_level(struct snd_soc_codec *codec,
 #define MAX9850_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
        SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops max9850_dai_ops = {
+static const struct snd_soc_dai_ops max9850_dai_ops = {
        .hw_params      = max9850_hw_params,
        .set_sysclk     = max9850_set_dai_sysclk,
        .set_fmt        = max9850_set_dai_fmt,
@@ -273,7 +273,7 @@ static struct snd_soc_dai_driver max9850_dai = {
 };
 
 #ifdef CONFIG_PM
-static int max9850_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int max9850_suspend(struct snd_soc_codec *codec)
 {
        max9850_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
index 9e7e964..dcf6f2a 100644 (file)
@@ -106,13 +106,13 @@ static int max9877_set_2reg(struct snd_kcontrol *kcontrol,
        unsigned int mask = mc->max;
        unsigned int val = (ucontrol->value.integer.value[0] & mask);
        unsigned int val2 = (ucontrol->value.integer.value[1] & mask);
-       unsigned int change = 1;
+       unsigned int change = 0;
 
-       if (((max9877_regs[reg] >> shift) & mask) == val)
-               change = 0;
+       if (((max9877_regs[reg] >> shift) & mask) != val)
+               change = 1;
 
-       if (((max9877_regs[reg2] >> shift) & mask) == val2)
-               change = 0;
+       if (((max9877_regs[reg2] >> shift) & mask) != val2)
+               change = 1;
 
        if (change) {
                max9877_regs[reg] &= ~(mask << shift);
index f731651..edcaa7e 100644 (file)
@@ -118,7 +118,7 @@ static int pcm3008_soc_remove(struct snd_soc_codec *codec)
 }
 
 #ifdef CONFIG_PM
-static int pcm3008_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
+static int pcm3008_soc_suspend(struct snd_soc_codec *codec)
 {
        struct pcm3008_setup_data *setup = codec->dev->platform_data;
 
@@ -172,17 +172,7 @@ static struct platform_driver pcm3008_codec_driver = {
        },
 };
 
-static int __init pcm3008_modinit(void)
-{
-       return platform_driver_register(&pcm3008_codec_driver);
-}
-module_init(pcm3008_modinit);
-
-static void __exit pcm3008_exit(void)
-{
-       platform_driver_unregister(&pcm3008_codec_driver);
-}
-module_exit(pcm3008_exit);
+module_platform_driver(pcm3008_codec_driver);
 
 MODULE_DESCRIPTION("Soc PCM3008 driver");
 MODULE_AUTHOR("Hugo Villeneuve");
index 27a078c..f6e4f5e 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -177,7 +176,7 @@ 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),
+       TLV_DB_RANGE_HEAD(7),
        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),
@@ -1642,7 +1641,7 @@ static int rt5631_remove(struct snd_soc_codec *codec)
 }
 
 #ifdef CONFIG_PM
-static int rt5631_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int rt5631_suspend(struct snd_soc_codec *codec)
 {
        rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -1664,7 +1663,7 @@ static int rt5631_resume(struct snd_soc_codec *codec)
                        SNDRV_PCM_FMTBIT_S24_LE | \
                        SNDRV_PCM_FMTBIT_S8)
 
-static struct snd_soc_dai_ops rt5631_ops = {
+static const struct snd_soc_dai_ops rt5631_ops = {
        .hw_params = rt5631_hifi_pcm_params,
        .set_fmt = rt5631_hifi_codec_set_dai_fmt,
        .set_sysclk = rt5631_hifi_codec_set_dai_sysclk,
index d15695d..2501757 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/clk.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/consumer.h>
@@ -365,7 +364,7 @@ static const DECLARE_TLV_DB_SCALE(capture_6db_attenuate, -600, 600, 0);
 
 /* tlv for mic gain, 0db 20db 30db 40db */
 static const unsigned int mic_gain_tlv[] = {
-       TLV_DB_RANGE_HEAD(4),
+       TLV_DB_RANGE_HEAD(2),
        0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
        1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0),
 };
@@ -923,7 +922,7 @@ static int sgtl5000_set_bias_level(struct snd_soc_codec *codec,
                        SNDRV_PCM_FMTBIT_S24_LE |\
                        SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops sgtl5000_ops = {
+static const struct snd_soc_dai_ops sgtl5000_ops = {
        .hw_params = sgtl5000_pcm_hw_params,
        .digital_mute = sgtl5000_digital_mute,
        .set_fmt = sgtl5000_set_dai_fmt,
@@ -968,7 +967,7 @@ static int sgtl5000_volatile_register(struct snd_soc_codec *codec,
 }
 
 #ifdef CONFIG_SUSPEND
-static int sgtl5000_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int sgtl5000_suspend(struct snd_soc_codec *codec)
 {
        sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c
new file mode 100644 (file)
index 0000000..5be42bf
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Load Analog Devices SigmaStudio firmware files
+ *
+ * Copyright 2009-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/module.h>
+
+#include "sigmadsp.h"
+
+#define SIGMA_MAGIC "ADISIGM"
+
+struct sigma_firmware_header {
+       unsigned char magic[7];
+       u8 version;
+       __le32 crc;
+} __packed;
+
+enum {
+       SIGMA_ACTION_WRITEXBYTES = 0,
+       SIGMA_ACTION_WRITESINGLE,
+       SIGMA_ACTION_WRITESAFELOAD,
+       SIGMA_ACTION_DELAY,
+       SIGMA_ACTION_PLLWAIT,
+       SIGMA_ACTION_NOOP,
+       SIGMA_ACTION_END,
+};
+
+struct sigma_action {
+       u8 instr;
+       u8 len_hi;
+       __le16 len;
+       __be16 addr;
+       unsigned char payload[];
+} __packed;
+
+struct sigma_firmware {
+       const struct firmware *fw;
+       size_t pos;
+
+       void *control_data;
+       int (*write)(void *control_data, const struct sigma_action *sa,
+                       size_t len);
+};
+
+static inline u32 sigma_action_len(struct sigma_action *sa)
+{
+       return (sa->len_hi << 16) | le16_to_cpu(sa->len);
+}
+
+static size_t sigma_action_size(struct sigma_action *sa)
+{
+       size_t payload = 0;
+
+       switch (sa->instr) {
+       case SIGMA_ACTION_WRITEXBYTES:
+       case SIGMA_ACTION_WRITESINGLE:
+       case SIGMA_ACTION_WRITESAFELOAD:
+               payload = sigma_action_len(sa);
+               break;
+       default:
+               break;
+       }
+
+       payload = ALIGN(payload, 2);
+
+       return payload + sizeof(struct sigma_action);
+}
+
+/*
+ * Returns a negative error value in case of an error, 0 if processing of
+ * the firmware should be stopped after this action, 1 otherwise.
+ */
+static int
+process_sigma_action(struct sigma_firmware *ssfw, struct sigma_action *sa)
+{
+       size_t len = sigma_action_len(sa);
+       int ret;
+
+       pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,
+               sa->instr, sa->addr, len);
+
+       switch (sa->instr) {
+       case SIGMA_ACTION_WRITEXBYTES:
+       case SIGMA_ACTION_WRITESINGLE:
+       case SIGMA_ACTION_WRITESAFELOAD:
+               ret = ssfw->write(ssfw->control_data, sa, len);
+               if (ret < 0)
+                       return -EINVAL;
+               break;
+       case SIGMA_ACTION_DELAY:
+               udelay(len);
+               len = 0;
+               break;
+       case SIGMA_ACTION_END:
+               return 0;
+       default:
+               return -EINVAL;
+       }
+
+       return 1;
+}
+
+static int
+process_sigma_actions(struct sigma_firmware *ssfw)
+{
+       struct sigma_action *sa;
+       size_t size;
+       int ret;
+
+       while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) {
+               sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos);
+
+               size = sigma_action_size(sa);
+               ssfw->pos += size;
+               if (ssfw->pos > ssfw->fw->size || size == 0)
+                       break;
+
+               ret = process_sigma_action(ssfw, sa);
+
+               pr_debug("%s: action returned %i\n", __func__, ret);
+
+               if (ret <= 0)
+                       return ret;
+       }
+
+       if (ssfw->pos != ssfw->fw->size)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int _process_sigma_firmware(struct device *dev,
+       struct sigma_firmware *ssfw, const char *name)
+{
+       int ret;
+       struct sigma_firmware_header *ssfw_head;
+       const struct firmware *fw;
+       u32 crc;
+
+       pr_debug("%s: loading firmware %s\n", __func__, name);
+
+       /* first load the blob */
+       ret = request_firmware(&fw, name, dev);
+       if (ret) {
+               pr_debug("%s: request_firmware() failed with %i\n", __func__, ret);
+               return ret;
+       }
+       ssfw->fw = fw;
+
+       /* then verify the header */
+       ret = -EINVAL;
+
+       /*
+        * Reject too small or unreasonable large files. The upper limit has been
+        * chosen a bit arbitrarily, but it should be enough for all practical
+        * purposes and having the limit makes it easier to avoid integer
+        * overflows later in the loading process.
+        */
+       if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) {
+               dev_err(dev, "Failed to load firmware: Invalid size\n");
+               goto done;
+       }
+
+       ssfw_head = (void *)fw->data;
+       if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) {
+               dev_err(dev, "Failed to load firmware: Invalid magic\n");
+               goto done;
+       }
+
+       crc = crc32(0, fw->data + sizeof(*ssfw_head),
+                       fw->size - sizeof(*ssfw_head));
+       pr_debug("%s: crc=%x\n", __func__, crc);
+       if (crc != le32_to_cpu(ssfw_head->crc)) {
+               dev_err(dev, "Failed to load firmware: Wrong crc checksum: expected %x got %x\n",
+                       le32_to_cpu(ssfw_head->crc), crc);
+               goto done;
+       }
+
+       ssfw->pos = sizeof(*ssfw_head);
+
+       /* finally process all of the actions */
+       ret = process_sigma_actions(ssfw);
+
+ done:
+       release_firmware(fw);
+
+       pr_debug("%s: loaded %s\n", __func__, name);
+
+       return ret;
+}
+
+#if IS_ENABLED(CONFIG_I2C)
+
+static int sigma_action_write_i2c(void *control_data,
+       const struct sigma_action *sa, size_t len)
+{
+       return i2c_master_send(control_data, (const unsigned char *)&sa->addr,
+               len);
+}
+
+int process_sigma_firmware(struct i2c_client *client, const char *name)
+{
+       struct sigma_firmware ssfw;
+
+       ssfw.control_data = client;
+       ssfw.write = sigma_action_write_i2c;
+
+       return _process_sigma_firmware(&client->dev, &ssfw, name);
+}
+EXPORT_SYMBOL(process_sigma_firmware);
+
+#endif
+
+#if IS_ENABLED(CONFIG_REGMAP)
+
+static int sigma_action_write_regmap(void *control_data,
+       const struct sigma_action *sa, size_t len)
+{
+       return regmap_raw_write(control_data, le16_to_cpu(sa->addr),
+               sa->payload, len - 2);
+}
+
+int process_sigma_firmware_regmap(struct device *dev, struct regmap *regmap,
+       const char *name)
+{
+       struct sigma_firmware ssfw;
+
+       ssfw.control_data = regmap;
+       ssfw.write = sigma_action_write_regmap;
+
+       return _process_sigma_firmware(dev, &ssfw, name);
+}
+EXPORT_SYMBOL(process_sigma_firmware_regmap);
+
+#endif
+
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sigmadsp.h b/sound/soc/codecs/sigmadsp.h
new file mode 100644 (file)
index 0000000..e439cbd
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Load firmware files from Analog Devices SigmaStudio
+ *
+ * Copyright 2009-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __SIGMA_FIRMWARE_H__
+#define __SIGMA_FIRMWARE_H__
+
+#include <linux/device.h>
+#include <linux/regmap.h>
+
+struct i2c_client;
+
+extern int process_sigma_firmware(struct i2c_client *client, const char *name);
+extern int process_sigma_firmware_regmap(struct device *dev,
+               struct regmap *regmap, const char *name);
+
+#endif
index 887d618..f99baa0 100644 (file)
@@ -698,21 +698,21 @@ static int sn95031_pcm_hw_params(struct snd_pcm_substream *substream,
 }
 
 /* Codec DAI section */
-static struct snd_soc_dai_ops sn95031_headset_dai_ops = {
+static const struct snd_soc_dai_ops sn95031_headset_dai_ops = {
        .digital_mute   = sn95031_pcm_hs_mute,
        .hw_params      = sn95031_pcm_hw_params,
 };
 
-static struct snd_soc_dai_ops sn95031_speaker_dai_ops = {
+static const struct snd_soc_dai_ops sn95031_speaker_dai_ops = {
        .digital_mute   = sn95031_pcm_spkr_mute,
        .hw_params      = sn95031_pcm_hw_params,
 };
 
-static struct snd_soc_dai_ops sn95031_vib1_dai_ops = {
+static const struct snd_soc_dai_ops sn95031_vib1_dai_ops = {
        .hw_params      = sn95031_pcm_hw_params,
 };
 
-static struct snd_soc_dai_ops sn95031_vib2_dai_ops = {
+static const struct snd_soc_dai_ops sn95031_vib2_dai_ops = {
        .hw_params      = sn95031_pcm_hw_params,
 };
 
@@ -920,19 +920,7 @@ static struct platform_driver sn95031_codec_driver = {
        .remove         = __devexit_p(sn95031_device_remove),
 };
 
-static int __init sn95031_init(void)
-{
-       pr_debug("driver init called\n");
-       return platform_driver_register(&sn95031_codec_driver);
-}
-module_init(sn95031_init);
-
-static void __exit sn95031_exit(void)
-{
-       pr_debug("driver exit called\n");
-       platform_driver_unregister(&sn95031_codec_driver);
-}
-module_exit(sn95031_exit);
+module_platform_driver(sn95031_codec_driver);
 
 MODULE_DESCRIPTION("ASoC TI SN95031 codec driver");
 MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
index 6a1a7e7..112a49d 100644 (file)
@@ -61,18 +61,7 @@ static struct platform_driver spdif_dit_driver = {
        },
 };
 
-static int __init dit_modinit(void)
-{
-       return platform_driver_register(&spdif_dit_driver);
-}
-
-static void __exit dit_exit(void)
-{
-       platform_driver_unregister(&spdif_dit_driver);
-}
-
-module_init(dit_modinit);
-module_exit(dit_exit);
+module_platform_driver(spdif_dit_driver);
 
 MODULE_AUTHOR("Steve Chen <schen@mvista.com>");
 MODULE_DESCRIPTION("SPDIF dummy codec driver");
index 3cb3271..7dfc7b0 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -498,7 +497,7 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
 #define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops ssm2602_dai_ops = {
+static const struct snd_soc_dai_ops ssm2602_dai_ops = {
        .startup        = ssm2602_startup,
        .hw_params      = ssm2602_hw_params,
        .shutdown       = ssm2602_shutdown,
@@ -524,7 +523,7 @@ static struct snd_soc_dai_driver ssm2602_dai = {
        .ops = &ssm2602_dai_ops,
 };
 
-static int ssm2602_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int ssm2602_suspend(struct snd_soc_codec *codec)
 {
        ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
index bb82408..6648af6 100644 (file)
@@ -24,9 +24,9 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+#include <linux/workqueue.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -35,6 +35,7 @@
 #include <sound/initval.h>
 #include <sound/tlv.h>
 
+#include <sound/sta32x.h>
 #include "sta32x.h"
 
 #define STA32X_RATES (SNDRV_PCM_RATE_32000 | \
@@ -73,9 +74,14 @@ static const char *sta32x_supply_names[] = {
 struct sta32x_priv {
        struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)];
        struct snd_soc_codec *codec;
+       struct sta32x_platform_data *pdata;
 
        unsigned int mclk;
        unsigned int format;
+
+       u32 coef_shadow[STA32X_COEF_COUNT];
+       struct delayed_work watchdog_work;
+       int shutdown;
 };
 
 static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1);
@@ -227,6 +233,7 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
                                  struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
        int numcoef = kcontrol->private_value >> 16;
        int index = kcontrol->private_value & 0xffff;
        unsigned int cfud;
@@ -239,6 +246,11 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
        snd_soc_write(codec, STA32X_CFUD, cfud);
 
        snd_soc_write(codec, STA32X_CFADDR2, index);
+       for (i = 0; i < numcoef && (index + i < STA32X_COEF_COUNT); i++)
+               sta32x->coef_shadow[index + i] =
+                         (ucontrol->value.bytes.data[3 * i] << 16)
+                       | (ucontrol->value.bytes.data[3 * i + 1] << 8)
+                       | (ucontrol->value.bytes.data[3 * i + 2]);
        for (i = 0; i < 3 * numcoef; i++)
                snd_soc_write(codec, STA32X_B1CF1 + i,
                              ucontrol->value.bytes.data[i]);
@@ -252,6 +264,88 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec)
+{
+       struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
+       unsigned int cfud;
+       int i;
+
+       /* preserve reserved bits in STA32X_CFUD */
+       cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0;
+
+       for (i = 0; i < STA32X_COEF_COUNT; i++) {
+               snd_soc_write(codec, STA32X_CFADDR2, i);
+               snd_soc_write(codec, STA32X_B1CF1,
+                             (sta32x->coef_shadow[i] >> 16) & 0xff);
+               snd_soc_write(codec, STA32X_B1CF2,
+                             (sta32x->coef_shadow[i] >> 8) & 0xff);
+               snd_soc_write(codec, STA32X_B1CF3,
+                             (sta32x->coef_shadow[i]) & 0xff);
+               /* chip documentation does not say if the bits are
+                * self-clearing, so do it explicitly */
+               snd_soc_write(codec, STA32X_CFUD, cfud);
+               snd_soc_write(codec, STA32X_CFUD, cfud | 0x01);
+       }
+       return 0;
+}
+
+static int sta32x_cache_sync(struct snd_soc_codec *codec)
+{
+       unsigned int mute;
+       int rc;
+
+       if (!codec->cache_sync)
+               return 0;
+
+       /* mute during register sync */
+       mute = snd_soc_read(codec, STA32X_MMUTE);
+       snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE);
+       sta32x_sync_coef_shadow(codec);
+       rc = snd_soc_cache_sync(codec);
+       snd_soc_write(codec, STA32X_MMUTE, mute);
+       return rc;
+}
+
+/* work around ESD issue where sta32x resets and loses all configuration */
+static void sta32x_watchdog(struct work_struct *work)
+{
+       struct sta32x_priv *sta32x = container_of(work, struct sta32x_priv,
+                                                 watchdog_work.work);
+       struct snd_soc_codec *codec = sta32x->codec;
+       unsigned int confa, confa_cached;
+
+       /* check if sta32x has reset itself */
+       confa_cached = snd_soc_read(codec, STA32X_CONFA);
+       codec->cache_bypass = 1;
+       confa = snd_soc_read(codec, STA32X_CONFA);
+       codec->cache_bypass = 0;
+       if (confa != confa_cached) {
+               codec->cache_sync = 1;
+               sta32x_cache_sync(codec);
+       }
+
+       if (!sta32x->shutdown)
+               schedule_delayed_work(&sta32x->watchdog_work,
+                                     round_jiffies_relative(HZ));
+}
+
+static void sta32x_watchdog_start(struct sta32x_priv *sta32x)
+{
+       if (sta32x->pdata->needs_esd_watchdog) {
+               sta32x->shutdown = 0;
+               schedule_delayed_work(&sta32x->watchdog_work,
+                                     round_jiffies_relative(HZ));
+       }
+}
+
+static void sta32x_watchdog_stop(struct sta32x_priv *sta32x)
+{
+       if (sta32x->pdata->needs_esd_watchdog) {
+               sta32x->shutdown = 1;
+               cancel_delayed_work_sync(&sta32x->watchdog_work);
+       }
+}
+
 #define SINGLE_COEF(xname, index) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
        .info = sta32x_coefficient_info, \
@@ -661,7 +755,8 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec,
                                return ret;
                        }
 
-                       snd_soc_cache_sync(codec);
+                       sta32x_cache_sync(codec);
+                       sta32x_watchdog_start(sta32x);
                }
 
                /* Power up to mute */
@@ -678,7 +773,7 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec,
                                    STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
                                    STA32X_CONFF_PWDN);
                msleep(300);
-
+               sta32x_watchdog_stop(sta32x);
                regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies),
                                       sta32x->supplies);
                break;
@@ -687,7 +782,7 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-static struct snd_soc_dai_ops sta32x_dai_ops = {
+static const struct snd_soc_dai_ops sta32x_dai_ops = {
        .hw_params      = sta32x_hw_params,
        .set_sysclk     = sta32x_set_dai_sysclk,
        .set_fmt        = sta32x_set_dai_fmt,
@@ -706,7 +801,7 @@ static struct snd_soc_dai_driver sta32x_dai = {
 };
 
 #ifdef CONFIG_PM
-static int sta32x_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int sta32x_suspend(struct snd_soc_codec *codec)
 {
        sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -725,9 +820,10 @@ static int sta32x_resume(struct snd_soc_codec *codec)
 static int sta32x_probe(struct snd_soc_codec *codec)
 {
        struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
-       int i, ret = 0;
+       int i, ret = 0, thermal = 0;
 
        sta32x->codec = codec;
+       sta32x->pdata = dev_get_platdata(codec->dev);
 
        /* regulators */
        for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++)
@@ -770,25 +866,48 @@ static int sta32x_probe(struct snd_soc_codec *codec)
        snd_soc_cache_write(codec, STA32X_AUTO3, 0x00);
        snd_soc_cache_write(codec, STA32X_C3CFG, 0x40);
 
-       /* FIXME enable thermal warning adjustment and recovery  */
+       /* set thermal warning adjustment and recovery */
+       if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE))
+               thermal |= STA32X_CONFA_TWAB;
+       if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_RECOVERY_ENABLE))
+               thermal |= STA32X_CONFA_TWRB;
        snd_soc_update_bits(codec, STA32X_CONFA,
-                           STA32X_CONFA_TWAB | STA32X_CONFA_TWRB, 0);
+                           STA32X_CONFA_TWAB | STA32X_CONFA_TWRB,
+                           thermal);
 
-       /* FIXME select 2.1 mode  */
+       /* select output configuration  */
        snd_soc_update_bits(codec, STA32X_CONFF,
                            STA32X_CONFF_OCFG_MASK,
-                           1 << STA32X_CONFF_OCFG_SHIFT);
+                           sta32x->pdata->output_conf
+                           << STA32X_CONFF_OCFG_SHIFT);
 
-       /* FIXME channel to output mapping */
+       /* channel to output mapping */
        snd_soc_update_bits(codec, STA32X_C1CFG,
                            STA32X_CxCFG_OM_MASK,
-                           0 << STA32X_CxCFG_OM_SHIFT);
+                           sta32x->pdata->ch1_output_mapping
+                           << STA32X_CxCFG_OM_SHIFT);
        snd_soc_update_bits(codec, STA32X_C2CFG,
                            STA32X_CxCFG_OM_MASK,
-                           1 << STA32X_CxCFG_OM_SHIFT);
+                           sta32x->pdata->ch2_output_mapping
+                           << STA32X_CxCFG_OM_SHIFT);
        snd_soc_update_bits(codec, STA32X_C3CFG,
                            STA32X_CxCFG_OM_MASK,
-                           2 << STA32X_CxCFG_OM_SHIFT);
+                           sta32x->pdata->ch3_output_mapping
+                           << STA32X_CxCFG_OM_SHIFT);
+
+       /* initialize coefficient shadow RAM with reset values */
+       for (i = 4; i <= 49; i += 5)
+               sta32x->coef_shadow[i] = 0x400000;
+       for (i = 50; i <= 54; i++)
+               sta32x->coef_shadow[i] = 0x7fffff;
+       sta32x->coef_shadow[55] = 0x5a9df7;
+       sta32x->coef_shadow[56] = 0x7fffff;
+       sta32x->coef_shadow[59] = 0x7fffff;
+       sta32x->coef_shadow[60] = 0x400000;
+       sta32x->coef_shadow[61] = 0x400000;
+
+       if (sta32x->pdata->needs_esd_watchdog)
+               INIT_DELAYED_WORK(&sta32x->watchdog_work, sta32x_watchdog);
 
        sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        /* Bias level configuration will have done an extra enable */
@@ -806,6 +925,7 @@ static int sta32x_remove(struct snd_soc_codec *codec)
 {
        struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
 
+       sta32x_watchdog_stop(sta32x);
        sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
        regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
        regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
index b97ee5a..d8e32a6 100644 (file)
@@ -19,6 +19,7 @@
 /* STA326 register addresses */
 
 #define STA32X_REGISTER_COUNT  0x2d
+#define STA32X_COEF_COUNT 62
 
 #define STA32X_CONFA   0x00
 #define STA32X_CONFB    0x01
index 78b2b50..cc0566c 100644 (file)
@@ -256,8 +256,7 @@ static int stac9766_reset(struct snd_soc_codec *codec, int try_warm)
        return 0;
 }
 
-static int stac9766_codec_suspend(struct snd_soc_codec *codec,
-                                 pm_message_t state)
+static int stac9766_codec_suspend(struct snd_soc_codec *codec)
 {
        stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -286,11 +285,11 @@ reset:
        return 0;
 }
 
-static struct snd_soc_dai_ops stac9766_dai_ops_analog = {
+static const struct snd_soc_dai_ops stac9766_dai_ops_analog = {
        .prepare = ac97_analog_prepare,
 };
 
-static struct snd_soc_dai_ops stac9766_dai_ops_digital = {
+static const struct snd_soc_dai_ops stac9766_dai_ops_digital = {
        .prepare = ac97_digital_prepare,
 };
 
@@ -380,7 +379,7 @@ static struct snd_soc_codec_driver soc_codec_dev_stac9766 = {
        .remove = stac9766_codec_remove,
        .suspend = stac9766_codec_suspend,
        .resume = stac9766_codec_resume,
-       .reg_cache_size = sizeof(stac9766_reg),
+       .reg_cache_size = ARRAY_SIZE(stac9766_reg),
        .reg_word_size = sizeof(u16),
        .reg_cache_step = 2,
        .reg_cache_default = stac9766_reg,
@@ -408,17 +407,7 @@ static struct platform_driver stac9766_codec_driver = {
        .remove = __devexit_p(stac9766_remove),
 };
 
-static int __init stac9766_init(void)
-{
-       return platform_driver_register(&stac9766_codec_driver);
-}
-module_init(stac9766_init);
-
-static void __exit stac9766_exit(void)
-{
-       platform_driver_unregister(&stac9766_codec_driver);
-}
-module_exit(stac9766_exit);
+module_platform_driver(stac9766_codec_driver);
 
 MODULE_DESCRIPTION("ASoC stac9766 driver");
 MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
index 336de8f..60d08ae 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -503,7 +502,7 @@ static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
 #define AIC23_FORMATS  (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
                         SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops tlv320aic23_dai_ops = {
+static const struct snd_soc_dai_ops tlv320aic23_dai_ops = {
        .prepare        = tlv320aic23_pcm_prepare,
        .hw_params      = tlv320aic23_hw_params,
        .shutdown       = tlv320aic23_shutdown,
@@ -529,8 +528,7 @@ static struct snd_soc_dai_driver tlv320aic23_dai = {
        .ops = &tlv320aic23_dai_ops,
 };
 
-static int tlv320aic23_suspend(struct snd_soc_codec *codec,
-                              pm_message_t state)
+static int tlv320aic23_suspend(struct snd_soc_codec *codec)
 {
        tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
index 7859bdc..86d1fa3 100644 (file)
@@ -275,7 +275,7 @@ static int aic26_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 #define AIC26_FORMATS  (SNDRV_PCM_FMTBIT_S8     | SNDRV_PCM_FMTBIT_S16_BE |\
                         SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE)
 
-static struct snd_soc_dai_ops aic26_dai_ops = {
+static const struct snd_soc_dai_ops aic26_dai_ops = {
        .hw_params      = aic26_hw_params,
        .digital_mute   = aic26_mute,
        .set_sysclk     = aic26_set_sysclk,
index b21c610..81a26e1 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/cdev.h>
 #include <linux/slab.h>
 
@@ -597,7 +596,7 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
 #define AIC32X4_FORMATS        (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
                         | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops aic32x4_ops = {
+static const struct snd_soc_dai_ops aic32x4_ops = {
        .hw_params = aic32x4_hw_params,
        .digital_mute = aic32x4_mute,
        .set_fmt = aic32x4_set_dai_fmt,
@@ -622,7 +621,7 @@ static struct snd_soc_dai_driver aic32x4_dai = {
        .symmetric_rates = 1,
 };
 
-static int aic32x4_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int aic32x4_suspend(struct snd_soc_codec *codec)
 {
        aic32x4_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
index 87d5ef1..6f963c5 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/i2c.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -833,7 +832,6 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
        int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
        u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
        u16 d, pll_d = 1;
-       u8 reg;
        int clk;
 
        /* select data word length */
@@ -869,14 +867,13 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
                snd_soc_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT);
                snd_soc_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV);
                /* disable PLL if it is bypassed */
-               reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
-               snd_soc_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE);
+               snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG, PLL_ENABLE, 0);
 
        } else {
                snd_soc_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV);
                /* enable PLL when it is used */
-               reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
-               snd_soc_write(codec, AIC3X_PLL_PROGA_REG, reg | PLL_ENABLE);
+               snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG,
+                                   PLL_ENABLE, PLL_ENABLE);
        }
 
        /* Route Left DAC to left channel input and
@@ -1156,7 +1153,6 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
                                enum snd_soc_bias_level level)
 {
        struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
-       u8 reg;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
@@ -1165,9 +1161,8 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
                if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY &&
                    aic3x->master) {
                        /* enable pll */
-                       reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
-                       snd_soc_write(codec, AIC3X_PLL_PROGA_REG,
-                                     reg | PLL_ENABLE);
+                       snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG,
+                                           PLL_ENABLE, PLL_ENABLE);
                }
                break;
        case SND_SOC_BIAS_STANDBY:
@@ -1176,9 +1171,8 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
                if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE &&
                    aic3x->master) {
                        /* disable pll */
-                       reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
-                       snd_soc_write(codec, AIC3X_PLL_PROGA_REG,
-                                     reg & ~PLL_ENABLE);
+                       snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG,
+                                           PLL_ENABLE, 0);
                }
                break;
        case SND_SOC_BIAS_OFF:
@@ -1249,7 +1243,7 @@ EXPORT_SYMBOL_GPL(aic3x_button_pressed);
 #define AIC3X_FORMATS  (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
                         SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops aic3x_dai_ops = {
+static const struct snd_soc_dai_ops aic3x_dai_ops = {
        .hw_params      = aic3x_hw_params,
        .digital_mute   = aic3x_mute,
        .set_sysclk     = aic3x_set_dai_sysclk,
@@ -1274,7 +1268,7 @@ static struct snd_soc_dai_driver aic3x_dai = {
        .symmetric_rates = 1,
 };
 
-static int aic3x_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int aic3x_suspend(struct snd_soc_codec *codec)
 {
        aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1295,7 +1289,6 @@ static int aic3x_resume(struct snd_soc_codec *codec)
 static int aic3x_init(struct snd_soc_codec *codec)
 {
        struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
-       int reg;
 
        snd_soc_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT);
        snd_soc_write(codec, AIC3X_RESET, SOFT_RESET);
@@ -1317,20 +1310,13 @@ static int aic3x_init(struct snd_soc_codec *codec)
        snd_soc_write(codec, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
 
        /* unmute all outputs */
-       reg = snd_soc_read(codec, LLOPM_CTRL);
-       snd_soc_write(codec, LLOPM_CTRL, reg | UNMUTE);
-       reg = snd_soc_read(codec, RLOPM_CTRL);
-       snd_soc_write(codec, RLOPM_CTRL, reg | UNMUTE);
-       reg = snd_soc_read(codec, MONOLOPM_CTRL);
-       snd_soc_write(codec, MONOLOPM_CTRL, reg | UNMUTE);
-       reg = snd_soc_read(codec, HPLOUT_CTRL);
-       snd_soc_write(codec, HPLOUT_CTRL, reg | UNMUTE);
-       reg = snd_soc_read(codec, HPROUT_CTRL);
-       snd_soc_write(codec, HPROUT_CTRL, reg | UNMUTE);
-       reg = snd_soc_read(codec, HPLCOM_CTRL);
-       snd_soc_write(codec, HPLCOM_CTRL, reg | UNMUTE);
-       reg = snd_soc_read(codec, HPRCOM_CTRL);
-       snd_soc_write(codec, HPRCOM_CTRL, reg | UNMUTE);
+       snd_soc_update_bits(codec, LLOPM_CTRL, UNMUTE, UNMUTE);
+       snd_soc_update_bits(codec, RLOPM_CTRL, UNMUTE, UNMUTE);
+       snd_soc_update_bits(codec, MONOLOPM_CTRL, UNMUTE, UNMUTE);
+       snd_soc_update_bits(codec, HPLOUT_CTRL, UNMUTE, UNMUTE);
+       snd_soc_update_bits(codec, HPROUT_CTRL, UNMUTE, UNMUTE);
+       snd_soc_update_bits(codec, HPLCOM_CTRL, UNMUTE, UNMUTE);
+       snd_soc_update_bits(codec, HPRCOM_CTRL, UNMUTE, UNMUTE);
 
        /* ADC default volume and unmute */
        snd_soc_write(codec, LADC_VOL, DEFAULT_GAIN);
@@ -1494,7 +1480,6 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
        .resume = aic3x_resume,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 /*
  * AIC3X 2 wire address can be up to 4 devices with device addresses
  * 0x18, 0x19, 0x1A, 0x1B
@@ -1561,27 +1546,22 @@ static struct i2c_driver aic3x_i2c_driver = {
        .remove = aic3x_i2c_remove,
        .id_table = aic3x_i2c_id,
 };
-#endif
 
 static int __init aic3x_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&aic3x_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n",
                       ret);
        }
-#endif
        return ret;
 }
 module_init(aic3x_modinit);
 
 static void __exit aic3x_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&aic3x_i2c_driver);
-#endif
 }
 module_exit(aic3x_exit);
 
index dc8a2b2..c7a61fb 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
@@ -1461,7 +1460,7 @@ static int dac33_soc_remove(struct snd_soc_codec *codec)
        return 0;
 }
 
-static int dac33_soc_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int dac33_soc_suspend(struct snd_soc_codec *codec)
 {
        dac33_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1499,7 +1498,7 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = {
                         SNDRV_PCM_RATE_48000)
 #define DAC33_FORMATS  (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops dac33_dai_ops = {
+static const struct snd_soc_dai_ops dac33_dai_ops = {
        .startup        = dac33_startup,
        .shutdown       = dac33_shutdown,
        .hw_params      = dac33_hw_params,
index f798247..18e7101 100644 (file)
@@ -2149,7 +2149,7 @@ static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate)
 #define TWL4030_RATES   (SNDRV_PCM_RATE_8000_48000)
 #define TWL4030_FORMATS         (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops twl4030_dai_hifi_ops = {
+static const struct snd_soc_dai_ops twl4030_dai_hifi_ops = {
        .startup        = twl4030_startup,
        .shutdown       = twl4030_shutdown,
        .hw_params      = twl4030_hw_params,
@@ -2158,7 +2158,7 @@ static struct snd_soc_dai_ops twl4030_dai_hifi_ops = {
        .set_tristate   = twl4030_set_tristate,
 };
 
-static struct snd_soc_dai_ops twl4030_dai_voice_ops = {
+static const struct snd_soc_dai_ops twl4030_dai_voice_ops = {
        .startup        = twl4030_voice_startup,
        .shutdown       = twl4030_voice_shutdown,
        .hw_params      = twl4030_voice_hw_params,
@@ -2202,7 +2202,7 @@ static struct snd_soc_dai_driver twl4030_dai[] = {
 },
 };
 
-static int twl4030_soc_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int twl4030_soc_suspend(struct snd_soc_codec *codec)
 {
        twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -2294,17 +2294,7 @@ static struct platform_driver twl4030_codec_driver = {
        },
 };
 
-static int __init twl4030_modinit(void)
-{
-       return platform_driver_register(&twl4030_codec_driver);
-}
-module_init(twl4030_modinit);
-
-static void __exit twl4030_exit(void)
-{
-       platform_driver_unregister(&twl4030_codec_driver);
-}
-module_exit(twl4030_exit);
+module_platform_driver(twl4030_codec_driver);
 
 MODULE_DESCRIPTION("ASoC TWL4030 codec driver");
 MODULE_AUTHOR("Steve Sakoman");
index 73e11f0..3376e6f 100644 (file)
@@ -1397,7 +1397,7 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
        return 0;
 }
 
-static struct snd_soc_dai_ops twl6040_dai_ops = {
+static const struct snd_soc_dai_ops twl6040_dai_ops = {
        .startup        = twl6040_startup,
        .hw_params      = twl6040_hw_params,
        .prepare        = twl6040_prepare,
@@ -1470,7 +1470,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = {
 };
 
 #ifdef CONFIG_PM
-static int twl6040_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int twl6040_suspend(struct snd_soc_codec *codec)
 {
        twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1620,17 +1620,7 @@ static struct platform_driver twl6040_codec_driver = {
        .remove = __devexit_p(twl6040_codec_remove),
 };
 
-static int __init twl6040_codec_init(void)
-{
-       return platform_driver_register(&twl6040_codec_driver);
-}
-module_init(twl6040_codec_init);
-
-static void __exit twl6040_codec_exit(void)
-{
-       platform_driver_unregister(&twl6040_codec_driver);
-}
-module_exit(twl6040_codec_exit);
+module_platform_driver(twl6040_codec_driver);
 
 MODULE_DESCRIPTION("ASoC TWL6040 codec driver");
 MODULE_AUTHOR("Misael Lopez Cruz");
index a7b8f30..8f4f469 100644 (file)
@@ -452,7 +452,7 @@ SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
 SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
 };
 
-static struct snd_soc_dai_ops uda134x_dai_ops = {
+static const struct snd_soc_dai_ops uda134x_dai_ops = {
        .startup        = uda134x_startup,
        .shutdown       = uda134x_shutdown,
        .hw_params      = uda134x_hw_params,
@@ -571,8 +571,7 @@ static int uda134x_soc_remove(struct snd_soc_codec *codec)
 }
 
 #if defined(CONFIG_PM)
-static int uda134x_soc_suspend(struct snd_soc_codec *codec,
-                                               pm_message_t state)
+static int uda134x_soc_suspend(struct snd_soc_codec *codec)
 {
        uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -625,17 +624,7 @@ static struct platform_driver uda134x_codec_driver = {
        .remove = __devexit_p(uda134x_codec_remove),
 };
 
-static int __init uda134x_codec_init(void)
-{
-       return platform_driver_register(&uda134x_codec_driver);
-}
-module_init(uda134x_codec_init);
-
-static void __exit uda134x_codec_exit(void)
-{
-       platform_driver_unregister(&uda134x_codec_driver);
-}
-module_exit(uda134x_codec_exit);
+module_platform_driver(uda134x_codec_driver);
 
 MODULE_DESCRIPTION("UDA134X ALSA soc codec driver");
 MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
index c5ca8cf..83e45d2 100644 (file)
@@ -643,21 +643,21 @@ static int uda1380_set_bias_level(struct snd_soc_codec *codec,
                       SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
                       SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
 
-static struct snd_soc_dai_ops uda1380_dai_ops = {
+static const struct snd_soc_dai_ops uda1380_dai_ops = {
        .hw_params      = uda1380_pcm_hw_params,
        .shutdown       = uda1380_pcm_shutdown,
        .trigger        = uda1380_trigger,
        .set_fmt        = uda1380_set_dai_fmt_both,
 };
 
-static struct snd_soc_dai_ops uda1380_dai_ops_playback = {
+static const struct snd_soc_dai_ops uda1380_dai_ops_playback = {
        .hw_params      = uda1380_pcm_hw_params,
        .shutdown       = uda1380_pcm_shutdown,
        .trigger        = uda1380_trigger,
        .set_fmt        = uda1380_set_dai_fmt_playback,
 };
 
-static struct snd_soc_dai_ops uda1380_dai_ops_capture = {
+static const struct snd_soc_dai_ops uda1380_dai_ops_capture = {
        .hw_params      = uda1380_pcm_hw_params,
        .shutdown       = uda1380_pcm_shutdown,
        .trigger        = uda1380_trigger,
@@ -705,7 +705,7 @@ static struct snd_soc_dai_driver uda1380_dai[] = {
 },
 };
 
-static int uda1380_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int uda1380_suspend(struct snd_soc_codec *codec)
 {
        uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -732,27 +732,21 @@ static int uda1380_probe(struct snd_soc_codec *codec)
                return -EINVAL;
 
        if (gpio_is_valid(pdata->gpio_reset)) {
-               ret = gpio_request(pdata->gpio_reset, "uda1380 reset");
+               ret = gpio_request_one(pdata->gpio_reset, GPIOF_OUT_INIT_LOW,
+                                      "uda1380 reset");
                if (ret)
                        goto err_out;
-               ret = gpio_direction_output(pdata->gpio_reset, 0);
-               if (ret)
-                       goto err_gpio_reset_conf;
        }
 
        if (gpio_is_valid(pdata->gpio_power)) {
-               ret = gpio_request(pdata->gpio_power, "uda1380 power");
-               if (ret)
-                       goto err_gpio;
-               ret = gpio_direction_output(pdata->gpio_power, 0);
+               ret = gpio_request_one(pdata->gpio_power, GPIOF_OUT_INIT_LOW,
+                                  "uda1380 power");
                if (ret)
-                       goto err_gpio_power_conf;
+                       goto err_free_gpio;
        } else {
                ret = uda1380_reset(codec);
-               if (ret) {
-                       dev_err(codec->dev, "Failed to issue reset\n");
-                       goto err_reset;
-               }
+               if (ret)
+                       goto err_free_gpio;
        }
 
        INIT_WORK(&uda1380->work, uda1380_flush_work);
@@ -776,13 +770,7 @@ static int uda1380_probe(struct snd_soc_codec *codec)
 
        return 0;
 
-err_reset:
-err_gpio_power_conf:
-       if (gpio_is_valid(pdata->gpio_power))
-               gpio_free(pdata->gpio_power);
-
-err_gpio_reset_conf:
-err_gpio:
+err_free_gpio:
        if (gpio_is_valid(pdata->gpio_reset))
                gpio_free(pdata->gpio_reset);
 err_out:
@@ -863,13 +851,13 @@ static struct i2c_driver uda1380_i2c_driver = {
 
 static int __init uda1380_modinit(void)
 {
-       int ret;
+       int ret = 0;
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&uda1380_i2c_driver);
        if (ret != 0)
                pr_err("Failed to register UDA1380 I2C driver: %d\n", ret);
 #endif
-       return 0;
+       return ret;
 }
 module_init(uda1380_modinit);
 
index a854989..44aacf9 100644 (file)
@@ -386,7 +386,7 @@ static int wl1273_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_dai_ops wl1273_dai_ops = {
+static const struct snd_soc_dai_ops wl1273_dai_ops = {
        .startup        = wl1273_startup,
        .hw_params      = wl1273_hw_params,
 };
@@ -510,17 +510,7 @@ static struct platform_driver wl1273_platform_driver = {
        .remove         = __devexit_p(wl1273_platform_remove),
 };
 
-static int __init wl1273_init(void)
-{
-       return platform_driver_register(&wl1273_platform_driver);
-}
-module_init(wl1273_init);
-
-static void __exit wl1273_exit(void)
-{
-       platform_driver_unregister(&wl1273_platform_driver);
-}
-module_exit(wl1273_exit);
+module_platform_driver(wl1273_platform_driver);
 
 MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>");
 MODULE_DESCRIPTION("ASoC WL1273 codec driver");
index cd0ec0f..aefb4f8 100644 (file)
@@ -116,7 +116,7 @@ static int __devinit wm1250_ev1_pdata(struct i2c_client *i2c)
        if (!pdata)
                return 0;
 
-       wm1250 = kzalloc(sizeof(*wm1250), GFP_KERNEL);
+       wm1250 = devm_kzalloc(&i2c->dev, sizeof(*wm1250), GFP_KERNEL);
        if (!wm1250) {
                dev_err(&i2c->dev, "Unable to allocate private data\n");
                ret = -ENOMEM;
@@ -134,15 +134,13 @@ static int __devinit wm1250_ev1_pdata(struct i2c_client *i2c)
        ret = gpio_request_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to get GPIOs: %d\n", ret);
-               goto err_alloc;
+               goto err;
        }
 
        dev_set_drvdata(&i2c->dev, wm1250);
 
        return ret;
 
-err_alloc:
-       kfree(wm1250);
 err:
        return ret;
 }
@@ -151,10 +149,8 @@ static void wm1250_ev1_free(struct i2c_client *i2c)
 {
        struct wm1250_priv *wm1250 = dev_get_drvdata(&i2c->dev);
 
-       if (wm1250) {
+       if (wm1250)
                gpio_free_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
-               kfree(wm1250);
-       }
 }
 
 static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
index a3b9cbb..c288090 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -52,6 +52,7 @@ enum wm2000_anc_mode {
 
 struct wm2000_priv {
        struct i2c_client *i2c;
+       struct regmap *regmap;
 
        enum wm2000_anc_mode anc_mode;
 
@@ -66,59 +67,24 @@ struct wm2000_priv {
        char *anc_download;
 };
 
-static struct i2c_client *wm2000_i2c;
-
 static int wm2000_write(struct i2c_client *i2c, unsigned int reg,
                        unsigned int value)
 {
-       u8 data[3];
-       int ret;
-
-       data[0] = (reg >> 8) & 0xff;
-       data[1] = reg & 0xff;
-       data[2] = value & 0xff;
-
-       dev_vdbg(&i2c->dev, "write %x = %x\n", reg, value);
-
-       ret = i2c_master_send(i2c, data, 3);
-       if (ret == 3)
-               return 0;
-       if (ret < 0)
-               return ret;
-       else
-               return -EIO;
+       struct wm2000_priv *wm2000 = i2c_get_clientdata(i2c);
+       return regmap_write(wm2000->regmap, reg, value);
 }
 
 static unsigned int wm2000_read(struct i2c_client *i2c, unsigned int r)
 {
-       struct i2c_msg xfer[2];
-       u8 reg[2];
-       u8 data;
+       struct wm2000_priv *wm2000 = i2c_get_clientdata(i2c);
+       unsigned int val;
        int ret;
 
-       /* Write register */
-       reg[0] = (r >> 8) & 0xff;
-       reg[1] = r & 0xff;
-       xfer[0].addr = i2c->addr;
-       xfer[0].flags = 0;
-       xfer[0].len = sizeof(reg);
-       xfer[0].buf = &reg[0];
-
-       /* Read data */
-       xfer[1].addr = i2c->addr;
-       xfer[1].flags = I2C_M_RD;
-       xfer[1].len = 1;
-       xfer[1].buf = &data;
-
-       ret = i2c_transfer(i2c->adapter, xfer, 2);
-       if (ret != 2) {
-               dev_err(&i2c->dev, "i2c_transfer() returned %d\n", ret);
-               return 0;
-       }
-
-       dev_vdbg(&i2c->dev, "read %x from %x\n", data, r);
+       ret = regmap_read(wm2000->regmap, r, &val);
+       if (ret < 0)
+               return -1;
 
-       return data;
+       return val;
 }
 
 static void wm2000_reset(struct wm2000_priv *wm2000)
@@ -612,7 +578,8 @@ static int wm2000_anc_set_mode(struct wm2000_priv *wm2000)
 static int wm2000_anc_mode_get(struct snd_kcontrol *kcontrol,
                               struct snd_ctl_elem_value *ucontrol)
 {
-       struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev);
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
 
        ucontrol->value.enumerated.item[0] = wm2000->anc_active;
 
@@ -622,7 +589,8 @@ static int wm2000_anc_mode_get(struct snd_kcontrol *kcontrol,
 static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol,
                               struct snd_ctl_elem_value *ucontrol)
 {
-       struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev);
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
        int anc_active = ucontrol->value.enumerated.item[0];
 
        if (anc_active > 1)
@@ -636,7 +604,8 @@ static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol,
 static int wm2000_speaker_get(struct snd_kcontrol *kcontrol,
                              struct snd_ctl_elem_value *ucontrol)
 {
-       struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev);
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
 
        ucontrol->value.enumerated.item[0] = wm2000->spk_ena;
 
@@ -646,7 +615,8 @@ static int wm2000_speaker_get(struct snd_kcontrol *kcontrol,
 static int wm2000_speaker_put(struct snd_kcontrol *kcontrol,
                              struct snd_ctl_elem_value *ucontrol)
 {
-       struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev);
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
        int val = ucontrol->value.enumerated.item[0];
 
        if (val > 1)
@@ -669,7 +639,8 @@ static const struct snd_kcontrol_new wm2000_controls[] = {
 static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w,
                                  struct snd_kcontrol *kcontrol, int event)
 {
-       struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev);
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
 
        if (SND_SOC_DAPM_EVENT_ON(event))
                wm2000->anc_eng_ena = 1;
@@ -682,11 +653,11 @@ static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w,
 
 static const struct snd_soc_dapm_widget wm2000_dapm_widgets[] = {
 /* Externally visible pins */
-SND_SOC_DAPM_OUTPUT("WM2000 SPKN"),
-SND_SOC_DAPM_OUTPUT("WM2000 SPKP"),
+SND_SOC_DAPM_OUTPUT("SPKN"),
+SND_SOC_DAPM_OUTPUT("SPKP"),
 
-SND_SOC_DAPM_INPUT("WM2000 LINN"),
-SND_SOC_DAPM_INPUT("WM2000 LINP"),
+SND_SOC_DAPM_INPUT("LINN"),
+SND_SOC_DAPM_INPUT("LINP"),
 
 SND_SOC_DAPM_PGA_E("ANC Engine", SND_SOC_NOPM, 0, 0, NULL, 0,
                   wm2000_anc_power_event,
@@ -694,37 +665,67 @@ SND_SOC_DAPM_PGA_E("ANC Engine", SND_SOC_NOPM, 0, 0, NULL, 0,
 };
 
 /* Target, Path, Source */
-static const struct snd_soc_dapm_route audio_map[] = {
-       { "WM2000 SPKN", NULL, "ANC Engine" },
-       { "WM2000 SPKP", NULL, "ANC Engine" },
-       { "ANC Engine", NULL, "WM2000 LINN" },
-       { "ANC Engine", NULL, "WM2000 LINP" },
+static const struct snd_soc_dapm_route wm2000_audio_map[] = {
+       { "SPKN", NULL, "ANC Engine" },
+       { "SPKP", NULL, "ANC Engine" },
+       { "ANC Engine", NULL, "LINN" },
+       { "ANC Engine", NULL, "LINP" },
 };
 
-/* Called from the machine driver */
-int wm2000_add_controls(struct snd_soc_codec *codec)
+#ifdef CONFIG_PM
+static int wm2000_suspend(struct snd_soc_codec *codec)
 {
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-       int ret;
+       struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
 
-       if (!wm2000_i2c) {
-               pr_err("WM2000 not yet probed\n");
-               return -ENODEV;
-       }
+       return wm2000_anc_transition(wm2000, ANC_OFF);
+}
 
-       ret = snd_soc_dapm_new_controls(dapm, wm2000_dapm_widgets,
-                                       ARRAY_SIZE(wm2000_dapm_widgets));
-       if (ret < 0)
-               return ret;
+static int wm2000_resume(struct snd_soc_codec *codec)
+{
+       struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
 
-       ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-       if (ret < 0)
-               return ret;
+       return wm2000_anc_set_mode(wm2000);
+}
+#else
+#define wm2000_suspend NULL
+#define wm2000_resume NULL
+#endif
+
+static const struct regmap_config wm2000_regmap = {
+       .reg_bits = 8,
+       .val_bits = 8,
+};
+
+static int wm2000_probe(struct snd_soc_codec *codec)
+{
+       struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
+
+       /* This will trigger a transition to standby mode by default */
+       wm2000_anc_set_mode(wm2000);
+
+       return 0;
+}
+
+static int wm2000_remove(struct snd_soc_codec *codec)
+{
+       struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
 
-       return snd_soc_add_controls(codec, wm2000_controls,
-                       ARRAY_SIZE(wm2000_controls));
+       return wm2000_anc_transition(wm2000, ANC_OFF);
 }
-EXPORT_SYMBOL_GPL(wm2000_add_controls);
+
+static struct snd_soc_codec_driver soc_codec_dev_wm2000 = {
+       .probe = wm2000_probe,
+       .remove = wm2000_remove,
+       .suspend = wm2000_suspend,
+       .resume = wm2000_resume,
+
+       .dapm_widgets = wm2000_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm2000_dapm_widgets),
+       .dapm_routes = wm2000_audio_map,
+       .num_dapm_routes = ARRAY_SIZE(wm2000_audio_map),
+       .controls = wm2000_controls,
+       .num_controls = ARRAY_SIZE(wm2000_controls),
+};
 
 static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *i2c_id)
@@ -736,17 +737,23 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
        int reg, ret;
        u16 id;
 
-       if (wm2000_i2c) {
-               dev_err(&i2c->dev, "Another WM2000 is already registered\n");
-               return -EINVAL;
-       }
-
-       wm2000 = kzalloc(sizeof(struct wm2000_priv), GFP_KERNEL);
+       wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv),
+                             GFP_KERNEL);
        if (wm2000 == NULL) {
                dev_err(&i2c->dev, "Unable to allocate private data\n");
                return -ENOMEM;
        }
 
+       dev_set_drvdata(&i2c->dev, wm2000);
+
+       wm2000->regmap = regmap_init_i2c(i2c, &wm2000_regmap);
+       if (IS_ERR(wm2000->regmap)) {
+               ret = PTR_ERR(wm2000->regmap);
+               dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               goto err;
+       }
+
        /* Verify that this is a WM2000 */
        reg = wm2000_read(i2c, WM2000_REG_ID1);
        id = reg << 8;
@@ -756,7 +763,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
        if (id != 0x2000) {
                dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id);
                ret = -ENODEV;
-               goto err;
+               goto err_regmap;
        }
 
        reg = wm2000_read(i2c, WM2000_REG_REVISON);
@@ -775,12 +782,14 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
        ret = request_firmware(&fw, filename, &i2c->dev);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret);
-               goto err;
+               goto err_regmap;
        }
 
        /* Pre-cook the concatenation of the register address onto the image */
        wm2000->anc_download_size = fw->size + 2;
-       wm2000->anc_download = kmalloc(wm2000->anc_download_size, GFP_KERNEL);
+       wm2000->anc_download = devm_kzalloc(&i2c->dev,
+                                           wm2000->anc_download_size,
+                                           GFP_KERNEL);
        if (wm2000->anc_download == NULL) {
                dev_err(&i2c->dev, "Out of memory\n");
                ret = -ENOMEM;
@@ -793,7 +802,6 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
 
        release_firmware(fw);
 
-       dev_set_drvdata(&i2c->dev, wm2000);
        wm2000->anc_eng_ena = 1;
        wm2000->anc_active = 1;
        wm2000->spk_ena = 1;
@@ -801,17 +809,18 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
 
        wm2000_reset(wm2000);
 
-       /* This will trigger a transition to standby mode by default */
-       wm2000_anc_set_mode(wm2000);    
-
-       wm2000_i2c = i2c;
+       ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000,
+                                    NULL, 0);
+       if (ret != 0)
+               goto err_fw;
 
        return 0;
 
 err_fw:
        release_firmware(fw);
+err_regmap:
+       regmap_exit(wm2000->regmap);
 err:
-       kfree(wm2000);
        return ret;
 }
 
@@ -819,42 +828,12 @@ static __devexit int wm2000_i2c_remove(struct i2c_client *i2c)
 {
        struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
 
-       wm2000_anc_transition(wm2000, ANC_OFF);
-
-       wm2000_i2c = NULL;
-       kfree(wm2000->anc_download);
-       kfree(wm2000);
+       snd_soc_unregister_codec(&i2c->dev);
+       regmap_exit(wm2000->regmap);
 
        return 0;
 }
 
-static void wm2000_i2c_shutdown(struct i2c_client *i2c)
-{
-       struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
-
-       wm2000_anc_transition(wm2000, ANC_OFF);
-}
-
-#ifdef CONFIG_PM
-static int wm2000_i2c_suspend(struct device *dev)
-{
-       struct i2c_client *i2c = to_i2c_client(dev);
-       struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
-
-       return wm2000_anc_transition(wm2000, ANC_OFF);
-}
-
-static int wm2000_i2c_resume(struct device *dev)
-{
-       struct i2c_client *i2c = to_i2c_client(dev);
-       struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
-
-       return wm2000_anc_set_mode(wm2000);
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(wm2000_pm, wm2000_i2c_suspend, wm2000_i2c_resume);
-
 static const struct i2c_device_id wm2000_i2c_id[] = {
        { "wm2000", 0 },
        { }
@@ -865,11 +844,9 @@ static struct i2c_driver wm2000_i2c_driver = {
        .driver = {
                .name = "wm2000",
                .owner = THIS_MODULE,
-               .pm = &wm2000_pm,
        },
        .probe = wm2000_i2c_probe,
        .remove = __devexit_p(wm2000_i2c_remove),
-       .shutdown = wm2000_i2c_shutdown,
        .id_table = wm2000_i2c_id,
 };
 
index 0b6f056..abcd82a 100644 (file)
@@ -9,13 +9,6 @@
 #ifndef _WM2000_H
 #define _WM2000_H
 
-struct wm2000_setup_data {
-       unsigned short i2c_address;
-       int mclk_div;   /* Set to a non-zero value if MCLK_DIV_2 required */
-};
-
-extern int wm2000_add_controls(struct snd_soc_codec *codec);
-
 #define WM2000_REG_SYS_START       0x8000
 #define WM2000_REG_SPEECH_CLARITY   0x8fef
 #define WM2000_REG_SYS_WATCHDOG     0x8ff6
index e9ce81a..9a18fae 100644 (file)
@@ -13,7 +13,7 @@
 
 #include "wm5100.h"
 
-int wm5100_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+bool wm5100_volatile_register(struct device *dev, unsigned int reg)
 {
        switch (reg) {
        case WM5100_SOFTWARE_RESET:
@@ -36,7 +36,7 @@ int wm5100_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
        }
 }
 
-int wm5100_readable_register(struct snd_soc_codec *codec, unsigned int reg)
+bool wm5100_readable_register(struct device *dev, unsigned int reg)
 {
        switch (reg) {
        case WM5100_SOFTWARE_RESET:
@@ -85,6 +85,7 @@ int wm5100_readable_register(struct snd_soc_codec *codec, unsigned int reg)
        case WM5100_MIC_DETECT_1:
        case WM5100_MIC_DETECT_2:
        case WM5100_MIC_DETECT_3:
+       case WM5100_MISC_CONTROL:
        case WM5100_INPUT_ENABLES:
        case WM5100_INPUT_ENABLES_STATUS:
        case WM5100_IN1L_CONTROL:
@@ -696,836 +697,668 @@ int wm5100_readable_register(struct snd_soc_codec *codec, unsigned int reg)
        case WM5100_HPLPF3_2:
        case WM5100_HPLPF4_1:
        case WM5100_HPLPF4_2:
-       case WM5100_DSP1_DM_0:
-       case WM5100_DSP1_DM_1:
-       case WM5100_DSP1_DM_2:
-       case WM5100_DSP1_DM_3:
-       case WM5100_DSP1_DM_508:
-       case WM5100_DSP1_DM_509:
-       case WM5100_DSP1_DM_510:
-       case WM5100_DSP1_DM_511:
-       case WM5100_DSP1_PM_0:
-       case WM5100_DSP1_PM_1:
-       case WM5100_DSP1_PM_2:
-       case WM5100_DSP1_PM_3:
-       case WM5100_DSP1_PM_4:
-       case WM5100_DSP1_PM_5:
-       case WM5100_DSP1_PM_1530:
-       case WM5100_DSP1_PM_1531:
-       case WM5100_DSP1_PM_1532:
-       case WM5100_DSP1_PM_1533:
-       case WM5100_DSP1_PM_1534:
-       case WM5100_DSP1_PM_1535:
-       case WM5100_DSP1_ZM_0:
-       case WM5100_DSP1_ZM_1:
-       case WM5100_DSP1_ZM_2:
-       case WM5100_DSP1_ZM_3:
-       case WM5100_DSP1_ZM_2044:
-       case WM5100_DSP1_ZM_2045:
-       case WM5100_DSP1_ZM_2046:
-       case WM5100_DSP1_ZM_2047:
-       case WM5100_DSP2_DM_0:
-       case WM5100_DSP2_DM_1:
-       case WM5100_DSP2_DM_2:
-       case WM5100_DSP2_DM_3:
-       case WM5100_DSP2_DM_508:
-       case WM5100_DSP2_DM_509:
-       case WM5100_DSP2_DM_510:
-       case WM5100_DSP2_DM_511:
-       case WM5100_DSP2_PM_0:
-       case WM5100_DSP2_PM_1:
-       case WM5100_DSP2_PM_2:
-       case WM5100_DSP2_PM_3:
-       case WM5100_DSP2_PM_4:
-       case WM5100_DSP2_PM_5:
-       case WM5100_DSP2_PM_1530:
-       case WM5100_DSP2_PM_1531:
-       case WM5100_DSP2_PM_1532:
-       case WM5100_DSP2_PM_1533:
-       case WM5100_DSP2_PM_1534:
-       case WM5100_DSP2_PM_1535:
-       case WM5100_DSP2_ZM_0:
-       case WM5100_DSP2_ZM_1:
-       case WM5100_DSP2_ZM_2:
-       case WM5100_DSP2_ZM_3:
-       case WM5100_DSP2_ZM_2044:
-       case WM5100_DSP2_ZM_2045:
-       case WM5100_DSP2_ZM_2046:
-       case WM5100_DSP2_ZM_2047:
-       case WM5100_DSP3_DM_0:
-       case WM5100_DSP3_DM_1:
-       case WM5100_DSP3_DM_2:
-       case WM5100_DSP3_DM_3:
-       case WM5100_DSP3_DM_508:
-       case WM5100_DSP3_DM_509:
-       case WM5100_DSP3_DM_510:
-       case WM5100_DSP3_DM_511:
-       case WM5100_DSP3_PM_0:
-       case WM5100_DSP3_PM_1:
-       case WM5100_DSP3_PM_2:
-       case WM5100_DSP3_PM_3:
-       case WM5100_DSP3_PM_4:
-       case WM5100_DSP3_PM_5:
-       case WM5100_DSP3_PM_1530:
-       case WM5100_DSP3_PM_1531:
-       case WM5100_DSP3_PM_1532:
-       case WM5100_DSP3_PM_1533:
-       case WM5100_DSP3_PM_1534:
-       case WM5100_DSP3_PM_1535:
-       case WM5100_DSP3_ZM_0:
-       case WM5100_DSP3_ZM_1:
-       case WM5100_DSP3_ZM_2:
-       case WM5100_DSP3_ZM_3:
-       case WM5100_DSP3_ZM_2044:
-       case WM5100_DSP3_ZM_2045:
-       case WM5100_DSP3_ZM_2046:
-       case WM5100_DSP3_ZM_2047:
                return 1;
        default:
                return 0;
        }
 }
 
-u16 wm5100_reg_defaults[WM5100_MAX_REGISTER + 1] = {
-       [0x0000] = 0x0000,     /* R0     - software reset */
-       [0x0001] = 0x0000,     /* R1     - Device Revision */
-       [0x0010] = 0x0801,     /* R16    - Ctrl IF 1 */
-       [0x0020] = 0x0000,     /* R32    - Tone Generator 1 */
-       [0x0030] = 0x0000,     /* R48    - PWM Drive 1 */
-       [0x0031] = 0x0100,     /* R49    - PWM Drive 2 */
-       [0x0032] = 0x0100,     /* R50    - PWM Drive 3 */
-       [0x0100] = 0x0002,     /* R256   - Clocking 1 */
-       [0x0101] = 0x0000,     /* R257   - Clocking 3 */
-       [0x0102] = 0x0011,     /* R258   - Clocking 4 */
-       [0x0103] = 0x0011,     /* R259   - Clocking 5 */
-       [0x0104] = 0x0011,     /* R260   - Clocking 6 */
-       [0x0107] = 0x0000,     /* R263   - Clocking 7 */
-       [0x0108] = 0x0000,     /* R264   - Clocking 8 */
-       [0x0120] = 0x0000,     /* R288   - ASRC_ENABLE */
-       [0x0121] = 0x0000,     /* R289   - ASRC_STATUS */
-       [0x0122] = 0x0000,     /* R290   - ASRC_RATE1 */
-       [0x0141] = 0x8000,     /* R321   - ISRC 1 CTRL 1 */
-       [0x0142] = 0x0000,     /* R322   - ISRC 1 CTRL 2 */
-       [0x0143] = 0x8000,     /* R323   - ISRC 2 CTRL1 */
-       [0x0144] = 0x0000,     /* R324   - ISRC 2 CTRL 2 */
-       [0x0182] = 0x0000,     /* R386   - FLL1 Control 1 */
-       [0x0183] = 0x0000,     /* R387   - FLL1 Control 2 */
-       [0x0184] = 0x0000,     /* R388   - FLL1 Control 3 */
-       [0x0186] = 0x0177,     /* R390   - FLL1 Control 5 */
-       [0x0187] = 0x0001,     /* R391   - FLL1 Control 6 */
-       [0x0188] = 0x0000,     /* R392   - FLL1 EFS 1 */
-       [0x01A2] = 0x0000,     /* R418   - FLL2 Control 1 */
-       [0x01A3] = 0x0000,     /* R419   - FLL2 Control 2 */
-       [0x01A4] = 0x0000,     /* R420   - FLL2 Control 3 */
-       [0x01A6] = 0x0177,     /* R422   - FLL2 Control 5 */
-       [0x01A7] = 0x0001,     /* R423   - FLL2 Control 6 */
-       [0x01A8] = 0x0000,     /* R424   - FLL2 EFS 1 */
-       [0x0200] = 0x0020,     /* R512   - Mic Charge Pump 1 */
-       [0x0201] = 0xB084,     /* R513   - Mic Charge Pump 2 */
-       [0x0202] = 0xBBDE,     /* R514   - HP Charge Pump 1 */
-       [0x0211] = 0x20D4,     /* R529   - LDO1 Control */
-       [0x0215] = 0x0062,     /* R533   - Mic Bias Ctrl 1 */
-       [0x0216] = 0x0062,     /* R534   - Mic Bias Ctrl 2 */
-       [0x0217] = 0x0062,     /* R535   - Mic Bias Ctrl 3 */
-       [0x0280] = 0x0004,     /* R640   - Accessory Detect Mode 1 */
-       [0x0288] = 0x0020,     /* R648   - Headphone Detect 1 */
-       [0x0289] = 0x0000,     /* R649   - Headphone Detect 2 */
-       [0x0290] = 0x1100,     /* R656   - Mic Detect 1 */
-       [0x0291] = 0x009F,     /* R657   - Mic Detect 2 */
-       [0x0292] = 0x0000,     /* R658   - Mic Detect 3 */
-       [0x0301] = 0x0000,     /* R769   - Input Enables */
-       [0x0302] = 0x0000,     /* R770   - Input Enables Status */
-       [0x0310] = 0x2280,     /* R784   - Status */
-       [0x0311] = 0x0080,     /* R785   - IN1R Control */
-       [0x0312] = 0x2280,     /* R786   - IN2L Control */
-       [0x0313] = 0x0080,     /* R787   - IN2R Control */
-       [0x0314] = 0x2280,     /* R788   - IN3L Control */
-       [0x0315] = 0x0080,     /* R789   - IN3R Control */
-       [0x0316] = 0x2280,     /* R790   - IN4L Control */
-       [0x0317] = 0x0080,     /* R791   - IN4R Control */
-       [0x0318] = 0x0000,     /* R792   - RXANC_SRC */
-       [0x0319] = 0x0022,     /* R793   - Input Volume Ramp */
-       [0x0320] = 0x0180,     /* R800   - ADC Digital Volume 1L */
-       [0x0321] = 0x0180,     /* R801   - ADC Digital Volume 1R */
-       [0x0322] = 0x0180,     /* R802   - ADC Digital Volume 2L */
-       [0x0323] = 0x0180,     /* R803   - ADC Digital Volume 2R */
-       [0x0324] = 0x0180,     /* R804   - ADC Digital Volume 3L */
-       [0x0325] = 0x0180,     /* R805   - ADC Digital Volume 3R */
-       [0x0326] = 0x0180,     /* R806   - ADC Digital Volume 4L */
-       [0x0327] = 0x0180,     /* R807   - ADC Digital Volume 4R */
-       [0x0401] = 0x0000,     /* R1025  - Output Enables 2 */
-       [0x0402] = 0x0000,     /* R1026  - Output Status 1 */
-       [0x0403] = 0x0000,     /* R1027  - Output Status 2 */
-       [0x0408] = 0x0000,     /* R1032  - Channel Enables 1 */
-       [0x0410] = 0x0080,     /* R1040  - Out Volume 1L */
-       [0x0411] = 0x0080,     /* R1041  - Out Volume 1R */
-       [0x0412] = 0x0080,     /* R1042  - DAC Volume Limit 1L */
-       [0x0413] = 0x0080,     /* R1043  - DAC Volume Limit 1R */
-       [0x0414] = 0x0080,     /* R1044  - Out Volume 2L */
-       [0x0415] = 0x0080,     /* R1045  - Out Volume 2R */
-       [0x0416] = 0x0080,     /* R1046  - DAC Volume Limit 2L */
-       [0x0417] = 0x0080,     /* R1047  - DAC Volume Limit 2R */
-       [0x0418] = 0x0080,     /* R1048  - Out Volume 3L */
-       [0x0419] = 0x0080,     /* R1049  - Out Volume 3R */
-       [0x041A] = 0x0080,     /* R1050  - DAC Volume Limit 3L */
-       [0x041B] = 0x0080,     /* R1051  - DAC Volume Limit 3R */
-       [0x041C] = 0x0080,     /* R1052  - Out Volume 4L */
-       [0x041D] = 0x0080,     /* R1053  - Out Volume 4R */
-       [0x041E] = 0x0080,     /* R1054  - DAC Volume Limit 5L */
-       [0x041F] = 0x0080,     /* R1055  - DAC Volume Limit 5R */
-       [0x0420] = 0x0080,     /* R1056  - DAC Volume Limit 6L */
-       [0x0421] = 0x0080,     /* R1057  - DAC Volume Limit 6R */
-       [0x0440] = 0x0000,     /* R1088  - DAC AEC Control 1 */
-       [0x0441] = 0x0022,     /* R1089  - Output Volume Ramp */
-       [0x0480] = 0x0180,     /* R1152  - DAC Digital Volume 1L */
-       [0x0481] = 0x0180,     /* R1153  - DAC Digital Volume 1R */
-       [0x0482] = 0x0180,     /* R1154  - DAC Digital Volume 2L */
-       [0x0483] = 0x0180,     /* R1155  - DAC Digital Volume 2R */
-       [0x0484] = 0x0180,     /* R1156  - DAC Digital Volume 3L */
-       [0x0485] = 0x0180,     /* R1157  - DAC Digital Volume 3R */
-       [0x0486] = 0x0180,     /* R1158  - DAC Digital Volume 4L */
-       [0x0487] = 0x0180,     /* R1159  - DAC Digital Volume 4R */
-       [0x0488] = 0x0180,     /* R1160  - DAC Digital Volume 5L */
-       [0x0489] = 0x0180,     /* R1161  - DAC Digital Volume 5R */
-       [0x048A] = 0x0180,     /* R1162  - DAC Digital Volume 6L */
-       [0x048B] = 0x0180,     /* R1163  - DAC Digital Volume 6R */
-       [0x04C0] = 0x0069,     /* R1216  - PDM SPK1 CTRL 1 */
-       [0x04C1] = 0x0000,     /* R1217  - PDM SPK1 CTRL 2 */
-       [0x04C2] = 0x0069,     /* R1218  - PDM SPK2 CTRL 1 */
-       [0x04C3] = 0x0000,     /* R1219  - PDM SPK2 CTRL 2 */
-       [0x0500] = 0x000C,     /* R1280  - Audio IF 1_1 */
-       [0x0501] = 0x0008,     /* R1281  - Audio IF 1_2 */
-       [0x0502] = 0x0000,     /* R1282  - Audio IF 1_3 */
-       [0x0503] = 0x0000,     /* R1283  - Audio IF 1_4 */
-       [0x0504] = 0x0000,     /* R1284  - Audio IF 1_5 */
-       [0x0505] = 0x0300,     /* R1285  - Audio IF 1_6 */
-       [0x0506] = 0x0300,     /* R1286  - Audio IF 1_7 */
-       [0x0507] = 0x1820,     /* R1287  - Audio IF 1_8 */
-       [0x0508] = 0x1820,     /* R1288  - Audio IF 1_9 */
-       [0x0509] = 0x0000,     /* R1289  - Audio IF 1_10 */
-       [0x050A] = 0x0001,     /* R1290  - Audio IF 1_11 */
-       [0x050B] = 0x0002,     /* R1291  - Audio IF 1_12 */
-       [0x050C] = 0x0003,     /* R1292  - Audio IF 1_13 */
-       [0x050D] = 0x0004,     /* R1293  - Audio IF 1_14 */
-       [0x050E] = 0x0005,     /* R1294  - Audio IF 1_15 */
-       [0x050F] = 0x0006,     /* R1295  - Audio IF 1_16 */
-       [0x0510] = 0x0007,     /* R1296  - Audio IF 1_17 */
-       [0x0511] = 0x0000,     /* R1297  - Audio IF 1_18 */
-       [0x0512] = 0x0001,     /* R1298  - Audio IF 1_19 */
-       [0x0513] = 0x0002,     /* R1299  - Audio IF 1_20 */
-       [0x0514] = 0x0003,     /* R1300  - Audio IF 1_21 */
-       [0x0515] = 0x0004,     /* R1301  - Audio IF 1_22 */
-       [0x0516] = 0x0005,     /* R1302  - Audio IF 1_23 */
-       [0x0517] = 0x0006,     /* R1303  - Audio IF 1_24 */
-       [0x0518] = 0x0007,     /* R1304  - Audio IF 1_25 */
-       [0x0519] = 0x0000,     /* R1305  - Audio IF 1_26 */
-       [0x051A] = 0x0000,     /* R1306  - Audio IF 1_27 */
-       [0x0540] = 0x000C,     /* R1344  - Audio IF 2_1 */
-       [0x0541] = 0x0008,     /* R1345  - Audio IF 2_2 */
-       [0x0542] = 0x0000,     /* R1346  - Audio IF 2_3 */
-       [0x0543] = 0x0000,     /* R1347  - Audio IF 2_4 */
-       [0x0544] = 0x0000,     /* R1348  - Audio IF 2_5 */
-       [0x0545] = 0x0300,     /* R1349  - Audio IF 2_6 */
-       [0x0546] = 0x0300,     /* R1350  - Audio IF 2_7 */
-       [0x0547] = 0x1820,     /* R1351  - Audio IF 2_8 */
-       [0x0548] = 0x1820,     /* R1352  - Audio IF 2_9 */
-       [0x0549] = 0x0000,     /* R1353  - Audio IF 2_10 */
-       [0x054A] = 0x0001,     /* R1354  - Audio IF 2_11 */
-       [0x0551] = 0x0000,     /* R1361  - Audio IF 2_18 */
-       [0x0552] = 0x0001,     /* R1362  - Audio IF 2_19 */
-       [0x0559] = 0x0000,     /* R1369  - Audio IF 2_26 */
-       [0x055A] = 0x0000,     /* R1370  - Audio IF 2_27 */
-       [0x0580] = 0x000C,     /* R1408  - Audio IF 3_1 */
-       [0x0581] = 0x0008,     /* R1409  - Audio IF 3_2 */
-       [0x0582] = 0x0000,     /* R1410  - Audio IF 3_3 */
-       [0x0583] = 0x0000,     /* R1411  - Audio IF 3_4 */
-       [0x0584] = 0x0000,     /* R1412  - Audio IF 3_5 */
-       [0x0585] = 0x0300,     /* R1413  - Audio IF 3_6 */
-       [0x0586] = 0x0300,     /* R1414  - Audio IF 3_7 */
-       [0x0587] = 0x1820,     /* R1415  - Audio IF 3_8 */
-       [0x0588] = 0x1820,     /* R1416  - Audio IF 3_9 */
-       [0x0589] = 0x0000,     /* R1417  - Audio IF 3_10 */
-       [0x058A] = 0x0001,     /* R1418  - Audio IF 3_11 */
-       [0x0591] = 0x0000,     /* R1425  - Audio IF 3_18 */
-       [0x0592] = 0x0001,     /* R1426  - Audio IF 3_19 */
-       [0x0599] = 0x0000,     /* R1433  - Audio IF 3_26 */
-       [0x059A] = 0x0000,     /* R1434  - Audio IF 3_27 */
-       [0x0640] = 0x0000,     /* R1600  - PWM1MIX Input 1 Source */
-       [0x0641] = 0x0080,     /* R1601  - PWM1MIX Input 1 Volume */
-       [0x0642] = 0x0000,     /* R1602  - PWM1MIX Input 2 Source */
-       [0x0643] = 0x0080,     /* R1603  - PWM1MIX Input 2 Volume */
-       [0x0644] = 0x0000,     /* R1604  - PWM1MIX Input 3 Source */
-       [0x0645] = 0x0080,     /* R1605  - PWM1MIX Input 3 Volume */
-       [0x0646] = 0x0000,     /* R1606  - PWM1MIX Input 4 Source */
-       [0x0647] = 0x0080,     /* R1607  - PWM1MIX Input 4 Volume */
-       [0x0648] = 0x0000,     /* R1608  - PWM2MIX Input 1 Source */
-       [0x0649] = 0x0080,     /* R1609  - PWM2MIX Input 1 Volume */
-       [0x064A] = 0x0000,     /* R1610  - PWM2MIX Input 2 Source */
-       [0x064B] = 0x0080,     /* R1611  - PWM2MIX Input 2 Volume */
-       [0x064C] = 0x0000,     /* R1612  - PWM2MIX Input 3 Source */
-       [0x064D] = 0x0080,     /* R1613  - PWM2MIX Input 3 Volume */
-       [0x064E] = 0x0000,     /* R1614  - PWM2MIX Input 4 Source */
-       [0x064F] = 0x0080,     /* R1615  - PWM2MIX Input 4 Volume */
-       [0x0680] = 0x0000,     /* R1664  - OUT1LMIX Input 1 Source */
-       [0x0681] = 0x0080,     /* R1665  - OUT1LMIX Input 1 Volume */
-       [0x0682] = 0x0000,     /* R1666  - OUT1LMIX Input 2 Source */
-       [0x0683] = 0x0080,     /* R1667  - OUT1LMIX Input 2 Volume */
-       [0x0684] = 0x0000,     /* R1668  - OUT1LMIX Input 3 Source */
-       [0x0685] = 0x0080,     /* R1669  - OUT1LMIX Input 3 Volume */
-       [0x0686] = 0x0000,     /* R1670  - OUT1LMIX Input 4 Source */
-       [0x0687] = 0x0080,     /* R1671  - OUT1LMIX Input 4 Volume */
-       [0x0688] = 0x0000,     /* R1672  - OUT1RMIX Input 1 Source */
-       [0x0689] = 0x0080,     /* R1673  - OUT1RMIX Input 1 Volume */
-       [0x068A] = 0x0000,     /* R1674  - OUT1RMIX Input 2 Source */
-       [0x068B] = 0x0080,     /* R1675  - OUT1RMIX Input 2 Volume */
-       [0x068C] = 0x0000,     /* R1676  - OUT1RMIX Input 3 Source */
-       [0x068D] = 0x0080,     /* R1677  - OUT1RMIX Input 3 Volume */
-       [0x068E] = 0x0000,     /* R1678  - OUT1RMIX Input 4 Source */
-       [0x068F] = 0x0080,     /* R1679  - OUT1RMIX Input 4 Volume */
-       [0x0690] = 0x0000,     /* R1680  - OUT2LMIX Input 1 Source */
-       [0x0691] = 0x0080,     /* R1681  - OUT2LMIX Input 1 Volume */
-       [0x0692] = 0x0000,     /* R1682  - OUT2LMIX Input 2 Source */
-       [0x0693] = 0x0080,     /* R1683  - OUT2LMIX Input 2 Volume */
-       [0x0694] = 0x0000,     /* R1684  - OUT2LMIX Input 3 Source */
-       [0x0695] = 0x0080,     /* R1685  - OUT2LMIX Input 3 Volume */
-       [0x0696] = 0x0000,     /* R1686  - OUT2LMIX Input 4 Source */
-       [0x0697] = 0x0080,     /* R1687  - OUT2LMIX Input 4 Volume */
-       [0x0698] = 0x0000,     /* R1688  - OUT2RMIX Input 1 Source */
-       [0x0699] = 0x0080,     /* R1689  - OUT2RMIX Input 1 Volume */
-       [0x069A] = 0x0000,     /* R1690  - OUT2RMIX Input 2 Source */
-       [0x069B] = 0x0080,     /* R1691  - OUT2RMIX Input 2 Volume */
-       [0x069C] = 0x0000,     /* R1692  - OUT2RMIX Input 3 Source */
-       [0x069D] = 0x0080,     /* R1693  - OUT2RMIX Input 3 Volume */
-       [0x069E] = 0x0000,     /* R1694  - OUT2RMIX Input 4 Source */
-       [0x069F] = 0x0080,     /* R1695  - OUT2RMIX Input 4 Volume */
-       [0x06A0] = 0x0000,     /* R1696  - OUT3LMIX Input 1 Source */
-       [0x06A1] = 0x0080,     /* R1697  - OUT3LMIX Input 1 Volume */
-       [0x06A2] = 0x0000,     /* R1698  - OUT3LMIX Input 2 Source */
-       [0x06A3] = 0x0080,     /* R1699  - OUT3LMIX Input 2 Volume */
-       [0x06A4] = 0x0000,     /* R1700  - OUT3LMIX Input 3 Source */
-       [0x06A5] = 0x0080,     /* R1701  - OUT3LMIX Input 3 Volume */
-       [0x06A6] = 0x0000,     /* R1702  - OUT3LMIX Input 4 Source */
-       [0x06A7] = 0x0080,     /* R1703  - OUT3LMIX Input 4 Volume */
-       [0x06A8] = 0x0000,     /* R1704  - OUT3RMIX Input 1 Source */
-       [0x06A9] = 0x0080,     /* R1705  - OUT3RMIX Input 1 Volume */
-       [0x06AA] = 0x0000,     /* R1706  - OUT3RMIX Input 2 Source */
-       [0x06AB] = 0x0080,     /* R1707  - OUT3RMIX Input 2 Volume */
-       [0x06AC] = 0x0000,     /* R1708  - OUT3RMIX Input 3 Source */
-       [0x06AD] = 0x0080,     /* R1709  - OUT3RMIX Input 3 Volume */
-       [0x06AE] = 0x0000,     /* R1710  - OUT3RMIX Input 4 Source */
-       [0x06AF] = 0x0080,     /* R1711  - OUT3RMIX Input 4 Volume */
-       [0x06B0] = 0x0000,     /* R1712  - OUT4LMIX Input 1 Source */
-       [0x06B1] = 0x0080,     /* R1713  - OUT4LMIX Input 1 Volume */
-       [0x06B2] = 0x0000,     /* R1714  - OUT4LMIX Input 2 Source */
-       [0x06B3] = 0x0080,     /* R1715  - OUT4LMIX Input 2 Volume */
-       [0x06B4] = 0x0000,     /* R1716  - OUT4LMIX Input 3 Source */
-       [0x06B5] = 0x0080,     /* R1717  - OUT4LMIX Input 3 Volume */
-       [0x06B6] = 0x0000,     /* R1718  - OUT4LMIX Input 4 Source */
-       [0x06B7] = 0x0080,     /* R1719  - OUT4LMIX Input 4 Volume */
-       [0x06B8] = 0x0000,     /* R1720  - OUT4RMIX Input 1 Source */
-       [0x06B9] = 0x0080,     /* R1721  - OUT4RMIX Input 1 Volume */
-       [0x06BA] = 0x0000,     /* R1722  - OUT4RMIX Input 2 Source */
-       [0x06BB] = 0x0080,     /* R1723  - OUT4RMIX Input 2 Volume */
-       [0x06BC] = 0x0000,     /* R1724  - OUT4RMIX Input 3 Source */
-       [0x06BD] = 0x0080,     /* R1725  - OUT4RMIX Input 3 Volume */
-       [0x06BE] = 0x0000,     /* R1726  - OUT4RMIX Input 4 Source */
-       [0x06BF] = 0x0080,     /* R1727  - OUT4RMIX Input 4 Volume */
-       [0x06C0] = 0x0000,     /* R1728  - OUT5LMIX Input 1 Source */
-       [0x06C1] = 0x0080,     /* R1729  - OUT5LMIX Input 1 Volume */
-       [0x06C2] = 0x0000,     /* R1730  - OUT5LMIX Input 2 Source */
-       [0x06C3] = 0x0080,     /* R1731  - OUT5LMIX Input 2 Volume */
-       [0x06C4] = 0x0000,     /* R1732  - OUT5LMIX Input 3 Source */
-       [0x06C5] = 0x0080,     /* R1733  - OUT5LMIX Input 3 Volume */
-       [0x06C6] = 0x0000,     /* R1734  - OUT5LMIX Input 4 Source */
-       [0x06C7] = 0x0080,     /* R1735  - OUT5LMIX Input 4 Volume */
-       [0x06C8] = 0x0000,     /* R1736  - OUT5RMIX Input 1 Source */
-       [0x06C9] = 0x0080,     /* R1737  - OUT5RMIX Input 1 Volume */
-       [0x06CA] = 0x0000,     /* R1738  - OUT5RMIX Input 2 Source */
-       [0x06CB] = 0x0080,     /* R1739  - OUT5RMIX Input 2 Volume */
-       [0x06CC] = 0x0000,     /* R1740  - OUT5RMIX Input 3 Source */
-       [0x06CD] = 0x0080,     /* R1741  - OUT5RMIX Input 3 Volume */
-       [0x06CE] = 0x0000,     /* R1742  - OUT5RMIX Input 4 Source */
-       [0x06CF] = 0x0080,     /* R1743  - OUT5RMIX Input 4 Volume */
-       [0x06D0] = 0x0000,     /* R1744  - OUT6LMIX Input 1 Source */
-       [0x06D1] = 0x0080,     /* R1745  - OUT6LMIX Input 1 Volume */
-       [0x06D2] = 0x0000,     /* R1746  - OUT6LMIX Input 2 Source */
-       [0x06D3] = 0x0080,     /* R1747  - OUT6LMIX Input 2 Volume */
-       [0x06D4] = 0x0000,     /* R1748  - OUT6LMIX Input 3 Source */
-       [0x06D5] = 0x0080,     /* R1749  - OUT6LMIX Input 3 Volume */
-       [0x06D6] = 0x0000,     /* R1750  - OUT6LMIX Input 4 Source */
-       [0x06D7] = 0x0080,     /* R1751  - OUT6LMIX Input 4 Volume */
-       [0x06D8] = 0x0000,     /* R1752  - OUT6RMIX Input 1 Source */
-       [0x06D9] = 0x0080,     /* R1753  - OUT6RMIX Input 1 Volume */
-       [0x06DA] = 0x0000,     /* R1754  - OUT6RMIX Input 2 Source */
-       [0x06DB] = 0x0080,     /* R1755  - OUT6RMIX Input 2 Volume */
-       [0x06DC] = 0x0000,     /* R1756  - OUT6RMIX Input 3 Source */
-       [0x06DD] = 0x0080,     /* R1757  - OUT6RMIX Input 3 Volume */
-       [0x06DE] = 0x0000,     /* R1758  - OUT6RMIX Input 4 Source */
-       [0x06DF] = 0x0080,     /* R1759  - OUT6RMIX Input 4 Volume */
-       [0x0700] = 0x0000,     /* R1792  - AIF1TX1MIX Input 1 Source */
-       [0x0701] = 0x0080,     /* R1793  - AIF1TX1MIX Input 1 Volume */
-       [0x0702] = 0x0000,     /* R1794  - AIF1TX1MIX Input 2 Source */
-       [0x0703] = 0x0080,     /* R1795  - AIF1TX1MIX Input 2 Volume */
-       [0x0704] = 0x0000,     /* R1796  - AIF1TX1MIX Input 3 Source */
-       [0x0705] = 0x0080,     /* R1797  - AIF1TX1MIX Input 3 Volume */
-       [0x0706] = 0x0000,     /* R1798  - AIF1TX1MIX Input 4 Source */
-       [0x0707] = 0x0080,     /* R1799  - AIF1TX1MIX Input 4 Volume */
-       [0x0708] = 0x0000,     /* R1800  - AIF1TX2MIX Input 1 Source */
-       [0x0709] = 0x0080,     /* R1801  - AIF1TX2MIX Input 1 Volume */
-       [0x070A] = 0x0000,     /* R1802  - AIF1TX2MIX Input 2 Source */
-       [0x070B] = 0x0080,     /* R1803  - AIF1TX2MIX Input 2 Volume */
-       [0x070C] = 0x0000,     /* R1804  - AIF1TX2MIX Input 3 Source */
-       [0x070D] = 0x0080,     /* R1805  - AIF1TX2MIX Input 3 Volume */
-       [0x070E] = 0x0000,     /* R1806  - AIF1TX2MIX Input 4 Source */
-       [0x070F] = 0x0080,     /* R1807  - AIF1TX2MIX Input 4 Volume */
-       [0x0710] = 0x0000,     /* R1808  - AIF1TX3MIX Input 1 Source */
-       [0x0711] = 0x0080,     /* R1809  - AIF1TX3MIX Input 1 Volume */
-       [0x0712] = 0x0000,     /* R1810  - AIF1TX3MIX Input 2 Source */
-       [0x0713] = 0x0080,     /* R1811  - AIF1TX3MIX Input 2 Volume */
-       [0x0714] = 0x0000,     /* R1812  - AIF1TX3MIX Input 3 Source */
-       [0x0715] = 0x0080,     /* R1813  - AIF1TX3MIX Input 3 Volume */
-       [0x0716] = 0x0000,     /* R1814  - AIF1TX3MIX Input 4 Source */
-       [0x0717] = 0x0080,     /* R1815  - AIF1TX3MIX Input 4 Volume */
-       [0x0718] = 0x0000,     /* R1816  - AIF1TX4MIX Input 1 Source */
-       [0x0719] = 0x0080,     /* R1817  - AIF1TX4MIX Input 1 Volume */
-       [0x071A] = 0x0000,     /* R1818  - AIF1TX4MIX Input 2 Source */
-       [0x071B] = 0x0080,     /* R1819  - AIF1TX4MIX Input 2 Volume */
-       [0x071C] = 0x0000,     /* R1820  - AIF1TX4MIX Input 3 Source */
-       [0x071D] = 0x0080,     /* R1821  - AIF1TX4MIX Input 3 Volume */
-       [0x071E] = 0x0000,     /* R1822  - AIF1TX4MIX Input 4 Source */
-       [0x071F] = 0x0080,     /* R1823  - AIF1TX4MIX Input 4 Volume */
-       [0x0720] = 0x0000,     /* R1824  - AIF1TX5MIX Input 1 Source */
-       [0x0721] = 0x0080,     /* R1825  - AIF1TX5MIX Input 1 Volume */
-       [0x0722] = 0x0000,     /* R1826  - AIF1TX5MIX Input 2 Source */
-       [0x0723] = 0x0080,     /* R1827  - AIF1TX5MIX Input 2 Volume */
-       [0x0724] = 0x0000,     /* R1828  - AIF1TX5MIX Input 3 Source */
-       [0x0725] = 0x0080,     /* R1829  - AIF1TX5MIX Input 3 Volume */
-       [0x0726] = 0x0000,     /* R1830  - AIF1TX5MIX Input 4 Source */
-       [0x0727] = 0x0080,     /* R1831  - AIF1TX5MIX Input 4 Volume */
-       [0x0728] = 0x0000,     /* R1832  - AIF1TX6MIX Input 1 Source */
-       [0x0729] = 0x0080,     /* R1833  - AIF1TX6MIX Input 1 Volume */
-       [0x072A] = 0x0000,     /* R1834  - AIF1TX6MIX Input 2 Source */
-       [0x072B] = 0x0080,     /* R1835  - AIF1TX6MIX Input 2 Volume */
-       [0x072C] = 0x0000,     /* R1836  - AIF1TX6MIX Input 3 Source */
-       [0x072D] = 0x0080,     /* R1837  - AIF1TX6MIX Input 3 Volume */
-       [0x072E] = 0x0000,     /* R1838  - AIF1TX6MIX Input 4 Source */
-       [0x072F] = 0x0080,     /* R1839  - AIF1TX6MIX Input 4 Volume */
-       [0x0730] = 0x0000,     /* R1840  - AIF1TX7MIX Input 1 Source */
-       [0x0731] = 0x0080,     /* R1841  - AIF1TX7MIX Input 1 Volume */
-       [0x0732] = 0x0000,     /* R1842  - AIF1TX7MIX Input 2 Source */
-       [0x0733] = 0x0080,     /* R1843  - AIF1TX7MIX Input 2 Volume */
-       [0x0734] = 0x0000,     /* R1844  - AIF1TX7MIX Input 3 Source */
-       [0x0735] = 0x0080,     /* R1845  - AIF1TX7MIX Input 3 Volume */
-       [0x0736] = 0x0000,     /* R1846  - AIF1TX7MIX Input 4 Source */
-       [0x0737] = 0x0080,     /* R1847  - AIF1TX7MIX Input 4 Volume */
-       [0x0738] = 0x0000,     /* R1848  - AIF1TX8MIX Input 1 Source */
-       [0x0739] = 0x0080,     /* R1849  - AIF1TX8MIX Input 1 Volume */
-       [0x073A] = 0x0000,     /* R1850  - AIF1TX8MIX Input 2 Source */
-       [0x073B] = 0x0080,     /* R1851  - AIF1TX8MIX Input 2 Volume */
-       [0x073C] = 0x0000,     /* R1852  - AIF1TX8MIX Input 3 Source */
-       [0x073D] = 0x0080,     /* R1853  - AIF1TX8MIX Input 3 Volume */
-       [0x073E] = 0x0000,     /* R1854  - AIF1TX8MIX Input 4 Source */
-       [0x073F] = 0x0080,     /* R1855  - AIF1TX8MIX Input 4 Volume */
-       [0x0740] = 0x0000,     /* R1856  - AIF2TX1MIX Input 1 Source */
-       [0x0741] = 0x0080,     /* R1857  - AIF2TX1MIX Input 1 Volume */
-       [0x0742] = 0x0000,     /* R1858  - AIF2TX1MIX Input 2 Source */
-       [0x0743] = 0x0080,     /* R1859  - AIF2TX1MIX Input 2 Volume */
-       [0x0744] = 0x0000,     /* R1860  - AIF2TX1MIX Input 3 Source */
-       [0x0745] = 0x0080,     /* R1861  - AIF2TX1MIX Input 3 Volume */
-       [0x0746] = 0x0000,     /* R1862  - AIF2TX1MIX Input 4 Source */
-       [0x0747] = 0x0080,     /* R1863  - AIF2TX1MIX Input 4 Volume */
-       [0x0748] = 0x0000,     /* R1864  - AIF2TX2MIX Input 1 Source */
-       [0x0749] = 0x0080,     /* R1865  - AIF2TX2MIX Input 1 Volume */
-       [0x074A] = 0x0000,     /* R1866  - AIF2TX2MIX Input 2 Source */
-       [0x074B] = 0x0080,     /* R1867  - AIF2TX2MIX Input 2 Volume */
-       [0x074C] = 0x0000,     /* R1868  - AIF2TX2MIX Input 3 Source */
-       [0x074D] = 0x0080,     /* R1869  - AIF2TX2MIX Input 3 Volume */
-       [0x074E] = 0x0000,     /* R1870  - AIF2TX2MIX Input 4 Source */
-       [0x074F] = 0x0080,     /* R1871  - AIF2TX2MIX Input 4 Volume */
-       [0x0780] = 0x0000,     /* R1920  - AIF3TX1MIX Input 1 Source */
-       [0x0781] = 0x0080,     /* R1921  - AIF3TX1MIX Input 1 Volume */
-       [0x0782] = 0x0000,     /* R1922  - AIF3TX1MIX Input 2 Source */
-       [0x0783] = 0x0080,     /* R1923  - AIF3TX1MIX Input 2 Volume */
-       [0x0784] = 0x0000,     /* R1924  - AIF3TX1MIX Input 3 Source */
-       [0x0785] = 0x0080,     /* R1925  - AIF3TX1MIX Input 3 Volume */
-       [0x0786] = 0x0000,     /* R1926  - AIF3TX1MIX Input 4 Source */
-       [0x0787] = 0x0080,     /* R1927  - AIF3TX1MIX Input 4 Volume */
-       [0x0788] = 0x0000,     /* R1928  - AIF3TX2MIX Input 1 Source */
-       [0x0789] = 0x0080,     /* R1929  - AIF3TX2MIX Input 1 Volume */
-       [0x078A] = 0x0000,     /* R1930  - AIF3TX2MIX Input 2 Source */
-       [0x078B] = 0x0080,     /* R1931  - AIF3TX2MIX Input 2 Volume */
-       [0x078C] = 0x0000,     /* R1932  - AIF3TX2MIX Input 3 Source */
-       [0x078D] = 0x0080,     /* R1933  - AIF3TX2MIX Input 3 Volume */
-       [0x078E] = 0x0000,     /* R1934  - AIF3TX2MIX Input 4 Source */
-       [0x078F] = 0x0080,     /* R1935  - AIF3TX2MIX Input 4 Volume */
-       [0x0880] = 0x0000,     /* R2176  - EQ1MIX Input 1 Source */
-       [0x0881] = 0x0080,     /* R2177  - EQ1MIX Input 1 Volume */
-       [0x0882] = 0x0000,     /* R2178  - EQ1MIX Input 2 Source */
-       [0x0883] = 0x0080,     /* R2179  - EQ1MIX Input 2 Volume */
-       [0x0884] = 0x0000,     /* R2180  - EQ1MIX Input 3 Source */
-       [0x0885] = 0x0080,     /* R2181  - EQ1MIX Input 3 Volume */
-       [0x0886] = 0x0000,     /* R2182  - EQ1MIX Input 4 Source */
-       [0x0887] = 0x0080,     /* R2183  - EQ1MIX Input 4 Volume */
-       [0x0888] = 0x0000,     /* R2184  - EQ2MIX Input 1 Source */
-       [0x0889] = 0x0080,     /* R2185  - EQ2MIX Input 1 Volume */
-       [0x088A] = 0x0000,     /* R2186  - EQ2MIX Input 2 Source */
-       [0x088B] = 0x0080,     /* R2187  - EQ2MIX Input 2 Volume */
-       [0x088C] = 0x0000,     /* R2188  - EQ2MIX Input 3 Source */
-       [0x088D] = 0x0080,     /* R2189  - EQ2MIX Input 3 Volume */
-       [0x088E] = 0x0000,     /* R2190  - EQ2MIX Input 4 Source */
-       [0x088F] = 0x0080,     /* R2191  - EQ2MIX Input 4 Volume */
-       [0x0890] = 0x0000,     /* R2192  - EQ3MIX Input 1 Source */
-       [0x0891] = 0x0080,     /* R2193  - EQ3MIX Input 1 Volume */
-       [0x0892] = 0x0000,     /* R2194  - EQ3MIX Input 2 Source */
-       [0x0893] = 0x0080,     /* R2195  - EQ3MIX Input 2 Volume */
-       [0x0894] = 0x0000,     /* R2196  - EQ3MIX Input 3 Source */
-       [0x0895] = 0x0080,     /* R2197  - EQ3MIX Input 3 Volume */
-       [0x0896] = 0x0000,     /* R2198  - EQ3MIX Input 4 Source */
-       [0x0897] = 0x0080,     /* R2199  - EQ3MIX Input 4 Volume */
-       [0x0898] = 0x0000,     /* R2200  - EQ4MIX Input 1 Source */
-       [0x0899] = 0x0080,     /* R2201  - EQ4MIX Input 1 Volume */
-       [0x089A] = 0x0000,     /* R2202  - EQ4MIX Input 2 Source */
-       [0x089B] = 0x0080,     /* R2203  - EQ4MIX Input 2 Volume */
-       [0x089C] = 0x0000,     /* R2204  - EQ4MIX Input 3 Source */
-       [0x089D] = 0x0080,     /* R2205  - EQ4MIX Input 3 Volume */
-       [0x089E] = 0x0000,     /* R2206  - EQ4MIX Input 4 Source */
-       [0x089F] = 0x0080,     /* R2207  - EQ4MIX Input 4 Volume */
-       [0x08C0] = 0x0000,     /* R2240  - DRC1LMIX Input 1 Source */
-       [0x08C1] = 0x0080,     /* R2241  - DRC1LMIX Input 1 Volume */
-       [0x08C2] = 0x0000,     /* R2242  - DRC1LMIX Input 2 Source */
-       [0x08C3] = 0x0080,     /* R2243  - DRC1LMIX Input 2 Volume */
-       [0x08C4] = 0x0000,     /* R2244  - DRC1LMIX Input 3 Source */
-       [0x08C5] = 0x0080,     /* R2245  - DRC1LMIX Input 3 Volume */
-       [0x08C6] = 0x0000,     /* R2246  - DRC1LMIX Input 4 Source */
-       [0x08C7] = 0x0080,     /* R2247  - DRC1LMIX Input 4 Volume */
-       [0x08C8] = 0x0000,     /* R2248  - DRC1RMIX Input 1 Source */
-       [0x08C9] = 0x0080,     /* R2249  - DRC1RMIX Input 1 Volume */
-       [0x08CA] = 0x0000,     /* R2250  - DRC1RMIX Input 2 Source */
-       [0x08CB] = 0x0080,     /* R2251  - DRC1RMIX Input 2 Volume */
-       [0x08CC] = 0x0000,     /* R2252  - DRC1RMIX Input 3 Source */
-       [0x08CD] = 0x0080,     /* R2253  - DRC1RMIX Input 3 Volume */
-       [0x08CE] = 0x0000,     /* R2254  - DRC1RMIX Input 4 Source */
-       [0x08CF] = 0x0080,     /* R2255  - DRC1RMIX Input 4 Volume */
-       [0x0900] = 0x0000,     /* R2304  - HPLP1MIX Input 1 Source */
-       [0x0901] = 0x0080,     /* R2305  - HPLP1MIX Input 1 Volume */
-       [0x0902] = 0x0000,     /* R2306  - HPLP1MIX Input 2 Source */
-       [0x0903] = 0x0080,     /* R2307  - HPLP1MIX Input 2 Volume */
-       [0x0904] = 0x0000,     /* R2308  - HPLP1MIX Input 3 Source */
-       [0x0905] = 0x0080,     /* R2309  - HPLP1MIX Input 3 Volume */
-       [0x0906] = 0x0000,     /* R2310  - HPLP1MIX Input 4 Source */
-       [0x0907] = 0x0080,     /* R2311  - HPLP1MIX Input 4 Volume */
-       [0x0908] = 0x0000,     /* R2312  - HPLP2MIX Input 1 Source */
-       [0x0909] = 0x0080,     /* R2313  - HPLP2MIX Input 1 Volume */
-       [0x090A] = 0x0000,     /* R2314  - HPLP2MIX Input 2 Source */
-       [0x090B] = 0x0080,     /* R2315  - HPLP2MIX Input 2 Volume */
-       [0x090C] = 0x0000,     /* R2316  - HPLP2MIX Input 3 Source */
-       [0x090D] = 0x0080,     /* R2317  - HPLP2MIX Input 3 Volume */
-       [0x090E] = 0x0000,     /* R2318  - HPLP2MIX Input 4 Source */
-       [0x090F] = 0x0080,     /* R2319  - HPLP2MIX Input 4 Volume */
-       [0x0910] = 0x0000,     /* R2320  - HPLP3MIX Input 1 Source */
-       [0x0911] = 0x0080,     /* R2321  - HPLP3MIX Input 1 Volume */
-       [0x0912] = 0x0000,     /* R2322  - HPLP3MIX Input 2 Source */
-       [0x0913] = 0x0080,     /* R2323  - HPLP3MIX Input 2 Volume */
-       [0x0914] = 0x0000,     /* R2324  - HPLP3MIX Input 3 Source */
-       [0x0915] = 0x0080,     /* R2325  - HPLP3MIX Input 3 Volume */
-       [0x0916] = 0x0000,     /* R2326  - HPLP3MIX Input 4 Source */
-       [0x0917] = 0x0080,     /* R2327  - HPLP3MIX Input 4 Volume */
-       [0x0918] = 0x0000,     /* R2328  - HPLP4MIX Input 1 Source */
-       [0x0919] = 0x0080,     /* R2329  - HPLP4MIX Input 1 Volume */
-       [0x091A] = 0x0000,     /* R2330  - HPLP4MIX Input 2 Source */
-       [0x091B] = 0x0080,     /* R2331  - HPLP4MIX Input 2 Volume */
-       [0x091C] = 0x0000,     /* R2332  - HPLP4MIX Input 3 Source */
-       [0x091D] = 0x0080,     /* R2333  - HPLP4MIX Input 3 Volume */
-       [0x091E] = 0x0000,     /* R2334  - HPLP4MIX Input 4 Source */
-       [0x091F] = 0x0080,     /* R2335  - HPLP4MIX Input 4 Volume */
-       [0x0940] = 0x0000,     /* R2368  - DSP1LMIX Input 1 Source */
-       [0x0941] = 0x0080,     /* R2369  - DSP1LMIX Input 1 Volume */
-       [0x0942] = 0x0000,     /* R2370  - DSP1LMIX Input 2 Source */
-       [0x0943] = 0x0080,     /* R2371  - DSP1LMIX Input 2 Volume */
-       [0x0944] = 0x0000,     /* R2372  - DSP1LMIX Input 3 Source */
-       [0x0945] = 0x0080,     /* R2373  - DSP1LMIX Input 3 Volume */
-       [0x0946] = 0x0000,     /* R2374  - DSP1LMIX Input 4 Source */
-       [0x0947] = 0x0080,     /* R2375  - DSP1LMIX Input 4 Volume */
-       [0x0948] = 0x0000,     /* R2376  - DSP1RMIX Input 1 Source */
-       [0x0949] = 0x0080,     /* R2377  - DSP1RMIX Input 1 Volume */
-       [0x094A] = 0x0000,     /* R2378  - DSP1RMIX Input 2 Source */
-       [0x094B] = 0x0080,     /* R2379  - DSP1RMIX Input 2 Volume */
-       [0x094C] = 0x0000,     /* R2380  - DSP1RMIX Input 3 Source */
-       [0x094D] = 0x0080,     /* R2381  - DSP1RMIX Input 3 Volume */
-       [0x094E] = 0x0000,     /* R2382  - DSP1RMIX Input 4 Source */
-       [0x094F] = 0x0080,     /* R2383  - DSP1RMIX Input 4 Volume */
-       [0x0950] = 0x0000,     /* R2384  - DSP1AUX1MIX Input 1 Source */
-       [0x0958] = 0x0000,     /* R2392  - DSP1AUX2MIX Input 1 Source */
-       [0x0960] = 0x0000,     /* R2400  - DSP1AUX3MIX Input 1 Source */
-       [0x0968] = 0x0000,     /* R2408  - DSP1AUX4MIX Input 1 Source */
-       [0x0970] = 0x0000,     /* R2416  - DSP1AUX5MIX Input 1 Source */
-       [0x0978] = 0x0000,     /* R2424  - DSP1AUX6MIX Input 1 Source */
-       [0x0980] = 0x0000,     /* R2432  - DSP2LMIX Input 1 Source */
-       [0x0981] = 0x0080,     /* R2433  - DSP2LMIX Input 1 Volume */
-       [0x0982] = 0x0000,     /* R2434  - DSP2LMIX Input 2 Source */
-       [0x0983] = 0x0080,     /* R2435  - DSP2LMIX Input 2 Volume */
-       [0x0984] = 0x0000,     /* R2436  - DSP2LMIX Input 3 Source */
-       [0x0985] = 0x0080,     /* R2437  - DSP2LMIX Input 3 Volume */
-       [0x0986] = 0x0000,     /* R2438  - DSP2LMIX Input 4 Source */
-       [0x0987] = 0x0080,     /* R2439  - DSP2LMIX Input 4 Volume */
-       [0x0988] = 0x0000,     /* R2440  - DSP2RMIX Input 1 Source */
-       [0x0989] = 0x0080,     /* R2441  - DSP2RMIX Input 1 Volume */
-       [0x098A] = 0x0000,     /* R2442  - DSP2RMIX Input 2 Source */
-       [0x098B] = 0x0080,     /* R2443  - DSP2RMIX Input 2 Volume */
-       [0x098C] = 0x0000,     /* R2444  - DSP2RMIX Input 3 Source */
-       [0x098D] = 0x0080,     /* R2445  - DSP2RMIX Input 3 Volume */
-       [0x098E] = 0x0000,     /* R2446  - DSP2RMIX Input 4 Source */
-       [0x098F] = 0x0080,     /* R2447  - DSP2RMIX Input 4 Volume */
-       [0x0990] = 0x0000,     /* R2448  - DSP2AUX1MIX Input 1 Source */
-       [0x0998] = 0x0000,     /* R2456  - DSP2AUX2MIX Input 1 Source */
-       [0x09A0] = 0x0000,     /* R2464  - DSP2AUX3MIX Input 1 Source */
-       [0x09A8] = 0x0000,     /* R2472  - DSP2AUX4MIX Input 1 Source */
-       [0x09B0] = 0x0000,     /* R2480  - DSP2AUX5MIX Input 1 Source */
-       [0x09B8] = 0x0000,     /* R2488  - DSP2AUX6MIX Input 1 Source */
-       [0x09C0] = 0x0000,     /* R2496  - DSP3LMIX Input 1 Source */
-       [0x09C1] = 0x0080,     /* R2497  - DSP3LMIX Input 1 Volume */
-       [0x09C2] = 0x0000,     /* R2498  - DSP3LMIX Input 2 Source */
-       [0x09C3] = 0x0080,     /* R2499  - DSP3LMIX Input 2 Volume */
-       [0x09C4] = 0x0000,     /* R2500  - DSP3LMIX Input 3 Source */
-       [0x09C5] = 0x0080,     /* R2501  - DSP3LMIX Input 3 Volume */
-       [0x09C6] = 0x0000,     /* R2502  - DSP3LMIX Input 4 Source */
-       [0x09C7] = 0x0080,     /* R2503  - DSP3LMIX Input 4 Volume */
-       [0x09C8] = 0x0000,     /* R2504  - DSP3RMIX Input 1 Source */
-       [0x09C9] = 0x0080,     /* R2505  - DSP3RMIX Input 1 Volume */
-       [0x09CA] = 0x0000,     /* R2506  - DSP3RMIX Input 2 Source */
-       [0x09CB] = 0x0080,     /* R2507  - DSP3RMIX Input 2 Volume */
-       [0x09CC] = 0x0000,     /* R2508  - DSP3RMIX Input 3 Source */
-       [0x09CD] = 0x0080,     /* R2509  - DSP3RMIX Input 3 Volume */
-       [0x09CE] = 0x0000,     /* R2510  - DSP3RMIX Input 4 Source */
-       [0x09CF] = 0x0080,     /* R2511  - DSP3RMIX Input 4 Volume */
-       [0x09D0] = 0x0000,     /* R2512  - DSP3AUX1MIX Input 1 Source */
-       [0x09D8] = 0x0000,     /* R2520  - DSP3AUX2MIX Input 1 Source */
-       [0x09E0] = 0x0000,     /* R2528  - DSP3AUX3MIX Input 1 Source */
-       [0x09E8] = 0x0000,     /* R2536  - DSP3AUX4MIX Input 1 Source */
-       [0x09F0] = 0x0000,     /* R2544  - DSP3AUX5MIX Input 1 Source */
-       [0x09F8] = 0x0000,     /* R2552  - DSP3AUX6MIX Input 1 Source */
-       [0x0A80] = 0x0000,     /* R2688  - ASRC1LMIX Input 1 Source */
-       [0x0A88] = 0x0000,     /* R2696  - ASRC1RMIX Input 1 Source */
-       [0x0A90] = 0x0000,     /* R2704  - ASRC2LMIX Input 1 Source */
-       [0x0A98] = 0x0000,     /* R2712  - ASRC2RMIX Input 1 Source */
-       [0x0B00] = 0x0000,     /* R2816  - ISRC1DEC1MIX Input 1 Source */
-       [0x0B08] = 0x0000,     /* R2824  - ISRC1DEC2MIX Input 1 Source */
-       [0x0B10] = 0x0000,     /* R2832  - ISRC1DEC3MIX Input 1 Source */
-       [0x0B18] = 0x0000,     /* R2840  - ISRC1DEC4MIX Input 1 Source */
-       [0x0B20] = 0x0000,     /* R2848  - ISRC1INT1MIX Input 1 Source */
-       [0x0B28] = 0x0000,     /* R2856  - ISRC1INT2MIX Input 1 Source */
-       [0x0B30] = 0x0000,     /* R2864  - ISRC1INT3MIX Input 1 Source */
-       [0x0B38] = 0x0000,     /* R2872  - ISRC1INT4MIX Input 1 Source */
-       [0x0B40] = 0x0000,     /* R2880  - ISRC2DEC1MIX Input 1 Source */
-       [0x0B48] = 0x0000,     /* R2888  - ISRC2DEC2MIX Input 1 Source */
-       [0x0B50] = 0x0000,     /* R2896  - ISRC2DEC3MIX Input 1 Source */
-       [0x0B58] = 0x0000,     /* R2904  - ISRC2DEC4MIX Input 1 Source */
-       [0x0B60] = 0x0000,     /* R2912  - ISRC2INT1MIX Input 1 Source */
-       [0x0B68] = 0x0000,     /* R2920  - ISRC2INT2MIX Input 1 Source */
-       [0x0B70] = 0x0000,     /* R2928  - ISRC2INT3MIX Input 1 Source */
-       [0x0B78] = 0x0000,     /* R2936  - ISRC2INT4MIX Input 1 Source */
-       [0x0C00] = 0xA001,     /* R3072  - GPIO CTRL 1 */
-       [0x0C01] = 0xA001,     /* R3073  - GPIO CTRL 2 */
-       [0x0C02] = 0xA001,     /* R3074  - GPIO CTRL 3 */
-       [0x0C03] = 0xA001,     /* R3075  - GPIO CTRL 4 */
-       [0x0C04] = 0xA001,     /* R3076  - GPIO CTRL 5 */
-       [0x0C05] = 0xA001,     /* R3077  - GPIO CTRL 6 */
-       [0x0C23] = 0x4003,     /* R3107  - Misc Pad Ctrl 1 */
-       [0x0C24] = 0x0000,     /* R3108  - Misc Pad Ctrl 2 */
-       [0x0C25] = 0x0000,     /* R3109  - Misc Pad Ctrl 3 */
-       [0x0C26] = 0x0000,     /* R3110  - Misc Pad Ctrl 4 */
-       [0x0C27] = 0x0000,     /* R3111  - Misc Pad Ctrl 5 */
-       [0x0C28] = 0x0000,     /* R3112  - Misc GPIO 1 */
-       [0x0D00] = 0x0000,     /* R3328  - Interrupt Status 1 */
-       [0x0D01] = 0x0000,     /* R3329  - Interrupt Status 2 */
-       [0x0D02] = 0x0000,     /* R3330  - Interrupt Status 3 */
-       [0x0D03] = 0x0000,     /* R3331  - Interrupt Status 4 */
-       [0x0D04] = 0x0000,     /* R3332  - Interrupt Raw Status 2 */
-       [0x0D05] = 0x0000,     /* R3333  - Interrupt Raw Status 3 */
-       [0x0D06] = 0x0000,     /* R3334  - Interrupt Raw Status 4 */
-       [0x0D07] = 0xFFFF,     /* R3335  - Interrupt Status 1 Mask */
-       [0x0D08] = 0xFFFF,     /* R3336  - Interrupt Status 2 Mask */
-       [0x0D09] = 0xFFFF,     /* R3337  - Interrupt Status 3 Mask */
-       [0x0D0A] = 0xFFFF,     /* R3338  - Interrupt Status 4 Mask */
-       [0x0D1F] = 0x0000,     /* R3359  - Interrupt Control */
-       [0x0D20] = 0xFFFF,     /* R3360  - IRQ Debounce 1 */
-       [0x0D21] = 0xFFFF,     /* R3361  - IRQ Debounce 2 */
-       [0x0E00] = 0x0000,     /* R3584  - FX_Ctrl */
-       [0x0E10] = 0x6318,     /* R3600  - EQ1_1 */
-       [0x0E11] = 0x6300,     /* R3601  - EQ1_2 */
-       [0x0E12] = 0x0FC8,     /* R3602  - EQ1_3 */
-       [0x0E13] = 0x03FE,     /* R3603  - EQ1_4 */
-       [0x0E14] = 0x00E0,     /* R3604  - EQ1_5 */
-       [0x0E15] = 0x1EC4,     /* R3605  - EQ1_6 */
-       [0x0E16] = 0xF136,     /* R3606  - EQ1_7 */
-       [0x0E17] = 0x0409,     /* R3607  - EQ1_8 */
-       [0x0E18] = 0x04CC,     /* R3608  - EQ1_9 */
-       [0x0E19] = 0x1C9B,     /* R3609  - EQ1_10 */
-       [0x0E1A] = 0xF337,     /* R3610  - EQ1_11 */
-       [0x0E1B] = 0x040B,     /* R3611  - EQ1_12 */
-       [0x0E1C] = 0x0CBB,     /* R3612  - EQ1_13 */
-       [0x0E1D] = 0x16F8,     /* R3613  - EQ1_14 */
-       [0x0E1E] = 0xF7D9,     /* R3614  - EQ1_15 */
-       [0x0E1F] = 0x040A,     /* R3615  - EQ1_16 */
-       [0x0E20] = 0x1F14,     /* R3616  - EQ1_17 */
-       [0x0E21] = 0x058C,     /* R3617  - EQ1_18 */
-       [0x0E22] = 0x0563,     /* R3618  - EQ1_19 */
-       [0x0E23] = 0x4000,     /* R3619  - EQ1_20 */
-       [0x0E26] = 0x6318,     /* R3622  - EQ2_1 */
-       [0x0E27] = 0x6300,     /* R3623  - EQ2_2 */
-       [0x0E28] = 0x0FC8,     /* R3624  - EQ2_3 */
-       [0x0E29] = 0x03FE,     /* R3625  - EQ2_4 */
-       [0x0E2A] = 0x00E0,     /* R3626  - EQ2_5 */
-       [0x0E2B] = 0x1EC4,     /* R3627  - EQ2_6 */
-       [0x0E2C] = 0xF136,     /* R3628  - EQ2_7 */
-       [0x0E2D] = 0x0409,     /* R3629  - EQ2_8 */
-       [0x0E2E] = 0x04CC,     /* R3630  - EQ2_9 */
-       [0x0E2F] = 0x1C9B,     /* R3631  - EQ2_10 */
-       [0x0E30] = 0xF337,     /* R3632  - EQ2_11 */
-       [0x0E31] = 0x040B,     /* R3633  - EQ2_12 */
-       [0x0E32] = 0x0CBB,     /* R3634  - EQ2_13 */
-       [0x0E33] = 0x16F8,     /* R3635  - EQ2_14 */
-       [0x0E34] = 0xF7D9,     /* R3636  - EQ2_15 */
-       [0x0E35] = 0x040A,     /* R3637  - EQ2_16 */
-       [0x0E36] = 0x1F14,     /* R3638  - EQ2_17 */
-       [0x0E37] = 0x058C,     /* R3639  - EQ2_18 */
-       [0x0E38] = 0x0563,     /* R3640  - EQ2_19 */
-       [0x0E39] = 0x4000,     /* R3641  - EQ2_20 */
-       [0x0E3C] = 0x6318,     /* R3644  - EQ3_1 */
-       [0x0E3D] = 0x6300,     /* R3645  - EQ3_2 */
-       [0x0E3E] = 0x0FC8,     /* R3646  - EQ3_3 */
-       [0x0E3F] = 0x03FE,     /* R3647  - EQ3_4 */
-       [0x0E40] = 0x00E0,     /* R3648  - EQ3_5 */
-       [0x0E41] = 0x1EC4,     /* R3649  - EQ3_6 */
-       [0x0E42] = 0xF136,     /* R3650  - EQ3_7 */
-       [0x0E43] = 0x0409,     /* R3651  - EQ3_8 */
-       [0x0E44] = 0x04CC,     /* R3652  - EQ3_9 */
-       [0x0E45] = 0x1C9B,     /* R3653  - EQ3_10 */
-       [0x0E46] = 0xF337,     /* R3654  - EQ3_11 */
-       [0x0E47] = 0x040B,     /* R3655  - EQ3_12 */
-       [0x0E48] = 0x0CBB,     /* R3656  - EQ3_13 */
-       [0x0E49] = 0x16F8,     /* R3657  - EQ3_14 */
-       [0x0E4A] = 0xF7D9,     /* R3658  - EQ3_15 */
-       [0x0E4B] = 0x040A,     /* R3659  - EQ3_16 */
-       [0x0E4C] = 0x1F14,     /* R3660  - EQ3_17 */
-       [0x0E4D] = 0x058C,     /* R3661  - EQ3_18 */
-       [0x0E4E] = 0x0563,     /* R3662  - EQ3_19 */
-       [0x0E4F] = 0x4000,     /* R3663  - EQ3_20 */
-       [0x0E52] = 0x6318,     /* R3666  - EQ4_1 */
-       [0x0E53] = 0x6300,     /* R3667  - EQ4_2 */
-       [0x0E54] = 0x0FC8,     /* R3668  - EQ4_3 */
-       [0x0E55] = 0x03FE,     /* R3669  - EQ4_4 */
-       [0x0E56] = 0x00E0,     /* R3670  - EQ4_5 */
-       [0x0E57] = 0x1EC4,     /* R3671  - EQ4_6 */
-       [0x0E58] = 0xF136,     /* R3672  - EQ4_7 */
-       [0x0E59] = 0x0409,     /* R3673  - EQ4_8 */
-       [0x0E5A] = 0x04CC,     /* R3674  - EQ4_9 */
-       [0x0E5B] = 0x1C9B,     /* R3675  - EQ4_10 */
-       [0x0E5C] = 0xF337,     /* R3676  - EQ4_11 */
-       [0x0E5D] = 0x040B,     /* R3677  - EQ4_12 */
-       [0x0E5E] = 0x0CBB,     /* R3678  - EQ4_13 */
-       [0x0E5F] = 0x16F8,     /* R3679  - EQ4_14 */
-       [0x0E60] = 0xF7D9,     /* R3680  - EQ4_15 */
-       [0x0E61] = 0x040A,     /* R3681  - EQ4_16 */
-       [0x0E62] = 0x1F14,     /* R3682  - EQ4_17 */
-       [0x0E63] = 0x058C,     /* R3683  - EQ4_18 */
-       [0x0E64] = 0x0563,     /* R3684  - EQ4_19 */
-       [0x0E65] = 0x4000,     /* R3685  - EQ4_20 */
-       [0x0E80] = 0x0018,     /* R3712  - DRC1 ctrl1 */
-       [0x0E81] = 0x0933,     /* R3713  - DRC1 ctrl2 */
-       [0x0E82] = 0x0018,     /* R3714  - DRC1 ctrl3 */
-       [0x0E83] = 0x0000,     /* R3715  - DRC1 ctrl4 */
-       [0x0E84] = 0x0000,     /* R3716  - DRC1 ctrl5 */
-       [0x0EC0] = 0x0000,     /* R3776  - HPLPF1_1 */
-       [0x0EC1] = 0x0000,     /* R3777  - HPLPF1_2 */
-       [0x0EC4] = 0x0000,     /* R3780  - HPLPF2_1 */
-       [0x0EC5] = 0x0000,     /* R3781  - HPLPF2_2 */
-       [0x0EC8] = 0x0000,     /* R3784  - HPLPF3_1 */
-       [0x0EC9] = 0x0000,     /* R3785  - HPLPF3_2 */
-       [0x0ECC] = 0x0000,     /* R3788  - HPLPF4_1 */
-       [0x0ECD] = 0x0000,     /* R3789  - HPLPF4_2 */
-       [0x4000] = 0x0000,     /* R16384 - DSP1 DM 0 */
-       [0x4001] = 0x0000,     /* R16385 - DSP1 DM 1 */
-       [0x4002] = 0x0000,     /* R16386 - DSP1 DM 2 */
-       [0x4003] = 0x0000,     /* R16387 - DSP1 DM 3 */
-       [0x41FC] = 0x0000,     /* R16892 - DSP1 DM 508 */
-       [0x41FD] = 0x0000,     /* R16893 - DSP1 DM 509 */
-       [0x41FE] = 0x0000,     /* R16894 - DSP1 DM 510 */
-       [0x41FF] = 0x0000,     /* R16895 - DSP1 DM 511 */
-       [0x4800] = 0x0000,     /* R18432 - DSP1 PM 0 */
-       [0x4801] = 0x0000,     /* R18433 - DSP1 PM 1 */
-       [0x4802] = 0x0000,     /* R18434 - DSP1 PM 2 */
-       [0x4803] = 0x0000,     /* R18435 - DSP1 PM 3 */
-       [0x4804] = 0x0000,     /* R18436 - DSP1 PM 4 */
-       [0x4805] = 0x0000,     /* R18437 - DSP1 PM 5 */
-       [0x4DFA] = 0x0000,     /* R19962 - DSP1 PM 1530 */
-       [0x4DFB] = 0x0000,     /* R19963 - DSP1 PM 1531 */
-       [0x4DFC] = 0x0000,     /* R19964 - DSP1 PM 1532 */
-       [0x4DFD] = 0x0000,     /* R19965 - DSP1 PM 1533 */
-       [0x4DFE] = 0x0000,     /* R19966 - DSP1 PM 1534 */
-       [0x4DFF] = 0x0000,     /* R19967 - DSP1 PM 1535 */
-       [0x5000] = 0x0000,     /* R20480 - DSP1 ZM 0 */
-       [0x5001] = 0x0000,     /* R20481 - DSP1 ZM 1 */
-       [0x5002] = 0x0000,     /* R20482 - DSP1 ZM 2 */
-       [0x5003] = 0x0000,     /* R20483 - DSP1 ZM 3 */
-       [0x57FC] = 0x0000,     /* R22524 - DSP1 ZM 2044 */
-       [0x57FD] = 0x0000,     /* R22525 - DSP1 ZM 2045 */
-       [0x57FE] = 0x0000,     /* R22526 - DSP1 ZM 2046 */
-       [0x57FF] = 0x0000,     /* R22527 - DSP1 ZM 2047 */
-       [0x6000] = 0x0000,     /* R24576 - DSP2 DM 0 */
-       [0x6001] = 0x0000,     /* R24577 - DSP2 DM 1 */
-       [0x6002] = 0x0000,     /* R24578 - DSP2 DM 2 */
-       [0x6003] = 0x0000,     /* R24579 - DSP2 DM 3 */
-       [0x61FC] = 0x0000,     /* R25084 - DSP2 DM 508 */
-       [0x61FD] = 0x0000,     /* R25085 - DSP2 DM 509 */
-       [0x61FE] = 0x0000,     /* R25086 - DSP2 DM 510 */
-       [0x61FF] = 0x0000,     /* R25087 - DSP2 DM 511 */
-       [0x6800] = 0x0000,     /* R26624 - DSP2 PM 0 */
-       [0x6801] = 0x0000,     /* R26625 - DSP2 PM 1 */
-       [0x6802] = 0x0000,     /* R26626 - DSP2 PM 2 */
-       [0x6803] = 0x0000,     /* R26627 - DSP2 PM 3 */
-       [0x6804] = 0x0000,     /* R26628 - DSP2 PM 4 */
-       [0x6805] = 0x0000,     /* R26629 - DSP2 PM 5 */
-       [0x6DFA] = 0x0000,     /* R28154 - DSP2 PM 1530 */
-       [0x6DFB] = 0x0000,     /* R28155 - DSP2 PM 1531 */
-       [0x6DFC] = 0x0000,     /* R28156 - DSP2 PM 1532 */
-       [0x6DFD] = 0x0000,     /* R28157 - DSP2 PM 1533 */
-       [0x6DFE] = 0x0000,     /* R28158 - DSP2 PM 1534 */
-       [0x6DFF] = 0x0000,     /* R28159 - DSP2 PM 1535 */
-       [0x7000] = 0x0000,     /* R28672 - DSP2 ZM 0 */
-       [0x7001] = 0x0000,     /* R28673 - DSP2 ZM 1 */
-       [0x7002] = 0x0000,     /* R28674 - DSP2 ZM 2 */
-       [0x7003] = 0x0000,     /* R28675 - DSP2 ZM 3 */
-       [0x77FC] = 0x0000,     /* R30716 - DSP2 ZM 2044 */
-       [0x77FD] = 0x0000,     /* R30717 - DSP2 ZM 2045 */
-       [0x77FE] = 0x0000,     /* R30718 - DSP2 ZM 2046 */
-       [0x77FF] = 0x0000,     /* R30719 - DSP2 ZM 2047 */
-       [0x8000] = 0x0000,     /* R32768 - DSP3 DM 0 */
-       [0x8001] = 0x0000,     /* R32769 - DSP3 DM 1 */
-       [0x8002] = 0x0000,     /* R32770 - DSP3 DM 2 */
-       [0x8003] = 0x0000,     /* R32771 - DSP3 DM 3 */
-       [0x81FC] = 0x0000,     /* R33276 - DSP3 DM 508 */
-       [0x81FD] = 0x0000,     /* R33277 - DSP3 DM 509 */
-       [0x81FE] = 0x0000,     /* R33278 - DSP3 DM 510 */
-       [0x81FF] = 0x0000,     /* R33279 - DSP3 DM 511 */
-       [0x8800] = 0x0000,     /* R34816 - DSP3 PM 0 */
-       [0x8801] = 0x0000,     /* R34817 - DSP3 PM 1 */
-       [0x8802] = 0x0000,     /* R34818 - DSP3 PM 2 */
-       [0x8803] = 0x0000,     /* R34819 - DSP3 PM 3 */
-       [0x8804] = 0x0000,     /* R34820 - DSP3 PM 4 */
-       [0x8805] = 0x0000,     /* R34821 - DSP3 PM 5 */
-       [0x8DFA] = 0x0000,     /* R36346 - DSP3 PM 1530 */
-       [0x8DFB] = 0x0000,     /* R36347 - DSP3 PM 1531 */
-       [0x8DFC] = 0x0000,     /* R36348 - DSP3 PM 1532 */
-       [0x8DFD] = 0x0000,     /* R36349 - DSP3 PM 1533 */
-       [0x8DFE] = 0x0000,     /* R36350 - DSP3 PM 1534 */
-       [0x8DFF] = 0x0000,     /* R36351 - DSP3 PM 1535 */
-       [0x9000] = 0x0000,     /* R36864 - DSP3 ZM 0 */
-       [0x9001] = 0x0000,     /* R36865 - DSP3 ZM 1 */
-       [0x9002] = 0x0000,     /* R36866 - DSP3 ZM 2 */
-       [0x9003] = 0x0000,     /* R36867 - DSP3 ZM 3 */
-       [0x97FC] = 0x0000,     /* R38908 - DSP3 ZM 2044 */
-       [0x97FD] = 0x0000,     /* R38909 - DSP3 ZM 2045 */
-       [0x97FE] = 0x0000,     /* R38910 - DSP3 ZM 2046 */
-       [0x97FF] = 0x0000      /* R38911 - DSP3 ZM 2047 */
+struct reg_default wm5100_reg_defaults[WM5100_REGISTER_COUNT] = {
+       { 0x0000, 0x0000 },  /* R0     - software reset */
+       { 0x0001, 0x0000 },  /* R1     - Device Revision */
+       { 0x0010, 0x0801 },  /* R16    - Ctrl IF 1 */
+       { 0x0020, 0x0000 },  /* R32    - Tone Generator 1 */
+       { 0x0030, 0x0000 },  /* R48    - PWM Drive 1 */
+       { 0x0031, 0x0100 },  /* R49    - PWM Drive 2 */
+       { 0x0032, 0x0100 },  /* R50    - PWM Drive 3 */
+       { 0x0100, 0x0002 },  /* R256   - Clocking 1 */
+       { 0x0101, 0x0000 },  /* R257   - Clocking 3 */
+       { 0x0102, 0x0011 },  /* R258   - Clocking 4 */
+       { 0x0103, 0x0011 },  /* R259   - Clocking 5 */
+       { 0x0104, 0x0011 },  /* R260   - Clocking 6 */
+       { 0x0107, 0x0000 },  /* R263   - Clocking 7 */
+       { 0x0108, 0x0000 },  /* R264   - Clocking 8 */
+       { 0x0120, 0x0000 },  /* R288   - ASRC_ENABLE */
+       { 0x0121, 0x0000 },  /* R289   - ASRC_STATUS */
+       { 0x0122, 0x0000 },  /* R290   - ASRC_RATE1 */
+       { 0x0141, 0x8000 },  /* R321   - ISRC 1 CTRL 1 */
+       { 0x0142, 0x0000 },  /* R322   - ISRC 1 CTRL 2 */
+       { 0x0143, 0x8000 },  /* R323   - ISRC 2 CTRL1 */
+       { 0x0144, 0x0000 },  /* R324   - ISRC 2 CTRL 2 */
+       { 0x0182, 0x0000 },  /* R386   - FLL1 Control 1 */
+       { 0x0183, 0x0000 },  /* R387   - FLL1 Control 2 */
+       { 0x0184, 0x0000 },  /* R388   - FLL1 Control 3 */
+       { 0x0186, 0x0177 },  /* R390   - FLL1 Control 5 */
+       { 0x0187, 0x0001 },  /* R391   - FLL1 Control 6 */
+       { 0x0188, 0x0000 },  /* R392   - FLL1 EFS 1 */
+       { 0x01A2, 0x0000 },  /* R418   - FLL2 Control 1 */
+       { 0x01A3, 0x0000 },  /* R419   - FLL2 Control 2 */
+       { 0x01A4, 0x0000 },  /* R420   - FLL2 Control 3 */
+       { 0x01A6, 0x0177 },  /* R422   - FLL2 Control 5 */
+       { 0x01A7, 0x0001 },  /* R423   - FLL2 Control 6 */
+       { 0x01A8, 0x0000 },  /* R424   - FLL2 EFS 1 */
+       { 0x0200, 0x0020 },  /* R512   - Mic Charge Pump 1 */
+       { 0x0201, 0xB084 },  /* R513   - Mic Charge Pump 2 */
+       { 0x0202, 0xBBDE },  /* R514   - HP Charge Pump 1 */
+       { 0x0211, 0x20D4 },  /* R529   - LDO1 Control */
+       { 0x0215, 0x0062 },  /* R533   - Mic Bias Ctrl 1 */
+       { 0x0216, 0x0062 },  /* R534   - Mic Bias Ctrl 2 */
+       { 0x0217, 0x0062 },  /* R535   - Mic Bias Ctrl 3 */
+       { 0x0280, 0x0004 },  /* R640   - Accessory Detect Mode 1 */
+       { 0x0288, 0x0020 },  /* R648   - Headphone Detect 1 */
+       { 0x0289, 0x0000 },  /* R649   - Headphone Detect 2 */
+       { 0x0290, 0x1100 },  /* R656   - Mic Detect 1 */
+       { 0x0291, 0x009F },  /* R657   - Mic Detect 2 */
+       { 0x0292, 0x0000 },  /* R658   - Mic Detect 3 */
+       { 0x0301, 0x0000 },  /* R769   - Input Enables */
+       { 0x0302, 0x0000 },  /* R770   - Input Enables Status */
+       { 0x0310, 0x2280 },  /* R784   - Status */
+       { 0x0311, 0x0080 },  /* R785   - IN1R Control */
+       { 0x0312, 0x2280 },  /* R786   - IN2L Control */
+       { 0x0313, 0x0080 },  /* R787   - IN2R Control */
+       { 0x0314, 0x2280 },  /* R788   - IN3L Control */
+       { 0x0315, 0x0080 },  /* R789   - IN3R Control */
+       { 0x0316, 0x2280 },  /* R790   - IN4L Control */
+       { 0x0317, 0x0080 },  /* R791   - IN4R Control */
+       { 0x0318, 0x0000 },  /* R792   - RXANC_SRC */
+       { 0x0319, 0x0022 },  /* R793   - Input Volume Ramp */
+       { 0x0320, 0x0180 },  /* R800   - ADC Digital Volume 1L */
+       { 0x0321, 0x0180 },  /* R801   - ADC Digital Volume 1R */
+       { 0x0322, 0x0180 },  /* R802   - ADC Digital Volume 2L */
+       { 0x0323, 0x0180 },  /* R803   - ADC Digital Volume 2R */
+       { 0x0324, 0x0180 },  /* R804   - ADC Digital Volume 3L */
+       { 0x0325, 0x0180 },  /* R805   - ADC Digital Volume 3R */
+       { 0x0326, 0x0180 },  /* R806   - ADC Digital Volume 4L */
+       { 0x0327, 0x0180 },  /* R807   - ADC Digital Volume 4R */
+       { 0x0401, 0x0000 },  /* R1025  - Output Enables 2 */
+       { 0x0402, 0x0000 },  /* R1026  - Output Status 1 */
+       { 0x0403, 0x0000 },  /* R1027  - Output Status 2 */
+       { 0x0408, 0x0000 },  /* R1032  - Channel Enables 1 */
+       { 0x0410, 0x0080 },  /* R1040  - Out Volume 1L */
+       { 0x0411, 0x0080 },  /* R1041  - Out Volume 1R */
+       { 0x0412, 0x0080 },  /* R1042  - DAC Volume Limit 1L */
+       { 0x0413, 0x0080 },  /* R1043  - DAC Volume Limit 1R */
+       { 0x0414, 0x0080 },  /* R1044  - Out Volume 2L */
+       { 0x0415, 0x0080 },  /* R1045  - Out Volume 2R */
+       { 0x0416, 0x0080 },  /* R1046  - DAC Volume Limit 2L */
+       { 0x0417, 0x0080 },  /* R1047  - DAC Volume Limit 2R */
+       { 0x0418, 0x0080 },  /* R1048  - Out Volume 3L */
+       { 0x0419, 0x0080 },  /* R1049  - Out Volume 3R */
+       { 0x041A, 0x0080 },  /* R1050  - DAC Volume Limit 3L */
+       { 0x041B, 0x0080 },  /* R1051  - DAC Volume Limit 3R */
+       { 0x041C, 0x0080 },  /* R1052  - Out Volume 4L */
+       { 0x041D, 0x0080 },  /* R1053  - Out Volume 4R */
+       { 0x041E, 0x0080 },  /* R1054  - DAC Volume Limit 5L */
+       { 0x041F, 0x0080 },  /* R1055  - DAC Volume Limit 5R */
+       { 0x0420, 0x0080 },  /* R1056  - DAC Volume Limit 6L */
+       { 0x0421, 0x0080 },  /* R1057  - DAC Volume Limit 6R */
+       { 0x0440, 0x0000 },  /* R1088  - DAC AEC Control 1 */
+       { 0x0441, 0x0022 },  /* R1089  - Output Volume Ramp */
+       { 0x0480, 0x0180 },  /* R1152  - DAC Digital Volume 1L */
+       { 0x0481, 0x0180 },  /* R1153  - DAC Digital Volume 1R */
+       { 0x0482, 0x0180 },  /* R1154  - DAC Digital Volume 2L */
+       { 0x0483, 0x0180 },  /* R1155  - DAC Digital Volume 2R */
+       { 0x0484, 0x0180 },  /* R1156  - DAC Digital Volume 3L */
+       { 0x0485, 0x0180 },  /* R1157  - DAC Digital Volume 3R */
+       { 0x0486, 0x0180 },  /* R1158  - DAC Digital Volume 4L */
+       { 0x0487, 0x0180 },  /* R1159  - DAC Digital Volume 4R */
+       { 0x0488, 0x0180 },  /* R1160  - DAC Digital Volume 5L */
+       { 0x0489, 0x0180 },  /* R1161  - DAC Digital Volume 5R */
+       { 0x048A, 0x0180 },  /* R1162  - DAC Digital Volume 6L */
+       { 0x048B, 0x0180 },  /* R1163  - DAC Digital Volume 6R */
+       { 0x04C0, 0x0069 },  /* R1216  - PDM SPK1 CTRL 1 */
+       { 0x04C1, 0x0000 },  /* R1217  - PDM SPK1 CTRL 2 */
+       { 0x04C2, 0x0069 },  /* R1218  - PDM SPK2 CTRL 1 */
+       { 0x04C3, 0x0000 },  /* R1219  - PDM SPK2 CTRL 2 */
+       { 0x0500, 0x000C },  /* R1280  - Audio IF 1_1 */
+       { 0x0501, 0x0008 },  /* R1281  - Audio IF 1_2 */
+       { 0x0502, 0x0000 },  /* R1282  - Audio IF 1_3 */
+       { 0x0503, 0x0000 },  /* R1283  - Audio IF 1_4 */
+       { 0x0504, 0x0000 },  /* R1284  - Audio IF 1_5 */
+       { 0x0505, 0x0300 },  /* R1285  - Audio IF 1_6 */
+       { 0x0506, 0x0300 },  /* R1286  - Audio IF 1_7 */
+       { 0x0507, 0x1820 },  /* R1287  - Audio IF 1_8 */
+       { 0x0508, 0x1820 },  /* R1288  - Audio IF 1_9 */
+       { 0x0509, 0x0000 },  /* R1289  - Audio IF 1_10 */
+       { 0x050A, 0x0001 },  /* R1290  - Audio IF 1_11 */
+       { 0x050B, 0x0002 },  /* R1291  - Audio IF 1_12 */
+       { 0x050C, 0x0003 },  /* R1292  - Audio IF 1_13 */
+       { 0x050D, 0x0004 },  /* R1293  - Audio IF 1_14 */
+       { 0x050E, 0x0005 },  /* R1294  - Audio IF 1_15 */
+       { 0x050F, 0x0006 },  /* R1295  - Audio IF 1_16 */
+       { 0x0510, 0x0007 },  /* R1296  - Audio IF 1_17 */
+       { 0x0511, 0x0000 },  /* R1297  - Audio IF 1_18 */
+       { 0x0512, 0x0001 },  /* R1298  - Audio IF 1_19 */
+       { 0x0513, 0x0002 },  /* R1299  - Audio IF 1_20 */
+       { 0x0514, 0x0003 },  /* R1300  - Audio IF 1_21 */
+       { 0x0515, 0x0004 },  /* R1301  - Audio IF 1_22 */
+       { 0x0516, 0x0005 },  /* R1302  - Audio IF 1_23 */
+       { 0x0517, 0x0006 },  /* R1303  - Audio IF 1_24 */
+       { 0x0518, 0x0007 },  /* R1304  - Audio IF 1_25 */
+       { 0x0519, 0x0000 },  /* R1305  - Audio IF 1_26 */
+       { 0x051A, 0x0000 },  /* R1306  - Audio IF 1_27 */
+       { 0x0540, 0x000C },  /* R1344  - Audio IF 2_1 */
+       { 0x0541, 0x0008 },  /* R1345  - Audio IF 2_2 */
+       { 0x0542, 0x0000 },  /* R1346  - Audio IF 2_3 */
+       { 0x0543, 0x0000 },  /* R1347  - Audio IF 2_4 */
+       { 0x0544, 0x0000 },  /* R1348  - Audio IF 2_5 */
+       { 0x0545, 0x0300 },  /* R1349  - Audio IF 2_6 */
+       { 0x0546, 0x0300 },  /* R1350  - Audio IF 2_7 */
+       { 0x0547, 0x1820 },  /* R1351  - Audio IF 2_8 */
+       { 0x0548, 0x1820 },  /* R1352  - Audio IF 2_9 */
+       { 0x0549, 0x0000 },  /* R1353  - Audio IF 2_10 */
+       { 0x054A, 0x0001 },  /* R1354  - Audio IF 2_11 */
+       { 0x0551, 0x0000 },  /* R1361  - Audio IF 2_18 */
+       { 0x0552, 0x0001 },  /* R1362  - Audio IF 2_19 */
+       { 0x0559, 0x0000 },  /* R1369  - Audio IF 2_26 */
+       { 0x055A, 0x0000 },  /* R1370  - Audio IF 2_27 */
+       { 0x0580, 0x000C },  /* R1408  - Audio IF 3_1 */
+       { 0x0581, 0x0008 },  /* R1409  - Audio IF 3_2 */
+       { 0x0582, 0x0000 },  /* R1410  - Audio IF 3_3 */
+       { 0x0583, 0x0000 },  /* R1411  - Audio IF 3_4 */
+       { 0x0584, 0x0000 },  /* R1412  - Audio IF 3_5 */
+       { 0x0585, 0x0300 },  /* R1413  - Audio IF 3_6 */
+       { 0x0586, 0x0300 },  /* R1414  - Audio IF 3_7 */
+       { 0x0587, 0x1820 },  /* R1415  - Audio IF 3_8 */
+       { 0x0588, 0x1820 },  /* R1416  - Audio IF 3_9 */
+       { 0x0589, 0x0000 },  /* R1417  - Audio IF 3_10 */
+       { 0x058A, 0x0001 },  /* R1418  - Audio IF 3_11 */
+       { 0x0591, 0x0000 },  /* R1425  - Audio IF 3_18 */
+       { 0x0592, 0x0001 },  /* R1426  - Audio IF 3_19 */
+       { 0x0599, 0x0000 },  /* R1433  - Audio IF 3_26 */
+       { 0x059A, 0x0000 },  /* R1434  - Audio IF 3_27 */
+       { 0x0640, 0x0000 },  /* R1600  - PWM1MIX Input 1 Source */
+       { 0x0641, 0x0080 },  /* R1601  - PWM1MIX Input 1 Volume */
+       { 0x0642, 0x0000 },  /* R1602  - PWM1MIX Input 2 Source */
+       { 0x0643, 0x0080 },  /* R1603  - PWM1MIX Input 2 Volume */
+       { 0x0644, 0x0000 },  /* R1604  - PWM1MIX Input 3 Source */
+       { 0x0645, 0x0080 },  /* R1605  - PWM1MIX Input 3 Volume */
+       { 0x0646, 0x0000 },  /* R1606  - PWM1MIX Input 4 Source */
+       { 0x0647, 0x0080 },  /* R1607  - PWM1MIX Input 4 Volume */
+       { 0x0648, 0x0000 },  /* R1608  - PWM2MIX Input 1 Source */
+       { 0x0649, 0x0080 },  /* R1609  - PWM2MIX Input 1 Volume */
+       { 0x064A, 0x0000 },  /* R1610  - PWM2MIX Input 2 Source */
+       { 0x064B, 0x0080 },  /* R1611  - PWM2MIX Input 2 Volume */
+       { 0x064C, 0x0000 },  /* R1612  - PWM2MIX Input 3 Source */
+       { 0x064D, 0x0080 },  /* R1613  - PWM2MIX Input 3 Volume */
+       { 0x064E, 0x0000 },  /* R1614  - PWM2MIX Input 4 Source */
+       { 0x064F, 0x0080 },  /* R1615  - PWM2MIX Input 4 Volume */
+       { 0x0680, 0x0000 },  /* R1664  - OUT1LMIX Input 1 Source */
+       { 0x0681, 0x0080 },  /* R1665  - OUT1LMIX Input 1 Volume */
+       { 0x0682, 0x0000 },  /* R1666  - OUT1LMIX Input 2 Source */
+       { 0x0683, 0x0080 },  /* R1667  - OUT1LMIX Input 2 Volume */
+       { 0x0684, 0x0000 },  /* R1668  - OUT1LMIX Input 3 Source */
+       { 0x0685, 0x0080 },  /* R1669  - OUT1LMIX Input 3 Volume */
+       { 0x0686, 0x0000 },  /* R1670  - OUT1LMIX Input 4 Source */
+       { 0x0687, 0x0080 },  /* R1671  - OUT1LMIX Input 4 Volume */
+       { 0x0688, 0x0000 },  /* R1672  - OUT1RMIX Input 1 Source */
+       { 0x0689, 0x0080 },  /* R1673  - OUT1RMIX Input 1 Volume */
+       { 0x068A, 0x0000 },  /* R1674  - OUT1RMIX Input 2 Source */
+       { 0x068B, 0x0080 },  /* R1675  - OUT1RMIX Input 2 Volume */
+       { 0x068C, 0x0000 },  /* R1676  - OUT1RMIX Input 3 Source */
+       { 0x068D, 0x0080 },  /* R1677  - OUT1RMIX Input 3 Volume */
+       { 0x068E, 0x0000 },  /* R1678  - OUT1RMIX Input 4 Source */
+       { 0x068F, 0x0080 },  /* R1679  - OUT1RMIX Input 4 Volume */
+       { 0x0690, 0x0000 },  /* R1680  - OUT2LMIX Input 1 Source */
+       { 0x0691, 0x0080 },  /* R1681  - OUT2LMIX Input 1 Volume */
+       { 0x0692, 0x0000 },  /* R1682  - OUT2LMIX Input 2 Source */
+       { 0x0693, 0x0080 },  /* R1683  - OUT2LMIX Input 2 Volume */
+       { 0x0694, 0x0000 },  /* R1684  - OUT2LMIX Input 3 Source */
+       { 0x0695, 0x0080 },  /* R1685  - OUT2LMIX Input 3 Volume */
+       { 0x0696, 0x0000 },  /* R1686  - OUT2LMIX Input 4 Source */
+       { 0x0697, 0x0080 },  /* R1687  - OUT2LMIX Input 4 Volume */
+       { 0x0698, 0x0000 },  /* R1688  - OUT2RMIX Input 1 Source */
+       { 0x0699, 0x0080 },  /* R1689  - OUT2RMIX Input 1 Volume */
+       { 0x069A, 0x0000 },  /* R1690  - OUT2RMIX Input 2 Source */
+       { 0x069B, 0x0080 },  /* R1691  - OUT2RMIX Input 2 Volume */
+       { 0x069C, 0x0000 },  /* R1692  - OUT2RMIX Input 3 Source */
+       { 0x069D, 0x0080 },  /* R1693  - OUT2RMIX Input 3 Volume */
+       { 0x069E, 0x0000 },  /* R1694  - OUT2RMIX Input 4 Source */
+       { 0x069F, 0x0080 },  /* R1695  - OUT2RMIX Input 4 Volume */
+       { 0x06A0, 0x0000 },  /* R1696  - OUT3LMIX Input 1 Source */
+       { 0x06A1, 0x0080 },  /* R1697  - OUT3LMIX Input 1 Volume */
+       { 0x06A2, 0x0000 },  /* R1698  - OUT3LMIX Input 2 Source */
+       { 0x06A3, 0x0080 },  /* R1699  - OUT3LMIX Input 2 Volume */
+       { 0x06A4, 0x0000 },  /* R1700  - OUT3LMIX Input 3 Source */
+       { 0x06A5, 0x0080 },  /* R1701  - OUT3LMIX Input 3 Volume */
+       { 0x06A6, 0x0000 },  /* R1702  - OUT3LMIX Input 4 Source */
+       { 0x06A7, 0x0080 },  /* R1703  - OUT3LMIX Input 4 Volume */
+       { 0x06A8, 0x0000 },  /* R1704  - OUT3RMIX Input 1 Source */
+       { 0x06A9, 0x0080 },  /* R1705  - OUT3RMIX Input 1 Volume */
+       { 0x06AA, 0x0000 },  /* R1706  - OUT3RMIX Input 2 Source */
+       { 0x06AB, 0x0080 },  /* R1707  - OUT3RMIX Input 2 Volume */
+       { 0x06AC, 0x0000 },  /* R1708  - OUT3RMIX Input 3 Source */
+       { 0x06AD, 0x0080 },  /* R1709  - OUT3RMIX Input 3 Volume */
+       { 0x06AE, 0x0000 },  /* R1710  - OUT3RMIX Input 4 Source */
+       { 0x06AF, 0x0080 },  /* R1711  - OUT3RMIX Input 4 Volume */
+       { 0x06B0, 0x0000 },  /* R1712  - OUT4LMIX Input 1 Source */
+       { 0x06B1, 0x0080 },  /* R1713  - OUT4LMIX Input 1 Volume */
+       { 0x06B2, 0x0000 },  /* R1714  - OUT4LMIX Input 2 Source */
+       { 0x06B3, 0x0080 },  /* R1715  - OUT4LMIX Input 2 Volume */
+       { 0x06B4, 0x0000 },  /* R1716  - OUT4LMIX Input 3 Source */
+       { 0x06B5, 0x0080 },  /* R1717  - OUT4LMIX Input 3 Volume */
+       { 0x06B6, 0x0000 },  /* R1718  - OUT4LMIX Input 4 Source */
+       { 0x06B7, 0x0080 },  /* R1719  - OUT4LMIX Input 4 Volume */
+       { 0x06B8, 0x0000 },  /* R1720  - OUT4RMIX Input 1 Source */
+       { 0x06B9, 0x0080 },  /* R1721  - OUT4RMIX Input 1 Volume */
+       { 0x06BA, 0x0000 },  /* R1722  - OUT4RMIX Input 2 Source */
+       { 0x06BB, 0x0080 },  /* R1723  - OUT4RMIX Input 2 Volume */
+       { 0x06BC, 0x0000 },  /* R1724  - OUT4RMIX Input 3 Source */
+       { 0x06BD, 0x0080 },  /* R1725  - OUT4RMIX Input 3 Volume */
+       { 0x06BE, 0x0000 },  /* R1726  - OUT4RMIX Input 4 Source */
+       { 0x06BF, 0x0080 },  /* R1727  - OUT4RMIX Input 4 Volume */
+       { 0x06C0, 0x0000 },  /* R1728  - OUT5LMIX Input 1 Source */
+       { 0x06C1, 0x0080 },  /* R1729  - OUT5LMIX Input 1 Volume */
+       { 0x06C2, 0x0000 },  /* R1730  - OUT5LMIX Input 2 Source */
+       { 0x06C3, 0x0080 },  /* R1731  - OUT5LMIX Input 2 Volume */
+       { 0x06C4, 0x0000 },  /* R1732  - OUT5LMIX Input 3 Source */
+       { 0x06C5, 0x0080 },  /* R1733  - OUT5LMIX Input 3 Volume */
+       { 0x06C6, 0x0000 },  /* R1734  - OUT5LMIX Input 4 Source */
+       { 0x06C7, 0x0080 },  /* R1735  - OUT5LMIX Input 4 Volume */
+       { 0x06C8, 0x0000 },  /* R1736  - OUT5RMIX Input 1 Source */
+       { 0x06C9, 0x0080 },  /* R1737  - OUT5RMIX Input 1 Volume */
+       { 0x06CA, 0x0000 },  /* R1738  - OUT5RMIX Input 2 Source */
+       { 0x06CB, 0x0080 },  /* R1739  - OUT5RMIX Input 2 Volume */
+       { 0x06CC, 0x0000 },  /* R1740  - OUT5RMIX Input 3 Source */
+       { 0x06CD, 0x0080 },  /* R1741  - OUT5RMIX Input 3 Volume */
+       { 0x06CE, 0x0000 },  /* R1742  - OUT5RMIX Input 4 Source */
+       { 0x06CF, 0x0080 },  /* R1743  - OUT5RMIX Input 4 Volume */
+       { 0x06D0, 0x0000 },  /* R1744  - OUT6LMIX Input 1 Source */
+       { 0x06D1, 0x0080 },  /* R1745  - OUT6LMIX Input 1 Volume */
+       { 0x06D2, 0x0000 },  /* R1746  - OUT6LMIX Input 2 Source */
+       { 0x06D3, 0x0080 },  /* R1747  - OUT6LMIX Input 2 Volume */
+       { 0x06D4, 0x0000 },  /* R1748  - OUT6LMIX Input 3 Source */
+       { 0x06D5, 0x0080 },  /* R1749  - OUT6LMIX Input 3 Volume */
+       { 0x06D6, 0x0000 },  /* R1750  - OUT6LMIX Input 4 Source */
+       { 0x06D7, 0x0080 },  /* R1751  - OUT6LMIX Input 4 Volume */
+       { 0x06D8, 0x0000 },  /* R1752  - OUT6RMIX Input 1 Source */
+       { 0x06D9, 0x0080 },  /* R1753  - OUT6RMIX Input 1 Volume */
+       { 0x06DA, 0x0000 },  /* R1754  - OUT6RMIX Input 2 Source */
+       { 0x06DB, 0x0080 },  /* R1755  - OUT6RMIX Input 2 Volume */
+       { 0x06DC, 0x0000 },  /* R1756  - OUT6RMIX Input 3 Source */
+       { 0x06DD, 0x0080 },  /* R1757  - OUT6RMIX Input 3 Volume */
+       { 0x06DE, 0x0000 },  /* R1758  - OUT6RMIX Input 4 Source */
+       { 0x06DF, 0x0080 },  /* R1759  - OUT6RMIX Input 4 Volume */
+       { 0x0700, 0x0000 },  /* R1792  - AIF1TX1MIX Input 1 Source */
+       { 0x0701, 0x0080 },  /* R1793  - AIF1TX1MIX Input 1 Volume */
+       { 0x0702, 0x0000 },  /* R1794  - AIF1TX1MIX Input 2 Source */
+       { 0x0703, 0x0080 },  /* R1795  - AIF1TX1MIX Input 2 Volume */
+       { 0x0704, 0x0000 },  /* R1796  - AIF1TX1MIX Input 3 Source */
+       { 0x0705, 0x0080 },  /* R1797  - AIF1TX1MIX Input 3 Volume */
+       { 0x0706, 0x0000 },  /* R1798  - AIF1TX1MIX Input 4 Source */
+       { 0x0707, 0x0080 },  /* R1799  - AIF1TX1MIX Input 4 Volume */
+       { 0x0708, 0x0000 },  /* R1800  - AIF1TX2MIX Input 1 Source */
+       { 0x0709, 0x0080 },  /* R1801  - AIF1TX2MIX Input 1 Volume */
+       { 0x070A, 0x0000 },  /* R1802  - AIF1TX2MIX Input 2 Source */
+       { 0x070B, 0x0080 },  /* R1803  - AIF1TX2MIX Input 2 Volume */
+       { 0x070C, 0x0000 },  /* R1804  - AIF1TX2MIX Input 3 Source */
+       { 0x070D, 0x0080 },  /* R1805  - AIF1TX2MIX Input 3 Volume */
+       { 0x070E, 0x0000 },  /* R1806  - AIF1TX2MIX Input 4 Source */
+       { 0x070F, 0x0080 },  /* R1807  - AIF1TX2MIX Input 4 Volume */
+       { 0x0710, 0x0000 },  /* R1808  - AIF1TX3MIX Input 1 Source */
+       { 0x0711, 0x0080 },  /* R1809  - AIF1TX3MIX Input 1 Volume */
+       { 0x0712, 0x0000 },  /* R1810  - AIF1TX3MIX Input 2 Source */
+       { 0x0713, 0x0080 },  /* R1811  - AIF1TX3MIX Input 2 Volume */
+       { 0x0714, 0x0000 },  /* R1812  - AIF1TX3MIX Input 3 Source */
+       { 0x0715, 0x0080 },  /* R1813  - AIF1TX3MIX Input 3 Volume */
+       { 0x0716, 0x0000 },  /* R1814  - AIF1TX3MIX Input 4 Source */
+       { 0x0717, 0x0080 },  /* R1815  - AIF1TX3MIX Input 4 Volume */
+       { 0x0718, 0x0000 },  /* R1816  - AIF1TX4MIX Input 1 Source */
+       { 0x0719, 0x0080 },  /* R1817  - AIF1TX4MIX Input 1 Volume */
+       { 0x071A, 0x0000 },  /* R1818  - AIF1TX4MIX Input 2 Source */
+       { 0x071B, 0x0080 },  /* R1819  - AIF1TX4MIX Input 2 Volume */
+       { 0x071C, 0x0000 },  /* R1820  - AIF1TX4MIX Input 3 Source */
+       { 0x071D, 0x0080 },  /* R1821  - AIF1TX4MIX Input 3 Volume */
+       { 0x071E, 0x0000 },  /* R1822  - AIF1TX4MIX Input 4 Source */
+       { 0x071F, 0x0080 },  /* R1823  - AIF1TX4MIX Input 4 Volume */
+       { 0x0720, 0x0000 },  /* R1824  - AIF1TX5MIX Input 1 Source */
+       { 0x0721, 0x0080 },  /* R1825  - AIF1TX5MIX Input 1 Volume */
+       { 0x0722, 0x0000 },  /* R1826  - AIF1TX5MIX Input 2 Source */
+       { 0x0723, 0x0080 },  /* R1827  - AIF1TX5MIX Input 2 Volume */
+       { 0x0724, 0x0000 },  /* R1828  - AIF1TX5MIX Input 3 Source */
+       { 0x0725, 0x0080 },  /* R1829  - AIF1TX5MIX Input 3 Volume */
+       { 0x0726, 0x0000 },  /* R1830  - AIF1TX5MIX Input 4 Source */
+       { 0x0727, 0x0080 },  /* R1831  - AIF1TX5MIX Input 4 Volume */
+       { 0x0728, 0x0000 },  /* R1832  - AIF1TX6MIX Input 1 Source */
+       { 0x0729, 0x0080 },  /* R1833  - AIF1TX6MIX Input 1 Volume */
+       { 0x072A, 0x0000 },  /* R1834  - AIF1TX6MIX Input 2 Source */
+       { 0x072B, 0x0080 },  /* R1835  - AIF1TX6MIX Input 2 Volume */
+       { 0x072C, 0x0000 },  /* R1836  - AIF1TX6MIX Input 3 Source */
+       { 0x072D, 0x0080 },  /* R1837  - AIF1TX6MIX Input 3 Volume */
+       { 0x072E, 0x0000 },  /* R1838  - AIF1TX6MIX Input 4 Source */
+       { 0x072F, 0x0080 },  /* R1839  - AIF1TX6MIX Input 4 Volume */
+       { 0x0730, 0x0000 },  /* R1840  - AIF1TX7MIX Input 1 Source */
+       { 0x0731, 0x0080 },  /* R1841  - AIF1TX7MIX Input 1 Volume */
+       { 0x0732, 0x0000 },  /* R1842  - AIF1TX7MIX Input 2 Source */
+       { 0x0733, 0x0080 },  /* R1843  - AIF1TX7MIX Input 2 Volume */
+       { 0x0734, 0x0000 },  /* R1844  - AIF1TX7MIX Input 3 Source */
+       { 0x0735, 0x0080 },  /* R1845  - AIF1TX7MIX Input 3 Volume */
+       { 0x0736, 0x0000 },  /* R1846  - AIF1TX7MIX Input 4 Source */
+       { 0x0737, 0x0080 },  /* R1847  - AIF1TX7MIX Input 4 Volume */
+       { 0x0738, 0x0000 },  /* R1848  - AIF1TX8MIX Input 1 Source */
+       { 0x0739, 0x0080 },  /* R1849  - AIF1TX8MIX Input 1 Volume */
+       { 0x073A, 0x0000 },  /* R1850  - AIF1TX8MIX Input 2 Source */
+       { 0x073B, 0x0080 },  /* R1851  - AIF1TX8MIX Input 2 Volume */
+       { 0x073C, 0x0000 },  /* R1852  - AIF1TX8MIX Input 3 Source */
+       { 0x073D, 0x0080 },  /* R1853  - AIF1TX8MIX Input 3 Volume */
+       { 0x073E, 0x0000 },  /* R1854  - AIF1TX8MIX Input 4 Source */
+       { 0x073F, 0x0080 },  /* R1855  - AIF1TX8MIX Input 4 Volume */
+       { 0x0740, 0x0000 },  /* R1856  - AIF2TX1MIX Input 1 Source */
+       { 0x0741, 0x0080 },  /* R1857  - AIF2TX1MIX Input 1 Volume */
+       { 0x0742, 0x0000 },  /* R1858  - AIF2TX1MIX Input 2 Source */
+       { 0x0743, 0x0080 },  /* R1859  - AIF2TX1MIX Input 2 Volume */
+       { 0x0744, 0x0000 },  /* R1860  - AIF2TX1MIX Input 3 Source */
+       { 0x0745, 0x0080 },  /* R1861  - AIF2TX1MIX Input 3 Volume */
+       { 0x0746, 0x0000 },  /* R1862  - AIF2TX1MIX Input 4 Source */
+       { 0x0747, 0x0080 },  /* R1863  - AIF2TX1MIX Input 4 Volume */
+       { 0x0748, 0x0000 },  /* R1864  - AIF2TX2MIX Input 1 Source */
+       { 0x0749, 0x0080 },  /* R1865  - AIF2TX2MIX Input 1 Volume */
+       { 0x074A, 0x0000 },  /* R1866  - AIF2TX2MIX Input 2 Source */
+       { 0x074B, 0x0080 },  /* R1867  - AIF2TX2MIX Input 2 Volume */
+       { 0x074C, 0x0000 },  /* R1868  - AIF2TX2MIX Input 3 Source */
+       { 0x074D, 0x0080 },  /* R1869  - AIF2TX2MIX Input 3 Volume */
+       { 0x074E, 0x0000 },  /* R1870  - AIF2TX2MIX Input 4 Source */
+       { 0x074F, 0x0080 },  /* R1871  - AIF2TX2MIX Input 4 Volume */
+       { 0x0780, 0x0000 },  /* R1920  - AIF3TX1MIX Input 1 Source */
+       { 0x0781, 0x0080 },  /* R1921  - AIF3TX1MIX Input 1 Volume */
+       { 0x0782, 0x0000 },  /* R1922  - AIF3TX1MIX Input 2 Source */
+       { 0x0783, 0x0080 },  /* R1923  - AIF3TX1MIX Input 2 Volume */
+       { 0x0784, 0x0000 },  /* R1924  - AIF3TX1MIX Input 3 Source */
+       { 0x0785, 0x0080 },  /* R1925  - AIF3TX1MIX Input 3 Volume */
+       { 0x0786, 0x0000 },  /* R1926  - AIF3TX1MIX Input 4 Source */
+       { 0x0787, 0x0080 },  /* R1927  - AIF3TX1MIX Input 4 Volume */
+       { 0x0788, 0x0000 },  /* R1928  - AIF3TX2MIX Input 1 Source */
+       { 0x0789, 0x0080 },  /* R1929  - AIF3TX2MIX Input 1 Volume */
+       { 0x078A, 0x0000 },  /* R1930  - AIF3TX2MIX Input 2 Source */
+       { 0x078B, 0x0080 },  /* R1931  - AIF3TX2MIX Input 2 Volume */
+       { 0x078C, 0x0000 },  /* R1932  - AIF3TX2MIX Input 3 Source */
+       { 0x078D, 0x0080 },  /* R1933  - AIF3TX2MIX Input 3 Volume */
+       { 0x078E, 0x0000 },  /* R1934  - AIF3TX2MIX Input 4 Source */
+       { 0x078F, 0x0080 },  /* R1935  - AIF3TX2MIX Input 4 Volume */
+       { 0x0880, 0x0000 },  /* R2176  - EQ1MIX Input 1 Source */
+       { 0x0881, 0x0080 },  /* R2177  - EQ1MIX Input 1 Volume */
+       { 0x0882, 0x0000 },  /* R2178  - EQ1MIX Input 2 Source */
+       { 0x0883, 0x0080 },  /* R2179  - EQ1MIX Input 2 Volume */
+       { 0x0884, 0x0000 },  /* R2180  - EQ1MIX Input 3 Source */
+       { 0x0885, 0x0080 },  /* R2181  - EQ1MIX Input 3 Volume */
+       { 0x0886, 0x0000 },  /* R2182  - EQ1MIX Input 4 Source */
+       { 0x0887, 0x0080 },  /* R2183  - EQ1MIX Input 4 Volume */
+       { 0x0888, 0x0000 },  /* R2184  - EQ2MIX Input 1 Source */
+       { 0x0889, 0x0080 },  /* R2185  - EQ2MIX Input 1 Volume */
+       { 0x088A, 0x0000 },  /* R2186  - EQ2MIX Input 2 Source */
+       { 0x088B, 0x0080 },  /* R2187  - EQ2MIX Input 2 Volume */
+       { 0x088C, 0x0000 },  /* R2188  - EQ2MIX Input 3 Source */
+       { 0x088D, 0x0080 },  /* R2189  - EQ2MIX Input 3 Volume */
+       { 0x088E, 0x0000 },  /* R2190  - EQ2MIX Input 4 Source */
+       { 0x088F, 0x0080 },  /* R2191  - EQ2MIX Input 4 Volume */
+       { 0x0890, 0x0000 },  /* R2192  - EQ3MIX Input 1 Source */
+       { 0x0891, 0x0080 },  /* R2193  - EQ3MIX Input 1 Volume */
+       { 0x0892, 0x0000 },  /* R2194  - EQ3MIX Input 2 Source */
+       { 0x0893, 0x0080 },  /* R2195  - EQ3MIX Input 2 Volume */
+       { 0x0894, 0x0000 },  /* R2196  - EQ3MIX Input 3 Source */
+       { 0x0895, 0x0080 },  /* R2197  - EQ3MIX Input 3 Volume */
+       { 0x0896, 0x0000 },  /* R2198  - EQ3MIX Input 4 Source */
+       { 0x0897, 0x0080 },  /* R2199  - EQ3MIX Input 4 Volume */
+       { 0x0898, 0x0000 },  /* R2200  - EQ4MIX Input 1 Source */
+       { 0x0899, 0x0080 },  /* R2201  - EQ4MIX Input 1 Volume */
+       { 0x089A, 0x0000 },  /* R2202  - EQ4MIX Input 2 Source */
+       { 0x089B, 0x0080 },  /* R2203  - EQ4MIX Input 2 Volume */
+       { 0x089C, 0x0000 },  /* R2204  - EQ4MIX Input 3 Source */
+       { 0x089D, 0x0080 },  /* R2205  - EQ4MIX Input 3 Volume */
+       { 0x089E, 0x0000 },  /* R2206  - EQ4MIX Input 4 Source */
+       { 0x089F, 0x0080 },  /* R2207  - EQ4MIX Input 4 Volume */
+       { 0x08C0, 0x0000 },  /* R2240  - DRC1LMIX Input 1 Source */
+       { 0x08C1, 0x0080 },  /* R2241  - DRC1LMIX Input 1 Volume */
+       { 0x08C2, 0x0000 },  /* R2242  - DRC1LMIX Input 2 Source */
+       { 0x08C3, 0x0080 },  /* R2243  - DRC1LMIX Input 2 Volume */
+       { 0x08C4, 0x0000 },  /* R2244  - DRC1LMIX Input 3 Source */
+       { 0x08C5, 0x0080 },  /* R2245  - DRC1LMIX Input 3 Volume */
+       { 0x08C6, 0x0000 },  /* R2246  - DRC1LMIX Input 4 Source */
+       { 0x08C7, 0x0080 },  /* R2247  - DRC1LMIX Input 4 Volume */
+       { 0x08C8, 0x0000 },  /* R2248  - DRC1RMIX Input 1 Source */
+       { 0x08C9, 0x0080 },  /* R2249  - DRC1RMIX Input 1 Volume */
+       { 0x08CA, 0x0000 },  /* R2250  - DRC1RMIX Input 2 Source */
+       { 0x08CB, 0x0080 },  /* R2251  - DRC1RMIX Input 2 Volume */
+       { 0x08CC, 0x0000 },  /* R2252  - DRC1RMIX Input 3 Source */
+       { 0x08CD, 0x0080 },  /* R2253  - DRC1RMIX Input 3 Volume */
+       { 0x08CE, 0x0000 },  /* R2254  - DRC1RMIX Input 4 Source */
+       { 0x08CF, 0x0080 },  /* R2255  - DRC1RMIX Input 4 Volume */
+       { 0x0900, 0x0000 },  /* R2304  - HPLP1MIX Input 1 Source */
+       { 0x0901, 0x0080 },  /* R2305  - HPLP1MIX Input 1 Volume */
+       { 0x0902, 0x0000 },  /* R2306  - HPLP1MIX Input 2 Source */
+       { 0x0903, 0x0080 },  /* R2307  - HPLP1MIX Input 2 Volume */
+       { 0x0904, 0x0000 },  /* R2308  - HPLP1MIX Input 3 Source */
+       { 0x0905, 0x0080 },  /* R2309  - HPLP1MIX Input 3 Volume */
+       { 0x0906, 0x0000 },  /* R2310  - HPLP1MIX Input 4 Source */
+       { 0x0907, 0x0080 },  /* R2311  - HPLP1MIX Input 4 Volume */
+       { 0x0908, 0x0000 },  /* R2312  - HPLP2MIX Input 1 Source */
+       { 0x0909, 0x0080 },  /* R2313  - HPLP2MIX Input 1 Volume */
+       { 0x090A, 0x0000 },  /* R2314  - HPLP2MIX Input 2 Source */
+       { 0x090B, 0x0080 },  /* R2315  - HPLP2MIX Input 2 Volume */
+       { 0x090C, 0x0000 },  /* R2316  - HPLP2MIX Input 3 Source */
+       { 0x090D, 0x0080 },  /* R2317  - HPLP2MIX Input 3 Volume */
+       { 0x090E, 0x0000 },  /* R2318  - HPLP2MIX Input 4 Source */
+       { 0x090F, 0x0080 },  /* R2319  - HPLP2MIX Input 4 Volume */
+       { 0x0910, 0x0000 },  /* R2320  - HPLP3MIX Input 1 Source */
+       { 0x0911, 0x0080 },  /* R2321  - HPLP3MIX Input 1 Volume */
+       { 0x0912, 0x0000 },  /* R2322  - HPLP3MIX Input 2 Source */
+       { 0x0913, 0x0080 },  /* R2323  - HPLP3MIX Input 2 Volume */
+       { 0x0914, 0x0000 },  /* R2324  - HPLP3MIX Input 3 Source */
+       { 0x0915, 0x0080 },  /* R2325  - HPLP3MIX Input 3 Volume */
+       { 0x0916, 0x0000 },  /* R2326  - HPLP3MIX Input 4 Source */
+       { 0x0917, 0x0080 },  /* R2327  - HPLP3MIX Input 4 Volume */
+       { 0x0918, 0x0000 },  /* R2328  - HPLP4MIX Input 1 Source */
+       { 0x0919, 0x0080 },  /* R2329  - HPLP4MIX Input 1 Volume */
+       { 0x091A, 0x0000 },  /* R2330  - HPLP4MIX Input 2 Source */
+       { 0x091B, 0x0080 },  /* R2331  - HPLP4MIX Input 2 Volume */
+       { 0x091C, 0x0000 },  /* R2332  - HPLP4MIX Input 3 Source */
+       { 0x091D, 0x0080 },  /* R2333  - HPLP4MIX Input 3 Volume */
+       { 0x091E, 0x0000 },  /* R2334  - HPLP4MIX Input 4 Source */
+       { 0x091F, 0x0080 },  /* R2335  - HPLP4MIX Input 4 Volume */
+       { 0x0940, 0x0000 },  /* R2368  - DSP1LMIX Input 1 Source */
+       { 0x0941, 0x0080 },  /* R2369  - DSP1LMIX Input 1 Volume */
+       { 0x0942, 0x0000 },  /* R2370  - DSP1LMIX Input 2 Source */
+       { 0x0943, 0x0080 },  /* R2371  - DSP1LMIX Input 2 Volume */
+       { 0x0944, 0x0000 },  /* R2372  - DSP1LMIX Input 3 Source */
+       { 0x0945, 0x0080 },  /* R2373  - DSP1LMIX Input 3 Volume */
+       { 0x0946, 0x0000 },  /* R2374  - DSP1LMIX Input 4 Source */
+       { 0x0947, 0x0080 },  /* R2375  - DSP1LMIX Input 4 Volume */
+       { 0x0948, 0x0000 },  /* R2376  - DSP1RMIX Input 1 Source */
+       { 0x0949, 0x0080 },  /* R2377  - DSP1RMIX Input 1 Volume */
+       { 0x094A, 0x0000 },  /* R2378  - DSP1RMIX Input 2 Source */
+       { 0x094B, 0x0080 },  /* R2379  - DSP1RMIX Input 2 Volume */
+       { 0x094C, 0x0000 },  /* R2380  - DSP1RMIX Input 3 Source */
+       { 0x094D, 0x0080 },  /* R2381  - DSP1RMIX Input 3 Volume */
+       { 0x094E, 0x0000 },  /* R2382  - DSP1RMIX Input 4 Source */
+       { 0x094F, 0x0080 },  /* R2383  - DSP1RMIX Input 4 Volume */
+       { 0x0950, 0x0000 },  /* R2384  - DSP1AUX1MIX Input 1 Source */
+       { 0x0958, 0x0000 },  /* R2392  - DSP1AUX2MIX Input 1 Source */
+       { 0x0960, 0x0000 },  /* R2400  - DSP1AUX3MIX Input 1 Source */
+       { 0x0968, 0x0000 },  /* R2408  - DSP1AUX4MIX Input 1 Source */
+       { 0x0970, 0x0000 },  /* R2416  - DSP1AUX5MIX Input 1 Source */
+       { 0x0978, 0x0000 },  /* R2424  - DSP1AUX6MIX Input 1 Source */
+       { 0x0980, 0x0000 },  /* R2432  - DSP2LMIX Input 1 Source */
+       { 0x0981, 0x0080 },  /* R2433  - DSP2LMIX Input 1 Volume */
+       { 0x0982, 0x0000 },  /* R2434  - DSP2LMIX Input 2 Source */
+       { 0x0983, 0x0080 },  /* R2435  - DSP2LMIX Input 2 Volume */
+       { 0x0984, 0x0000 },  /* R2436  - DSP2LMIX Input 3 Source */
+       { 0x0985, 0x0080 },  /* R2437  - DSP2LMIX Input 3 Volume */
+       { 0x0986, 0x0000 },  /* R2438  - DSP2LMIX Input 4 Source */
+       { 0x0987, 0x0080 },  /* R2439  - DSP2LMIX Input 4 Volume */
+       { 0x0988, 0x0000 },  /* R2440  - DSP2RMIX Input 1 Source */
+       { 0x0989, 0x0080 },  /* R2441  - DSP2RMIX Input 1 Volume */
+       { 0x098A, 0x0000 },  /* R2442  - DSP2RMIX Input 2 Source */
+       { 0x098B, 0x0080 },  /* R2443  - DSP2RMIX Input 2 Volume */
+       { 0x098C, 0x0000 },  /* R2444  - DSP2RMIX Input 3 Source */
+       { 0x098D, 0x0080 },  /* R2445  - DSP2RMIX Input 3 Volume */
+       { 0x098E, 0x0000 },  /* R2446  - DSP2RMIX Input 4 Source */
+       { 0x098F, 0x0080 },  /* R2447  - DSP2RMIX Input 4 Volume */
+       { 0x0990, 0x0000 },  /* R2448  - DSP2AUX1MIX Input 1 Source */
+       { 0x0998, 0x0000 },  /* R2456  - DSP2AUX2MIX Input 1 Source */
+       { 0x09A0, 0x0000 },  /* R2464  - DSP2AUX3MIX Input 1 Source */
+       { 0x09A8, 0x0000 },  /* R2472  - DSP2AUX4MIX Input 1 Source */
+       { 0x09B0, 0x0000 },  /* R2480  - DSP2AUX5MIX Input 1 Source */
+       { 0x09B8, 0x0000 },  /* R2488  - DSP2AUX6MIX Input 1 Source */
+       { 0x09C0, 0x0000 },  /* R2496  - DSP3LMIX Input 1 Source */
+       { 0x09C1, 0x0080 },  /* R2497  - DSP3LMIX Input 1 Volume */
+       { 0x09C2, 0x0000 },  /* R2498  - DSP3LMIX Input 2 Source */
+       { 0x09C3, 0x0080 },  /* R2499  - DSP3LMIX Input 2 Volume */
+       { 0x09C4, 0x0000 },  /* R2500  - DSP3LMIX Input 3 Source */
+       { 0x09C5, 0x0080 },  /* R2501  - DSP3LMIX Input 3 Volume */
+       { 0x09C6, 0x0000 },  /* R2502  - DSP3LMIX Input 4 Source */
+       { 0x09C7, 0x0080 },  /* R2503  - DSP3LMIX Input 4 Volume */
+       { 0x09C8, 0x0000 },  /* R2504  - DSP3RMIX Input 1 Source */
+       { 0x09C9, 0x0080 },  /* R2505  - DSP3RMIX Input 1 Volume */
+       { 0x09CA, 0x0000 },  /* R2506  - DSP3RMIX Input 2 Source */
+       { 0x09CB, 0x0080 },  /* R2507  - DSP3RMIX Input 2 Volume */
+       { 0x09CC, 0x0000 },  /* R2508  - DSP3RMIX Input 3 Source */
+       { 0x09CD, 0x0080 },  /* R2509  - DSP3RMIX Input 3 Volume */
+       { 0x09CE, 0x0000 },  /* R2510  - DSP3RMIX Input 4 Source */
+       { 0x09CF, 0x0080 },  /* R2511  - DSP3RMIX Input 4 Volume */
+       { 0x09D0, 0x0000 },  /* R2512  - DSP3AUX1MIX Input 1 Source */
+       { 0x09D8, 0x0000 },  /* R2520  - DSP3AUX2MIX Input 1 Source */
+       { 0x09E0, 0x0000 },  /* R2528  - DSP3AUX3MIX Input 1 Source */
+       { 0x09E8, 0x0000 },  /* R2536  - DSP3AUX4MIX Input 1 Source */
+       { 0x09F0, 0x0000 },  /* R2544  - DSP3AUX5MIX Input 1 Source */
+       { 0x09F8, 0x0000 },  /* R2552  - DSP3AUX6MIX Input 1 Source */
+       { 0x0A80, 0x0000 },  /* R2688  - ASRC1LMIX Input 1 Source */
+       { 0x0A88, 0x0000 },  /* R2696  - ASRC1RMIX Input 1 Source */
+       { 0x0A90, 0x0000 },  /* R2704  - ASRC2LMIX Input 1 Source */
+       { 0x0A98, 0x0000 },  /* R2712  - ASRC2RMIX Input 1 Source */
+       { 0x0B00, 0x0000 },  /* R2816  - ISRC1DEC1MIX Input 1 Source */
+       { 0x0B08, 0x0000 },  /* R2824  - ISRC1DEC2MIX Input 1 Source */
+       { 0x0B10, 0x0000 },  /* R2832  - ISRC1DEC3MIX Input 1 Source */
+       { 0x0B18, 0x0000 },  /* R2840  - ISRC1DEC4MIX Input 1 Source */
+       { 0x0B20, 0x0000 },  /* R2848  - ISRC1INT1MIX Input 1 Source */
+       { 0x0B28, 0x0000 },  /* R2856  - ISRC1INT2MIX Input 1 Source */
+       { 0x0B30, 0x0000 },  /* R2864  - ISRC1INT3MIX Input 1 Source */
+       { 0x0B38, 0x0000 },  /* R2872  - ISRC1INT4MIX Input 1 Source */
+       { 0x0B40, 0x0000 },  /* R2880  - ISRC2DEC1MIX Input 1 Source */
+       { 0x0B48, 0x0000 },  /* R2888  - ISRC2DEC2MIX Input 1 Source */
+       { 0x0B50, 0x0000 },  /* R2896  - ISRC2DEC3MIX Input 1 Source */
+       { 0x0B58, 0x0000 },  /* R2904  - ISRC2DEC4MIX Input 1 Source */
+       { 0x0B60, 0x0000 },  /* R2912  - ISRC2INT1MIX Input 1 Source */
+       { 0x0B68, 0x0000 },  /* R2920  - ISRC2INT2MIX Input 1 Source */
+       { 0x0B70, 0x0000 },  /* R2928  - ISRC2INT3MIX Input 1 Source */
+       { 0x0B78, 0x0000 },  /* R2936  - ISRC2INT4MIX Input 1 Source */
+       { 0x0C00, 0xA001 },  /* R3072  - GPIO CTRL 1 */
+       { 0x0C01, 0xA001 },  /* R3073  - GPIO CTRL 2 */
+       { 0x0C02, 0xA001 },  /* R3074  - GPIO CTRL 3 */
+       { 0x0C03, 0xA001 },  /* R3075  - GPIO CTRL 4 */
+       { 0x0C04, 0xA001 },  /* R3076  - GPIO CTRL 5 */
+       { 0x0C05, 0xA001 },  /* R3077  - GPIO CTRL 6 */
+       { 0x0C23, 0x4003 },  /* R3107  - Misc Pad Ctrl 1 */
+       { 0x0C24, 0x0000 },  /* R3108  - Misc Pad Ctrl 2 */
+       { 0x0C25, 0x0000 },  /* R3109  - Misc Pad Ctrl 3 */
+       { 0x0C26, 0x0000 },  /* R3110  - Misc Pad Ctrl 4 */
+       { 0x0C27, 0x0000 },  /* R3111  - Misc Pad Ctrl 5 */
+       { 0x0C28, 0x0000 },  /* R3112  - Misc GPIO 1 */
+       { 0x0D00, 0x0000 },  /* R3328  - Interrupt Status 1 */
+       { 0x0D01, 0x0000 },  /* R3329  - Interrupt Status 2 */
+       { 0x0D02, 0x0000 },  /* R3330  - Interrupt Status 3 */
+       { 0x0D03, 0x0000 },  /* R3331  - Interrupt Status 4 */
+       { 0x0D04, 0x0000 },  /* R3332  - Interrupt Raw Status 2 */
+       { 0x0D05, 0x0000 },  /* R3333  - Interrupt Raw Status 3 */
+       { 0x0D06, 0x0000 },  /* R3334  - Interrupt Raw Status 4 */
+       { 0x0D07, 0xFFFF },  /* R3335  - Interrupt Status 1 Mask */
+       { 0x0D08, 0xFFFF },  /* R3336  - Interrupt Status 2 Mask */
+       { 0x0D09, 0xFFFF },  /* R3337  - Interrupt Status 3 Mask */
+       { 0x0D0A, 0xFFFF },  /* R3338  - Interrupt Status 4 Mask */
+       { 0x0D1F, 0x0000 },  /* R3359  - Interrupt Control */
+       { 0x0D20, 0xFFFF },  /* R3360  - IRQ Debounce 1 */
+       { 0x0D21, 0xFFFF },  /* R3361  - IRQ Debounce 2 */
+       { 0x0E00, 0x0000 },  /* R3584  - FX_Ctrl */
+       { 0x0E10, 0x6318 },  /* R3600  - EQ1_1 */
+       { 0x0E11, 0x6300 },  /* R3601  - EQ1_2 */
+       { 0x0E12, 0x0FC8 },  /* R3602  - EQ1_3 */
+       { 0x0E13, 0x03FE },  /* R3603  - EQ1_4 */
+       { 0x0E14, 0x00E0 },  /* R3604  - EQ1_5 */
+       { 0x0E15, 0x1EC4 },  /* R3605  - EQ1_6 */
+       { 0x0E16, 0xF136 },  /* R3606  - EQ1_7 */
+       { 0x0E17, 0x0409 },  /* R3607  - EQ1_8 */
+       { 0x0E18, 0x04CC },  /* R3608  - EQ1_9 */
+       { 0x0E19, 0x1C9B },  /* R3609  - EQ1_10 */
+       { 0x0E1A, 0xF337 },  /* R3610  - EQ1_11 */
+       { 0x0E1B, 0x040B },  /* R3611  - EQ1_12 */
+       { 0x0E1C, 0x0CBB },  /* R3612  - EQ1_13 */
+       { 0x0E1D, 0x16F8 },  /* R3613  - EQ1_14 */
+       { 0x0E1E, 0xF7D9 },  /* R3614  - EQ1_15 */
+       { 0x0E1F, 0x040A },  /* R3615  - EQ1_16 */
+       { 0x0E20, 0x1F14 },  /* R3616  - EQ1_17 */
+       { 0x0E21, 0x058C },  /* R3617  - EQ1_18 */
+       { 0x0E22, 0x0563 },  /* R3618  - EQ1_19 */
+       { 0x0E23, 0x4000 },  /* R3619  - EQ1_20 */
+       { 0x0E26, 0x6318 },  /* R3622  - EQ2_1 */
+       { 0x0E27, 0x6300 },  /* R3623  - EQ2_2 */
+       { 0x0E28, 0x0FC8 },  /* R3624  - EQ2_3 */
+       { 0x0E29, 0x03FE },  /* R3625  - EQ2_4 */
+       { 0x0E2A, 0x00E0 },  /* R3626  - EQ2_5 */
+       { 0x0E2B, 0x1EC4 },  /* R3627  - EQ2_6 */
+       { 0x0E2C, 0xF136 },  /* R3628  - EQ2_7 */
+       { 0x0E2D, 0x0409 },  /* R3629  - EQ2_8 */
+       { 0x0E2E, 0x04CC },  /* R3630  - EQ2_9 */
+       { 0x0E2F, 0x1C9B },  /* R3631  - EQ2_10 */
+       { 0x0E30, 0xF337 },  /* R3632  - EQ2_11 */
+       { 0x0E31, 0x040B },  /* R3633  - EQ2_12 */
+       { 0x0E32, 0x0CBB },  /* R3634  - EQ2_13 */
+       { 0x0E33, 0x16F8 },  /* R3635  - EQ2_14 */
+       { 0x0E34, 0xF7D9 },  /* R3636  - EQ2_15 */
+       { 0x0E35, 0x040A },  /* R3637  - EQ2_16 */
+       { 0x0E36, 0x1F14 },  /* R3638  - EQ2_17 */
+       { 0x0E37, 0x058C },  /* R3639  - EQ2_18 */
+       { 0x0E38, 0x0563 },  /* R3640  - EQ2_19 */
+       { 0x0E39, 0x4000 },  /* R3641  - EQ2_20 */
+       { 0x0E3C, 0x6318 },  /* R3644  - EQ3_1 */
+       { 0x0E3D, 0x6300 },  /* R3645  - EQ3_2 */
+       { 0x0E3E, 0x0FC8 },  /* R3646  - EQ3_3 */
+       { 0x0E3F, 0x03FE },  /* R3647  - EQ3_4 */
+       { 0x0E40, 0x00E0 },  /* R3648  - EQ3_5 */
+       { 0x0E41, 0x1EC4 },  /* R3649  - EQ3_6 */
+       { 0x0E42, 0xF136 },  /* R3650  - EQ3_7 */
+       { 0x0E43, 0x0409 },  /* R3651  - EQ3_8 */
+       { 0x0E44, 0x04CC },  /* R3652  - EQ3_9 */
+       { 0x0E45, 0x1C9B },  /* R3653  - EQ3_10 */
+       { 0x0E46, 0xF337 },  /* R3654  - EQ3_11 */
+       { 0x0E47, 0x040B },  /* R3655  - EQ3_12 */
+       { 0x0E48, 0x0CBB },  /* R3656  - EQ3_13 */
+       { 0x0E49, 0x16F8 },  /* R3657  - EQ3_14 */
+       { 0x0E4A, 0xF7D9 },  /* R3658  - EQ3_15 */
+       { 0x0E4B, 0x040A },  /* R3659  - EQ3_16 */
+       { 0x0E4C, 0x1F14 },  /* R3660  - EQ3_17 */
+       { 0x0E4D, 0x058C },  /* R3661  - EQ3_18 */
+       { 0x0E4E, 0x0563 },  /* R3662  - EQ3_19 */
+       { 0x0E4F, 0x4000 },  /* R3663  - EQ3_20 */
+       { 0x0E52, 0x6318 },  /* R3666  - EQ4_1 */
+       { 0x0E53, 0x6300 },  /* R3667  - EQ4_2 */
+       { 0x0E54, 0x0FC8 },  /* R3668  - EQ4_3 */
+       { 0x0E55, 0x03FE },  /* R3669  - EQ4_4 */
+       { 0x0E56, 0x00E0 },  /* R3670  - EQ4_5 */
+       { 0x0E57, 0x1EC4 },  /* R3671  - EQ4_6 */
+       { 0x0E58, 0xF136 },  /* R3672  - EQ4_7 */
+       { 0x0E59, 0x0409 },  /* R3673  - EQ4_8 */
+       { 0x0E5A, 0x04CC },  /* R3674  - EQ4_9 */
+       { 0x0E5B, 0x1C9B },  /* R3675  - EQ4_10 */
+       { 0x0E5C, 0xF337 },  /* R3676  - EQ4_11 */
+       { 0x0E5D, 0x040B },  /* R3677  - EQ4_12 */
+       { 0x0E5E, 0x0CBB },  /* R3678  - EQ4_13 */
+       { 0x0E5F, 0x16F8 },  /* R3679  - EQ4_14 */
+       { 0x0E60, 0xF7D9 },  /* R3680  - EQ4_15 */
+       { 0x0E61, 0x040A },  /* R3681  - EQ4_16 */
+       { 0x0E62, 0x1F14 },  /* R3682  - EQ4_17 */
+       { 0x0E63, 0x058C },  /* R3683  - EQ4_18 */
+       { 0x0E64, 0x0563 },  /* R3684  - EQ4_19 */
+       { 0x0E65, 0x4000 },  /* R3685  - EQ4_20 */
+       { 0x0E80, 0x0018 },  /* R3712  - DRC1 ctrl1 */
+       { 0x0E81, 0x0933 },  /* R3713  - DRC1 ctrl2 */
+       { 0x0E82, 0x0018 },  /* R3714  - DRC1 ctrl3 */
+       { 0x0E83, 0x0000 },  /* R3715  - DRC1 ctrl4 */
+       { 0x0E84, 0x0000 },  /* R3716  - DRC1 ctrl5 */
+       { 0x0EC0, 0x0000 },  /* R3776  - HPLPF1_1 */
+       { 0x0EC1, 0x0000 },  /* R3777  - HPLPF1_2 */
+       { 0x0EC4, 0x0000 },  /* R3780  - HPLPF2_1 */
+       { 0x0EC5, 0x0000 },  /* R3781  - HPLPF2_2 */
+       { 0x0EC8, 0x0000 },  /* R3784  - HPLPF3_1 */
+       { 0x0EC9, 0x0000 },  /* R3785  - HPLPF3_2 */
+       { 0x0ECC, 0x0000 },  /* R3788  - HPLPF4_1 */
+       { 0x0ECD, 0x0000 },  /* R3789  - HPLPF4_2 */
 };
index 42d9039..a234b70 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/gcd.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/fixed.h>
 #include <linux/slab.h>
@@ -51,6 +50,7 @@ struct wm5100_fll {
 
 /* codec private data */
 struct wm5100_priv {
+       struct regmap *regmap;
        struct snd_soc_codec *codec;
 
        struct regulator_bulk_data core_supplies[WM5100_NUM_CORE_SUPPLIES];
@@ -204,17 +204,15 @@ static void wm5100_free_sr(struct snd_soc_codec *codec, int rate)
        }
 }
 
-static int wm5100_reset(struct snd_soc_codec *codec)
+static int wm5100_reset(struct wm5100_priv *wm5100)
 {
-       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
-
        if (wm5100->pdata.reset) {
                gpio_set_value_cansleep(wm5100->pdata.reset, 0);
                gpio_set_value_cansleep(wm5100->pdata.reset, 1);
 
                return 0;
        } else {
-               return snd_soc_write(codec, WM5100_SOFTWARE_RESET, 0);
+               return regmap_write(wm5100->regmap, WM5100_SOFTWARE_RESET, 0);
        }
 }
 
@@ -954,7 +952,7 @@ SND_SOC_DAPM_INPUT("IN3L"),
 SND_SOC_DAPM_INPUT("IN3R"),
 SND_SOC_DAPM_INPUT("IN4L"),
 SND_SOC_DAPM_INPUT("IN4R"),
-SND_SOC_DAPM_INPUT("TONE"),
+SND_SOC_DAPM_SIGGEN("TONE"),
 
 SND_SOC_DAPM_PGA_E("IN1L PGA", WM5100_INPUT_ENABLES, WM5100_IN1L_ENA_SHIFT, 0,
                   NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
@@ -1375,7 +1373,7 @@ static int wm5100_set_bias_level(struct snd_soc_codec *codec,
                                msleep(2);
                        }
 
-                       codec->cache_only = false;
+                       regcache_cache_only(wm5100->regmap, false);
 
                        switch (wm5100->rev) {
                        case 0:
@@ -1399,7 +1397,7 @@ static int wm5100_set_bias_level(struct snd_soc_codec *codec,
                                break;
                        }
 
-                       snd_soc_cache_sync(codec);
+                       regcache_sync(wm5100->regmap);
                }
                break;
 
@@ -1662,7 +1660,7 @@ static int wm5100_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_dai_ops wm5100_dai_ops = {
+static const struct snd_soc_dai_ops wm5100_dai_ops = {
        .set_fmt = wm5100_set_fmt,
        .hw_params = wm5100_hw_params,
 };
@@ -1993,6 +1991,9 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
        else
                timeout = 50;
 
+       snd_soc_update_bits(codec, WM5100_CLOCKING_3, WM5100_SYSCLK_ENA,
+                           WM5100_SYSCLK_ENA);
+
        /* Poll for the lock; will use interrupt when we can test */
        for (i = 0; i < timeout; i++) {
                if (i2c->irq) {
@@ -2350,24 +2351,22 @@ static inline struct wm5100_priv *gpio_to_wm5100(struct gpio_chip *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);
+       regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset,
+                          WM5100_GP1_LVL, !!value << WM5100_GP1_LVL_SHIFT);
 }
 
 static int wm5100_gpio_direction_out(struct gpio_chip *chip,
                                     unsigned offset, int value)
 {
        struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
-       struct snd_soc_codec *codec = wm5100->codec;
        int val, ret;
 
        val = (1 << WM5100_GP1_FN_SHIFT) | (!!value << WM5100_GP1_LVL_SHIFT);
 
-       ret = snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset,
-                                 WM5100_GP1_FN_MASK | WM5100_GP1_DIR |
-                                 WM5100_GP1_LVL, val);
+       ret = regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset,
+                                WM5100_GP1_FN_MASK | WM5100_GP1_DIR |
+                                WM5100_GP1_LVL, val);
        if (ret < 0)
                return ret;
        else
@@ -2377,25 +2376,24 @@ static int wm5100_gpio_direction_out(struct gpio_chip *chip,
 static int wm5100_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
        struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
-       struct snd_soc_codec *codec = wm5100->codec;
+       unsigned int reg;
        int ret;
 
-       ret = snd_soc_read(codec, WM5100_GPIO_CTRL_1 + offset);
+       ret = regmap_read(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset, &reg);
        if (ret < 0)
                return ret;
 
-       return (ret & WM5100_GP1_LVL) != 0;
+       return (reg & WM5100_GP1_LVL) != 0;
 }
 
 static int wm5100_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
 {
        struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
-       struct snd_soc_codec *codec = wm5100->codec;
 
-       return snd_soc_update_bits(codec, WM5100_GPIO_CTRL_1 + offset,
-                                  WM5100_GP1_FN_MASK | WM5100_GP1_DIR,
-                                  (1 << WM5100_GP1_FN_SHIFT) |
-                                  (1 << WM5100_GP1_DIR_SHIFT));
+       return regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset,
+                                 WM5100_GP1_FN_MASK | WM5100_GP1_DIR,
+                                 (1 << WM5100_GP1_FN_SHIFT) |
+                                 (1 << WM5100_GP1_DIR_SHIFT));
 }
 
 static struct gpio_chip wm5100_template_chip = {
@@ -2408,14 +2406,14 @@ static struct gpio_chip wm5100_template_chip = {
        .can_sleep              = 1,
 };
 
-static void wm5100_init_gpio(struct snd_soc_codec *codec)
+static void wm5100_init_gpio(struct i2c_client *i2c)
 {
-       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
        int ret;
 
        wm5100->gpio_chip = wm5100_template_chip;
        wm5100->gpio_chip.ngpio = 6;
-       wm5100->gpio_chip.dev = codec->dev;
+       wm5100->gpio_chip.dev = &i2c->dev;
 
        if (wm5100->pdata.gpio_base)
                wm5100->gpio_chip.base = wm5100->pdata.gpio_base;
@@ -2424,24 +2422,24 @@ static void wm5100_init_gpio(struct snd_soc_codec *codec)
 
        ret = gpiochip_add(&wm5100->gpio_chip);
        if (ret != 0)
-               dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
+               dev_err(&i2c->dev, "Failed to add GPIOs: %d\n", ret);
 }
 
-static void wm5100_free_gpio(struct snd_soc_codec *codec)
+static void wm5100_free_gpio(struct i2c_client *i2c)
 {
-       struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+       struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
        int ret;
 
        ret = gpiochip_remove(&wm5100->gpio_chip);
        if (ret != 0)
-               dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
+               dev_err(&i2c->dev, "Failed to remove GPIOs: %d\n", ret);
 }
 #else
-static void wm5100_init_gpio(struct snd_soc_codec *codec)
+static void wm5100_init_gpio(struct i2c_client *i2c)
 {
 }
 
-static void wm5100_free_gpio(struct snd_soc_codec *codec)
+static void wm5100_free_gpio(struct i2c_client *i2c)
 {
 }
 #endif
@@ -2453,131 +2451,21 @@ static int wm5100_probe(struct snd_soc_codec *codec)
        int ret, i, irq_flags;
 
        wm5100->codec = codec;
+       codec->control_data = wm5100->regmap;
 
-       ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
+       ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
        }
 
-       for (i = 0; i < ARRAY_SIZE(wm5100->core_supplies); i++)
-               wm5100->core_supplies[i].supply = wm5100_core_supply_names[i];
-
-       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;
-       }
+       regcache_cache_only(wm5100->regmap, true);
 
-       if (wm5100->pdata.ldo_ena) {
-               ret = gpio_request_one(wm5100->pdata.ldo_ena,
-                                      GPIOF_OUT_INIT_HIGH, "WM5100 LDOENA");
-               if (ret < 0) {
-                       dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
-                               wm5100->pdata.ldo_ena, ret);
-                       goto err_enable;
-               }
-               msleep(2);
-       }
-
-       if (wm5100->pdata.reset) {
-               ret = gpio_request_one(wm5100->pdata.reset,
-                                      GPIOF_OUT_INIT_HIGH, "WM5100 /RESET");
-               if (ret < 0) {
-                       dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
-                               wm5100->pdata.reset, ret);
-                       goto err_ldo;
-               }
-       }
-
-       ret = snd_soc_read(codec, WM5100_SOFTWARE_RESET);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to read ID register\n");
-               goto err_reset;
-       }
-       switch (ret) {
-       case 0x8997:
-       case 0x5100:
-               break;
-
-       default:
-               dev_err(codec->dev, "Device is not a WM5100, ID is %x\n", ret);
-               ret = -EINVAL;
-               goto err_reset;
-       }
-
-       ret = snd_soc_read(codec, WM5100_DEVICE_REVISION);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to read revision register\n");
-               goto err_reset;
-       }
-       wm5100->rev = ret & WM5100_DEVICE_REVISION_MASK;
-
-       dev_info(codec->dev, "revision %c\n", wm5100->rev + 'A');
-
-       ret = wm5100_reset(codec);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to issue reset\n");
-               goto err_reset;
-       }
-
-       codec->cache_only = true;
-
-       wm5100_init_gpio(codec);
 
        for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++)
                snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU,
                                    WM5100_OUT_VU);
 
-       for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) {
-               snd_soc_update_bits(codec, WM5100_IN1L_CONTROL,
-                                   WM5100_IN1_MODE_MASK |
-                                   WM5100_IN1_DMIC_SUP_MASK,
-                                   (wm5100->pdata.in_mode[i] <<
-                                    WM5100_IN1_MODE_SHIFT) |
-                                   (wm5100->pdata.dmic_sup[i] <<
-                                    WM5100_IN1_DMIC_SUP_SHIFT));
-       }
-
-       for (i = 0; i < ARRAY_SIZE(wm5100->pdata.gpio_defaults); i++) {
-               if (!wm5100->pdata.gpio_defaults[i])
-                       continue;
-
-               snd_soc_write(codec, WM5100_GPIO_CTRL_1 + i,
-                             wm5100->pdata.gpio_defaults[i]);
-       }
-
        /* Don't debounce interrupts to support use of SYSCLK only */
        snd_soc_write(codec, WM5100_IRQ_DEBOUNCE_1, 0);
        snd_soc_write(codec, WM5100_IRQ_DEBOUNCE_2, 0);
@@ -2662,29 +2550,6 @@ static int wm5100_probe(struct snd_soc_codec *codec)
 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;
 }
@@ -2700,20 +2565,6 @@ static int wm5100_remove(struct snd_soc_codec *codec)
        }
        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;
 }
 
@@ -2733,14 +2584,18 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5100 = {
        .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,
+static const struct regmap_config wm5100_regmap = {
+       .reg_bits = 16,
+       .val_bits = 16,
 
-       .volatile_register = wm5100_volatile_register,
-       .readable_register = wm5100_readable_register,
+       .max_register = WM5100_MAX_REGISTER,
+       .reg_defaults = wm5100_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm5100_reg_defaults),
+       .volatile_reg = wm5100_volatile_register,
+       .readable_reg = wm5100_readable_register,
+       .cache_type = REGCACHE_RBTREE,
 };
 
 static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
@@ -2748,12 +2603,22 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
 {
        struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev);
        struct wm5100_priv *wm5100;
+       unsigned int reg;
        int ret, i;
 
-       wm5100 = kzalloc(sizeof(struct wm5100_priv), GFP_KERNEL);
+       wm5100 = devm_kzalloc(&i2c->dev, sizeof(struct wm5100_priv),
+                             GFP_KERNEL);
        if (wm5100 == NULL)
                return -ENOMEM;
 
+       wm5100->regmap = regmap_init_i2c(i2c, &wm5100_regmap);
+       if (IS_ERR(wm5100->regmap)) {
+               ret = PTR_ERR(wm5100->regmap);
+               dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               goto err;
+       }
+
        for (i = 0; i < ARRAY_SIZE(wm5100->fll); i++)
                init_completion(&wm5100->fll[i].lock);
 
@@ -2762,21 +2627,178 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
 
        i2c_set_clientdata(i2c, wm5100);
 
+       for (i = 0; i < ARRAY_SIZE(wm5100->core_supplies); i++)
+               wm5100->core_supplies[i].supply = wm5100_core_supply_names[i];
+
+       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm5100->core_supplies),
+                                wm5100->core_supplies);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
+                       ret);
+               goto err_regmap;
+       }
+
+       wm5100->cpvdd = regulator_get(&i2c->dev, "CPVDD");
+       if (IS_ERR(wm5100->cpvdd)) {
+               ret = PTR_ERR(wm5100->cpvdd);
+               dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret);
+               goto err_core;
+       }
+
+       wm5100->dbvdd2 = regulator_get(&i2c->dev, "DBVDD2");
+       if (IS_ERR(wm5100->dbvdd2)) {
+               ret = PTR_ERR(wm5100->dbvdd2);
+               dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret);
+               goto err_cpvdd;
+       }
+
+       wm5100->dbvdd3 = regulator_get(&i2c->dev, "DBVDD3");
+       if (IS_ERR(wm5100->dbvdd3)) {
+               ret = PTR_ERR(wm5100->dbvdd3);
+               dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret);
+               goto err_dbvdd2;
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
+                                   wm5100->core_supplies);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
+                       ret);
+               goto err_dbvdd3;
+       }
+
+       if (wm5100->pdata.ldo_ena) {
+               ret = gpio_request_one(wm5100->pdata.ldo_ena,
+                                      GPIOF_OUT_INIT_HIGH, "WM5100 LDOENA");
+               if (ret < 0) {
+                       dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
+                               wm5100->pdata.ldo_ena, ret);
+                       goto err_enable;
+               }
+               msleep(2);
+       }
+
+       if (wm5100->pdata.reset) {
+               ret = gpio_request_one(wm5100->pdata.reset,
+                                      GPIOF_OUT_INIT_HIGH, "WM5100 /RESET");
+               if (ret < 0) {
+                       dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
+                               wm5100->pdata.reset, ret);
+                       goto err_ldo;
+               }
+       }
+
+       ret = regmap_read(wm5100->regmap, WM5100_SOFTWARE_RESET, &reg);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to read ID register\n");
+               goto err_reset;
+       }
+       switch (reg) {
+       case 0x8997:
+       case 0x5100:
+               break;
+
+       default:
+               dev_err(&i2c->dev, "Device is not a WM5100, ID is %x\n", reg);
+               ret = -EINVAL;
+               goto err_reset;
+       }
+
+       ret = regmap_read(wm5100->regmap, WM5100_DEVICE_REVISION, &reg);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to read revision register\n");
+               goto err_reset;
+       }
+       wm5100->rev = reg & WM5100_DEVICE_REVISION_MASK;
+
+       dev_info(&i2c->dev, "revision %c\n", wm5100->rev + 'A');
+
+       ret = wm5100_reset(wm5100);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to issue reset\n");
+               goto err_reset;
+       }
+
+       wm5100_init_gpio(i2c);
+
+       for (i = 0; i < ARRAY_SIZE(wm5100->pdata.gpio_defaults); i++) {
+               if (!wm5100->pdata.gpio_defaults[i])
+                       continue;
+
+               regmap_write(wm5100->regmap, WM5100_GPIO_CTRL_1 + i,
+                            wm5100->pdata.gpio_defaults[i]);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) {
+               regmap_update_bits(wm5100->regmap, WM5100_IN1L_CONTROL,
+                                  WM5100_IN1_MODE_MASK |
+                                  WM5100_IN1_DMIC_SUP_MASK,
+                                  (wm5100->pdata.in_mode[i] <<
+                                   WM5100_IN1_MODE_SHIFT) |
+                                  (wm5100->pdata.dmic_sup[i] <<
+                                   WM5100_IN1_DMIC_SUP_SHIFT));
+       }
+
        ret = snd_soc_register_codec(&i2c->dev,
                                     &soc_codec_dev_wm5100, wm5100_dai,
                                     ARRAY_SIZE(wm5100_dai));
        if (ret < 0) {
                dev_err(&i2c->dev, "Failed to register WM5100: %d\n", ret);
-               kfree(wm5100);
+               goto err_reset;
        }
 
        return ret;
+
+err_reset:
+       wm5100_free_gpio(i2c);
+       if (wm5100->pdata.reset) {
+               gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+               gpio_free(wm5100->pdata.reset);
+       }
+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);
+err_regmap:
+       regmap_exit(wm5100->regmap);
+err:
+       return ret;
 }
 
 static __devexit int wm5100_i2c_remove(struct i2c_client *client)
 {
+       struct wm5100_priv *wm5100 = i2c_get_clientdata(client);
+
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+       wm5100_free_gpio(client);
+       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);
+       regmap_exit(wm5100->regmap);
+
        return 0;
 }
 
index 9707596..25cb601 100644 (file)
@@ -15,6 +15,7 @@
 #define WM5100_ASOC_H
 
 #include <sound/soc.h>
+#include <linux/regmap.h>
 
 int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
 
@@ -5147,9 +5148,9 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
 #define WM5100_DSP3_ZM_END_SHIFT                     0  /* DSP3_ZM_END - [15:0] */
 #define WM5100_DSP3_ZM_END_WIDTH                    16  /* DSP3_ZM_END - [15:0] */
 
-int wm5100_readable_register(struct snd_soc_codec *codec, unsigned int reg);
-int wm5100_volatile_register(struct snd_soc_codec *codec, unsigned int reg);
+bool wm5100_readable_register(struct device *dev, unsigned int reg);
+bool wm5100_volatile_register(struct device *dev, unsigned int reg);
 
-extern u16 wm5100_reg_defaults[WM5100_MAX_REGISTER + 1];
+extern struct reg_default wm5100_reg_defaults[WM5100_REGISTER_COUNT];
 
 #endif
index 35f3ad8..8c4c959 100644 (file)
@@ -696,7 +696,7 @@ static const struct snd_soc_dapm_widget wm8350_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("IN3L"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8350_dapm_routes[] = {
 
        /* left playback mixer */
        {"Left Playback Mixer", "Playback Switch", "Left DAC"},
@@ -777,29 +777,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Beep", NULL, "IN3R PGA"},
 };
 
-static int wm8350_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-       int ret;
-
-       ret = snd_soc_dapm_new_controls(dapm,
-                                       wm8350_dapm_widgets,
-                                       ARRAY_SIZE(wm8350_dapm_widgets));
-       if (ret != 0) {
-               dev_err(codec->dev, "dapm control register failed\n");
-               return ret;
-       }
-
-       /* set up audio paths */
-       ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-       if (ret != 0) {
-               dev_err(codec->dev, "DAPM route register failed\n");
-               return ret;
-       }
-
-       return 0;
-}
-
 static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai,
                                 int clk_id, unsigned int freq, int dir)
 {
@@ -1315,7 +1292,7 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-static int wm8350_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8350_suspend(struct snd_soc_codec *codec)
 {
        wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -1511,7 +1488,7 @@ EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect);
                        SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8350_dai_ops = {
+static const struct snd_soc_dai_ops wm8350_dai_ops = {
         .hw_params     = wm8350_pcm_hw_params,
         .digital_mute  = wm8350_mute,
         .trigger       = wm8350_pcm_trigger,
@@ -1553,7 +1530,8 @@ static  int wm8350_codec_probe(struct snd_soc_codec *codec)
                return -EINVAL;
        }
 
-       priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL);
+       priv = devm_kzalloc(codec->dev, sizeof(struct wm8350_data),
+                           GFP_KERNEL);
        if (priv == NULL)
                return -ENOMEM;
        snd_soc_codec_set_drvdata(codec, priv);
@@ -1564,7 +1542,7 @@ static  int wm8350_codec_probe(struct snd_soc_codec *codec)
        ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
                                 priv->supplies);
        if (ret != 0)
-               goto err_priv;
+               return ret;
 
        wm8350->codec.codec = codec;
        codec->control_data = wm8350;
@@ -1633,17 +1611,9 @@ static  int wm8350_codec_probe(struct snd_soc_codec *codec)
                            wm8350_mic_handler, 0, "Microphone detect", priv);
 
 
-       snd_soc_add_controls(codec, wm8350_snd_controls,
-                               ARRAY_SIZE(wm8350_snd_controls));
-       wm8350_add_widgets(codec);
-
        wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
-
-err_priv:
-       kfree(priv);
-       return ret;
 }
 
 static int  wm8350_codec_remove(struct snd_soc_codec *codec)
@@ -1676,7 +1646,7 @@ static int  wm8350_codec_remove(struct snd_soc_codec *codec)
        wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
 
        regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
-       kfree(priv);
+
        return 0;
 }
 
@@ -1688,6 +1658,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8350 = {
        .read = wm8350_codec_read,
        .write = wm8350_codec_write,
        .set_bias_level = wm8350_set_bias_level,
+
+       .controls = wm8350_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8350_snd_controls),
+       .dapm_widgets = wm8350_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8350_dapm_widgets),
+       .dapm_routes = wm8350_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8350_dapm_routes),
 };
 
 static int __devinit wm8350_probe(struct platform_device *pdev)
@@ -1711,17 +1688,7 @@ static struct platform_driver wm8350_codec_driver = {
        .remove = __devexit_p(wm8350_remove),
 };
 
-static __init int wm8350_init(void)
-{
-       return platform_driver_register(&wm8350_codec_driver);
-}
-module_init(wm8350_init);
-
-static __exit void wm8350_exit(void)
-{
-       platform_driver_unregister(&wm8350_codec_driver);
-}
-module_exit(wm8350_exit);
+module_platform_driver(wm8350_codec_driver);
 
 MODULE_DESCRIPTION("ASoC WM8350 driver");
 MODULE_AUTHOR("Liam Girdwood");
index dc13be2..898979d 100644 (file)
@@ -353,13 +353,6 @@ SOC_SINGLE("RIN34 Mute Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME,
 
 };
 
-/* add non dapm controls */
-static int wm8400_add_controls(struct snd_soc_codec *codec)
-{
-       return snd_soc_add_controls(codec, wm8400_snd_controls,
-                               ARRAY_SIZE(wm8400_snd_controls));
-}
-
 /*
  * _DAPM_ Controls
  */
@@ -766,8 +759,8 @@ SND_SOC_DAPM_PGA("ROPGA", WM8400_POWER_MANAGEMENT_3, WM8400_ROPGA_ENA_SHIFT, 0,
        NULL, 0),
 
 /* MICBIAS */
-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8400_POWER_MANAGEMENT_1,
-       WM8400_MIC1BIAS_ENA_SHIFT, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8400_POWER_MANAGEMENT_1,
+                   WM8400_MIC1BIAS_ENA_SHIFT, 0, NULL, 0),
 
 SND_SOC_DAPM_OUTPUT("LON"),
 SND_SOC_DAPM_OUTPUT("LOP"),
@@ -783,7 +776,7 @@ SND_SOC_DAPM_OUTPUT("RON"),
 SND_SOC_DAPM_OUTPUT("Internal DAC Sink"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8400_dapm_routes[] = {
        /* Make DACs turn on when playing even if not mixed into any outputs */
        {"Internal DAC Sink", NULL, "Left DAC"},
        {"Internal DAC Sink", NULL, "Right DAC"},
@@ -909,17 +902,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"RON", NULL, "RONMIX"},
 };
 
-static int wm8400_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_new_controls(dapm, wm8400_dapm_widgets,
-                                 ARRAY_SIZE(wm8400_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-       return 0;
-}
-
 /*
  * Clock after FLL and dividers
  */
@@ -1059,7 +1041,7 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
        wm8400_write(codec, WM8400_FLL_CONTROL_3, factors.n);
 
        reg = wm8400_read(codec, WM8400_FLL_CONTROL_4);
-       reg &= WM8400_FLL_OUTDIV_MASK;
+       reg &= ~WM8400_FLL_OUTDIV_MASK;
        reg |= factors.outdiv;
        wm8400_write(codec, WM8400_FLL_CONTROL_4, reg);
 
@@ -1316,7 +1298,7 @@ static int wm8400_set_bias_level(struct snd_soc_codec *codec,
 #define WM8400_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
        SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8400_dai_ops = {
+static const struct snd_soc_dai_ops wm8400_dai_ops = {
        .hw_params = wm8400_hw_params,
        .digital_mute = wm8400_mute,
        .set_fmt = wm8400_set_dai_fmt,
@@ -1352,7 +1334,7 @@ static struct snd_soc_dai_driver wm8400_dai = {
        .ops = &wm8400_dai_ops,
 };
 
-static int wm8400_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8400_suspend(struct snd_soc_codec *codec)
 {
        wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1383,7 +1365,8 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
        int ret;
        u16 reg;
 
-       priv = kzalloc(sizeof(struct wm8400_priv), GFP_KERNEL);
+       priv = devm_kzalloc(codec->dev, sizeof(struct wm8400_priv),
+                           GFP_KERNEL);
        if (priv == NULL)
                return -ENOMEM;
 
@@ -1395,7 +1378,7 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
                                 ARRAY_SIZE(power), &power[0]);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to get regulators: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        INIT_WORK(&priv->work, wm8400_probe_deferred);
@@ -1420,20 +1403,15 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
                ret = -EINVAL;
                goto err_regulator;
        }
-       wm8400_add_controls(codec);
-       wm8400_add_widgets(codec);
        return 0;
 
 err_regulator:
        regulator_bulk_free(ARRAY_SIZE(power), power);
-err:
-       kfree(priv);
        return ret;
 }
 
 static int  wm8400_codec_remove(struct snd_soc_codec *codec)
 {
-       struct wm8400_priv *priv = snd_soc_codec_get_drvdata(codec);
        u16 reg;
 
        reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1);
@@ -1441,7 +1419,6 @@ static int  wm8400_codec_remove(struct snd_soc_codec *codec)
                     reg & (~WM8400_CODEC_ENA));
 
        regulator_bulk_free(ARRAY_SIZE(power), power);
-       kfree(priv);
 
        return 0;
 }
@@ -1454,6 +1431,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8400 = {
        .read = wm8400_read,
        .write = wm8400_write,
        .set_bias_level = wm8400_set_bias_level,
+
+       .controls = wm8400_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8400_snd_controls),
+       .dapm_widgets = wm8400_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8400_dapm_widgets),
+       .dapm_routes = wm8400_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8400_dapm_routes),
 };
 
 static int __devinit wm8400_probe(struct platform_device *pdev)
@@ -1477,17 +1461,7 @@ static struct platform_driver wm8400_codec_driver = {
        .remove = __devexit_p(wm8400_remove),
 };
 
-static __init int wm8400_init(void)
-{
-       return platform_driver_register(&wm8400_codec_driver);
-}
-module_init(wm8400_init);
-
-static __exit void wm8400_exit(void)
-{
-       platform_driver_unregister(&wm8400_codec_driver);
-}
-module_exit(wm8400_exit);
+module_platform_driver(wm8400_codec_driver);
 
 MODULE_DESCRIPTION("ASoC WM8400 driver");
 MODULE_AUTHOR("Mark Brown");
index 07c9cc7..9166126 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
@@ -182,7 +181,7 @@ SND_SOC_DAPM_OUTPUT("SPKOUTP"),
 SND_SOC_DAPM_OUTPUT("SPKOUTN"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8510_dapm_routes[] = {
        /* Mono output mixer */
        {"Mono Mixer", "PCM Playback Switch", "DAC"},
        {"Mono Mixer", "Aux Playback Switch", "Aux Input"},
@@ -214,17 +213,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"ADC", NULL, "Boost Mixer"},
 };
 
-static int wm8510_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_new_controls(dapm, wm8510_dapm_widgets,
-                                 ARRAY_SIZE(wm8510_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-       return 0;
-}
-
 struct pll_ {
        unsigned int pre_div:4; /* prescale - 1 */
        unsigned int n:4;
@@ -509,7 +497,7 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec,
 #define WM8510_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8510_dai_ops = {
+static const struct snd_soc_dai_ops wm8510_dai_ops = {
        .hw_params      = wm8510_pcm_hw_params,
        .digital_mute   = wm8510_mute,
        .set_fmt        = wm8510_set_dai_fmt,
@@ -535,7 +523,7 @@ static struct snd_soc_dai_driver wm8510_dai = {
        .symmetric_rates = 1,
 };
 
-static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8510_suspend(struct snd_soc_codec *codec)
 {
        wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -562,9 +550,6 @@ static int wm8510_probe(struct snd_soc_codec *codec)
 
        /* power on device */
        wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-       snd_soc_add_controls(codec, wm8510_snd_controls,
-                               ARRAY_SIZE(wm8510_snd_controls));
-       wm8510_add_widgets(codec);
 
        return ret;
 }
@@ -588,6 +573,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8510 = {
        .reg_cache_size = ARRAY_SIZE(wm8510_reg),
        .reg_word_size = sizeof(u16),
        .reg_cache_default =wm8510_reg,
+
+       .controls = wm8510_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8510_snd_controls),
+       .dapm_widgets = wm8510_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8510_dapm_widgets),
+       .dapm_routes = wm8510_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8510_dapm_routes),
 };
 
 static const struct of_device_id wm8510_of_match[] = {
@@ -667,7 +659,7 @@ MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id);
 
 static struct i2c_driver wm8510_i2c_driver = {
        .driver = {
-               .name = "wm8510-codec",
+               .name = "wm8510",
                .owner = THIS_MODULE,
                .of_match_table = wm8510_of_match,
        },
index db7a681..7fea2c3 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
@@ -365,7 +364,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec,
 #define WM8523_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8523_dai_ops = {
+static const struct snd_soc_dai_ops wm8523_dai_ops = {
        .startup        = wm8523_startup,
        .hw_params      = wm8523_hw_params,
        .set_sysclk     = wm8523_set_dai_sysclk,
@@ -385,7 +384,7 @@ static struct snd_soc_dai_driver wm8523_dai = {
 };
 
 #ifdef CONFIG_PM
-static int wm8523_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8523_suspend(struct snd_soc_codec *codec)
 {
        wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
index 8212b3c..b1c8d3d 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
@@ -273,7 +272,7 @@ SND_SOC_DAPM_INPUT("AINL"),
 SND_SOC_DAPM_INPUT("AINR"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8580_dapm_routes[] = {
        { "VOUT1L", NULL, "DAC1" },
        { "VOUT1R", NULL, "DAC1" },
 
@@ -287,17 +286,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
        { "ADC", NULL, "AINR" },
 };
 
-static int wm8580_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_new_controls(dapm, wm8580_dapm_widgets,
-                                 ARRAY_SIZE(wm8580_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-       return 0;
-}
-
 /* PLL divisors */
 struct _pll_div {
        u32 prescale:1;
@@ -776,7 +764,7 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
 #define WM8580_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8580_dai_ops_playback = {
+static const struct snd_soc_dai_ops wm8580_dai_ops_playback = {
        .set_sysclk     = wm8580_set_sysclk,
        .hw_params      = wm8580_paif_hw_params,
        .set_fmt        = wm8580_set_paif_dai_fmt,
@@ -785,7 +773,7 @@ static struct snd_soc_dai_ops wm8580_dai_ops_playback = {
        .digital_mute   = wm8580_digital_mute,
 };
 
-static struct snd_soc_dai_ops wm8580_dai_ops_capture = {
+static const struct snd_soc_dai_ops wm8580_dai_ops_capture = {
        .set_sysclk     = wm8580_set_sysclk,
        .hw_params      = wm8580_paif_hw_params,
        .set_fmt        = wm8580_set_paif_dai_fmt,
@@ -857,10 +845,6 @@ static int wm8580_probe(struct snd_soc_codec *codec)
 
        wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       snd_soc_add_controls(codec, wm8580_snd_controls,
-                            ARRAY_SIZE(wm8580_snd_controls));
-       wm8580_add_widgets(codec);
-
        return 0;
 
 err_regulator_enable:
@@ -890,6 +874,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8580 = {
        .reg_cache_size = ARRAY_SIZE(wm8580_reg),
        .reg_word_size = sizeof(u16),
        .reg_cache_default = wm8580_reg,
+
+       .controls = wm8580_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8580_snd_controls),
+       .dapm_widgets = wm8580_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8580_dapm_widgets),
+       .dapm_routes = wm8580_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8580_dapm_routes),
 };
 
 static const struct of_device_id wm8580_of_match[] = {
index 076bdb9..0b76d1d 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
@@ -318,7 +317,7 @@ static int wm8711_set_bias_level(struct snd_soc_codec *codec,
 #define WM8711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
        SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8711_ops = {
+static const struct snd_soc_dai_ops wm8711_ops = {
        .prepare = wm8711_pcm_prepare,
        .hw_params = wm8711_hw_params,
        .shutdown = wm8711_shutdown,
@@ -339,7 +338,7 @@ static struct snd_soc_dai_driver wm8711_dai = {
        .ops = &wm8711_ops,
 };
 
-static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8711_suspend(struct snd_soc_codec *codec)
 {
        snd_soc_write(codec, WM8711_ACTIVE, 0x0);
        wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -375,9 +374,6 @@ static int wm8711_probe(struct snd_soc_codec *codec)
        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));
-
        return ret;
 
 }
@@ -398,6 +394,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8711 = {
        .reg_cache_size = ARRAY_SIZE(wm8711_reg),
        .reg_word_size = sizeof(u16),
        .reg_cache_default = wm8711_reg,
+       .controls = wm8711_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8711_snd_controls),
        .dapm_widgets = wm8711_dapm_widgets,
        .num_dapm_widgets = ARRAY_SIZE(wm8711_dapm_widgets),
        .dapm_routes = wm8711_intercon,
index 7488082..e817056 100644 (file)
@@ -59,7 +59,7 @@ static int __devexit wm8727_remove(struct platform_device *pdev)
 
 static struct platform_driver wm8727_codec_driver = {
        .driver = {
-                       .name = "wm8727-codec",
+                       .name = "wm8727",
                        .owner = THIS_MODULE,
        },
 
@@ -67,17 +67,7 @@ static struct platform_driver wm8727_codec_driver = {
        .remove = __devexit_p(wm8727_remove),
 };
 
-static int __init wm8727_init(void)
-{
-       return platform_driver_register(&wm8727_codec_driver);
-}
-module_init(wm8727_init);
-
-static void __exit wm8727_exit(void)
-{
-       platform_driver_unregister(&wm8727_codec_driver);
-}
-module_exit(wm8727_exit);
+module_platform_driver(wm8727_codec_driver);
 
 MODULE_DESCRIPTION("ASoC wm8727 driver");
 MODULE_AUTHOR("Neil Jones");
index 04b027e..fc3d59e 100644 (file)
@@ -196,7 +196,7 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec,
 #define WM8728_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
        SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8728_dai_ops = {
+static const struct snd_soc_dai_ops wm8728_dai_ops = {
        .hw_params      = wm8728_hw_params,
        .digital_mute   = wm8728_mute,
        .set_fmt        = wm8728_set_dai_fmt,
@@ -214,7 +214,7 @@ static struct snd_soc_dai_driver wm8728_dai = {
        .ops = &wm8728_dai_ops,
 };
 
-static int wm8728_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8728_suspend(struct snd_soc_codec *codec)
 {
        wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -243,9 +243,6 @@ static int wm8728_probe(struct snd_soc_codec *codec)
        /* power on device */
        wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       snd_soc_add_controls(codec, wm8728_snd_controls,
-                               ARRAY_SIZE(wm8728_snd_controls));
-
        return ret;
 }
 
@@ -264,6 +261,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8728 = {
        .reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults),
        .reg_word_size = sizeof(u16),
        .reg_cache_default = wm8728_reg_defaults,
+       .controls = wm8728_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8728_snd_controls),
        .dapm_widgets = wm8728_dapm_widgets,
        .num_dapm_widgets = ARRAY_SIZE(wm8728_dapm_widgets),
        .dapm_routes = wm8728_intercon,
index 7e5ec03..8821af7 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 #include <linux/of_device.h>
@@ -453,6 +452,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
                snd_soc_write(codec, WM8731_PWR, 0xffff);
                regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
                                       wm8731->supplies);
+               codec->cache_sync = 1;
                break;
        }
        codec->dapm.bias_level = level;
@@ -464,7 +464,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
 #define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
        SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8731_dai_ops = {
+static const struct snd_soc_dai_ops wm8731_dai_ops = {
        .hw_params      = wm8731_hw_params,
        .digital_mute   = wm8731_mute,
        .set_sysclk     = wm8731_set_dai_sysclk,
@@ -490,7 +490,7 @@ static struct snd_soc_dai_driver wm8731_dai = {
 };
 
 #ifdef CONFIG_PM
-static int wm8731_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8731_suspend(struct snd_soc_codec *codec)
 {
        wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -553,9 +553,6 @@ static int wm8731_probe(struct snd_soc_codec *codec)
        /* Disable bypass path by default */
        snd_soc_update_bits(codec, WM8731_APANA, 0x8, 0);
 
-       snd_soc_add_controls(codec, wm8731_snd_controls,
-                            ARRAY_SIZE(wm8731_snd_controls));
-
        /* Regulators will have been enabled by bias management */
        regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
 
@@ -595,6 +592,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8731 = {
        .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets),
        .dapm_routes = wm8731_intercon,
        .num_dapm_routes = ARRAY_SIZE(wm8731_intercon),
+       .controls =     wm8731_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8731_snd_controls),
 };
 
 static const struct of_device_id wm8731_of_match[] = {
index f6aef58..ff95e62 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
@@ -521,7 +520,7 @@ static int wm8737_set_bias_level(struct snd_soc_codec *codec,
 #define WM8737_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8737_dai_ops = {
+static const struct snd_soc_dai_ops wm8737_dai_ops = {
        .hw_params      = wm8737_hw_params,
        .set_sysclk     = wm8737_set_dai_sysclk,
        .set_fmt        = wm8737_set_dai_fmt,
@@ -540,7 +539,7 @@ static struct snd_soc_dai_driver wm8737_dai = {
 };
 
 #ifdef CONFIG_PM
-static int wm8737_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8737_suspend(struct snd_soc_codec *codec)
 {
        wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
index 57ad22a..3941f50 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
@@ -86,24 +85,13 @@ SND_SOC_DAPM_OUTPUT("VOUTRP"),
 SND_SOC_DAPM_OUTPUT("VOUTRN"),
 };
 
-static const struct snd_soc_dapm_route intercon[] = {
+static const struct snd_soc_dapm_route wm8741_dapm_routes[] = {
        { "VOUTLP", NULL, "DACL" },
        { "VOUTLN", NULL, "DACL" },
        { "VOUTRP", NULL, "DACR" },
        { "VOUTRN", NULL, "DACR" },
 };
 
-static int wm8741_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_new_controls(dapm, wm8741_dapm_widgets,
-                                 ARRAY_SIZE(wm8741_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
-
-       return 0;
-}
-
 static struct {
        int value;
        int ratio;
@@ -382,7 +370,7 @@ static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai,
 #define WM8741_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8741_dai_ops = {
+static const struct snd_soc_dai_ops wm8741_dai_ops = {
        .startup        = wm8741_startup,
        .hw_params      = wm8741_hw_params,
        .set_sysclk     = wm8741_set_dai_sysclk,
@@ -457,10 +445,6 @@ static int wm8741_probe(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, WM8741_DACRMSB_ATTENUATION,
                            WM8741_UPDATERM, WM8741_UPDATERM);
 
-       snd_soc_add_controls(codec, wm8741_snd_controls,
-                            ARRAY_SIZE(wm8741_snd_controls));
-       wm8741_add_widgets(codec);
-
        dev_dbg(codec->dev, "Successful registration\n");
        return ret;
 
@@ -489,6 +473,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8741 = {
        .reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults),
        .reg_word_size = sizeof(u16),
        .reg_cache_default = wm8741_reg_defaults,
+
+       .controls = wm8741_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8741_snd_controls),
+       .dapm_widgets = wm8741_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8741_dapm_widgets),
+       .dapm_routes = wm8741_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8741_dapm_routes),
 };
 
 static const struct of_device_id wm8741_of_match[] = {
@@ -504,7 +495,8 @@ static int wm8741_i2c_probe(struct i2c_client *i2c,
        struct wm8741_priv *wm8741;
        int ret;
 
-       wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL);
+       wm8741 = devm_kzalloc(&i2c->dev, sizeof(struct wm8741_priv),
+                             GFP_KERNEL);
        if (wm8741 == NULL)
                return -ENOMEM;
 
@@ -513,20 +505,13 @@ static int wm8741_i2c_probe(struct i2c_client *i2c,
 
        ret = snd_soc_register_codec(&i2c->dev,
                                     &soc_codec_dev_wm8741, &wm8741_dai, 1);
-       if (ret != 0)
-               goto err;
 
        return ret;
-
-err:
-       kfree(wm8741);
-       return ret;
 }
 
 static int wm8741_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -554,7 +539,8 @@ static int __devinit wm8741_spi_probe(struct spi_device *spi)
        struct wm8741_priv *wm8741;
        int ret;
 
-       wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL);
+       wm8741 = devm_kzalloc(&spi->dev, sizeof(struct wm8741_priv),
+                            GFP_KERNEL);
        if (wm8741 == NULL)
                return -ENOMEM;
 
@@ -563,15 +549,12 @@ static int __devinit wm8741_spi_probe(struct spi_device *spi)
 
        ret = snd_soc_register_codec(&spi->dev,
                        &soc_codec_dev_wm8741, &wm8741_dai, 1);
-       if (ret < 0)
-               kfree(wm8741);
        return ret;
 }
 
 static int __devexit wm8741_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
-       kfree(spi_get_drvdata(spi));
        return 0;
 }
 
index ca75a81..e4c50ce 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
@@ -302,7 +301,7 @@ static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("RINPUT3"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8750_dapm_routes[] = {
        /* left mixer */
        {"Left Mixer", "Playback Switch", "Left DAC"},
        {"Left Mixer", "Left Bypass Switch", "Left Line Mux"},
@@ -396,17 +395,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Right ADC", NULL, "Right ADC Mux"},
 };
 
-static int wm8750_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets,
-                                 ARRAY_SIZE(wm8750_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-       return 0;
-}
-
 struct _coeff_div {
        u32 mclk;
        u32 rate;
@@ -643,7 +631,7 @@ static int wm8750_set_bias_level(struct snd_soc_codec *codec,
 #define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
        SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8750_dai_ops = {
+static const struct snd_soc_dai_ops wm8750_dai_ops = {
        .hw_params      = wm8750_pcm_hw_params,
        .digital_mute   = wm8750_mute,
        .set_fmt        = wm8750_set_dai_fmt,
@@ -667,7 +655,7 @@ static struct snd_soc_dai_driver wm8750_dai = {
        .ops = &wm8750_dai_ops,
 };
 
-static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8750_suspend(struct snd_soc_codec *codec)
 {
        wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -709,9 +697,6 @@ static int wm8750_probe(struct snd_soc_codec *codec)
        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));
-       wm8750_add_widgets(codec);
        return ret;
 }
 
@@ -730,6 +715,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8750 = {
        .reg_cache_size = ARRAY_SIZE(wm8750_reg),
        .reg_word_size = sizeof(u16),
        .reg_cache_default = wm8750_reg,
+
+       .controls = wm8750_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8750_snd_controls),
+       .dapm_widgets = wm8750_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets),
+       .dapm_routes = wm8750_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8750_dapm_routes),
 };
 
 static const struct of_device_id wm8750_of_match[] = {
@@ -745,7 +737,8 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
        struct wm8750_priv *wm8750;
        int ret;
 
-       wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
+       wm8750 = devm_kzalloc(&spi->dev, sizeof(struct wm8750_priv),
+                             GFP_KERNEL);
        if (wm8750 == NULL)
                return -ENOMEM;
 
@@ -754,15 +747,12 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
 
        ret = snd_soc_register_codec(&spi->dev,
                        &soc_codec_dev_wm8750, &wm8750_dai, 1);
-       if (ret < 0)
-               kfree(wm8750);
        return ret;
 }
 
 static int __devexit wm8750_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
-       kfree(spi_get_drvdata(spi));
        return 0;
 }
 
@@ -792,7 +782,8 @@ static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
        struct wm8750_priv *wm8750;
        int ret;
 
-       wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
+       wm8750 = devm_kzalloc(&i2c->dev, sizeof(struct wm8750_priv),
+                             GFP_KERNEL);
        if (wm8750 == NULL)
                return -ENOMEM;
 
@@ -801,15 +792,12 @@ static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
 
        ret =  snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8750, &wm8750_dai, 1);
-       if (ret < 0)
-               kfree(wm8750);
        return ret;
 }
 
 static __devexit int wm8750_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
index a950471..b114c19 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/of_device.h>
-#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -190,6 +189,9 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
        struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
        u16 ioctl;
 
+       if (wm8753->dai_func == ucontrol->value.integer.value[0])
+               return 0;
+
        if (codec->active)
                return -EBUSY;
 
@@ -483,7 +485,7 @@ SND_SOC_DAPM_INPUT("MIC2"),
 SND_SOC_DAPM_VMID("VREF"),
 };
 
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8753_dapm_routes[] = {
        /* left mixer */
        {"Left Mixer", "Left Playback Switch", "Left DAC"},
        {"Left Mixer", "Voice Playback Switch", "Voice DAC"},
@@ -637,17 +639,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"ACOP", NULL, "ALC Mixer"},
 };
 
-static int wm8753_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_new_controls(dapm, wm8753_dapm_widgets,
-                                 ARRAY_SIZE(wm8753_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-       return 0;
-}
-
 /* PLL divisors */
 struct _pll_div {
        u32 div2:1;
@@ -1323,7 +1314,7 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec,
  * 3. Voice disabled - HIFI over HIFI
  * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture
  */
-static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode = {
+static const struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode = {
        .hw_params      = wm8753_i2s_hw_params,
        .digital_mute   = wm8753_mute,
        .set_fmt        = wm8753_hifi_set_dai_fmt,
@@ -1332,7 +1323,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode = {
        .set_sysclk     = wm8753_set_dai_sysclk,
 };
 
-static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode = {
+static const struct snd_soc_dai_ops wm8753_dai_ops_voice_mode = {
        .hw_params      = wm8753_pcm_hw_params,
        .digital_mute   = wm8753_mute,
        .set_fmt        = wm8753_voice_set_dai_fmt,
@@ -1389,7 +1380,7 @@ static void wm8753_work(struct work_struct *work)
        wm8753_set_bias_level(codec, dapm->bias_level);
 }
 
-static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8753_suspend(struct snd_soc_codec *codec)
 {
        wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -1464,10 +1455,6 @@ static int wm8753_probe(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, WM8753_LINVOL, 0x0100, 0x0100);
        snd_soc_update_bits(codec, WM8753_RINVOL, 0x0100, 0x0100);
 
-       snd_soc_add_controls(codec, wm8753_snd_controls,
-                            ARRAY_SIZE(wm8753_snd_controls));
-       wm8753_add_widgets(codec);
-
        return 0;
 }
 
@@ -1489,6 +1476,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8753 = {
        .reg_cache_size = ARRAY_SIZE(wm8753_reg),
        .reg_word_size = sizeof(u16),
        .reg_cache_default = wm8753_reg,
+
+       .controls = wm8753_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8753_snd_controls),
+       .dapm_widgets = wm8753_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8753_dapm_widgets),
+       .dapm_routes = wm8753_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8753_dapm_routes),
 };
 
 static const struct of_device_id wm8753_of_match[] = {
index aa05e65..19374a9 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/delay.h>
 #include <linux/of_device.h>
 #include <linux/pm.h>
-#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
@@ -528,7 +527,7 @@ static int wm8770_set_bias_level(struct snd_soc_codec *codec,
 #define WM8770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8770_dai_ops = {
+static const struct snd_soc_dai_ops wm8770_dai_ops = {
        .digital_mute = wm8770_mute,
        .hw_params = wm8770_hw_params,
        .set_fmt = wm8770_set_fmt,
@@ -556,7 +555,7 @@ static struct snd_soc_dai_driver wm8770_dai = {
 };
 
 #ifdef CONFIG_PM
-static int wm8770_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8770_suspend(struct snd_soc_codec *codec)
 {
        wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -691,13 +690,13 @@ static const struct of_device_id wm8770_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, wm8770_of_match);
 
-#if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8770_spi_probe(struct spi_device *spi)
 {
        struct wm8770_priv *wm8770;
        int ret;
 
-       wm8770 = kzalloc(sizeof(struct wm8770_priv), GFP_KERNEL);
+       wm8770 = devm_kzalloc(&spi->dev, sizeof(struct wm8770_priv),
+                             GFP_KERNEL);
        if (!wm8770)
                return -ENOMEM;
 
@@ -706,15 +705,13 @@ static int __devinit wm8770_spi_probe(struct spi_device *spi)
 
        ret = snd_soc_register_codec(&spi->dev,
                                     &soc_codec_dev_wm8770, &wm8770_dai, 1);
-       if (ret < 0)
-               kfree(wm8770);
+
        return ret;
 }
 
 static int __devexit wm8770_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
-       kfree(spi_get_drvdata(spi));
        return 0;
 }
 
@@ -727,28 +724,23 @@ static struct spi_driver wm8770_spi_driver = {
        .probe = wm8770_spi_probe,
        .remove = __devexit_p(wm8770_spi_remove)
 };
-#endif
 
 static int __init wm8770_modinit(void)
 {
        int ret = 0;
 
-#if defined(CONFIG_SPI_MASTER)
        ret = spi_register_driver(&wm8770_spi_driver);
        if (ret) {
                printk(KERN_ERR "Failed to register wm8770 SPI driver: %d\n",
                       ret);
        }
-#endif
        return ret;
 }
 module_init(wm8770_modinit);
 
 static void __exit wm8770_exit(void)
 {
-#if defined(CONFIG_SPI_MASTER)
        spi_unregister_driver(&wm8770_spi_driver);
-#endif
 }
 module_exit(wm8770_exit);
 
index bfdc523..38b4556 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/of_device.h>
-#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -327,14 +326,14 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec,
 #define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8776_dac_ops = {
+static const struct snd_soc_dai_ops wm8776_dac_ops = {
        .digital_mute   = wm8776_mute,
        .hw_params      = wm8776_hw_params,
        .set_fmt        = wm8776_set_fmt,
        .set_sysclk     = wm8776_set_sysclk,
 };
 
-static struct snd_soc_dai_ops wm8776_adc_ops = {
+static const struct snd_soc_dai_ops wm8776_adc_ops = {
        .hw_params      = wm8776_hw_params,
        .set_fmt        = wm8776_set_fmt,
        .set_sysclk     = wm8776_set_sysclk,
@@ -372,7 +371,7 @@ static struct snd_soc_dai_driver wm8776_dai[] = {
 };
 
 #ifdef CONFIG_PM
-static int wm8776_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8776_suspend(struct snd_soc_codec *codec)
 {
        wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -392,7 +391,6 @@ static int wm8776_resume(struct snd_soc_codec *codec)
 static int wm8776_probe(struct snd_soc_codec *codec)
 {
        struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec);
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
        int ret = 0;
 
        ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type);
@@ -414,12 +412,6 @@ static int wm8776_probe(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100);
        snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100);
 
-       snd_soc_add_controls(codec, wm8776_snd_controls,
-                            ARRAY_SIZE(wm8776_snd_controls));
-       snd_soc_dapm_new_controls(dapm, wm8776_dapm_widgets,
-                                 ARRAY_SIZE(wm8776_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes));
-
        return ret;
 }
 
@@ -439,6 +431,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8776 = {
        .reg_cache_size = ARRAY_SIZE(wm8776_reg),
        .reg_word_size = sizeof(u16),
        .reg_cache_default = wm8776_reg,
+
+       .controls = wm8776_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8776_snd_controls),
+       .dapm_widgets = wm8776_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8776_dapm_widgets),
+       .dapm_routes = routes,
+       .num_dapm_routes = ARRAY_SIZE(routes),
 };
 
 static const struct of_device_id wm8776_of_match[] = {
@@ -453,7 +452,8 @@ static int __devinit wm8776_spi_probe(struct spi_device *spi)
        struct wm8776_priv *wm8776;
        int ret;
 
-       wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);
+       wm8776 = devm_kzalloc(&spi->dev, sizeof(struct wm8776_priv),
+                             GFP_KERNEL);
        if (wm8776 == NULL)
                return -ENOMEM;
 
@@ -462,15 +462,13 @@ static int __devinit wm8776_spi_probe(struct spi_device *spi)
 
        ret = snd_soc_register_codec(&spi->dev,
                        &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai));
-       if (ret < 0)
-               kfree(wm8776);
+
        return ret;
 }
 
 static int __devexit wm8776_spi_remove(struct spi_device *spi)
 {
        snd_soc_unregister_codec(&spi->dev);
-       kfree(spi_get_drvdata(spi));
        return 0;
 }
 
@@ -492,7 +490,8 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
        struct wm8776_priv *wm8776;
        int ret;
 
-       wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);
+       wm8776 = devm_kzalloc(&i2c->dev, sizeof(struct wm8776_priv),
+                             GFP_KERNEL);
        if (wm8776 == NULL)
                return -ENOMEM;
 
@@ -501,15 +500,13 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
 
        ret =  snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai));
-       if (ret < 0)
-               kfree(wm8776);
+
        return ret;
 }
 
 static __devexit int wm8776_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
index f2ced71..3fdea98 100644 (file)
@@ -63,17 +63,7 @@ static struct platform_driver wm8782_codec_driver = {
        .remove = __devexit_p(wm8782_remove),
 };
 
-static int __init wm8782_init(void)
-{
-       return platform_driver_register(&wm8782_codec_driver);
-}
-module_init(wm8782_init);
-
-static void __exit wm8782_exit(void)
-{
-       platform_driver_unregister(&wm8782_codec_driver);
-}
-module_exit(wm8782_exit);
+module_platform_driver(wm8782_codec_driver);
 
 MODULE_DESCRIPTION("ASoC WM8782 driver");
 MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>");
index 9ee072b..d54a3ca 100644 (file)
@@ -542,7 +542,7 @@ static int wm8804_set_bias_level(struct snd_soc_codec *codec,
 }
 
 #ifdef CONFIG_PM
-static int wm8804_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8804_suspend(struct snd_soc_codec *codec)
 {
        wm8804_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -659,8 +659,6 @@ static int wm8804_probe(struct snd_soc_codec *codec)
 
        wm8804_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       snd_soc_add_controls(codec, wm8804_snd_controls,
-                            ARRAY_SIZE(wm8804_snd_controls));
        return 0;
 
 err_reg_enable:
@@ -670,7 +668,7 @@ err_reg_get:
        return ret;
 }
 
-static struct snd_soc_dai_ops wm8804_dai_ops = {
+static const struct snd_soc_dai_ops wm8804_dai_ops = {
        .hw_params = wm8804_hw_params,
        .set_fmt = wm8804_set_fmt,
        .set_sysclk = wm8804_set_sysclk,
@@ -715,7 +713,10 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
        .reg_cache_size = ARRAY_SIZE(wm8804_reg_defs),
        .reg_word_size = sizeof(u8),
        .reg_cache_default = wm8804_reg_defs,
-       .volatile_register = wm8804_volatile
+       .volatile_register = wm8804_volatile,
+
+       .controls = wm8804_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8804_snd_controls),
 };
 
 static const struct of_device_id wm8804_of_match[] = {
index 3d0dc15..f18c554 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -513,7 +512,7 @@ SND_SOC_DAPM_MIXER("Right Input Mixer", WM8900_REG_POWER2, 4, 0,
                   wm8900_rinmix_controls,
                   ARRAY_SIZE(wm8900_rinmix_controls)),
 
-SND_SOC_DAPM_MICBIAS("Mic Bias", WM8900_REG_POWER1, 4, 0),
+SND_SOC_DAPM_SUPPLY("Mic Bias", WM8900_REG_POWER1, 4, 0, NULL, 0),
 
 SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8900_REG_POWER2, 1, 0),
 SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8900_REG_POWER2, 0, 0),
@@ -543,7 +542,7 @@ SND_SOC_DAPM_MIXER("Right Output Mixer", WM8900_REG_POWER3, 2, 0,
 };
 
 /* Target, Path, Source */
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8900_dapm_routes[] = {
 /* Inputs */
 {"Left Input PGA", "LINPUT1 Switch", "LINPUT1"},
 {"Left Input PGA", "LINPUT2 Switch", "LINPUT2"},
@@ -607,17 +606,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
 {"HP_R", NULL, "Headphone Amplifier"},
 };
 
-static int wm8900_add_widgets(struct snd_soc_codec *codec)
-{
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_new_controls(dapm, wm8900_dapm_widgets,
-                                 ARRAY_SIZE(wm8900_dapm_widgets));
-       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-       return 0;
-}
-
 static int wm8900_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params,
        struct snd_soc_dai *dai)
@@ -987,7 +975,7 @@ static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute)
        (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
         SNDRV_PCM_FORMAT_S24_LE)
 
-static struct snd_soc_dai_ops wm8900_dai_ops = {
+static const struct snd_soc_dai_ops wm8900_dai_ops = {
        .hw_params      = wm8900_hw_params,
        .set_clkdiv     = wm8900_set_dai_clkdiv,
        .set_pll        = wm8900_set_dai_pll,
@@ -1107,7 +1095,7 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-static int wm8900_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8900_suspend(struct snd_soc_codec *codec)
 {
        struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
        int fll_out = wm8900->fll_out;
@@ -1204,10 +1192,6 @@ static int wm8900_probe(struct snd_soc_codec *codec)
        /* Set the DAC and mixer output bias */
        snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
 
-       snd_soc_add_controls(codec, wm8900_snd_controls,
-                               ARRAY_SIZE(wm8900_snd_controls));
-       wm8900_add_widgets(codec);
-
        return 0;
 }
 
@@ -1228,6 +1212,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8900 = {
        .reg_cache_size = ARRAY_SIZE(wm8900_reg_defaults),
        .reg_word_size = sizeof(u16),
        .reg_cache_default = wm8900_reg_defaults,
+
+       .controls = wm8900_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8900_snd_controls),
+       .dapm_widgets = wm8900_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8900_dapm_widgets),
+       .dapm_routes = wm8900_dapm_routes,
+       .num_dapm_routes = ARRAY_SIZE(wm8900_dapm_routes),
 };
 
 #if defined(CONFIG_SPI_MASTER)
@@ -1259,7 +1250,7 @@ static int __devexit wm8900_spi_remove(struct spi_device *spi)
 
 static struct spi_driver wm8900_spi_driver = {
        .driver = {
-               .name   = "wm8900-codec",
+               .name   = "wm8900",
                .owner  = THIS_MODULE,
        },
        .probe          = wm8900_spi_probe,
@@ -1303,7 +1294,7 @@ MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id);
 
 static struct i2c_driver wm8900_i2c_driver = {
        .driver = {
-               .name = "wm8900-codec",
+               .name = "wm8900",
                .owner = THIS_MODULE,
        },
        .probe =    wm8900_i2c_probe,
index 4ad8ebd..d88b727 100644 (file)
@@ -23,8 +23,9 @@
 #include <linux/gpio.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
+#include <linux/irq.h>
 #include <sound/core.h>
 #include <sound/jack.h>
 #include <sound/pcm.h>
 #include "wm8903.h"
 
 /* Register defaults at reset */
-static u16 wm8903_reg_defaults[] = {
-       0x8903,     /* R0   - SW Reset and ID */
-       0x0000,     /* R1   - Revision Number */
-       0x0000,     /* R2 */
-       0x0000,     /* R3 */
-       0x0018,     /* R4   - Bias Control 0 */
-       0x0000,     /* R5   - VMID Control 0 */
-       0x0000,     /* R6   - Mic Bias Control 0 */
-       0x0000,     /* R7 */
-       0x0001,     /* R8   - Analogue DAC 0 */
-       0x0000,     /* R9 */
-       0x0001,     /* R10  - Analogue ADC 0 */
-       0x0000,     /* R11 */
-       0x0000,     /* R12  - Power Management 0 */
-       0x0000,     /* R13  - Power Management 1 */
-       0x0000,     /* R14  - Power Management 2 */
-       0x0000,     /* R15  - Power Management 3 */
-       0x0000,     /* R16  - Power Management 4 */
-       0x0000,     /* R17  - Power Management 5 */
-       0x0000,     /* R18  - Power Management 6 */
-       0x0000,     /* R19 */
-       0x0400,     /* R20  - Clock Rates 0 */
-       0x0D07,     /* R21  - Clock Rates 1 */
-       0x0000,     /* R22  - Clock Rates 2 */
-       0x0000,     /* R23 */
-       0x0050,     /* R24  - Audio Interface 0 */
-       0x0242,     /* R25  - Audio Interface 1 */
-       0x0008,     /* R26  - Audio Interface 2 */
-       0x0022,     /* R27  - Audio Interface 3 */
-       0x0000,     /* R28 */
-       0x0000,     /* R29 */
-       0x00C0,     /* R30  - DAC Digital Volume Left */
-       0x00C0,     /* R31  - DAC Digital Volume Right */
-       0x0000,     /* R32  - DAC Digital 0 */
-       0x0000,     /* R33  - DAC Digital 1 */
-       0x0000,     /* R34 */
-       0x0000,     /* R35 */
-       0x00C0,     /* R36  - ADC Digital Volume Left */
-       0x00C0,     /* R37  - ADC Digital Volume Right */
-       0x0000,     /* R38  - ADC Digital 0 */
-       0x0073,     /* R39  - Digital Microphone 0 */
-       0x09BF,     /* R40  - DRC 0 */
-       0x3241,     /* R41  - DRC 1 */
-       0x0020,     /* R42  - DRC 2 */
-       0x0000,     /* R43  - DRC 3 */
-       0x0085,     /* R44  - Analogue Left Input 0 */
-       0x0085,     /* R45  - Analogue Right Input 0 */
-       0x0044,     /* R46  - Analogue Left Input 1 */
-       0x0044,     /* R47  - Analogue Right Input 1 */
-       0x0000,     /* R48 */
-       0x0000,     /* R49 */
-       0x0008,     /* R50  - Analogue Left Mix 0 */
-       0x0004,     /* R51  - Analogue Right Mix 0 */
-       0x0000,     /* R52  - Analogue Spk Mix Left 0 */
-       0x0000,     /* R53  - Analogue Spk Mix Left 1 */
-       0x0000,     /* R54  - Analogue Spk Mix Right 0 */
-       0x0000,     /* R55  - Analogue Spk Mix Right 1 */
-       0x0000,     /* R56 */
-       0x002D,     /* R57  - Analogue OUT1 Left */
-       0x002D,     /* R58  - Analogue OUT1 Right */
-       0x0039,     /* R59  - Analogue OUT2 Left */
-       0x0039,     /* R60  - Analogue OUT2 Right */
-       0x0100,     /* R61 */
-       0x0139,     /* R62  - Analogue OUT3 Left */
-       0x0139,     /* R63  - Analogue OUT3 Right */
-       0x0000,     /* R64 */
-       0x0000,     /* R65  - Analogue SPK Output Control 0 */
-       0x0000,     /* R66 */
-       0x0010,     /* R67  - DC Servo 0 */
-       0x0100,     /* R68 */
-       0x00A4,     /* R69  - DC Servo 2 */
-       0x0807,     /* R70 */
-       0x0000,     /* R71 */
-       0x0000,     /* R72 */
-       0x0000,     /* R73 */
-       0x0000,     /* R74 */
-       0x0000,     /* R75 */
-       0x0000,     /* R76 */
-       0x0000,     /* R77 */
-       0x0000,     /* R78 */
-       0x000E,     /* R79 */
-       0x0000,     /* R80 */
-       0x0000,     /* R81 */
-       0x0000,     /* R82 */
-       0x0000,     /* R83 */
-       0x0000,     /* R84 */
-       0x0000,     /* R85 */
-       0x0000,     /* R86 */
-       0x0006,     /* R87 */
-       0x0000,     /* R88 */
-       0x0000,     /* R89 */
-       0x0000,     /* R90  - Analogue HP 0 */
-       0x0060,     /* R91 */
-       0x0000,     /* R92 */
-       0x0000,     /* R93 */
-       0x0000,     /* R94  - Analogue Lineout 0 */
-       0x0060,     /* R95 */
-       0x0000,     /* R96 */
-       0x0000,     /* R97 */
-       0x0000,     /* R98  - Charge Pump 0 */
-       0x1F25,     /* R99 */
-       0x2B19,     /* R100 */
-       0x01C0,     /* R101 */
-       0x01EF,     /* R102 */
-       0x2B00,     /* R103 */
-       0x0000,     /* R104 - Class W 0 */
-       0x01C0,     /* R105 */
-       0x1C10,     /* R106 */
-       0x0000,     /* R107 */
-       0x0000,     /* R108 - Write Sequencer 0 */
-       0x0000,     /* R109 - Write Sequencer 1 */
-       0x0000,     /* R110 - Write Sequencer 2 */
-       0x0000,     /* R111 - Write Sequencer 3 */
-       0x0000,     /* R112 - Write Sequencer 4 */
-       0x0000,     /* R113 */
-       0x0000,     /* R114 - Control Interface */
-       0x0000,     /* R115 */
-       0x00A8,     /* R116 - GPIO Control 1 */
-       0x00A8,     /* R117 - GPIO Control 2 */
-       0x00A8,     /* R118 - GPIO Control 3 */
-       0x0220,     /* R119 - GPIO Control 4 */
-       0x01A0,     /* R120 - GPIO Control 5 */
-       0x0000,     /* R121 - Interrupt Status 1 */
-       0xFFFF,     /* R122 - Interrupt Status 1 Mask */
-       0x0000,     /* R123 - Interrupt Polarity 1 */
-       0x0000,     /* R124 */
-       0x0003,     /* R125 */
-       0x0000,     /* R126 - Interrupt Control */
-       0x0000,     /* R127 */
-       0x0005,     /* R128 */
-       0x0000,     /* R129 - Control Interface Test 1 */
-       0x0000,     /* R130 */
-       0x0000,     /* R131 */
-       0x0000,     /* R132 */
-       0x0000,     /* R133 */
-       0x0000,     /* R134 */
-       0x03FF,     /* R135 */
-       0x0007,     /* R136 */
-       0x0040,     /* R137 */
-       0x0000,     /* R138 */
-       0x0000,     /* R139 */
-       0x0000,     /* R140 */
-       0x0000,     /* R141 */
-       0x0000,     /* R142 */
-       0x0000,     /* R143 */
-       0x0000,     /* R144 */
-       0x0000,     /* R145 */
-       0x0000,     /* R146 */
-       0x0000,     /* R147 */
-       0x4000,     /* R148 */
-       0x6810,     /* R149 - Charge Pump Test 1 */
-       0x0004,     /* R150 */
-       0x0000,     /* R151 */
-       0x0000,     /* R152 */
-       0x0000,     /* R153 */
-       0x0000,     /* R154 */
-       0x0000,     /* R155 */
-       0x0000,     /* R156 */
-       0x0000,     /* R157 */
-       0x0000,     /* R158 */
-       0x0000,     /* R159 */
-       0x0000,     /* R160 */
-       0x0000,     /* R161 */
-       0x0000,     /* R162 */
-       0x0000,     /* R163 */
-       0x0028,     /* R164 - Clock Rate Test 4 */
-       0x0004,     /* R165 */
-       0x0000,     /* R166 */
-       0x0060,     /* R167 */
-       0x0000,     /* R168 */
-       0x0000,     /* R169 */
-       0x0000,     /* R170 */
-       0x0000,     /* R171 */
-       0x0000,     /* R172 - Analogue Output Bias 0 */
+static const struct reg_default wm8903_reg_defaults[] = {
+       { 4,  0x0018 },     /* R4   - Bias Control 0 */
+       { 5,  0x0000 },     /* R5   - VMID Control 0 */
+       { 6,  0x0000 },     /* R6   - Mic Bias Control 0 */
+       { 8,  0x0001 },     /* R8   - Analogue DAC 0 */
+       { 10, 0x0001 },     /* R10  - Analogue ADC 0 */
+       { 12, 0x0000 },     /* R12  - Power Management 0 */
+       { 13, 0x0000 },     /* R13  - Power Management 1 */
+       { 14, 0x0000 },     /* R14  - Power Management 2 */
+       { 15, 0x0000 },     /* R15  - Power Management 3 */
+       { 16, 0x0000 },     /* R16  - Power Management 4 */
+       { 17, 0x0000 },     /* R17  - Power Management 5 */
+       { 18, 0x0000 },     /* R18  - Power Management 6 */
+       { 20, 0x0400 },     /* R20  - Clock Rates 0 */
+       { 21, 0x0D07 },     /* R21  - Clock Rates 1 */
+       { 22, 0x0000 },     /* R22  - Clock Rates 2 */
+       { 24, 0x0050 },     /* R24  - Audio Interface 0 */
+       { 25, 0x0242 },     /* R25  - Audio Interface 1 */
+       { 26, 0x0008 },     /* R26  - Audio Interface 2 */
+       { 27, 0x0022 },     /* R27  - Audio Interface 3 */
+       { 30, 0x00C0 },     /* R30  - DAC Digital Volume Left */
+       { 31, 0x00C0 },     /* R31  - DAC Digital Volume Right */
+       { 32, 0x0000 },     /* R32  - DAC Digital 0 */
+       { 33, 0x0000 },     /* R33  - DAC Digital 1 */
+       { 36, 0x00C0 },     /* R36  - ADC Digital Volume Left */
+       { 37, 0x00C0 },     /* R37  - ADC Digital Volume Right */
+       { 38, 0x0000 },     /* R38  - ADC Digital 0 */
+       { 39, 0x0073 },     /* R39  - Digital Microphone 0 */
+       { 40, 0x09BF },     /* R40  - DRC 0 */
+       { 41, 0x3241 },     /* R41  - DRC 1 */
+       { 42, 0x0020 },     /* R42  - DRC 2 */
+       { 43, 0x0000 },     /* R43  - DRC 3 */
+       { 44, 0x0085 },     /* R44  - Analogue Left Input 0 */
+       { 45, 0x0085 },     /* R45  - Analogue Right Input 0 */
+       { 46, 0x0044 },     /* R46  - Analogue Left Input 1 */
+       { 47, 0x0044 },     /* R47  - Analogue Right Input 1 */
+       { 50, 0x0008 },     /* R50  - Analogue Left Mix 0 */
+       { 51, 0x0004 },     /* R51  - Analogue Right Mix 0 */
+       { 52, 0x0000 },     /* R52  - Analogue Spk Mix Left 0 */
+       { 53, 0x0000 },     /* R53  - Analogue Spk Mix Left 1 */
+       { 54, 0x0000 },     /* R54  - Analogue Spk Mix Right 0 */
+       { 55, 0x0000 },     /* R55  - Analogue Spk Mix Right 1 */
+       { 57, 0x002D },     /* R57  - Analogue OUT1 Left */
+       { 58, 0x002D },     /* R58  - Analogue OUT1 Right */
+       { 59, 0x0039 },     /* R59  - Analogue OUT2 Left */
+       { 60, 0x0039 },     /* R60  - Analogue OUT2 Right */
+       { 62, 0x0139 },     /* R62  - Analogue OUT3 Left */
+       { 63, 0x0139 },     /* R63  - Analogue OUT3 Right */
+       { 64, 0x0000 },     /* R65  - Analogue SPK Output Control 0 */
+       { 67, 0x0010 },     /* R67  - DC Servo 0 */
+       { 69, 0x00A4 },     /* R69  - DC Servo 2 */
+       { 90, 0x0000 },     /* R90  - Analogue HP 0 */
+       { 94, 0x0000 },     /* R94  - Analogue Lineout 0 */
+       { 98, 0x0000 },     /* R98  - Charge Pump 0 */
+       { 104, 0x0000 },    /* R104 - Class W 0 */
+       { 108, 0x0000 },    /* R108 - Write Sequencer 0 */
+       { 109, 0x0000 },    /* R109 - Write Sequencer 1 */
+       { 110, 0x0000 },    /* R110 - Write Sequencer 2 */
+       { 111, 0x0000 },    /* R111 - Write Sequencer 3 */
+       { 112, 0x0000 },    /* R112 - Write Sequencer 4 */
+       { 114, 0x0000 },    /* R114 - Control Interface */
+       { 116, 0x00A8 },    /* R116 - GPIO Control 1 */
+       { 117, 0x00A8 },    /* R117 - GPIO Control 2 */
+       { 118, 0x00A8 },    /* R118 - GPIO Control 3 */
+       { 119, 0x0220 },    /* R119 - GPIO Control 4 */
+       { 120, 0x01A0 },    /* R120 - GPIO Control 5 */
+       { 122, 0xFFFF },    /* R122 - Interrupt Status 1 Mask */
+       { 123, 0x0000 },    /* R123 - Interrupt Polarity 1 */
+       { 126, 0x0000 },    /* R126 - Interrupt Control */
+       { 129, 0x0000 },    /* R129 - Control Interface Test 1 */
+       { 149, 0x6810 },    /* R149 - Charge Pump Test 1 */
+       { 164, 0x0028 },    /* R164 - Clock Rate Test 4 */
+       { 172, 0x0000 },    /* R172 - Analogue Output Bias 0 */
 };
 
 struct wm8903_priv {
+       struct wm8903_platform_data *pdata;
        struct snd_soc_codec *codec;
+       struct regmap *regmap;
 
        int sysclk;
        int irq;
@@ -240,7 +142,93 @@ struct wm8903_priv {
 #endif
 };
 
-static int wm8903_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8903_readable_register(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM8903_SW_RESET_AND_ID:
+       case WM8903_REVISION_NUMBER:
+       case WM8903_BIAS_CONTROL_0:
+       case WM8903_VMID_CONTROL_0:
+       case WM8903_MIC_BIAS_CONTROL_0:
+       case WM8903_ANALOGUE_DAC_0:
+       case WM8903_ANALOGUE_ADC_0:
+       case WM8903_POWER_MANAGEMENT_0:
+       case WM8903_POWER_MANAGEMENT_1:
+       case WM8903_POWER_MANAGEMENT_2:
+       case WM8903_POWER_MANAGEMENT_3:
+       case WM8903_POWER_MANAGEMENT_4:
+       case WM8903_POWER_MANAGEMENT_5:
+       case WM8903_POWER_MANAGEMENT_6:
+       case WM8903_CLOCK_RATES_0:
+       case WM8903_CLOCK_RATES_1:
+       case WM8903_CLOCK_RATES_2:
+       case WM8903_AUDIO_INTERFACE_0:
+       case WM8903_AUDIO_INTERFACE_1:
+       case WM8903_AUDIO_INTERFACE_2:
+       case WM8903_AUDIO_INTERFACE_3:
+       case WM8903_DAC_DIGITAL_VOLUME_LEFT:
+       case WM8903_DAC_DIGITAL_VOLUME_RIGHT:
+       case WM8903_DAC_DIGITAL_0:
+       case WM8903_DAC_DIGITAL_1:
+       case WM8903_ADC_DIGITAL_VOLUME_LEFT:
+       case WM8903_ADC_DIGITAL_VOLUME_RIGHT:
+       case WM8903_ADC_DIGITAL_0:
+       case WM8903_DIGITAL_MICROPHONE_0:
+       case WM8903_DRC_0:
+       case WM8903_DRC_1:
+       case WM8903_DRC_2:
+       case WM8903_DRC_3:
+       case WM8903_ANALOGUE_LEFT_INPUT_0:
+       case WM8903_ANALOGUE_RIGHT_INPUT_0:
+       case WM8903_ANALOGUE_LEFT_INPUT_1:
+       case WM8903_ANALOGUE_RIGHT_INPUT_1:
+       case WM8903_ANALOGUE_LEFT_MIX_0:
+       case WM8903_ANALOGUE_RIGHT_MIX_0:
+       case WM8903_ANALOGUE_SPK_MIX_LEFT_0:
+       case WM8903_ANALOGUE_SPK_MIX_LEFT_1:
+       case WM8903_ANALOGUE_SPK_MIX_RIGHT_0:
+       case WM8903_ANALOGUE_SPK_MIX_RIGHT_1:
+       case WM8903_ANALOGUE_OUT1_LEFT:
+       case WM8903_ANALOGUE_OUT1_RIGHT:
+       case WM8903_ANALOGUE_OUT2_LEFT:
+       case WM8903_ANALOGUE_OUT2_RIGHT:
+       case WM8903_ANALOGUE_OUT3_LEFT:
+       case WM8903_ANALOGUE_OUT3_RIGHT:
+       case WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0:
+       case WM8903_DC_SERVO_0:
+       case WM8903_DC_SERVO_2:
+       case WM8903_DC_SERVO_READBACK_1:
+       case WM8903_DC_SERVO_READBACK_2:
+       case WM8903_DC_SERVO_READBACK_3:
+       case WM8903_DC_SERVO_READBACK_4:
+       case WM8903_ANALOGUE_HP_0:
+       case WM8903_ANALOGUE_LINEOUT_0:
+       case WM8903_CHARGE_PUMP_0:
+       case WM8903_CLASS_W_0:
+       case WM8903_WRITE_SEQUENCER_0:
+       case WM8903_WRITE_SEQUENCER_1:
+       case WM8903_WRITE_SEQUENCER_2:
+       case WM8903_WRITE_SEQUENCER_3:
+       case WM8903_WRITE_SEQUENCER_4:
+       case WM8903_CONTROL_INTERFACE:
+       case WM8903_GPIO_CONTROL_1:
+       case WM8903_GPIO_CONTROL_2:
+       case WM8903_GPIO_CONTROL_3:
+       case WM8903_GPIO_CONTROL_4:
+       case WM8903_GPIO_CONTROL_5:
+       case WM8903_INTERRUPT_STATUS_1:
+       case WM8903_INTERRUPT_STATUS_1_MASK:
+       case WM8903_INTERRUPT_POLARITY_1:
+       case WM8903_INTERRUPT_CONTROL:
+       case WM8903_CLOCK_RATE_TEST_4:
+       case WM8903_ANALOGUE_OUTPUT_BIAS_0:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool wm8903_volatile_register(struct device *dev, unsigned int reg)
 {
        switch (reg) {
        case WM8903_SW_RESET_AND_ID:
@@ -258,13 +246,6 @@ static int wm8903_volatile_register(struct snd_soc_codec *codec, unsigned int re
        }
 }
 
-static void wm8903_reset(struct snd_soc_codec *codec)
-{
-       snd_soc_write(codec, WM8903_SW_RESET_AND_ID, 0);
-       memcpy(codec->reg_cache, wm8903_reg_defaults,
-              sizeof(wm8903_reg_defaults));
-}
-
 static int wm8903_cp_event(struct snd_soc_dapm_widget *w,
                           struct snd_kcontrol *kcontrol, int event)
 {
@@ -839,7 +820,7 @@ SND_SOC_DAPM_OUTPUT("LON"),
 SND_SOC_DAPM_OUTPUT("ROP"),
 SND_SOC_DAPM_OUTPUT("RON"),
 
-SND_SOC_DAPM_MICBIAS("Mic Bias", WM8903_MIC_BIAS_CONTROL_0, 0, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8903_MIC_BIAS_CONTROL_0, 0, 0, NULL, 0),
 
 SND_SOC_DAPM_MUX("Left Input Mux", SND_SOC_NOPM, 0, 0, &linput_mux),
 SND_SOC_DAPM_MUX("Left Input Inverting Mux", SND_SOC_NOPM, 0, 0,
@@ -948,7 +929,7 @@ SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8903_CLOCK_RATES_2, 2, 0, NULL, 0),
 static const struct snd_soc_dapm_route wm8903_intercon[] = {
 
        { "CLK_DSP", NULL, "CLK_SYS" },
-       { "Mic Bias", NULL, "CLK_SYS" },
+       { "MICBIAS", NULL, "CLK_SYS" },
        { "HPL_DCS", NULL, "CLK_SYS" },
        { "HPR_DCS", NULL, "CLK_SYS" },
        { "LINEOUTL_DCS", NULL, "CLK_SYS" },
@@ -1732,7 +1713,7 @@ static irqreturn_t wm8903_irq(int irq, void *data)
                        SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8903_dai_ops = {
+static const struct snd_soc_dai_ops wm8903_dai_ops = {
        .hw_params      = wm8903_hw_params,
        .digital_mute   = wm8903_digital_mute,
        .set_fmt        = wm8903_set_dai_fmt,
@@ -1759,7 +1740,7 @@ static struct snd_soc_dai_driver wm8903_dai = {
        .symmetric_rates = 1,
 };
 
-static int wm8903_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8903_suspend(struct snd_soc_codec *codec)
 {
        wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1768,23 +1749,11 @@ static int wm8903_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8903_resume(struct snd_soc_codec *codec)
 {
-       int i;
-       u16 *reg_cache = codec->reg_cache;
-       u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults),
-                                GFP_KERNEL);
+       struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
 
-       /* Bring the codec back up to standby first to minimise pop/clicks */
-       wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       regcache_sync(wm8903->regmap);
 
-       /* Sync back everything else */
-       if (tmp_cache) {
-               for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++)
-                       if (tmp_cache[i] != reg_cache[i])
-                               snd_soc_write(codec, i, tmp_cache[i]);
-               kfree(tmp_cache);
-       } else {
-               dev_err(codec->dev, "Failed to allocate temporary cache\n");
-       }
+       wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
 }
@@ -1867,14 +1836,14 @@ static struct gpio_chip wm8903_template_chip = {
 static void wm8903_init_gpio(struct snd_soc_codec *codec)
 {
        struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
-       struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev);
+       struct wm8903_platform_data *pdata = wm8903->pdata;
        int ret;
 
        wm8903->gpio_chip = wm8903_template_chip;
        wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO;
        wm8903->gpio_chip.dev = codec->dev;
 
-       if (pdata && pdata->gpio_base)
+       if (pdata->gpio_base)
                wm8903->gpio_chip.base = pdata->gpio_base;
        else
                wm8903->gpio_chip.base = -1;
@@ -1905,78 +1874,65 @@ static void wm8903_free_gpio(struct snd_soc_codec *codec)
 
 static int wm8903_probe(struct snd_soc_codec *codec)
 {
-       struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev);
        struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
+       struct wm8903_platform_data *pdata = wm8903->pdata;
        int ret, i;
        int trigger, irq_pol;
        u16 val;
+       bool mic_gpio = false;
 
        wm8903->codec = codec;
+       codec->control_data = wm8903->regmap;
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
        }
 
-       val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID);
-       if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
-               dev_err(codec->dev,
-                       "Device with ID register %x is not a WM8903\n", val);
-               return -ENODEV;
-       }
-
-       val = snd_soc_read(codec, WM8903_REVISION_NUMBER);
-       dev_info(codec->dev, "WM8903 revision %c\n",
-                (val & WM8903_CHIP_REV_MASK) + 'A');
-
-       wm8903_reset(codec);
+       /* Set up GPIOs, detect if any are MIC detect outputs */
+       for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) {
+               if ((!pdata->gpio_cfg[i]) ||
+                   (pdata->gpio_cfg[i] > WM8903_GPIO_CONFIG_ZERO))
+                       continue;
 
-       /* Set up GPIOs and microphone detection */
-       if (pdata) {
-               bool mic_gpio = false;
+               snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i,
+                               pdata->gpio_cfg[i] & 0x7fff);
 
-               for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) {
-                       if (pdata->gpio_cfg[i] == WM8903_GPIO_NO_CONFIG)
-                               continue;
+               val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK)
+                       >> WM8903_GP1_FN_SHIFT;
 
-                       snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i,
-                                     pdata->gpio_cfg[i] & 0xffff);
-
-                       val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK)
-                               >> WM8903_GP1_FN_SHIFT;
-
-                       switch (val) {
-                       case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT:
-                       case WM8903_GPn_FN_MICBIAS_SHORT_DETECT:
-                               mic_gpio = true;
-                               break;
-                       default:
-                               break;
-                       }
+               switch (val) {
+               case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT:
+               case WM8903_GPn_FN_MICBIAS_SHORT_DETECT:
+                       mic_gpio = true;
+                       break;
+               default:
+                       break;
                }
+       }
 
-               snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0,
-                             pdata->micdet_cfg);
+       /* Set up microphone detection */
+       snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0,
+                       pdata->micdet_cfg);
 
-               /* Microphone detection needs the WSEQ clock */
-               if (pdata->micdet_cfg)
-                       snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0,
-                                           WM8903_WSEQ_ENA, WM8903_WSEQ_ENA);
+       /* Microphone detection needs the WSEQ clock */
+       if (pdata->micdet_cfg)
+               snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0,
+                                   WM8903_WSEQ_ENA, WM8903_WSEQ_ENA);
 
-               /* If microphone detection is enabled by pdata but
-                * detected via IRQ then interrupts can be lost before
-                * the machine driver has set up microphone detection
-                * IRQs as the IRQs are clear on read.  The detection
-                * will be enabled when the machine driver configures.
-                */
-               WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA));
+       /* If microphone detection is enabled by pdata but
+           * detected via IRQ then interrupts can be lost before
+           * the machine driver has set up microphone detection
+           * IRQs as the IRQs are clear on read.  The detection
+           * will be enabled when the machine driver configures.
+           */
+       WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA));
+
+       wm8903->mic_delay = pdata->micdet_delay;
 
-               wm8903->mic_delay = pdata->micdet_delay;
-       }
-       
        if (wm8903->irq) {
-               if (pdata && pdata->irq_active_low) {
+               if (pdata->irq_active_low) {
                        trigger = IRQF_TRIGGER_LOW;
                        irq_pol = WM8903_IRQ_POL;
                } else {
@@ -2035,9 +1991,6 @@ static int wm8903_probe(struct snd_soc_codec *codec)
                            WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE,
                            WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE);
 
-       snd_soc_add_controls(codec, wm8903_snd_controls,
-                               ARRAY_SIZE(wm8903_snd_controls));
-
        wm8903_init_gpio(codec);
 
        return ret;
@@ -2062,45 +2015,198 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8903 = {
        .suspend =      wm8903_suspend,
        .resume =       wm8903_resume,
        .set_bias_level = wm8903_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8903_reg_defaults,
-       .volatile_register = wm8903_volatile_register,
        .seq_notifier = wm8903_seq_notifier,
+       .controls = wm8903_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8903_snd_controls),
        .dapm_widgets = wm8903_dapm_widgets,
        .num_dapm_widgets = ARRAY_SIZE(wm8903_dapm_widgets),
        .dapm_routes = wm8903_intercon,
        .num_dapm_routes = ARRAY_SIZE(wm8903_intercon),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static const struct regmap_config wm8903_regmap = {
+       .reg_bits = 8,
+       .val_bits = 16,
+
+       .max_register = WM8903_MAX_REGISTER,
+       .volatile_reg = wm8903_volatile_register,
+       .readable_reg = wm8903_readable_register,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = wm8903_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8903_reg_defaults),
+};
+
+static int wm8903_set_pdata_irq_trigger(struct i2c_client *i2c,
+                                       struct wm8903_platform_data *pdata)
+{
+       struct irq_data *irq_data = irq_get_irq_data(i2c->irq);
+       if (!irq_data) {
+               dev_err(&i2c->dev, "Invalid IRQ: %d\n",
+                       i2c->irq);
+               return -EINVAL;
+       }
+
+       switch (irqd_get_trigger_type(irq_data)) {
+       case IRQ_TYPE_NONE:
+       default:
+               /*
+               * We assume the controller imposes no restrictions,
+               * so we are able to select active-high
+               */
+               /* Fall-through */
+       case IRQ_TYPE_LEVEL_HIGH:
+               pdata->irq_active_low = false;
+               break;
+       case IRQ_TYPE_LEVEL_LOW:
+               pdata->irq_active_low = true;
+               break;
+       }
+
+       return 0;
+}
+
+static int wm8903_set_pdata_from_of(struct i2c_client *i2c,
+                                   struct wm8903_platform_data *pdata)
+{
+       const struct device_node *np = i2c->dev.of_node;
+       u32 val32;
+       int i;
+
+       if (of_property_read_u32(np, "micdet-cfg", &val32) >= 0)
+               pdata->micdet_cfg = val32;
+
+       if (of_property_read_u32(np, "micdet-delay", &val32) >= 0)
+               pdata->micdet_delay = val32;
+
+       if (of_property_read_u32_array(np, "gpio-cfg", pdata->gpio_cfg,
+                                      ARRAY_SIZE(pdata->gpio_cfg)) >= 0) {
+               /*
+                * In device tree: 0 means "write 0",
+                * 0xffffffff means "don't touch".
+                *
+                * In platform data: 0 means "don't touch",
+                * 0x8000 means "write 0".
+                *
+                * Note: WM8903_GPIO_CONFIG_ZERO == 0x8000.
+                *
+                *  Convert from DT to pdata representation here,
+                * so no other code needs to change.
+                */
+               for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) {
+                       if (pdata->gpio_cfg[i] == 0) {
+                               pdata->gpio_cfg[i] = WM8903_GPIO_CONFIG_ZERO;
+                       } else if (pdata->gpio_cfg[i] == 0xffffffff) {
+                               pdata->gpio_cfg[i] = 0;
+                       } else if (pdata->gpio_cfg[i] > 0x7fff) {
+                               dev_err(&i2c->dev, "Invalid gpio-cfg[%d] %x\n",
+                                       i, pdata->gpio_cfg[i]);
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       return 0;
+}
+
 static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
+       struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev);
        struct wm8903_priv *wm8903;
+       unsigned int val;
        int ret;
 
-       wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
+       wm8903 = devm_kzalloc(&i2c->dev,  sizeof(struct wm8903_priv),
+                             GFP_KERNEL);
        if (wm8903 == NULL)
                return -ENOMEM;
 
+       wm8903->regmap = regmap_init_i2c(i2c, &wm8903_regmap);
+       if (IS_ERR(wm8903->regmap)) {
+               ret = PTR_ERR(wm8903->regmap);
+               dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               return ret;
+       }
+
        i2c_set_clientdata(i2c, wm8903);
        wm8903->irq = i2c->irq;
 
+       /* If no platform data was supplied, create storage for defaults */
+       if (pdata) {
+               wm8903->pdata = pdata;
+       } else {
+               wm8903->pdata = devm_kzalloc(&i2c->dev,
+                                       sizeof(struct wm8903_platform_data),
+                                       GFP_KERNEL);
+               if (wm8903->pdata == NULL) {
+                       dev_err(&i2c->dev, "Failed to allocate pdata\n");
+                       return -ENOMEM;
+               }
+
+               if (i2c->irq) {
+                       ret = wm8903_set_pdata_irq_trigger(i2c, wm8903->pdata);
+                       if (ret != 0)
+                               return ret;
+               }
+
+               if (i2c->dev.of_node) {
+                       ret = wm8903_set_pdata_from_of(i2c, wm8903->pdata);
+                       if (ret != 0)
+                               return ret;
+               }
+       }
+
+       ret = regmap_read(wm8903->regmap, WM8903_SW_RESET_AND_ID, &val);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
+               goto err;
+       }
+       if (val != 0x8903) {
+               dev_err(&i2c->dev, "Device with ID %x is not a WM8903\n", val);
+               ret = -ENODEV;
+               goto err;
+       }
+
+       ret = regmap_read(wm8903->regmap, WM8903_REVISION_NUMBER, &val);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to read chip revision: %d\n", ret);
+               goto err;
+       }
+       dev_info(&i2c->dev, "WM8903 revision %c\n",
+                (val & WM8903_CHIP_REV_MASK) + 'A');
+
+       /* Reset the device */
+       regmap_write(wm8903->regmap, WM8903_SW_RESET_AND_ID, 0x8903);
+
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8903, &wm8903_dai, 1);
-       if (ret < 0)
-               kfree(wm8903);
+       if (ret != 0)
+               goto err;
+
+       return 0;
+err:
+       regmap_exit(wm8903->regmap);
        return ret;
 }
 
 static __devexit int wm8903_i2c_remove(struct i2c_client *client)
 {
+       struct wm8903_priv *wm8903 = i2c_get_clientdata(client);
+
+       regmap_exit(wm8903->regmap);
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+
        return 0;
 }
 
+static const struct of_device_id wm8903_of_match[] = {
+       { .compatible = "wlf,wm8903", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, wm8903_of_match);
+
 static const struct i2c_device_id wm8903_i2c_id[] = {
        { "wm8903", 0 },
        { }
@@ -2111,32 +2217,28 @@ static struct i2c_driver wm8903_i2c_driver = {
        .driver = {
                .name = "wm8903",
                .owner = THIS_MODULE,
+               .of_match_table = wm8903_of_match,
        },
        .probe =    wm8903_i2c_probe,
        .remove =   __devexit_p(wm8903_i2c_remove),
        .id_table = wm8903_i2c_id,
 };
-#endif
 
 static int __init wm8903_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8903_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register wm8903 I2C driver: %d\n",
                       ret);
        }
-#endif
        return ret;
 }
 module_init(wm8903_modinit);
 
 static void __exit wm8903_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8903_i2c_driver);
-#endif
 }
 module_exit(wm8903_exit);
 
index 285ef87..f31c754 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -1196,7 +1195,7 @@ SND_SOC_DAPM_INPUT("IN2R"),
 SND_SOC_DAPM_INPUT("IN3L"),
 SND_SOC_DAPM_INPUT("IN3R"),
 
-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8904_MIC_BIAS_CONTROL_0, 0, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8904_MIC_BIAS_CONTROL_0, 0, 0, NULL, 0),
 
 SND_SOC_DAPM_MUX("Left Capture Mux", SND_SOC_NOPM, 0, 0, &lin_mux),
 SND_SOC_DAPM_MUX("Left Capture Inverting Mux", SND_SOC_NOPM, 0, 0,
@@ -2205,7 +2204,7 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec,
 #define WM8904_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8904_dai_ops = {
+static const struct snd_soc_dai_ops wm8904_dai_ops = {
        .set_sysclk = wm8904_set_sysclk,
        .set_fmt = wm8904_set_fmt,
        .set_tdm_slot = wm8904_set_tdm_slot,
@@ -2235,7 +2234,7 @@ static struct snd_soc_dai_driver wm8904_dai = {
 };
 
 #ifdef CONFIG_PM
-static int wm8904_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8904_suspend(struct snd_soc_codec *codec)
 {
        wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -2565,7 +2564,7 @@ MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id);
 
 static struct i2c_driver wm8904_i2c_driver = {
        .driver = {
-               .name = "wm8904-codec",
+               .name = "wm8904",
                .owner = THIS_MODULE,
        },
        .probe =    wm8904_i2c_probe,
index de9ec9b..14039ea 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -629,8 +628,8 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
                ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 5));
                break;
        case WM8940_OPCLKDIV:
-               reg = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFCF;
-               ret = snd_soc_write(codec, WM8940_ADDCNTRL, reg | (div << 4));
+               reg = snd_soc_read(codec, WM8940_GPIO) & 0xFFCF;
+               ret = snd_soc_write(codec, WM8940_GPIO, reg | (div << 4));
                break;
        }
        return ret;
@@ -644,7 +643,7 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
                        SNDRV_PCM_FMTBIT_S24_LE |                       \
                        SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8940_dai_ops = {
+static const struct snd_soc_dai_ops wm8940_dai_ops = {
        .hw_params = wm8940_i2s_hw_params,
        .set_sysclk = wm8940_set_dai_sysclk,
        .digital_mute = wm8940_mute,
@@ -673,7 +672,7 @@ static struct snd_soc_dai_driver wm8940_dai = {
        .symmetric_rates = 1,
 };
 
-static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8940_suspend(struct snd_soc_codec *codec)
 {
        return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF);
 }
@@ -780,7 +779,7 @@ MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id);
 
 static struct i2c_driver wm8940_i2c_driver = {
        .driver = {
-               .name = "wm8940-codec",
+               .name = "wm8940",
                .owner = THIS_MODULE,
        },
        .probe =    wm8940_i2c_probe,
index 3c71987..9245481 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -859,7 +858,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
 #define WM8955_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8955_dai_ops = {
+static const struct snd_soc_dai_ops wm8955_dai_ops = {
        .set_sysclk = wm8955_set_sysclk,
        .set_fmt = wm8955_set_fmt,
        .hw_params = wm8955_hw_params,
@@ -879,7 +878,7 @@ static struct snd_soc_dai_driver wm8955_dai = {
 };
 
 #ifdef CONFIG_PM
-static int wm8955_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8955_suspend(struct snd_soc_codec *codec)
 {
        wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1038,7 +1037,7 @@ MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id);
 
 static struct i2c_driver wm8955_i2c_driver = {
        .driver = {
-               .name = "wm8955-codec",
+               .name = "wm8955",
                .owner = THIS_MODULE,
        },
        .probe =    wm8955_i2c_probe,
index 0293763..8d4ea43 100644 (file)
@@ -55,11 +55,14 @@ static int wm8958_dsp2_fw(struct snd_soc_codec *codec, const char *name,
                return 0;
 
        if (fw->size < 32) {
-               dev_err(codec->dev, "%s: firmware too short\n", name);
+               dev_err(codec->dev, "%s: firmware too short (%d bytes)\n",
+                       name, fw->size);
                goto err;
        }
 
        if (memcmp(fw->data, "WMFW", 4) != 0) {
+               memcpy(&data32, fw->data, sizeof(data32));
+               data32 = be32_to_cpu(data32);
                dev_err(codec->dev, "%s: firmware has bad file magic %08x\n",
                        name, data32);
                goto err;
index 2df253c..2315b86 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -26,8 +25,6 @@
 
 #include "wm8960.h"
 
-#define AUDIO_NAME "wm8960"
-
 /* R25 - Power 1 */
 #define WM8960_VMID_MASK 0x180
 #define WM8960_VREF      0x40
@@ -265,7 +262,7 @@ SND_SOC_DAPM_INPUT("RINPUT2"),
 SND_SOC_DAPM_INPUT("LINPUT3"),
 SND_SOC_DAPM_INPUT("RINPUT3"),
 
-SND_SOC_DAPM_MICBIAS("MICB", WM8960_POWER1, 1, 0),
+SND_SOC_DAPM_SUPPLY("MICB", WM8960_POWER1, 1, 0, NULL, 0),
 
 SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8960_POWER1, 5, 0,
                   wm8960_lin_boost, ARRAY_SIZE(wm8960_lin_boost)),
@@ -546,30 +543,24 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
 static int wm8960_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
-       u16 mute_reg = snd_soc_read(codec, WM8960_DACCTL1) & 0xfff7;
 
        if (mute)
-               snd_soc_write(codec, WM8960_DACCTL1, mute_reg | 0x8);
+               snd_soc_update_bits(codec, WM8960_DACCTL1, 0x8, 0x8);
        else
-               snd_soc_write(codec, WM8960_DACCTL1, mute_reg);
+               snd_soc_update_bits(codec, WM8960_DACCTL1, 0x8, 0);
        return 0;
 }
 
 static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec,
                                      enum snd_soc_bias_level level)
 {
-       u16 reg;
-
        switch (level) {
        case SND_SOC_BIAS_ON:
                break;
 
        case SND_SOC_BIAS_PREPARE:
                /* Set VMID to 2x50k */
-               reg = snd_soc_read(codec, WM8960_POWER1);
-               reg &= ~0x180;
-               reg |= 0x80;
-               snd_soc_write(codec, WM8960_POWER1, reg);
+               snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x80);
                break;
 
        case SND_SOC_BIAS_STANDBY:
@@ -582,23 +573,19 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec,
                                      WM8960_BUFDCOPEN | WM8960_BUFIOEN);
 
                        /* Enable & ramp VMID at 2x50k */
-                       reg = snd_soc_read(codec, WM8960_POWER1);
-                       reg |= 0x80;
-                       snd_soc_write(codec, WM8960_POWER1, reg);
+                       snd_soc_update_bits(codec, WM8960_POWER1, 0x80, 0x80);
                        msleep(100);
 
                        /* Enable VREF */
-                       snd_soc_write(codec, WM8960_POWER1, reg | WM8960_VREF);
+                       snd_soc_update_bits(codec, WM8960_POWER1, WM8960_VREF,
+                                           WM8960_VREF);
 
                        /* Disable anti-pop features */
                        snd_soc_write(codec, WM8960_APOP1, WM8960_BUFIOEN);
                }
 
                /* Set VMID to 2x250k */
-               reg = snd_soc_read(codec, WM8960_POWER1);
-               reg &= ~0x180;
-               reg |= 0x100;
-               snd_soc_write(codec, WM8960_POWER1, reg);
+               snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x100);
                break;
 
        case SND_SOC_BIAS_OFF:
@@ -790,10 +777,8 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
 
        /* Disable the PLL: even if we are changing the frequency the
         * PLL needs to be disabled while we do so. */
-       snd_soc_write(codec, WM8960_CLOCK1,
-                    snd_soc_read(codec, WM8960_CLOCK1) & ~1);
-       snd_soc_write(codec, WM8960_POWER2,
-                    snd_soc_read(codec, WM8960_POWER2) & ~1);
+       snd_soc_update_bits(codec, WM8960_CLOCK1, 0x1, 0);
+       snd_soc_update_bits(codec, WM8960_POWER2, 0x1, 0);
 
        if (!freq_in || !freq_out)
                return 0;
@@ -812,11 +797,9 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
        snd_soc_write(codec, WM8960_PLL1, reg);
 
        /* Turn it on */
-       snd_soc_write(codec, WM8960_POWER2,
-                    snd_soc_read(codec, WM8960_POWER2) | 1);
+       snd_soc_update_bits(codec, WM8960_POWER2, 0x1, 0x1);
        msleep(250);
-       snd_soc_write(codec, WM8960_CLOCK1,
-                    snd_soc_read(codec, WM8960_CLOCK1) | 1);
+       snd_soc_update_bits(codec, WM8960_CLOCK1, 0x1, 0x1);
 
        return 0;
 }
@@ -869,7 +852,7 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec,
        (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
        SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8960_dai_ops = {
+static const struct snd_soc_dai_ops wm8960_dai_ops = {
        .hw_params = wm8960_hw_params,
        .digital_mute = wm8960_mute,
        .set_fmt = wm8960_set_dai_fmt,
@@ -895,7 +878,7 @@ static struct snd_soc_dai_driver wm8960_dai = {
        .symmetric_rates = 1,
 };
 
-static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8960_suspend(struct snd_soc_codec *codec)
 {
        struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
 
@@ -916,7 +899,6 @@ static int wm8960_probe(struct snd_soc_codec *codec)
        struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
        struct wm8960_data *pdata = dev_get_platdata(codec->dev);
        int ret;
-       u16 reg;
 
        wm8960->set_bias_level = wm8960_set_bias_level_out3;
 
@@ -947,26 +929,16 @@ static int wm8960_probe(struct snd_soc_codec *codec)
        wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* Latch the update bits */
-       reg = snd_soc_read(codec, WM8960_LINVOL);
-       snd_soc_write(codec, WM8960_LINVOL, reg | 0x100);
-       reg = snd_soc_read(codec, WM8960_RINVOL);
-       snd_soc_write(codec, WM8960_RINVOL, reg | 0x100);
-       reg = snd_soc_read(codec, WM8960_LADC);
-       snd_soc_write(codec, WM8960_LADC, reg | 0x100);
-       reg = snd_soc_read(codec, WM8960_RADC);
-       snd_soc_write(codec, WM8960_RADC, reg | 0x100);
-       reg = snd_soc_read(codec, WM8960_LDAC);
-       snd_soc_write(codec, WM8960_LDAC, reg | 0x100);
-       reg = snd_soc_read(codec, WM8960_RDAC);
-       snd_soc_write(codec, WM8960_RDAC, reg | 0x100);
-       reg = snd_soc_read(codec, WM8960_LOUT1);
-       snd_soc_write(codec, WM8960_LOUT1, reg | 0x100);
-       reg = snd_soc_read(codec, WM8960_ROUT1);
-       snd_soc_write(codec, WM8960_ROUT1, reg | 0x100);
-       reg = snd_soc_read(codec, WM8960_LOUT2);
-       snd_soc_write(codec, WM8960_LOUT2, reg | 0x100);
-       reg = snd_soc_read(codec, WM8960_ROUT2);
-       snd_soc_write(codec, WM8960_ROUT2, reg | 0x100);
+       snd_soc_update_bits(codec, WM8960_LINVOL, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8960_RINVOL, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8960_LADC, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8960_RADC, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8960_LDAC, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8960_RDAC, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8960_LOUT1, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8960_ROUT1, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8960_LOUT2, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8960_ROUT2, 0x100, 0x100);
 
        snd_soc_add_controls(codec, wm8960_snd_controls,
                                     ARRAY_SIZE(wm8960_snd_controls));
@@ -995,7 +967,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8960 = {
        .reg_cache_default = wm8960_reg,
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
@@ -1031,34 +1002,29 @@ MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id);
 
 static struct i2c_driver wm8960_i2c_driver = {
        .driver = {
-               .name = "wm8960-codec",
+               .name = "wm8960",
                .owner = THIS_MODULE,
        },
        .probe =    wm8960_i2c_probe,
        .remove =   __devexit_p(wm8960_i2c_remove),
        .id_table = wm8960_i2c_id,
 };
-#endif
 
 static int __init wm8960_modinit(void)
 {
        int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8960_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n",
                       ret);
        }
-#endif
        return ret;
 }
 module_init(wm8960_modinit);
 
 static void __exit wm8960_exit(void)
 {
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8960_i2c_driver);
-#endif
 }
 module_exit(wm8960_exit);
 
index 9568c8a..58fbf0a 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -423,11 +422,11 @@ static int wm8961_spk_event(struct snd_soc_dapm_widget *w,
        }
 
        if (event & SND_SOC_DAPM_PRE_PMD) {
-               /* Enable the amplifier */
+               /* Disable the amplifier */
                spk_reg &= ~(WM8961_SPKL_ENA | WM8961_SPKR_ENA);
                snd_soc_write(codec, WM8961_CLASS_D_CONTROL_1, spk_reg);
 
-               /* Enable the PGA */
+               /* Disable the PGA */
                pwr_reg &= ~(WM8961_SPKL_PGA | WM8961_SPKR_PGA);
                snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
        }
@@ -531,7 +530,7 @@ SND_SOC_DAPM_PGA("Right Input", WM8961_PWR_MGMT_1, 4, 0, NULL, 0),
 SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", WM8961_PWR_MGMT_1, 3, 0),
 SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", WM8961_PWR_MGMT_1, 2, 0),
 
-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8961_PWR_MGMT_1, 1, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8961_PWR_MGMT_1, 1, 0, NULL, 0),
 
 SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &dacl_mux),
 SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &dacr_mux),
@@ -929,7 +928,7 @@ static int wm8961_set_bias_level(struct snd_soc_codec *codec,
        (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
        SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8961_dai_ops = {
+static const struct snd_soc_dai_ops wm8961_dai_ops = {
        .hw_params = wm8961_hw_params,
        .set_sysclk = wm8961_set_sysclk,
        .set_fmt = wm8961_set_fmt,
@@ -1039,7 +1038,7 @@ static int wm8961_remove(struct snd_soc_codec *codec)
 }
 
 #ifdef CONFIG_PM
-static int wm8961_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8961_suspend(struct snd_soc_codec *codec)
 {
        wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1117,7 +1116,7 @@ MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id);
 
 static struct i2c_driver wm8961_i2c_driver = {
        .driver = {
-               .name = "wm8961-codec",
+               .name = "wm8961",
                .owner = THIS_MODULE,
        },
        .probe =    wm8961_i2c_probe,
index 91d3c6d..be35b64 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
-#include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
@@ -50,6 +50,7 @@ static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = {
 
 /* codec private data */
 struct wm8962_priv {
+       struct regmap *regmap;
        struct snd_soc_codec *codec;
 
        int sysclk;
@@ -95,7 +96,7 @@ static int wm8962_regulator_event_##n(struct notifier_block *nb, \
        struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \
                                                  disable_nb[n]); \
        if (event & REGULATOR_EVENT_DISABLE) { \
-               wm8962->codec->cache_sync = 1; \
+               regcache_cache_only(wm8962->regmap, true);      \
        } \
        return 0; \
 }
@@ -109,691 +110,691 @@ WM8962_REGULATOR_EVENT(5)
 WM8962_REGULATOR_EVENT(6)
 WM8962_REGULATOR_EVENT(7)
 
-static const u16 wm8962_reg[WM8962_MAX_REGISTER + 1] = {
-       [0] = 0x009F,     /* R0     - Left Input volume */
-       [1] = 0x049F,     /* R1     - Right Input volume */
-       [2] = 0x0000,     /* R2     - HPOUTL volume */
-       [3] = 0x0000,     /* R3     - HPOUTR volume */
-       [4] = 0x0020,     /* R4     - Clocking1 */
-       [5] = 0x0018,     /* R5     - ADC & DAC Control 1 */
-       [6] = 0x2008,     /* R6     - ADC & DAC Control 2 */
-       [7] = 0x000A,     /* R7     - Audio Interface 0 */
-       [8] = 0x01E4,     /* R8     - Clocking2 */
-       [9] = 0x0300,     /* R9     - Audio Interface 1 */
-       [10] = 0x00C0,    /* R10    - Left DAC volume */
-       [11] = 0x00C0,    /* R11    - Right DAC volume */
-
-       [14] = 0x0040,     /* R14    - Audio Interface 2 */
-       [15] = 0x6243,     /* R15    - Software Reset */
-
-       [17] = 0x007B,     /* R17    - ALC1 */
-       [18] = 0x0000,     /* R18    - ALC2 */
-       [19] = 0x1C32,     /* R19    - ALC3 */
-       [20] = 0x3200,     /* R20    - Noise Gate */
-       [21] = 0x00C0,     /* R21    - Left ADC volume */
-       [22] = 0x00C0,     /* R22    - Right ADC volume */
-       [23] = 0x0160,     /* R23    - Additional control(1) */
-       [24] = 0x0000,     /* R24    - Additional control(2) */
-       [25] = 0x0000,     /* R25    - Pwr Mgmt (1) */
-       [26] = 0x0000,     /* R26    - Pwr Mgmt (2) */
-       [27] = 0x0010,     /* R27    - Additional Control (3) */
-       [28] = 0x0000,     /* R28    - Anti-pop */
-
-       [30] = 0x005E,     /* R30    - Clocking 3 */
-       [31] = 0x0000,     /* R31    - Input mixer control (1) */
-       [32] = 0x0145,     /* R32    - Left input mixer volume */
-       [33] = 0x0145,     /* R33    - Right input mixer volume */
-       [34] = 0x0009,     /* R34    - Input mixer control (2) */
-       [35] = 0x0003,     /* R35    - Input bias control */
-       [37] = 0x0008,     /* R37    - Left input PGA control */
-       [38] = 0x0008,     /* R38    - Right input PGA control */
-
-       [40] = 0x0000,     /* R40    - SPKOUTL volume */
-       [41] = 0x0000,     /* R41    - SPKOUTR volume */
-
-       [47] = 0x0000,     /* R47    - Thermal Shutdown Status */
-       [48] = 0x8027,     /* R48    - Additional Control (4) */
-       [49] = 0x0010,     /* R49    - Class D Control 1 */
-
-       [51] = 0x0003,     /* R51    - Class D Control 2 */
-
-       [56] = 0x0506,     /* R56    - Clocking 4 */
-       [57] = 0x0000,     /* R57    - DAC DSP Mixing (1) */
-       [58] = 0x0000,     /* R58    - DAC DSP Mixing (2) */
-
-       [60] = 0x0300,     /* R60    - DC Servo 0 */
-       [61] = 0x0300,     /* R61    - DC Servo 1 */
-
-       [64] = 0x0810,     /* R64    - DC Servo 4 */
-
-       [66] = 0x0000,     /* R66    - DC Servo 6 */
-
-       [68] = 0x001B,     /* R68    - Analogue PGA Bias */
-       [69] = 0x0000,     /* R69    - Analogue HP 0 */
-
-       [71] = 0x01FB,     /* R71    - Analogue HP 2 */
-       [72] = 0x0000,     /* R72    - Charge Pump 1 */
-
-       [82] = 0x0004,     /* R82    - Charge Pump B */
-
-       [87] = 0x0000,     /* R87    - Write Sequencer Control 1 */
-
-       [90] = 0x0000,     /* R90    - Write Sequencer Control 2 */
-
-       [93] = 0x0000,     /* R93    - Write Sequencer Control 3 */
-       [94] = 0x0000,     /* R94    - Control Interface */
-
-       [99] = 0x0000,     /* R99    - Mixer Enables */
-       [100] = 0x0000,     /* R100   - Headphone Mixer (1) */
-       [101] = 0x0000,     /* R101   - Headphone Mixer (2) */
-       [102] = 0x013F,     /* R102   - Headphone Mixer (3) */
-       [103] = 0x013F,     /* R103   - Headphone Mixer (4) */
-
-       [105] = 0x0000,     /* R105   - Speaker Mixer (1) */
-       [106] = 0x0000,     /* R106   - Speaker Mixer (2) */
-       [107] = 0x013F,     /* R107   - Speaker Mixer (3) */
-       [108] = 0x013F,     /* R108   - Speaker Mixer (4) */
-       [109] = 0x0003,     /* R109   - Speaker Mixer (5) */
-       [110] = 0x0002,     /* R110   - Beep Generator (1) */
-
-       [115] = 0x0006,     /* R115   - Oscillator Trim (3) */
-       [116] = 0x0026,     /* R116   - Oscillator Trim (4) */
-
-       [119] = 0x0000,     /* R119   - Oscillator Trim (7) */
-
-       [124] = 0x0011,     /* R124   - Analogue Clocking1 */
-       [125] = 0x004B,     /* R125   - Analogue Clocking2 */
-       [126] = 0x000D,     /* R126   - Analogue Clocking3 */
-       [127] = 0x0000,     /* R127   - PLL Software Reset */
-
-       [129] = 0x0000,     /* R129   - PLL2 */
-
-       [131] = 0x0000,     /* R131   - PLL 4 */
-
-       [136] = 0x0067,     /* R136   - PLL 9 */
-       [137] = 0x001C,     /* R137   - PLL 10 */
-       [138] = 0x0071,     /* R138   - PLL 11 */
-       [139] = 0x00C7,     /* R139   - PLL 12 */
-       [140] = 0x0067,     /* R140   - PLL 13 */
-       [141] = 0x0048,     /* R141   - PLL 14 */
-       [142] = 0x0022,     /* R142   - PLL 15 */
-       [143] = 0x0097,     /* R143   - PLL 16 */
-
-       [155] = 0x000C,     /* R155   - FLL Control (1) */
-       [156] = 0x0039,     /* R156   - FLL Control (2) */
-       [157] = 0x0180,     /* R157   - FLL Control (3) */
-
-       [159] = 0x0032,     /* R159   - FLL Control (5) */
-       [160] = 0x0018,     /* R160   - FLL Control (6) */
-       [161] = 0x007D,     /* R161   - FLL Control (7) */
-       [162] = 0x0008,     /* R162   - FLL Control (8) */
-
-       [252] = 0x0005,     /* R252   - General test 1 */
-
-       [256] = 0x0000,     /* R256   - DF1 */
-       [257] = 0x0000,     /* R257   - DF2 */
-       [258] = 0x0000,     /* R258   - DF3 */
-       [259] = 0x0000,     /* R259   - DF4 */
-       [260] = 0x0000,     /* R260   - DF5 */
-       [261] = 0x0000,     /* R261   - DF6 */
-       [262] = 0x0000,     /* R262   - DF7 */
-
-       [264] = 0x0000,     /* R264   - LHPF1 */
-       [265] = 0x0000,     /* R265   - LHPF2 */
-
-       [268] = 0x0000,     /* R268   - THREED1 */
-       [269] = 0x0000,     /* R269   - THREED2 */
-       [270] = 0x0000,     /* R270   - THREED3 */
-       [271] = 0x0000,     /* R271   - THREED4 */
-
-       [276] = 0x000C,     /* R276   - DRC 1 */
-       [277] = 0x0925,     /* R277   - DRC 2 */
-       [278] = 0x0000,     /* R278   - DRC 3 */
-       [279] = 0x0000,     /* R279   - DRC 4 */
-       [280] = 0x0000,     /* R280   - DRC 5 */
-
-       [285] = 0x0000,     /* R285   - Tloopback */
-
-       [335] = 0x0004,     /* R335   - EQ1 */
-       [336] = 0x6318,     /* R336   - EQ2 */
-       [337] = 0x6300,     /* R337   - EQ3 */
-       [338] = 0x0FCA,     /* R338   - EQ4 */
-       [339] = 0x0400,     /* R339   - EQ5 */
-       [340] = 0x00D8,     /* R340   - EQ6 */
-       [341] = 0x1EB5,     /* R341   - EQ7 */
-       [342] = 0xF145,     /* R342   - EQ8 */
-       [343] = 0x0B75,     /* R343   - EQ9 */
-       [344] = 0x01C5,     /* R344   - EQ10 */
-       [345] = 0x1C58,     /* R345   - EQ11 */
-       [346] = 0xF373,     /* R346   - EQ12 */
-       [347] = 0x0A54,     /* R347   - EQ13 */
-       [348] = 0x0558,     /* R348   - EQ14 */
-       [349] = 0x168E,     /* R349   - EQ15 */
-       [350] = 0xF829,     /* R350   - EQ16 */
-       [351] = 0x07AD,     /* R351   - EQ17 */
-       [352] = 0x1103,     /* R352   - EQ18 */
-       [353] = 0x0564,     /* R353   - EQ19 */
-       [354] = 0x0559,     /* R354   - EQ20 */
-       [355] = 0x4000,     /* R355   - EQ21 */
-       [356] = 0x6318,     /* R356   - EQ22 */
-       [357] = 0x6300,     /* R357   - EQ23 */
-       [358] = 0x0FCA,     /* R358   - EQ24 */
-       [359] = 0x0400,     /* R359   - EQ25 */
-       [360] = 0x00D8,     /* R360   - EQ26 */
-       [361] = 0x1EB5,     /* R361   - EQ27 */
-       [362] = 0xF145,     /* R362   - EQ28 */
-       [363] = 0x0B75,     /* R363   - EQ29 */
-       [364] = 0x01C5,     /* R364   - EQ30 */
-       [365] = 0x1C58,     /* R365   - EQ31 */
-       [366] = 0xF373,     /* R366   - EQ32 */
-       [367] = 0x0A54,     /* R367   - EQ33 */
-       [368] = 0x0558,     /* R368   - EQ34 */
-       [369] = 0x168E,     /* R369   - EQ35 */
-       [370] = 0xF829,     /* R370   - EQ36 */
-       [371] = 0x07AD,     /* R371   - EQ37 */
-       [372] = 0x1103,     /* R372   - EQ38 */
-       [373] = 0x0564,     /* R373   - EQ39 */
-       [374] = 0x0559,     /* R374   - EQ40 */
-       [375] = 0x4000,     /* R375   - EQ41 */
-
-       [513] = 0x0000,     /* R513   - GPIO 2 */
-       [514] = 0x0000,     /* R514   - GPIO 3 */
-
-       [516] = 0x8100,     /* R516   - GPIO 5 */
-       [517] = 0x8100,     /* R517   - GPIO 6 */
-
-       [560] = 0x0000,     /* R560   - Interrupt Status 1 */
-       [561] = 0x0000,     /* R561   - Interrupt Status 2 */
-
-       [568] = 0x0030,     /* R568   - Interrupt Status 1 Mask */
-       [569] = 0xFFED,     /* R569   - Interrupt Status 2 Mask */
-
-       [576] = 0x0000,     /* R576   - Interrupt Control */
-
-       [584] = 0x002D,     /* R584   - IRQ Debounce */
-
-       [586] = 0x0000,     /* R586   -  MICINT Source Pol */
-
-       [768] = 0x1C00,     /* R768   - DSP2 Power Management */
-
-       [1037] = 0x0000,     /* R1037  - DSP2_ExecControl */
-
-       [8192] = 0x0000,     /* R8192  - DSP2 Instruction RAM 0 */
-
-       [9216] = 0x0030,     /* R9216  - DSP2 Address RAM 2 */
-       [9217] = 0x0000,     /* R9217  - DSP2 Address RAM 1 */
-       [9218] = 0x0000,     /* R9218  - DSP2 Address RAM 0 */
-
-       [12288] = 0x0000,     /* R12288 - DSP2 Data1 RAM 1 */
-       [12289] = 0x0000,     /* R12289 - DSP2 Data1 RAM 0 */
-
-       [13312] = 0x0000,     /* R13312 - DSP2 Data2 RAM 1 */
-       [13313] = 0x0000,     /* R13313 - DSP2 Data2 RAM 0 */
-
-       [14336] = 0x0000,     /* R14336 - DSP2 Data3 RAM 1 */
-       [14337] = 0x0000,     /* R14337 - DSP2 Data3 RAM 0 */
-
-       [15360] = 0x000A,     /* R15360 - DSP2 Coeff RAM 0 */
-
-       [16384] = 0x0000,     /* R16384 - RETUNEADC_SHARED_COEFF_1 */
-       [16385] = 0x0000,     /* R16385 - RETUNEADC_SHARED_COEFF_0 */
-       [16386] = 0x0000,     /* R16386 - RETUNEDAC_SHARED_COEFF_1 */
-       [16387] = 0x0000,     /* R16387 - RETUNEDAC_SHARED_COEFF_0 */
-       [16388] = 0x0000,     /* R16388 - SOUNDSTAGE_ENABLES_1 */
-       [16389] = 0x0000,     /* R16389 - SOUNDSTAGE_ENABLES_0 */
-
-       [16896] = 0x0002,     /* R16896 - HDBASS_AI_1 */
-       [16897] = 0xBD12,     /* R16897 - HDBASS_AI_0 */
-       [16898] = 0x007C,     /* R16898 - HDBASS_AR_1 */
-       [16899] = 0x586C,     /* R16899 - HDBASS_AR_0 */
-       [16900] = 0x0053,     /* R16900 - HDBASS_B_1 */
-       [16901] = 0x8121,     /* R16901 - HDBASS_B_0 */
-       [16902] = 0x003F,     /* R16902 - HDBASS_K_1 */
-       [16903] = 0x8BD8,     /* R16903 - HDBASS_K_0 */
-       [16904] = 0x0032,     /* R16904 - HDBASS_N1_1 */
-       [16905] = 0xF52D,     /* R16905 - HDBASS_N1_0 */
-       [16906] = 0x0065,     /* R16906 - HDBASS_N2_1 */
-       [16907] = 0xAC8C,     /* R16907 - HDBASS_N2_0 */
-       [16908] = 0x006B,     /* R16908 - HDBASS_N3_1 */
-       [16909] = 0xE087,     /* R16909 - HDBASS_N3_0 */
-       [16910] = 0x0072,     /* R16910 - HDBASS_N4_1 */
-       [16911] = 0x1483,     /* R16911 - HDBASS_N4_0 */
-       [16912] = 0x0072,     /* R16912 - HDBASS_N5_1 */
-       [16913] = 0x1483,     /* R16913 - HDBASS_N5_0 */
-       [16914] = 0x0043,     /* R16914 - HDBASS_X1_1 */
-       [16915] = 0x3525,     /* R16915 - HDBASS_X1_0 */
-       [16916] = 0x0006,     /* R16916 - HDBASS_X2_1 */
-       [16917] = 0x6A4A,     /* R16917 - HDBASS_X2_0 */
-       [16918] = 0x0043,     /* R16918 - HDBASS_X3_1 */
-       [16919] = 0x6079,     /* R16919 - HDBASS_X3_0 */
-       [16920] = 0x0008,     /* R16920 - HDBASS_ATK_1 */
-       [16921] = 0x0000,     /* R16921 - HDBASS_ATK_0 */
-       [16922] = 0x0001,     /* R16922 - HDBASS_DCY_1 */
-       [16923] = 0x0000,     /* R16923 - HDBASS_DCY_0 */
-       [16924] = 0x0059,     /* R16924 - HDBASS_PG_1 */
-       [16925] = 0x999A,     /* R16925 - HDBASS_PG_0 */
-
-       [17048] = 0x0083,     /* R17408 - HPF_C_1 */
-       [17049] = 0x98AD,     /* R17409 - HPF_C_0 */
-
-       [17920] = 0x007F,     /* R17920 - ADCL_RETUNE_C1_1 */
-       [17921] = 0xFFFF,     /* R17921 - ADCL_RETUNE_C1_0 */
-       [17922] = 0x0000,     /* R17922 - ADCL_RETUNE_C2_1 */
-       [17923] = 0x0000,     /* R17923 - ADCL_RETUNE_C2_0 */
-       [17924] = 0x0000,     /* R17924 - ADCL_RETUNE_C3_1 */
-       [17925] = 0x0000,     /* R17925 - ADCL_RETUNE_C3_0 */
-       [17926] = 0x0000,     /* R17926 - ADCL_RETUNE_C4_1 */
-       [17927] = 0x0000,     /* R17927 - ADCL_RETUNE_C4_0 */
-       [17928] = 0x0000,     /* R17928 - ADCL_RETUNE_C5_1 */
-       [17929] = 0x0000,     /* R17929 - ADCL_RETUNE_C5_0 */
-       [17930] = 0x0000,     /* R17930 - ADCL_RETUNE_C6_1 */
-       [17931] = 0x0000,     /* R17931 - ADCL_RETUNE_C6_0 */
-       [17932] = 0x0000,     /* R17932 - ADCL_RETUNE_C7_1 */
-       [17933] = 0x0000,     /* R17933 - ADCL_RETUNE_C7_0 */
-       [17934] = 0x0000,     /* R17934 - ADCL_RETUNE_C8_1 */
-       [17935] = 0x0000,     /* R17935 - ADCL_RETUNE_C8_0 */
-       [17936] = 0x0000,     /* R17936 - ADCL_RETUNE_C9_1 */
-       [17937] = 0x0000,     /* R17937 - ADCL_RETUNE_C9_0 */
-       [17938] = 0x0000,     /* R17938 - ADCL_RETUNE_C10_1 */
-       [17939] = 0x0000,     /* R17939 - ADCL_RETUNE_C10_0 */
-       [17940] = 0x0000,     /* R17940 - ADCL_RETUNE_C11_1 */
-       [17941] = 0x0000,     /* R17941 - ADCL_RETUNE_C11_0 */
-       [17942] = 0x0000,     /* R17942 - ADCL_RETUNE_C12_1 */
-       [17943] = 0x0000,     /* R17943 - ADCL_RETUNE_C12_0 */
-       [17944] = 0x0000,     /* R17944 - ADCL_RETUNE_C13_1 */
-       [17945] = 0x0000,     /* R17945 - ADCL_RETUNE_C13_0 */
-       [17946] = 0x0000,     /* R17946 - ADCL_RETUNE_C14_1 */
-       [17947] = 0x0000,     /* R17947 - ADCL_RETUNE_C14_0 */
-       [17948] = 0x0000,     /* R17948 - ADCL_RETUNE_C15_1 */
-       [17949] = 0x0000,     /* R17949 - ADCL_RETUNE_C15_0 */
-       [17950] = 0x0000,     /* R17950 - ADCL_RETUNE_C16_1 */
-       [17951] = 0x0000,     /* R17951 - ADCL_RETUNE_C16_0 */
-       [17952] = 0x0000,     /* R17952 - ADCL_RETUNE_C17_1 */
-       [17953] = 0x0000,     /* R17953 - ADCL_RETUNE_C17_0 */
-       [17954] = 0x0000,     /* R17954 - ADCL_RETUNE_C18_1 */
-       [17955] = 0x0000,     /* R17955 - ADCL_RETUNE_C18_0 */
-       [17956] = 0x0000,     /* R17956 - ADCL_RETUNE_C19_1 */
-       [17957] = 0x0000,     /* R17957 - ADCL_RETUNE_C19_0 */
-       [17958] = 0x0000,     /* R17958 - ADCL_RETUNE_C20_1 */
-       [17959] = 0x0000,     /* R17959 - ADCL_RETUNE_C20_0 */
-       [17960] = 0x0000,     /* R17960 - ADCL_RETUNE_C21_1 */
-       [17961] = 0x0000,     /* R17961 - ADCL_RETUNE_C21_0 */
-       [17962] = 0x0000,     /* R17962 - ADCL_RETUNE_C22_1 */
-       [17963] = 0x0000,     /* R17963 - ADCL_RETUNE_C22_0 */
-       [17964] = 0x0000,     /* R17964 - ADCL_RETUNE_C23_1 */
-       [17965] = 0x0000,     /* R17965 - ADCL_RETUNE_C23_0 */
-       [17966] = 0x0000,     /* R17966 - ADCL_RETUNE_C24_1 */
-       [17967] = 0x0000,     /* R17967 - ADCL_RETUNE_C24_0 */
-       [17968] = 0x0000,     /* R17968 - ADCL_RETUNE_C25_1 */
-       [17969] = 0x0000,     /* R17969 - ADCL_RETUNE_C25_0 */
-       [17970] = 0x0000,     /* R17970 - ADCL_RETUNE_C26_1 */
-       [17971] = 0x0000,     /* R17971 - ADCL_RETUNE_C26_0 */
-       [17972] = 0x0000,     /* R17972 - ADCL_RETUNE_C27_1 */
-       [17973] = 0x0000,     /* R17973 - ADCL_RETUNE_C27_0 */
-       [17974] = 0x0000,     /* R17974 - ADCL_RETUNE_C28_1 */
-       [17975] = 0x0000,     /* R17975 - ADCL_RETUNE_C28_0 */
-       [17976] = 0x0000,     /* R17976 - ADCL_RETUNE_C29_1 */
-       [17977] = 0x0000,     /* R17977 - ADCL_RETUNE_C29_0 */
-       [17978] = 0x0000,     /* R17978 - ADCL_RETUNE_C30_1 */
-       [17979] = 0x0000,     /* R17979 - ADCL_RETUNE_C30_0 */
-       [17980] = 0x0000,     /* R17980 - ADCL_RETUNE_C31_1 */
-       [17981] = 0x0000,     /* R17981 - ADCL_RETUNE_C31_0 */
-       [17982] = 0x0000,     /* R17982 - ADCL_RETUNE_C32_1 */
-       [17983] = 0x0000,     /* R17983 - ADCL_RETUNE_C32_0 */
-
-       [18432] = 0x0020,     /* R18432 - RETUNEADC_PG2_1 */
-       [18433] = 0x0000,     /* R18433 - RETUNEADC_PG2_0 */
-       [18434] = 0x0040,     /* R18434 - RETUNEADC_PG_1 */
-       [18435] = 0x0000,     /* R18435 - RETUNEADC_PG_0 */
-
-       [18944] = 0x007F,     /* R18944 - ADCR_RETUNE_C1_1 */
-       [18945] = 0xFFFF,     /* R18945 - ADCR_RETUNE_C1_0 */
-       [18946] = 0x0000,     /* R18946 - ADCR_RETUNE_C2_1 */
-       [18947] = 0x0000,     /* R18947 - ADCR_RETUNE_C2_0 */
-       [18948] = 0x0000,     /* R18948 - ADCR_RETUNE_C3_1 */
-       [18949] = 0x0000,     /* R18949 - ADCR_RETUNE_C3_0 */
-       [18950] = 0x0000,     /* R18950 - ADCR_RETUNE_C4_1 */
-       [18951] = 0x0000,     /* R18951 - ADCR_RETUNE_C4_0 */
-       [18952] = 0x0000,     /* R18952 - ADCR_RETUNE_C5_1 */
-       [18953] = 0x0000,     /* R18953 - ADCR_RETUNE_C5_0 */
-       [18954] = 0x0000,     /* R18954 - ADCR_RETUNE_C6_1 */
-       [18955] = 0x0000,     /* R18955 - ADCR_RETUNE_C6_0 */
-       [18956] = 0x0000,     /* R18956 - ADCR_RETUNE_C7_1 */
-       [18957] = 0x0000,     /* R18957 - ADCR_RETUNE_C7_0 */
-       [18958] = 0x0000,     /* R18958 - ADCR_RETUNE_C8_1 */
-       [18959] = 0x0000,     /* R18959 - ADCR_RETUNE_C8_0 */
-       [18960] = 0x0000,     /* R18960 - ADCR_RETUNE_C9_1 */
-       [18961] = 0x0000,     /* R18961 - ADCR_RETUNE_C9_0 */
-       [18962] = 0x0000,     /* R18962 - ADCR_RETUNE_C10_1 */
-       [18963] = 0x0000,     /* R18963 - ADCR_RETUNE_C10_0 */
-       [18964] = 0x0000,     /* R18964 - ADCR_RETUNE_C11_1 */
-       [18965] = 0x0000,     /* R18965 - ADCR_RETUNE_C11_0 */
-       [18966] = 0x0000,     /* R18966 - ADCR_RETUNE_C12_1 */
-       [18967] = 0x0000,     /* R18967 - ADCR_RETUNE_C12_0 */
-       [18968] = 0x0000,     /* R18968 - ADCR_RETUNE_C13_1 */
-       [18969] = 0x0000,     /* R18969 - ADCR_RETUNE_C13_0 */
-       [18970] = 0x0000,     /* R18970 - ADCR_RETUNE_C14_1 */
-       [18971] = 0x0000,     /* R18971 - ADCR_RETUNE_C14_0 */
-       [18972] = 0x0000,     /* R18972 - ADCR_RETUNE_C15_1 */
-       [18973] = 0x0000,     /* R18973 - ADCR_RETUNE_C15_0 */
-       [18974] = 0x0000,     /* R18974 - ADCR_RETUNE_C16_1 */
-       [18975] = 0x0000,     /* R18975 - ADCR_RETUNE_C16_0 */
-       [18976] = 0x0000,     /* R18976 - ADCR_RETUNE_C17_1 */
-       [18977] = 0x0000,     /* R18977 - ADCR_RETUNE_C17_0 */
-       [18978] = 0x0000,     /* R18978 - ADCR_RETUNE_C18_1 */
-       [18979] = 0x0000,     /* R18979 - ADCR_RETUNE_C18_0 */
-       [18980] = 0x0000,     /* R18980 - ADCR_RETUNE_C19_1 */
-       [18981] = 0x0000,     /* R18981 - ADCR_RETUNE_C19_0 */
-       [18982] = 0x0000,     /* R18982 - ADCR_RETUNE_C20_1 */
-       [18983] = 0x0000,     /* R18983 - ADCR_RETUNE_C20_0 */
-       [18984] = 0x0000,     /* R18984 - ADCR_RETUNE_C21_1 */
-       [18985] = 0x0000,     /* R18985 - ADCR_RETUNE_C21_0 */
-       [18986] = 0x0000,     /* R18986 - ADCR_RETUNE_C22_1 */
-       [18987] = 0x0000,     /* R18987 - ADCR_RETUNE_C22_0 */
-       [18988] = 0x0000,     /* R18988 - ADCR_RETUNE_C23_1 */
-       [18989] = 0x0000,     /* R18989 - ADCR_RETUNE_C23_0 */
-       [18990] = 0x0000,     /* R18990 - ADCR_RETUNE_C24_1 */
-       [18991] = 0x0000,     /* R18991 - ADCR_RETUNE_C24_0 */
-       [18992] = 0x0000,     /* R18992 - ADCR_RETUNE_C25_1 */
-       [18993] = 0x0000,     /* R18993 - ADCR_RETUNE_C25_0 */
-       [18994] = 0x0000,     /* R18994 - ADCR_RETUNE_C26_1 */
-       [18995] = 0x0000,     /* R18995 - ADCR_RETUNE_C26_0 */
-       [18996] = 0x0000,     /* R18996 - ADCR_RETUNE_C27_1 */
-       [18997] = 0x0000,     /* R18997 - ADCR_RETUNE_C27_0 */
-       [18998] = 0x0000,     /* R18998 - ADCR_RETUNE_C28_1 */
-       [18999] = 0x0000,     /* R18999 - ADCR_RETUNE_C28_0 */
-       [19000] = 0x0000,     /* R19000 - ADCR_RETUNE_C29_1 */
-       [19001] = 0x0000,     /* R19001 - ADCR_RETUNE_C29_0 */
-       [19002] = 0x0000,     /* R19002 - ADCR_RETUNE_C30_1 */
-       [19003] = 0x0000,     /* R19003 - ADCR_RETUNE_C30_0 */
-       [19004] = 0x0000,     /* R19004 - ADCR_RETUNE_C31_1 */
-       [19005] = 0x0000,     /* R19005 - ADCR_RETUNE_C31_0 */
-       [19006] = 0x0000,     /* R19006 - ADCR_RETUNE_C32_1 */
-       [19007] = 0x0000,     /* R19007 - ADCR_RETUNE_C32_0 */
-
-       [19456] = 0x007F,     /* R19456 - DACL_RETUNE_C1_1 */
-       [19457] = 0xFFFF,     /* R19457 - DACL_RETUNE_C1_0 */
-       [19458] = 0x0000,     /* R19458 - DACL_RETUNE_C2_1 */
-       [19459] = 0x0000,     /* R19459 - DACL_RETUNE_C2_0 */
-       [19460] = 0x0000,     /* R19460 - DACL_RETUNE_C3_1 */
-       [19461] = 0x0000,     /* R19461 - DACL_RETUNE_C3_0 */
-       [19462] = 0x0000,     /* R19462 - DACL_RETUNE_C4_1 */
-       [19463] = 0x0000,     /* R19463 - DACL_RETUNE_C4_0 */
-       [19464] = 0x0000,     /* R19464 - DACL_RETUNE_C5_1 */
-       [19465] = 0x0000,     /* R19465 - DACL_RETUNE_C5_0 */
-       [19466] = 0x0000,     /* R19466 - DACL_RETUNE_C6_1 */
-       [19467] = 0x0000,     /* R19467 - DACL_RETUNE_C6_0 */
-       [19468] = 0x0000,     /* R19468 - DACL_RETUNE_C7_1 */
-       [19469] = 0x0000,     /* R19469 - DACL_RETUNE_C7_0 */
-       [19470] = 0x0000,     /* R19470 - DACL_RETUNE_C8_1 */
-       [19471] = 0x0000,     /* R19471 - DACL_RETUNE_C8_0 */
-       [19472] = 0x0000,     /* R19472 - DACL_RETUNE_C9_1 */
-       [19473] = 0x0000,     /* R19473 - DACL_RETUNE_C9_0 */
-       [19474] = 0x0000,     /* R19474 - DACL_RETUNE_C10_1 */
-       [19475] = 0x0000,     /* R19475 - DACL_RETUNE_C10_0 */
-       [19476] = 0x0000,     /* R19476 - DACL_RETUNE_C11_1 */
-       [19477] = 0x0000,     /* R19477 - DACL_RETUNE_C11_0 */
-       [19478] = 0x0000,     /* R19478 - DACL_RETUNE_C12_1 */
-       [19479] = 0x0000,     /* R19479 - DACL_RETUNE_C12_0 */
-       [19480] = 0x0000,     /* R19480 - DACL_RETUNE_C13_1 */
-       [19481] = 0x0000,     /* R19481 - DACL_RETUNE_C13_0 */
-       [19482] = 0x0000,     /* R19482 - DACL_RETUNE_C14_1 */
-       [19483] = 0x0000,     /* R19483 - DACL_RETUNE_C14_0 */
-       [19484] = 0x0000,     /* R19484 - DACL_RETUNE_C15_1 */
-       [19485] = 0x0000,     /* R19485 - DACL_RETUNE_C15_0 */
-       [19486] = 0x0000,     /* R19486 - DACL_RETUNE_C16_1 */
-       [19487] = 0x0000,     /* R19487 - DACL_RETUNE_C16_0 */
-       [19488] = 0x0000,     /* R19488 - DACL_RETUNE_C17_1 */
-       [19489] = 0x0000,     /* R19489 - DACL_RETUNE_C17_0 */
-       [19490] = 0x0000,     /* R19490 - DACL_RETUNE_C18_1 */
-       [19491] = 0x0000,     /* R19491 - DACL_RETUNE_C18_0 */
-       [19492] = 0x0000,     /* R19492 - DACL_RETUNE_C19_1 */
-       [19493] = 0x0000,     /* R19493 - DACL_RETUNE_C19_0 */
-       [19494] = 0x0000,     /* R19494 - DACL_RETUNE_C20_1 */
-       [19495] = 0x0000,     /* R19495 - DACL_RETUNE_C20_0 */
-       [19496] = 0x0000,     /* R19496 - DACL_RETUNE_C21_1 */
-       [19497] = 0x0000,     /* R19497 - DACL_RETUNE_C21_0 */
-       [19498] = 0x0000,     /* R19498 - DACL_RETUNE_C22_1 */
-       [19499] = 0x0000,     /* R19499 - DACL_RETUNE_C22_0 */
-       [19500] = 0x0000,     /* R19500 - DACL_RETUNE_C23_1 */
-       [19501] = 0x0000,     /* R19501 - DACL_RETUNE_C23_0 */
-       [19502] = 0x0000,     /* R19502 - DACL_RETUNE_C24_1 */
-       [19503] = 0x0000,     /* R19503 - DACL_RETUNE_C24_0 */
-       [19504] = 0x0000,     /* R19504 - DACL_RETUNE_C25_1 */
-       [19505] = 0x0000,     /* R19505 - DACL_RETUNE_C25_0 */
-       [19506] = 0x0000,     /* R19506 - DACL_RETUNE_C26_1 */
-       [19507] = 0x0000,     /* R19507 - DACL_RETUNE_C26_0 */
-       [19508] = 0x0000,     /* R19508 - DACL_RETUNE_C27_1 */
-       [19509] = 0x0000,     /* R19509 - DACL_RETUNE_C27_0 */
-       [19510] = 0x0000,     /* R19510 - DACL_RETUNE_C28_1 */
-       [19511] = 0x0000,     /* R19511 - DACL_RETUNE_C28_0 */
-       [19512] = 0x0000,     /* R19512 - DACL_RETUNE_C29_1 */
-       [19513] = 0x0000,     /* R19513 - DACL_RETUNE_C29_0 */
-       [19514] = 0x0000,     /* R19514 - DACL_RETUNE_C30_1 */
-       [19515] = 0x0000,     /* R19515 - DACL_RETUNE_C30_0 */
-       [19516] = 0x0000,     /* R19516 - DACL_RETUNE_C31_1 */
-       [19517] = 0x0000,     /* R19517 - DACL_RETUNE_C31_0 */
-       [19518] = 0x0000,     /* R19518 - DACL_RETUNE_C32_1 */
-       [19519] = 0x0000,     /* R19519 - DACL_RETUNE_C32_0 */
-
-       [19968] = 0x0020,     /* R19968 - RETUNEDAC_PG2_1 */
-       [19969] = 0x0000,     /* R19969 - RETUNEDAC_PG2_0 */
-       [19970] = 0x0040,     /* R19970 - RETUNEDAC_PG_1 */
-       [19971] = 0x0000,     /* R19971 - RETUNEDAC_PG_0 */
-
-       [20480] = 0x007F,     /* R20480 - DACR_RETUNE_C1_1 */
-       [20481] = 0xFFFF,     /* R20481 - DACR_RETUNE_C1_0 */
-       [20482] = 0x0000,     /* R20482 - DACR_RETUNE_C2_1 */
-       [20483] = 0x0000,     /* R20483 - DACR_RETUNE_C2_0 */
-       [20484] = 0x0000,     /* R20484 - DACR_RETUNE_C3_1 */
-       [20485] = 0x0000,     /* R20485 - DACR_RETUNE_C3_0 */
-       [20486] = 0x0000,     /* R20486 - DACR_RETUNE_C4_1 */
-       [20487] = 0x0000,     /* R20487 - DACR_RETUNE_C4_0 */
-       [20488] = 0x0000,     /* R20488 - DACR_RETUNE_C5_1 */
-       [20489] = 0x0000,     /* R20489 - DACR_RETUNE_C5_0 */
-       [20490] = 0x0000,     /* R20490 - DACR_RETUNE_C6_1 */
-       [20491] = 0x0000,     /* R20491 - DACR_RETUNE_C6_0 */
-       [20492] = 0x0000,     /* R20492 - DACR_RETUNE_C7_1 */
-       [20493] = 0x0000,     /* R20493 - DACR_RETUNE_C7_0 */
-       [20494] = 0x0000,     /* R20494 - DACR_RETUNE_C8_1 */
-       [20495] = 0x0000,     /* R20495 - DACR_RETUNE_C8_0 */
-       [20496] = 0x0000,     /* R20496 - DACR_RETUNE_C9_1 */
-       [20497] = 0x0000,     /* R20497 - DACR_RETUNE_C9_0 */
-       [20498] = 0x0000,     /* R20498 - DACR_RETUNE_C10_1 */
-       [20499] = 0x0000,     /* R20499 - DACR_RETUNE_C10_0 */
-       [20500] = 0x0000,     /* R20500 - DACR_RETUNE_C11_1 */
-       [20501] = 0x0000,     /* R20501 - DACR_RETUNE_C11_0 */
-       [20502] = 0x0000,     /* R20502 - DACR_RETUNE_C12_1 */
-       [20503] = 0x0000,     /* R20503 - DACR_RETUNE_C12_0 */
-       [20504] = 0x0000,     /* R20504 - DACR_RETUNE_C13_1 */
-       [20505] = 0x0000,     /* R20505 - DACR_RETUNE_C13_0 */
-       [20506] = 0x0000,     /* R20506 - DACR_RETUNE_C14_1 */
-       [20507] = 0x0000,     /* R20507 - DACR_RETUNE_C14_0 */
-       [20508] = 0x0000,     /* R20508 - DACR_RETUNE_C15_1 */
-       [20509] = 0x0000,     /* R20509 - DACR_RETUNE_C15_0 */
-       [20510] = 0x0000,     /* R20510 - DACR_RETUNE_C16_1 */
-       [20511] = 0x0000,     /* R20511 - DACR_RETUNE_C16_0 */
-       [20512] = 0x0000,     /* R20512 - DACR_RETUNE_C17_1 */
-       [20513] = 0x0000,     /* R20513 - DACR_RETUNE_C17_0 */
-       [20514] = 0x0000,     /* R20514 - DACR_RETUNE_C18_1 */
-       [20515] = 0x0000,     /* R20515 - DACR_RETUNE_C18_0 */
-       [20516] = 0x0000,     /* R20516 - DACR_RETUNE_C19_1 */
-       [20517] = 0x0000,     /* R20517 - DACR_RETUNE_C19_0 */
-       [20518] = 0x0000,     /* R20518 - DACR_RETUNE_C20_1 */
-       [20519] = 0x0000,     /* R20519 - DACR_RETUNE_C20_0 */
-       [20520] = 0x0000,     /* R20520 - DACR_RETUNE_C21_1 */
-       [20521] = 0x0000,     /* R20521 - DACR_RETUNE_C21_0 */
-       [20522] = 0x0000,     /* R20522 - DACR_RETUNE_C22_1 */
-       [20523] = 0x0000,     /* R20523 - DACR_RETUNE_C22_0 */
-       [20524] = 0x0000,     /* R20524 - DACR_RETUNE_C23_1 */
-       [20525] = 0x0000,     /* R20525 - DACR_RETUNE_C23_0 */
-       [20526] = 0x0000,     /* R20526 - DACR_RETUNE_C24_1 */
-       [20527] = 0x0000,     /* R20527 - DACR_RETUNE_C24_0 */
-       [20528] = 0x0000,     /* R20528 - DACR_RETUNE_C25_1 */
-       [20529] = 0x0000,     /* R20529 - DACR_RETUNE_C25_0 */
-       [20530] = 0x0000,     /* R20530 - DACR_RETUNE_C26_1 */
-       [20531] = 0x0000,     /* R20531 - DACR_RETUNE_C26_0 */
-       [20532] = 0x0000,     /* R20532 - DACR_RETUNE_C27_1 */
-       [20533] = 0x0000,     /* R20533 - DACR_RETUNE_C27_0 */
-       [20534] = 0x0000,     /* R20534 - DACR_RETUNE_C28_1 */
-       [20535] = 0x0000,     /* R20535 - DACR_RETUNE_C28_0 */
-       [20536] = 0x0000,     /* R20536 - DACR_RETUNE_C29_1 */
-       [20537] = 0x0000,     /* R20537 - DACR_RETUNE_C29_0 */
-       [20538] = 0x0000,     /* R20538 - DACR_RETUNE_C30_1 */
-       [20539] = 0x0000,     /* R20539 - DACR_RETUNE_C30_0 */
-       [20540] = 0x0000,     /* R20540 - DACR_RETUNE_C31_1 */
-       [20541] = 0x0000,     /* R20541 - DACR_RETUNE_C31_0 */
-       [20542] = 0x0000,     /* R20542 - DACR_RETUNE_C32_1 */
-       [20543] = 0x0000,     /* R20543 - DACR_RETUNE_C32_0 */
-
-       [20992] = 0x008C,     /* R20992 - VSS_XHD2_1 */
-       [20993] = 0x0200,     /* R20993 - VSS_XHD2_0 */
-       [20994] = 0x0035,     /* R20994 - VSS_XHD3_1 */
-       [20995] = 0x0700,     /* R20995 - VSS_XHD3_0 */
-       [20996] = 0x003A,     /* R20996 - VSS_XHN1_1 */
-       [20997] = 0x4100,     /* R20997 - VSS_XHN1_0 */
-       [20998] = 0x008B,     /* R20998 - VSS_XHN2_1 */
-       [20999] = 0x7D00,     /* R20999 - VSS_XHN2_0 */
-       [21000] = 0x003A,     /* R21000 - VSS_XHN3_1 */
-       [21001] = 0x4100,     /* R21001 - VSS_XHN3_0 */
-       [21002] = 0x008C,     /* R21002 - VSS_XLA_1 */
-       [21003] = 0xFEE8,     /* R21003 - VSS_XLA_0 */
-       [21004] = 0x0078,     /* R21004 - VSS_XLB_1 */
-       [21005] = 0x0000,     /* R21005 - VSS_XLB_0 */
-       [21006] = 0x003F,     /* R21006 - VSS_XLG_1 */
-       [21007] = 0xB260,     /* R21007 - VSS_XLG_0 */
-       [21008] = 0x002D,     /* R21008 - VSS_PG2_1 */
-       [21009] = 0x1818,     /* R21009 - VSS_PG2_0 */
-       [21010] = 0x0020,     /* R21010 - VSS_PG_1 */
-       [21011] = 0x0000,     /* R21011 - VSS_PG_0 */
-       [21012] = 0x00F1,     /* R21012 - VSS_XTD1_1 */
-       [21013] = 0x8340,     /* R21013 - VSS_XTD1_0 */
-       [21014] = 0x00FB,     /* R21014 - VSS_XTD2_1 */
-       [21015] = 0x8300,     /* R21015 - VSS_XTD2_0 */
-       [21016] = 0x00EE,     /* R21016 - VSS_XTD3_1 */
-       [21017] = 0xAEC0,     /* R21017 - VSS_XTD3_0 */
-       [21018] = 0x00FB,     /* R21018 - VSS_XTD4_1 */
-       [21019] = 0xAC40,     /* R21019 - VSS_XTD4_0 */
-       [21020] = 0x00F1,     /* R21020 - VSS_XTD5_1 */
-       [21021] = 0x7F80,     /* R21021 - VSS_XTD5_0 */
-       [21022] = 0x00F4,     /* R21022 - VSS_XTD6_1 */
-       [21023] = 0x3B40,     /* R21023 - VSS_XTD6_0 */
-       [21024] = 0x00F5,     /* R21024 - VSS_XTD7_1 */
-       [21025] = 0xFB00,     /* R21025 - VSS_XTD7_0 */
-       [21026] = 0x00EA,     /* R21026 - VSS_XTD8_1 */
-       [21027] = 0x10C0,     /* R21027 - VSS_XTD8_0 */
-       [21028] = 0x00FC,     /* R21028 - VSS_XTD9_1 */
-       [21029] = 0xC580,     /* R21029 - VSS_XTD9_0 */
-       [21030] = 0x00E2,     /* R21030 - VSS_XTD10_1 */
-       [21031] = 0x75C0,     /* R21031 - VSS_XTD10_0 */
-       [21032] = 0x0004,     /* R21032 - VSS_XTD11_1 */
-       [21033] = 0xB480,     /* R21033 - VSS_XTD11_0 */
-       [21034] = 0x00D4,     /* R21034 - VSS_XTD12_1 */
-       [21035] = 0xF980,     /* R21035 - VSS_XTD12_0 */
-       [21036] = 0x0004,     /* R21036 - VSS_XTD13_1 */
-       [21037] = 0x9140,     /* R21037 - VSS_XTD13_0 */
-       [21038] = 0x00D8,     /* R21038 - VSS_XTD14_1 */
-       [21039] = 0xA480,     /* R21039 - VSS_XTD14_0 */
-       [21040] = 0x0002,     /* R21040 - VSS_XTD15_1 */
-       [21041] = 0x3DC0,     /* R21041 - VSS_XTD15_0 */
-       [21042] = 0x00CF,     /* R21042 - VSS_XTD16_1 */
-       [21043] = 0x7A80,     /* R21043 - VSS_XTD16_0 */
-       [21044] = 0x00DC,     /* R21044 - VSS_XTD17_1 */
-       [21045] = 0x0600,     /* R21045 - VSS_XTD17_0 */
-       [21046] = 0x00F2,     /* R21046 - VSS_XTD18_1 */
-       [21047] = 0xDAC0,     /* R21047 - VSS_XTD18_0 */
-       [21048] = 0x00BA,     /* R21048 - VSS_XTD19_1 */
-       [21049] = 0xF340,     /* R21049 - VSS_XTD19_0 */
-       [21050] = 0x000A,     /* R21050 - VSS_XTD20_1 */
-       [21051] = 0x7940,     /* R21051 - VSS_XTD20_0 */
-       [21052] = 0x001C,     /* R21052 - VSS_XTD21_1 */
-       [21053] = 0x0680,     /* R21053 - VSS_XTD21_0 */
-       [21054] = 0x00FD,     /* R21054 - VSS_XTD22_1 */
-       [21055] = 0x2D00,     /* R21055 - VSS_XTD22_0 */
-       [21056] = 0x001C,     /* R21056 - VSS_XTD23_1 */
-       [21057] = 0xE840,     /* R21057 - VSS_XTD23_0 */
-       [21058] = 0x000D,     /* R21058 - VSS_XTD24_1 */
-       [21059] = 0xDC40,     /* R21059 - VSS_XTD24_0 */
-       [21060] = 0x00FC,     /* R21060 - VSS_XTD25_1 */
-       [21061] = 0x9D00,     /* R21061 - VSS_XTD25_0 */
-       [21062] = 0x0009,     /* R21062 - VSS_XTD26_1 */
-       [21063] = 0x5580,     /* R21063 - VSS_XTD26_0 */
-       [21064] = 0x00FE,     /* R21064 - VSS_XTD27_1 */
-       [21065] = 0x7E80,     /* R21065 - VSS_XTD27_0 */
-       [21066] = 0x000E,     /* R21066 - VSS_XTD28_1 */
-       [21067] = 0xAB40,     /* R21067 - VSS_XTD28_0 */
-       [21068] = 0x00F9,     /* R21068 - VSS_XTD29_1 */
-       [21069] = 0x9880,     /* R21069 - VSS_XTD29_0 */
-       [21070] = 0x0009,     /* R21070 - VSS_XTD30_1 */
-       [21071] = 0x87C0,     /* R21071 - VSS_XTD30_0 */
-       [21072] = 0x00FD,     /* R21072 - VSS_XTD31_1 */
-       [21073] = 0x2C40,     /* R21073 - VSS_XTD31_0 */
-       [21074] = 0x0009,     /* R21074 - VSS_XTD32_1 */
-       [21075] = 0x4800,     /* R21075 - VSS_XTD32_0 */
-       [21076] = 0x0003,     /* R21076 - VSS_XTS1_1 */
-       [21077] = 0x5F40,     /* R21077 - VSS_XTS1_0 */
-       [21078] = 0x0000,     /* R21078 - VSS_XTS2_1 */
-       [21079] = 0x8700,     /* R21079 - VSS_XTS2_0 */
-       [21080] = 0x00FA,     /* R21080 - VSS_XTS3_1 */
-       [21081] = 0xE4C0,     /* R21081 - VSS_XTS3_0 */
-       [21082] = 0x0000,     /* R21082 - VSS_XTS4_1 */
-       [21083] = 0x0B40,     /* R21083 - VSS_XTS4_0 */
-       [21084] = 0x0004,     /* R21084 - VSS_XTS5_1 */
-       [21085] = 0xE180,     /* R21085 - VSS_XTS5_0 */
-       [21086] = 0x0001,     /* R21086 - VSS_XTS6_1 */
-       [21087] = 0x1F40,     /* R21087 - VSS_XTS6_0 */
-       [21088] = 0x00F8,     /* R21088 - VSS_XTS7_1 */
-       [21089] = 0xB000,     /* R21089 - VSS_XTS7_0 */
-       [21090] = 0x00FB,     /* R21090 - VSS_XTS8_1 */
-       [21091] = 0xCBC0,     /* R21091 - VSS_XTS8_0 */
-       [21092] = 0x0004,     /* R21092 - VSS_XTS9_1 */
-       [21093] = 0xF380,     /* R21093 - VSS_XTS9_0 */
-       [21094] = 0x0007,     /* R21094 - VSS_XTS10_1 */
-       [21095] = 0xDF40,     /* R21095 - VSS_XTS10_0 */
-       [21096] = 0x00FF,     /* R21096 - VSS_XTS11_1 */
-       [21097] = 0x0700,     /* R21097 - VSS_XTS11_0 */
-       [21098] = 0x00EF,     /* R21098 - VSS_XTS12_1 */
-       [21099] = 0xD700,     /* R21099 - VSS_XTS12_0 */
-       [21100] = 0x00FB,     /* R21100 - VSS_XTS13_1 */
-       [21101] = 0xAF40,     /* R21101 - VSS_XTS13_0 */
-       [21102] = 0x0010,     /* R21102 - VSS_XTS14_1 */
-       [21103] = 0x8A80,     /* R21103 - VSS_XTS14_0 */
-       [21104] = 0x0011,     /* R21104 - VSS_XTS15_1 */
-       [21105] = 0x07C0,     /* R21105 - VSS_XTS15_0 */
-       [21106] = 0x00E0,     /* R21106 - VSS_XTS16_1 */
-       [21107] = 0x0800,     /* R21107 - VSS_XTS16_0 */
-       [21108] = 0x00D2,     /* R21108 - VSS_XTS17_1 */
-       [21109] = 0x7600,     /* R21109 - VSS_XTS17_0 */
-       [21110] = 0x0020,     /* R21110 - VSS_XTS18_1 */
-       [21111] = 0xCF40,     /* R21111 - VSS_XTS18_0 */
-       [21112] = 0x0030,     /* R21112 - VSS_XTS19_1 */
-       [21113] = 0x2340,     /* R21113 - VSS_XTS19_0 */
-       [21114] = 0x00FD,     /* R21114 - VSS_XTS20_1 */
-       [21115] = 0x69C0,     /* R21115 - VSS_XTS20_0 */
-       [21116] = 0x0028,     /* R21116 - VSS_XTS21_1 */
-       [21117] = 0x3500,     /* R21117 - VSS_XTS21_0 */
-       [21118] = 0x0006,     /* R21118 - VSS_XTS22_1 */
-       [21119] = 0x3300,     /* R21119 - VSS_XTS22_0 */
-       [21120] = 0x00D9,     /* R21120 - VSS_XTS23_1 */
-       [21121] = 0xF6C0,     /* R21121 - VSS_XTS23_0 */
-       [21122] = 0x00F3,     /* R21122 - VSS_XTS24_1 */
-       [21123] = 0x3340,     /* R21123 - VSS_XTS24_0 */
-       [21124] = 0x000F,     /* R21124 - VSS_XTS25_1 */
-       [21125] = 0x4200,     /* R21125 - VSS_XTS25_0 */
-       [21126] = 0x0004,     /* R21126 - VSS_XTS26_1 */
-       [21127] = 0x0C80,     /* R21127 - VSS_XTS26_0 */
-       [21128] = 0x00FB,     /* R21128 - VSS_XTS27_1 */
-       [21129] = 0x3F80,     /* R21129 - VSS_XTS27_0 */
-       [21130] = 0x00F7,     /* R21130 - VSS_XTS28_1 */
-       [21131] = 0x57C0,     /* R21131 - VSS_XTS28_0 */
-       [21132] = 0x0003,     /* R21132 - VSS_XTS29_1 */
-       [21133] = 0x5400,     /* R21133 - VSS_XTS29_0 */
-       [21134] = 0x0000,     /* R21134 - VSS_XTS30_1 */
-       [21135] = 0xC6C0,     /* R21135 - VSS_XTS30_0 */
-       [21136] = 0x0003,     /* R21136 - VSS_XTS31_1 */
-       [21137] = 0x12C0,     /* R21137 - VSS_XTS31_0 */
-       [21138] = 0x00FD,     /* R21138 - VSS_XTS32_1 */
-       [21139] = 0x8580,     /* R21139 - VSS_XTS32_0 */
+static struct reg_default wm8962_reg[] = {
+       { 0, 0x009F },   /* R0     - Left Input volume */
+       { 1, 0x049F },   /* R1     - Right Input volume */
+       { 2, 0x0000 },   /* R2     - HPOUTL volume */
+       { 3, 0x0000 },   /* R3     - HPOUTR volume */
+       { 4, 0x0020 },   /* R4     - Clocking1 */
+       { 5, 0x0018 },   /* R5     - ADC & DAC Control 1 */
+       { 6, 0x2008 },   /* R6     - ADC & DAC Control 2 */
+       { 7, 0x000A },   /* R7     - Audio Interface 0 */
+       { 8, 0x01E4 },   /* R8     - Clocking2 */
+       { 9, 0x0300 },   /* R9     - Audio Interface 1 */
+       { 10, 0x00C0 },  /* R10    - Left DAC volume */
+       { 11, 0x00C0 },  /* R11    - Right DAC volume */
+
+       { 14, 0x0040 },   /* R14    - Audio Interface 2 */
+       { 15, 0x6243 },   /* R15    - Software Reset */
+
+       { 17, 0x007B },   /* R17    - ALC1 */
+       { 18, 0x0000 },   /* R18    - ALC2 */
+       { 19, 0x1C32 },   /* R19    - ALC3 */
+       { 20, 0x3200 },   /* R20    - Noise Gate */
+       { 21, 0x00C0 },   /* R21    - Left ADC volume */
+       { 22, 0x00C0 },   /* R22    - Right ADC volume */
+       { 23, 0x0160 },   /* R23    - Additional control(1) */
+       { 24, 0x0000 },   /* R24    - Additional control(2) */
+       { 25, 0x0000 },   /* R25    - Pwr Mgmt (1) */
+       { 26, 0x0000 },   /* R26    - Pwr Mgmt (2) */
+       { 27, 0x0010 },   /* R27    - Additional Control (3) */
+       { 28, 0x0000 },   /* R28    - Anti-pop */
+
+       { 30, 0x005E },   /* R30    - Clocking 3 */
+       { 31, 0x0000 },   /* R31    - Input mixer control (1) */
+       { 32, 0x0145 },   /* R32    - Left input mixer volume */
+       { 33, 0x0145 },   /* R33    - Right input mixer volume */
+       { 34, 0x0009 },   /* R34    - Input mixer control (2) */
+       { 35, 0x0003 },   /* R35    - Input bias control */
+       { 37, 0x0008 },   /* R37    - Left input PGA control */
+       { 38, 0x0008 },   /* R38    - Right input PGA control */
+
+       { 40, 0x0000 },   /* R40    - SPKOUTL volume */
+       { 41, 0x0000 },   /* R41    - SPKOUTR volume */
+
+       { 47, 0x0000 },   /* R47    - Thermal Shutdown Status */
+       { 48, 0x8027 },   /* R48    - Additional Control (4) */
+       { 49, 0x0010 },   /* R49    - Class D Control 1 */
+
+       { 51, 0x0003 },   /* R51    - Class D Control 2 */
+
+       { 56, 0x0506 },   /* R56    - Clocking 4 */
+       { 57, 0x0000 },   /* R57    - DAC DSP Mixing (1) */
+       { 58, 0x0000 },   /* R58    - DAC DSP Mixing (2) */
+
+       { 60, 0x0300 },   /* R60    - DC Servo 0 */
+       { 61, 0x0300 },   /* R61    - DC Servo 1 */
+
+       { 64, 0x0810 },   /* R64    - DC Servo 4 */
+
+       { 66, 0x0000 },   /* R66    - DC Servo 6 */
+
+       { 68, 0x001B },   /* R68    - Analogue PGA Bias */
+       { 69, 0x0000 },   /* R69    - Analogue HP 0 */
+
+       { 71, 0x01FB },   /* R71    - Analogue HP 2 */
+       { 72, 0x0000 },   /* R72    - Charge Pump 1 */
+
+       { 82, 0x0004 },   /* R82    - Charge Pump B */
+
+       { 87, 0x0000 },   /* R87    - Write Sequencer Control 1 */
+
+       { 90, 0x0000 },   /* R90    - Write Sequencer Control 2 */
+
+       { 93, 0x0000 },   /* R93    - Write Sequencer Control 3 */
+       { 94, 0x0000 },   /* R94    - Control Interface */
+
+       { 99, 0x0000 },   /* R99    - Mixer Enables */
+       { 100, 0x0000 },   /* R100   - Headphone Mixer (1) */
+       { 101, 0x0000 },   /* R101   - Headphone Mixer (2) */
+       { 102, 0x013F },   /* R102   - Headphone Mixer (3) */
+       { 103, 0x013F },   /* R103   - Headphone Mixer (4) */
+
+       { 105, 0x0000 },   /* R105   - Speaker Mixer (1) */
+       { 106, 0x0000 },   /* R106   - Speaker Mixer (2) */
+       { 107, 0x013F },   /* R107   - Speaker Mixer (3) */
+       { 108, 0x013F },   /* R108   - Speaker Mixer (4) */
+       { 109, 0x0003 },   /* R109   - Speaker Mixer (5) */
+       { 110, 0x0002 },   /* R110   - Beep Generator (1) */
+
+       { 115, 0x0006 },   /* R115   - Oscillator Trim (3) */
+       { 116, 0x0026 },   /* R116   - Oscillator Trim (4) */
+
+       { 119, 0x0000 },   /* R119   - Oscillator Trim (7) */
+
+       { 124, 0x0011 },   /* R124   - Analogue Clocking1 */
+       { 125, 0x004B },   /* R125   - Analogue Clocking2 */
+       { 126, 0x000D },   /* R126   - Analogue Clocking3 */
+       { 127, 0x0000 },   /* R127   - PLL Software Reset */
+
+       { 129, 0x0000 },   /* R129   - PLL2 */
+
+       { 131, 0x0000 },   /* R131   - PLL 4 */
+
+       { 136, 0x0067 },   /* R136   - PLL 9 */
+       { 137, 0x001C },   /* R137   - PLL 10 */
+       { 138, 0x0071 },   /* R138   - PLL 11 */
+       { 139, 0x00C7 },   /* R139   - PLL 12 */
+       { 140, 0x0067 },   /* R140   - PLL 13 */
+       { 141, 0x0048 },   /* R141   - PLL 14 */
+       { 142, 0x0022 },   /* R142   - PLL 15 */
+       { 143, 0x0097 },   /* R143   - PLL 16 */
+
+       { 155, 0x000C },   /* R155   - FLL Control (1) */
+       { 156, 0x0039 },   /* R156   - FLL Control (2) */
+       { 157, 0x0180 },   /* R157   - FLL Control (3) */
+
+       { 159, 0x0032 },   /* R159   - FLL Control (5) */
+       { 160, 0x0018 },   /* R160   - FLL Control (6) */
+       { 161, 0x007D },   /* R161   - FLL Control (7) */
+       { 162, 0x0008 },   /* R162   - FLL Control (8) */
+
+       { 252, 0x0005 },   /* R252   - General test 1 */
+
+       { 256, 0x0000 },   /* R256   - DF1 */
+       { 257, 0x0000 },   /* R257   - DF2 */
+       { 258, 0x0000 },   /* R258   - DF3 */
+       { 259, 0x0000 },   /* R259   - DF4 */
+       { 260, 0x0000 },   /* R260   - DF5 */
+       { 261, 0x0000 },   /* R261   - DF6 */
+       { 262, 0x0000 },   /* R262   - DF7 */
+
+       { 264, 0x0000 },   /* R264   - LHPF1 */
+       { 265, 0x0000 },   /* R265   - LHPF2 */
+
+       { 268, 0x0000 },   /* R268   - THREED1 */
+       { 269, 0x0000 },   /* R269   - THREED2 */
+       { 270, 0x0000 },   /* R270   - THREED3 */
+       { 271, 0x0000 },   /* R271   - THREED4 */
+
+       { 276, 0x000C },   /* R276   - DRC 1 */
+       { 277, 0x0925 },   /* R277   - DRC 2 */
+       { 278, 0x0000 },   /* R278   - DRC 3 */
+       { 279, 0x0000 },   /* R279   - DRC 4 */
+       { 280, 0x0000 },   /* R280   - DRC 5 */
+
+       { 285, 0x0000 },   /* R285   - Tloopback */
+
+       { 335, 0x0004 },   /* R335   - EQ1 */
+       { 336, 0x6318 },   /* R336   - EQ2 */
+       { 337, 0x6300 },   /* R337   - EQ3 */
+       { 338, 0x0FCA },   /* R338   - EQ4 */
+       { 339, 0x0400 },   /* R339   - EQ5 */
+       { 340, 0x00D8 },   /* R340   - EQ6 */
+       { 341, 0x1EB5 },   /* R341   - EQ7 */
+       { 342, 0xF145 },   /* R342   - EQ8 */
+       { 343, 0x0B75 },   /* R343   - EQ9 */
+       { 344, 0x01C5 },   /* R344   - EQ10 */
+       { 345, 0x1C58 },   /* R345   - EQ11 */
+       { 346, 0xF373 },   /* R346   - EQ12 */
+       { 347, 0x0A54 },   /* R347   - EQ13 */
+       { 348, 0x0558 },   /* R348   - EQ14 */
+       { 349, 0x168E },   /* R349   - EQ15 */
+       { 350, 0xF829 },   /* R350   - EQ16 */
+       { 351, 0x07AD },   /* R351   - EQ17 */
+       { 352, 0x1103 },   /* R352   - EQ18 */
+       { 353, 0x0564 },   /* R353   - EQ19 */
+       { 354, 0x0559 },   /* R354   - EQ20 */
+       { 355, 0x4000 },   /* R355   - EQ21 */
+       { 356, 0x6318 },   /* R356   - EQ22 */
+       { 357, 0x6300 },   /* R357   - EQ23 */
+       { 358, 0x0FCA },   /* R358   - EQ24 */
+       { 359, 0x0400 },   /* R359   - EQ25 */
+       { 360, 0x00D8 },   /* R360   - EQ26 */
+       { 361, 0x1EB5 },   /* R361   - EQ27 */
+       { 362, 0xF145 },   /* R362   - EQ28 */
+       { 363, 0x0B75 },   /* R363   - EQ29 */
+       { 364, 0x01C5 },   /* R364   - EQ30 */
+       { 365, 0x1C58 },   /* R365   - EQ31 */
+       { 366, 0xF373 },   /* R366   - EQ32 */
+       { 367, 0x0A54 },   /* R367   - EQ33 */
+       { 368, 0x0558 },   /* R368   - EQ34 */
+       { 369, 0x168E },   /* R369   - EQ35 */
+       { 370, 0xF829 },   /* R370   - EQ36 */
+       { 371, 0x07AD },   /* R371   - EQ37 */
+       { 372, 0x1103 },   /* R372   - EQ38 */
+       { 373, 0x0564 },   /* R373   - EQ39 */
+       { 374, 0x0559 },   /* R374   - EQ40 */
+       { 375, 0x4000 },   /* R375   - EQ41 */
+
+       { 513, 0x0000 },   /* R513   - GPIO 2 */
+       { 514, 0x0000 },   /* R514   - GPIO 3 */
+
+       { 516, 0x8100 },   /* R516   - GPIO 5 */
+       { 517, 0x8100 },   /* R517   - GPIO 6 */
+
+       { 560, 0x0000 },   /* R560   - Interrupt Status 1 */
+       { 561, 0x0000 },   /* R561   - Interrupt Status 2 */
+
+       { 568, 0x0030 },   /* R568   - Interrupt Status 1 Mask */
+       { 569, 0xFFED },   /* R569   - Interrupt Status 2 Mask */
+
+       { 576, 0x0000 },   /* R576   - Interrupt Control */
+
+       { 584, 0x002D },   /* R584   - IRQ Debounce */
+
+       { 586, 0x0000 },   /* R586   -  MICINT Source Pol */
+
+       { 768, 0x1C00 },   /* R768   - DSP2 Power Management */
+
+       { 1037, 0x0000 },   /* R1037  - DSP2_ExecControl */
+
+       { 8192, 0x0000 },   /* R8192  - DSP2 Instruction RAM 0 */
+
+       { 9216, 0x0030 },   /* R9216  - DSP2 Address RAM 2 */
+       { 9217, 0x0000 },   /* R9217  - DSP2 Address RAM 1 */
+       { 9218, 0x0000 },   /* R9218  - DSP2 Address RAM 0 */
+
+       { 12288, 0x0000 },   /* R12288 - DSP2 Data1 RAM 1 */
+       { 12289, 0x0000 },   /* R12289 - DSP2 Data1 RAM 0 */
+
+       { 13312, 0x0000 },   /* R13312 - DSP2 Data2 RAM 1 */
+       { 13313, 0x0000 },   /* R13313 - DSP2 Data2 RAM 0 */
+
+       { 14336, 0x0000 },   /* R14336 - DSP2 Data3 RAM 1 */
+       { 14337, 0x0000 },   /* R14337 - DSP2 Data3 RAM 0 */
+
+       { 15360, 0x000A },   /* R15360 - DSP2 Coeff RAM 0 */
+
+       { 16384, 0x0000 },   /* R16384 - RETUNEADC_SHARED_COEFF_1 */
+       { 16385, 0x0000 },   /* R16385 - RETUNEADC_SHARED_COEFF_0 */
+       { 16386, 0x0000 },   /* R16386 - RETUNEDAC_SHARED_COEFF_1 */
+       { 16387, 0x0000 },   /* R16387 - RETUNEDAC_SHARED_COEFF_0 */
+       { 16388, 0x0000 },   /* R16388 - SOUNDSTAGE_ENABLES_1 */
+       { 16389, 0x0000 },   /* R16389 - SOUNDSTAGE_ENABLES_0 */
+
+       { 16896, 0x0002 },   /* R16896 - HDBASS_AI_1 */
+       { 16897, 0xBD12 },   /* R16897 - HDBASS_AI_0 */
+       { 16898, 0x007C },   /* R16898 - HDBASS_AR_1 */
+       { 16899, 0x586C },   /* R16899 - HDBASS_AR_0 */
+       { 16900, 0x0053 },   /* R16900 - HDBASS_B_1 */
+       { 16901, 0x8121 },   /* R16901 - HDBASS_B_0 */
+       { 16902, 0x003F },   /* R16902 - HDBASS_K_1 */
+       { 16903, 0x8BD8 },   /* R16903 - HDBASS_K_0 */
+       { 16904, 0x0032 },   /* R16904 - HDBASS_N1_1 */
+       { 16905, 0xF52D },   /* R16905 - HDBASS_N1_0 */
+       { 16906, 0x0065 },   /* R16906 - HDBASS_N2_1 */
+       { 16907, 0xAC8C },   /* R16907 - HDBASS_N2_0 */
+       { 16908, 0x006B },   /* R16908 - HDBASS_N3_1 */
+       { 16909, 0xE087 },   /* R16909 - HDBASS_N3_0 */
+       { 16910, 0x0072 },   /* R16910 - HDBASS_N4_1 */
+       { 16911, 0x1483 },   /* R16911 - HDBASS_N4_0 */
+       { 16912, 0x0072 },   /* R16912 - HDBASS_N5_1 */
+       { 16913, 0x1483 },   /* R16913 - HDBASS_N5_0 */
+       { 16914, 0x0043 },   /* R16914 - HDBASS_X1_1 */
+       { 16915, 0x3525 },   /* R16915 - HDBASS_X1_0 */
+       { 16916, 0x0006 },   /* R16916 - HDBASS_X2_1 */
+       { 16917, 0x6A4A },   /* R16917 - HDBASS_X2_0 */
+       { 16918, 0x0043 },   /* R16918 - HDBASS_X3_1 */
+       { 16919, 0x6079 },   /* R16919 - HDBASS_X3_0 */
+       { 16920, 0x0008 },   /* R16920 - HDBASS_ATK_1 */
+       { 16921, 0x0000 },   /* R16921 - HDBASS_ATK_0 */
+       { 16922, 0x0001 },   /* R16922 - HDBASS_DCY_1 */
+       { 16923, 0x0000 },   /* R16923 - HDBASS_DCY_0 */
+       { 16924, 0x0059 },   /* R16924 - HDBASS_PG_1 */
+       { 16925, 0x999A },   /* R16925 - HDBASS_PG_0 */
+
+       { 17048, 0x0083 },   /* R17408 - HPF_C_1 */
+       { 17049, 0x98AD },   /* R17409 - HPF_C_0 */
+
+       { 17920, 0x007F },   /* R17920 - ADCL_RETUNE_C1_1 */
+       { 17921, 0xFFFF },   /* R17921 - ADCL_RETUNE_C1_0 */
+       { 17922, 0x0000 },   /* R17922 - ADCL_RETUNE_C2_1 */
+       { 17923, 0x0000 },   /* R17923 - ADCL_RETUNE_C2_0 */
+       { 17924, 0x0000 },   /* R17924 - ADCL_RETUNE_C3_1 */
+       { 17925, 0x0000 },   /* R17925 - ADCL_RETUNE_C3_0 */
+       { 17926, 0x0000 },   /* R17926 - ADCL_RETUNE_C4_1 */
+       { 17927, 0x0000 },   /* R17927 - ADCL_RETUNE_C4_0 */
+       { 17928, 0x0000 },   /* R17928 - ADCL_RETUNE_C5_1 */
+       { 17929, 0x0000 },   /* R17929 - ADCL_RETUNE_C5_0 */
+       { 17930, 0x0000 },   /* R17930 - ADCL_RETUNE_C6_1 */
+       { 17931, 0x0000 },   /* R17931 - ADCL_RETUNE_C6_0 */
+       { 17932, 0x0000 },   /* R17932 - ADCL_RETUNE_C7_1 */
+       { 17933, 0x0000 },   /* R17933 - ADCL_RETUNE_C7_0 */
+       { 17934, 0x0000 },   /* R17934 - ADCL_RETUNE_C8_1 */
+       { 17935, 0x0000 },   /* R17935 - ADCL_RETUNE_C8_0 */
+       { 17936, 0x0000 },   /* R17936 - ADCL_RETUNE_C9_1 */
+       { 17937, 0x0000 },   /* R17937 - ADCL_RETUNE_C9_0 */
+       { 17938, 0x0000 },   /* R17938 - ADCL_RETUNE_C10_1 */
+       { 17939, 0x0000 },   /* R17939 - ADCL_RETUNE_C10_0 */
+       { 17940, 0x0000 },   /* R17940 - ADCL_RETUNE_C11_1 */
+       { 17941, 0x0000 },   /* R17941 - ADCL_RETUNE_C11_0 */
+       { 17942, 0x0000 },   /* R17942 - ADCL_RETUNE_C12_1 */
+       { 17943, 0x0000 },   /* R17943 - ADCL_RETUNE_C12_0 */
+       { 17944, 0x0000 },   /* R17944 - ADCL_RETUNE_C13_1 */
+       { 17945, 0x0000 },   /* R17945 - ADCL_RETUNE_C13_0 */
+       { 17946, 0x0000 },   /* R17946 - ADCL_RETUNE_C14_1 */
+       { 17947, 0x0000 },   /* R17947 - ADCL_RETUNE_C14_0 */
+       { 17948, 0x0000 },   /* R17948 - ADCL_RETUNE_C15_1 */
+       { 17949, 0x0000 },   /* R17949 - ADCL_RETUNE_C15_0 */
+       { 17950, 0x0000 },   /* R17950 - ADCL_RETUNE_C16_1 */
+       { 17951, 0x0000 },   /* R17951 - ADCL_RETUNE_C16_0 */
+       { 17952, 0x0000 },   /* R17952 - ADCL_RETUNE_C17_1 */
+       { 17953, 0x0000 },   /* R17953 - ADCL_RETUNE_C17_0 */
+       { 17954, 0x0000 },   /* R17954 - ADCL_RETUNE_C18_1 */
+       { 17955, 0x0000 },   /* R17955 - ADCL_RETUNE_C18_0 */
+       { 17956, 0x0000 },   /* R17956 - ADCL_RETUNE_C19_1 */
+       { 17957, 0x0000 },   /* R17957 - ADCL_RETUNE_C19_0 */
+       { 17958, 0x0000 },   /* R17958 - ADCL_RETUNE_C20_1 */
+       { 17959, 0x0000 },   /* R17959 - ADCL_RETUNE_C20_0 */
+       { 17960, 0x0000 },   /* R17960 - ADCL_RETUNE_C21_1 */
+       { 17961, 0x0000 },   /* R17961 - ADCL_RETUNE_C21_0 */
+       { 17962, 0x0000 },   /* R17962 - ADCL_RETUNE_C22_1 */
+       { 17963, 0x0000 },   /* R17963 - ADCL_RETUNE_C22_0 */
+       { 17964, 0x0000 },   /* R17964 - ADCL_RETUNE_C23_1 */
+       { 17965, 0x0000 },   /* R17965 - ADCL_RETUNE_C23_0 */
+       { 17966, 0x0000 },   /* R17966 - ADCL_RETUNE_C24_1 */
+       { 17967, 0x0000 },   /* R17967 - ADCL_RETUNE_C24_0 */
+       { 17968, 0x0000 },   /* R17968 - ADCL_RETUNE_C25_1 */
+       { 17969, 0x0000 },   /* R17969 - ADCL_RETUNE_C25_0 */
+       { 17970, 0x0000 },   /* R17970 - ADCL_RETUNE_C26_1 */
+       { 17971, 0x0000 },   /* R17971 - ADCL_RETUNE_C26_0 */
+       { 17972, 0x0000 },   /* R17972 - ADCL_RETUNE_C27_1 */
+       { 17973, 0x0000 },   /* R17973 - ADCL_RETUNE_C27_0 */
+       { 17974, 0x0000 },   /* R17974 - ADCL_RETUNE_C28_1 */
+       { 17975, 0x0000 },   /* R17975 - ADCL_RETUNE_C28_0 */
+       { 17976, 0x0000 },   /* R17976 - ADCL_RETUNE_C29_1 */
+       { 17977, 0x0000 },   /* R17977 - ADCL_RETUNE_C29_0 */
+       { 17978, 0x0000 },   /* R17978 - ADCL_RETUNE_C30_1 */
+       { 17979, 0x0000 },   /* R17979 - ADCL_RETUNE_C30_0 */
+       { 17980, 0x0000 },   /* R17980 - ADCL_RETUNE_C31_1 */
+       { 17981, 0x0000 },   /* R17981 - ADCL_RETUNE_C31_0 */
+       { 17982, 0x0000 },   /* R17982 - ADCL_RETUNE_C32_1 */
+       { 17983, 0x0000 },   /* R17983 - ADCL_RETUNE_C32_0 */
+
+       { 18432, 0x0020 },   /* R18432 - RETUNEADC_PG2_1 */
+       { 18433, 0x0000 },   /* R18433 - RETUNEADC_PG2_0 */
+       { 18434, 0x0040 },   /* R18434 - RETUNEADC_PG_1 */
+       { 18435, 0x0000 },   /* R18435 - RETUNEADC_PG_0 */
+
+       { 18944, 0x007F },   /* R18944 - ADCR_RETUNE_C1_1 */
+       { 18945, 0xFFFF },   /* R18945 - ADCR_RETUNE_C1_0 */
+       { 18946, 0x0000 },   /* R18946 - ADCR_RETUNE_C2_1 */
+       { 18947, 0x0000 },   /* R18947 - ADCR_RETUNE_C2_0 */
+       { 18948, 0x0000 },   /* R18948 - ADCR_RETUNE_C3_1 */
+       { 18949, 0x0000 },   /* R18949 - ADCR_RETUNE_C3_0 */
+       { 18950, 0x0000 },   /* R18950 - ADCR_RETUNE_C4_1 */
+       { 18951, 0x0000 },   /* R18951 - ADCR_RETUNE_C4_0 */
+       { 18952, 0x0000 },   /* R18952 - ADCR_RETUNE_C5_1 */
+       { 18953, 0x0000 },   /* R18953 - ADCR_RETUNE_C5_0 */
+       { 18954, 0x0000 },   /* R18954 - ADCR_RETUNE_C6_1 */
+       { 18955, 0x0000 },   /* R18955 - ADCR_RETUNE_C6_0 */
+       { 18956, 0x0000 },   /* R18956 - ADCR_RETUNE_C7_1 */
+       { 18957, 0x0000 },   /* R18957 - ADCR_RETUNE_C7_0 */
+       { 18958, 0x0000 },   /* R18958 - ADCR_RETUNE_C8_1 */
+       { 18959, 0x0000 },   /* R18959 - ADCR_RETUNE_C8_0 */
+       { 18960, 0x0000 },   /* R18960 - ADCR_RETUNE_C9_1 */
+       { 18961, 0x0000 },   /* R18961 - ADCR_RETUNE_C9_0 */
+       { 18962, 0x0000 },   /* R18962 - ADCR_RETUNE_C10_1 */
+       { 18963, 0x0000 },   /* R18963 - ADCR_RETUNE_C10_0 */
+       { 18964, 0x0000 },   /* R18964 - ADCR_RETUNE_C11_1 */
+       { 18965, 0x0000 },   /* R18965 - ADCR_RETUNE_C11_0 */
+       { 18966, 0x0000 },   /* R18966 - ADCR_RETUNE_C12_1 */
+       { 18967, 0x0000 },   /* R18967 - ADCR_RETUNE_C12_0 */
+       { 18968, 0x0000 },   /* R18968 - ADCR_RETUNE_C13_1 */
+       { 18969, 0x0000 },   /* R18969 - ADCR_RETUNE_C13_0 */
+       { 18970, 0x0000 },   /* R18970 - ADCR_RETUNE_C14_1 */
+       { 18971, 0x0000 },   /* R18971 - ADCR_RETUNE_C14_0 */
+       { 18972, 0x0000 },   /* R18972 - ADCR_RETUNE_C15_1 */
+       { 18973, 0x0000 },   /* R18973 - ADCR_RETUNE_C15_0 */
+       { 18974, 0x0000 },   /* R18974 - ADCR_RETUNE_C16_1 */
+       { 18975, 0x0000 },   /* R18975 - ADCR_RETUNE_C16_0 */
+       { 18976, 0x0000 },   /* R18976 - ADCR_RETUNE_C17_1 */
+       { 18977, 0x0000 },   /* R18977 - ADCR_RETUNE_C17_0 */
+       { 18978, 0x0000 },   /* R18978 - ADCR_RETUNE_C18_1 */
+       { 18979, 0x0000 },   /* R18979 - ADCR_RETUNE_C18_0 */
+       { 18980, 0x0000 },   /* R18980 - ADCR_RETUNE_C19_1 */
+       { 18981, 0x0000 },   /* R18981 - ADCR_RETUNE_C19_0 */
+       { 18982, 0x0000 },   /* R18982 - ADCR_RETUNE_C20_1 */
+       { 18983, 0x0000 },   /* R18983 - ADCR_RETUNE_C20_0 */
+       { 18984, 0x0000 },   /* R18984 - ADCR_RETUNE_C21_1 */
+       { 18985, 0x0000 },   /* R18985 - ADCR_RETUNE_C21_0 */
+       { 18986, 0x0000 },   /* R18986 - ADCR_RETUNE_C22_1 */
+       { 18987, 0x0000 },   /* R18987 - ADCR_RETUNE_C22_0 */
+       { 18988, 0x0000 },   /* R18988 - ADCR_RETUNE_C23_1 */
+       { 18989, 0x0000 },   /* R18989 - ADCR_RETUNE_C23_0 */
+       { 18990, 0x0000 },   /* R18990 - ADCR_RETUNE_C24_1 */
+       { 18991, 0x0000 },   /* R18991 - ADCR_RETUNE_C24_0 */
+       { 18992, 0x0000 },   /* R18992 - ADCR_RETUNE_C25_1 */
+       { 18993, 0x0000 },   /* R18993 - ADCR_RETUNE_C25_0 */
+       { 18994, 0x0000 },   /* R18994 - ADCR_RETUNE_C26_1 */
+       { 18995, 0x0000 },   /* R18995 - ADCR_RETUNE_C26_0 */
+       { 18996, 0x0000 },   /* R18996 - ADCR_RETUNE_C27_1 */
+       { 18997, 0x0000 },   /* R18997 - ADCR_RETUNE_C27_0 */
+       { 18998, 0x0000 },   /* R18998 - ADCR_RETUNE_C28_1 */
+       { 18999, 0x0000 },   /* R18999 - ADCR_RETUNE_C28_0 */
+       { 19000, 0x0000 },   /* R19000 - ADCR_RETUNE_C29_1 */
+       { 19001, 0x0000 },   /* R19001 - ADCR_RETUNE_C29_0 */
+       { 19002, 0x0000 },   /* R19002 - ADCR_RETUNE_C30_1 */
+       { 19003, 0x0000 },   /* R19003 - ADCR_RETUNE_C30_0 */
+       { 19004, 0x0000 },   /* R19004 - ADCR_RETUNE_C31_1 */
+       { 19005, 0x0000 },   /* R19005 - ADCR_RETUNE_C31_0 */
+       { 19006, 0x0000 },   /* R19006 - ADCR_RETUNE_C32_1 */
+       { 19007, 0x0000 },   /* R19007 - ADCR_RETUNE_C32_0 */
+
+       { 19456, 0x007F },   /* R19456 - DACL_RETUNE_C1_1 */
+       { 19457, 0xFFFF },   /* R19457 - DACL_RETUNE_C1_0 */
+       { 19458, 0x0000 },   /* R19458 - DACL_RETUNE_C2_1 */
+       { 19459, 0x0000 },   /* R19459 - DACL_RETUNE_C2_0 */
+       { 19460, 0x0000 },   /* R19460 - DACL_RETUNE_C3_1 */
+       { 19461, 0x0000 },   /* R19461 - DACL_RETUNE_C3_0 */
+       { 19462, 0x0000 },   /* R19462 - DACL_RETUNE_C4_1 */
+       { 19463, 0x0000 },   /* R19463 - DACL_RETUNE_C4_0 */
+       { 19464, 0x0000 },   /* R19464 - DACL_RETUNE_C5_1 */
+       { 19465, 0x0000 },   /* R19465 - DACL_RETUNE_C5_0 */
+       { 19466, 0x0000 },   /* R19466 - DACL_RETUNE_C6_1 */
+       { 19467, 0x0000 },   /* R19467 - DACL_RETUNE_C6_0 */
+       { 19468, 0x0000 },   /* R19468 - DACL_RETUNE_C7_1 */
+       { 19469, 0x0000 },   /* R19469 - DACL_RETUNE_C7_0 */
+       { 19470, 0x0000 },   /* R19470 - DACL_RETUNE_C8_1 */
+       { 19471, 0x0000 },   /* R19471 - DACL_RETUNE_C8_0 */
+       { 19472, 0x0000 },   /* R19472 - DACL_RETUNE_C9_1 */
+       { 19473, 0x0000 },   /* R19473 - DACL_RETUNE_C9_0 */
+       { 19474, 0x0000 },   /* R19474 - DACL_RETUNE_C10_1 */
+       { 19475, 0x0000 },   /* R19475 - DACL_RETUNE_C10_0 */
+       { 19476, 0x0000 },   /* R19476 - DACL_RETUNE_C11_1 */
+       { 19477, 0x0000 },   /* R19477 - DACL_RETUNE_C11_0 */
+       { 19478, 0x0000 },   /* R19478 - DACL_RETUNE_C12_1 */
+       { 19479, 0x0000 },   /* R19479 - DACL_RETUNE_C12_0 */
+       { 19480, 0x0000 },   /* R19480 - DACL_RETUNE_C13_1 */
+       { 19481, 0x0000 },   /* R19481 - DACL_RETUNE_C13_0 */
+       { 19482, 0x0000 },   /* R19482 - DACL_RETUNE_C14_1 */
+       { 19483, 0x0000 },   /* R19483 - DACL_RETUNE_C14_0 */
+       { 19484, 0x0000 },   /* R19484 - DACL_RETUNE_C15_1 */
+       { 19485, 0x0000 },   /* R19485 - DACL_RETUNE_C15_0 */
+       { 19486, 0x0000 },   /* R19486 - DACL_RETUNE_C16_1 */
+       { 19487, 0x0000 },   /* R19487 - DACL_RETUNE_C16_0 */
+       { 19488, 0x0000 },   /* R19488 - DACL_RETUNE_C17_1 */
+       { 19489, 0x0000 },   /* R19489 - DACL_RETUNE_C17_0 */
+       { 19490, 0x0000 },   /* R19490 - DACL_RETUNE_C18_1 */
+       { 19491, 0x0000 },   /* R19491 - DACL_RETUNE_C18_0 */
+       { 19492, 0x0000 },   /* R19492 - DACL_RETUNE_C19_1 */
+       { 19493, 0x0000 },   /* R19493 - DACL_RETUNE_C19_0 */
+       { 19494, 0x0000 },   /* R19494 - DACL_RETUNE_C20_1 */
+       { 19495, 0x0000 },   /* R19495 - DACL_RETUNE_C20_0 */
+       { 19496, 0x0000 },   /* R19496 - DACL_RETUNE_C21_1 */
+       { 19497, 0x0000 },   /* R19497 - DACL_RETUNE_C21_0 */
+       { 19498, 0x0000 },   /* R19498 - DACL_RETUNE_C22_1 */
+       { 19499, 0x0000 },   /* R19499 - DACL_RETUNE_C22_0 */
+       { 19500, 0x0000 },   /* R19500 - DACL_RETUNE_C23_1 */
+       { 19501, 0x0000 },   /* R19501 - DACL_RETUNE_C23_0 */
+       { 19502, 0x0000 },   /* R19502 - DACL_RETUNE_C24_1 */
+       { 19503, 0x0000 },   /* R19503 - DACL_RETUNE_C24_0 */
+       { 19504, 0x0000 },   /* R19504 - DACL_RETUNE_C25_1 */
+       { 19505, 0x0000 },   /* R19505 - DACL_RETUNE_C25_0 */
+       { 19506, 0x0000 },   /* R19506 - DACL_RETUNE_C26_1 */
+       { 19507, 0x0000 },   /* R19507 - DACL_RETUNE_C26_0 */
+       { 19508, 0x0000 },   /* R19508 - DACL_RETUNE_C27_1 */
+       { 19509, 0x0000 },   /* R19509 - DACL_RETUNE_C27_0 */
+       { 19510, 0x0000 },   /* R19510 - DACL_RETUNE_C28_1 */
+       { 19511, 0x0000 },   /* R19511 - DACL_RETUNE_C28_0 */
+       { 19512, 0x0000 },   /* R19512 - DACL_RETUNE_C29_1 */
+       { 19513, 0x0000 },   /* R19513 - DACL_RETUNE_C29_0 */
+       { 19514, 0x0000 },   /* R19514 - DACL_RETUNE_C30_1 */
+       { 19515, 0x0000 },   /* R19515 - DACL_RETUNE_C30_0 */
+       { 19516, 0x0000 },   /* R19516 - DACL_RETUNE_C31_1 */
+       { 19517, 0x0000 },   /* R19517 - DACL_RETUNE_C31_0 */
+       { 19518, 0x0000 },   /* R19518 - DACL_RETUNE_C32_1 */
+       { 19519, 0x0000 },   /* R19519 - DACL_RETUNE_C32_0 */
+
+       { 19968, 0x0020 },   /* R19968 - RETUNEDAC_PG2_1 */
+       { 19969, 0x0000 },   /* R19969 - RETUNEDAC_PG2_0 */
+       { 19970, 0x0040 },   /* R19970 - RETUNEDAC_PG_1 */
+       { 19971, 0x0000 },   /* R19971 - RETUNEDAC_PG_0 */
+
+       { 20480, 0x007F },   /* R20480 - DACR_RETUNE_C1_1 */
+       { 20481, 0xFFFF },   /* R20481 - DACR_RETUNE_C1_0 */
+       { 20482, 0x0000 },   /* R20482 - DACR_RETUNE_C2_1 */
+       { 20483, 0x0000 },   /* R20483 - DACR_RETUNE_C2_0 */
+       { 20484, 0x0000 },   /* R20484 - DACR_RETUNE_C3_1 */
+       { 20485, 0x0000 },   /* R20485 - DACR_RETUNE_C3_0 */
+       { 20486, 0x0000 },   /* R20486 - DACR_RETUNE_C4_1 */
+       { 20487, 0x0000 },   /* R20487 - DACR_RETUNE_C4_0 */
+       { 20488, 0x0000 },   /* R20488 - DACR_RETUNE_C5_1 */
+       { 20489, 0x0000 },   /* R20489 - DACR_RETUNE_C5_0 */
+       { 20490, 0x0000 },   /* R20490 - DACR_RETUNE_C6_1 */
+       { 20491, 0x0000 },   /* R20491 - DACR_RETUNE_C6_0 */
+       { 20492, 0x0000 },   /* R20492 - DACR_RETUNE_C7_1 */
+       { 20493, 0x0000 },   /* R20493 - DACR_RETUNE_C7_0 */
+       { 20494, 0x0000 },   /* R20494 - DACR_RETUNE_C8_1 */
+       { 20495, 0x0000 },   /* R20495 - DACR_RETUNE_C8_0 */
+       { 20496, 0x0000 },   /* R20496 - DACR_RETUNE_C9_1 */
+       { 20497, 0x0000 },   /* R20497 - DACR_RETUNE_C9_0 */
+       { 20498, 0x0000 },   /* R20498 - DACR_RETUNE_C10_1 */
+       { 20499, 0x0000 },   /* R20499 - DACR_RETUNE_C10_0 */
+       { 20500, 0x0000 },   /* R20500 - DACR_RETUNE_C11_1 */
+       { 20501, 0x0000 },   /* R20501 - DACR_RETUNE_C11_0 */
+       { 20502, 0x0000 },   /* R20502 - DACR_RETUNE_C12_1 */
+       { 20503, 0x0000 },   /* R20503 - DACR_RETUNE_C12_0 */
+       { 20504, 0x0000 },   /* R20504 - DACR_RETUNE_C13_1 */
+       { 20505, 0x0000 },   /* R20505 - DACR_RETUNE_C13_0 */
+       { 20506, 0x0000 },   /* R20506 - DACR_RETUNE_C14_1 */
+       { 20507, 0x0000 },   /* R20507 - DACR_RETUNE_C14_0 */
+       { 20508, 0x0000 },   /* R20508 - DACR_RETUNE_C15_1 */
+       { 20509, 0x0000 },   /* R20509 - DACR_RETUNE_C15_0 */
+       { 20510, 0x0000 },   /* R20510 - DACR_RETUNE_C16_1 */
+       { 20511, 0x0000 },   /* R20511 - DACR_RETUNE_C16_0 */
+       { 20512, 0x0000 },   /* R20512 - DACR_RETUNE_C17_1 */
+       { 20513, 0x0000 },   /* R20513 - DACR_RETUNE_C17_0 */
+       { 20514, 0x0000 },   /* R20514 - DACR_RETUNE_C18_1 */
+       { 20515, 0x0000 },   /* R20515 - DACR_RETUNE_C18_0 */
+       { 20516, 0x0000 },   /* R20516 - DACR_RETUNE_C19_1 */
+       { 20517, 0x0000 },   /* R20517 - DACR_RETUNE_C19_0 */
+       { 20518, 0x0000 },   /* R20518 - DACR_RETUNE_C20_1 */
+       { 20519, 0x0000 },   /* R20519 - DACR_RETUNE_C20_0 */
+       { 20520, 0x0000 },   /* R20520 - DACR_RETUNE_C21_1 */
+       { 20521, 0x0000 },   /* R20521 - DACR_RETUNE_C21_0 */
+       { 20522, 0x0000 },   /* R20522 - DACR_RETUNE_C22_1 */
+       { 20523, 0x0000 },   /* R20523 - DACR_RETUNE_C22_0 */
+       { 20524, 0x0000 },   /* R20524 - DACR_RETUNE_C23_1 */
+       { 20525, 0x0000 },   /* R20525 - DACR_RETUNE_C23_0 */
+       { 20526, 0x0000 },   /* R20526 - DACR_RETUNE_C24_1 */
+       { 20527, 0x0000 },   /* R20527 - DACR_RETUNE_C24_0 */
+       { 20528, 0x0000 },   /* R20528 - DACR_RETUNE_C25_1 */
+       { 20529, 0x0000 },   /* R20529 - DACR_RETUNE_C25_0 */
+       { 20530, 0x0000 },   /* R20530 - DACR_RETUNE_C26_1 */
+       { 20531, 0x0000 },   /* R20531 - DACR_RETUNE_C26_0 */
+       { 20532, 0x0000 },   /* R20532 - DACR_RETUNE_C27_1 */
+       { 20533, 0x0000 },   /* R20533 - DACR_RETUNE_C27_0 */
+       { 20534, 0x0000 },   /* R20534 - DACR_RETUNE_C28_1 */
+       { 20535, 0x0000 },   /* R20535 - DACR_RETUNE_C28_0 */
+       { 20536, 0x0000 },   /* R20536 - DACR_RETUNE_C29_1 */
+       { 20537, 0x0000 },   /* R20537 - DACR_RETUNE_C29_0 */
+       { 20538, 0x0000 },   /* R20538 - DACR_RETUNE_C30_1 */
+       { 20539, 0x0000 },   /* R20539 - DACR_RETUNE_C30_0 */
+       { 20540, 0x0000 },   /* R20540 - DACR_RETUNE_C31_1 */
+       { 20541, 0x0000 },   /* R20541 - DACR_RETUNE_C31_0 */
+       { 20542, 0x0000 },   /* R20542 - DACR_RETUNE_C32_1 */
+       { 20543, 0x0000 },   /* R20543 - DACR_RETUNE_C32_0 */
+
+       { 20992, 0x008C },   /* R20992 - VSS_XHD2_1 */
+       { 20993, 0x0200 },   /* R20993 - VSS_XHD2_0 */
+       { 20994, 0x0035 },   /* R20994 - VSS_XHD3_1 */
+       { 20995, 0x0700 },   /* R20995 - VSS_XHD3_0 */
+       { 20996, 0x003A },   /* R20996 - VSS_XHN1_1 */
+       { 20997, 0x4100 },   /* R20997 - VSS_XHN1_0 */
+       { 20998, 0x008B },   /* R20998 - VSS_XHN2_1 */
+       { 20999, 0x7D00 },   /* R20999 - VSS_XHN2_0 */
+       { 21000, 0x003A },   /* R21000 - VSS_XHN3_1 */
+       { 21001, 0x4100 },   /* R21001 - VSS_XHN3_0 */
+       { 21002, 0x008C },   /* R21002 - VSS_XLA_1 */
+       { 21003, 0xFEE8 },   /* R21003 - VSS_XLA_0 */
+       { 21004, 0x0078 },   /* R21004 - VSS_XLB_1 */
+       { 21005, 0x0000 },   /* R21005 - VSS_XLB_0 */
+       { 21006, 0x003F },   /* R21006 - VSS_XLG_1 */
+       { 21007, 0xB260 },   /* R21007 - VSS_XLG_0 */
+       { 21008, 0x002D },   /* R21008 - VSS_PG2_1 */
+       { 21009, 0x1818 },   /* R21009 - VSS_PG2_0 */
+       { 21010, 0x0020 },   /* R21010 - VSS_PG_1 */
+       { 21011, 0x0000 },   /* R21011 - VSS_PG_0 */
+       { 21012, 0x00F1 },   /* R21012 - VSS_XTD1_1 */
+       { 21013, 0x8340 },   /* R21013 - VSS_XTD1_0 */
+       { 21014, 0x00FB },   /* R21014 - VSS_XTD2_1 */
+       { 21015, 0x8300 },   /* R21015 - VSS_XTD2_0 */
+       { 21016, 0x00EE },   /* R21016 - VSS_XTD3_1 */
+       { 21017, 0xAEC0 },   /* R21017 - VSS_XTD3_0 */
+       { 21018, 0x00FB },   /* R21018 - VSS_XTD4_1 */
+       { 21019, 0xAC40 },   /* R21019 - VSS_XTD4_0 */
+       { 21020, 0x00F1 },   /* R21020 - VSS_XTD5_1 */
+       { 21021, 0x7F80 },   /* R21021 - VSS_XTD5_0 */
+       { 21022, 0x00F4 },   /* R21022 - VSS_XTD6_1 */
+       { 21023, 0x3B40 },   /* R21023 - VSS_XTD6_0 */
+       { 21024, 0x00F5 },   /* R21024 - VSS_XTD7_1 */
+       { 21025, 0xFB00 },   /* R21025 - VSS_XTD7_0 */
+       { 21026, 0x00EA },   /* R21026 - VSS_XTD8_1 */
+       { 21027, 0x10C0 },   /* R21027 - VSS_XTD8_0 */
+       { 21028, 0x00FC },   /* R21028 - VSS_XTD9_1 */
+       { 21029, 0xC580 },   /* R21029 - VSS_XTD9_0 */
+       { 21030, 0x00E2 },   /* R21030 - VSS_XTD10_1 */
+       { 21031, 0x75C0 },   /* R21031 - VSS_XTD10_0 */
+       { 21032, 0x0004 },   /* R21032 - VSS_XTD11_1 */
+       { 21033, 0xB480 },   /* R21033 - VSS_XTD11_0 */
+       { 21034, 0x00D4 },   /* R21034 - VSS_XTD12_1 */
+       { 21035, 0xF980 },   /* R21035 - VSS_XTD12_0 */
+       { 21036, 0x0004 },   /* R21036 - VSS_XTD13_1 */
+       { 21037, 0x9140 },   /* R21037 - VSS_XTD13_0 */
+       { 21038, 0x00D8 },   /* R21038 - VSS_XTD14_1 */
+       { 21039, 0xA480 },   /* R21039 - VSS_XTD14_0 */
+       { 21040, 0x0002 },   /* R21040 - VSS_XTD15_1 */
+       { 21041, 0x3DC0 },   /* R21041 - VSS_XTD15_0 */
+       { 21042, 0x00CF },   /* R21042 - VSS_XTD16_1 */
+       { 21043, 0x7A80 },   /* R21043 - VSS_XTD16_0 */
+       { 21044, 0x00DC },   /* R21044 - VSS_XTD17_1 */
+       { 21045, 0x0600 },   /* R21045 - VSS_XTD17_0 */
+       { 21046, 0x00F2 },   /* R21046 - VSS_XTD18_1 */
+       { 21047, 0xDAC0 },   /* R21047 - VSS_XTD18_0 */
+       { 21048, 0x00BA },   /* R21048 - VSS_XTD19_1 */
+       { 21049, 0xF340 },   /* R21049 - VSS_XTD19_0 */
+       { 21050, 0x000A },   /* R21050 - VSS_XTD20_1 */
+       { 21051, 0x7940 },   /* R21051 - VSS_XTD20_0 */
+       { 21052, 0x001C },   /* R21052 - VSS_XTD21_1 */
+       { 21053, 0x0680 },   /* R21053 - VSS_XTD21_0 */
+       { 21054, 0x00FD },   /* R21054 - VSS_XTD22_1 */
+       { 21055, 0x2D00 },   /* R21055 - VSS_XTD22_0 */
+       { 21056, 0x001C },   /* R21056 - VSS_XTD23_1 */
+       { 21057, 0xE840 },   /* R21057 - VSS_XTD23_0 */
+       { 21058, 0x000D },   /* R21058 - VSS_XTD24_1 */
+       { 21059, 0xDC40 },   /* R21059 - VSS_XTD24_0 */
+       { 21060, 0x00FC },   /* R21060 - VSS_XTD25_1 */
+       { 21061, 0x9D00 },   /* R21061 - VSS_XTD25_0 */
+       { 21062, 0x0009 },   /* R21062 - VSS_XTD26_1 */
+       { 21063, 0x5580 },   /* R21063 - VSS_XTD26_0 */
+       { 21064, 0x00FE },   /* R21064 - VSS_XTD27_1 */
+       { 21065, 0x7E80 },   /* R21065 - VSS_XTD27_0 */
+       { 21066, 0x000E },   /* R21066 - VSS_XTD28_1 */
+       { 21067, 0xAB40 },   /* R21067 - VSS_XTD28_0 */
+       { 21068, 0x00F9 },   /* R21068 - VSS_XTD29_1 */
+       { 21069, 0x9880 },   /* R21069 - VSS_XTD29_0 */
+       { 21070, 0x0009 },   /* R21070 - VSS_XTD30_1 */
+       { 21071, 0x87C0 },   /* R21071 - VSS_XTD30_0 */
+       { 21072, 0x00FD },   /* R21072 - VSS_XTD31_1 */
+       { 21073, 0x2C40 },   /* R21073 - VSS_XTD31_0 */
+       { 21074, 0x0009 },   /* R21074 - VSS_XTD32_1 */
+       { 21075, 0x4800 },   /* R21075 - VSS_XTD32_0 */
+       { 21076, 0x0003 },   /* R21076 - VSS_XTS1_1 */
+       { 21077, 0x5F40 },   /* R21077 - VSS_XTS1_0 */
+       { 21078, 0x0000 },   /* R21078 - VSS_XTS2_1 */
+       { 21079, 0x8700 },   /* R21079 - VSS_XTS2_0 */
+       { 21080, 0x00FA },   /* R21080 - VSS_XTS3_1 */
+       { 21081, 0xE4C0 },   /* R21081 - VSS_XTS3_0 */
+       { 21082, 0x0000 },   /* R21082 - VSS_XTS4_1 */
+       { 21083, 0x0B40 },   /* R21083 - VSS_XTS4_0 */
+       { 21084, 0x0004 },   /* R21084 - VSS_XTS5_1 */
+       { 21085, 0xE180 },   /* R21085 - VSS_XTS5_0 */
+       { 21086, 0x0001 },   /* R21086 - VSS_XTS6_1 */
+       { 21087, 0x1F40 },   /* R21087 - VSS_XTS6_0 */
+       { 21088, 0x00F8 },   /* R21088 - VSS_XTS7_1 */
+       { 21089, 0xB000 },   /* R21089 - VSS_XTS7_0 */
+       { 21090, 0x00FB },   /* R21090 - VSS_XTS8_1 */
+       { 21091, 0xCBC0 },   /* R21091 - VSS_XTS8_0 */
+       { 21092, 0x0004 },   /* R21092 - VSS_XTS9_1 */
+       { 21093, 0xF380 },   /* R21093 - VSS_XTS9_0 */
+       { 21094, 0x0007 },   /* R21094 - VSS_XTS10_1 */
+       { 21095, 0xDF40 },   /* R21095 - VSS_XTS10_0 */
+       { 21096, 0x00FF },   /* R21096 - VSS_XTS11_1 */
+       { 21097, 0x0700 },   /* R21097 - VSS_XTS11_0 */
+       { 21098, 0x00EF },   /* R21098 - VSS_XTS12_1 */
+       { 21099, 0xD700 },   /* R21099 - VSS_XTS12_0 */
+       { 21100, 0x00FB },   /* R21100 - VSS_XTS13_1 */
+       { 21101, 0xAF40 },   /* R21101 - VSS_XTS13_0 */
+       { 21102, 0x0010 },   /* R21102 - VSS_XTS14_1 */
+       { 21103, 0x8A80 },   /* R21103 - VSS_XTS14_0 */
+       { 21104, 0x0011 },   /* R21104 - VSS_XTS15_1 */
+       { 21105, 0x07C0 },   /* R21105 - VSS_XTS15_0 */
+       { 21106, 0x00E0 },   /* R21106 - VSS_XTS16_1 */
+       { 21107, 0x0800 },   /* R21107 - VSS_XTS16_0 */
+       { 21108, 0x00D2 },   /* R21108 - VSS_XTS17_1 */
+       { 21109, 0x7600 },   /* R21109 - VSS_XTS17_0 */
+       { 21110, 0x0020 },   /* R21110 - VSS_XTS18_1 */
+       { 21111, 0xCF40 },   /* R21111 - VSS_XTS18_0 */
+       { 21112, 0x0030 },   /* R21112 - VSS_XTS19_1 */
+       { 21113, 0x2340 },   /* R21113 - VSS_XTS19_0 */
+       { 21114, 0x00FD },   /* R21114 - VSS_XTS20_1 */
+       { 21115, 0x69C0 },   /* R21115 - VSS_XTS20_0 */
+       { 21116, 0x0028 },   /* R21116 - VSS_XTS21_1 */
+       { 21117, 0x3500 },   /* R21117 - VSS_XTS21_0 */
+       { 21118, 0x0006 },   /* R21118 - VSS_XTS22_1 */
+       { 21119, 0x3300 },   /* R21119 - VSS_XTS22_0 */
+       { 21120, 0x00D9 },   /* R21120 - VSS_XTS23_1 */
+       { 21121, 0xF6C0 },   /* R21121 - VSS_XTS23_0 */
+       { 21122, 0x00F3 },   /* R21122 - VSS_XTS24_1 */
+       { 21123, 0x3340 },   /* R21123 - VSS_XTS24_0 */
+       { 21124, 0x000F },   /* R21124 - VSS_XTS25_1 */
+       { 21125, 0x4200 },   /* R21125 - VSS_XTS25_0 */
+       { 21126, 0x0004 },   /* R21126 - VSS_XTS26_1 */
+       { 21127, 0x0C80 },   /* R21127 - VSS_XTS26_0 */
+       { 21128, 0x00FB },   /* R21128 - VSS_XTS27_1 */
+       { 21129, 0x3F80 },   /* R21129 - VSS_XTS27_0 */
+       { 21130, 0x00F7 },   /* R21130 - VSS_XTS28_1 */
+       { 21131, 0x57C0 },   /* R21131 - VSS_XTS28_0 */
+       { 21132, 0x0003 },   /* R21132 - VSS_XTS29_1 */
+       { 21133, 0x5400 },   /* R21133 - VSS_XTS29_0 */
+       { 21134, 0x0000 },   /* R21134 - VSS_XTS30_1 */
+       { 21135, 0xC6C0 },   /* R21135 - VSS_XTS30_0 */
+       { 21136, 0x0003 },   /* R21136 - VSS_XTS31_1 */
+       { 21137, 0x12C0 },   /* R21137 - VSS_XTS31_0 */
+       { 21138, 0x00FD },   /* R21138 - VSS_XTS32_1 */
+       { 21139, 0x8580 },   /* R21139 - VSS_XTS32_0 */
 };
 
 static const struct wm8962_reg_access {
@@ -802,7 +803,7 @@ static const struct wm8962_reg_access {
        u16 vol;
 } wm8962_reg_access[WM8962_MAX_REGISTER + 1] = {
        [0] = { 0x00FF, 0x01FF, 0x0000 }, /* R0     - Left Input volume */
-       [1] = { 0xFEFF, 0x01FF, 0xFFFF }, /* R1     - Right Input volume */
+       [1] = { 0xFEFF, 0x01FF, 0x0000 }, /* R1     - Right Input volume */
        [2] = { 0x00FF, 0x01FF, 0x0000 }, /* R2     - HPOUTL volume */
        [3] = { 0x00FF, 0x01FF, 0x0000 }, /* R3     - HPOUTR volume */
        [4] = { 0x07FE, 0x07FE, 0xFFFF }, /* R4     - Clocking1 */
@@ -1943,7 +1944,7 @@ static const struct wm8962_reg_access {
        [21139] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21139 - VSS_XTS32_0 */
 };
 
-static int wm8962_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8962_volatile_register(struct device *dev, unsigned int reg)
 {
        if (wm8962_reg_access[reg].vol)
                return 1;
@@ -1951,7 +1952,7 @@ static int wm8962_volatile_register(struct snd_soc_codec *codec, unsigned int re
                return 0;
 }
 
-static int wm8962_readable_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8962_readable_register(struct device *dev, unsigned int reg)
 {
        if (wm8962_reg_access[reg].read)
                return 1;
@@ -1959,21 +1960,21 @@ static int wm8962_readable_register(struct snd_soc_codec *codec, unsigned int re
                return 0;
 }
 
-static int wm8962_reset(struct snd_soc_codec *codec)
+static int wm8962_reset(struct wm8962_priv *wm8962)
 {
        int ret;
 
-       ret = snd_soc_write(codec, WM8962_SOFTWARE_RESET, 0x6243);
+       ret = regmap_write(wm8962->regmap, WM8962_SOFTWARE_RESET, 0x6243);
        if (ret != 0)
                return ret;
 
-       return snd_soc_write(codec, WM8962_PLL_SOFTWARE_RESET, 0);
+       return regmap_write(wm8962->regmap, WM8962_PLL_SOFTWARE_RESET, 0);
 }
 
 static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0);
 static const DECLARE_TLV_DB_SCALE(mixin_tlv, -1500, 300, 0);
 static const unsigned int mixinpga_tlv[] = {
-       TLV_DB_RANGE_HEAD(7),
+       TLV_DB_RANGE_HEAD(5),
        0, 1, TLV_DB_SCALE_ITEM(0, 600, 0),
        2, 2, TLV_DB_SCALE_ITEM(1300, 1300, 0),
        3, 4, TLV_DB_SCALE_ITEM(1800, 200, 0),
@@ -1988,7 +1989,7 @@ static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
 static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
 static const DECLARE_TLV_DB_SCALE(hp_tlv, -700, 100, 0);
 static const unsigned int classd_tlv[] = {
-       TLV_DB_RANGE_HEAD(7),
+       TLV_DB_RANGE_HEAD(2),
        0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
        7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
 };
@@ -2345,6 +2346,10 @@ static int sysclk_event(struct snd_soc_dapm_widget *w,
        int src;
        int fll;
 
+       /* Ignore attempts to run the event during startup */
+       if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
+               return 0;
+
        src = snd_soc_read(codec, WM8962_CLOCKING2) & WM8962_SYSCLK_SRC_MASK;
 
        switch (src) {
@@ -2670,7 +2675,7 @@ SND_SOC_DAPM_INPUT("IN3L"),
 SND_SOC_DAPM_INPUT("IN3R"),
 SND_SOC_DAPM_INPUT("IN4L"),
 SND_SOC_DAPM_INPUT("IN4R"),
-SND_SOC_DAPM_INPUT("Beep"),
+SND_SOC_DAPM_SIGGEN("Beep"),
 SND_SOC_DAPM_INPUT("DMICDAT"),
 
 SND_SOC_DAPM_SUPPLY("MICBIAS", WM8962_PWR_MGMT_1, 1, 0, NULL, 0),
@@ -2684,6 +2689,8 @@ SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY_S("DSP2", 1, WM8962_DSP2_POWER_MANAGEMENT,
                      WM8962_DSP2_ENA_SHIFT, 0, dsp2_event,
                      SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_SUPPLY("TEMP_HP", WM8962_ADDITIONAL_CONTROL_4, 2, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("TEMP_SPK", WM8962_ADDITIONAL_CONTROL_4, 1, 0, NULL, 0),
 
 SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0,
                   inpgal, ARRAY_SIZE(inpgal)),
@@ -2839,6 +2846,9 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = {
 
        { "HPOUTL", NULL, "HPOUT" },
        { "HPOUTR", NULL, "HPOUT" },
+
+       { "HPOUTL", NULL, "TEMP_HP" },
+       { "HPOUTR", NULL, "TEMP_HP" },
 };
 
 static const struct snd_soc_dapm_route wm8962_spk_mono_intercon[] = {
@@ -2855,6 +2865,7 @@ static const struct snd_soc_dapm_route wm8962_spk_mono_intercon[] = {
        { "Speaker Output", NULL, "Speaker PGA" },
        { "Speaker Output", NULL, "SYSCLK" },
        { "Speaker Output", NULL, "TOCLK" },
+       { "Speaker Output", NULL, "TEMP_SPK" },
 
        { "SPKOUT", NULL, "Speaker Output" },
 };
@@ -2883,10 +2894,12 @@ static const struct snd_soc_dapm_route wm8962_spk_stereo_intercon[] = {
        { "SPKOUTL Output", NULL, "SPKOUTL PGA" },
        { "SPKOUTL Output", NULL, "SYSCLK" },
        { "SPKOUTL Output", NULL, "TOCLK" },
+       { "SPKOUTL Output", NULL, "TEMP_SPK" },
 
        { "SPKOUTR Output", NULL, "SPKOUTR PGA" },
        { "SPKOUTR Output", NULL, "SYSCLK" },
        { "SPKOUTR Output", NULL, "TOCLK" },
+       { "SPKOUTR Output", NULL, "TEMP_SPK" },
 
        { "SPKOUTL", NULL, "SPKOUTL Output" },
        { "SPKOUTR", NULL, "SPKOUTR Output" },
@@ -2931,33 +2944,6 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec)
        return 0;
 }
 
-static void wm8962_sync_cache(struct snd_soc_codec *codec)
-{
-       u16 *reg_cache = codec->reg_cache;
-       int i;
-
-       if (!codec->cache_sync)
-               return;
-
-       dev_dbg(codec->dev, "Syncing cache\n");
-
-       codec->cache_only = 0;
-
-       /* Sync back cached values if they're different from the
-        * hardware default.
-        */
-       for (i = 1; i < codec->driver->reg_cache_size; i++) {
-               if (i == WM8962_SOFTWARE_RESET)
-                       continue;
-               if (reg_cache[i] == wm8962_reg[i])
-                       continue;
-
-               snd_soc_write(codec, i, reg_cache[i]);
-       }
-
-       codec->cache_sync = 0;
-}
-
 /* -1 for reserved values */
 static const int bclk_divs[] = {
        1, -1, 2, 3, 4, -1, 6, 8, -1, 12, 16, 24, -1, 32, 32, 32
@@ -3085,7 +3071,8 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec,
                                return ret;
                        }
 
-                       wm8962_sync_cache(codec);
+                       regcache_cache_only(wm8962->regmap, false);
+                       regcache_sync(wm8962->regmap);
 
                        snd_soc_update_bits(codec, WM8962_ANTI_POP,
                                            WM8962_STARTUP_BIAS_ENA |
@@ -3399,6 +3386,7 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
        unsigned long timeout;
        int ret;
        int fll1 = snd_soc_read(codec, WM8962_FLL_CONTROL_1) & WM8962_FLL_ENA;
+       int sysclk = snd_soc_read(codec, WM8962_CLOCKING2) & WM8962_SYSCLK_ENA;
 
        /* Any change? */
        if (source == wm8962->fll_src && Fref == wm8962->fll_fref &&
@@ -3459,6 +3447,9 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 
        try_wait_for_completion(&wm8962->fll_lock);
 
+       if (sysclk)
+               fll1 |= WM8962_FLL_ENA;
+
        snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
                            WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK |
                            WM8962_FLL_ENA, fll1);
@@ -3511,7 +3502,7 @@ static int wm8962_mute(struct snd_soc_dai *dai, int mute)
 #define WM8962_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8962_dai_ops = {
+static const struct snd_soc_dai_ops wm8962_dai_ops = {
        .hw_params = wm8962_hw_params,
        .set_sysclk = wm8962_set_dai_sysclk,
        .set_fmt = wm8962_set_dai_fmt,
@@ -3662,6 +3653,14 @@ int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
        snd_soc_jack_report(wm8962->jack, 0,
                            SND_JACK_MICROPHONE | SND_JACK_BTN_0);
 
+       if (jack) {
+               snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK");
+               snd_soc_dapm_force_enable_pin(&codec->dapm, "MICBIAS");
+       } else {
+               snd_soc_dapm_disable_pin(&codec->dapm, "SYSCLK");
+               snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS");
+       }
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(wm8962_mic_detect);
@@ -3946,26 +3945,12 @@ static int wm8962_probe(struct snd_soc_codec *codec)
        bool dmicclk, dmicdat;
 
        wm8962->codec = codec;
-       INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work);
-       init_completion(&wm8962->fll_lock);
+       codec->control_data = wm8962->regmap;
 
-       codec->cache_sync = 1;
-       codec->dapm.idle_bias_off = 1;
-
-       ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
+       ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
-               goto err;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
-               wm8962->supplies[i].supply = wm8962_supply_names[i];
-
-       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8962->supplies),
-                                wm8962->supplies);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        wm8962->disable_nb[0].notifier_call = wm8962_regulator_event_0;
@@ -3988,43 +3973,6 @@ static int wm8962_probe(struct snd_soc_codec *codec)
                }
        }
 
-       ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
-                                   wm8962->supplies);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
-               goto err_get;
-       }
-
-       ret = snd_soc_read(codec, WM8962_SOFTWARE_RESET);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to read ID register\n");
-               goto err_enable;
-       }
-       if (ret != wm8962_reg[WM8962_SOFTWARE_RESET]) {
-               dev_err(codec->dev, "Device is not a WM8962, ID %x != %x\n",
-                       ret, wm8962_reg[WM8962_SOFTWARE_RESET]);
-               ret = -EINVAL;
-               goto err_enable;
-       }
-
-       ret = snd_soc_read(codec, WM8962_RIGHT_INPUT_VOLUME);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to read device revision: %d\n",
-                       ret);
-               goto err_enable;
-       }
-       
-       dev_info(codec->dev, "customer id %x revision %c\n",
-                (ret & WM8962_CUST_ID_MASK) >> WM8962_CUST_ID_SHIFT,
-                ((ret & WM8962_CHIP_REV_MASK) >> WM8962_CHIP_REV_SHIFT)
-                + 'A');
-
-       ret = wm8962_reset(codec);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to issue reset\n");
-               goto err_enable;
-       }
-
        /* SYSCLK defaults to on; make sure it is off so we can safely
         * write to registers if the device is declocked.
         */
@@ -4039,8 +3987,6 @@ static int wm8962_probe(struct snd_soc_codec *codec)
                            WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA,
                            0);
 
-       regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
-
        if (pdata) {
                /* Apply static configuration for GPIOs */
                for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++)
@@ -4091,6 +4037,12 @@ static int wm8962_probe(struct snd_soc_codec *codec)
        /* Stereo control for EQ */
        snd_soc_update_bits(codec, WM8962_EQ1, WM8962_EQ_SHARED_COEFF, 0);
 
+       /* Don't debouce interrupts so we don't need SYSCLK */
+       snd_soc_update_bits(codec, WM8962_IRQ_DEBOUNCE,
+                           WM8962_FLL_LOCK_DB | WM8962_PLL3_LOCK_DB |
+                           WM8962_PLL2_LOCK_DB | WM8962_TEMP_SHUT_DB,
+                           0);
+
        wm8962_add_widgets(codec);
 
        /* Save boards having to disable DMIC when not in use */
@@ -4150,13 +4102,6 @@ static int wm8962_probe(struct snd_soc_codec *codec)
        }
 
        return 0;
-
-err_enable:
-       regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
-err_get:
-       regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
-err:
-       return ret;
 }
 
 static int wm8962_remove(struct snd_soc_codec *codec)
@@ -4174,7 +4119,6 @@ static int wm8962_remove(struct snd_soc_codec *codec)
        for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
                regulator_unregister_notifier(wm8962->supplies[i].consumer,
                                              &wm8962->disable_nb[i]);
-       regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
 
        return 0;
 }
@@ -4183,41 +4127,132 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8962 = {
        .probe =        wm8962_probe,
        .remove =       wm8962_remove,
        .set_bias_level = wm8962_set_bias_level,
-       .reg_cache_size = WM8962_MAX_REGISTER + 1,
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8962_reg,
-       .volatile_register = wm8962_volatile_register,
-       .readable_register = wm8962_readable_register,
        .set_pll = wm8962_set_fll,
 };
 
+static const struct regmap_config wm8962_regmap = {
+       .reg_bits = 16,
+       .val_bits = 16,
+
+       .max_register = WM8962_MAX_REGISTER,
+       .reg_defaults = wm8962_reg,
+       .num_reg_defaults = ARRAY_SIZE(wm8962_reg),
+       .volatile_reg = wm8962_volatile_register,
+       .readable_reg = wm8962_readable_register,
+       .cache_type = REGCACHE_RBTREE,
+};
+
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm8962_priv *wm8962;
-       int ret;
+       unsigned int reg;
+       int ret, i;
 
-       wm8962 = kzalloc(sizeof(struct wm8962_priv), GFP_KERNEL);
+       wm8962 = devm_kzalloc(&i2c->dev, sizeof(struct wm8962_priv),
+                             GFP_KERNEL);
        if (wm8962 == NULL)
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm8962);
 
+       INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work);
+       init_completion(&wm8962->fll_lock);
        wm8962->irq = i2c->irq;
 
+       for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
+               wm8962->supplies[i].supply = wm8962_supply_names[i];
+
+       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8962->supplies),
+                                wm8962->supplies);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
+               goto err;
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
+                                   wm8962->supplies);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
+               goto err_get;
+       }
+
+       wm8962->regmap = regmap_init_i2c(i2c, &wm8962_regmap);
+       if (IS_ERR(wm8962->regmap)) {
+               ret = PTR_ERR(wm8962->regmap);
+               dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+               goto err_enable;
+       }
+
+       /*
+        * We haven't marked the chip revision as volatile due to
+        * sharing a register with the right input volume; explicitly
+        * bypass the cache to read it.
+        */
+       regcache_cache_bypass(wm8962->regmap, true);
+
+       ret = regmap_read(wm8962->regmap, WM8962_SOFTWARE_RESET, &reg);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to read ID register\n");
+               goto err_regmap;
+       }
+       if (reg != 0x6243) {
+               dev_err(&i2c->dev,
+                       "Device is not a WM8962, ID %x != 0x6243\n", ret);
+               ret = -EINVAL;
+               goto err_regmap;
+       }
+
+       ret = regmap_read(wm8962->regmap, WM8962_RIGHT_INPUT_VOLUME, &reg);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to read device revision: %d\n",
+                       ret);
+               goto err_regmap;
+       }
+
+       dev_info(&i2c->dev, "customer id %x revision %c\n",
+                (reg & WM8962_CUST_ID_MASK) >> WM8962_CUST_ID_SHIFT,
+                ((reg & WM8962_CHIP_REV_MASK) >> WM8962_CHIP_REV_SHIFT)
+                + 'A');
+
+       regcache_cache_bypass(wm8962->regmap, false);
+
+       ret = wm8962_reset(wm8962);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to issue reset\n");
+               goto err_regmap;
+       }
+
+       regcache_cache_only(wm8962->regmap, true);
+
        ret = snd_soc_register_codec(&i2c->dev,
                                     &soc_codec_dev_wm8962, &wm8962_dai, 1);
        if (ret < 0)
-               kfree(wm8962);
+               goto err_regmap;
+
+       /* The drivers should power up as needed */
+       regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+
+       return 0;
 
+err_regmap:
+       regmap_exit(wm8962->regmap);
+err_enable:
+       regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+err_get:
+       regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+err:
        return ret;
 }
 
 static __devexit int wm8962_i2c_remove(struct i2c_client *client)
 {
+       struct wm8962_priv *wm8962 = dev_get_drvdata(&client->dev);
+
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+       regmap_exit(wm8962->regmap);
+       regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
        return 0;
 }
 
index b444b29..4af8936 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -224,7 +223,7 @@ static const struct snd_soc_dapm_widget wm8971_dapm_widgets[] = {
        SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8971_PWR2, 8, 0),
        SND_SOC_DAPM_PGA("Mono Out 1", WM8971_PWR2, 2, 0, NULL, 0),
 
-       SND_SOC_DAPM_MICBIAS("Mic Bias", WM8971_PWR1, 1, 0),
+       SND_SOC_DAPM_SUPPLY("Mic Bias", WM8971_PWR1, 1, 0, NULL, 0),
        SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8971_PWR1, 2, 0),
        SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8971_PWR1, 3, 0),
 
@@ -567,7 +566,7 @@ static int wm8971_set_bias_level(struct snd_soc_codec *codec,
 #define WM8971_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
        SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8971_dai_ops = {
+static const struct snd_soc_dai_ops wm8971_dai_ops = {
        .hw_params      = wm8971_pcm_hw_params,
        .digital_mute   = wm8971_mute,
        .set_fmt        = wm8971_set_dai_fmt,
@@ -600,7 +599,7 @@ static void wm8971_work(struct work_struct *work)
        wm8971_set_bias_level(codec, codec->dapm.bias_level);
 }
 
-static int wm8971_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8971_suspend(struct snd_soc_codec *codec)
 {
        wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -725,7 +724,7 @@ MODULE_DEVICE_TABLE(i2c, wm8971_i2c_id);
 
 static struct i2c_driver wm8971_i2c_driver = {
        .driver = {
-               .name = "wm8971-codec",
+               .name = "wm8971",
                .owner = THIS_MODULE,
        },
        .probe =    wm8971_i2c_probe,
index 9352f1e..4a6a7b5 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -226,7 +225,7 @@ SND_SOC_DAPM_MIXER("Input PGA", WM8974_POWER2, 2, 0, wm8974_inpga,
 SND_SOC_DAPM_MIXER("Boost Mixer", WM8974_POWER2, 4, 0,
                   wm8974_boost_mixer, ARRAY_SIZE(wm8974_boost_mixer)),
 
-SND_SOC_DAPM_MICBIAS("Mic Bias", WM8974_POWER1, 4, 0),
+SND_SOC_DAPM_SUPPLY("Mic Bias", WM8974_POWER1, 4, 0, NULL, 0),
 
 SND_SOC_DAPM_INPUT("MICN"),
 SND_SOC_DAPM_INPUT("MICP"),
@@ -557,7 +556,7 @@ static int wm8974_set_bias_level(struct snd_soc_codec *codec,
 #define WM8974_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
        SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8974_ops = {
+static const struct snd_soc_dai_ops wm8974_ops = {
        .hw_params = wm8974_pcm_hw_params,
        .digital_mute = wm8974_mute,
        .set_fmt = wm8974_set_dai_fmt,
@@ -583,7 +582,7 @@ static struct snd_soc_dai_driver wm8974_dai = {
        .symmetric_rates = 1,
 };
 
-static int wm8974_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8974_suspend(struct snd_soc_codec *codec)
 {
        wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -672,7 +671,7 @@ MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id);
 
 static struct i2c_driver wm8974_i2c_driver = {
        .driver = {
-               .name = "wm8974-codec",
+               .name = "wm8974",
                .owner = THIS_MODULE,
        },
        .probe =    wm8974_i2c_probe,
index 41ca4d9..85d514d 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -865,7 +864,7 @@ static int wm8978_set_bias_level(struct snd_soc_codec *codec,
 #define WM8978_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8978_dai_ops = {
+static const struct snd_soc_dai_ops wm8978_dai_ops = {
        .hw_params      = wm8978_hw_params,
        .digital_mute   = wm8978_mute,
        .set_fmt        = wm8978_set_dai_fmt,
@@ -893,7 +892,7 @@ static struct snd_soc_dai_driver wm8978_dai = {
        .ops = &wm8978_dai_ops,
 };
 
-static int wm8978_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8978_suspend(struct snd_soc_codec *codec)
 {
        wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF);
        /* Also switch PLL off */
index 93ee284..cebde56 100644 (file)
@@ -481,7 +481,8 @@ static const struct snd_soc_dapm_widget wm8983_dapm_widgets[] = {
        SND_SOC_DAPM_PGA("OUT4 Out", WM8983_POWER_MANAGEMENT_3,
                         8, 0, NULL, 0),
 
-       SND_SOC_DAPM_MICBIAS("Mic Bias", WM8983_POWER_MANAGEMENT_1, 4, 0),
+       SND_SOC_DAPM_SUPPLY("Mic Bias", WM8983_POWER_MANAGEMENT_1, 4, 0,
+                           NULL, 0),
 
        SND_SOC_DAPM_INPUT("LIN"),
        SND_SOC_DAPM_INPUT("LIP"),
@@ -973,7 +974,7 @@ static int wm8983_set_bias_level(struct snd_soc_codec *codec,
 }
 
 #ifdef CONFIG_PM
-static int wm8983_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8983_suspend(struct snd_soc_codec *codec)
 {
        wm8983_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -1034,7 +1035,7 @@ static int wm8983_probe(struct snd_soc_codec *codec)
        return 0;
 }
 
-static struct snd_soc_dai_ops wm8983_dai_ops = {
+static const struct snd_soc_dai_ops wm8983_dai_ops = {
        .digital_mute = wm8983_dac_mute,
        .hw_params = wm8983_hw_params,
        .set_fmt = wm8983_set_fmt,
index bae510a..c0c86b3 100644 (file)
@@ -411,7 +411,8 @@ static const struct snd_soc_dapm_widget wm8985_dapm_widgets[] = {
        SND_SOC_DAPM_PGA("Right Speaker Out", WM8985_POWER_MANAGEMENT_3,
                6, 0, NULL, 0),
 
-       SND_SOC_DAPM_MICBIAS("Mic Bias", WM8985_POWER_MANAGEMENT_1, 4, 0),
+       SND_SOC_DAPM_SUPPLY("Mic Bias", WM8985_POWER_MANAGEMENT_1, 4, 0,
+                           NULL, 0),
 
        SND_SOC_DAPM_INPUT("LIN"),
        SND_SOC_DAPM_INPUT("LIP"),
@@ -944,7 +945,7 @@ static int wm8985_set_bias_level(struct snd_soc_codec *codec,
 }
 
 #ifdef CONFIG_PM
-static int wm8985_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8985_suspend(struct snd_soc_codec *codec)
 {
        wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -1030,7 +1031,7 @@ err_reg_get:
        return ret;
 }
 
-static struct snd_soc_dai_ops wm8985_dai_ops = {
+static const struct snd_soc_dai_ops wm8985_dai_ops = {
        .digital_mute = wm8985_dac_mute,
        .hw_params = wm8985_hw_params,
        .set_fmt = wm8985_set_fmt,
index 2e9eba7..ab52963 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -267,7 +266,7 @@ static const struct snd_kcontrol_new wm8988_monomux_controls =
        SOC_DAPM_ENUM("Route", monomux);
 
 static const struct snd_soc_dapm_widget wm8988_dapm_widgets[] = {
-       SND_SOC_DAPM_MICBIAS("Mic Bias", WM8988_PWR1, 1, 0),
+       SND_SOC_DAPM_SUPPLY("Mic Bias", WM8988_PWR1, 1, 0, NULL, 0),
 
        SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
                &wm8988_diffmux_controls),
@@ -701,7 +700,7 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
 #define WM8988_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
        SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8988_ops = {
+static const struct snd_soc_dai_ops wm8988_ops = {
        .startup = wm8988_pcm_startup,
        .hw_params = wm8988_pcm_hw_params,
        .set_fmt = wm8988_set_dai_fmt,
@@ -729,7 +728,7 @@ static struct snd_soc_dai_driver wm8988_dai = {
        .symmetric_rates = 1,
 };
 
-static int wm8988_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8988_suspend(struct snd_soc_codec *codec)
 {
        wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -823,7 +822,7 @@ static int __devexit wm8988_spi_remove(struct spi_device *spi)
 
 static struct spi_driver wm8988_spi_driver = {
        .driver = {
-               .name   = "wm8988-codec",
+               .name   = "wm8988",
                .owner  = THIS_MODULE,
        },
        .probe          = wm8988_spi_probe,
index d29a962..e538eda 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -776,8 +775,8 @@ SND_SOC_DAPM_PGA("ROPGA", WM8990_POWER_MANAGEMENT_3, WM8990_ROPGA_ENA_BIT, 0,
        NULL, 0),
 
 /* MICBIAS */
-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8990_POWER_MANAGEMENT_1,
-       WM8990_MICBIAS_ENA_BIT, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8990_POWER_MANAGEMENT_1,
+                   WM8990_MICBIAS_ENA_BIT, 0, NULL, 0),
 
 SND_SOC_DAPM_OUTPUT("LON"),
 SND_SOC_DAPM_OUTPUT("LOP"),
@@ -1287,7 +1286,7 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
  * 1. ADC/DAC on Primary Interface
  * 2. ADC on Primary Interface/DAC on secondary
  */
-static struct snd_soc_dai_ops wm8990_dai_ops = {
+static const struct snd_soc_dai_ops wm8990_dai_ops = {
        .hw_params      = wm8990_hw_params,
        .digital_mute   = wm8990_mute,
        .set_fmt        = wm8990_set_dai_fmt,
@@ -1314,7 +1313,7 @@ static struct snd_soc_dai_driver wm8990_dai = {
        .ops = &wm8990_dai_ops,
 };
 
-static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8990_suspend(struct snd_soc_codec *codec)
 {
        wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -1418,7 +1417,7 @@ MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id);
 
 static struct i2c_driver wm8990_i2c_driver = {
        .driver = {
-               .name = "wm8990-codec",
+               .name = "wm8990",
                .owner = THIS_MODULE,
        },
        .probe =    wm8990_i2c_probe,
index c9ab3ba..7ee40da 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -770,8 +769,8 @@ static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = {
                NULL, 0),
 
        /* MICBIAS */
-       SND_SOC_DAPM_MICBIAS("MICBIAS", WM8991_POWER_MANAGEMENT_1,
-               WM8991_MICBIAS_ENA_BIT, 0),
+       SND_SOC_DAPM_SUPPLY("MICBIAS", WM8991_POWER_MANAGEMENT_1,
+                           WM8991_MICBIAS_ENA_BIT, 0, NULL, 0),
 
        SND_SOC_DAPM_OUTPUT("LON"),
        SND_SOC_DAPM_OUTPUT("LOP"),
@@ -1241,7 +1240,7 @@ static int wm8991_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-static int wm8991_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8991_suspend(struct snd_soc_codec *codec)
 {
        wm8991_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -1311,7 +1310,7 @@ static int wm8991_probe(struct snd_soc_codec *codec)
 #define WM8991_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops wm8991_ops = {
+static const struct snd_soc_dai_ops wm8991_ops = {
        .hw_params = wm8991_hw_params,
        .digital_mute = wm8991_mute,
        .set_fmt = wm8991_set_dai_fmt,
index eec8e14..f472ea6 100644 (file)
@@ -512,7 +512,7 @@ static const DECLARE_TLV_DB_SCALE(drc_comp_threash, -4500, 75, 0);
 static const DECLARE_TLV_DB_SCALE(drc_comp_amp, -2250, 75, 0);
 static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0);
 static const unsigned int drc_max_tlv[] = {
-       TLV_DB_RANGE_HEAD(4),
+       TLV_DB_RANGE_HEAD(2),
        0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0),
        3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0),
 };
@@ -1394,7 +1394,7 @@ out:
        return 0;
 }
 
-static struct snd_soc_dai_ops wm8993_ops = {
+static const struct snd_soc_dai_ops wm8993_ops = {
        .set_sysclk = wm8993_set_sysclk,
        .set_fmt = wm8993_set_dai_fmt,
        .hw_params = wm8993_hw_params,
@@ -1544,7 +1544,7 @@ static int wm8993_remove(struct snd_soc_codec *codec)
 }
 
 #ifdef CONFIG_PM
-static int wm8993_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8993_suspend(struct snd_soc_codec *codec)
 {
        struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
        int fll_fout = wm8993->fll_fout;
@@ -1641,7 +1641,7 @@ MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id);
 
 static struct i2c_driver wm8993_i2c_driver = {
        .driver = {
-               .name = "wm8993-codec",
+               .name = "wm8993",
                .owner = THIS_MODULE,
        },
        .probe =    wm8993_i2c_probe,
index 9c982e4..3eaf56a 100644 (file)
 #include "wm8994.h"
 #include "wm_hubs.h"
 
+#define WM1811_JACKDET_MODE_NONE  0x0000
+#define WM1811_JACKDET_MODE_JACK  0x0100
+#define WM1811_JACKDET_MODE_MIC   0x0080
+#define WM1811_JACKDET_MODE_AUDIO 0x0180
+
 #define WM8994_NUM_DRC 3
 #define WM8994_NUM_EQ  3
 
@@ -53,10 +58,75 @@ static int wm8994_retune_mobile_base[] = {
        WM8994_AIF2_EQ_GAINS_1,
 };
 
+static void wm8958_default_micdet(u16 status, void *data);
+
+static const struct wm8958_micd_rate micdet_rates[] = {
+       { 32768,       true,  1, 4 },
+       { 32768,       false, 1, 1 },
+       { 44100 * 256, true,  7, 10 },
+       { 44100 * 256, false, 7, 10 },
+};
+
+static const struct wm8958_micd_rate jackdet_rates[] = {
+       { 32768,       true,  0, 1 },
+       { 32768,       false, 0, 1 },
+       { 44100 * 256, true,  7, 10 },
+       { 44100 * 256, false, 7, 10 },
+};
+
+static void wm8958_micd_set_rate(struct snd_soc_codec *codec)
+{
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       int best, i, sysclk, val;
+       bool idle;
+       const struct wm8958_micd_rate *rates;
+       int num_rates;
+
+       if (wm8994->jack_cb != wm8958_default_micdet)
+               return;
+
+       idle = !wm8994->jack_mic;
+
+       sysclk = snd_soc_read(codec, WM8994_CLOCKING_1);
+       if (sysclk & WM8994_SYSCLK_SRC)
+               sysclk = wm8994->aifclk[1];
+       else
+               sysclk = wm8994->aifclk[0];
+
+       if (wm8994->pdata && wm8994->pdata->micd_rates) {
+               rates = wm8994->pdata->micd_rates;
+               num_rates = wm8994->pdata->num_micd_rates;
+       } else if (wm8994->jackdet) {
+               rates = jackdet_rates;
+               num_rates = ARRAY_SIZE(jackdet_rates);
+       } else {
+               rates = micdet_rates;
+               num_rates = ARRAY_SIZE(micdet_rates);
+       }
+
+       best = 0;
+       for (i = 0; i < num_rates; i++) {
+               if (rates[i].idle != idle)
+                       continue;
+               if (abs(rates[i].sysclk - sysclk) <
+                   abs(rates[best].sysclk - sysclk))
+                       best = i;
+               else if (rates[best].idle != idle)
+                       best = i;
+       }
+
+       val = rates[best].start << WM8958_MICD_BIAS_STARTTIME_SHIFT
+               | rates[best].rate << WM8958_MICD_RATE_SHIFT;
+
+       snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+                           WM8958_MICD_BIAS_STARTTIME_MASK |
+                           WM8958_MICD_RATE_MASK, val);
+}
+
 static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994 *control = codec->control_data;
+       struct wm8994 *control = wm8994->wm8994;
 
        switch (reg) {
        case WM8994_GPIO_1:
@@ -221,8 +291,10 @@ static int configure_clock(struct snd_soc_codec *codec)
         */
 
        /* If they're equal it doesn't matter which is used */
-       if (wm8994->aifclk[0] == wm8994->aifclk[1])
+       if (wm8994->aifclk[0] == wm8994->aifclk[1]) {
+               wm8958_micd_set_rate(codec);
                return 0;
+       }
 
        if (wm8994->aifclk[0] < wm8994->aifclk[1])
                new = WM8994_SYSCLK_SRC;
@@ -231,10 +303,10 @@ static int configure_clock(struct snd_soc_codec *codec)
 
        change = snd_soc_update_bits(codec, WM8994_CLOCKING_1,
                                     WM8994_SYSCLK_SRC, new);
-       if (!change)
-               return 0;
+       if (change)
+               snd_soc_dapm_sync(&codec->dapm);
 
-       snd_soc_dapm_sync(&codec->dapm);
+       wm8958_micd_set_rate(codec);
 
        return 0;
 }
@@ -708,6 +780,74 @@ SOC_SINGLE_TLV("MIXINL IN1RP Boost Volume", WM8994_INPUT_MIXER_1, 8, 1, 0,
               mixin_boost_tlv),
 };
 
+/* We run all mode setting through a function to enforce audio mode */
+static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode)
+{
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+       if (wm8994->active_refcount)
+               mode = WM1811_JACKDET_MODE_AUDIO;
+
+       snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+                           WM1811_JACKDET_MODE_MASK, mode);
+
+       if (mode == WM1811_JACKDET_MODE_MIC)
+               msleep(2);
+}
+
+static void active_reference(struct snd_soc_codec *codec)
+{
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+       mutex_lock(&wm8994->accdet_lock);
+
+       wm8994->active_refcount++;
+
+       dev_dbg(codec->dev, "Active refcount incremented, now %d\n",
+               wm8994->active_refcount);
+
+       if (wm8994->active_refcount == 1) {
+               /* If we're using jack detection go into audio mode */
+               if (wm8994->jackdet && wm8994->jack_cb) {
+                       snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+                                           WM1811_JACKDET_MODE_MASK,
+                                           WM1811_JACKDET_MODE_AUDIO);
+                       msleep(2);
+               }
+       }
+
+       mutex_unlock(&wm8994->accdet_lock);
+}
+
+static void active_dereference(struct snd_soc_codec *codec)
+{
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       u16 mode;
+
+       mutex_lock(&wm8994->accdet_lock);
+
+       wm8994->active_refcount--;
+
+       dev_dbg(codec->dev, "Active refcount decremented, now %d\n",
+               wm8994->active_refcount);
+
+       if (wm8994->active_refcount == 0) {
+               /* Go into appropriate detection only mode */
+               if (wm8994->jackdet && wm8994->jack_cb) {
+                       if (wm8994->jack_mic || wm8994->mic_detecting)
+                               mode = WM1811_JACKDET_MODE_MIC;
+                       else
+                               mode = WM1811_JACKDET_MODE_JACK;
+
+                       snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+                                           WM1811_JACKDET_MODE_MASK,
+                                           mode);
+               }
+       }
+
+       mutex_unlock(&wm8994->accdet_lock);
+}
+
 static int clk_sys_event(struct snd_soc_dapm_widget *w,
                         struct snd_kcontrol *kcontrol, int event)
 {
@@ -1325,15 +1465,15 @@ SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0),
 };
 
 static const struct snd_soc_dapm_widget wm8994_adc_revd_widgets[] = {
-SND_SOC_DAPM_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux,
-                  adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
-SND_SOC_DAPM_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux,
-                  adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_VIRT_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux,
+                       adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_VIRT_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux,
+                       adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
 };
 
 static const struct snd_soc_dapm_widget wm8994_adc_widgets[] = {
-SND_SOC_DAPM_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux),
-SND_SOC_DAPM_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux),
+SND_SOC_DAPM_VIRT_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux),
+SND_SOC_DAPM_VIRT_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux),
 };
 
 static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = {
@@ -1768,7 +1908,7 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
                          unsigned int freq_in, unsigned int freq_out)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994 *control = codec->control_data;
+       struct wm8994 *control = wm8994->wm8994;
        int reg_offset, ret;
        struct fll_div fll;
        u16 reg, aif1, aif2;
@@ -1865,6 +2005,8 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
        if (freq_out) {
                /* Enable VMID if we need it */
                if (!was_enabled) {
+                       active_reference(codec);
+
                        switch (control->type) {
                        case WM8994:
                                vmid_reference(codec);
@@ -1908,6 +2050,8 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
                        default:
                                break;
                        }
+
+                       active_dereference(codec);
                }
        }
 
@@ -2017,20 +2161,33 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
 static int wm8994_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
-       struct wm8994 *control = codec->control_data;
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       struct wm8994 *control = wm8994->wm8994;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
                break;
 
        case SND_SOC_BIAS_PREPARE:
+               /* MICBIAS into regulating mode */
+               switch (control->type) {
+               case WM8958:
+               case WM1811:
+                       snd_soc_update_bits(codec, WM8958_MICBIAS1,
+                                           WM8958_MICB1_MODE, 0);
+                       snd_soc_update_bits(codec, WM8958_MICBIAS2,
+                                           WM8958_MICB2_MODE, 0);
+                       break;
+               default:
+                       break;
+               }
+
+               if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
+                       active_reference(codec);
                break;
 
        case SND_SOC_BIAS_STANDBY:
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-                       pm_runtime_get_sync(codec->dev);
-
                        switch (control->type) {
                        case WM8994:
                                if (wm8994->revision < 4) {
@@ -2077,25 +2234,40 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
                                            WM8994_LINEOUT2_DISCH);
                }
 
+               if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE)
+                       active_dereference(codec);
 
+               /* MICBIAS into bypass mode on newer devices */
+               switch (control->type) {
+               case WM8958:
+               case WM1811:
+                       snd_soc_update_bits(codec, WM8958_MICBIAS1,
+                                           WM8958_MICB1_MODE,
+                                           WM8958_MICB1_MODE);
+                       snd_soc_update_bits(codec, WM8958_MICBIAS2,
+                                           WM8958_MICB2_MODE,
+                                           WM8958_MICB2_MODE);
+                       break;
+               default:
+                       break;
+               }
                break;
 
        case SND_SOC_BIAS_OFF:
-               if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
+               if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
                        wm8994->cur_fw = NULL;
-
-                       pm_runtime_put(codec->dev);
-               }
                break;
        }
        codec->dapm.bias_level = level;
+
        return 0;
 }
 
 static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
        struct snd_soc_codec *codec = dai->codec;
-       struct wm8994 *control = codec->control_data;
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       struct wm8994 *control = wm8994->wm8994;
        int ms_reg;
        int aif1_reg;
        int ms = 0;
@@ -2357,6 +2529,11 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
        bclk |= best << WM8994_AIF1_BCLK_DIV_SHIFT;
 
        lrclk = bclk_rate / params_rate(params);
+       if (!lrclk) {
+               dev_err(dai->dev, "Unable to generate LRCLK from %dHz BCLK\n",
+                       bclk_rate);
+               return -EINVAL;
+       }
        dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n",
                lrclk, bclk_rate / lrclk);
 
@@ -2390,7 +2567,8 @@ static int wm8994_aif3_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);
+       struct wm8994 *control = wm8994->wm8994;
        int aif1_reg;
        int aif1 = 0;
 
@@ -2531,7 +2709,7 @@ static int wm8994_aif2_probe(struct snd_soc_dai *dai)
 #define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8994_aif1_dai_ops = {
+static const struct snd_soc_dai_ops wm8994_aif1_dai_ops = {
        .set_sysclk     = wm8994_set_dai_sysclk,
        .set_fmt        = wm8994_set_dai_fmt,
        .hw_params      = wm8994_hw_params,
@@ -2541,7 +2719,7 @@ static struct snd_soc_dai_ops wm8994_aif1_dai_ops = {
        .set_tristate   = wm8994_set_tristate,
 };
 
-static struct snd_soc_dai_ops wm8994_aif2_dai_ops = {
+static const struct snd_soc_dai_ops wm8994_aif2_dai_ops = {
        .set_sysclk     = wm8994_set_dai_sysclk,
        .set_fmt        = wm8994_set_dai_fmt,
        .hw_params      = wm8994_hw_params,
@@ -2551,7 +2729,7 @@ static struct snd_soc_dai_ops wm8994_aif2_dai_ops = {
        .set_tristate   = wm8994_set_tristate,
 };
 
-static struct snd_soc_dai_ops wm8994_aif3_dai_ops = {
+static const struct snd_soc_dai_ops wm8994_aif3_dai_ops = {
        .hw_params      = wm8994_aif3_hw_params,
        .set_tristate   = wm8994_set_tristate,
 };
@@ -2618,10 +2796,10 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
 };
 
 #ifdef CONFIG_PM
-static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8994_suspend(struct snd_soc_codec *codec)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994 *control = codec->control_data;
+       struct wm8994 *control = wm8994->wm8994;
        int i, ret;
 
        switch (control->type) {
@@ -2629,6 +2807,9 @@ static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
                snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0);
                break;
        case WM1811:
+               snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+                                   WM1811_JACKDET_MODE_MASK, 0);
+               /* Fall through */
        case WM8958:
                snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
                                    WM8958_MICD_ENA, 0);
@@ -2652,7 +2833,7 @@ static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
 static int wm8994_resume(struct snd_soc_codec *codec)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994 *control = codec->control_data;
+       struct wm8994 *control = wm8994->wm8994;
        int i, ret;
        unsigned int val, mask;
 
@@ -2698,6 +2879,13 @@ static int wm8994_resume(struct snd_soc_codec *codec)
                                            WM8994_MICD_ENA, WM8994_MICD_ENA);
                break;
        case WM1811:
+               if (wm8994->jackdet && wm8994->jack_cb) {
+                       /* Restart from idle */
+                       snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+                                           WM1811_JACKDET_MODE_MASK,
+                                           WM1811_JACKDET_MODE_JACK);
+                       break;
+               }
        case WM8958:
                if (wm8994->jack_cb)
                        snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
@@ -2810,8 +2998,8 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
                };
 
                /* We need an array of texts for the enum API */
-               wm8994->drc_texts = kmalloc(sizeof(char *)
-                                           * pdata->num_drc_cfgs, GFP_KERNEL);
+               wm8994->drc_texts = devm_kzalloc(wm8994->codec->dev,
+                           sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL);
                if (!wm8994->drc_texts) {
                        dev_err(wm8994->codec->dev,
                                "Failed to allocate %d DRC config texts\n",
@@ -2874,7 +3062,7 @@ int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994_micdet *micdet;
-       struct wm8994 *control = codec->control_data;
+       struct wm8994 *control = wm8994->wm8994;
        int reg;
 
        if (control->type != WM8994)
@@ -2957,21 +3145,136 @@ static void wm8958_default_micdet(u16 status, void *data)
 {
        struct snd_soc_codec *codec = data;
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       int report = 0;
+       int report;
+
+       dev_dbg(codec->dev, "MICDET %x\n", status);
+
+       /* Either nothing present or just starting detection */
+       if (!(status & WM8958_MICD_STS)) {
+               if (!wm8994->jackdet) {
+                       /* If nothing present then clear our statuses */
+                       dev_dbg(codec->dev, "Detected open circuit\n");
+                       wm8994->jack_mic = false;
+                       wm8994->mic_detecting = true;
+
+                       wm8958_micd_set_rate(codec);
 
-       /* If nothing present then clear our statuses */
-       if (!(status & WM8958_MICD_STS))
-               goto done;
+                       snd_soc_jack_report(wm8994->micdet[0].jack, 0,
+                                           wm8994->btn_mask |
+                                            SND_JACK_HEADSET);
+               }
+               return;
+       }
+
+       /* If the measurement is showing a high impedence we've got a
+        * microphone.
+        */
+       if (wm8994->mic_detecting && (status & 0x600)) {
+               dev_dbg(codec->dev, "Detected microphone\n");
 
-       report = SND_JACK_MICROPHONE;
+               wm8994->mic_detecting = false;
+               wm8994->jack_mic = true;
 
-       /* Everything else is buttons; just assign slots */
-       if (status & 0x1c)
-               report |= SND_JACK_BTN_0;
+               wm8958_micd_set_rate(codec);
 
-done:
-       snd_soc_jack_report(wm8994->micdet[0].jack, report,
-                           SND_JACK_BTN_0 | SND_JACK_MICROPHONE);
+               snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADSET,
+                                   SND_JACK_HEADSET);
+       }
+
+
+       if (wm8994->mic_detecting && status & 0x4) {
+               dev_dbg(codec->dev, "Detected headphone\n");
+               wm8994->mic_detecting = false;
+
+               wm8958_micd_set_rate(codec);
+
+               snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADPHONE,
+                                   SND_JACK_HEADSET);
+
+               /* If we have jackdet that will detect removal */
+               if (wm8994->jackdet) {
+                       snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+                                           WM8958_MICD_ENA, 0);
+
+                       wm1811_jackdet_set_mode(codec,
+                                               WM1811_JACKDET_MODE_JACK);
+               }
+       }
+
+       /* Report short circuit as a button */
+       if (wm8994->jack_mic) {
+               report = 0;
+               if (status & 0x4)
+                       report |= SND_JACK_BTN_0;
+
+               if (status & 0x8)
+                       report |= SND_JACK_BTN_1;
+
+               if (status & 0x10)
+                       report |= SND_JACK_BTN_2;
+
+               if (status & 0x20)
+                       report |= SND_JACK_BTN_3;
+
+               if (status & 0x40)
+                       report |= SND_JACK_BTN_4;
+
+               if (status & 0x80)
+                       report |= SND_JACK_BTN_5;
+
+               snd_soc_jack_report(wm8994->micdet[0].jack, report,
+                                   wm8994->btn_mask);
+       }
+}
+
+static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
+{
+       struct wm8994_priv *wm8994 = data;
+       struct snd_soc_codec *codec = wm8994->codec;
+       int reg;
+
+       mutex_lock(&wm8994->accdet_lock);
+
+       reg = snd_soc_read(codec, WM1811_JACKDET_CTRL);
+       if (reg < 0) {
+               dev_err(codec->dev, "Failed to read jack status: %d\n", reg);
+               mutex_unlock(&wm8994->accdet_lock);
+               return IRQ_NONE;
+       }
+
+       dev_dbg(codec->dev, "JACKDET %x\n", reg);
+
+       if (reg & WM1811_JACKDET_LVL) {
+               dev_dbg(codec->dev, "Jack detected\n");
+
+               snd_soc_jack_report(wm8994->micdet[0].jack,
+                                   SND_JACK_MECHANICAL, SND_JACK_MECHANICAL);
+
+               /*
+                * Start off measument of microphone impedence to find
+                * out what's actually there.
+                */
+               wm8994->mic_detecting = true;
+               wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
+               snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+                                   WM8958_MICD_ENA, WM8958_MICD_ENA);
+       } else {
+               dev_dbg(codec->dev, "Jack not detected\n");
+
+               snd_soc_jack_report(wm8994->micdet[0].jack, 0,
+                                   SND_JACK_MECHANICAL | SND_JACK_HEADSET |
+                                   wm8994->btn_mask);
+
+               wm8994->mic_detecting = false;
+               wm8994->jack_mic = false;
+               snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+                                   WM8958_MICD_ENA, 0);
+               wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK);
+       }
+
+       mutex_unlock(&wm8994->accdet_lock);
+
+       return IRQ_HANDLED;
 }
 
 /**
@@ -2994,7 +3297,8 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
                      wm8958_micdet_cb cb, void *cb_data)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994 *control = codec->control_data;
+       struct wm8994 *control = wm8994->wm8994;
+       u16 micd_lvl_sel;
 
        switch (control->type) {
        case WM1811:
@@ -3011,15 +3315,50 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
                        cb_data = codec;
                }
 
+               snd_soc_dapm_force_enable_pin(&codec->dapm, "CLK_SYS");
+
                wm8994->micdet[0].jack = jack;
                wm8994->jack_cb = cb;
                wm8994->jack_cb_data = cb_data;
 
-               snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
-                                   WM8958_MICD_ENA, WM8958_MICD_ENA);
+               wm8994->mic_detecting = true;
+               wm8994->jack_mic = false;
+
+               wm8958_micd_set_rate(codec);
+
+               /* Detect microphones and short circuits by default */
+               if (wm8994->pdata->micd_lvl_sel)
+                       micd_lvl_sel = wm8994->pdata->micd_lvl_sel;
+               else
+                       micd_lvl_sel = 0x41;
+
+               wm8994->btn_mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+                       SND_JACK_BTN_2 | SND_JACK_BTN_3 |
+                       SND_JACK_BTN_4 | SND_JACK_BTN_5;
+
+               snd_soc_update_bits(codec, WM8958_MIC_DETECT_2,
+                                   WM8958_MICD_LVL_SEL_MASK, micd_lvl_sel);
+
+               WARN_ON(codec->dapm.bias_level > SND_SOC_BIAS_STANDBY);
+
+               /*
+                * If we can use jack detection start off with that,
+                * otherwise jump straight to microphone detection.
+                */
+               if (wm8994->jackdet) {
+                       snd_soc_update_bits(codec, WM8994_LDO_1,
+                                           WM8994_LDO1_DISCH, 0);
+                       wm1811_jackdet_set_mode(codec,
+                                               WM1811_JACKDET_MODE_JACK);
+               } else {
+                       snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+                                           WM8958_MICD_ENA, WM8958_MICD_ENA);
+               }
+
        } else {
                snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
                                    WM8958_MICD_ENA, 0);
+               snd_soc_dapm_disable_pin(&codec->dapm, "CLK_SYS");
        }
 
        return 0;
@@ -3032,6 +3371,18 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
        struct snd_soc_codec *codec = wm8994->codec;
        int reg, count;
 
+       mutex_lock(&wm8994->accdet_lock);
+
+       /*
+        * Jack detection may have detected a removal simulataneously
+        * with an update of the MICDET status; if so it will have
+        * stopped detection and we can ignore this interrupt.
+        */
+       if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA)) {
+               mutex_unlock(&wm8994->accdet_lock);
+               return IRQ_HANDLED;
+       }
+
        /* We may occasionally read a detection without an impedence
         * range being provided - if that happens loop again.
         */
@@ -3039,6 +3390,7 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
        do {
                reg = snd_soc_read(codec, WM8958_MIC_DETECT_3);
                if (reg < 0) {
+                       mutex_unlock(&wm8994->accdet_lock);
                        dev_err(codec->dev,
                                "Failed to read mic detect status: %d\n",
                                reg);
@@ -3069,6 +3421,8 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
                dev_warn(codec->dev, "Accessory detection with no callback\n");
 
 out:
+       mutex_unlock(&wm8994->accdet_lock);
+
        return IRQ_HANDLED;
 }
 
@@ -3109,14 +3463,19 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
        codec->control_data = dev_get_drvdata(codec->dev->parent);
        control = codec->control_data;
 
-       wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL);
+       wm8994 = devm_kzalloc(codec->dev, sizeof(struct wm8994_priv),
+                             GFP_KERNEL);
        if (wm8994 == NULL)
                return -ENOMEM;
        snd_soc_codec_set_drvdata(codec, wm8994);
 
+
+       wm8994->wm8994 = dev_get_drvdata(codec->dev->parent);
        wm8994->pdata = dev_get_platdata(codec->dev->parent);
        wm8994->codec = codec;
 
+       mutex_init(&wm8994->accdet_lock);
+
        for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
                init_completion(&wm8994->fll_locked[i]);
 
@@ -3178,6 +3537,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                switch (wm8994->revision) {
                case 0:
                case 1:
+               case 2:
+               case 3:
                        wm8994->hubs.dcs_codes_l = -9;
                        wm8994->hubs.dcs_codes_r = -5;
                        break;
@@ -3193,14 +3554,14 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                break;
        }
 
-       wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR,
+       wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_FIFOS_ERR,
                           wm8994_fifo_error, "FIFO error", codec);
-       wm8994_request_irq(codec->control_data, WM8994_IRQ_TEMP_WARN,
+       wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_TEMP_WARN,
                           wm8994_temp_warn, "Thermal warning", codec);
-       wm8994_request_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT,
+       wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT,
                           wm8994_temp_shut, "Thermal shutdown", codec);
 
-       ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
+       ret = wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE,
                                 wm_hubs_dcs_done, "DC servo done",
                                 &wm8994->hubs);
        if (ret == 0)
@@ -3220,7 +3581,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                                         ret);
                }
 
-               ret = wm8994_request_irq(codec->control_data,
+               ret = wm8994_request_irq(wm8994->wm8994,
                                         WM8994_IRQ_MIC1_SHRT,
                                         wm8994_mic_irq, "Mic 1 short",
                                         wm8994);
@@ -3229,7 +3590,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                                 "Failed to request Mic1 short IRQ: %d\n",
                                 ret);
 
-               ret = wm8994_request_irq(codec->control_data,
+               ret = wm8994_request_irq(wm8994->wm8994,
                                         WM8994_IRQ_MIC2_DET,
                                         wm8994_mic_irq, "Mic 2 detect",
                                         wm8994);
@@ -3238,7 +3599,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                                 "Failed to request Mic2 detect IRQ: %d\n",
                                 ret);
 
-               ret = wm8994_request_irq(codec->control_data,
+               ret = wm8994_request_irq(wm8994->wm8994,
                                         WM8994_IRQ_MIC2_SHRT,
                                         wm8994_mic_irq, "Mic 2 short",
                                         wm8994);
@@ -3263,9 +3624,24 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                }
        }
 
+       switch (control->type) {
+       case WM1811:
+               if (wm8994->revision > 1) {
+                       ret = wm8994_request_irq(wm8994->wm8994,
+                                                WM8994_IRQ_GPIO(6),
+                                                wm1811_jackdet_irq, "JACKDET",
+                                                wm8994);
+                       if (ret == 0)
+                               wm8994->jackdet = true;
+               }
+               break;
+       default:
+               break;
+       }
+
        wm8994->fll_locked_irq = true;
        for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) {
-               ret = wm8994_request_irq(codec->control_data,
+               ret = wm8994_request_irq(wm8994->wm8994,
                                         WM8994_IRQ_FLL1_LOCK + i,
                                         wm8994_fll_locked_irq, "FLL lock",
                                         &wm8994->fll_locked[i]);
@@ -3361,6 +3737,19 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
                break;
        }
 
+       /* Put MICBIAS into bypass mode by default on newer devices */
+       switch (control->type) {
+       case WM8958:
+       case WM1811:
+               snd_soc_update_bits(codec, WM8958_MICBIAS1,
+                                   WM8958_MICB1_MODE, WM8958_MICB1_MODE);
+               snd_soc_update_bits(codec, WM8958_MICBIAS2,
+                                   WM8958_MICB2_MODE, WM8958_MICB2_MODE);
+               break;
+       default:
+               break;
+       }
+
        wm8994_update_class_w(codec);
 
        wm8994_handle_pdata(wm8994);
@@ -3472,28 +3861,29 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
        return 0;
 
 err_irq:
-       wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
-       wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
-       wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
+       if (wm8994->jackdet)
+               wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_GPIO(6), wm8994);
+       wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC2_SHRT, wm8994);
+       wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC2_DET, wm8994);
+       wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC1_SHRT, wm8994);
        if (wm8994->micdet_irq)
                free_irq(wm8994->micdet_irq, wm8994);
        for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
-               wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i,
+               wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FLL1_LOCK + i,
                                &wm8994->fll_locked[i]);
-       wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
+       wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE,
                        &wm8994->hubs);
-       wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec);
-       wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT, codec);
-       wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_WARN, codec);
+       wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FIFOS_ERR, codec);
+       wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT, codec);
+       wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_WARN, codec);
 err:
-       kfree(wm8994);
        return ret;
 }
 
 static int  wm8994_codec_remove(struct snd_soc_codec *codec)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
-       struct wm8994 *control = codec->control_data;
+       struct wm8994 *control = wm8994->wm8994;
        int i;
 
        wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -3501,24 +3891,27 @@ static int  wm8994_codec_remove(struct snd_soc_codec *codec)
        pm_runtime_disable(codec->dev);
 
        for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
-               wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i,
+               wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FLL1_LOCK + i,
                                &wm8994->fll_locked[i]);
 
-       wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
+       wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE,
                        &wm8994->hubs);
-       wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec);
-       wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT, codec);
-       wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_WARN, codec);
+       wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FIFOS_ERR, codec);
+       wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT, codec);
+       wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_WARN, codec);
+
+       if (wm8994->jackdet)
+               wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_GPIO(6), wm8994);
 
        switch (control->type) {
        case WM8994:
                if (wm8994->micdet_irq)
                        free_irq(wm8994->micdet_irq, wm8994);
-               wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET,
+               wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC2_DET,
                                wm8994);
-               wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT,
+               wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC1_SHRT,
                                wm8994);
-               wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET,
+               wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC1_DET,
                                wm8994);
                break;
 
@@ -3535,8 +3928,6 @@ static int  wm8994_codec_remove(struct snd_soc_codec *codec)
        if (wm8994->enh_eq)
                release_firmware(wm8994->enh_eq);
        kfree(wm8994->retune_mobile_texts);
-       kfree(wm8994->drc_texts);
-       kfree(wm8994);
 
        return 0;
 }
@@ -3579,18 +3970,7 @@ static struct platform_driver wm8994_codec_driver = {
        .remove = __devexit_p(wm8994_remove),
 };
 
-static __init int wm8994_init(void)
-{
-       return platform_driver_register(&wm8994_codec_driver);
-}
-module_init(wm8994_init);
-
-static __exit void wm8994_exit(void)
-{
-       platform_driver_unregister(&wm8994_codec_driver);
-}
-module_exit(wm8994_exit);
-
+module_platform_driver(wm8994_codec_driver);
 
 MODULE_DESCRIPTION("ASoC WM8994 driver");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
index f4f1355..6ef3f11 100644 (file)
@@ -70,10 +70,11 @@ struct wm8994_fll_config {
 #define WM8994_NUM_DRC 3
 #define WM8994_NUM_EQ  3
 
+struct wm8994;
+
 struct wm8994_priv {
        struct wm_hubs_data hubs;
-       enum snd_soc_control_type control_type;
-       void *control_data;
+       struct wm8994 *wm8994;
        struct snd_soc_codec *codec;
        int sysclk[2];
        int sysclk_rate[2];
@@ -84,6 +85,7 @@ struct wm8994_priv {
        bool fll_locked_irq;
 
        int vmid_refcount;
+       int active_refcount;
 
        int dac_rates[2];
        int lrclk_shared[2];
@@ -125,7 +127,12 @@ struct wm8994_priv {
        const char **enh_eq_texts;
        struct soc_enum enh_eq_enum;
 
+       struct mutex accdet_lock;
        struct wm8994_micdet micdet[2];
+       bool mic_detecting;
+       bool jack_mic;
+       int btn_mask;
+       bool jackdet;
 
        wm8958_micdet_cb jack_cb;
        void *jack_cb_data;
index 78eeb21..5863406 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/spi/spi.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
@@ -43,88 +44,331 @@ static const char *wm8995_supply_names[WM8995_NUM_SUPPLIES] = {
        "MICVDD"
 };
 
-static const u16 wm8995_reg_defs[WM8995_MAX_REGISTER + 1] = {
-       [0]     = 0x8995, [5]     = 0x0100, [16]    = 0x000b, [17]    = 0x000b,
-       [24]    = 0x02c0, [25]    = 0x02c0, [26]    = 0x02c0, [27]    = 0x02c0,
-       [28]    = 0x000f, [32]    = 0x0005, [33]    = 0x0005, [40]    = 0x0003,
-       [41]    = 0x0013, [48]    = 0x0004, [56]    = 0x09f8, [64]    = 0x1f25,
-       [69]    = 0x0004, [82]    = 0xaaaa, [84]    = 0x2a2a, [146]   = 0x0060,
-       [256]   = 0x0002, [257]   = 0x8004, [520]   = 0x0010, [528]   = 0x0083,
-       [529]   = 0x0083, [548]   = 0x0c80, [580]   = 0x0c80, [768]   = 0x4050,
-       [769]   = 0x4000, [771]   = 0x0040, [772]   = 0x0040, [773]   = 0x0040,
-       [774]   = 0x0004, [775]   = 0x0100, [784]   = 0x4050, [785]   = 0x4000,
-       [787]   = 0x0040, [788]   = 0x0040, [789]   = 0x0040, [1024]  = 0x00c0,
-       [1025]  = 0x00c0, [1026]  = 0x00c0, [1027]  = 0x00c0, [1028]  = 0x00c0,
-       [1029]  = 0x00c0, [1030]  = 0x00c0, [1031]  = 0x00c0, [1056]  = 0x0200,
-       [1057]  = 0x0010, [1058]  = 0x0200, [1059]  = 0x0010, [1088]  = 0x0098,
-       [1089]  = 0x0845, [1104]  = 0x0098, [1105]  = 0x0845, [1152]  = 0x6318,
-       [1153]  = 0x6300, [1154]  = 0x0fca, [1155]  = 0x0400, [1156]  = 0x00d8,
-       [1157]  = 0x1eb5, [1158]  = 0xf145, [1159]  = 0x0b75, [1160]  = 0x01c5,
-       [1161]  = 0x1c58, [1162]  = 0xf373, [1163]  = 0x0a54, [1164]  = 0x0558,
-       [1165]  = 0x168e, [1166]  = 0xf829, [1167]  = 0x07ad, [1168]  = 0x1103,
-       [1169]  = 0x0564, [1170]  = 0x0559, [1171]  = 0x4000, [1184]  = 0x6318,
-       [1185]  = 0x6300, [1186]  = 0x0fca, [1187]  = 0x0400, [1188]  = 0x00d8,
-       [1189]  = 0x1eb5, [1190]  = 0xf145, [1191]  = 0x0b75, [1192]  = 0x01c5,
-       [1193]  = 0x1c58, [1194]  = 0xf373, [1195]  = 0x0a54, [1196]  = 0x0558,
-       [1197]  = 0x168e, [1198]  = 0xf829, [1199]  = 0x07ad, [1200]  = 0x1103,
-       [1201]  = 0x0564, [1202]  = 0x0559, [1203]  = 0x4000, [1280]  = 0x00c0,
-       [1281]  = 0x00c0, [1282]  = 0x00c0, [1283]  = 0x00c0, [1312]  = 0x0200,
-       [1313]  = 0x0010, [1344]  = 0x0098, [1345]  = 0x0845, [1408]  = 0x6318,
-       [1409]  = 0x6300, [1410]  = 0x0fca, [1411]  = 0x0400, [1412]  = 0x00d8,
-       [1413]  = 0x1eb5, [1414]  = 0xf145, [1415]  = 0x0b75, [1416]  = 0x01c5,
-       [1417]  = 0x1c58, [1418]  = 0xf373, [1419]  = 0x0a54, [1420]  = 0x0558,
-       [1421]  = 0x168e, [1422]  = 0xf829, [1423]  = 0x07ad, [1424]  = 0x1103,
-       [1425]  = 0x0564, [1426]  = 0x0559, [1427]  = 0x4000, [1568]  = 0x0002,
-       [1792]  = 0xa100, [1793]  = 0xa101, [1794]  = 0xa101, [1795]  = 0xa101,
-       [1796]  = 0xa101, [1797]  = 0xa101, [1798]  = 0xa101, [1799]  = 0xa101,
-       [1800]  = 0xa101, [1801]  = 0xa101, [1802]  = 0xa101, [1803]  = 0xa101,
-       [1804]  = 0xa101, [1805]  = 0xa101, [1825]  = 0x0055, [1848]  = 0x3fff,
-       [1849]  = 0x1fff, [2049]  = 0x0001, [2050]  = 0x0069, [2056]  = 0x0002,
-       [2057]  = 0x0003, [2058]  = 0x0069, [12288] = 0x0001, [12289] = 0x0001,
-       [12291] = 0x0006, [12292] = 0x0040, [12293] = 0x0001, [12294] = 0x000f,
-       [12295] = 0x0006, [12296] = 0x0001, [12297] = 0x0003, [12298] = 0x0104,
-       [12300] = 0x0060, [12301] = 0x0011, [12302] = 0x0401, [12304] = 0x0050,
-       [12305] = 0x0003, [12306] = 0x0100, [12308] = 0x0051, [12309] = 0x0003,
-       [12310] = 0x0104, [12311] = 0x000a, [12312] = 0x0060, [12313] = 0x003b,
-       [12314] = 0x0502, [12315] = 0x0100, [12316] = 0x2fff, [12320] = 0x2fff,
-       [12324] = 0x2fff, [12328] = 0x2fff, [12332] = 0x2fff, [12336] = 0x2fff,
-       [12340] = 0x2fff, [12344] = 0x2fff, [12348] = 0x2fff, [12352] = 0x0001,
-       [12353] = 0x0001, [12355] = 0x0006, [12356] = 0x0040, [12357] = 0x0001,
-       [12358] = 0x000f, [12359] = 0x0006, [12360] = 0x0001, [12361] = 0x0003,
-       [12362] = 0x0104, [12364] = 0x0060, [12365] = 0x0011, [12366] = 0x0401,
-       [12368] = 0x0050, [12369] = 0x0003, [12370] = 0x0100, [12372] = 0x0060,
-       [12373] = 0x003b, [12374] = 0x0502, [12375] = 0x0100, [12376] = 0x2fff,
-       [12380] = 0x2fff, [12384] = 0x2fff, [12388] = 0x2fff, [12392] = 0x2fff,
-       [12396] = 0x2fff, [12400] = 0x2fff, [12404] = 0x2fff, [12408] = 0x2fff,
-       [12412] = 0x2fff, [12416] = 0x0001, [12417] = 0x0001, [12419] = 0x0006,
-       [12420] = 0x0040, [12421] = 0x0001, [12422] = 0x000f, [12423] = 0x0006,
-       [12424] = 0x0001, [12425] = 0x0003, [12426] = 0x0106, [12428] = 0x0061,
-       [12429] = 0x0011, [12430] = 0x0401, [12432] = 0x0050, [12433] = 0x0003,
-       [12434] = 0x0102, [12436] = 0x0051, [12437] = 0x0003, [12438] = 0x0106,
-       [12439] = 0x000a, [12440] = 0x0061, [12441] = 0x003b, [12442] = 0x0502,
-       [12443] = 0x0100, [12444] = 0x2fff, [12448] = 0x2fff, [12452] = 0x2fff,
-       [12456] = 0x2fff, [12460] = 0x2fff, [12464] = 0x2fff, [12468] = 0x2fff,
-       [12472] = 0x2fff, [12476] = 0x2fff, [12480] = 0x0001, [12481] = 0x0001,
-       [12483] = 0x0006, [12484] = 0x0040, [12485] = 0x0001, [12486] = 0x000f,
-       [12487] = 0x0006, [12488] = 0x0001, [12489] = 0x0003, [12490] = 0x0106,
-       [12492] = 0x0061, [12493] = 0x0011, [12494] = 0x0401, [12496] = 0x0050,
-       [12497] = 0x0003, [12498] = 0x0102, [12500] = 0x0061, [12501] = 0x003b,
-       [12502] = 0x0502, [12503] = 0x0100, [12504] = 0x2fff, [12508] = 0x2fff,
-       [12512] = 0x2fff, [12516] = 0x2fff, [12520] = 0x2fff, [12524] = 0x2fff,
-       [12528] = 0x2fff, [12532] = 0x2fff, [12536] = 0x2fff, [12540] = 0x2fff,
-       [12544] = 0x0060, [12546] = 0x0601, [12548] = 0x0050, [12550] = 0x0100,
-       [12552] = 0x0001, [12554] = 0x0104, [12555] = 0x0100, [12556] = 0x2fff,
-       [12560] = 0x2fff, [12564] = 0x2fff, [12568] = 0x2fff, [12572] = 0x2fff,
-       [12576] = 0x2fff, [12580] = 0x2fff, [12584] = 0x2fff, [12588] = 0x2fff,
-       [12592] = 0x2fff, [12596] = 0x2fff, [12600] = 0x2fff, [12604] = 0x2fff,
-       [12608] = 0x0061, [12610] = 0x0601, [12612] = 0x0050, [12614] = 0x0102,
-       [12616] = 0x0001, [12618] = 0x0106, [12619] = 0x0100, [12620] = 0x2fff,
-       [12624] = 0x2fff, [12628] = 0x2fff, [12632] = 0x2fff, [12636] = 0x2fff,
-       [12640] = 0x2fff, [12644] = 0x2fff, [12648] = 0x2fff, [12652] = 0x2fff,
-       [12656] = 0x2fff, [12660] = 0x2fff, [12664] = 0x2fff, [12668] = 0x2fff,
-       [12672] = 0x0060, [12674] = 0x0601, [12676] = 0x0061, [12678] = 0x0601,
-       [12680] = 0x0050, [12682] = 0x0300, [12684] = 0x0001, [12686] = 0x0304,
-       [12688] = 0x0040, [12690] = 0x000f, [12692] = 0x0001, [12695] = 0x0100
+static struct reg_default wm8995_reg_defaults[] = {
+       { 0, 0x8995 },
+       { 5, 0x0100 },
+       { 16, 0x000b },
+       { 17, 0x000b },
+       { 24, 0x02c0 },
+       { 25, 0x02c0 },
+       { 26, 0x02c0 },
+       { 27, 0x02c0 },
+       { 28, 0x000f },
+       { 32, 0x0005 },
+       { 33, 0x0005 },
+       { 40, 0x0003 },
+       { 41, 0x0013 },
+       { 48, 0x0004 },
+       { 56, 0x09f8 },
+       { 64, 0x1f25 },
+       { 69, 0x0004 },
+       { 82, 0xaaaa },
+       { 84, 0x2a2a },
+       { 146, 0x0060 },
+       { 256, 0x0002 },
+       { 257, 0x8004 },
+       { 520, 0x0010 },
+       { 528, 0x0083 },
+       { 529, 0x0083 },
+       { 548, 0x0c80 },
+       { 580, 0x0c80 },
+       { 768, 0x4050 },
+       { 769, 0x4000 },
+       { 771, 0x0040 },
+       { 772, 0x0040 },
+       { 773, 0x0040 },
+       { 774, 0x0004 },
+       { 775, 0x0100 },
+       { 784, 0x4050 },
+       { 785, 0x4000 },
+       { 787, 0x0040 },
+       { 788, 0x0040 },
+       { 789, 0x0040 },
+       { 1024, 0x00c0 },
+       { 1025, 0x00c0 },
+       { 1026, 0x00c0 },
+       { 1027, 0x00c0 },
+       { 1028, 0x00c0 },
+       { 1029, 0x00c0 },
+       { 1030, 0x00c0 },
+       { 1031, 0x00c0 },
+       { 1056, 0x0200 },
+       { 1057, 0x0010 },
+       { 1058, 0x0200 },
+       { 1059, 0x0010 },
+       { 1088, 0x0098 },
+       { 1089, 0x0845 },
+       { 1104, 0x0098 },
+       { 1105, 0x0845 },
+       { 1152, 0x6318 },
+       { 1153, 0x6300 },
+       { 1154, 0x0fca },
+       { 1155, 0x0400 },
+       { 1156, 0x00d8 },
+       { 1157, 0x1eb5 },
+       { 1158, 0xf145 },
+       { 1159, 0x0b75 },
+       { 1160, 0x01c5 },
+       { 1161, 0x1c58 },
+       { 1162, 0xf373 },
+       { 1163, 0x0a54 },
+       { 1164, 0x0558 },
+       { 1165, 0x168e },
+       { 1166, 0xf829 },
+       { 1167, 0x07ad },
+       { 1168, 0x1103 },
+       { 1169, 0x0564 },
+       { 1170, 0x0559 },
+       { 1171, 0x4000 },
+       { 1184, 0x6318 },
+       { 1185, 0x6300 },
+       { 1186, 0x0fca },
+       { 1187, 0x0400 },
+       { 1188, 0x00d8 },
+       { 1189, 0x1eb5 },
+       { 1190, 0xf145 },
+       { 1191, 0x0b75 },
+       { 1192, 0x01c5 },
+       { 1193, 0x1c58 },
+       { 1194, 0xf373 },
+       { 1195, 0x0a54 },
+       { 1196, 0x0558 },
+       { 1197, 0x168e },
+       { 1198, 0xf829 },
+       { 1199, 0x07ad },
+       { 1200, 0x1103 },
+       { 1201, 0x0564 },
+       { 1202, 0x0559 },
+       { 1203, 0x4000 },
+       { 1280, 0x00c0 },
+       { 1281, 0x00c0 },
+       { 1282, 0x00c0 },
+       { 1283, 0x00c0 },
+       { 1312, 0x0200 },
+       { 1313, 0x0010 },
+       { 1344, 0x0098 },
+       { 1345, 0x0845 },
+       { 1408, 0x6318 },
+       { 1409, 0x6300 },
+       { 1410, 0x0fca },
+       { 1411, 0x0400 },
+       { 1412, 0x00d8 },
+       { 1413, 0x1eb5 },
+       { 1414, 0xf145 },
+       { 1415, 0x0b75 },
+       { 1416, 0x01c5 },
+       { 1417, 0x1c58 },
+       { 1418, 0xf373 },
+       { 1419, 0x0a54 },
+       { 1420, 0x0558 },
+       { 1421, 0x168e },
+       { 1422, 0xf829 },
+       { 1423, 0x07ad },
+       { 1424, 0x1103 },
+       { 1425, 0x0564 },
+       { 1426, 0x0559 },
+       { 1427, 0x4000 },
+       { 1568, 0x0002 },
+       { 1792, 0xa100 },
+       { 1793, 0xa101 },
+       { 1794, 0xa101 },
+       { 1795, 0xa101 },
+       { 1796, 0xa101 },
+       { 1797, 0xa101 },
+       { 1798, 0xa101 },
+       { 1799, 0xa101 },
+       { 1800, 0xa101 },
+       { 1801, 0xa101 },
+       { 1802, 0xa101 },
+       { 1803, 0xa101 },
+       { 1804, 0xa101 },
+       { 1805, 0xa101 },
+       { 1825, 0x0055 },
+       { 1848, 0x3fff },
+       { 1849, 0x1fff },
+       { 2049, 0x0001 },
+       { 2050, 0x0069 },
+       { 2056, 0x0002 },
+       { 2057, 0x0003 },
+       { 2058, 0x0069 },
+       { 12288, 0x0001 },
+       { 12289, 0x0001 },
+       { 12291, 0x0006 },
+       { 12292, 0x0040 },
+       { 12293, 0x0001 },
+       { 12294, 0x000f },
+       { 12295, 0x0006 },
+       { 12296, 0x0001 },
+       { 12297, 0x0003 },
+       { 12298, 0x0104 },
+       { 12300, 0x0060 },
+       { 12301, 0x0011 },
+       { 12302, 0x0401 },
+       { 12304, 0x0050 },
+       { 12305, 0x0003 },
+       { 12306, 0x0100 },
+       { 12308, 0x0051 },
+       { 12309, 0x0003 },
+       { 12310, 0x0104 },
+       { 12311, 0x000a },
+       { 12312, 0x0060 },
+       { 12313, 0x003b },
+       { 12314, 0x0502 },
+       { 12315, 0x0100 },
+       { 12316, 0x2fff },
+       { 12320, 0x2fff },
+       { 12324, 0x2fff },
+       { 12328, 0x2fff },
+       { 12332, 0x2fff },
+       { 12336, 0x2fff },
+       { 12340, 0x2fff },
+       { 12344, 0x2fff },
+       { 12348, 0x2fff },
+       { 12352, 0x0001 },
+       { 12353, 0x0001 },
+       { 12355, 0x0006 },
+       { 12356, 0x0040 },
+       { 12357, 0x0001 },
+       { 12358, 0x000f },
+       { 12359, 0x0006 },
+       { 12360, 0x0001 },
+       { 12361, 0x0003 },
+       { 12362, 0x0104 },
+       { 12364, 0x0060 },
+       { 12365, 0x0011 },
+       { 12366, 0x0401 },
+       { 12368, 0x0050 },
+       { 12369, 0x0003 },
+       { 12370, 0x0100 },
+       { 12372, 0x0060 },
+       { 12373, 0x003b },
+       { 12374, 0x0502 },
+       { 12375, 0x0100 },
+       { 12376, 0x2fff },
+       { 12380, 0x2fff },
+       { 12384, 0x2fff },
+       { 12388, 0x2fff },
+       { 12392, 0x2fff },
+       { 12396, 0x2fff },
+       { 12400, 0x2fff },
+       { 12404, 0x2fff },
+       { 12408, 0x2fff },
+       { 12412, 0x2fff },
+       { 12416, 0x0001 },
+       { 12417, 0x0001 },
+       { 12419, 0x0006 },
+       { 12420, 0x0040 },
+       { 12421, 0x0001 },
+       { 12422, 0x000f },
+       { 12423, 0x0006 },
+       { 12424, 0x0001 },
+       { 12425, 0x0003 },
+       { 12426, 0x0106 },
+       { 12428, 0x0061 },
+       { 12429, 0x0011 },
+       { 12430, 0x0401 },
+       { 12432, 0x0050 },
+       { 12433, 0x0003 },
+       { 12434, 0x0102 },
+       { 12436, 0x0051 },
+       { 12437, 0x0003 },
+       { 12438, 0x0106 },
+       { 12439, 0x000a },
+       { 12440, 0x0061 },
+       { 12441, 0x003b },
+       { 12442, 0x0502 },
+       { 12443, 0x0100 },
+       { 12444, 0x2fff },
+       { 12448, 0x2fff },
+       { 12452, 0x2fff },
+       { 12456, 0x2fff },
+       { 12460, 0x2fff },
+       { 12464, 0x2fff },
+       { 12468, 0x2fff },
+       { 12472, 0x2fff },
+       { 12476, 0x2fff },
+       { 12480, 0x0001 },
+       { 12481, 0x0001 },
+       { 12483, 0x0006 },
+       { 12484, 0x0040 },
+       { 12485, 0x0001 },
+       { 12486, 0x000f },
+       { 12487, 0x0006 },
+       { 12488, 0x0001 },
+       { 12489, 0x0003 },
+       { 12490, 0x0106 },
+       { 12492, 0x0061 },
+       { 12493, 0x0011 },
+       { 12494, 0x0401 },
+       { 12496, 0x0050 },
+       { 12497, 0x0003 },
+       { 12498, 0x0102 },
+       { 12500, 0x0061 },
+       { 12501, 0x003b },
+       { 12502, 0x0502 },
+       { 12503, 0x0100 },
+       { 12504, 0x2fff },
+       { 12508, 0x2fff },
+       { 12512, 0x2fff },
+       { 12516, 0x2fff },
+       { 12520, 0x2fff },
+       { 12524, 0x2fff },
+       { 12528, 0x2fff },
+       { 12532, 0x2fff },
+       { 12536, 0x2fff },
+       { 12540, 0x2fff },
+       { 12544, 0x0060 },
+       { 12546, 0x0601 },
+       { 12548, 0x0050 },
+       { 12550, 0x0100 },
+       { 12552, 0x0001 },
+       { 12554, 0x0104 },
+       { 12555, 0x0100 },
+       { 12556, 0x2fff },
+       { 12560, 0x2fff },
+       { 12564, 0x2fff },
+       { 12568, 0x2fff },
+       { 12572, 0x2fff },
+       { 12576, 0x2fff },
+       { 12580, 0x2fff },
+       { 12584, 0x2fff },
+       { 12588, 0x2fff },
+       { 12592, 0x2fff },
+       { 12596, 0x2fff },
+       { 12600, 0x2fff },
+       { 12604, 0x2fff },
+       { 12608, 0x0061 },
+       { 12610, 0x0601 },
+       { 12612, 0x0050 },
+       { 12614, 0x0102 },
+       { 12616, 0x0001 },
+       { 12618, 0x0106 },
+       { 12619, 0x0100 },
+       { 12620, 0x2fff },
+       { 12624, 0x2fff },
+       { 12628, 0x2fff },
+       { 12632, 0x2fff },
+       { 12636, 0x2fff },
+       { 12640, 0x2fff },
+       { 12644, 0x2fff },
+       { 12648, 0x2fff },
+       { 12652, 0x2fff },
+       { 12656, 0x2fff },
+       { 12660, 0x2fff },
+       { 12664, 0x2fff },
+       { 12668, 0x2fff },
+       { 12672, 0x0060 },
+       { 12674, 0x0601 },
+       { 12676, 0x0061 },
+       { 12678, 0x0601 },
+       { 12680, 0x0050 },
+       { 12682, 0x0300 },
+       { 12684, 0x0001 },
+       { 12686, 0x0304 },
+       { 12688, 0x0040 },
+       { 12690, 0x000f },
+       { 12692, 0x0001 },
+       { 12695, 0x0100 },
 };
 
 struct fll_config {
@@ -134,7 +378,7 @@ struct fll_config {
 };
 
 struct wm8995_priv {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
        int sysclk[2];
        int mclk[2];
        int aifclk[2];
@@ -156,7 +400,7 @@ static int wm8995_regulator_event_##n(struct notifier_block *nb, \
        struct wm8995_priv *wm8995 = container_of(nb, struct wm8995_priv, \
                                     disable_nb[n]); \
        if (event & REGULATOR_EVENT_DISABLE) { \
-               wm8995->codec->cache_sync = 1; \
+               regcache_mark_dirty(wm8995->regmap);    \
        } \
        return 0; \
 }
@@ -688,8 +932,10 @@ static const struct snd_soc_dapm_widget wm8995_dapm_widgets[] = {
        SND_SOC_DAPM_MIXER("IN1R PGA", SND_SOC_NOPM, 0, 0,
                &in1r_pga, 1),
 
-       SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8995_POWER_MANAGEMENT_1, 8, 0),
-       SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8995_POWER_MANAGEMENT_1, 9, 0),
+       SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8995_POWER_MANAGEMENT_1, 8, 0,
+                           NULL, 0),
+       SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8995_POWER_MANAGEMENT_1, 9, 0,
+                           NULL, 0),
 
        SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8995_AIF1_CLOCKING_1, 0, 0, NULL, 0),
        SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8995_AIF2_CLOCKING_1, 0, 0, NULL, 0),
@@ -947,31 +1193,244 @@ static const struct snd_soc_dapm_route wm8995_intercon[] = {
        { "SPK2R", NULL, "SPK2R Driver" }
 };
 
-static int wm8995_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8995_readable(struct device *dev, unsigned int reg)
 {
-       /* out of bounds registers are generally considered
-        * volatile to support register banks that are partially
-        * owned by something else for e.g. a DSP
-        */
-       if (reg > WM8995_MAX_CACHED_REGISTER)
-               return 1;
-
        switch (reg) {
        case WM8995_SOFTWARE_RESET:
+       case WM8995_POWER_MANAGEMENT_1:
+       case WM8995_POWER_MANAGEMENT_2:
+       case WM8995_POWER_MANAGEMENT_3:
+       case WM8995_POWER_MANAGEMENT_4:
+       case WM8995_POWER_MANAGEMENT_5:
+       case WM8995_LEFT_LINE_INPUT_1_VOLUME:
+       case WM8995_RIGHT_LINE_INPUT_1_VOLUME:
+       case WM8995_LEFT_LINE_INPUT_CONTROL:
+       case WM8995_DAC1_LEFT_VOLUME:
+       case WM8995_DAC1_RIGHT_VOLUME:
+       case WM8995_DAC2_LEFT_VOLUME:
+       case WM8995_DAC2_RIGHT_VOLUME:
+       case WM8995_OUTPUT_VOLUME_ZC_1:
+       case WM8995_MICBIAS_1:
+       case WM8995_MICBIAS_2:
+       case WM8995_LDO_1:
+       case WM8995_LDO_2:
+       case WM8995_ACCESSORY_DETECT_MODE1:
+       case WM8995_ACCESSORY_DETECT_MODE2:
+       case WM8995_HEADPHONE_DETECT1:
+       case WM8995_HEADPHONE_DETECT2:
+       case WM8995_MIC_DETECT_1:
+       case WM8995_MIC_DETECT_2:
+       case WM8995_CHARGE_PUMP_1:
+       case WM8995_CLASS_W_1:
+       case WM8995_DC_SERVO_1:
+       case WM8995_DC_SERVO_2:
+       case WM8995_DC_SERVO_3:
+       case WM8995_DC_SERVO_5:
+       case WM8995_DC_SERVO_6:
+       case WM8995_DC_SERVO_7:
        case WM8995_DC_SERVO_READBACK_0:
+       case WM8995_ANALOGUE_HP_1:
+       case WM8995_ANALOGUE_HP_2:
+       case WM8995_CHIP_REVISION:
+       case WM8995_CONTROL_INTERFACE_1:
+       case WM8995_CONTROL_INTERFACE_2:
+       case WM8995_WRITE_SEQUENCER_CTRL_1:
+       case WM8995_WRITE_SEQUENCER_CTRL_2:
+       case WM8995_AIF1_CLOCKING_1:
+       case WM8995_AIF1_CLOCKING_2:
+       case WM8995_AIF2_CLOCKING_1:
+       case WM8995_AIF2_CLOCKING_2:
+       case WM8995_CLOCKING_1:
+       case WM8995_CLOCKING_2:
+       case WM8995_AIF1_RATE:
+       case WM8995_AIF2_RATE:
+       case WM8995_RATE_STATUS:
+       case WM8995_FLL1_CONTROL_1:
+       case WM8995_FLL1_CONTROL_2:
+       case WM8995_FLL1_CONTROL_3:
+       case WM8995_FLL1_CONTROL_4:
+       case WM8995_FLL1_CONTROL_5:
+       case WM8995_FLL2_CONTROL_1:
+       case WM8995_FLL2_CONTROL_2:
+       case WM8995_FLL2_CONTROL_3:
+       case WM8995_FLL2_CONTROL_4:
+       case WM8995_FLL2_CONTROL_5:
+       case WM8995_AIF1_CONTROL_1:
+       case WM8995_AIF1_CONTROL_2:
+       case WM8995_AIF1_MASTER_SLAVE:
+       case WM8995_AIF1_BCLK:
+       case WM8995_AIF1ADC_LRCLK:
+       case WM8995_AIF1DAC_LRCLK:
+       case WM8995_AIF1DAC_DATA:
+       case WM8995_AIF1ADC_DATA:
+       case WM8995_AIF2_CONTROL_1:
+       case WM8995_AIF2_CONTROL_2:
+       case WM8995_AIF2_MASTER_SLAVE:
+       case WM8995_AIF2_BCLK:
+       case WM8995_AIF2ADC_LRCLK:
+       case WM8995_AIF2DAC_LRCLK:
+       case WM8995_AIF2DAC_DATA:
+       case WM8995_AIF2ADC_DATA:
+       case WM8995_AIF1_ADC1_LEFT_VOLUME:
+       case WM8995_AIF1_ADC1_RIGHT_VOLUME:
+       case WM8995_AIF1_DAC1_LEFT_VOLUME:
+       case WM8995_AIF1_DAC1_RIGHT_VOLUME:
+       case WM8995_AIF1_ADC2_LEFT_VOLUME:
+       case WM8995_AIF1_ADC2_RIGHT_VOLUME:
+       case WM8995_AIF1_DAC2_LEFT_VOLUME:
+       case WM8995_AIF1_DAC2_RIGHT_VOLUME:
+       case WM8995_AIF1_ADC1_FILTERS:
+       case WM8995_AIF1_ADC2_FILTERS:
+       case WM8995_AIF1_DAC1_FILTERS_1:
+       case WM8995_AIF1_DAC1_FILTERS_2:
+       case WM8995_AIF1_DAC2_FILTERS_1:
+       case WM8995_AIF1_DAC2_FILTERS_2:
+       case WM8995_AIF1_DRC1_1:
+       case WM8995_AIF1_DRC1_2:
+       case WM8995_AIF1_DRC1_3:
+       case WM8995_AIF1_DRC1_4:
+       case WM8995_AIF1_DRC1_5:
+       case WM8995_AIF1_DRC2_1:
+       case WM8995_AIF1_DRC2_2:
+       case WM8995_AIF1_DRC2_3:
+       case WM8995_AIF1_DRC2_4:
+       case WM8995_AIF1_DRC2_5:
+       case WM8995_AIF1_DAC1_EQ_GAINS_1:
+       case WM8995_AIF1_DAC1_EQ_GAINS_2:
+       case WM8995_AIF1_DAC1_EQ_BAND_1_A:
+       case WM8995_AIF1_DAC1_EQ_BAND_1_B:
+       case WM8995_AIF1_DAC1_EQ_BAND_1_PG:
+       case WM8995_AIF1_DAC1_EQ_BAND_2_A:
+       case WM8995_AIF1_DAC1_EQ_BAND_2_B:
+       case WM8995_AIF1_DAC1_EQ_BAND_2_C:
+       case WM8995_AIF1_DAC1_EQ_BAND_2_PG:
+       case WM8995_AIF1_DAC1_EQ_BAND_3_A:
+       case WM8995_AIF1_DAC1_EQ_BAND_3_B:
+       case WM8995_AIF1_DAC1_EQ_BAND_3_C:
+       case WM8995_AIF1_DAC1_EQ_BAND_3_PG:
+       case WM8995_AIF1_DAC1_EQ_BAND_4_A:
+       case WM8995_AIF1_DAC1_EQ_BAND_4_B:
+       case WM8995_AIF1_DAC1_EQ_BAND_4_C:
+       case WM8995_AIF1_DAC1_EQ_BAND_4_PG:
+       case WM8995_AIF1_DAC1_EQ_BAND_5_A:
+       case WM8995_AIF1_DAC1_EQ_BAND_5_B:
+       case WM8995_AIF1_DAC1_EQ_BAND_5_PG:
+       case WM8995_AIF1_DAC2_EQ_GAINS_1:
+       case WM8995_AIF1_DAC2_EQ_GAINS_2:
+       case WM8995_AIF1_DAC2_EQ_BAND_1_A:
+       case WM8995_AIF1_DAC2_EQ_BAND_1_B:
+       case WM8995_AIF1_DAC2_EQ_BAND_1_PG:
+       case WM8995_AIF1_DAC2_EQ_BAND_2_A:
+       case WM8995_AIF1_DAC2_EQ_BAND_2_B:
+       case WM8995_AIF1_DAC2_EQ_BAND_2_C:
+       case WM8995_AIF1_DAC2_EQ_BAND_2_PG:
+       case WM8995_AIF1_DAC2_EQ_BAND_3_A:
+       case WM8995_AIF1_DAC2_EQ_BAND_3_B:
+       case WM8995_AIF1_DAC2_EQ_BAND_3_C:
+       case WM8995_AIF1_DAC2_EQ_BAND_3_PG:
+       case WM8995_AIF1_DAC2_EQ_BAND_4_A:
+       case WM8995_AIF1_DAC2_EQ_BAND_4_B:
+       case WM8995_AIF1_DAC2_EQ_BAND_4_C:
+       case WM8995_AIF1_DAC2_EQ_BAND_4_PG:
+       case WM8995_AIF1_DAC2_EQ_BAND_5_A:
+       case WM8995_AIF1_DAC2_EQ_BAND_5_B:
+       case WM8995_AIF1_DAC2_EQ_BAND_5_PG:
+       case WM8995_AIF2_ADC_LEFT_VOLUME:
+       case WM8995_AIF2_ADC_RIGHT_VOLUME:
+       case WM8995_AIF2_DAC_LEFT_VOLUME:
+       case WM8995_AIF2_DAC_RIGHT_VOLUME:
+       case WM8995_AIF2_ADC_FILTERS:
+       case WM8995_AIF2_DAC_FILTERS_1:
+       case WM8995_AIF2_DAC_FILTERS_2:
+       case WM8995_AIF2_DRC_1:
+       case WM8995_AIF2_DRC_2:
+       case WM8995_AIF2_DRC_3:
+       case WM8995_AIF2_DRC_4:
+       case WM8995_AIF2_DRC_5:
+       case WM8995_AIF2_EQ_GAINS_1:
+       case WM8995_AIF2_EQ_GAINS_2:
+       case WM8995_AIF2_EQ_BAND_1_A:
+       case WM8995_AIF2_EQ_BAND_1_B:
+       case WM8995_AIF2_EQ_BAND_1_PG:
+       case WM8995_AIF2_EQ_BAND_2_A:
+       case WM8995_AIF2_EQ_BAND_2_B:
+       case WM8995_AIF2_EQ_BAND_2_C:
+       case WM8995_AIF2_EQ_BAND_2_PG:
+       case WM8995_AIF2_EQ_BAND_3_A:
+       case WM8995_AIF2_EQ_BAND_3_B:
+       case WM8995_AIF2_EQ_BAND_3_C:
+       case WM8995_AIF2_EQ_BAND_3_PG:
+       case WM8995_AIF2_EQ_BAND_4_A:
+       case WM8995_AIF2_EQ_BAND_4_B:
+       case WM8995_AIF2_EQ_BAND_4_C:
+       case WM8995_AIF2_EQ_BAND_4_PG:
+       case WM8995_AIF2_EQ_BAND_5_A:
+       case WM8995_AIF2_EQ_BAND_5_B:
+       case WM8995_AIF2_EQ_BAND_5_PG:
+       case WM8995_DAC1_MIXER_VOLUMES:
+       case WM8995_DAC1_LEFT_MIXER_ROUTING:
+       case WM8995_DAC1_RIGHT_MIXER_ROUTING:
+       case WM8995_DAC2_MIXER_VOLUMES:
+       case WM8995_DAC2_LEFT_MIXER_ROUTING:
+       case WM8995_DAC2_RIGHT_MIXER_ROUTING:
+       case WM8995_AIF1_ADC1_LEFT_MIXER_ROUTING:
+       case WM8995_AIF1_ADC1_RIGHT_MIXER_ROUTING:
+       case WM8995_AIF1_ADC2_LEFT_MIXER_ROUTING:
+       case WM8995_AIF1_ADC2_RIGHT_MIXER_ROUTING:
+       case WM8995_DAC_SOFTMUTE:
+       case WM8995_OVERSAMPLING:
+       case WM8995_SIDETONE:
+       case WM8995_GPIO_1:
+       case WM8995_GPIO_2:
+       case WM8995_GPIO_3:
+       case WM8995_GPIO_4:
+       case WM8995_GPIO_5:
+       case WM8995_GPIO_6:
+       case WM8995_GPIO_7:
+       case WM8995_GPIO_8:
+       case WM8995_GPIO_9:
+       case WM8995_GPIO_10:
+       case WM8995_GPIO_11:
+       case WM8995_GPIO_12:
+       case WM8995_GPIO_13:
+       case WM8995_GPIO_14:
+       case WM8995_PULL_CONTROL_1:
+       case WM8995_PULL_CONTROL_2:
        case WM8995_INTERRUPT_STATUS_1:
        case WM8995_INTERRUPT_STATUS_2:
+       case WM8995_INTERRUPT_RAW_STATUS_2:
        case WM8995_INTERRUPT_STATUS_1_MASK:
        case WM8995_INTERRUPT_STATUS_2_MASK:
        case WM8995_INTERRUPT_CONTROL:
+       case WM8995_LEFT_PDM_SPEAKER_1:
+       case WM8995_RIGHT_PDM_SPEAKER_1:
+       case WM8995_PDM_SPEAKER_1_MUTE_SEQUENCE:
+       case WM8995_LEFT_PDM_SPEAKER_2:
+       case WM8995_RIGHT_PDM_SPEAKER_2:
+       case WM8995_PDM_SPEAKER_2_MUTE_SEQUENCE:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool wm8995_volatile(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM8995_SOFTWARE_RESET:
+       case WM8995_DC_SERVO_READBACK_0:
+       case WM8995_INTERRUPT_STATUS_1:
+       case WM8995_INTERRUPT_STATUS_2:
+       case WM8995_INTERRUPT_CONTROL:
        case WM8995_ACCESSORY_DETECT_MODE1:
        case WM8995_ACCESSORY_DETECT_MODE2:
        case WM8995_HEADPHONE_DETECT1:
        case WM8995_HEADPHONE_DETECT2:
-               return 1;
+       case WM8995_RATE_STATUS:
+               return true;
+       default:
+               return false;
        }
-
-       return 0;
 }
 
 static int wm8995_aif_mute(struct snd_soc_dai *dai, int mute)
@@ -1526,7 +1985,7 @@ static int wm8995_set_bias_level(struct snd_soc_codec *codec,
                        if (ret)
                                return ret;
 
-                       ret = snd_soc_cache_sync(codec);
+                       ret = regcache_sync(wm8995->regmap);
                        if (ret) {
                                dev_err(codec->dev,
                                        "Failed to sync cache: %d\n", ret);
@@ -1550,7 +2009,7 @@ static int wm8995_set_bias_level(struct snd_soc_codec *codec,
 }
 
 #ifdef CONFIG_PM
-static int wm8995_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8995_suspend(struct snd_soc_codec *codec)
 {
        wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -1592,7 +2051,7 @@ static int wm8995_probe(struct snd_soc_codec *codec)
        wm8995 = snd_soc_codec_get_drvdata(codec);
        wm8995->codec = codec;
 
-       ret = snd_soc_codec_set_cache_io(codec, 16, 16, wm8995->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
                return ret;
@@ -1696,7 +2155,7 @@ err_reg_get:
 #define WM8995_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8995_aif1_dai_ops = {
+static const struct snd_soc_dai_ops wm8995_aif1_dai_ops = {
        .set_sysclk = wm8995_set_dai_sysclk,
        .set_fmt = wm8995_set_dai_fmt,
        .hw_params = wm8995_hw_params,
@@ -1705,7 +2164,7 @@ static struct snd_soc_dai_ops wm8995_aif1_dai_ops = {
        .set_tristate = wm8995_set_tristate,
 };
 
-static struct snd_soc_dai_ops wm8995_aif2_dai_ops = {
+static const struct snd_soc_dai_ops wm8995_aif2_dai_ops = {
        .set_sysclk = wm8995_set_dai_sysclk,
        .set_fmt = wm8995_set_dai_fmt,
        .hw_params = wm8995_hw_params,
@@ -1714,7 +2173,7 @@ static struct snd_soc_dai_ops wm8995_aif2_dai_ops = {
        .set_tristate = wm8995_set_tristate,
 };
 
-static struct snd_soc_dai_ops wm8995_aif3_dai_ops = {
+static const struct snd_soc_dai_ops wm8995_aif3_dai_ops = {
        .set_tristate = wm8995_set_tristate,
 };
 
@@ -1781,11 +2240,18 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8995 = {
        .suspend = wm8995_suspend,
        .resume = wm8995_resume,
        .set_bias_level = wm8995_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8995_reg_defs),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8995_reg_defs,
-       .volatile_register = wm8995_volatile,
-       .compress_type = SND_SOC_RBTREE_COMPRESSION
+};
+
+static struct regmap_config wm8995_regmap = {
+       .reg_bits = 16,
+       .val_bits = 16,
+
+       .max_register = WM8995_MAX_REGISTER,
+       .reg_defaults = wm8995_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8995_reg_defaults),
+       .volatile_reg = wm8995_volatile,
+       .readable_reg = wm8995_readable,
+       .cache_type = REGCACHE_RBTREE,
 };
 
 #if defined(CONFIG_SPI_MASTER)
@@ -1798,21 +2264,37 @@ static int __devinit wm8995_spi_probe(struct spi_device *spi)
        if (!wm8995)
                return -ENOMEM;
 
-       wm8995->control_type = SND_SOC_SPI;
        spi_set_drvdata(spi, wm8995);
 
+       wm8995->regmap = regmap_init_spi(spi, &wm8995_regmap);
+       if (IS_ERR(wm8995->regmap)) {
+               ret = PTR_ERR(wm8995->regmap);
+               dev_err(&spi->dev, "Failed to register regmap: %d\n", ret);
+               goto err_alloc;
+       }
+
        ret = snd_soc_register_codec(&spi->dev,
                                     &soc_codec_dev_wm8995, wm8995_dai,
                                     ARRAY_SIZE(wm8995_dai));
        if (ret < 0)
-               kfree(wm8995);
+               goto err_regmap;
+
+       return ret;
+
+err_regmap:
+       regmap_exit(wm8995->regmap);
+err_alloc:
+       kfree(wm8995);
+
        return ret;
 }
 
 static int __devexit wm8995_spi_remove(struct spi_device *spi)
 {
+       struct wm8995_priv *wm8995 = spi_get_drvdata(spi);
        snd_soc_unregister_codec(&spi->dev);
-       kfree(spi_get_drvdata(spi));
+       regmap_exit(wm8995->regmap);
+       kfree(wm8995);
        return 0;
 }
 
@@ -1837,21 +2319,40 @@ static __devinit int wm8995_i2c_probe(struct i2c_client *i2c,
        if (!wm8995)
                return -ENOMEM;
 
-       wm8995->control_type = SND_SOC_I2C;
        i2c_set_clientdata(i2c, wm8995);
 
+       wm8995->regmap = regmap_init_i2c(i2c, &wm8995_regmap);
+       if (IS_ERR(wm8995->regmap)) {
+               ret = PTR_ERR(wm8995->regmap);
+               dev_err(&i2c->dev, "Failed to register regmap: %d\n", ret);
+               goto err_alloc;
+       }
+
        ret = snd_soc_register_codec(&i2c->dev,
                                     &soc_codec_dev_wm8995, wm8995_dai,
                                     ARRAY_SIZE(wm8995_dai));
-       if (ret < 0)
-               kfree(wm8995);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+               goto err_regmap;
+       }
+
+       return ret;
+
+err_regmap:
+       regmap_exit(wm8995->regmap);
+err_alloc:
+       kfree(wm8995);
+
        return ret;
 }
 
 static __devexit int wm8995_i2c_remove(struct i2c_client *client)
 {
+       struct wm8995_priv *wm8995 = i2c_get_clientdata(client);
+
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+       regmap_exit(wm8995->regmap);
+       kfree(wm8995);
        return 0;
 }
 
index 645c980..8f88f5a 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/gcd.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
@@ -49,6 +50,8 @@ static const char *wm8996_supply_names[WM8996_NUM_SUPPLIES] = {
 };
 
 struct wm8996_priv {
+       struct device *dev;
+       struct regmap *regmap;
        struct snd_soc_codec *codec;
 
        int ldo1ena;
@@ -105,7 +108,7 @@ static int wm8996_regulator_event_##n(struct notifier_block *nb, \
        struct wm8996_priv *wm8996 = container_of(nb, struct wm8996_priv, \
                                                  disable_nb[n]); \
        if (event & REGULATOR_EVENT_DISABLE) { \
-               wm8996->codec->cache_sync = 1; \
+               regcache_cache_only(wm8996->regmap, true);      \
        } \
        return 0; \
 }
@@ -114,297 +117,365 @@ WM8996_REGULATOR_EVENT(0)
 WM8996_REGULATOR_EVENT(1)
 WM8996_REGULATOR_EVENT(2)
 
-static const u16 wm8996_reg[WM8996_MAX_REGISTER] = {
-       [WM8996_SOFTWARE_RESET] = 0x8996,
-       [WM8996_POWER_MANAGEMENT_7] = 0x10,
-       [WM8996_DAC1_HPOUT1_VOLUME] = 0x88,
-       [WM8996_DAC2_HPOUT2_VOLUME] = 0x88,
-       [WM8996_DAC1_LEFT_VOLUME] = 0x2c0,
-       [WM8996_DAC1_RIGHT_VOLUME] = 0x2c0,
-       [WM8996_DAC2_LEFT_VOLUME] = 0x2c0,
-       [WM8996_DAC2_RIGHT_VOLUME] = 0x2c0,
-       [WM8996_OUTPUT1_LEFT_VOLUME] = 0x80,
-       [WM8996_OUTPUT1_RIGHT_VOLUME] = 0x80,
-       [WM8996_OUTPUT2_LEFT_VOLUME] = 0x80,
-       [WM8996_OUTPUT2_RIGHT_VOLUME] = 0x80,
-       [WM8996_MICBIAS_1] = 0x39,
-       [WM8996_MICBIAS_2] = 0x39,
-       [WM8996_LDO_1] = 0x3,
-       [WM8996_LDO_2] = 0x13,
-       [WM8996_ACCESSORY_DETECT_MODE_1] = 0x4,
-       [WM8996_HEADPHONE_DETECT_1] = 0x20,
-       [WM8996_MIC_DETECT_1] = 0x7600,
-       [WM8996_MIC_DETECT_2] = 0xbf,
-       [WM8996_CHARGE_PUMP_1] = 0x1f25,
-       [WM8996_CHARGE_PUMP_2] = 0xab19,
-       [WM8996_DC_SERVO_5] = 0x2a2a,
-       [WM8996_CONTROL_INTERFACE_1] = 0x8004,
-       [WM8996_CLOCKING_1] = 0x10,
-       [WM8996_AIF_RATE] = 0x83,
-       [WM8996_FLL_CONTROL_4] = 0x5dc0,
-       [WM8996_FLL_CONTROL_5] = 0xc84,
-       [WM8996_FLL_EFS_2] = 0x2,
-       [WM8996_AIF1_TX_LRCLK_1] = 0x80,
-       [WM8996_AIF1_TX_LRCLK_2] = 0x8,
-       [WM8996_AIF1_RX_LRCLK_1] = 0x80,
-       [WM8996_AIF1TX_DATA_CONFIGURATION_1] = 0x1818,
-       [WM8996_AIF1RX_DATA_CONFIGURATION] = 0x1818,
-       [WM8996_AIF1TX_TEST] = 0x7,
-       [WM8996_AIF2_TX_LRCLK_1] = 0x80,
-       [WM8996_AIF2_TX_LRCLK_2] = 0x8,
-       [WM8996_AIF2_RX_LRCLK_1] = 0x80,
-       [WM8996_AIF2TX_DATA_CONFIGURATION_1] = 0x1818,
-       [WM8996_AIF2RX_DATA_CONFIGURATION] = 0x1818,
-       [WM8996_AIF2TX_TEST] = 0x1,
-       [WM8996_DSP1_TX_LEFT_VOLUME] = 0xc0,
-       [WM8996_DSP1_TX_RIGHT_VOLUME] = 0xc0,
-       [WM8996_DSP1_RX_LEFT_VOLUME] = 0xc0,
-       [WM8996_DSP1_RX_RIGHT_VOLUME] = 0xc0,
-       [WM8996_DSP1_TX_FILTERS] = 0x2000,
-       [WM8996_DSP1_RX_FILTERS_1] = 0x200,
-       [WM8996_DSP1_RX_FILTERS_2] = 0x10,
-       [WM8996_DSP1_DRC_1] = 0x98,
-       [WM8996_DSP1_DRC_2] = 0x845,
-       [WM8996_DSP1_RX_EQ_GAINS_1] = 0x6318,
-       [WM8996_DSP1_RX_EQ_GAINS_2] = 0x6300,
-       [WM8996_DSP1_RX_EQ_BAND_1_A] = 0xfca,
-       [WM8996_DSP1_RX_EQ_BAND_1_B] = 0x400,
-       [WM8996_DSP1_RX_EQ_BAND_1_PG] = 0xd8,
-       [WM8996_DSP1_RX_EQ_BAND_2_A] = 0x1eb5,
-       [WM8996_DSP1_RX_EQ_BAND_2_B] = 0xf145,
-       [WM8996_DSP1_RX_EQ_BAND_2_C] = 0xb75,
-       [WM8996_DSP1_RX_EQ_BAND_2_PG] = 0x1c5,
-       [WM8996_DSP1_RX_EQ_BAND_3_A] = 0x1c58,
-       [WM8996_DSP1_RX_EQ_BAND_3_B] = 0xf373,
-       [WM8996_DSP1_RX_EQ_BAND_3_C] = 0xa54,
-       [WM8996_DSP1_RX_EQ_BAND_3_PG] = 0x558,
-       [WM8996_DSP1_RX_EQ_BAND_4_A] = 0x168e,
-       [WM8996_DSP1_RX_EQ_BAND_4_B] = 0xf829,
-       [WM8996_DSP1_RX_EQ_BAND_4_C] = 0x7ad,
-       [WM8996_DSP1_RX_EQ_BAND_4_PG] = 0x1103,
-       [WM8996_DSP1_RX_EQ_BAND_5_A] = 0x564,
-       [WM8996_DSP1_RX_EQ_BAND_5_B] = 0x559,
-       [WM8996_DSP1_RX_EQ_BAND_5_PG] = 0x4000,
-       [WM8996_DSP2_TX_LEFT_VOLUME] = 0xc0,
-       [WM8996_DSP2_TX_RIGHT_VOLUME] = 0xc0,
-       [WM8996_DSP2_RX_LEFT_VOLUME] = 0xc0,
-       [WM8996_DSP2_RX_RIGHT_VOLUME] = 0xc0,
-       [WM8996_DSP2_TX_FILTERS] = 0x2000,
-       [WM8996_DSP2_RX_FILTERS_1] = 0x200,
-       [WM8996_DSP2_RX_FILTERS_2] = 0x10,
-       [WM8996_DSP2_DRC_1] = 0x98,
-       [WM8996_DSP2_DRC_2] = 0x845,
-       [WM8996_DSP2_RX_EQ_GAINS_1] = 0x6318,
-       [WM8996_DSP2_RX_EQ_GAINS_2] = 0x6300,
-       [WM8996_DSP2_RX_EQ_BAND_1_A] = 0xfca,
-       [WM8996_DSP2_RX_EQ_BAND_1_B] = 0x400,
-       [WM8996_DSP2_RX_EQ_BAND_1_PG] = 0xd8,
-       [WM8996_DSP2_RX_EQ_BAND_2_A] = 0x1eb5,
-       [WM8996_DSP2_RX_EQ_BAND_2_B] = 0xf145,
-       [WM8996_DSP2_RX_EQ_BAND_2_C] = 0xb75,
-       [WM8996_DSP2_RX_EQ_BAND_2_PG] = 0x1c5,
-       [WM8996_DSP2_RX_EQ_BAND_3_A] = 0x1c58,
-       [WM8996_DSP2_RX_EQ_BAND_3_B] = 0xf373,
-       [WM8996_DSP2_RX_EQ_BAND_3_C] = 0xa54,
-       [WM8996_DSP2_RX_EQ_BAND_3_PG] = 0x558,
-       [WM8996_DSP2_RX_EQ_BAND_4_A] = 0x168e,
-       [WM8996_DSP2_RX_EQ_BAND_4_B] = 0xf829,
-       [WM8996_DSP2_RX_EQ_BAND_4_C] = 0x7ad,
-       [WM8996_DSP2_RX_EQ_BAND_4_PG] = 0x1103,
-       [WM8996_DSP2_RX_EQ_BAND_5_A] = 0x564,
-       [WM8996_DSP2_RX_EQ_BAND_5_B] = 0x559,
-       [WM8996_DSP2_RX_EQ_BAND_5_PG] = 0x4000,
-       [WM8996_OVERSAMPLING] = 0xd,
-       [WM8996_SIDETONE] = 0x1040,
-       [WM8996_GPIO_1] = 0xa101,
-       [WM8996_GPIO_2] = 0xa101,
-       [WM8996_GPIO_3] = 0xa101,
-       [WM8996_GPIO_4] = 0xa101,
-       [WM8996_GPIO_5] = 0xa101,
-       [WM8996_PULL_CONTROL_2] = 0x140,
-       [WM8996_INTERRUPT_STATUS_1_MASK] = 0x1f,
-       [WM8996_INTERRUPT_STATUS_2_MASK] = 0x1ecf,
-       [WM8996_RIGHT_PDM_SPEAKER] = 0x1,
-       [WM8996_PDM_SPEAKER_MUTE_SEQUENCE] = 0x69,
-       [WM8996_PDM_SPEAKER_VOLUME] = 0x66,
-       [WM8996_WRITE_SEQUENCER_0] = 0x1,
-       [WM8996_WRITE_SEQUENCER_1] = 0x1,
-       [WM8996_WRITE_SEQUENCER_3] = 0x6,
-       [WM8996_WRITE_SEQUENCER_4] = 0x40,
-       [WM8996_WRITE_SEQUENCER_5] = 0x1,
-       [WM8996_WRITE_SEQUENCER_6] = 0xf,
-       [WM8996_WRITE_SEQUENCER_7] = 0x6,
-       [WM8996_WRITE_SEQUENCER_8] = 0x1,
-       [WM8996_WRITE_SEQUENCER_9] = 0x3,
-       [WM8996_WRITE_SEQUENCER_10] = 0x104,
-       [WM8996_WRITE_SEQUENCER_12] = 0x60,
-       [WM8996_WRITE_SEQUENCER_13] = 0x11,
-       [WM8996_WRITE_SEQUENCER_14] = 0x401,
-       [WM8996_WRITE_SEQUENCER_16] = 0x50,
-       [WM8996_WRITE_SEQUENCER_17] = 0x3,
-       [WM8996_WRITE_SEQUENCER_18] = 0x100,
-       [WM8996_WRITE_SEQUENCER_20] = 0x51,
-       [WM8996_WRITE_SEQUENCER_21] = 0x3,
-       [WM8996_WRITE_SEQUENCER_22] = 0x104,
-       [WM8996_WRITE_SEQUENCER_23] = 0xa,
-       [WM8996_WRITE_SEQUENCER_24] = 0x60,
-       [WM8996_WRITE_SEQUENCER_25] = 0x3b,
-       [WM8996_WRITE_SEQUENCER_26] = 0x502,
-       [WM8996_WRITE_SEQUENCER_27] = 0x100,
-       [WM8996_WRITE_SEQUENCER_28] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_32] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_36] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_40] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_44] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_48] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_52] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_56] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_60] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_64] = 0x1,
-       [WM8996_WRITE_SEQUENCER_65] = 0x1,
-       [WM8996_WRITE_SEQUENCER_67] = 0x6,
-       [WM8996_WRITE_SEQUENCER_68] = 0x40,
-       [WM8996_WRITE_SEQUENCER_69] = 0x1,
-       [WM8996_WRITE_SEQUENCER_70] = 0xf,
-       [WM8996_WRITE_SEQUENCER_71] = 0x6,
-       [WM8996_WRITE_SEQUENCER_72] = 0x1,
-       [WM8996_WRITE_SEQUENCER_73] = 0x3,
-       [WM8996_WRITE_SEQUENCER_74] = 0x104,
-       [WM8996_WRITE_SEQUENCER_76] = 0x60,
-       [WM8996_WRITE_SEQUENCER_77] = 0x11,
-       [WM8996_WRITE_SEQUENCER_78] = 0x401,
-       [WM8996_WRITE_SEQUENCER_80] = 0x50,
-       [WM8996_WRITE_SEQUENCER_81] = 0x3,
-       [WM8996_WRITE_SEQUENCER_82] = 0x100,
-       [WM8996_WRITE_SEQUENCER_84] = 0x60,
-       [WM8996_WRITE_SEQUENCER_85] = 0x3b,
-       [WM8996_WRITE_SEQUENCER_86] = 0x502,
-       [WM8996_WRITE_SEQUENCER_87] = 0x100,
-       [WM8996_WRITE_SEQUENCER_88] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_92] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_96] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_100] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_104] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_108] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_112] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_116] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_120] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_124] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_128] = 0x1,
-       [WM8996_WRITE_SEQUENCER_129] = 0x1,
-       [WM8996_WRITE_SEQUENCER_131] = 0x6,
-       [WM8996_WRITE_SEQUENCER_132] = 0x40,
-       [WM8996_WRITE_SEQUENCER_133] = 0x1,
-       [WM8996_WRITE_SEQUENCER_134] = 0xf,
-       [WM8996_WRITE_SEQUENCER_135] = 0x6,
-       [WM8996_WRITE_SEQUENCER_136] = 0x1,
-       [WM8996_WRITE_SEQUENCER_137] = 0x3,
-       [WM8996_WRITE_SEQUENCER_138] = 0x106,
-       [WM8996_WRITE_SEQUENCER_140] = 0x61,
-       [WM8996_WRITE_SEQUENCER_141] = 0x11,
-       [WM8996_WRITE_SEQUENCER_142] = 0x401,
-       [WM8996_WRITE_SEQUENCER_144] = 0x50,
-       [WM8996_WRITE_SEQUENCER_145] = 0x3,
-       [WM8996_WRITE_SEQUENCER_146] = 0x102,
-       [WM8996_WRITE_SEQUENCER_148] = 0x51,
-       [WM8996_WRITE_SEQUENCER_149] = 0x3,
-       [WM8996_WRITE_SEQUENCER_150] = 0x106,
-       [WM8996_WRITE_SEQUENCER_151] = 0xa,
-       [WM8996_WRITE_SEQUENCER_152] = 0x61,
-       [WM8996_WRITE_SEQUENCER_153] = 0x3b,
-       [WM8996_WRITE_SEQUENCER_154] = 0x502,
-       [WM8996_WRITE_SEQUENCER_155] = 0x100,
-       [WM8996_WRITE_SEQUENCER_156] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_160] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_164] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_168] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_172] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_176] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_180] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_184] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_188] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_192] = 0x1,
-       [WM8996_WRITE_SEQUENCER_193] = 0x1,
-       [WM8996_WRITE_SEQUENCER_195] = 0x6,
-       [WM8996_WRITE_SEQUENCER_196] = 0x40,
-       [WM8996_WRITE_SEQUENCER_197] = 0x1,
-       [WM8996_WRITE_SEQUENCER_198] = 0xf,
-       [WM8996_WRITE_SEQUENCER_199] = 0x6,
-       [WM8996_WRITE_SEQUENCER_200] = 0x1,
-       [WM8996_WRITE_SEQUENCER_201] = 0x3,
-       [WM8996_WRITE_SEQUENCER_202] = 0x106,
-       [WM8996_WRITE_SEQUENCER_204] = 0x61,
-       [WM8996_WRITE_SEQUENCER_205] = 0x11,
-       [WM8996_WRITE_SEQUENCER_206] = 0x401,
-       [WM8996_WRITE_SEQUENCER_208] = 0x50,
-       [WM8996_WRITE_SEQUENCER_209] = 0x3,
-       [WM8996_WRITE_SEQUENCER_210] = 0x102,
-       [WM8996_WRITE_SEQUENCER_212] = 0x61,
-       [WM8996_WRITE_SEQUENCER_213] = 0x3b,
-       [WM8996_WRITE_SEQUENCER_214] = 0x502,
-       [WM8996_WRITE_SEQUENCER_215] = 0x100,
-       [WM8996_WRITE_SEQUENCER_216] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_220] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_224] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_228] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_232] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_236] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_240] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_244] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_248] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_252] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_256] = 0x60,
-       [WM8996_WRITE_SEQUENCER_258] = 0x601,
-       [WM8996_WRITE_SEQUENCER_260] = 0x50,
-       [WM8996_WRITE_SEQUENCER_262] = 0x100,
-       [WM8996_WRITE_SEQUENCER_264] = 0x1,
-       [WM8996_WRITE_SEQUENCER_266] = 0x104,
-       [WM8996_WRITE_SEQUENCER_267] = 0x100,
-       [WM8996_WRITE_SEQUENCER_268] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_272] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_276] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_280] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_284] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_288] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_292] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_296] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_300] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_304] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_308] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_312] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_316] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_320] = 0x61,
-       [WM8996_WRITE_SEQUENCER_322] = 0x601,
-       [WM8996_WRITE_SEQUENCER_324] = 0x50,
-       [WM8996_WRITE_SEQUENCER_326] = 0x102,
-       [WM8996_WRITE_SEQUENCER_328] = 0x1,
-       [WM8996_WRITE_SEQUENCER_330] = 0x106,
-       [WM8996_WRITE_SEQUENCER_331] = 0x100,
-       [WM8996_WRITE_SEQUENCER_332] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_336] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_340] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_344] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_348] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_352] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_356] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_360] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_364] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_368] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_372] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_376] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_380] = 0x2fff,
-       [WM8996_WRITE_SEQUENCER_384] = 0x60,
-       [WM8996_WRITE_SEQUENCER_386] = 0x601,
-       [WM8996_WRITE_SEQUENCER_388] = 0x61,
-       [WM8996_WRITE_SEQUENCER_390] = 0x601,
-       [WM8996_WRITE_SEQUENCER_392] = 0x50,
-       [WM8996_WRITE_SEQUENCER_394] = 0x300,
-       [WM8996_WRITE_SEQUENCER_396] = 0x1,
-       [WM8996_WRITE_SEQUENCER_398] = 0x304,
-       [WM8996_WRITE_SEQUENCER_400] = 0x40,
-       [WM8996_WRITE_SEQUENCER_402] = 0xf,
-       [WM8996_WRITE_SEQUENCER_404] = 0x1,
-       [WM8996_WRITE_SEQUENCER_407] = 0x100,
+static struct reg_default wm8996_reg[] = {
+       { WM8996_SOFTWARE_RESET, 0x8996 },
+       { WM8996_POWER_MANAGEMENT_1, 0x0 },
+       { WM8996_POWER_MANAGEMENT_2, 0x0 },
+       { WM8996_POWER_MANAGEMENT_3, 0x0 },
+       { WM8996_POWER_MANAGEMENT_4, 0x0 },
+       { WM8996_POWER_MANAGEMENT_5, 0x0 },
+       { WM8996_POWER_MANAGEMENT_6, 0x0 },
+       { WM8996_POWER_MANAGEMENT_7, 0x10 },
+       { WM8996_POWER_MANAGEMENT_8, 0x0 },
+       { WM8996_LEFT_LINE_INPUT_VOLUME, 0x0 },
+       { WM8996_RIGHT_LINE_INPUT_VOLUME, 0x0 },
+       { WM8996_LINE_INPUT_CONTROL, 0x0 },
+       { WM8996_DAC1_HPOUT1_VOLUME, 0x88 },
+       { WM8996_DAC2_HPOUT2_VOLUME, 0x88 },
+       { WM8996_DAC1_LEFT_VOLUME, 0x2c0 },
+       { WM8996_DAC1_RIGHT_VOLUME, 0x2c0 },
+       { WM8996_DAC2_LEFT_VOLUME, 0x2c0 },
+       { WM8996_DAC2_RIGHT_VOLUME, 0x2c0 },
+       { WM8996_OUTPUT1_LEFT_VOLUME, 0x80 },
+       { WM8996_OUTPUT1_RIGHT_VOLUME, 0x80 },
+       { WM8996_OUTPUT2_LEFT_VOLUME, 0x80 },
+       { WM8996_OUTPUT2_RIGHT_VOLUME, 0x80 },
+       { WM8996_MICBIAS_1, 0x39 },
+       { WM8996_MICBIAS_2, 0x39 },
+       { WM8996_LDO_1, 0x3 },
+       { WM8996_LDO_2, 0x13 },
+       { WM8996_ACCESSORY_DETECT_MODE_1, 0x4 },
+       { WM8996_ACCESSORY_DETECT_MODE_2, 0x0 },
+       { WM8996_HEADPHONE_DETECT_1, 0x20 },
+       { WM8996_HEADPHONE_DETECT_2, 0x0 },
+       { WM8996_MIC_DETECT_1, 0x7600 },
+       { WM8996_MIC_DETECT_2, 0xbf },
+       { WM8996_CHARGE_PUMP_1, 0x1f25 },
+       { WM8996_CHARGE_PUMP_2, 0xab19 },
+       { WM8996_DC_SERVO_1, 0x0 },
+       { WM8996_DC_SERVO_2, 0x0 },
+       { WM8996_DC_SERVO_3, 0x0 },
+       { WM8996_DC_SERVO_5, 0x2a2a },
+       { WM8996_DC_SERVO_6, 0x0 },
+       { WM8996_DC_SERVO_7, 0x0 },
+       { WM8996_ANALOGUE_HP_1, 0x0 },
+       { WM8996_ANALOGUE_HP_2, 0x0 },
+       { WM8996_CONTROL_INTERFACE_1, 0x8004 },
+       { WM8996_WRITE_SEQUENCER_CTRL_1, 0x0 },
+       { WM8996_WRITE_SEQUENCER_CTRL_2, 0x0 },
+       { WM8996_AIF_CLOCKING_1, 0x0 },
+       { WM8996_AIF_CLOCKING_2, 0x0 },
+       { WM8996_CLOCKING_1, 0x10 },
+       { WM8996_CLOCKING_2, 0x0 },
+       { WM8996_AIF_RATE, 0x83 },
+       { WM8996_FLL_CONTROL_1, 0x0 },
+       { WM8996_FLL_CONTROL_2, 0x0 },
+       { WM8996_FLL_CONTROL_3, 0x0 },
+       { WM8996_FLL_CONTROL_4, 0x5dc0 },
+       { WM8996_FLL_CONTROL_5, 0xc84 },
+       { WM8996_FLL_EFS_1, 0x0 },
+       { WM8996_FLL_EFS_2, 0x2 },
+       { WM8996_AIF1_CONTROL, 0x0 },
+       { WM8996_AIF1_BCLK, 0x0 },
+       { WM8996_AIF1_TX_LRCLK_1, 0x80 },
+       { WM8996_AIF1_TX_LRCLK_2, 0x8 },
+       { WM8996_AIF1_RX_LRCLK_1, 0x80 },
+       { WM8996_AIF1_RX_LRCLK_2, 0x0 },
+       { WM8996_AIF1TX_DATA_CONFIGURATION_1, 0x1818 },
+       { WM8996_AIF1TX_DATA_CONFIGURATION_2, 0 },
+       { WM8996_AIF1RX_DATA_CONFIGURATION, 0x1818 },
+       { WM8996_AIF1TX_CHANNEL_0_CONFIGURATION, 0x0 },
+       { WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, 0x0 },
+       { WM8996_AIF1TX_CHANNEL_2_CONFIGURATION, 0x0 },
+       { WM8996_AIF1TX_CHANNEL_3_CONFIGURATION, 0x0 },
+       { WM8996_AIF1TX_CHANNEL_4_CONFIGURATION, 0x0 },
+       { WM8996_AIF1TX_CHANNEL_5_CONFIGURATION, 0x0 },
+       { WM8996_AIF1RX_CHANNEL_0_CONFIGURATION, 0x0 },
+       { WM8996_AIF1RX_CHANNEL_1_CONFIGURATION, 0x0 },
+       { WM8996_AIF1RX_CHANNEL_2_CONFIGURATION, 0x0 },
+       { WM8996_AIF1RX_CHANNEL_3_CONFIGURATION, 0x0 },
+       { WM8996_AIF1RX_CHANNEL_4_CONFIGURATION, 0x0 },
+       { WM8996_AIF1RX_CHANNEL_5_CONFIGURATION, 0x0 },
+       { WM8996_AIF1RX_MONO_CONFIGURATION, 0x0 },
+       { WM8996_AIF1TX_TEST, 0x7 },
+       { WM8996_AIF2_CONTROL, 0x0 },
+       { WM8996_AIF2_BCLK, 0x0 },
+       { WM8996_AIF2_TX_LRCLK_1, 0x80 },
+       { WM8996_AIF2_TX_LRCLK_2, 0x8 },
+       { WM8996_AIF2_RX_LRCLK_1, 0x80 },
+       { WM8996_AIF2_RX_LRCLK_2, 0x0 },
+       { WM8996_AIF2TX_DATA_CONFIGURATION_1, 0x1818 },
+       { WM8996_AIF2RX_DATA_CONFIGURATION, 0x1818 },
+       { WM8996_AIF2RX_DATA_CONFIGURATION, 0x0 },
+       { WM8996_AIF2TX_CHANNEL_0_CONFIGURATION, 0x0 },
+       { WM8996_AIF2TX_CHANNEL_1_CONFIGURATION, 0x0 },
+       { WM8996_AIF2RX_CHANNEL_0_CONFIGURATION, 0x0 },
+       { WM8996_AIF2RX_CHANNEL_1_CONFIGURATION, 0x0 },
+       { WM8996_AIF2RX_MONO_CONFIGURATION, 0x0 },
+       { WM8996_AIF2TX_TEST, 0x1 },
+       { WM8996_DSP1_TX_LEFT_VOLUME, 0xc0 },
+       { WM8996_DSP1_TX_RIGHT_VOLUME, 0xc0 },
+       { WM8996_DSP1_RX_LEFT_VOLUME, 0xc0 },
+       { WM8996_DSP1_RX_RIGHT_VOLUME, 0xc0 },
+       { WM8996_DSP1_TX_FILTERS, 0x2000 },
+       { WM8996_DSP1_RX_FILTERS_1, 0x200 },
+       { WM8996_DSP1_RX_FILTERS_2, 0x10 },
+       { WM8996_DSP1_DRC_1, 0x98 },
+       { WM8996_DSP1_DRC_2, 0x845 },
+       { WM8996_DSP1_RX_EQ_GAINS_1, 0x6318 },
+       { WM8996_DSP1_RX_EQ_GAINS_2, 0x6300 },
+       { WM8996_DSP1_RX_EQ_BAND_1_A, 0xfca },
+       { WM8996_DSP1_RX_EQ_BAND_1_B, 0x400 },
+       { WM8996_DSP1_RX_EQ_BAND_1_PG, 0xd8 },
+       { WM8996_DSP1_RX_EQ_BAND_2_A, 0x1eb5 },
+       { WM8996_DSP1_RX_EQ_BAND_2_B, 0xf145 },
+       { WM8996_DSP1_RX_EQ_BAND_2_C, 0xb75 },
+       { WM8996_DSP1_RX_EQ_BAND_2_PG, 0x1c5 },
+       { WM8996_DSP1_RX_EQ_BAND_3_A, 0x1c58 },
+       { WM8996_DSP1_RX_EQ_BAND_3_B, 0xf373 },
+       { WM8996_DSP1_RX_EQ_BAND_3_C, 0xa54 },
+       { WM8996_DSP1_RX_EQ_BAND_3_PG, 0x558 },
+       { WM8996_DSP1_RX_EQ_BAND_4_A, 0x168e },
+       { WM8996_DSP1_RX_EQ_BAND_4_B, 0xf829 },
+       { WM8996_DSP1_RX_EQ_BAND_4_C, 0x7ad },
+       { WM8996_DSP1_RX_EQ_BAND_4_PG, 0x1103 },
+       { WM8996_DSP1_RX_EQ_BAND_5_A, 0x564 },
+       { WM8996_DSP1_RX_EQ_BAND_5_B, 0x559 },
+       { WM8996_DSP1_RX_EQ_BAND_5_PG, 0x4000 },
+       { WM8996_DSP2_TX_LEFT_VOLUME, 0xc0 },
+       { WM8996_DSP2_TX_RIGHT_VOLUME, 0xc0 },
+       { WM8996_DSP2_RX_LEFT_VOLUME, 0xc0 },
+       { WM8996_DSP2_RX_RIGHT_VOLUME, 0xc0 },
+       { WM8996_DSP2_TX_FILTERS, 0x2000 },
+       { WM8996_DSP2_RX_FILTERS_1, 0x200 },
+       { WM8996_DSP2_RX_FILTERS_2, 0x10 },
+       { WM8996_DSP2_DRC_1, 0x98 },
+       { WM8996_DSP2_DRC_2, 0x845 },
+       { WM8996_DSP2_RX_EQ_GAINS_1, 0x6318 },
+       { WM8996_DSP2_RX_EQ_GAINS_2, 0x6300 },
+       { WM8996_DSP2_RX_EQ_BAND_1_A, 0xfca },
+       { WM8996_DSP2_RX_EQ_BAND_1_B, 0x400 },
+       { WM8996_DSP2_RX_EQ_BAND_1_PG, 0xd8 },
+       { WM8996_DSP2_RX_EQ_BAND_2_A, 0x1eb5 },
+       { WM8996_DSP2_RX_EQ_BAND_2_B, 0xf145 },
+       { WM8996_DSP2_RX_EQ_BAND_2_C, 0xb75 },
+       { WM8996_DSP2_RX_EQ_BAND_2_PG, 0x1c5 },
+       { WM8996_DSP2_RX_EQ_BAND_3_A, 0x1c58 },
+       { WM8996_DSP2_RX_EQ_BAND_3_B, 0xf373 },
+       { WM8996_DSP2_RX_EQ_BAND_3_C, 0xa54 },
+       { WM8996_DSP2_RX_EQ_BAND_3_PG, 0x558 },
+       { WM8996_DSP2_RX_EQ_BAND_4_A, 0x168e },
+       { WM8996_DSP2_RX_EQ_BAND_4_B, 0xf829 },
+       { WM8996_DSP2_RX_EQ_BAND_4_C, 0x7ad },
+       { WM8996_DSP2_RX_EQ_BAND_4_PG, 0x1103 },
+       { WM8996_DSP2_RX_EQ_BAND_5_A, 0x564 },
+       { WM8996_DSP2_RX_EQ_BAND_5_B, 0x559 },
+       { WM8996_DSP2_RX_EQ_BAND_5_PG, 0x4000 },
+       { WM8996_DAC1_MIXER_VOLUMES, 0x0 },
+       { WM8996_DAC1_LEFT_MIXER_ROUTING, 0x0 },
+       { WM8996_DAC1_RIGHT_MIXER_ROUTING, 0x0 },
+       { WM8996_DAC2_MIXER_VOLUMES, 0x0 },
+       { WM8996_DAC2_LEFT_MIXER_ROUTING, 0x0 },
+       { WM8996_DAC2_RIGHT_MIXER_ROUTING, 0x0 },
+       { WM8996_DSP1_TX_LEFT_MIXER_ROUTING, 0x0 },
+       { WM8996_DSP1_TX_RIGHT_MIXER_ROUTING, 0x0 },
+       { WM8996_DSP2_TX_LEFT_MIXER_ROUTING, 0x0 },
+       { WM8996_DSP2_TX_RIGHT_MIXER_ROUTING, 0x0 },
+       { WM8996_DSP_TX_MIXER_SELECT, 0x0 },
+       { WM8996_DAC_SOFTMUTE, 0x0 },
+       { WM8996_OVERSAMPLING, 0xd },
+       { WM8996_SIDETONE, 0x1040 },
+       { WM8996_GPIO_1, 0xa101 },
+       { WM8996_GPIO_2, 0xa101 },
+       { WM8996_GPIO_3, 0xa101 },
+       { WM8996_GPIO_4, 0xa101 },
+       { WM8996_GPIO_5, 0xa101 },
+       { WM8996_PULL_CONTROL_1, 0x0 },
+       { WM8996_PULL_CONTROL_2, 0x140 },
+       { WM8996_INTERRUPT_STATUS_1_MASK, 0x1f },
+       { WM8996_INTERRUPT_STATUS_2_MASK, 0x1ecf },
+       { WM8996_LEFT_PDM_SPEAKER, 0x0 },
+       { WM8996_RIGHT_PDM_SPEAKER, 0x1 },
+       { WM8996_PDM_SPEAKER_MUTE_SEQUENCE, 0x69 },
+       { WM8996_PDM_SPEAKER_VOLUME, 0x66 },
+       { WM8996_WRITE_SEQUENCER_0, 0x1 },
+       { WM8996_WRITE_SEQUENCER_1, 0x1 },
+       { WM8996_WRITE_SEQUENCER_3, 0x6 },
+       { WM8996_WRITE_SEQUENCER_4, 0x40 },
+       { WM8996_WRITE_SEQUENCER_5, 0x1 },
+       { WM8996_WRITE_SEQUENCER_6, 0xf },
+       { WM8996_WRITE_SEQUENCER_7, 0x6 },
+       { WM8996_WRITE_SEQUENCER_8, 0x1 },
+       { WM8996_WRITE_SEQUENCER_9, 0x3 },
+       { WM8996_WRITE_SEQUENCER_10, 0x104 },
+       { WM8996_WRITE_SEQUENCER_12, 0x60 },
+       { WM8996_WRITE_SEQUENCER_13, 0x11 },
+       { WM8996_WRITE_SEQUENCER_14, 0x401 },
+       { WM8996_WRITE_SEQUENCER_16, 0x50 },
+       { WM8996_WRITE_SEQUENCER_17, 0x3 },
+       { WM8996_WRITE_SEQUENCER_18, 0x100 },
+       { WM8996_WRITE_SEQUENCER_20, 0x51 },
+       { WM8996_WRITE_SEQUENCER_21, 0x3 },
+       { WM8996_WRITE_SEQUENCER_22, 0x104 },
+       { WM8996_WRITE_SEQUENCER_23, 0xa },
+       { WM8996_WRITE_SEQUENCER_24, 0x60 },
+       { WM8996_WRITE_SEQUENCER_25, 0x3b },
+       { WM8996_WRITE_SEQUENCER_26, 0x502 },
+       { WM8996_WRITE_SEQUENCER_27, 0x100 },
+       { WM8996_WRITE_SEQUENCER_28, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_32, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_36, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_40, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_44, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_48, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_52, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_56, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_60, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_64, 0x1 },
+       { WM8996_WRITE_SEQUENCER_65, 0x1 },
+       { WM8996_WRITE_SEQUENCER_67, 0x6 },
+       { WM8996_WRITE_SEQUENCER_68, 0x40 },
+       { WM8996_WRITE_SEQUENCER_69, 0x1 },
+       { WM8996_WRITE_SEQUENCER_70, 0xf },
+       { WM8996_WRITE_SEQUENCER_71, 0x6 },
+       { WM8996_WRITE_SEQUENCER_72, 0x1 },
+       { WM8996_WRITE_SEQUENCER_73, 0x3 },
+       { WM8996_WRITE_SEQUENCER_74, 0x104 },
+       { WM8996_WRITE_SEQUENCER_76, 0x60 },
+       { WM8996_WRITE_SEQUENCER_77, 0x11 },
+       { WM8996_WRITE_SEQUENCER_78, 0x401 },
+       { WM8996_WRITE_SEQUENCER_80, 0x50 },
+       { WM8996_WRITE_SEQUENCER_81, 0x3 },
+       { WM8996_WRITE_SEQUENCER_82, 0x100 },
+       { WM8996_WRITE_SEQUENCER_84, 0x60 },
+       { WM8996_WRITE_SEQUENCER_85, 0x3b },
+       { WM8996_WRITE_SEQUENCER_86, 0x502 },
+       { WM8996_WRITE_SEQUENCER_87, 0x100 },
+       { WM8996_WRITE_SEQUENCER_88, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_92, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_96, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_100, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_104, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_108, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_112, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_116, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_120, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_124, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_128, 0x1 },
+       { WM8996_WRITE_SEQUENCER_129, 0x1 },
+       { WM8996_WRITE_SEQUENCER_131, 0x6 },
+       { WM8996_WRITE_SEQUENCER_132, 0x40 },
+       { WM8996_WRITE_SEQUENCER_133, 0x1 },
+       { WM8996_WRITE_SEQUENCER_134, 0xf },
+       { WM8996_WRITE_SEQUENCER_135, 0x6 },
+       { WM8996_WRITE_SEQUENCER_136, 0x1 },
+       { WM8996_WRITE_SEQUENCER_137, 0x3 },
+       { WM8996_WRITE_SEQUENCER_138, 0x106 },
+       { WM8996_WRITE_SEQUENCER_140, 0x61 },
+       { WM8996_WRITE_SEQUENCER_141, 0x11 },
+       { WM8996_WRITE_SEQUENCER_142, 0x401 },
+       { WM8996_WRITE_SEQUENCER_144, 0x50 },
+       { WM8996_WRITE_SEQUENCER_145, 0x3 },
+       { WM8996_WRITE_SEQUENCER_146, 0x102 },
+       { WM8996_WRITE_SEQUENCER_148, 0x51 },
+       { WM8996_WRITE_SEQUENCER_149, 0x3 },
+       { WM8996_WRITE_SEQUENCER_150, 0x106 },
+       { WM8996_WRITE_SEQUENCER_151, 0xa },
+       { WM8996_WRITE_SEQUENCER_152, 0x61 },
+       { WM8996_WRITE_SEQUENCER_153, 0x3b },
+       { WM8996_WRITE_SEQUENCER_154, 0x502 },
+       { WM8996_WRITE_SEQUENCER_155, 0x100 },
+       { WM8996_WRITE_SEQUENCER_156, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_160, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_164, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_168, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_172, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_176, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_180, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_184, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_188, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_192, 0x1 },
+       { WM8996_WRITE_SEQUENCER_193, 0x1 },
+       { WM8996_WRITE_SEQUENCER_195, 0x6 },
+       { WM8996_WRITE_SEQUENCER_196, 0x40 },
+       { WM8996_WRITE_SEQUENCER_197, 0x1 },
+       { WM8996_WRITE_SEQUENCER_198, 0xf },
+       { WM8996_WRITE_SEQUENCER_199, 0x6 },
+       { WM8996_WRITE_SEQUENCER_200, 0x1 },
+       { WM8996_WRITE_SEQUENCER_201, 0x3 },
+       { WM8996_WRITE_SEQUENCER_202, 0x106 },
+       { WM8996_WRITE_SEQUENCER_204, 0x61 },
+       { WM8996_WRITE_SEQUENCER_205, 0x11 },
+       { WM8996_WRITE_SEQUENCER_206, 0x401 },
+       { WM8996_WRITE_SEQUENCER_208, 0x50 },
+       { WM8996_WRITE_SEQUENCER_209, 0x3 },
+       { WM8996_WRITE_SEQUENCER_210, 0x102 },
+       { WM8996_WRITE_SEQUENCER_212, 0x61 },
+       { WM8996_WRITE_SEQUENCER_213, 0x3b },
+       { WM8996_WRITE_SEQUENCER_214, 0x502 },
+       { WM8996_WRITE_SEQUENCER_215, 0x100 },
+       { WM8996_WRITE_SEQUENCER_216, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_220, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_224, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_228, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_232, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_236, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_240, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_244, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_248, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_252, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_256, 0x60 },
+       { WM8996_WRITE_SEQUENCER_258, 0x601 },
+       { WM8996_WRITE_SEQUENCER_260, 0x50 },
+       { WM8996_WRITE_SEQUENCER_262, 0x100 },
+       { WM8996_WRITE_SEQUENCER_264, 0x1 },
+       { WM8996_WRITE_SEQUENCER_266, 0x104 },
+       { WM8996_WRITE_SEQUENCER_267, 0x100 },
+       { WM8996_WRITE_SEQUENCER_268, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_272, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_276, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_280, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_284, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_288, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_292, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_296, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_300, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_304, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_308, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_312, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_316, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_320, 0x61 },
+       { WM8996_WRITE_SEQUENCER_322, 0x601 },
+       { WM8996_WRITE_SEQUENCER_324, 0x50 },
+       { WM8996_WRITE_SEQUENCER_326, 0x102 },
+       { WM8996_WRITE_SEQUENCER_328, 0x1 },
+       { WM8996_WRITE_SEQUENCER_330, 0x106 },
+       { WM8996_WRITE_SEQUENCER_331, 0x100 },
+       { WM8996_WRITE_SEQUENCER_332, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_336, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_340, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_344, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_348, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_352, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_356, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_360, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_364, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_368, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_372, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_376, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_380, 0x2fff },
+       { WM8996_WRITE_SEQUENCER_384, 0x60 },
+       { WM8996_WRITE_SEQUENCER_386, 0x601 },
+       { WM8996_WRITE_SEQUENCER_388, 0x61 },
+       { WM8996_WRITE_SEQUENCER_390, 0x601 },
+       { WM8996_WRITE_SEQUENCER_392, 0x50 },
+       { WM8996_WRITE_SEQUENCER_394, 0x300 },
+       { WM8996_WRITE_SEQUENCER_396, 0x1 },
+       { WM8996_WRITE_SEQUENCER_398, 0x304 },
+       { WM8996_WRITE_SEQUENCER_400, 0x40 },
+       { WM8996_WRITE_SEQUENCER_402, 0xf },
+       { WM8996_WRITE_SEQUENCER_404, 0x1 },
+       { WM8996_WRITE_SEQUENCER_407, 0x100 },
 };
 
 static const DECLARE_TLV_DB_SCALE(inpga_tlv, 0, 100, 0);
@@ -1413,8 +1484,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
        { "SPKDAT", NULL, "SPKR PGA" },
 };
 
-static int wm8996_readable_register(struct snd_soc_codec *codec,
-                                   unsigned int reg)
+static bool wm8996_readable_register(struct device *dev, unsigned int reg)
 {
        /* Due to the sparseness of the register map the compiler
         * output from an explicit switch statement ends up being much
@@ -1621,8 +1691,7 @@ static int wm8996_readable_register(struct snd_soc_codec *codec,
        }
 }
 
-static int wm8996_volatile_register(struct snd_soc_codec *codec,
-                                   unsigned int reg)
+static bool wm8996_volatile_register(struct device *dev, unsigned int reg)
 {
        switch (reg) {
        case WM8996_SOFTWARE_RESET:
@@ -1646,9 +1715,15 @@ static int wm8996_volatile_register(struct snd_soc_codec *codec,
        }
 }
 
-static int wm8996_reset(struct snd_soc_codec *codec)
+static int wm8996_reset(struct wm8996_priv *wm8996)
 {
-       return snd_soc_write(codec, WM8996_SOFTWARE_RESET, 0x8915);
+       if (wm8996->pdata.ldo_ena > 0) {
+               gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
+               return 0;
+       } else {
+               return regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET,
+                                   0x8915);
+       }
 }
 
 static const int bclk_divs[] = {
@@ -1723,13 +1798,13 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec,
                                msleep(5);
                        }
 
-                       codec->cache_only = false;
-                       snd_soc_cache_sync(codec);
+                       regcache_cache_only(codec->control_data, false);
+                       regcache_sync(codec->control_data);
                }
                break;
 
        case SND_SOC_BIAS_OFF:
-               codec->cache_only = true;
+               regcache_cache_only(codec->control_data, true);
                if (wm8996->pdata.ldo_ena >= 0)
                        gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
                regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies),
@@ -1968,6 +2043,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai,
                break;
        case 24576000:
                ratediv = WM8996_SYSCLK_DIV;
+               wm8996->sysclk /= 2;
        case 12288000:
                snd_soc_update_bits(codec, WM8996_AIF_RATE,
                                    WM8996_SYSCLK_RATE, WM8996_SYSCLK_RATE);
@@ -2251,48 +2327,45 @@ static inline struct wm8996_priv *gpio_to_wm8996(struct gpio_chip *chip)
 static void wm8996_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
        struct wm8996_priv *wm8996 = gpio_to_wm8996(chip);
-       struct snd_soc_codec *codec = wm8996->codec;
 
-       snd_soc_update_bits(codec, WM8996_GPIO_1 + offset,
-                           WM8996_GP1_LVL, !!value << WM8996_GP1_LVL_SHIFT);
+       regmap_update_bits(wm8996->regmap, WM8996_GPIO_1 + offset,
+                          WM8996_GP1_LVL, !!value << WM8996_GP1_LVL_SHIFT);
 }
 
 static int wm8996_gpio_direction_out(struct gpio_chip *chip,
                                     unsigned offset, int value)
 {
        struct wm8996_priv *wm8996 = gpio_to_wm8996(chip);
-       struct snd_soc_codec *codec = wm8996->codec;
        int val;
 
        val = (1 << WM8996_GP1_FN_SHIFT) | (!!value << WM8996_GP1_LVL_SHIFT);
 
-       return snd_soc_update_bits(codec, WM8996_GPIO_1 + offset,
-                                  WM8996_GP1_FN_MASK | WM8996_GP1_DIR |
-                                  WM8996_GP1_LVL, val);
+       return regmap_update_bits(wm8996->regmap, WM8996_GPIO_1 + offset,
+                                 WM8996_GP1_FN_MASK | WM8996_GP1_DIR |
+                                 WM8996_GP1_LVL, val);
 }
 
 static int wm8996_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
        struct wm8996_priv *wm8996 = gpio_to_wm8996(chip);
-       struct snd_soc_codec *codec = wm8996->codec;
+       unsigned int reg;
        int ret;
 
-       ret = snd_soc_read(codec, WM8996_GPIO_1 + offset);
+       ret = regmap_read(wm8996->regmap, WM8996_GPIO_1 + offset, &reg);
        if (ret < 0)
                return ret;
 
-       return (ret & WM8996_GP1_LVL) != 0;
+       return (reg & WM8996_GP1_LVL) != 0;
 }
 
 static int wm8996_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
 {
        struct wm8996_priv *wm8996 = gpio_to_wm8996(chip);
-       struct snd_soc_codec *codec = wm8996->codec;
 
-       return snd_soc_update_bits(codec, WM8996_GPIO_1 + offset,
-                                  WM8996_GP1_FN_MASK | WM8996_GP1_DIR,
-                                  (1 << WM8996_GP1_FN_SHIFT) |
-                                  (1 << WM8996_GP1_DIR_SHIFT));
+       return regmap_update_bits(wm8996->regmap, WM8996_GPIO_1 + offset,
+                                 WM8996_GP1_FN_MASK | WM8996_GP1_DIR,
+                                 (1 << WM8996_GP1_FN_SHIFT) |
+                                 (1 << WM8996_GP1_DIR_SHIFT));
 }
 
 static struct gpio_chip wm8996_template_chip = {
@@ -2305,14 +2378,13 @@ static struct gpio_chip wm8996_template_chip = {
        .can_sleep              = 1,
 };
 
-static void wm8996_init_gpio(struct snd_soc_codec *codec)
+static void wm8996_init_gpio(struct wm8996_priv *wm8996)
 {
-       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
        wm8996->gpio_chip = wm8996_template_chip;
        wm8996->gpio_chip.ngpio = 5;
-       wm8996->gpio_chip.dev = codec->dev;
+       wm8996->gpio_chip.dev = wm8996->dev;
 
        if (wm8996->pdata.gpio_base)
                wm8996->gpio_chip.base = wm8996->pdata.gpio_base;
@@ -2321,24 +2393,23 @@ static void wm8996_init_gpio(struct snd_soc_codec *codec)
 
        ret = gpiochip_add(&wm8996->gpio_chip);
        if (ret != 0)
-               dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
+               dev_err(wm8996->dev, "Failed to add GPIOs: %d\n", ret);
 }
 
-static void wm8996_free_gpio(struct snd_soc_codec *codec)
+static void wm8996_free_gpio(struct wm8996_priv *wm8996)
 {
-       struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
        ret = gpiochip_remove(&wm8996->gpio_chip);
        if (ret != 0)
-               dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
+               dev_err(wm8996->dev, "Failed to remove GPIOs: %d\n", ret);
 }
 #else
-static void wm8996_init_gpio(struct snd_soc_codec *codec)
+static void wm8996_init_gpio(struct wm8996_priv *wm8996)
 {
 }
 
-static void wm8996_free_gpio(struct snd_soc_codec *codec)
+static void wm8996_free_gpio(struct wm8996_priv *wm8996)
 {
 }
 #endif
@@ -2692,6 +2763,18 @@ static void wm8996_retune_mobile_pdata(struct snd_soc_codec *codec)
                        "Failed to add ReTune Mobile controls: %d\n", ret);
 }
 
+static const struct regmap_config wm8996_regmap = {
+       .reg_bits = 16,
+       .val_bits = 16,
+
+       .max_register = WM8996_MAX_REGISTER,
+       .reg_defaults = wm8996_reg,
+       .num_reg_defaults = ARRAY_SIZE(wm8996_reg),
+       .volatile_reg = wm8996_volatile_register,
+       .readable_reg = wm8996_readable_register,
+       .cache_type = REGCACHE_RBTREE,
+};
+
 static int wm8996_probe(struct snd_soc_codec *codec)
 {
        int ret;
@@ -2707,19 +2790,11 @@ static int wm8996_probe(struct snd_soc_codec *codec)
 
        dapm->idle_bias_off = true;
 
-       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);
-               goto err;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
-               wm8996->supplies[i].supply = wm8996_supply_names[i];
+       codec->control_data = wm8996->regmap;
 
-       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8996->supplies),
-                                wm8996->supplies);
+       ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
        if (ret != 0) {
-               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                goto err;
        }
 
@@ -2727,13 +2802,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
        wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1;
        wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2;
 
-       wm8996->cpvdd = regulator_get(&i2c->dev, "CPVDD");
-       if (IS_ERR(wm8996->cpvdd)) {
-               ret = PTR_ERR(wm8996->cpvdd);
-               dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret);
-               goto err_get;
-       }
-
        /* This should really be moved into the regulator core */
        for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) {
                ret = regulator_register_notifier(wm8996->supplies[i].consumer,
@@ -2745,50 +2813,7 @@ static int wm8996_probe(struct snd_soc_codec *codec)
                }
        }
 
-       ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies),
-                                   wm8996->supplies);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
-               goto err_cpvdd;
-       }
-
-       if (wm8996->pdata.ldo_ena >= 0) {
-               gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1);
-               msleep(5);
-       }
-
-       ret = snd_soc_read(codec, WM8996_SOFTWARE_RESET);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to read ID register: %d\n", ret);
-               goto err_enable;
-       }
-       if (ret != 0x8915) {
-               dev_err(codec->dev, "Device is not a WM8996, ID %x\n", ret);
-               ret = -EINVAL;
-               goto err_enable;
-       }
-
-       ret = snd_soc_read(codec, WM8996_CHIP_REVISION);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to read device revision: %d\n",
-                       ret);
-               goto err_enable;
-       }
-       
-       dev_info(codec->dev, "revision %c\n",
-                (ret & WM8996_CHIP_REV_MASK) + 'A');
-
-       if (wm8996->pdata.ldo_ena >= 0) {
-               gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
-       } else {
-               ret = wm8996_reset(codec);
-               if (ret < 0) {
-                       dev_err(codec->dev, "Failed to issue reset\n");
-                       goto err_enable;
-               }
-       }
-
-       codec->cache_only = true;
+       regcache_cache_only(codec->control_data, true);
 
        /* Apply platform data settings */
        snd_soc_update_bits(codec, WM8996_LINE_INPUT_CONTROL,
@@ -2946,10 +2971,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
                                    WM8996_AIF2TX_LRCLK_MODE,
                                    WM8996_AIF2TX_LRCLK_MODE);
 
-       regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
-
-       wm8996_init_gpio(codec);
-
        if (i2c->irq) {
                if (wm8996->pdata.irq_flags)
                        irq_flags = wm8996->pdata.irq_flags;
@@ -2987,15 +3008,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
 
        return 0;
 
-err_enable:
-       if (wm8996->pdata.ldo_ena >= 0)
-               gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
-
-       regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
-err_cpvdd:
-       regulator_put(wm8996->cpvdd);
-err_get:
-       regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
 err:
        return ret;
 }
@@ -3012,8 +3024,6 @@ static int wm8996_remove(struct snd_soc_codec *codec)
        if (i2c->irq)
                free_irq(i2c->irq, codec);
 
-       wm8996_free_gpio(codec);
-
        for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
                regulator_unregister_notifier(wm8996->supplies[i].consumer,
                                              &wm8996->disable_nb[i]);
@@ -3028,12 +3038,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8996 = {
        .remove =       wm8996_remove,
        .set_bias_level = wm8996_set_bias_level,
        .seq_notifier = wm8996_seq_notifier,
-       .reg_cache_size = WM8996_MAX_REGISTER + 1,
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8996_reg,
-       .volatile_register = wm8996_volatile_register,
-       .readable_register = wm8996_readable_register,
-       .compress_type = SND_SOC_RBTREE_COMPRESSION,
        .controls = wm8996_snd_controls,
        .num_controls = ARRAY_SIZE(wm8996_snd_controls),
        .dapm_widgets = wm8996_dapm_widgets,
@@ -3049,7 +3053,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8996 = {
                        SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\
                        SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm8996_dai_ops = {
+static const struct snd_soc_dai_ops wm8996_dai_ops = {
        .set_fmt = wm8996_set_fmt,
        .hw_params = wm8996_hw_params,
        .set_sysclk = wm8996_set_sysclk,
@@ -3098,13 +3102,16 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm8996_priv *wm8996;
-       int ret;
+       int ret, i;
+       unsigned int reg;
 
-       wm8996 = kzalloc(sizeof(struct wm8996_priv), GFP_KERNEL);
+       wm8996 = devm_kzalloc(&i2c->dev, sizeof(struct wm8996_priv),
+                             GFP_KERNEL);
        if (wm8996 == NULL)
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm8996);
+       wm8996->dev = &i2c->dev;
 
        if (dev_get_platdata(&i2c->dev))
                memcpy(&wm8996->pdata, dev_get_platdata(&i2c->dev),
@@ -3120,19 +3127,97 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
                }
        }
 
+       for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
+               wm8996->supplies[i].supply = wm8996_supply_names[i];
+
+       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8996->supplies),
+                                wm8996->supplies);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
+               goto err_gpio;
+       }
+
+       wm8996->cpvdd = regulator_get(&i2c->dev, "CPVDD");
+       if (IS_ERR(wm8996->cpvdd)) {
+               ret = PTR_ERR(wm8996->cpvdd);
+               dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret);
+               goto err_get;
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies),
+                                   wm8996->supplies);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
+               goto err_cpvdd;
+       }
+
+       if (wm8996->pdata.ldo_ena > 0) {
+               gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1);
+               msleep(5);
+       }
+
+       wm8996->regmap = regmap_init_i2c(i2c, &wm8996_regmap);
+       if (IS_ERR(wm8996->regmap)) {
+               ret = PTR_ERR(wm8996->regmap);
+               dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
+               goto err_enable;
+       }
+
+       ret = regmap_read(wm8996->regmap, WM8996_SOFTWARE_RESET, &reg);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
+               goto err_regmap;
+       }
+       if (reg != 0x8915) {
+               dev_err(&i2c->dev, "Device is not a WM8996, ID %x\n", ret);
+               ret = -EINVAL;
+               goto err_regmap;
+       }
+
+       ret = regmap_read(wm8996->regmap, WM8996_CHIP_REVISION, &reg);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to read device revision: %d\n",
+                       ret);
+               goto err_regmap;
+       }
+
+       dev_info(&i2c->dev, "revision %c\n",
+                (reg & WM8996_CHIP_REV_MASK) + 'A');
+
+       regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
+
+       ret = wm8996_reset(wm8996);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to issue reset\n");
+               goto err_regmap;
+       }
+
+       wm8996_init_gpio(wm8996);
+
        ret = snd_soc_register_codec(&i2c->dev,
                                     &soc_codec_dev_wm8996, wm8996_dai,
                                     ARRAY_SIZE(wm8996_dai));
        if (ret < 0)
-               goto err_gpio;
+               goto err_gpiolib;
 
        return ret;
 
+err_gpiolib:
+       wm8996_free_gpio(wm8996);
+err_regmap:
+       regmap_exit(wm8996->regmap);
+err_enable:
+       if (wm8996->pdata.ldo_ena > 0)
+               gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
+       regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
+err_cpvdd:
+       regulator_put(wm8996->cpvdd);
+err_get:
+       regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
 err_gpio:
        if (wm8996->pdata.ldo_ena > 0)
                gpio_free(wm8996->pdata.ldo_ena);
 err:
-       kfree(wm8996);
 
        return ret;
 }
@@ -3142,9 +3227,14 @@ static __devexit int wm8996_i2c_remove(struct i2c_client *client)
        struct wm8996_priv *wm8996 = i2c_get_clientdata(client);
 
        snd_soc_unregister_codec(&client->dev);
-       if (wm8996->pdata.ldo_ena > 0)
+       wm8996_free_gpio(wm8996);
+       regulator_put(wm8996->cpvdd);
+       regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
+       regmap_exit(wm8996->regmap);
+       if (wm8996->pdata.ldo_ena > 0) {
+               gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
                gpio_free(wm8996->pdata.ldo_ena);
-       kfree(i2c_get_clientdata(client));
+       }
        return 0;
 }
 
index 3cd35a0..1f2672b 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/device.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/wm9081.h>
 #include "wm9081.h"
 
-static u16 wm9081_reg_defaults[] = {
-       0x0000,     /* R0  - Software Reset */
-       0x0000,     /* R1 */
-       0x00B9,     /* R2  - Analogue Lineout */
-       0x00B9,     /* R3  - Analogue Speaker PGA */
-       0x0001,     /* R4  - VMID Control */
-       0x0068,     /* R5  - Bias Control 1 */
-       0x0000,     /* R6 */
-       0x0000,     /* R7  - Analogue Mixer */
-       0x0000,     /* R8  - Anti Pop Control */
-       0x01DB,     /* R9  - Analogue Speaker 1 */
-       0x0018,     /* R10 - Analogue Speaker 2 */
-       0x0180,     /* R11 - Power Management */
-       0x0000,     /* R12 - Clock Control 1 */
-       0x0038,     /* R13 - Clock Control 2 */
-       0x4000,     /* R14 - Clock Control 3 */
-       0x0000,     /* R15 */
-       0x0000,     /* R16 - FLL Control 1 */
-       0x0200,     /* R17 - FLL Control 2 */
-       0x0000,     /* R18 - FLL Control 3 */
-       0x0204,     /* R19 - FLL Control 4 */
-       0x0000,     /* R20 - FLL Control 5 */
-       0x0000,     /* R21 */
-       0x0000,     /* R22 - Audio Interface 1 */
-       0x0002,     /* R23 - Audio Interface 2 */
-       0x0008,     /* R24 - Audio Interface 3 */
-       0x0022,     /* R25 - Audio Interface 4 */
-       0x0000,     /* R26 - Interrupt Status */
-       0x0006,     /* R27 - Interrupt Status Mask */
-       0x0000,     /* R28 - Interrupt Polarity */
-       0x0000,     /* R29 - Interrupt Control */
-       0x00C0,     /* R30 - DAC Digital 1 */
-       0x0008,     /* R31 - DAC Digital 2 */
-       0x09AF,     /* R32 - DRC 1 */
-       0x4201,     /* R33 - DRC 2 */
-       0x0000,     /* R34 - DRC 3 */
-       0x0000,     /* R35 - DRC 4 */
-       0x0000,     /* R36 */
-       0x0000,     /* R37 */
-       0x0000,     /* R38 - Write Sequencer 1 */
-       0x0000,     /* R39 - Write Sequencer 2 */
-       0x0002,     /* R40 - MW Slave 1 */
-       0x0000,     /* R41 */
-       0x0000,     /* R42 - EQ 1 */
-       0x0000,     /* R43 - EQ 2 */
-       0x0FCA,     /* R44 - EQ 3 */
-       0x0400,     /* R45 - EQ 4 */
-       0x00B8,     /* R46 - EQ 5 */
-       0x1EB5,     /* R47 - EQ 6 */
-       0xF145,     /* R48 - EQ 7 */
-       0x0B75,     /* R49 - EQ 8 */
-       0x01C5,     /* R50 - EQ 9 */
-       0x169E,     /* R51 - EQ 10 */
-       0xF829,     /* R52 - EQ 11 */
-       0x07AD,     /* R53 - EQ 12 */
-       0x1103,     /* R54 - EQ 13 */
-       0x1C58,     /* R55 - EQ 14 */
-       0xF373,     /* R56 - EQ 15 */
-       0x0A54,     /* R57 - EQ 16 */
-       0x0558,     /* R58 - EQ 17 */
-       0x0564,     /* R59 - EQ 18 */
-       0x0559,     /* R60 - EQ 19 */
-       0x4000,     /* R61 - EQ 20 */
+static struct reg_default wm9081_reg[] = {
+       {  0, 0x9081 },     /* R0  - Software Reset */
+       {  2, 0x00B9 },     /* R2  - Analogue Lineout */
+       {  3, 0x00B9 },     /* R3  - Analogue Speaker PGA */
+       {  4, 0x0001 },     /* R4  - VMID Control */
+       {  5, 0x0068 },     /* R5  - Bias Control 1 */
+       {  7, 0x0000 },     /* R7  - Analogue Mixer */
+       {  8, 0x0000 },     /* R8  - Anti Pop Control */
+       {  9, 0x01DB },     /* R9  - Analogue Speaker 1 */
+       { 10, 0x0018 },     /* R10 - Analogue Speaker 2 */
+       { 11, 0x0180 },     /* R11 - Power Management */
+       { 12, 0x0000 },     /* R12 - Clock Control 1 */
+       { 13, 0x0038 },     /* R13 - Clock Control 2 */
+       { 14, 0x4000 },     /* R14 - Clock Control 3 */
+       { 16, 0x0000 },     /* R16 - FLL Control 1 */
+       { 17, 0x0200 },     /* R17 - FLL Control 2 */
+       { 18, 0x0000 },     /* R18 - FLL Control 3 */
+       { 19, 0x0204 },     /* R19 - FLL Control 4 */
+       { 20, 0x0000 },     /* R20 - FLL Control 5 */
+       { 22, 0x0000 },     /* R22 - Audio Interface 1 */
+       { 23, 0x0002 },     /* R23 - Audio Interface 2 */
+       { 24, 0x0008 },     /* R24 - Audio Interface 3 */
+       { 25, 0x0022 },     /* R25 - Audio Interface 4 */
+       { 27, 0x0006 },     /* R27 - Interrupt Status Mask */
+       { 28, 0x0000 },     /* R28 - Interrupt Polarity */
+       { 29, 0x0000 },     /* R29 - Interrupt Control */
+       { 30, 0x00C0 },     /* R30 - DAC Digital 1 */
+       { 31, 0x0008 },     /* R31 - DAC Digital 2 */
+       { 32, 0x09AF },     /* R32 - DRC 1 */
+       { 33, 0x4201 },     /* R33 - DRC 2 */
+       { 34, 0x0000 },     /* R34 - DRC 3 */
+       { 35, 0x0000 },     /* R35 - DRC 4 */
+       { 38, 0x0000 },     /* R38 - Write Sequencer 1 */
+       { 39, 0x0000 },     /* R39 - Write Sequencer 2 */
+       { 40, 0x0002 },     /* R40 - MW Slave 1 */
+       { 42, 0x0000 },     /* R42 - EQ 1 */
+       { 43, 0x0000 },     /* R43 - EQ 2 */
+       { 44, 0x0FCA },     /* R44 - EQ 3 */
+       { 45, 0x0400 },     /* R45 - EQ 4 */
+       { 46, 0x00B8 },     /* R46 - EQ 5 */
+       { 47, 0x1EB5 },     /* R47 - EQ 6 */
+       { 48, 0xF145 },     /* R48 - EQ 7 */
+       { 49, 0x0B75 },     /* R49 - EQ 8 */
+       { 50, 0x01C5 },     /* R50 - EQ 9 */
+       { 51, 0x169E },     /* R51 - EQ 10 */
+       { 52, 0xF829 },     /* R52 - EQ 11 */
+       { 53, 0x07AD },     /* R53 - EQ 12 */
+       { 54, 0x1103 },     /* R54 - EQ 13 */
+       { 55, 0x1C58 },     /* R55 - EQ 14 */
+       { 56, 0xF373 },     /* R56 - EQ 15 */
+       { 57, 0x0A54 },     /* R57 - EQ 16 */
+       { 58, 0x0558 },     /* R58 - EQ 17 */
+       { 59, 0x0564 },     /* R59 - EQ 18 */
+       { 60, 0x0559 },     /* R60 - EQ 19 */
+       { 61, 0x4000 },     /* R61 - EQ 20 */
 };
 
 static struct {
@@ -156,7 +148,7 @@ static struct {
 };
 
 struct wm9081_priv {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
        int sysclk_source;
        int mclk_rate;
        int sysclk_rate;
@@ -169,20 +161,84 @@ struct wm9081_priv {
        struct wm9081_pdata pdata;
 };
 
-static int wm9081_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm9081_volatile_register(struct device *dev, unsigned int reg)
 {
        switch (reg) {
        case WM9081_SOFTWARE_RESET:
        case WM9081_INTERRUPT_STATUS:
-               return 1;
+               return true;
        default:
-               return 0;
+               return false;
+       }
+}
+
+static bool wm9081_readable_register(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM9081_SOFTWARE_RESET:
+       case WM9081_ANALOGUE_LINEOUT:
+       case WM9081_ANALOGUE_SPEAKER_PGA:
+       case WM9081_VMID_CONTROL:
+       case WM9081_BIAS_CONTROL_1:
+       case WM9081_ANALOGUE_MIXER:
+       case WM9081_ANTI_POP_CONTROL:
+       case WM9081_ANALOGUE_SPEAKER_1:
+       case WM9081_ANALOGUE_SPEAKER_2:
+       case WM9081_POWER_MANAGEMENT:
+       case WM9081_CLOCK_CONTROL_1:
+       case WM9081_CLOCK_CONTROL_2:
+       case WM9081_CLOCK_CONTROL_3:
+       case WM9081_FLL_CONTROL_1:
+       case WM9081_FLL_CONTROL_2:
+       case WM9081_FLL_CONTROL_3:
+       case WM9081_FLL_CONTROL_4:
+       case WM9081_FLL_CONTROL_5:
+       case WM9081_AUDIO_INTERFACE_1:
+       case WM9081_AUDIO_INTERFACE_2:
+       case WM9081_AUDIO_INTERFACE_3:
+       case WM9081_AUDIO_INTERFACE_4:
+       case WM9081_INTERRUPT_STATUS:
+       case WM9081_INTERRUPT_STATUS_MASK:
+       case WM9081_INTERRUPT_POLARITY:
+       case WM9081_INTERRUPT_CONTROL:
+       case WM9081_DAC_DIGITAL_1:
+       case WM9081_DAC_DIGITAL_2:
+       case WM9081_DRC_1:
+       case WM9081_DRC_2:
+       case WM9081_DRC_3:
+       case WM9081_DRC_4:
+       case WM9081_WRITE_SEQUENCER_1:
+       case WM9081_WRITE_SEQUENCER_2:
+       case WM9081_MW_SLAVE_1:
+       case WM9081_EQ_1:
+       case WM9081_EQ_2:
+       case WM9081_EQ_3:
+       case WM9081_EQ_4:
+       case WM9081_EQ_5:
+       case WM9081_EQ_6:
+       case WM9081_EQ_7:
+       case WM9081_EQ_8:
+       case WM9081_EQ_9:
+       case WM9081_EQ_10:
+       case WM9081_EQ_11:
+       case WM9081_EQ_12:
+       case WM9081_EQ_13:
+       case WM9081_EQ_14:
+       case WM9081_EQ_15:
+       case WM9081_EQ_16:
+       case WM9081_EQ_17:
+       case WM9081_EQ_18:
+       case WM9081_EQ_19:
+       case WM9081_EQ_20:
+               return true;
+       default:
+               return false;
        }
 }
 
-static int wm9081_reset(struct snd_soc_codec *codec)
+static int wm9081_reset(struct regmap *map)
 {
-       return snd_soc_write(codec, WM9081_SOFTWARE_RESET, 0);
+       return regmap_write(map, WM9081_SOFTWARE_RESET, 0x9081);
 }
 
 static const DECLARE_TLV_DB_SCALE(drc_in_tlv, -4500, 75, 0);
@@ -737,6 +793,7 @@ SND_SOC_DAPM_SUPPLY("CLK_SYS", WM9081_CLOCK_CONTROL_3, 0, 0, clk_sys_event,
                    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 SND_SOC_DAPM_SUPPLY("CLK_DSP", WM9081_CLOCK_CONTROL_3, 1, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("TOCLK", WM9081_CLOCK_CONTROL_3, 2, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("TSENSE", WM9081_POWER_MANAGEMENT, 7, 0, NULL, 0),
 };
 
 
@@ -759,6 +816,7 @@ static const struct snd_soc_dapm_route wm9081_audio_paths[] = {
        { "Speaker PGA", NULL, "CLK_SYS" },
 
        { "Speaker", NULL, "Speaker PGA" },
+       { "Speaker", NULL, "TSENSE" },
 
        { "SPKN", NULL, "Speaker" },
        { "SPKP", NULL, "Speaker" },
@@ -767,84 +825,74 @@ static const struct snd_soc_dapm_route wm9081_audio_paths[] = {
 static int wm9081_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
-       u16 reg;
-
        switch (level) {
        case SND_SOC_BIAS_ON:
                break;
 
        case SND_SOC_BIAS_PREPARE:
                /* VMID=2*40k */
-               reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
-               reg &= ~WM9081_VMID_SEL_MASK;
-               reg |= 0x2;
-               snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
+               snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
+                                   WM9081_VMID_SEL_MASK, 0x2);
 
                /* Normal bias current */
-               reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
-               reg &= ~WM9081_STBY_BIAS_ENA;
-               snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
+               snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
+                                   WM9081_STBY_BIAS_ENA, 0);
                break;
 
        case SND_SOC_BIAS_STANDBY:
                /* Initial cold start */
                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
                        /* Disable LINEOUT discharge */
-                       reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL);
-                       reg &= ~WM9081_LINEOUT_DISCH;
-                       snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg);
+                       snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL,
+                                           WM9081_LINEOUT_DISCH, 0);
 
                        /* Select startup bias source */
-                       reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
-                       reg |= WM9081_BIAS_SRC | WM9081_BIAS_ENA;
-                       snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
+                       snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
+                                           WM9081_BIAS_SRC | WM9081_BIAS_ENA,
+                                           WM9081_BIAS_SRC | WM9081_BIAS_ENA);
 
                        /* VMID 2*4k; Soft VMID ramp enable */
-                       reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
-                       reg |= WM9081_VMID_RAMP | 0x6;
-                       snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
+                       snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
+                                           WM9081_VMID_RAMP |
+                                           WM9081_VMID_SEL_MASK,
+                                           WM9081_VMID_RAMP | 0x6);
 
                        mdelay(100);
 
                        /* Normal bias enable & soft start off */
-                       reg |= WM9081_BIAS_ENA;
-                       reg &= ~WM9081_VMID_RAMP;
-                       snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
+                       snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
+                                           WM9081_VMID_RAMP, 0);
 
                        /* Standard bias source */
-                       reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
-                       reg &= ~WM9081_BIAS_SRC;
-                       snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
+                       snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
+                                           WM9081_BIAS_SRC, 0);
                }
 
                /* VMID 2*240k */
-               reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
-               reg &= ~WM9081_VMID_SEL_MASK;
-               reg |= 0x04;
-               snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
+               snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
+                                   WM9081_VMID_SEL_MASK, 0x04);
 
                /* Standby bias current on */
-               reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
-               reg |= WM9081_STBY_BIAS_ENA;
-               snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
+               snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
+                                   WM9081_STBY_BIAS_ENA,
+                                   WM9081_STBY_BIAS_ENA);
                break;
 
        case SND_SOC_BIAS_OFF:
-               /* Startup bias source */
-               reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
-               reg |= WM9081_BIAS_SRC;
-               snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
+               /* Startup bias source and disable bias */
+               snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
+                                   WM9081_BIAS_SRC | WM9081_BIAS_ENA,
+                                   WM9081_BIAS_SRC);
 
-               /* Disable VMID and biases with soft ramping */
-               reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
-               reg &= ~(WM9081_VMID_SEL_MASK | WM9081_BIAS_ENA);
-               reg |= WM9081_VMID_RAMP;
-               snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
+               /* Disable VMID with soft ramping */
+               snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
+                                   WM9081_VMID_RAMP | WM9081_VMID_SEL_MASK,
+                                   WM9081_VMID_RAMP);
 
                /* Actively discharge LINEOUT */
-               reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL);
-               reg |= WM9081_LINEOUT_DISCH;
-               snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg);
+               snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL,
+                                   WM9081_LINEOUT_DISCH,
+                                   WM9081_LINEOUT_DISCH);
                break;
        }
 
@@ -1185,7 +1233,7 @@ static int wm9081_set_tdm_slot(struct snd_soc_dai *dai,
        (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
         SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops wm9081_dai_ops = {
+static const struct snd_soc_dai_ops wm9081_dai_ops = {
        .hw_params = wm9081_hw_params,
        .set_fmt = wm9081_set_dai_fmt,
        .digital_mute = wm9081_digital_mute,
@@ -1213,25 +1261,14 @@ static int wm9081_probe(struct snd_soc_codec *codec)
        int ret;
        u16 reg;
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm9081->control_type);
+       codec->control_data = wm9081->regmap;
+
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
        }
 
-       reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET);
-       if (reg != 0x9081) {
-               dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg);
-               ret = -EINVAL;
-               return ret;
-       }
-
-       ret = wm9081_reset(codec);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to issue reset\n");
-               return ret;
-       }
-
        reg = 0;
        if (wm9081->pdata.irq_high)
                reg |= WM9081_IRQ_POL;
@@ -1243,11 +1280,10 @@ static int wm9081_probe(struct snd_soc_codec *codec)
        wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* Enable zero cross by default */
-       reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT);
-       snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC);
-       reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA);
-       snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA,
-                    reg | WM9081_SPKPGAZC);
+       snd_soc_update_bits(codec, WM9081_ANALOGUE_LINEOUT,
+                           WM9081_LINEOUTZC, WM9081_LINEOUTZC);
+       snd_soc_update_bits(codec, WM9081_ANALOGUE_SPEAKER_PGA,
+                           WM9081_SPKPGAZC, WM9081_SPKPGAZC);
 
        if (!wm9081->pdata.num_retune_configs) {
                dev_dbg(codec->dev,
@@ -1266,7 +1302,7 @@ static int wm9081_remove(struct snd_soc_codec *codec)
 }
 
 #ifdef CONFIG_PM
-static int wm9081_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm9081_suspend(struct snd_soc_codec *codec)
 {
        wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -1275,15 +1311,9 @@ static int wm9081_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm9081_resume(struct snd_soc_codec *codec)
 {
-       u16 *reg_cache = codec->reg_cache;
-       int i;
-
-       for (i = 0; i < codec->driver->reg_cache_size; i++) {
-               if (i == WM9081_SOFTWARE_RESET)
-                       continue;
+       struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
 
-               snd_soc_write(codec, i, reg_cache[i]);
-       }
+       regcache_sync(wm9081->regmap);
 
        wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
@@ -1303,11 +1333,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9081 = {
        .set_sysclk = wm9081_set_sysclk,
        .set_bias_level = wm9081_set_bias_level,
 
-       .reg_cache_size = ARRAY_SIZE(wm9081_reg_defaults),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm9081_reg_defaults,
-       .volatile_register = wm9081_volatile_register,
-
        .controls         = wm9081_snd_controls,
        .num_controls     = ARRAY_SIZE(wm9081_snd_controls),
        .dapm_widgets     = wm9081_dapm_widgets,
@@ -1316,19 +1341,56 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9081 = {
        .num_dapm_routes = ARRAY_SIZE(wm9081_audio_paths),
 };
 
+static const struct regmap_config wm9081_regmap = {
+       .reg_bits = 8,
+       .val_bits = 16,
+
+       .max_register = WM9081_MAX_REGISTER,
+       .reg_defaults = wm9081_reg,
+       .num_reg_defaults = ARRAY_SIZE(wm9081_reg),
+       .volatile_reg = wm9081_volatile_register,
+       .readable_reg = wm9081_readable_register,
+       .cache_type = REGCACHE_RBTREE,
+};
+
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm9081_priv *wm9081;
+       unsigned int reg;
        int ret;
 
-       wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL);
+       wm9081 = devm_kzalloc(&i2c->dev, sizeof(struct wm9081_priv),
+                             GFP_KERNEL);
        if (wm9081 == NULL)
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm9081);
-       wm9081->control_type = SND_SOC_I2C;
+
+       wm9081->regmap = regmap_init_i2c(i2c, &wm9081_regmap);
+       if (IS_ERR(wm9081->regmap)) {
+               ret = PTR_ERR(wm9081->regmap);
+               dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
+               goto err;
+       }
+
+       ret = regmap_read(wm9081->regmap, WM9081_SOFTWARE_RESET, &reg);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
+               goto err_regmap;
+       }
+       if (reg != 0x9081) {
+               dev_err(&i2c->dev, "Device is not a WM9081: ID=0x%x\n", reg);
+               ret = -EINVAL;
+               goto err_regmap;
+       }
+
+       ret = wm9081_reset(wm9081->regmap);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to issue reset\n");
+               goto err_regmap;
+       }
 
        if (dev_get_platdata(&i2c->dev))
                memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev),
@@ -1337,14 +1399,23 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm9081, &wm9081_dai, 1);
        if (ret < 0)
-               kfree(wm9081);
+               goto err_regmap;
+
+       return 0;
+
+err_regmap:
+       regmap_exit(wm9081->regmap);
+err:
+
        return ret;
 }
 
 static __devexit int wm9081_i2c_remove(struct i2c_client *client)
 {
+       struct wm9081_priv *wm9081 = i2c_get_clientdata(client);
+
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));
+       regmap_exit(wm9081->regmap);
        return 0;
 }
 
index 2b5252c..d1d2c70 100644 (file)
@@ -177,19 +177,19 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec)
 }
 
 static const unsigned int in_tlv[] = {
-       TLV_DB_RANGE_HEAD(6),
+       TLV_DB_RANGE_HEAD(3),
        0, 0, TLV_DB_SCALE_ITEM(-600, 0, 0),
        1, 3, TLV_DB_SCALE_ITEM(-350, 350, 0),
        4, 6, TLV_DB_SCALE_ITEM(600, 600, 0),
 };
 static const unsigned int mix_tlv[] = {
-       TLV_DB_RANGE_HEAD(4),
+       TLV_DB_RANGE_HEAD(2),
        0, 2, TLV_DB_SCALE_ITEM(-1200, 300, 0),
        3, 3, TLV_DB_SCALE_ITEM(0, 0, 0),
 };
 static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
 static const unsigned int spkboost_tlv[] = {
-       TLV_DB_RANGE_HEAD(7),
+       TLV_DB_RANGE_HEAD(2),
        0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
        7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
 };
@@ -604,7 +604,7 @@ static int wm9090_probe(struct snd_soc_codec *codec)
 }
 
 #ifdef CONFIG_PM
-static int wm9090_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm9090_suspend(struct snd_soc_codec *codec)
 {
        wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
@@ -647,7 +647,7 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
        struct wm9090_priv *wm9090;
        int ret;
 
-       wm9090 = kzalloc(sizeof(*wm9090), GFP_KERNEL);
+       wm9090 = devm_kzalloc(&i2c->dev, sizeof(*wm9090), GFP_KERNEL);
        if (wm9090 == NULL) {
                dev_err(&i2c->dev, "Can not allocate memory\n");
                return -ENOMEM;
@@ -661,8 +661,6 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
 
        ret =  snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm9090,  NULL, 0);
-       if (ret < 0)
-               kfree(wm9090);
        return ret;
 }
 
@@ -671,7 +669,6 @@ static int __devexit wm9090_i2c_remove(struct i2c_client *i2c)
        struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c);
 
        snd_soc_unregister_codec(&i2c->dev);
-       kfree(wm9090);
 
        return 0;
 }
@@ -685,7 +682,7 @@ MODULE_DEVICE_TABLE(i2c, wm9090_id);
 
 static struct i2c_driver wm9090_i2c_driver = {
        .driver = {
-               .name = "wm9090-codec",
+               .name = "wm9090",
                .owner = THIS_MODULE,
        },
        .probe = wm9090_i2c_probe,
index 646b58d..40c92ea 100644 (file)
@@ -258,7 +258,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
                        SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
                        SNDRV_PCM_RATE_48000)
 
-static struct snd_soc_dai_ops wm9705_dai_ops = {
+static const struct snd_soc_dai_ops wm9705_dai_ops = {
        .prepare        = ac97_prepare,
 };
 
@@ -306,7 +306,7 @@ static int wm9705_reset(struct snd_soc_codec *codec)
 }
 
 #ifdef CONFIG_PM
-static int wm9705_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
+static int wm9705_soc_suspend(struct snd_soc_codec *codec)
 {
        soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff);
 
@@ -406,17 +406,7 @@ static struct platform_driver wm9705_codec_driver = {
        .remove = __devexit_p(wm9705_remove),
 };
 
-static int __init wm9705_init(void)
-{
-       return platform_driver_register(&wm9705_codec_driver);
-}
-module_init(wm9705_init);
-
-static void __exit wm9705_exit(void)
-{
-       platform_driver_unregister(&wm9705_codec_driver);
-}
-module_exit(wm9705_exit);
+module_platform_driver(wm9705_codec_driver);
 
 MODULE_DESCRIPTION("ASoC WM9705 driver");
 MODULE_AUTHOR("Ian Molton");
index 90117f8..b7b31f8 100644 (file)
@@ -505,11 +505,11 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream,
                SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
                SNDRV_PCM_RATE_48000)
 
-static struct snd_soc_dai_ops wm9712_dai_ops_hifi = {
+static const struct snd_soc_dai_ops wm9712_dai_ops_hifi = {
        .prepare        = ac97_prepare,
 };
 
-static struct snd_soc_dai_ops wm9712_dai_ops_aux = {
+static const struct snd_soc_dai_ops wm9712_dai_ops_aux = {
        .prepare        = ac97_aux_prepare,
 };
 
@@ -583,8 +583,7 @@ err:
        return -EIO;
 }
 
-static int wm9712_soc_suspend(struct snd_soc_codec *codec,
-       pm_message_t state)
+static int wm9712_soc_suspend(struct snd_soc_codec *codec)
 {
        wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
@@ -694,17 +693,7 @@ static struct platform_driver wm9712_codec_driver = {
        .remove = __devexit_p(wm9712_remove),
 };
 
-static int __init wm9712_init(void)
-{
-       return platform_driver_register(&wm9712_codec_driver);
-}
-module_init(wm9712_init);
-
-static void __exit wm9712_exit(void)
-{
-       platform_driver_unregister(&wm9712_codec_driver);
-}
-module_exit(wm9712_exit);
+module_platform_driver(wm9712_codec_driver);
 
 MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver");
 MODULE_AUTHOR("Liam Girdwood");
index 7167cb6..2b8479b 100644 (file)
@@ -1026,19 +1026,19 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream,
        (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
         SNDRV_PCM_FORMAT_S24_LE)
 
-static struct snd_soc_dai_ops wm9713_dai_ops_hifi = {
+static const struct snd_soc_dai_ops wm9713_dai_ops_hifi = {
        .prepare        = ac97_hifi_prepare,
        .set_clkdiv     = wm9713_set_dai_clkdiv,
        .set_pll        = wm9713_set_dai_pll,
 };
 
-static struct snd_soc_dai_ops wm9713_dai_ops_aux = {
+static const struct snd_soc_dai_ops wm9713_dai_ops_aux = {
        .prepare        = ac97_aux_prepare,
        .set_clkdiv     = wm9713_set_dai_clkdiv,
        .set_pll        = wm9713_set_dai_pll,
 };
 
-static struct snd_soc_dai_ops wm9713_dai_ops_voice = {
+static const struct snd_soc_dai_ops wm9713_dai_ops_voice = {
        .hw_params      = wm9713_pcm_hw_params,
        .set_clkdiv     = wm9713_set_dai_clkdiv,
        .set_pll        = wm9713_set_dai_pll,
@@ -1140,8 +1140,7 @@ static int wm9713_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-static int wm9713_soc_suspend(struct snd_soc_codec *codec,
-       pm_message_t state)
+static int wm9713_soc_suspend(struct snd_soc_codec *codec)
 {
        u16 reg;
 
@@ -1277,17 +1276,7 @@ static struct platform_driver wm9713_codec_driver = {
        .remove = __devexit_p(wm9713_remove),
 };
 
-static int __init wm9713_init(void)
-{
-       return platform_driver_register(&wm9713_codec_driver);
-}
-module_init(wm9713_init);
-
-static void __exit wm9713_exit(void)
-{
-       platform_driver_unregister(&wm9713_codec_driver);
-}
-module_exit(wm9713_exit);
+module_platform_driver(wm9713_codec_driver);
 
 MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver");
 MODULE_AUTHOR("Liam Girdwood");
index 84f33d4..2a61094 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
-#include <linux/platform_device.h>
 #include <linux/mfd/wm8994/registers.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -40,7 +39,7 @@ static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0);
 static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1);
 static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0);
 static const unsigned int spkboost_tlv[] = {
-       TLV_DB_RANGE_HEAD(7),
+       TLV_DB_RANGE_HEAD(2),
        0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
        7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
 };
@@ -611,8 +610,8 @@ SND_SOC_DAPM_INPUT("IN1RP"),
 SND_SOC_DAPM_INPUT("IN2RN"),
 SND_SOC_DAPM_INPUT("IN2RP:VXRP"),
 
-SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0),
-SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0),
 
 SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
                   in1l_pga, ARRAY_SIZE(in1l_pga)),
@@ -654,6 +653,7 @@ SND_SOC_DAPM_MIXER("SPKL Boost", SND_SOC_NOPM, 0, 0,
 SND_SOC_DAPM_MIXER("SPKR Boost", SND_SOC_NOPM, 0, 0,
                   right_speaker_boost, ARRAY_SIZE(right_speaker_boost)),
 
+SND_SOC_DAPM_SUPPLY("TSHUT", WM8993_POWER_MANAGEMENT_2, 14, 0, NULL, 0),
 SND_SOC_DAPM_PGA("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
                 NULL, 0),
 SND_SOC_DAPM_PGA("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
@@ -789,10 +789,12 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
        { "SPKL Driver", NULL, "VMID" },
        { "SPKL Driver", NULL, "SPKL Boost" },
        { "SPKL Driver", NULL, "CLK_SYS" },
+       { "SPKL Driver", NULL, "TSHUT" },
 
        { "SPKR Driver", NULL, "VMID" },
        { "SPKR Driver", NULL, "SPKR Boost" },
        { "SPKR Driver", NULL, "CLK_SYS" },
+       { "SPKR Driver", NULL, "TSHUT" },
 
        { "SPKOUTLP", NULL, "SPKL Driver" },
        { "SPKOUTLN", NULL, "SPKL Driver" },
index 300e121..ec18710 100644 (file)
@@ -620,7 +620,7 @@ static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
 
 #define DAVINCI_I2S_RATES      SNDRV_PCM_RATE_8000_96000
 
-static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
+static const struct snd_soc_dai_ops davinci_i2s_dai_ops = {
        .startup        = davinci_i2s_startup,
        .shutdown       = davinci_i2s_shutdown,
        .prepare        = davinci_i2s_prepare,
@@ -774,17 +774,7 @@ static struct platform_driver davinci_mcbsp_driver = {
        },
 };
 
-static int __init davinci_i2s_init(void)
-{
-       return platform_driver_register(&davinci_mcbsp_driver);
-}
-module_init(davinci_i2s_init);
-
-static void __exit davinci_i2s_exit(void)
-{
-       platform_driver_unregister(&davinci_mcbsp_driver);
-}
-module_exit(davinci_i2s_exit);
+module_platform_driver(davinci_mcbsp_driver);
 
 MODULE_AUTHOR("Vladimir Barinov");
 MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface");
index 7173df2..2152ff5 100644 (file)
@@ -813,7 +813,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
+static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
        .startup        = davinci_mcasp_startup,
        .trigger        = davinci_mcasp_trigger,
        .hw_params      = davinci_mcasp_hw_params,
@@ -991,17 +991,7 @@ static struct platform_driver davinci_mcasp_driver = {
        },
 };
 
-static int __init davinci_mcasp_init(void)
-{
-       return platform_driver_register(&davinci_mcasp_driver);
-}
-module_init(davinci_mcasp_init);
-
-static void __exit davinci_mcasp_exit(void)
-{
-       platform_driver_unregister(&davinci_mcasp_driver);
-}
-module_exit(davinci_mcasp_exit);
+module_platform_driver(davinci_mcasp_driver);
 
 MODULE_AUTHOR("Steve Chen");
 MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface");
index d5fe08c..65bff3d 100644 (file)
@@ -886,17 +886,7 @@ static struct platform_driver davinci_pcm_driver = {
        .remove = __devexit_p(davinci_soc_platform_remove),
 };
 
-static int __init snd_davinci_pcm_init(void)
-{
-       return platform_driver_register(&davinci_pcm_driver);
-}
-module_init(snd_davinci_pcm_init);
-
-static void __exit snd_davinci_pcm_exit(void)
-{
-       platform_driver_unregister(&davinci_pcm_driver);
-}
-module_exit(snd_davinci_pcm_exit);
+module_platform_driver(davinci_pcm_driver);
 
 MODULE_AUTHOR("Vladimir Barinov");
 MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
index 1f11525..70ce10c 100644 (file)
@@ -183,7 +183,7 @@ static int davinci_vcif_startup(struct snd_pcm_substream *substream,
 
 #define DAVINCI_VCIF_RATES     SNDRV_PCM_RATE_8000_48000
 
-static struct snd_soc_dai_ops davinci_vcif_dai_ops = {
+static const struct snd_soc_dai_ops davinci_vcif_dai_ops = {
        .startup        = davinci_vcif_startup,
        .trigger        = davinci_vcif_trigger,
        .hw_params      = davinci_vcif_hw_params,
@@ -265,17 +265,7 @@ static struct platform_driver davinci_vcif_driver = {
        },
 };
 
-static int __init davinci_vcif_init(void)
-{
-       return platform_driver_probe(&davinci_vcif_driver, davinci_vcif_probe);
-}
-module_init(davinci_vcif_init);
-
-static void __exit davinci_vcif_exit(void)
-{
-       platform_driver_unregister(&davinci_vcif_driver);
-}
-module_exit(davinci_vcif_exit);
+module_platform_driver(davinci_vcif_driver);
 
 MODULE_AUTHOR("Miguel Aguilar");
 MODULE_DESCRIPTION("Texas Instruments DaVinci ASoC Voice Codec Interface");
index 51930b6..6b90c75 100644 (file)
@@ -131,17 +131,7 @@ static struct platform_driver edb93xx_driver = {
        .remove         = __devexit_p(edb93xx_remove),
 };
 
-static int __init edb93xx_init(void)
-{
-       return platform_driver_register(&edb93xx_driver);
-}
-module_init(edb93xx_init);
-
-static void __exit edb93xx_exit(void)
-{
-       platform_driver_unregister(&edb93xx_driver);
-}
-module_exit(edb93xx_exit);
+module_platform_driver(edb93xx_driver);
 
 MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>");
 MODULE_DESCRIPTION("ALSA SoC EDB93xx");
index 3cd6158..0678637 100644 (file)
@@ -330,7 +330,7 @@ static int ep93xx_ac97_startup(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_dai_ops ep93xx_ac97_dai_ops = {
+static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = {
        .startup        = ep93xx_ac97_startup,
        .trigger        = ep93xx_ac97_trigger,
 };
@@ -449,17 +449,7 @@ static struct platform_driver ep93xx_ac97_driver = {
        },
 };
 
-static int __init ep93xx_ac97_init(void)
-{
-       return platform_driver_register(&ep93xx_ac97_driver);
-}
-module_init(ep93xx_ac97_init);
-
-static void __exit ep93xx_ac97_exit(void)
-{
-       platform_driver_unregister(&ep93xx_ac97_driver);
-}
-module_exit(ep93xx_ac97_exit);
+module_platform_driver(ep93xx_ac97_driver);
 
 MODULE_DESCRIPTION("EP93xx AC97 ASoC Driver");
 MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
index 099614e..f7a6234 100644 (file)
@@ -338,7 +338,7 @@ static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
 #define ep93xx_i2s_resume      NULL
 #endif
 
-static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
+static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
        .startup        = ep93xx_i2s_startup,
        .shutdown       = ep93xx_i2s_shutdown,
        .hw_params      = ep93xx_i2s_hw_params,
@@ -464,18 +464,7 @@ static struct platform_driver ep93xx_i2s_driver = {
        },
 };
 
-static int __init ep93xx_i2s_init(void)
-{
-       return platform_driver_register(&ep93xx_i2s_driver);
-}
-
-static void __exit ep93xx_i2s_exit(void)
-{
-       platform_driver_unregister(&ep93xx_i2s_driver);
-}
-
-module_init(ep93xx_i2s_init);
-module_exit(ep93xx_i2s_exit);
+module_platform_driver(ep93xx_i2s_driver);
 
 MODULE_ALIAS("platform:ep93xx-i2s");
 MODULE_AUTHOR("Ryan Mallon");
index d00230a..a2de9c4 100644 (file)
@@ -339,18 +339,7 @@ static struct platform_driver ep93xx_pcm_driver = {
        .remove = __devexit_p(ep93xx_soc_platform_remove),
 };
 
-static int __init ep93xx_soc_platform_init(void)
-{
-       return platform_driver_register(&ep93xx_pcm_driver);
-}
-
-static void __exit ep93xx_soc_platform_exit(void)
-{
-       platform_driver_unregister(&ep93xx_pcm_driver);
-}
-
-module_init(ep93xx_soc_platform_init);
-module_exit(ep93xx_soc_platform_exit);
+module_platform_driver(ep93xx_pcm_driver);
 
 MODULE_AUTHOR("Ryan Mallon");
 MODULE_DESCRIPTION("EP93xx ALSA PCM interface");
index 968cb31..1e00b33 100644 (file)
@@ -81,17 +81,7 @@ static struct platform_driver simone_driver = {
        .remove         = __devexit_p(simone_remove),
 };
 
-static int __init simone_init(void)
-{
-       return platform_driver_register(&simone_driver);
-}
-module_init(simone_init);
-
-static void __exit simone_exit(void)
-{
-       platform_driver_unregister(&simone_driver);
-}
-module_exit(simone_exit);
+module_platform_driver(simone_driver);
 
 MODULE_DESCRIPTION("ALSA SoC Simplemachines Sim.One");
 MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
index 2cde433..33901d6 100644 (file)
@@ -147,18 +147,7 @@ static struct platform_driver snappercl15_driver = {
        .remove         = __devexit_p(snappercl15_remove),
 };
 
-static int __init snappercl15_init(void)
-{
-       return platform_driver_register(&snappercl15_driver);
-}
-
-static void __exit snappercl15_exit(void)
-{
-       platform_driver_unregister(&snappercl15_driver);
-}
-
-module_init(snappercl15_init);
-module_exit(snappercl15_exit);
+module_platform_driver(snappercl15_driver);
 
 MODULE_AUTHOR("Ryan Mallon");
 MODULE_DESCRIPTION("ALSA SoC Snapper CL15");
index ef15402..4f59bba 100644 (file)
@@ -992,20 +992,7 @@ static struct platform_driver fsl_soc_dma_driver = {
        .remove = __devexit_p(fsl_soc_dma_remove),
 };
 
-static int __init fsl_soc_dma_init(void)
-{
-       pr_info("Freescale Elo DMA ASoC PCM Driver\n");
-
-       return platform_driver_register(&fsl_soc_dma_driver);
-}
-
-static void __exit fsl_soc_dma_exit(void)
-{
-       platform_driver_unregister(&fsl_soc_dma_driver);
-}
-
-module_init(fsl_soc_dma_init);
-module_exit(fsl_soc_dma_exit);
+module_platform_driver(fsl_soc_dma_driver);
 
 MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
 MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM Driver");
index 0268cf9..3e06696 100644 (file)
@@ -514,7 +514,7 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
        }
 }
 
-static struct snd_soc_dai_ops fsl_ssi_dai_ops = {
+static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
        .startup        = fsl_ssi_startup,
        .hw_params      = fsl_ssi_hw_params,
        .shutdown       = fsl_ssi_shutdown,
@@ -694,6 +694,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
 
        /* Initialize the the device_attribute structure */
        dev_attr = &ssi_private->dev_attr;
+       sysfs_attr_init(&dev_attr->attr);
        dev_attr->attr.name = "statistics";
        dev_attr->attr.mode = S_IRUGO;
        dev_attr->show = fsl_sysfs_ssi_show;
@@ -792,20 +793,7 @@ static struct platform_driver fsl_ssi_driver = {
        .remove = fsl_ssi_remove,
 };
 
-static int __init fsl_ssi_init(void)
-{
-       printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n");
-
-       return platform_driver_register(&fsl_ssi_driver);
-}
-
-static void __exit fsl_ssi_exit(void)
-{
-       platform_driver_unregister(&fsl_ssi_driver);
-}
-
-module_init(fsl_ssi_init);
-module_exit(fsl_ssi_exit);
+module_platform_driver(fsl_ssi_driver);
 
 MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
 MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver");
index 5c6c245..e7803d3 100644 (file)
@@ -526,17 +526,7 @@ static struct platform_driver mpc5200_hpcd_of_driver = {
        }
 };
 
-static int __init mpc5200_hpcd_init(void)
-{
-       return platform_driver_register(&mpc5200_hpcd_of_driver);
-}
-module_init(mpc5200_hpcd_init);
-
-static void __exit mpc5200_hpcd_exit(void)
-{
-       platform_driver_unregister(&mpc5200_hpcd_of_driver);
-}
-module_exit(mpc5200_hpcd_exit);
+module_platform_driver(mpc5200_hpcd_of_driver);
 
 MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
 MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver");
index ad36b09..ffa00a2 100644 (file)
@@ -226,12 +226,12 @@ static int psc_ac97_probe(struct snd_soc_dai *cpu_dai)
 /**
  * psc_ac97_dai_template: template CPU Digital Audio Interface
  */
-static struct snd_soc_dai_ops psc_ac97_analog_ops = {
+static const struct snd_soc_dai_ops psc_ac97_analog_ops = {
        .hw_params      = psc_ac97_hw_analog_params,
        .trigger        = psc_ac97_trigger,
 };
 
-static struct snd_soc_dai_ops psc_ac97_digital_ops = {
+static const struct snd_soc_dai_ops psc_ac97_digital_ops = {
        .hw_params      = psc_ac97_hw_digital_params,
 };
 
@@ -325,21 +325,7 @@ static struct platform_driver psc_ac97_driver = {
        },
 };
 
-/* ---------------------------------------------------------------------
- * Module setup and teardown; simply register the of_platform driver
- * for the PSC in AC97 mode.
- */
-static int __init psc_ac97_init(void)
-{
-       return platform_driver_register(&psc_ac97_driver);
-}
-module_init(psc_ac97_init);
-
-static void __exit psc_ac97_exit(void)
-{
-       platform_driver_unregister(&psc_ac97_driver);
-}
-module_exit(psc_ac97_exit);
+module_platform_driver(psc_ac97_driver);
 
 MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
 MODULE_DESCRIPTION("mpc5200 AC97 module");
index 87cf2a5..7b53032 100644 (file)
@@ -123,7 +123,7 @@ static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
 /**
  * psc_i2s_dai_template: template CPU Digital Audio Interface
  */
-static struct snd_soc_dai_ops psc_i2s_dai_ops = {
+static const struct snd_soc_dai_ops psc_i2s_dai_ops = {
        .hw_params      = psc_i2s_hw_params,
        .set_sysclk     = psc_i2s_set_sysclk,
        .set_fmt        = psc_i2s_set_fmt,
@@ -222,21 +222,7 @@ static struct platform_driver psc_i2s_driver = {
        },
 };
 
-/* ---------------------------------------------------------------------
- * Module setup and teardown; simply register the of_platform driver
- * for the PSC in I2S mode.
- */
-static int __init psc_i2s_init(void)
-{
-       return platform_driver_register(&psc_i2s_driver);
-}
-module_init(psc_i2s_init);
-
-static void __exit psc_i2s_exit(void)
-{
-       platform_driver_unregister(&psc_i2s_driver);
-}
-module_exit(psc_i2s_exit);
+module_platform_driver(psc_i2s_driver);
 
 MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
 MODULE_DESCRIPTION("Freescale MPC5200 PSC in I2S mode ASoC Driver");
index 31af405..0ea4a5a 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/interrupt.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
+#include <linux/of_i2c.h>
 #include <sound/soc.h>
 #include <asm/fsl_guts.h>
 
@@ -249,8 +250,9 @@ static int get_parent_cell_index(struct device_node *np)
 static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
 {
        const u32 *iprop;
-       int bus, addr;
+       int addr;
        char temp[DAI_NAME_SIZE];
+       struct i2c_client *i2c;
 
        of_modalias_node(np, temp, DAI_NAME_SIZE);
 
@@ -260,11 +262,12 @@ static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
 
        addr = be32_to_cpup(iprop);
 
-       bus = get_parent_cell_index(np);
-       if (bus < 0)
-               return bus;
+       /* We need the adapter number */
+       i2c = of_find_i2c_device_by_node(np);
+       if (!i2c)
+               return -ENODEV;
 
-       snprintf(buf, len, "%s-codec.%u-%04x", temp, bus, addr);
+       snprintf(buf, len, "%s-codec.%u-%04x", temp, i2c->adapter->nr, addr);
 
        return 0;
 }
@@ -392,7 +395,8 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
        }
 
        if (strcasecmp(sprop, "i2s-slave") == 0) {
-               machine_data->dai_format = SND_SOC_DAIFMT_I2S;
+               machine_data->dai_format =
+                       SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM;
                machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;
                machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;
 
@@ -409,31 +413,38 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
                }
                machine_data->clk_frequency = be32_to_cpup(iprop);
        } else if (strcasecmp(sprop, "i2s-master") == 0) {
-               machine_data->dai_format = SND_SOC_DAIFMT_I2S;
+               machine_data->dai_format =
+                       SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS;
                machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;
                machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;
        } else if (strcasecmp(sprop, "lj-slave") == 0) {
-               machine_data->dai_format = SND_SOC_DAIFMT_LEFT_J;
+               machine_data->dai_format =
+                       SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM;
                machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;
                machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;
        } else if (strcasecmp(sprop, "lj-master") == 0) {
-               machine_data->dai_format = SND_SOC_DAIFMT_LEFT_J;
+               machine_data->dai_format =
+                       SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS;
                machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;
                machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;
        } else if (strcasecmp(sprop, "rj-slave") == 0) {
-               machine_data->dai_format = SND_SOC_DAIFMT_RIGHT_J;
+               machine_data->dai_format =
+                       SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBM_CFM;
                machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;
                machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;
        } else if (strcasecmp(sprop, "rj-master") == 0) {
-               machine_data->dai_format = SND_SOC_DAIFMT_RIGHT_J;
+               machine_data->dai_format =
+                       SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBS_CFS;
                machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;
                machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;
        } else if (strcasecmp(sprop, "ac97-slave") == 0) {
-               machine_data->dai_format = SND_SOC_DAIFMT_AC97;
+               machine_data->dai_format =
+                       SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBM_CFM;
                machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;
                machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;
        } else if (strcasecmp(sprop, "ac97-master") == 0) {
-               machine_data->dai_format = SND_SOC_DAIFMT_AC97;
+               machine_data->dai_format =
+                       SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBS_CFS;
                machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;
                machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;
        } else {
index 2c064a9..a5d4e80 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/interrupt.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
+#include <linux/of_i2c.h>
 #include <sound/soc.h>
 #include <asm/fsl_guts.h>
 
@@ -252,8 +253,9 @@ static int get_parent_cell_index(struct device_node *np)
 static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
 {
        const u32 *iprop;
-       int bus, addr;
+       int addr;
        char temp[DAI_NAME_SIZE];
+       struct i2c_client *i2c;
 
        of_modalias_node(np, temp, DAI_NAME_SIZE);
 
@@ -263,11 +265,12 @@ static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
 
        addr = be32_to_cpup(iprop);
 
-       bus = get_parent_cell_index(np);
-       if (bus < 0)
-               return bus;
+       /* We need the adapter number */
+       i2c = of_find_i2c_device_by_node(np);
+       if (!i2c)
+               return -ENODEV;
 
-       snprintf(buf, len, "%s.%u-%04x", temp, bus, addr);
+       snprintf(buf, len, "%s.%u-%04x", temp, i2c->adapter->nr, addr);
 
        return 0;
 }
@@ -540,12 +543,6 @@ static struct platform_driver p1022_ds_driver = {
        .probe = p1022_ds_probe,
        .remove = __devexit_p(p1022_ds_remove),
        .driver = {
-               /* The name must match the 'model' property in the device tree,
-                * in lowercase letters, but only the part after that last
-                * comma.  This is because some model properties have a "fsl,"
-                * prefix.
-                */
-               .name = "snd-soc-p1022",
                .owner = THIS_MODULE,
        },
 };
@@ -559,13 +556,39 @@ static int __init p1022_ds_init(void)
 {
        struct device_node *guts_np;
        struct resource res;
+       const char *sprop;
+
+       /*
+        * Check if we're actually running on a P1022DS.  Older device trees
+        * have a model of "fsl,P1022" and newer ones use "fsl,P1022DS", so we
+        * need to support both.  The SSI driver uses that property to link to
+        * the machine driver, so have to match it.
+        */
+       sprop = of_get_property(of_find_node_by_path("/"), "model", NULL);
+       if (!sprop) {
+               pr_err("snd-soc-p1022ds: missing /model node");
+               return -ENODEV;
+       }
+
+       pr_debug("snd-soc-p1022ds: board model name is %s\n", sprop);
 
-       pr_info("Freescale P1022 DS ALSA SoC machine driver\n");
+       /*
+        * The name of this board, taken from the device tree.  Normally, this is a*
+        * fixed string, but some P1022DS device trees have a /model property of
+        * "fsl,P1022", and others have "fsl,P1022DS".
+        */
+       if (strcasecmp(sprop, "fsl,p1022ds") == 0)
+               p1022_ds_driver.driver.name = "snd-soc-p1022ds";
+       else if (strcasecmp(sprop, "fsl,p1022") == 0)
+               p1022_ds_driver.driver.name = "snd-soc-p1022";
+       else
+               return -ENODEV;
 
        /* Get the physical address of the global utilities registers */
        guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
        if (of_address_to_resource(guts_np, 0, &res)) {
-               pr_err("p1022-ds: missing/invalid global utilities node\n");
+               pr_err("snd-soc-p1022ds: missing/invalid global utils node\n");
+               of_node_put(guts_np);
                return -EINVAL;
        }
        guts_phys = res.start;
index b133bfc..7383917 100644 (file)
@@ -28,7 +28,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
+       depends on MACH_IMX27_VISSTRIM_M10 && I2C
        select SND_SOC_TLV320AIC32X4
        select SND_MXC_SOC_MX2
        help
index 43fdc24..1cf2fe8 100644 (file)
@@ -326,16 +326,6 @@ static struct platform_driver imx_pcm_driver = {
        .remove = __devexit_p(imx_soc_platform_remove),
 };
 
-static int __init snd_imx_pcm_init(void)
-{
-       return platform_driver_register(&imx_pcm_driver);
-}
-module_init(snd_imx_pcm_init);
-
-static void __exit snd_imx_pcm_exit(void)
-{
-       platform_driver_unregister(&imx_pcm_driver);
-}
-module_exit(snd_imx_pcm_exit);
+module_platform_driver(imx_pcm_driver);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:imx-pcm-audio");
index 8df0fae..456b7d7 100644 (file)
@@ -331,14 +331,6 @@ static struct platform_driver imx_pcm_driver = {
        .remove = __devexit_p(imx_soc_platform_remove),
 };
 
-static int __init snd_imx_pcm_init(void)
-{
-       return platform_driver_register(&imx_pcm_driver);
-}
-module_init(snd_imx_pcm_init);
+module_platform_driver(imx_pcm_driver);
 
-static void __exit snd_imx_pcm_exit(void)
-{
-       platform_driver_unregister(&imx_pcm_driver);
-}
-module_exit(snd_imx_pcm_exit);
+MODULE_LICENSE("GPL");
index 4c05e2b..01d1f74 100644 (file)
@@ -342,7 +342,7 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
        return 0;
 }
 
-static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
+static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
        .hw_params      = imx_ssi_hw_params,
        .set_fmt        = imx_ssi_set_dai_fmt,
        .set_clkdiv     = imx_ssi_set_dai_clkdiv,
@@ -757,18 +757,7 @@ static struct platform_driver imx_ssi_driver = {
        },
 };
 
-static int __init imx_ssi_init(void)
-{
-       return platform_driver_register(&imx_ssi_driver);
-}
-
-static void __exit imx_ssi_exit(void)
-{
-       platform_driver_unregister(&imx_ssi_driver);
-}
-
-module_init(imx_ssi_init);
-module_exit(imx_ssi_exit);
+module_platform_driver(imx_ssi_driver);
 
 /* Module information */
 MODULE_AUTHOR("Sascha Hauer, <s.hauer@pengutronix.de>");
index cd22a54..a5af7c4 100644 (file)
@@ -392,7 +392,7 @@ static int jz4740_i2s_dai_remove(struct snd_soc_dai *dai)
        return 0;
 }
 
-static struct snd_soc_dai_ops jz4740_i2s_dai_ops = {
+static const struct snd_soc_dai_ops jz4740_i2s_dai_ops = {
        .startup = jz4740_i2s_startup,
        .shutdown = jz4740_i2s_shutdown,
        .trigger = jz4740_i2s_trigger,
@@ -519,17 +519,7 @@ static struct platform_driver jz4740_i2s_driver = {
        },
 };
 
-static int __init jz4740_i2s_init(void)
-{
-       return platform_driver_register(&jz4740_i2s_driver);
-}
-module_init(jz4740_i2s_init);
-
-static void __exit jz4740_i2s_exit(void)
-{
-       platform_driver_unregister(&jz4740_i2s_driver);
-}
-module_exit(jz4740_i2s_exit);
+module_platform_driver(jz4740_i2s_driver);
 
 MODULE_AUTHOR("Lars-Peter Clausen, <lars@metafoo.de>");
 MODULE_DESCRIPTION("Ingenic JZ4740 SoC I2S driver");
index d1989cd..50cda9e 100644 (file)
@@ -356,17 +356,7 @@ static struct platform_driver jz4740_pcm_driver = {
        },
 };
 
-static int __init jz4740_soc_platform_init(void)
-{
-       return platform_driver_register(&jz4740_pcm_driver);
-}
-module_init(jz4740_soc_platform_init);
-
-static void __exit jz4740_soc_platform_exit(void)
-{
-       return platform_driver_unregister(&jz4740_pcm_driver);
-}
-module_exit(jz4740_soc_platform_exit);
+module_platform_driver(jz4740_pcm_driver);
 
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("Ingenic SoC JZ4740 PCM driver");
index 8f49e16..c62d715 100644 (file)
@@ -12,6 +12,7 @@ config SND_KIRKWOOD_SOC_I2S
 config SND_KIRKWOOD_SOC_OPENRD
        tristate "SoC Audio support for Kirkwood Openrd Client"
        depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE)
+       depends on I2C
        select SND_KIRKWOOD_SOC_I2S
        select SND_SOC_CS42L51
        help
@@ -20,7 +21,7 @@ config SND_KIRKWOOD_SOC_OPENRD
 
 config SND_KIRKWOOD_SOC_T5325
        tristate "SoC Audio support for HP t5325"
-       depends on SND_KIRKWOOD_SOC && MACH_T5325
+       depends on SND_KIRKWOOD_SOC && MACH_T5325 && I2C
        select SND_KIRKWOOD_SOC_I2S
        select SND_SOC_ALC5623
        help
index cd33de1..2104382 100644 (file)
@@ -388,17 +388,7 @@ static struct platform_driver kirkwood_pcm_driver = {
        .remove = __devexit_p(kirkwood_soc_platform_remove),
 };
 
-static int __init kirkwood_pcm_init(void)
-{
-       return platform_driver_register(&kirkwood_pcm_driver);
-}
-module_init(kirkwood_pcm_init);
-
-static void __exit kirkwood_pcm_exit(void)
-{
-       platform_driver_unregister(&kirkwood_pcm_driver);
-}
-module_exit(kirkwood_pcm_exit);
+module_platform_driver(kirkwood_pcm_driver);
 
 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module");
index 715e841..f6bb211 100644 (file)
@@ -373,7 +373,7 @@ static int kirkwood_i2s_remove(struct snd_soc_dai *dai)
        return 0;
 }
 
-static struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
+static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
        .startup        = kirkwood_i2s_startup,
        .trigger        = kirkwood_i2s_trigger,
        .hw_params      = kirkwood_i2s_hw_params,
@@ -483,17 +483,7 @@ static struct platform_driver kirkwood_i2s_driver = {
        },
 };
 
-static int __init kirkwood_i2s_init(void)
-{
-       return platform_driver_register(&kirkwood_i2s_driver);
-}
-module_init(kirkwood_i2s_init);
-
-static void __exit kirkwood_i2s_exit(void)
-{
-       platform_driver_unregister(&kirkwood_i2s_driver);
-}
-module_exit(kirkwood_i2s_exit);
+module_platform_driver(kirkwood_i2s_driver);
 
 /* Module information */
 MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
index 2935042..61c10bf 100644 (file)
@@ -1,7 +1,6 @@
 config SND_MFLD_MACHINE
        tristate "SOC Machine Audio driver for Intel Medfield MID platform"
        depends on INTEL_SCU_IPC
-       depends on SND_INTEL_SST
        select SND_SOC_SN95031
        select SND_SST_PLATFORM
        help
index cca693a..e53f8e4 100644 (file)
@@ -428,19 +428,7 @@ static struct platform_driver snd_mfld_mc_driver = {
        .remove = __devexit_p(snd_mfld_mc_remove),
 };
 
-static int __init snd_mfld_driver_init(void)
-{
-       pr_debug("snd_mfld_driver_init called\n");
-       return platform_driver_register(&snd_mfld_mc_driver);
-}
-module_init(snd_mfld_driver_init);
-
-static void __exit snd_mfld_driver_exit(void)
-{
-       pr_debug("snd_mfld_driver_exit called\n");
-       platform_driver_unregister(&snd_mfld_mc_driver);
-}
-module_exit(snd_mfld_driver_exit);
+module_platform_driver(snd_mfld_mc_driver);
 
 MODULE_DESCRIPTION("ASoC Intel(R) MID Machine driver");
 MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
index 2305702..24f9471 100644 (file)
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
-#include "../../../drivers/staging/intel_sst/intel_sst_ioctl.h"
-#include "../../../drivers/staging/intel_sst/intel_sst.h"
 #include "sst_platform.h"
 
+static struct sst_device *sst;
+static DEFINE_MUTEX(sst_lock);
+
+int sst_register_dsp(struct sst_device *dev)
+{
+       BUG_ON(!dev);
+       if (!try_module_get(dev->dev->driver->owner))
+               return -ENODEV;
+       mutex_lock(&sst_lock);
+       if (sst) {
+               pr_err("we already have a device %s\n", sst->name);
+               module_put(dev->dev->driver->owner);
+               mutex_unlock(&sst_lock);
+               return -EEXIST;
+       }
+       pr_debug("registering device %s\n", dev->name);
+       sst = dev;
+       mutex_unlock(&sst_lock);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(sst_register_dsp);
+
+int sst_unregister_dsp(struct sst_device *dev)
+{
+       BUG_ON(!dev);
+       if (dev != sst)
+               return -EINVAL;
+
+       mutex_lock(&sst_lock);
+
+       if (!sst) {
+               mutex_unlock(&sst_lock);
+               return -EIO;
+       }
+
+       module_put(sst->dev->driver->owner);
+       pr_debug("unreg %s\n", sst->name);
+       sst = NULL;
+       mutex_unlock(&sst_lock);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(sst_unregister_dsp);
+
 static struct snd_pcm_hardware sst_platform_pcm_hw = {
        .info = (SNDRV_PCM_INFO_INTERLEAVED |
                        SNDRV_PCM_INFO_DOUBLE |
@@ -135,37 +176,34 @@ static inline int sst_get_stream_status(struct sst_runtime_stream *stream)
 }
 
 static void sst_fill_pcm_params(struct snd_pcm_substream *substream,
-                               struct snd_sst_stream_params *param)
+                               struct sst_pcm_params *param)
 {
 
-       param->uc.pcm_params.codec = SST_CODEC_TYPE_PCM;
-       param->uc.pcm_params.num_chan = (u8) substream->runtime->channels;
-       param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits;
-       param->uc.pcm_params.reserved = 0;
-       param->uc.pcm_params.sfreq = substream->runtime->rate;
-       param->uc.pcm_params.ring_buffer_size =
-                                       snd_pcm_lib_buffer_bytes(substream);
-       param->uc.pcm_params.period_count = substream->runtime->period_size;
-       param->uc.pcm_params.ring_buffer_addr =
-                               virt_to_phys(substream->dma_buffer.area);
-       pr_debug("period_cnt = %d\n", param->uc.pcm_params.period_count);
-       pr_debug("sfreq= %d, wd_sz = %d\n",
-                param->uc.pcm_params.sfreq, param->uc.pcm_params.pcm_wd_sz);
+       param->codec = SST_CODEC_TYPE_PCM;
+       param->num_chan = (u8) substream->runtime->channels;
+       param->pcm_wd_sz = substream->runtime->sample_bits;
+       param->reserved = 0;
+       param->sfreq = substream->runtime->rate;
+       param->ring_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+       param->period_count = substream->runtime->period_size;
+       param->ring_buffer_addr = virt_to_phys(substream->dma_buffer.area);
+       pr_debug("period_cnt = %d\n", param->period_count);
+       pr_debug("sfreq= %d, wd_sz = %d\n", param->sfreq, param->pcm_wd_sz);
 }
 
 static int sst_platform_alloc_stream(struct snd_pcm_substream *substream)
 {
        struct sst_runtime_stream *stream =
                        substream->runtime->private_data;
-       struct snd_sst_stream_params param = {{{0,},},};
-       struct snd_sst_params str_params = {0};
+       struct sst_pcm_params param = {0};
+       struct sst_stream_params str_params = {0};
        int ret_val;
 
        /* set codec params and inform SST driver the same */
        sst_fill_pcm_params(substream, &param);
        substream->runtime->dma_area = substream->dma_buffer.area;
        str_params.sparams = param;
-       str_params.codec =  param.uc.pcm_params.codec;
+       str_params.codec =  param.codec;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                str_params.ops = STREAM_OPS_PLAYBACK;
                str_params.device_type = substream->pcm->device + 1;
@@ -177,7 +215,7 @@ static int sst_platform_alloc_stream(struct snd_pcm_substream *substream)
                pr_debug("Capture stream,Device %d\n",
                                        substream->pcm->device);
        }
-       ret_val = stream->sstdrv_ops->pcm_control->open(&str_params);
+       ret_val = stream->ops->open(&str_params);
        pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val);
        if (ret_val < 0)
                return ret_val;
@@ -216,7 +254,7 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream)
        stream->stream_info.mad_substream = substream;
        stream->stream_info.buffer_ptr = 0;
        stream->stream_info.sfreq = substream->runtime->rate;
-       ret_val = stream->sstdrv_ops->pcm_control->device_control(
+       ret_val = stream->ops->device_control(
                        SST_SND_STREAM_INIT, &stream->stream_info);
        if (ret_val)
                pr_err("control_set ret error %d\n", ret_val);
@@ -229,7 +267,6 @@ static int sst_platform_open(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct sst_runtime_stream *stream;
-       int ret_val = 0;
 
        pr_debug("sst_platform_open called\n");
 
@@ -243,27 +280,27 @@ static int sst_platform_open(struct snd_pcm_substream *substream)
        if (!stream)
                return -ENOMEM;
        spin_lock_init(&stream->status_lock);
-       stream->stream_info.str_id = 0;
-       sst_set_stream_status(stream, SST_PLATFORM_INIT);
-       stream->stream_info.mad_substream = substream;
-       /* allocate memory for SST API set */
-       stream->sstdrv_ops = kzalloc(sizeof(*stream->sstdrv_ops),
-                                                       GFP_KERNEL);
-       if (!stream->sstdrv_ops) {
-               pr_err("sst: mem allocation for ops fail\n");
+
+       /* get the sst ops */
+       mutex_lock(&sst_lock);
+       if (!sst) {
+               pr_err("no device available to run\n");
+               mutex_unlock(&sst_lock);
                kfree(stream);
-               return -ENOMEM;
+               return -ENODEV;
        }
-       stream->sstdrv_ops->vendor_id = MSIC_VENDOR_ID;
-       stream->sstdrv_ops->module_name = SST_CARD_NAMES;
-       /* registering with SST driver to get access to SST APIs to use */
-       ret_val = register_sst_card(stream->sstdrv_ops);
-       if (ret_val) {
-               pr_err("sst: sst card registration failed\n");
-               kfree(stream->sstdrv_ops);
+       if (!try_module_get(sst->dev->driver->owner)) {
+               mutex_unlock(&sst_lock);
                kfree(stream);
-               return ret_val;
+               return -ENODEV;
        }
+       stream->ops = sst->ops;
+       mutex_unlock(&sst_lock);
+
+       stream->stream_info.str_id = 0;
+       sst_set_stream_status(stream, SST_PLATFORM_INIT);
+       stream->stream_info.mad_substream = substream;
+       /* allocate memory for SST API set */
        runtime->private_data = stream;
 
        return 0;
@@ -278,9 +315,8 @@ static int sst_platform_close(struct snd_pcm_substream *substream)
        stream = substream->runtime->private_data;
        str_id = stream->stream_info.str_id;
        if (str_id)
-               ret_val = stream->sstdrv_ops->pcm_control->close(str_id);
-       unregister_sst_card(stream->sstdrv_ops);
-       kfree(stream->sstdrv_ops);
+               ret_val = stream->ops->close(str_id);
+       module_put(sst->dev->driver->owner);
        kfree(stream);
        return ret_val;
 }
@@ -294,8 +330,8 @@ static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream)
        stream = substream->runtime->private_data;
        str_id = stream->stream_info.str_id;
        if (stream->stream_info.str_id) {
-               ret_val = stream->sstdrv_ops->pcm_control->device_control(
-                                       SST_SND_DROP, &str_id);
+               ret_val = stream->ops->device_control(
+                               SST_SND_DROP, &str_id);
                return ret_val;
        }
 
@@ -347,8 +383,7 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
        default:
                return -EINVAL;
        }
-       ret_val = stream->sstdrv_ops->pcm_control->device_control(str_cmd,
-                                                               &str_id);
+       ret_val = stream->ops->device_control(str_cmd, &str_id);
        if (!ret_val)
                sst_set_stream_status(stream, status);
 
@@ -368,7 +403,7 @@ static snd_pcm_uframes_t sst_platform_pcm_pointer
        if (status == SST_PLATFORM_INIT)
                return 0;
        str_info = &stream->stream_info;
-       ret_val = stream->sstdrv_ops->pcm_control->device_control(
+       ret_val = stream->ops->device_control(
                                SST_SND_BUFFER_POINTER, str_info);
        if (ret_val) {
                pr_err("sst: error code = %d\n", ret_val);
@@ -439,6 +474,7 @@ static int sst_platform_probe(struct platform_device *pdev)
        int ret;
 
        pr_debug("sst_platform_probe called\n");
+       sst = NULL;
        ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv);
        if (ret) {
                pr_err("registering soc platform failed\n");
@@ -472,19 +508,7 @@ static struct platform_driver sst_platform_driver = {
        .remove         = sst_platform_remove,
 };
 
-static int __init sst_soc_platform_init(void)
-{
-       pr_debug("sst_soc_platform_init called\n");
-       return platform_driver_register(&sst_platform_driver);
-}
-module_init(sst_soc_platform_init);
-
-static void __exit sst_soc_platform_exit(void)
-{
-       platform_driver_unregister(&sst_platform_driver);
-       pr_debug("sst_soc_platform_exit success\n");
-}
-module_exit(sst_soc_platform_exit);
+module_platform_driver(sst_platform_driver);
 
 MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver");
 MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
index df37028..f04f4f7 100644 (file)
 #define SST_MIN_PERIODS                2
 #define SST_MAX_PERIODS                (1024*2)
 #define SST_FIFO_SIZE          0
-#define SST_CARD_NAMES         "intel_mid_card"
-#define MSIC_VENDOR_ID         3
+#define SST_CODEC_TYPE_PCM     1
 
-struct sst_runtime_stream {
-       int     stream_status;
-       struct pcm_stream_info stream_info;
-       struct intel_sst_card_ops *sstdrv_ops;
-       spinlock_t      status_lock;
+struct pcm_stream_info {
+       int str_id;
+       void *mad_substream;
+       void (*period_elapsed) (void *mad_substream);
+       unsigned long long buffer_ptr;
+       int sfreq;
 };
 
 enum sst_drv_status {
@@ -60,4 +60,72 @@ enum sst_drv_status {
        SST_PLATFORM_DROPPED,
 };
 
+enum sst_controls {
+       SST_SND_ALLOC =                 0x00,
+       SST_SND_PAUSE =                 0x01,
+       SST_SND_RESUME =                0x02,
+       SST_SND_DROP =                  0x03,
+       SST_SND_FREE =                  0x04,
+       SST_SND_BUFFER_POINTER =        0x05,
+       SST_SND_STREAM_INIT =           0x06,
+       SST_SND_START    =              0x07,
+       SST_MAX_CONTROLS =              0x07,
+};
+
+enum sst_stream_ops {
+       STREAM_OPS_PLAYBACK = 0,
+       STREAM_OPS_CAPTURE,
+};
+
+enum sst_audio_device_type {
+       SND_SST_DEVICE_HEADSET = 1,
+       SND_SST_DEVICE_IHF,
+       SND_SST_DEVICE_VIBRA,
+       SND_SST_DEVICE_HAPTIC,
+       SND_SST_DEVICE_CAPTURE,
+};
+
+/* PCM Parameters */
+struct sst_pcm_params {
+       u16 codec;      /* codec type */
+       u8 num_chan;    /* 1=Mono, 2=Stereo */
+       u8 pcm_wd_sz;   /* 16/24 - bit*/
+       u32 reserved;   /* Bitrate in bits per second */
+       u32 sfreq;      /* Sampling rate in Hz */
+       u32 ring_buffer_size;
+       u32 period_count;       /* period elapsed in samples*/
+       u32 ring_buffer_addr;
+};
+
+struct sst_stream_params {
+       u32 result;
+       u32 stream_id;
+       u8 codec;
+       u8 ops;
+       u8 stream_type;
+       u8 device_type;
+       struct sst_pcm_params sparams;
+};
+
+struct sst_ops {
+       int (*open) (struct sst_stream_params *str_param);
+       int (*device_control) (int cmd, void *arg);
+       int (*close) (unsigned int str_id);
+};
+
+struct sst_runtime_stream {
+       int     stream_status;
+       struct pcm_stream_info stream_info;
+       struct sst_ops *ops;
+       spinlock_t      status_lock;
+};
+
+struct sst_device {
+       char *name;
+       struct device *dev;
+       struct sst_ops *ops;
+};
+
+int sst_register_dsp(struct sst_device *sst);
+int sst_unregister_dsp(struct sst_device *sst);
 #endif
index dea5aa4..0e12f4e 100644 (file)
@@ -346,14 +346,7 @@ static struct platform_driver mxs_pcm_driver = {
        .remove = __devexit_p(mxs_soc_platform_remove),
 };
 
-static int __init snd_mxs_pcm_init(void)
-{
-       return platform_driver_register(&mxs_pcm_driver);
-}
-module_init(snd_mxs_pcm_init);
+module_platform_driver(mxs_pcm_driver);
 
-static void __exit snd_mxs_pcm_exit(void)
-{
-       platform_driver_unregister(&mxs_pcm_driver);
-}
-module_exit(snd_mxs_pcm_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mxs-pcm-audio");
index 76dc74d..1a13ab8 100644 (file)
@@ -550,7 +550,7 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
        (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
        SNDRV_PCM_FMTBIT_S24_LE)
 
-static struct snd_soc_dai_ops mxs_saif_dai_ops = {
+static const struct snd_soc_dai_ops mxs_saif_dai_ops = {
        .startup = mxs_saif_startup,
        .trigger = mxs_saif_trigger,
        .prepare = mxs_saif_prepare,
@@ -781,18 +781,8 @@ static struct platform_driver mxs_saif_driver = {
        },
 };
 
-static int __init mxs_saif_init(void)
-{
-       return platform_driver_register(&mxs_saif_driver);
-}
-
-static void __exit mxs_saif_exit(void)
-{
-       platform_driver_unregister(&mxs_saif_driver);
-}
+module_platform_driver(mxs_saif_driver);
 
-module_init(mxs_saif_init);
-module_exit(mxs_saif_exit);
 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 MODULE_DESCRIPTION("MXS ASoC SAIF driver");
 MODULE_LICENSE("GPL");
index 7fbeaec..259278f 100644 (file)
@@ -156,18 +156,9 @@ static struct platform_driver mxs_sgtl5000_audio_driver = {
        .remove = __devexit_p(mxs_sgtl5000_remove),
 };
 
-static int __init mxs_sgtl5000_init(void)
-{
-       return platform_driver_register(&mxs_sgtl5000_audio_driver);
-}
-module_init(mxs_sgtl5000_init);
-
-static void __exit mxs_sgtl5000_exit(void)
-{
-       platform_driver_unregister(&mxs_sgtl5000_audio_driver);
-}
-module_exit(mxs_sgtl5000_exit);
+module_platform_driver(mxs_sgtl5000_audio_driver);
 
 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 MODULE_DESCRIPTION("MXS ALSA SoC Machine driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mxs-sgtl5000");
index 9c0edad..f0c7904 100644 (file)
@@ -291,7 +291,7 @@ static int nuc900_ac97_remove(struct snd_soc_dai *dai)
        return 0;
 }
 
-static struct snd_soc_dai_ops nuc900_ac97_dai_ops = {
+static const struct snd_soc_dai_ops nuc900_ac97_dai_ops = {
        .trigger        = nuc900_ac97_trigger,
 };
 
@@ -405,18 +405,7 @@ static struct platform_driver nuc900_ac97_driver = {
        .remove         = __devexit_p(nuc900_ac97_drvremove),
 };
 
-static int __init nuc900_ac97_init(void)
-{
-       return platform_driver_register(&nuc900_ac97_driver);
-}
-
-static void __exit nuc900_ac97_exit(void)
-{
-       platform_driver_unregister(&nuc900_ac97_driver);
-}
-
-module_init(nuc900_ac97_init);
-module_exit(nuc900_ac97_exit);
+module_platform_driver(nuc900_ac97_driver);
 
 MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
 MODULE_DESCRIPTION("NUC900 AC97 SoC driver!");
index ae8d680..37585b4 100644 (file)
@@ -358,17 +358,7 @@ static struct platform_driver nuc900_pcm_driver = {
        .remove = __devexit_p(nuc900_soc_platform_remove),
 };
 
-static int __init nuc900_pcm_init(void)
-{
-       return platform_driver_register(&nuc900_pcm_driver);
-}
-module_init(nuc900_pcm_init);
-
-static void __exit nuc900_pcm_exit(void)
-{
-       platform_driver_unregister(&nuc900_pcm_driver);
-}
-module_exit(nuc900_pcm_exit);
+module_platform_driver(nuc900_pcm_driver);
 
 MODULE_AUTHOR("Wan ZongShun, <mcuos.com@gmail.com>");
 MODULE_DESCRIPTION("nuc900 Audio DMA module");
index fe83d0d..fb1bf25 100644 (file)
@@ -2,6 +2,9 @@ config SND_OMAP_SOC
        tristate "SoC Audio for the Texas Instruments OMAP chips"
        depends on ARCH_OMAP
 
+config SND_OMAP_SOC_DMIC
+       tristate
+
 config SND_OMAP_SOC_MCBSP
        tristate
        select OMAP_MCBSP
@@ -97,8 +100,10 @@ config SND_OMAP_SOC_SDP3430
 config SND_OMAP_SOC_SDP4430
        tristate "SoC Audio support for Texas Instruments SDP4430"
        depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_4430SDP
+       select SND_OMAP_SOC_DMIC
        select SND_OMAP_SOC_MCPDM
        select SND_SOC_TWL6040
+       select SND_SOC_DMIC
        help
          Say Y if you want to add support for SoC audio on Texas Instruments
          SDP4430.
index 052fd75..1fd723f 100644 (file)
@@ -1,10 +1,12 @@
 # OMAP Platform Support
 snd-soc-omap-objs := omap-pcm.o
+snd-soc-omap-dmic-objs := omap-dmic.o
 snd-soc-omap-mcbsp-objs := omap-mcbsp.o
 snd-soc-omap-mcpdm-objs := omap-mcpdm.o
 snd-soc-omap-hdmi-objs := omap-hdmi.o
 
 obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o
+obj-$(CONFIG_SND_OMAP_SOC_DMIC) += snd-soc-omap-dmic.o
 obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
 obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o
 obj-$(CONFIG_SND_OMAP_SOC_HDMI) += snd-soc-omap-hdmi.o
index ccb8a6a..a04a433 100644 (file)
@@ -474,7 +474,7 @@ static int ams_delta_digital_mute(struct snd_soc_dai *dai, int mute)
 }
 
 /* Our codec DAI probably doesn't have its own .ops structure */
-static struct snd_soc_dai_ops ams_delta_dai_ops = {
+static const struct snd_soc_dai_ops ams_delta_dai_ops = {
        .digital_mute = ams_delta_digital_mute,
 };
 
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c
new file mode 100644 (file)
index 0000000..0855c1c
--- /dev/null
@@ -0,0 +1,546 @@
+/*
+ * omap-dmic.c  --  OMAP ASoC DMIC DAI driver
+ *
+ * Copyright (C) 2010 - 2011 Texas Instruments
+ *
+ * Author: David Lambert <dlambert@ti.com>
+ *        Misael Lopez Cruz <misael.lopez@ti.com>
+ *        Liam Girdwood <lrg@ti.com>
+ *        Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <plat/dma.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include "omap-pcm.h"
+#include "omap-dmic.h"
+
+struct omap_dmic {
+       struct device *dev;
+       void __iomem *io_base;
+       struct clk *fclk;
+       int fclk_freq;
+       int out_freq;
+       int clk_div;
+       int sysclk;
+       int threshold;
+       u32 ch_enabled;
+       bool active;
+       struct mutex mutex;
+};
+
+/*
+ * Stream DMA parameters
+ */
+static struct omap_pcm_dma_data omap_dmic_dai_dma_params = {
+       .name           = "DMIC capture",
+       .data_type      = OMAP_DMA_DATA_TYPE_S32,
+       .sync_mode      = OMAP_DMA_SYNC_PACKET,
+};
+
+static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val)
+{
+       __raw_writel(val, dmic->io_base + reg);
+}
+
+static inline int omap_dmic_read(struct omap_dmic *dmic, u16 reg)
+{
+       return __raw_readl(dmic->io_base + reg);
+}
+
+static inline void omap_dmic_start(struct omap_dmic *dmic)
+{
+       u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
+
+       /* Configure DMA controller */
+       omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_SET_REG,
+                       OMAP_DMIC_DMA_ENABLE);
+
+       omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl | dmic->ch_enabled);
+}
+
+static inline void omap_dmic_stop(struct omap_dmic *dmic)
+{
+       u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
+       omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG,
+                       ctrl & ~OMAP_DMIC_UP_ENABLE_MASK);
+
+       /* Disable DMA request generation */
+       omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_CLR_REG,
+                       OMAP_DMIC_DMA_ENABLE);
+
+}
+
+static inline int dmic_is_enabled(struct omap_dmic *dmic)
+{
+       return omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG) &
+                                               OMAP_DMIC_UP_ENABLE_MASK;
+}
+
+static int omap_dmic_dai_startup(struct snd_pcm_substream *substream,
+                                 struct snd_soc_dai *dai)
+{
+       struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+       int ret = 0;
+
+       mutex_lock(&dmic->mutex);
+
+       if (!dai->active) {
+               snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
+               dmic->active = 1;
+       } else {
+               ret = -EBUSY;
+       }
+
+       mutex_unlock(&dmic->mutex);
+
+       return ret;
+}
+
+static void omap_dmic_dai_shutdown(struct snd_pcm_substream *substream,
+                                   struct snd_soc_dai *dai)
+{
+       struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+       mutex_lock(&dmic->mutex);
+
+       if (!dai->active)
+               dmic->active = 0;
+
+       mutex_unlock(&dmic->mutex);
+}
+
+static int omap_dmic_select_divider(struct omap_dmic *dmic, int sample_rate)
+{
+       int divider = -EINVAL;
+
+       /*
+        * 192KHz rate is only supported with 19.2MHz/3.84MHz clock
+        * configuration.
+        */
+       if (sample_rate == 192000) {
+               if (dmic->fclk_freq == 19200000 && dmic->out_freq == 3840000)
+                       divider = 0x6; /* Divider: 5 (192KHz sampling rate) */
+               else
+                       dev_err(dmic->dev,
+                               "invalid clock configuration for 192KHz\n");
+
+               return divider;
+       }
+
+       switch (dmic->out_freq) {
+       case 1536000:
+               if (dmic->fclk_freq != 24576000)
+                       goto div_err;
+               divider = 0x4; /* Divider: 16 */
+               break;
+       case 2400000:
+               switch (dmic->fclk_freq) {
+               case 12000000:
+                       divider = 0x5; /* Divider: 5 */
+                       break;
+               case 19200000:
+                       divider = 0x0; /* Divider: 8 */
+                       break;
+               case 24000000:
+                       divider = 0x2; /* Divider: 10 */
+                       break;
+               default:
+                       goto div_err;
+               }
+               break;
+       case 3072000:
+               if (dmic->fclk_freq != 24576000)
+                       goto div_err;
+               divider = 0x3; /* Divider: 8 */
+               break;
+       case 3840000:
+               if (dmic->fclk_freq != 19200000)
+                       goto div_err;
+               divider = 0x1; /* Divider: 5 (96KHz sampling rate) */
+               break;
+       default:
+               dev_err(dmic->dev, "invalid out frequency: %dHz\n",
+                       dmic->out_freq);
+               break;
+       }
+
+       return divider;
+
+div_err:
+       dev_err(dmic->dev, "invalid out frequency %dHz for %dHz input\n",
+               dmic->out_freq, dmic->fclk_freq);
+       return -EINVAL;
+}
+
+static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
+                                   struct snd_pcm_hw_params *params,
+                                   struct snd_soc_dai *dai)
+{
+       struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+       int channels;
+
+       dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params));
+       if (dmic->clk_div < 0) {
+               dev_err(dmic->dev, "no valid divider for %dHz from %dHz\n",
+                       dmic->out_freq, dmic->fclk_freq);
+               return -EINVAL;
+       }
+
+       dmic->ch_enabled = 0;
+       channels = params_channels(params);
+       switch (channels) {
+       case 6:
+               dmic->ch_enabled |= OMAP_DMIC_UP3_ENABLE;
+       case 4:
+               dmic->ch_enabled |= OMAP_DMIC_UP2_ENABLE;
+       case 2:
+               dmic->ch_enabled |= OMAP_DMIC_UP1_ENABLE;
+               break;
+       default:
+               dev_err(dmic->dev, "invalid number of legacy channels\n");
+               return -EINVAL;
+       }
+
+       /* packet size is threshold * channels */
+       omap_dmic_dai_dma_params.packet_size = dmic->threshold * channels;
+       snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params);
+
+       return 0;
+}
+
+static int omap_dmic_dai_prepare(struct snd_pcm_substream *substream,
+                                 struct snd_soc_dai *dai)
+{
+       struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+       u32 ctrl;
+
+       /* Configure uplink threshold */
+       omap_dmic_write(dmic, OMAP_DMIC_FIFO_CTRL_REG, dmic->threshold);
+
+       ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
+
+       /* Set dmic out format */
+       ctrl &= ~(OMAP_DMIC_FORMAT | OMAP_DMIC_POLAR_MASK);
+       ctrl |= (OMAP_DMICOUTFORMAT_LJUST | OMAP_DMIC_POLAR1 |
+                OMAP_DMIC_POLAR2 | OMAP_DMIC_POLAR3);
+
+       /* Configure dmic clock divider */
+       ctrl &= ~OMAP_DMIC_CLK_DIV_MASK;
+       ctrl |= OMAP_DMIC_CLK_DIV(dmic->clk_div);
+
+       omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl);
+
+       omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG,
+                       ctrl | OMAP_DMICOUTFORMAT_LJUST | OMAP_DMIC_POLAR1 |
+                       OMAP_DMIC_POLAR2 | OMAP_DMIC_POLAR3);
+
+       return 0;
+}
+
+static int omap_dmic_dai_trigger(struct snd_pcm_substream *substream,
+                                 int cmd, struct snd_soc_dai *dai)
+{
+       struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               omap_dmic_start(dmic);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               omap_dmic_stop(dmic);
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int omap_dmic_select_fclk(struct omap_dmic *dmic, int clk_id,
+                                unsigned int freq)
+{
+       struct clk *parent_clk;
+       char *parent_clk_name;
+       int ret = 0;
+
+       switch (freq) {
+       case 12000000:
+       case 19200000:
+       case 24000000:
+       case 24576000:
+               break;
+       default:
+               dev_err(dmic->dev, "invalid input frequency: %dHz\n", freq);
+               dmic->fclk_freq = 0;
+               return -EINVAL;
+       }
+
+       if (dmic->sysclk == clk_id) {
+               dmic->fclk_freq = freq;
+               return 0;
+       }
+
+       /* re-parent not allowed if a stream is ongoing */
+       if (dmic->active && dmic_is_enabled(dmic)) {
+               dev_err(dmic->dev, "can't re-parent when DMIC active\n");
+               return -EBUSY;
+       }
+
+       switch (clk_id) {
+       case OMAP_DMIC_SYSCLK_PAD_CLKS:
+               parent_clk_name = "pad_clks_ck";
+               break;
+       case OMAP_DMIC_SYSCLK_SLIMBLUS_CLKS:
+               parent_clk_name = "slimbus_clk";
+               break;
+       case OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS:
+               parent_clk_name = "dmic_sync_mux_ck";
+               break;
+       default:
+               dev_err(dmic->dev, "fclk clk_id (%d) not supported\n", clk_id);
+               return -EINVAL;
+       }
+
+       parent_clk = clk_get(dmic->dev, parent_clk_name);
+       if (IS_ERR(parent_clk)) {
+               dev_err(dmic->dev, "can't get %s\n", parent_clk_name);
+               return -ENODEV;
+       }
+
+       mutex_lock(&dmic->mutex);
+       if (dmic->active) {
+               /* disable clock while reparenting */
+               pm_runtime_put_sync(dmic->dev);
+               ret = clk_set_parent(dmic->fclk, parent_clk);
+               pm_runtime_get_sync(dmic->dev);
+       } else {
+               ret = clk_set_parent(dmic->fclk, parent_clk);
+       }
+       mutex_unlock(&dmic->mutex);
+
+       if (ret < 0) {
+               dev_err(dmic->dev, "re-parent failed\n");
+               goto err_busy;
+       }
+
+       dmic->sysclk = clk_id;
+       dmic->fclk_freq = freq;
+
+err_busy:
+       clk_put(parent_clk);
+
+       return ret;
+}
+
+static int omap_dmic_select_outclk(struct omap_dmic *dmic, int clk_id,
+                                   unsigned int freq)
+{
+       int ret = 0;
+
+       if (clk_id != OMAP_DMIC_ABE_DMIC_CLK) {
+               dev_err(dmic->dev, "output clk_id (%d) not supported\n",
+                       clk_id);
+               return -EINVAL;
+       }
+
+       switch (freq) {
+       case 1536000:
+       case 2400000:
+       case 3072000:
+       case 3840000:
+               dmic->out_freq = freq;
+               break;
+       default:
+               dev_err(dmic->dev, "invalid out frequency: %dHz\n", freq);
+               dmic->out_freq = 0;
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static int omap_dmic_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
+                                   unsigned int freq, int dir)
+{
+       struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+       if (dir == SND_SOC_CLOCK_IN)
+               return omap_dmic_select_fclk(dmic, clk_id, freq);
+       else if (dir == SND_SOC_CLOCK_OUT)
+               return omap_dmic_select_outclk(dmic, clk_id, freq);
+
+       dev_err(dmic->dev, "invalid clock direction (%d)\n", dir);
+       return -EINVAL;
+}
+
+static const struct snd_soc_dai_ops omap_dmic_dai_ops = {
+       .startup        = omap_dmic_dai_startup,
+       .shutdown       = omap_dmic_dai_shutdown,
+       .hw_params      = omap_dmic_dai_hw_params,
+       .prepare        = omap_dmic_dai_prepare,
+       .trigger        = omap_dmic_dai_trigger,
+       .set_sysclk     = omap_dmic_set_dai_sysclk,
+};
+
+static int omap_dmic_probe(struct snd_soc_dai *dai)
+{
+       struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+       pm_runtime_enable(dmic->dev);
+
+       /* Disable lines while request is ongoing */
+       pm_runtime_get_sync(dmic->dev);
+       omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, 0x00);
+       pm_runtime_put_sync(dmic->dev);
+
+       /* Configure DMIC threshold value */
+       dmic->threshold = OMAP_DMIC_THRES_MAX - 3;
+       return 0;
+}
+
+static int omap_dmic_remove(struct snd_soc_dai *dai)
+{
+       struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+       pm_runtime_disable(dmic->dev);
+
+       return 0;
+}
+
+static struct snd_soc_dai_driver omap_dmic_dai = {
+       .name = "omap-dmic",
+       .probe = omap_dmic_probe,
+       .remove = omap_dmic_remove,
+       .capture = {
+               .channels_min = 2,
+               .channels_max = 6,
+               .rates = SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
+               .formats = SNDRV_PCM_FMTBIT_S32_LE,
+       },
+       .ops = &omap_dmic_dai_ops,
+};
+
+static __devinit int asoc_dmic_probe(struct platform_device *pdev)
+{
+       struct omap_dmic *dmic;
+       struct resource *res;
+       int ret;
+
+       dmic = devm_kzalloc(&pdev->dev, sizeof(struct omap_dmic), GFP_KERNEL);
+       if (!dmic)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, dmic);
+       dmic->dev = &pdev->dev;
+       dmic->sysclk = OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS;
+
+       mutex_init(&dmic->mutex);
+
+       dmic->fclk = clk_get(dmic->dev, "dmic_fck");
+       if (IS_ERR(dmic->fclk)) {
+               dev_err(dmic->dev, "cant get dmic_fck\n");
+               return -ENODEV;
+       }
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
+       if (!res) {
+               dev_err(dmic->dev, "invalid dma memory resource\n");
+               ret = -ENODEV;
+               goto err_put_clk;
+       }
+       omap_dmic_dai_dma_params.port_addr = res->start + OMAP_DMIC_DATA_REG;
+
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!res) {
+               dev_err(dmic->dev, "invalid dma resource\n");
+               ret = -ENODEV;
+               goto err_put_clk;
+       }
+       omap_dmic_dai_dma_params.dma_req = res->start;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
+       if (!res) {
+               dev_err(dmic->dev, "invalid memory resource\n");
+               ret = -ENODEV;
+               goto err_put_clk;
+       }
+
+       if (!devm_request_mem_region(&pdev->dev, res->start,
+                                    resource_size(res), pdev->name)) {
+               dev_err(dmic->dev, "memory region already claimed\n");
+               ret = -ENODEV;
+               goto err_put_clk;
+       }
+
+       dmic->io_base = devm_ioremap(&pdev->dev, res->start,
+                                    resource_size(res));
+       if (!dmic->io_base) {
+               ret = -ENOMEM;
+               goto err_put_clk;
+       }
+
+       ret = snd_soc_register_dai(&pdev->dev, &omap_dmic_dai);
+       if (ret)
+               goto err_put_clk;
+
+       return 0;
+
+err_put_clk:
+       clk_put(dmic->fclk);
+       return ret;
+}
+
+static int __devexit asoc_dmic_remove(struct platform_device *pdev)
+{
+       struct omap_dmic *dmic = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_dai(&pdev->dev);
+       clk_put(dmic->fclk);
+
+       return 0;
+}
+
+static struct platform_driver asoc_dmic_driver = {
+       .driver = {
+               .name = "omap-dmic",
+               .owner = THIS_MODULE,
+       },
+       .probe = asoc_dmic_probe,
+       .remove = __devexit_p(asoc_dmic_remove),
+};
+
+module_platform_driver(asoc_dmic_driver);
+
+MODULE_ALIAS("platform:omap-dmic");
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_DESCRIPTION("OMAP DMIC ASoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-dmic.h b/sound/soc/omap/omap-dmic.h
new file mode 100644 (file)
index 0000000..231e728
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * omap-dmic.h  --  OMAP Digital Microphone Controller
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _OMAP_DMIC_H
+#define _OMAP_DMIC_H
+
+#define OMAP_DMIC_REVISION_REG         0x00
+#define OMAP_DMIC_SYSCONFIG_REG                0x10
+#define OMAP_DMIC_IRQSTATUS_RAW_REG    0x24
+#define OMAP_DMIC_IRQSTATUS_REG                0x28
+#define OMAP_DMIC_IRQENABLE_SET_REG    0x2C
+#define OMAP_DMIC_IRQENABLE_CLR_REG    0x30
+#define OMAP_DMIC_IRQWAKE_EN_REG       0x34
+#define OMAP_DMIC_DMAENABLE_SET_REG    0x38
+#define OMAP_DMIC_DMAENABLE_CLR_REG    0x3C
+#define OMAP_DMIC_DMAWAKEEN_REG                0x40
+#define OMAP_DMIC_CTRL_REG             0x44
+#define OMAP_DMIC_DATA_REG             0x48
+#define OMAP_DMIC_FIFO_CTRL_REG                0x4C
+#define OMAP_DMIC_FIFO_DMIC1R_DATA_REG 0x50
+#define OMAP_DMIC_FIFO_DMIC1L_DATA_REG 0x54
+#define OMAP_DMIC_FIFO_DMIC2R_DATA_REG 0x58
+#define OMAP_DMIC_FIFO_DMIC2L_DATA_REG 0x5C
+#define OMAP_DMIC_FIFO_DMIC3R_DATA_REG 0x60
+#define OMAP_DMIC_FIFO_DMIC3L_DATA_REG 0x64
+
+/* IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR bit fields */
+#define OMAP_DMIC_IRQ                  (1 << 0)
+#define OMAP_DMIC_IRQ_FULL             (1 << 1)
+#define OMAP_DMIC_IRQ_ALMST_EMPTY      (1 << 2)
+#define OMAP_DMIC_IRQ_EMPTY            (1 << 3)
+#define OMAP_DMIC_IRQ_MASK             0x07
+
+/* DMIC_DMAENABLE bit fields */
+#define OMAP_DMIC_DMA_ENABLE           0x1
+
+/* DMIC_CTRL bit fields */
+#define OMAP_DMIC_UP1_ENABLE           (1 << 0)
+#define OMAP_DMIC_UP2_ENABLE           (1 << 1)
+#define OMAP_DMIC_UP3_ENABLE           (1 << 2)
+#define OMAP_DMIC_UP_ENABLE_MASK       0x7
+#define OMAP_DMIC_FORMAT               (1 << 3)
+#define OMAP_DMIC_POLAR1               (1 << 4)
+#define OMAP_DMIC_POLAR2               (1 << 5)
+#define OMAP_DMIC_POLAR3               (1 << 6)
+#define OMAP_DMIC_POLAR_MASK           (0x7 << 4)
+#define OMAP_DMIC_CLK_DIV(x)           (((x) & 0x7) << 7)
+#define OMAP_DMIC_CLK_DIV_MASK         (0x7 << 7)
+#define        OMAP_DMIC_RESET                 (1 << 10)
+
+#define OMAP_DMICOUTFORMAT_LJUST       (0 << 3)
+#define OMAP_DMICOUTFORMAT_RJUST       (1 << 3)
+
+/* DMIC_FIFO_CTRL bit fields */
+#define OMAP_DMIC_THRES_MAX            0xF
+
+enum omap_dmic_clk {
+       OMAP_DMIC_SYSCLK_PAD_CLKS,              /* PAD_CLKS */
+       OMAP_DMIC_SYSCLK_SLIMBLUS_CLKS,         /* SLIMBUS_CLK */
+       OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS,         /* DMIC_SYNC_MUX_CLK */
+       OMAP_DMIC_ABE_DMIC_CLK,                 /* abe_dmic_clk */
+};
+
+#endif
index 36c6eae..38e0def 100644 (file)
@@ -83,7 +83,7 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
        return err;
 }
 
-static struct snd_soc_dai_ops omap_hdmi_dai_ops = {
+static const struct snd_soc_dai_ops omap_hdmi_dai_ops = {
        .startup        = omap_hdmi_dai_startup,
        .hw_params      = omap_hdmi_dai_hw_params,
 };
@@ -139,17 +139,7 @@ static struct platform_driver hdmi_dai_driver = {
        .remove = __devexit_p(omap_hdmi_remove),
 };
 
-static int __init hdmi_dai_init(void)
-{
-       return platform_driver_register(&hdmi_dai_driver);
-}
-module_init(hdmi_dai_init);
-
-static void __exit hdmi_dai_exit(void)
-{
-       platform_driver_unregister(&hdmi_dai_driver);
-}
-module_exit(hdmi_dai_exit);
+module_platform_driver(hdmi_dai_driver);
 
 MODULE_AUTHOR("Jorge Candelaria <jorge.candelaria@ti.com>");
 MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
index 4314647..bd11d25 100644 (file)
@@ -599,7 +599,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
        return err;
 }
 
-static struct snd_soc_dai_ops mcbsp_dai_ops = {
+static const struct snd_soc_dai_ops mcbsp_dai_ops = {
        .startup        = omap_mcbsp_dai_startup,
        .shutdown       = omap_mcbsp_dai_shutdown,
        .trigger        = omap_mcbsp_dai_trigger,
@@ -785,17 +785,7 @@ static struct platform_driver asoc_mcbsp_driver = {
        .remove = __devexit_p(asoc_mcbsp_remove),
 };
 
-static int __init snd_omap_mcbsp_init(void)
-{
-       return platform_driver_register(&asoc_mcbsp_driver);
-}
-module_init(snd_omap_mcbsp_init);
-
-static void __exit snd_omap_mcbsp_exit(void)
-{
-       platform_driver_unregister(&asoc_mcbsp_driver);
-}
-module_exit(snd_omap_mcbsp_exit);
+module_platform_driver(asoc_mcbsp_driver);
 
 MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
 MODULE_DESCRIPTION("OMAP I2S SoC Interface");
index 41d1706..0e25df4 100644 (file)
@@ -266,8 +266,6 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
        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);
@@ -295,9 +293,6 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
                        omap_mcpdm_stop(mcpdm);
                        omap_mcpdm_close_streams(mcpdm);
                }
-
-               if (!omap_mcpdm_active(mcpdm))
-                       pm_runtime_put_sync(mcpdm->dev);
        }
 
        mutex_unlock(&mcpdm->mutex);
@@ -367,7 +362,7 @@ static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_dai_ops omap_mcpdm_dai_ops = {
+static const struct snd_soc_dai_ops omap_mcpdm_dai_ops = {
        .startup        = omap_mcpdm_dai_startup,
        .shutdown       = omap_mcpdm_dai_shutdown,
        .hw_params      = omap_mcpdm_dai_hw_params,
@@ -520,17 +515,7 @@ static struct platform_driver asoc_mcpdm_driver = {
        .remove = __devexit_p(asoc_mcpdm_remove),
 };
 
-static int __init snd_omap_mcpdm_init(void)
-{
-       return platform_driver_register(&asoc_mcpdm_driver);
-}
-module_init(snd_omap_mcpdm_init);
-
-static void __exit snd_omap_mcpdm_exit(void)
-{
-       platform_driver_unregister(&asoc_mcpdm_driver);
-}
-module_exit(snd_omap_mcpdm_exit);
+module_platform_driver(asoc_mcpdm_driver);
 
 MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
 MODULE_DESCRIPTION("OMAP PDM SoC Interface");
index 6ede7dc..52a0f63 100644 (file)
@@ -433,17 +433,7 @@ static struct platform_driver omap_pcm_driver = {
        .remove = __devexit_p(omap_pcm_remove),
 };
 
-static int __init snd_omap_pcm_init(void)
-{
-       return platform_driver_register(&omap_pcm_driver);
-}
-module_init(snd_omap_pcm_init);
-
-static void __exit snd_omap_pcm_exit(void)
-{
-       platform_driver_unregister(&omap_pcm_driver);
-}
-module_exit(snd_omap_pcm_exit);
+module_platform_driver(omap_pcm_driver);
 
 MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
 MODULE_DESCRIPTION("OMAP PCM DMA module");
index 8671261..52d471c 100644 (file)
@@ -112,17 +112,7 @@ static struct platform_driver omap4_hdmi_driver = {
        .remove = __devexit_p(omap4_hdmi_remove),
 };
 
-static int __init omap4_hdmi_init(void)
-{
-       return platform_driver_register(&omap4_hdmi_driver);
-}
-module_init(omap4_hdmi_init);
-
-static void __exit omap4_hdmi_exit(void)
-{
-       platform_driver_unregister(&omap4_hdmi_driver);
-}
-module_exit(omap4_hdmi_exit);
+module_platform_driver(omap4_hdmi_driver);
 
 MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
 MODULE_DESCRIPTION("OMAP4 HDMI machine ASoC driver");
index 03d9fa4..2735fa0 100644 (file)
@@ -33,6 +33,7 @@
 #include <plat/hardware.h>
 #include <plat/mux.h>
 
+#include "omap-dmic.h"
 #include "omap-mcpdm.h"
 #include "omap-pcm.h"
 #include "../codecs/twl6040.h"
@@ -67,6 +68,32 @@ static struct snd_soc_ops sdp4430_ops = {
        .hw_params = sdp4430_hw_params,
 };
 
+static int sdp4430_dmic_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       int ret = 0;
+
+       ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_SYSCLK_PAD_CLKS,
+                                    19200000, SND_SOC_CLOCK_IN);
+       if (ret < 0) {
+               printk(KERN_ERR "can't set DMIC cpu system clock\n");
+               return ret;
+       }
+       ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_ABE_DMIC_CLK, 2400000,
+                                    SND_SOC_CLOCK_OUT);
+       if (ret < 0) {
+               printk(KERN_ERR "can't set DMIC output clock\n");
+               return ret;
+       }
+       return 0;
+}
+
+static struct snd_soc_ops sdp4430_dmic_ops = {
+       .hw_params = sdp4430_dmic_hw_params,
+};
+
 /* Headset jack */
 static struct snd_soc_jack hs_jack;
 
@@ -148,23 +175,59 @@ static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
        return ret;
 }
 
+static const struct snd_soc_dapm_widget sdp4430_dmic_dapm_widgets[] = {
+       SND_SOC_DAPM_MIC("Digital Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route dmic_audio_map[] = {
+       {"DMic", NULL, "Digital Mic1 Bias"},
+       {"Digital Mic1 Bias", NULL, "Digital Mic"},
+};
+
+static int sdp4430_dmic_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_codec *codec = rtd->codec;
+       struct snd_soc_dapm_context *dapm = &codec->dapm;
+       int ret;
+
+       ret = snd_soc_dapm_new_controls(dapm, sdp4430_dmic_dapm_widgets,
+                               ARRAY_SIZE(sdp4430_dmic_dapm_widgets));
+       if (ret)
+               return ret;
+
+       return snd_soc_dapm_add_routes(dapm, dmic_audio_map,
+                               ARRAY_SIZE(dmic_audio_map));
+}
+
 /* Digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link sdp4430_dai = {
-       .name = "TWL6040",
-       .stream_name = "TWL6040",
-       .cpu_dai_name = "omap-mcpdm",
-       .codec_dai_name = "twl6040-legacy",
-       .platform_name = "omap-pcm-audio",
-       .codec_name = "twl6040-codec",
-       .init = sdp4430_twl6040_init,
-       .ops = &sdp4430_ops,
+static struct snd_soc_dai_link sdp4430_dai[] = {
+       {
+               .name = "TWL6040",
+               .stream_name = "TWL6040",
+               .cpu_dai_name = "omap-mcpdm",
+               .codec_dai_name = "twl6040-legacy",
+               .platform_name = "omap-pcm-audio",
+               .codec_name = "twl6040-codec",
+               .init = sdp4430_twl6040_init,
+               .ops = &sdp4430_ops,
+       },
+       {
+               .name = "DMIC",
+               .stream_name = "DMIC Capture",
+               .cpu_dai_name = "omap-dmic",
+               .codec_dai_name = "dmic-hifi",
+               .platform_name = "omap-pcm-audio",
+               .codec_name = "dmic-codec",
+               .init = sdp4430_dmic_init,
+               .ops = &sdp4430_dmic_ops,
+       },
 };
 
 /* Audio machine driver */
 static struct snd_soc_card snd_soc_sdp4430 = {
        .name = "SDP4430",
-       .dai_link = &sdp4430_dai,
-       .num_links = 1,
+       .dai_link = sdp4430_dai,
+       .num_links = ARRAY_SIZE(sdp4430_dai),
 
        .dapm_widgets = sdp4430_twl6040_dapm_widgets,
        .num_dapm_widgets = ARRAY_SIZE(sdp4430_twl6040_dapm_widgets),
index ffd2242..a0f7d3c 100644 (file)
@@ -151,6 +151,7 @@ config SND_SOC_ZYLONITE
 config SND_SOC_RAUMFELD
        tristate "SoC Audio support Raumfeld audio adapter"
        depends on SND_PXA2XX_SOC && (MACH_RAUMFELD_SPEAKER || MACH_RAUMFELD_CONNECTOR)
+       depends on I2C && SPI_MASTER
        select SND_PXA_SOC_SSP
        select SND_SOC_CS4270
        select SND_SOC_AK4104
@@ -159,7 +160,7 @@ config SND_SOC_RAUMFELD
 
 config SND_PXA2XX_SOC_HX4700
        tristate "SoC Audio support for HP iPAQ hx4700"
-       depends on SND_PXA2XX_SOC && MACH_H4700
+       depends on SND_PXA2XX_SOC && MACH_H4700 && I2C
        select SND_PXA2XX_SOC_I2S
        select SND_SOC_AK4641
        help
index 35ed7eb..818dc57 100644 (file)
@@ -146,29 +146,21 @@ static int __init e740_init(void)
        if (!machine_is_e740())
                return -ENODEV;
 
-       ret = gpio_request(GPIO_E740_MIC_ON,  "Mic amp");
+       /* Disable audio */
+       ret = gpio_request_one(GPIO_E740_MIC_ON, GPIOF_OUT_INIT_LOW, "Mic amp");
        if (ret)
                return ret;
 
-       ret = gpio_request(GPIO_E740_AMP_ON, "Output amp");
+       ret = gpio_request_one(GPIO_E740_AMP_ON, GPIOF_OUT_INIT_LOW,
+                              "Output amp");
        if (ret)
                goto free_mic_amp_gpio;
 
-       ret = gpio_request(GPIO_E740_WM9705_nAVDD2, "Audio power");
+       ret = gpio_request_one(GPIO_E740_WM9705_nAVDD2, GPIOF_OUT_INIT_HIGH,
+                          "Audio power");
        if (ret)
                goto free_op_amp_gpio;
 
-       /* Disable audio */
-       ret = gpio_direction_output(GPIO_E740_MIC_ON, 0);
-       if (ret)
-               goto free_apwr_gpio;
-       ret = gpio_direction_output(GPIO_E740_AMP_ON, 0);
-       if (ret)
-               goto free_apwr_gpio;
-       ret = gpio_direction_output(GPIO_E740_WM9705_nAVDD2, 1);
-       if (ret)
-               goto free_apwr_gpio;
-
        e740_snd_device = platform_device_alloc("soc-audio", -1);
        if (!e740_snd_device) {
                ret = -ENOMEM;
index ce5f056..55c53d1 100644 (file)
@@ -129,22 +129,16 @@ static int __init e750_init(void)
        if (!machine_is_e750())
                return -ENODEV;
 
-       ret = gpio_request(GPIO_E750_HP_AMP_OFF,  "Headphone amp");
+       ret = gpio_request_one(GPIO_E750_HP_AMP_OFF, GPIOF_OUT_INIT_HIGH,
+                              "Headphone amp");
        if (ret)
                return ret;
 
-       ret = gpio_request(GPIO_E750_SPK_AMP_OFF, "Speaker amp");
+       ret = gpio_request_one(GPIO_E750_SPK_AMP_OFF, GPIOF_OUT_INIT_HIGH,
+                              "Speaker amp");
        if (ret)
                goto free_hp_amp_gpio;
 
-       ret = gpio_direction_output(GPIO_E750_HP_AMP_OFF, 1);
-       if (ret)
-               goto free_spk_amp_gpio;
-
-       ret = gpio_direction_output(GPIO_E750_SPK_AMP_OFF, 1);
-       if (ret)
-               goto free_spk_amp_gpio;
-
        e750_snd_device = platform_device_alloc("soc-audio", -1);
        if (!e750_snd_device) {
                ret = -ENOMEM;
index 6a8f38b..478ff19 100644 (file)
@@ -119,25 +119,21 @@ static int __init e800_init(void)
        if (!machine_is_e800())
                return -ENODEV;
 
-       ret = gpio_request(GPIO_E800_HP_AMP_OFF,  "Headphone amp");
+       ret = gpio_request_one(GPIO_E800_HP_AMP_OFF, GPIOF_OUT_INIT_HIGH,
+                              "Headphone amp");
        if (ret)
                return ret;
 
-       ret = gpio_request(GPIO_E800_SPK_AMP_ON, "Speaker amp");
+       ret = gpio_request_one(GPIO_E800_SPK_AMP_ON, GPIOF_OUT_INIT_HIGH,
+                              "Speaker amp");
        if (ret)
                goto free_hp_amp_gpio;
 
-       ret = gpio_direction_output(GPIO_E800_HP_AMP_OFF, 1);
-       if (ret)
-               goto free_spk_amp_gpio;
-
-       ret = gpio_direction_output(GPIO_E800_SPK_AMP_ON, 1);
-       if (ret)
-               goto free_spk_amp_gpio;
-
        e800_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!e800_snd_device)
-               return -ENOMEM;
+       if (!e800_snd_device) {
+               ret = -ENOMEM;
+               goto free_spk_amp_gpio;
+       }
 
        platform_set_drvdata(e800_snd_device, &e800);
        ret = platform_device_add(e800_snd_device);
index 65c1248..03ef9f3 100644 (file)
@@ -209,9 +209,10 @@ static int __devinit hx4700_audio_probe(struct platform_device *pdev)
        snd_soc_card_hx4700.dev = &pdev->dev;
        ret = snd_soc_register_card(&snd_soc_card_hx4700);
        if (ret)
-               return ret;
+               gpio_free_array(hx4700_audio_gpios,
+                               ARRAY_SIZE(hx4700_audio_gpios));
 
-       return 0;
+       return ret;
 }
 
 static int __devexit hx4700_audio_remove(struct platform_device *pdev)
@@ -236,18 +237,7 @@ static struct platform_driver hx4700_audio_driver = {
        .remove = __devexit_p(hx4700_audio_remove),
 };
 
-static int __init hx4700_modinit(void)
-{
-       return platform_driver_register(&hx4700_audio_driver);
-}
-module_init(hx4700_modinit);
-
-static void __exit hx4700_modexit(void)
-{
-       platform_driver_unregister(&hx4700_audio_driver);
-}
-
-module_exit(hx4700_modexit);
+module_platform_driver(hx4700_audio_driver);
 
 MODULE_AUTHOR("Philipp Zabel");
 MODULE_DESCRIPTION("ALSA SoC iPAQ hx4700");
index 0b8d1ee..0e73a7f 100644 (file)
@@ -227,18 +227,7 @@ static struct platform_driver mioa701_wm9713_driver = {
        },
 };
 
-static int __init mioa701_asoc_init(void)
-{
-       return platform_driver_register(&mioa701_wm9713_driver);
-}
-
-static void __exit mioa701_asoc_exit(void)
-{
-       platform_driver_unregister(&mioa701_wm9713_driver);
-}
-
-module_init(mioa701_asoc_init);
-module_exit(mioa701_asoc_exit);
+module_platform_driver(mioa701_wm9713_driver);
 
 /* Module information */
 MODULE_AUTHOR("Robert Jarzmik (rjarzmik@free.fr)");
index 7edc1fb..f313eca 100644 (file)
@@ -201,18 +201,7 @@ static struct platform_driver palm27x_wm9712_driver = {
        },
 };
 
-static int __init palm27x_asoc_init(void)
-{
-       return platform_driver_register(&palm27x_wm9712_driver);
-}
-
-static void __exit palm27x_asoc_exit(void)
-{
-       platform_driver_unregister(&palm27x_wm9712_driver);
-}
-
-module_init(palm27x_asoc_init);
-module_exit(palm27x_asoc_exit);
+module_platform_driver(palm27x_wm9712_driver);
 
 /* Module information */
 MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
index 8ad93ee..a57cfbc 100644 (file)
@@ -771,7 +771,7 @@ static int pxa_ssp_remove(struct snd_soc_dai *dai)
                            SNDRV_PCM_FMTBIT_S24_LE |   \
                            SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops pxa_ssp_dai_ops = {
+static const struct snd_soc_dai_ops pxa_ssp_dai_ops = {
        .startup        = pxa_ssp_startup,
        .shutdown       = pxa_ssp_shutdown,
        .trigger        = pxa_ssp_trigger,
@@ -825,17 +825,7 @@ static struct platform_driver asoc_ssp_driver = {
        .remove = __devexit_p(asoc_ssp_remove),
 };
 
-static int __init pxa_ssp_init(void)
-{
-       return platform_driver_register(&asoc_ssp_driver);
-}
-module_init(pxa_ssp_init);
-
-static void __exit pxa_ssp_exit(void)
-{
-       platform_driver_unregister(&asoc_ssp_driver);
-}
-module_exit(pxa_ssp_exit);
+module_platform_driver(asoc_ssp_driver);
 
 /* Module information */
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
index ac51c6d..837ff34 100644 (file)
@@ -163,15 +163,15 @@ static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
                SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
                SNDRV_PCM_RATE_48000)
 
-static struct snd_soc_dai_ops pxa_ac97_hifi_dai_ops = {
+static const struct snd_soc_dai_ops pxa_ac97_hifi_dai_ops = {
        .hw_params      = pxa2xx_ac97_hw_params,
 };
 
-static struct snd_soc_dai_ops pxa_ac97_aux_dai_ops = {
+static const struct snd_soc_dai_ops pxa_ac97_aux_dai_ops = {
        .hw_params      = pxa2xx_ac97_hw_aux_params,
 };
 
-static struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = {
+static const struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = {
        .hw_params      = pxa2xx_ac97_hw_mic_params,
 };
 
@@ -263,17 +263,7 @@ static struct platform_driver pxa2xx_ac97_driver = {
        },
 };
 
-static int __init pxa_ac97_init(void)
-{
-       return platform_driver_register(&pxa2xx_ac97_driver);
-}
-module_init(pxa_ac97_init);
-
-static void __exit pxa_ac97_exit(void)
-{
-       platform_driver_unregister(&pxa2xx_ac97_driver);
-}
-module_exit(pxa_ac97_exit);
+module_platform_driver(pxa2xx_ac97_driver);
 
 MODULE_AUTHOR("Nicolas Pitre");
 MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
index 11be595..609abd5 100644 (file)
@@ -331,7 +331,7 @@ static int  pxa2xx_i2s_remove(struct snd_soc_dai *dai)
                SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
                SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
 
-static struct snd_soc_dai_ops pxa_i2s_dai_ops = {
+static const struct snd_soc_dai_ops pxa_i2s_dai_ops = {
        .startup        = pxa2xx_i2s_startup,
        .shutdown       = pxa2xx_i2s_shutdown,
        .trigger        = pxa2xx_i2s_trigger,
index 600676f..fdd6bed 100644 (file)
@@ -141,17 +141,7 @@ static struct platform_driver pxa_pcm_driver = {
        .remove = __devexit_p(pxa2xx_soc_platform_remove),
 };
 
-static int __init snd_pxa_pcm_init(void)
-{
-       return platform_driver_register(&pxa_pcm_driver);
-}
-module_init(snd_pxa_pcm_init);
-
-static void __exit snd_pxa_pcm_exit(void)
-{
-       platform_driver_unregister(&pxa_pcm_driver);
-}
-module_exit(snd_pxa_pcm_exit);
+module_platform_driver(pxa_pcm_driver);
 
 MODULE_AUTHOR("Nicolas Pitre");
 MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
index 3052f64..aaabdba 100644 (file)
@@ -409,7 +409,7 @@ static int s6000_i2s_dai_probe(struct snd_soc_dai *dai)
                         SNDRV_PCM_RATE_8000_192000)
 #define S6000_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-static struct snd_soc_dai_ops s6000_i2s_dai_ops = {
+static const struct snd_soc_dai_ops s6000_i2s_dai_ops = {
        .set_fmt = s6000_i2s_set_dai_fmt,
        .set_clkdiv = s6000_i2s_set_clkdiv,
        .hw_params = s6000_i2s_hw_params,
@@ -604,17 +604,7 @@ static struct platform_driver s6000_i2s_driver = {
        },
 };
 
-static int __init s6000_i2s_init(void)
-{
-       return platform_driver_register(&s6000_i2s_driver);
-}
-module_init(s6000_i2s_init);
-
-static void __exit s6000_i2s_exit(void)
-{
-       platform_driver_unregister(&s6000_i2s_driver);
-}
-module_exit(s6000_i2s_exit);
+module_platform_driver(s6000_i2s_driver);
 
 MODULE_AUTHOR("Daniel Gloeckner");
 MODULE_DESCRIPTION("Stretch s6000 family I2S SoC Interface");
index 55efc2b..43c014f 100644 (file)
@@ -520,17 +520,7 @@ static struct platform_driver s6000_pcm_driver = {
        .remove = __devexit_p(s6000_soc_platform_remove),
 };
 
-static int __init snd_s6000_pcm_init(void)
-{
-       return platform_driver_register(&s6000_pcm_driver);
-}
-module_init(snd_s6000_pcm_init);
-
-static void __exit snd_s6000_pcm_exit(void)
-{
-       platform_driver_unregister(&s6000_pcm_driver);
-}
-module_exit(snd_s6000_pcm_exit);
+module_platform_driver(s6000_pcm_driver);
 
 MODULE_AUTHOR("Daniel Gloeckner");
 MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module");
index 53aaa69..f3417f2 100644 (file)
@@ -193,8 +193,22 @@ config SND_SOC_SPEYSIDE
        select SND_SOC_WM9081
        select SND_SOC_WM1250_EV1
 
-config SND_SOC_SPEYSIDE_WM8962
-       tristate "Audio support for Wolfson Speyside with WM8962"
+config SND_SOC_TOBERMORY
+       tristate "Audio support for Wolfson Tobermory"
        depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410
        select SND_SAMSUNG_I2S
        select SND_SOC_WM8962
+
+config SND_SOC_LOWLAND
+       tristate "Audio support for Wolfson Lowland"
+       depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410
+       select SND_SAMSUNG_I2S
+       select SND_SOC_WM5100
+       select SND_SOC_WM9081
+
+config SND_SOC_LITTLEMILL
+       tristate "Audio support for Wolfson Littlemill"
+       depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410
+       select SND_SAMSUNG_I2S
+       select MFD_WM8994
+       select SND_SOC_WM8994
index 8509d3c..9d03beb 100644 (file)
@@ -39,7 +39,9 @@ snd-soc-smdk-spdif-objs := smdk_spdif.o
 snd-soc-smdk-wm8580pcm-objs := smdk_wm8580pcm.o
 snd-soc-smdk-wm8994pcm-objs := smdk_wm8994pcm.o
 snd-soc-speyside-objs := speyside.o
-snd-soc-speyside-wm8962-objs := speyside_wm8962.o
+snd-soc-tobermory-objs := tobermory.o
+snd-soc-lowland-objs := lowland.o
+snd-soc-littlemill-objs := littlemill.o
 
 obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o
 obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
@@ -60,4 +62,6 @@ obj-$(CONFIG_SND_SOC_GONI_AQUILA_WM8994) += snd-soc-goni-wm8994.o
 obj-$(CONFIG_SND_SOC_SMDK_WM8580_PCM) += snd-soc-smdk-wm8580pcm.o
 obj-$(CONFIG_SND_SOC_SMDK_WM8994_PCM) += snd-soc-smdk-wm8994pcm.o
 obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o
-obj-$(CONFIG_SND_SOC_SPEYSIDE_WM8962) += snd-soc-speyside-wm8962.o
+obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o
+obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o
+obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o
index 16521e3..7b9bf93 100644 (file)
@@ -329,12 +329,12 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_soc_dai_ops s3c_ac97_dai_ops = {
+static const struct snd_soc_dai_ops s3c_ac97_dai_ops = {
        .hw_params      = s3c_ac97_hw_params,
        .trigger        = s3c_ac97_trigger,
 };
 
-static struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = {
+static const struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = {
        .hw_params      = s3c_ac97_hw_mic_params,
        .trigger        = s3c_ac97_mic_trigger,
 };
@@ -509,17 +509,7 @@ static struct platform_driver s3c_ac97_driver = {
        },
 };
 
-static int __init s3c_ac97_init(void)
-{
-       return platform_driver_register(&s3c_ac97_driver);
-}
-module_init(s3c_ac97_init);
-
-static void __exit s3c_ac97_exit(void)
-{
-       platform_driver_unregister(&s3c_ac97_driver);
-}
-module_exit(s3c_ac97_exit);
+module_platform_driver(s3c_ac97_driver);
 
 MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
 MODULE_DESCRIPTION("AC97 driver for the Samsung SoC");
index a68b264..797c3d5 100644 (file)
@@ -458,17 +458,7 @@ static struct platform_driver asoc_dma_driver = {
        .remove = __devexit_p(samsung_asoc_platform_remove),
 };
 
-static int __init samsung_asoc_init(void)
-{
-       return platform_driver_register(&asoc_dma_driver);
-}
-module_init(samsung_asoc_init);
-
-static void __exit samsung_asoc_exit(void)
-{
-       platform_driver_unregister(&asoc_dma_driver);
-}
-module_exit(samsung_asoc_exit);
+module_platform_driver(asoc_dma_driver);
 
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("Samsung ASoC DMA Driver");
index bff42bf..ff5d919 100644 (file)
@@ -881,7 +881,7 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
                writel(CON_RSTCLR, i2s->addr + I2SCON);
 
        if (i2s->quirks & QUIRK_SEC_DAI)
-               idma_reg_addr_init((void *)i2s->addr,
+               idma_reg_addr_init(i2s->addr,
                                        i2s->sec_dai->idma_playback.dma_addr);
 
 probe_exit:
@@ -923,7 +923,7 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
        return 0;
 }
 
-static struct snd_soc_dai_ops samsung_i2s_dai_ops = {
+static const struct snd_soc_dai_ops samsung_i2s_dai_ops = {
        .trigger = i2s_trigger,
        .hw_params = i2s_hw_params,
        .set_fmt = i2s_set_fmt,
@@ -945,7 +945,7 @@ struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
 {
        struct i2s_dai *i2s;
 
-       i2s = kzalloc(sizeof(struct i2s_dai), GFP_KERNEL);
+       i2s = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dai), GFP_KERNEL);
        if (i2s == NULL)
                return NULL;
 
@@ -972,10 +972,8 @@ struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
                i2s->pdev = platform_device_register_resndata(NULL,
                                pdev->name, pdev->id + SAMSUNG_I2S_SECOFF,
                                NULL, 0, NULL, 0);
-               if (IS_ERR(i2s->pdev)) {
-                       kfree(i2s);
+               if (IS_ERR(i2s->pdev))
                        return NULL;
-               }
        }
 
        /* Pre-assign snd_soc_dai_set_drvdata */
@@ -1048,7 +1046,7 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
        if (!pri_dai) {
                dev_err(&pdev->dev, "Unable to alloc I2S_pri\n");
                ret = -ENOMEM;
-               goto err1;
+               goto err;
        }
 
        pri_dai->dma_playback.dma_addr = regs_base + I2STXD;
@@ -1073,7 +1071,7 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
                if (!sec_dai) {
                        dev_err(&pdev->dev, "Unable to alloc I2S_sec\n");
                        ret = -ENOMEM;
-                       goto err2;
+                       goto err;
                }
                sec_dai->dma_playback.dma_addr = regs_base + I2STXDS;
                sec_dai->dma_playback.client =
@@ -1092,17 +1090,13 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
        if (i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
                dev_err(&pdev->dev, "Unable to configure gpio\n");
                ret = -EINVAL;
-               goto err3;
+               goto err;
        }
 
        snd_soc_register_dai(&pri_dai->pdev->dev, &pri_dai->i2s_dai_drv);
 
        return 0;
-err3:
-       kfree(sec_dai);
-err2:
-       kfree(pri_dai);
-err1:
+err:
        release_mem_region(regs_base, resource_size(res));
 
        return ret;
@@ -1128,8 +1122,6 @@ static __devexit int samsung_i2s_remove(struct platform_device *pdev)
        i2s->pri_dai = NULL;
        i2s->sec_dai = NULL;
 
-       kfree(i2s);
-
        snd_soc_unregister_dai(&pdev->dev);
 
        return 0;
@@ -1144,17 +1136,7 @@ static struct platform_driver samsung_i2s_driver = {
        },
 };
 
-static int __init samsung_i2s_init(void)
-{
-       return platform_driver_register(&samsung_i2s_driver);
-}
-module_init(samsung_i2s_init);
-
-static void __exit samsung_i2s_exit(void)
-{
-       platform_driver_unregister(&samsung_i2s_driver);
-}
-module_exit(samsung_i2s_exit);
+module_platform_driver(samsung_i2s_driver);
 
 /* Module information */
 MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
index c41178e..baf97eb 100644 (file)
@@ -403,7 +403,7 @@ static int idma_new(struct snd_soc_pcm_runtime *rtd)
        return ret;
 }
 
-void idma_reg_addr_init(void *regs, dma_addr_t addr)
+void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr)
 {
        spin_lock_init(&idma.lock);
        idma.regs = regs;
@@ -437,17 +437,7 @@ static struct platform_driver asoc_idma_driver = {
        .remove = __devexit_p(asoc_idma_platform_remove),
 };
 
-static int __init asoc_idma_init(void)
-{
-       return platform_driver_register(&asoc_idma_driver);
-}
-module_init(asoc_idma_init);
-
-static void __exit asoc_idma_exit(void)
-{
-       platform_driver_unregister(&asoc_idma_driver);
-}
-module_exit(asoc_idma_exit);
+module_platform_driver(asoc_idma_driver);
 
 MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
 MODULE_DESCRIPTION("Samsung ASoC IDMA Driver");
index 4827321..8644946 100644 (file)
@@ -14,7 +14,7 @@
 #ifndef __SND_SOC_SAMSUNG_IDMA_H_
 #define __SND_SOC_SAMSUNG_IDMA_H_
 
-extern void idma_reg_addr_init(void *regs, dma_addr_t addr);
+extern void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr);
 
 /* dma_state */
 #define LPAM_DMA_STOP  0
index 1826acf..8e523fd 100644 (file)
@@ -101,7 +101,6 @@ static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_codec *codec = rtd->codec;
        struct snd_soc_dapm_context *dapm = &codec->dapm;
-       int err;
 
        /* These endpoints are not being used. */
        snd_soc_dapm_nc_pin(dapm, "LINPUT2");
@@ -131,7 +130,7 @@ static struct snd_soc_card snd_soc_machine_jive = {
        .dai_link       = &jive_dai,
        .num_links      = 1,
 
-       .dapm_widgtets  = wm8750_dapm_widgets,
+       .dapm_widgets   = wm8750_dapm_widgets,
        .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets),
        .dapm_routes    = audio_map,
        .num_dapm_routes = ARRAY_SIZE(audio_map),
diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
new file mode 100644 (file)
index 0000000..5cea59b
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Littlemill audio support
+ *
+ * Copyright 2011 Wolfson Microelectronics
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+
+#include "../codecs/wm8994.h"
+
+static int sample_rate = 44100;
+
+static int littlemill_set_bias_level(struct snd_soc_card *card,
+                                         struct snd_soc_dapm_context *dapm,
+                                         enum snd_soc_bias_level level)
+{
+       struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+       int ret;
+
+       if (dapm->dev != codec_dai->dev)
+               return 0;
+
+       switch (level) {
+       case SND_SOC_BIAS_PREPARE:
+               /*
+                * If we've not already clocked things via hw_params()
+                * then do so now, otherwise these are noops.
+                */
+               if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
+                       ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1,
+                                                 WM8994_FLL_SRC_MCLK2, 32768,
+                                                 sample_rate * 512);
+                       if (ret < 0) {
+                               pr_err("Failed to start FLL: %d\n", ret);
+                               return ret;
+                       }
+
+                       ret = snd_soc_dai_set_sysclk(codec_dai,
+                                                    WM8994_SYSCLK_FLL1,
+                                                    sample_rate * 512,
+                                                    SND_SOC_CLOCK_IN);
+                       if (ret < 0) {
+                               pr_err("Failed to set SYSCLK: %d\n", ret);
+                               return ret;
+                       }
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int littlemill_set_bias_level_post(struct snd_soc_card *card,
+                                              struct snd_soc_dapm_context *dapm,
+                                              enum snd_soc_bias_level level)
+{
+       struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+       int ret;
+
+       if (dapm->dev != codec_dai->dev)
+               return 0;
+
+       switch (level) {
+       case SND_SOC_BIAS_STANDBY:
+               ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK2,
+                                            32768, SND_SOC_CLOCK_IN);
+               if (ret < 0) {
+                       pr_err("Failed to switch away from FLL: %d\n", ret);
+                       return ret;
+               }
+
+               ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1,
+                                         0, 0, 0);
+               if (ret < 0) {
+                       pr_err("Failed to stop FLL: %d\n", ret);
+                       return ret;
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       dapm->bias_level = level;
+
+       return 0;
+}
+
+static int littlemill_hw_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       int ret;
+
+       sample_rate = params_rate(params);
+
+       ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1,
+                                 WM8994_FLL_SRC_MCLK2, 32768,
+                                 sample_rate * 512);
+       if (ret < 0) {
+               pr_err("Failed to start FLL: %d\n", ret);
+               return ret;
+       }
+
+       ret = snd_soc_dai_set_sysclk(codec_dai,
+                                    WM8994_SYSCLK_FLL1,
+                                    sample_rate * 512,
+                                    SND_SOC_CLOCK_IN);
+       if (ret < 0) {
+               pr_err("Failed to set SYSCLK: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static struct snd_soc_ops littlemill_ops = {
+       .hw_params = littlemill_hw_params,
+};
+
+static struct snd_soc_dai_link littlemill_dai[] = {
+       {
+               .name = "CPU",
+               .stream_name = "CPU",
+               .cpu_dai_name = "samsung-i2s.0",
+               .codec_dai_name = "wm8994-aif1",
+               .platform_name = "samsung-audio",
+               .codec_name = "wm8994-codec",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+                               | SND_SOC_DAIFMT_CBM_CFM,
+               .ops = &littlemill_ops,
+       },
+};
+
+static struct snd_soc_dapm_widget widgets[] = {
+       SND_SOC_DAPM_HP("Headphone", NULL),
+
+       SND_SOC_DAPM_MIC("AMIC", NULL),
+       SND_SOC_DAPM_MIC("DMIC", NULL),
+};
+
+static struct snd_soc_dapm_route audio_paths[] = {
+       { "Headphone", NULL, "HPOUT1L" },
+       { "Headphone", NULL, "HPOUT1R" },
+
+       { "AMIC", NULL, "MICBIAS1" },   /* Default for AMICBIAS jumper */
+       { "IN1LN", NULL, "AMIC" },
+
+       { "DMIC", NULL, "MICBIAS2" },   /* Default for DMICBIAS jumper */
+       { "DMIC1DAT", NULL, "DMIC" },
+       { "DMIC2DAT", NULL, "DMIC" },
+};
+
+static struct snd_soc_jack littlemill_headset;
+
+static int littlemill_late_probe(struct snd_soc_card *card)
+{
+       struct snd_soc_codec *codec = card->rtd[0].codec;
+       struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+       int ret;
+
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK2,
+                                    32768, SND_SOC_CLOCK_IN);
+       if (ret < 0)
+               return ret;
+
+       ret = snd_soc_jack_new(codec, "Headset",
+                              SND_JACK_HEADSET | SND_JACK_MECHANICAL |
+                              SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+                              SND_JACK_BTN_2 | SND_JACK_BTN_3 |
+                              SND_JACK_BTN_4 | SND_JACK_BTN_5,
+                              &littlemill_headset);
+       if (ret)
+               return ret;
+
+       /* This will check device compatibility itself */
+       wm8958_mic_detect(codec, &littlemill_headset, NULL, NULL);
+
+       return 0;
+}
+
+static struct snd_soc_card littlemill = {
+       .name = "Littlemill",
+       .dai_link = littlemill_dai,
+       .num_links = ARRAY_SIZE(littlemill_dai),
+
+       .set_bias_level = littlemill_set_bias_level,
+       .set_bias_level_post = littlemill_set_bias_level_post,
+
+       .dapm_widgets = widgets,
+       .num_dapm_widgets = ARRAY_SIZE(widgets),
+       .dapm_routes = audio_paths,
+       .num_dapm_routes = ARRAY_SIZE(audio_paths),
+
+       .late_probe = littlemill_late_probe,
+};
+
+static __devinit int littlemill_probe(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = &littlemill;
+       int ret;
+
+       card->dev = &pdev->dev;
+
+       ret = snd_soc_register_card(card);
+       if (ret) {
+               dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+                       ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int __devexit littlemill_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_card(card);
+
+       return 0;
+}
+
+static struct platform_driver littlemill_driver = {
+       .driver = {
+               .name = "littlemill",
+               .owner = THIS_MODULE,
+               .pm = &snd_soc_pm_ops,
+       },
+       .probe = littlemill_probe,
+       .remove = __devexit_p(littlemill_remove),
+};
+
+module_platform_driver(littlemill_driver);
+
+MODULE_DESCRIPTION("Littlemill audio support");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:littlemill");
diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c
new file mode 100644 (file)
index 0000000..4216a06
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Lowland audio support
+ *
+ * Copyright 2011 Wolfson Microelectronics
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+
+#include "../codecs/wm5100.h"
+#include "../codecs/wm9081.h"
+
+#define MCLK1_RATE (44100 * 512)
+#define CLKOUT_RATE (44100 * 256)
+
+static int lowland_hw_params(struct snd_pcm_substream *substream,
+                            struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       int ret;
+
+       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
+                                        | SND_SOC_DAIFMT_NB_NF
+                                        | SND_SOC_DAIFMT_CBM_CFM);
+       if (ret < 0)
+               return ret;
+
+       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
+                                        | SND_SOC_DAIFMT_NB_NF
+                                        | SND_SOC_DAIFMT_CBM_CFM);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static struct snd_soc_ops lowland_ops = {
+       .hw_params = lowland_hw_params,
+};
+
+static struct snd_soc_jack lowland_headset;
+
+/* Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin lowland_headset_pins[] = {
+       {
+               .pin = "Headphone",
+               .mask = SND_JACK_HEADPHONE | SND_JACK_LINEOUT,
+       },
+       {
+               .pin = "Headset Mic",
+               .mask = SND_JACK_MICROPHONE,
+       },
+};
+
+static int lowland_wm5100_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_codec *codec = rtd->codec;
+       int ret;
+
+       ret = snd_soc_codec_set_sysclk(codec, WM5100_CLK_SYSCLK,
+                                      WM5100_CLKSRC_MCLK1, MCLK1_RATE,
+                                      SND_SOC_CLOCK_IN);
+       if (ret < 0) {
+               pr_err("Failed to set SYSCLK clock source: %d\n", ret);
+               return ret;
+       }
+
+       /* Clock OPCLK, used by the other audio components. */
+       ret = snd_soc_codec_set_sysclk(codec, WM5100_CLK_OPCLK, 0,
+                                      CLKOUT_RATE, 0);
+       if (ret < 0) {
+               pr_err("Failed to set OPCLK rate: %d\n", ret);
+               return ret;
+       }
+
+       ret = snd_soc_jack_new(codec, "Headset",
+                              SND_JACK_LINEOUT | SND_JACK_HEADSET |
+                              SND_JACK_BTN_0,
+                              &lowland_headset);
+       if (ret)
+               return ret;
+
+       ret = snd_soc_jack_add_pins(&lowland_headset,
+                                   ARRAY_SIZE(lowland_headset_pins),
+                                   lowland_headset_pins);
+       if (ret)
+               return ret;
+
+       wm5100_detect(codec, &lowland_headset);
+
+       return 0;
+}
+
+static struct snd_soc_dai_link lowland_dai[] = {
+       {
+               .name = "CPU",
+               .stream_name = "CPU",
+               .cpu_dai_name = "samsung-i2s.0",
+               .codec_dai_name = "wm5100-aif1",
+               .platform_name = "samsung-audio",
+               .codec_name = "wm5100.1-001a",
+               .ops = &lowland_ops,
+               .init = lowland_wm5100_init,
+       },
+       {
+               .name = "Baseband",
+               .stream_name = "Baseband",
+               .cpu_dai_name = "wm5100-aif2",
+               .codec_dai_name = "wm1250-ev1",
+               .codec_name = "wm1250-ev1.1-0027",
+               .ops = &lowland_ops,
+               .ignore_suspend = 1,
+       },
+};
+
+static int lowland_wm9081_init(struct snd_soc_dapm_context *dapm)
+{
+       snd_soc_dapm_nc_pin(dapm, "LINEOUT");
+
+       /* At any time the WM9081 is active it will have this clock */
+       return snd_soc_codec_set_sysclk(dapm->codec, WM9081_SYSCLK_MCLK, 0,
+                                       CLKOUT_RATE, 0);
+}
+
+static struct snd_soc_aux_dev lowland_aux_dev[] = {
+       {
+               .name = "wm9081",
+               .codec_name = "wm9081.1-006c",
+               .init = lowland_wm9081_init,
+       },
+};
+
+static struct snd_soc_codec_conf lowland_codec_conf[] = {
+       {
+               .dev_name = "wm9081.1-006c",
+               .name_prefix = "Sub",
+       },
+};
+
+static const struct snd_kcontrol_new controls[] = {
+       SOC_DAPM_PIN_SWITCH("Main Speaker"),
+       SOC_DAPM_PIN_SWITCH("Main DMIC"),
+       SOC_DAPM_PIN_SWITCH("Main AMIC"),
+       SOC_DAPM_PIN_SWITCH("WM1250 Input"),
+       SOC_DAPM_PIN_SWITCH("WM1250 Output"),
+       SOC_DAPM_PIN_SWITCH("Headphone"),
+};
+
+static struct snd_soc_dapm_widget widgets[] = {
+       SND_SOC_DAPM_HP("Headphone", NULL),
+       SND_SOC_DAPM_MIC("Headset Mic", NULL),
+
+       SND_SOC_DAPM_SPK("Main Speaker", NULL),
+
+       SND_SOC_DAPM_MIC("Main AMIC", NULL),
+       SND_SOC_DAPM_MIC("Main DMIC", NULL),
+};
+
+static struct snd_soc_dapm_route audio_paths[] = {
+       { "Sub IN1", NULL, "HPOUT2L" },
+       { "Sub IN2", NULL, "HPOUT2R" },
+
+       { "Main Speaker", NULL, "Sub SPKN" },
+       { "Main Speaker", NULL, "Sub SPKP" },
+       { "Main Speaker", NULL, "SPKDAT1" },
+};
+
+static struct snd_soc_card lowland = {
+       .name = "Lowland",
+       .dai_link = lowland_dai,
+       .num_links = ARRAY_SIZE(lowland_dai),
+       .aux_dev = lowland_aux_dev,
+       .num_aux_devs = ARRAY_SIZE(lowland_aux_dev),
+       .codec_conf = lowland_codec_conf,
+       .num_configs = ARRAY_SIZE(lowland_codec_conf),
+
+       .controls = controls,
+       .num_controls = ARRAY_SIZE(controls),
+       .dapm_widgets = widgets,
+       .num_dapm_widgets = ARRAY_SIZE(widgets),
+       .dapm_routes = audio_paths,
+       .num_dapm_routes = ARRAY_SIZE(audio_paths),
+};
+
+static __devinit int lowland_probe(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = &lowland;
+       int ret;
+
+       card->dev = &pdev->dev;
+
+       ret = snd_soc_register_card(card);
+       if (ret) {
+               dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+                       ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int __devexit lowland_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_card(card);
+
+       return 0;
+}
+
+static struct platform_driver lowland_driver = {
+       .driver = {
+               .name = "lowland",
+               .owner = THIS_MODULE,
+               .pm = &snd_soc_pm_ops,
+       },
+       .probe = lowland_probe,
+       .remove = __devexit_p(lowland_remove),
+};
+
+module_platform_driver(lowland_driver);
+
+MODULE_DESCRIPTION("Lowland audio support");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lowland");
index 05a47cf..beef63f 100644 (file)
@@ -452,7 +452,7 @@ static int s3c_pcm_set_sysclk(struct snd_soc_dai *cpu_dai,
        return 0;
 }
 
-static struct snd_soc_dai_ops s3c_pcm_dai_ops = {
+static const struct snd_soc_dai_ops s3c_pcm_dai_ops = {
        .set_sysclk     = s3c_pcm_set_sysclk,
        .set_clkdiv     = s3c_pcm_set_clkdiv,
        .trigger        = s3c_pcm_trigger,
@@ -632,17 +632,7 @@ static struct platform_driver s3c_pcm_driver = {
        },
 };
 
-static int __init s3c_pcm_init(void)
-{
-       return platform_driver_register(&s3c_pcm_driver);
-}
-module_init(s3c_pcm_init);
-
-static void __exit s3c_pcm_exit(void)
-{
-       platform_driver_unregister(&s3c_pcm_driver);
-}
-module_exit(s3c_pcm_exit);
+module_platform_driver(s3c_pcm_driver);
 
 /* Module information */
 MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
index 7bbec25..7218507 100644 (file)
@@ -142,7 +142,7 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
        SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
        SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
 
-static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = {
+static const struct snd_soc_dai_ops s3c2412_i2s_dai_ops = {
        .hw_params      = s3c2412_i2s_hw_params,
 };
 
@@ -184,17 +184,7 @@ static struct platform_driver s3c2412_iis_driver = {
        },
 };
 
-static int __init s3c2412_i2s_init(void)
-{
-       return platform_driver_register(&s3c2412_iis_driver);
-}
-module_init(s3c2412_i2s_init);
-
-static void __exit s3c2412_i2s_exit(void)
-{
-       platform_driver_unregister(&s3c2412_iis_driver);
-}
-module_exit(s3c2412_i2s_exit);
+module_platform_driver(s3c2412_iis_driver);
 
 /* Module information */
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
index 558c64b..c4aa4d4 100644 (file)
@@ -444,7 +444,7 @@ static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai)
        SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
        SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
 
-static struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {
+static const struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {
        .trigger        = s3c24xx_i2s_trigger,
        .hw_params      = s3c24xx_i2s_hw_params,
        .set_fmt        = s3c24xx_i2s_set_fmt,
@@ -489,17 +489,7 @@ static struct platform_driver s3c24xx_iis_driver = {
        },
 };
 
-static int __init s3c24xx_i2s_init(void)
-{
-       return platform_driver_register(&s3c24xx_iis_driver);
-}
-module_init(s3c24xx_i2s_init);
-
-static void __exit s3c24xx_i2s_exit(void)
-{
-       platform_driver_unregister(&s3c24xx_iis_driver);
-}
-module_exit(s3c24xx_i2s_exit);
+module_platform_driver(s3c24xx_iis_driver);
 
 /* Module information */
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
index d125e79..5027981 100644 (file)
@@ -114,21 +114,9 @@ static struct platform_driver simtec_audio_hermes_platdrv = {
        .remove = __devexit_p(simtec_audio_remove),
 };
 
-MODULE_ALIAS("platform:s3c24xx-simtec-hermes-snd");
-
-static int __init simtec_hermes_modinit(void)
-{
-       return platform_driver_register(&simtec_audio_hermes_platdrv);
-}
-
-static void __exit simtec_hermes_modexit(void)
-{
-       platform_driver_unregister(&simtec_audio_hermes_platdrv);
-}
-
-module_init(simtec_hermes_modinit);
-module_exit(simtec_hermes_modexit);
+module_platform_driver(simtec_audio_hermes_platdrv);
 
+MODULE_ALIAS("platform:s3c24xx-simtec-hermes-snd");
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("ALSA SoC Simtec Audio support");
 MODULE_LICENSE("GPL");
index 5e4fd46..89b57b5 100644 (file)
@@ -92,7 +92,7 @@ static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd)
        return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic23);
 }
 
-static struct platform_driver simtec_audio_tlv320aic23_platdrv = {
+static struct platform_driver simtec_audio_tlv320aic23_driver = {
        .driver = {
                .owner  = THIS_MODULE,
                .name   = "s3c24xx-simtec-tlv320aic23",
@@ -102,21 +102,9 @@ static struct platform_driver simtec_audio_tlv320aic23_platdrv = {
        .remove = __devexit_p(simtec_audio_remove),
 };
 
-MODULE_ALIAS("platform:s3c24xx-simtec-tlv320aic23");
-
-static int __init simtec_tlv320aic23_modinit(void)
-{
-       return platform_driver_register(&simtec_audio_tlv320aic23_platdrv);
-}
-
-static void __exit simtec_tlv320aic23_modexit(void)
-{
-       platform_driver_unregister(&simtec_audio_tlv320aic23_platdrv);
-}
-
-module_init(simtec_tlv320aic23_modinit);
-module_exit(simtec_tlv320aic23_modexit);
+module_platform_driver(simtec_audio_tlv320aic23_driver);
 
+MODULE_ALIAS("platform:s3c24xx-simtec-tlv320aic23");
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("ALSA SoC Simtec Audio support");
 MODULE_LICENSE("GPL");
index 548c6ac..62b69fb 100644 (file)
@@ -343,19 +343,7 @@ static struct platform_driver s3c24xx_uda134x_driver = {
        },
 };
 
-static int __init s3c24xx_uda134x_init(void)
-{
-       return platform_driver_register(&s3c24xx_uda134x_driver);
-}
-
-static void __exit s3c24xx_uda134x_exit(void)
-{
-       platform_driver_unregister(&s3c24xx_uda134x_driver);
-}
-
-
-module_init(s3c24xx_uda134x_init);
-module_exit(s3c24xx_uda134x_exit);
+module_platform_driver(s3c24xx_uda134x_driver);
 
 MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
 MODULE_DESCRIPTION("S3C24XX_UDA134X ALSA SoC audio driver");
index 3a0dbfc..8bd1dc5 100644 (file)
@@ -12,6 +12,7 @@
  *
  */
 
+#include <linux/module.h>
 #include <sound/soc.h>
 
 static struct snd_soc_card smdk2443;
index 0677473..49dfafb 100644 (file)
@@ -188,19 +188,7 @@ static struct platform_driver snd_smdk_driver = {
        .remove = __devexit_p(snd_smdk_remove),
 };
 
-static int __init smdk_audio_init(void)
-{
-       return platform_driver_register(&snd_smdk_driver);
-}
-
-module_init(smdk_audio_init);
-
-static void __exit smdk_audio_exit(void)
-{
-       platform_driver_unregister(&snd_smdk_driver);
-}
-
-module_exit(smdk_audio_exit);
+module_platform_driver(snd_smdk_driver);
 
 MODULE_AUTHOR("Sangbeom Kim, <sbkim73@samsung.com>");
 MODULE_DESCRIPTION("ALSA SoC SMDK WM8580 for PCM");
index f75e439..ad9ac42 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "../codecs/wm8994.h"
 #include <sound/pcm_params.h>
+#include <linux/module.h>
 
  /*
   * Default CFG switch settings to use this driver:
index da9c2a2..23c7fb7 100644 (file)
@@ -158,19 +158,7 @@ static struct platform_driver snd_smdk_driver = {
        .remove = __devexit_p(snd_smdk_remove),
 };
 
-static int __init smdk_audio_init(void)
-{
-       return platform_driver_register(&snd_smdk_driver);
-}
-
-module_init(smdk_audio_init);
-
-static void __exit smdk_audio_exit(void)
-{
-       platform_driver_unregister(&snd_smdk_driver);
-}
-
-module_exit(smdk_audio_exit);
+module_platform_driver(snd_smdk_driver);
 
 MODULE_AUTHOR("Sangbeom Kim, <sbkim73@samsung.com>");
 MODULE_DESCRIPTION("ALSA SoC SMDK WM8994 for PCM");
index 468cff1..a5a56a1 100644 (file)
@@ -334,7 +334,7 @@ static int spdif_resume(struct snd_soc_dai *cpu_dai)
 #define spdif_resume NULL
 #endif
 
-static struct snd_soc_dai_ops spdif_dai_ops = {
+static const struct snd_soc_dai_ops spdif_dai_ops = {
        .set_sysclk     = spdif_set_sysclk,
        .trigger        = spdif_trigger,
        .hw_params      = spdif_hw_params,
@@ -483,17 +483,7 @@ static struct platform_driver samsung_spdif_driver = {
        },
 };
 
-static int __init spdif_init(void)
-{
-       return platform_driver_register(&samsung_spdif_driver);
-}
-module_init(spdif_init);
-
-static void __exit spdif_exit(void)
-{
-       platform_driver_unregister(&samsung_spdif_driver);
-}
-module_exit(spdif_exit);
+module_platform_driver(samsung_spdif_driver);
 
 MODULE_AUTHOR("Seungwhan Youn, <sw.youn@samsung.com>");
 MODULE_DESCRIPTION("Samsung S/PDIF Controller Driver");
index 85bf541..0222d86 100644 (file)
@@ -19,6 +19,7 @@
 #include "../codecs/wm9081.h"
 
 #define WM8996_HPSEL_GPIO 214
+#define MCLK_AUDIO_RATE (512 * 48000)
 
 static int speyside_set_bias_level(struct snd_soc_card *card,
                                   struct snd_soc_dapm_context *dapm,
@@ -67,7 +68,7 @@ static int speyside_set_bias_level_post(struct snd_soc_card *card,
                if (card->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
                        ret = snd_soc_dai_set_pll(codec_dai, 0,
                                                  WM8996_FLL_MCLK2,
-                                                 32768, 48000 * 256);
+                                                 32768, MCLK_AUDIO_RATE);
                        if (ret < 0) {
                                pr_err("Failed to start FLL\n");
                                return ret;
@@ -75,7 +76,7 @@ static int speyside_set_bias_level_post(struct snd_soc_card *card,
 
                        ret = snd_soc_dai_set_sysclk(codec_dai,
                                                     WM8996_SYSCLK_FLL,
-                                                    48000 * 256,
+                                                    MCLK_AUDIO_RATE,
                                                     SND_SOC_CLOCK_IN);
                        if (ret < 0)
                                return ret;
@@ -191,7 +192,7 @@ static int speyside_late_probe(struct snd_soc_card *card)
        snd_soc_dapm_ignore_suspend(&card->dapm, "Headset Mic");
        snd_soc_dapm_ignore_suspend(&card->dapm, "Main AMIC");
        snd_soc_dapm_ignore_suspend(&card->dapm, "Main DMIC");
-       snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");
+       snd_soc_dapm_ignore_suspend(&card->dapm, "Main Speaker");
        snd_soc_dapm_ignore_suspend(&card->dapm, "WM1250 Output");
        snd_soc_dapm_ignore_suspend(&card->dapm, "WM1250 Input");
 
@@ -222,11 +223,9 @@ static struct snd_soc_dai_link speyside_dai[] = {
 
 static int speyside_wm9081_init(struct snd_soc_dapm_context *dapm)
 {
-       snd_soc_dapm_nc_pin(dapm, "LINEOUT");
-
        /* At any time the WM9081 is active it will have this clock */
        return snd_soc_codec_set_sysclk(dapm->codec, WM9081_SYSCLK_MCLK, 0,
-                                       48000 * 256, 0);
+                                       MCLK_AUDIO_RATE, 0);
 }
 
 static struct snd_soc_aux_dev speyside_aux_dev[] = {
@@ -308,6 +307,7 @@ static struct snd_soc_card speyside = {
        .num_dapm_widgets = ARRAY_SIZE(widgets),
        .dapm_routes = audio_paths,
        .num_dapm_routes = ARRAY_SIZE(audio_paths),
+       .fully_routed = true,
 
        .late_probe = speyside_late_probe,
 };
@@ -348,17 +348,7 @@ static struct platform_driver speyside_driver = {
        .remove = __devexit_p(speyside_remove),
 };
 
-static int __init speyside_audio_init(void)
-{
-       return platform_driver_register(&speyside_driver);
-}
-module_init(speyside_audio_init);
-
-static void __exit speyside_audio_exit(void)
-{
-       platform_driver_unregister(&speyside_driver);
-}
-module_exit(speyside_audio_exit);
+module_platform_driver(speyside_driver);
 
 MODULE_DESCRIPTION("Speyside audio support");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/samsung/speyside_wm8962.c b/sound/soc/samsung/speyside_wm8962.c
deleted file mode 100644 (file)
index e3e2716..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Speyside with WM8962 audio support
- *
- * Copyright 2011 Wolfson Microelectronics
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <sound/jack.h>
-#include <linux/gpio.h>
-#include <linux/module.h>
-
-#include "../codecs/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)
-{
-       struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
-       int ret;
-
-       if (dapm->dev != codec_dai->dev)
-               return 0;
-
-       switch (level) {
-       case SND_SOC_BIAS_PREPARE:
-               if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
-                       ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL,
-                                                 WM8962_FLL_MCLK, 32768,
-                                                 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,
-                                                    sample_rate * 512,
-                                                    SND_SOC_CLOCK_IN);
-                       if (ret < 0) {
-                               pr_err("Failed to set SYSCLK: %d\n", ret);
-                               return ret;
-                       }
-               }
-               break;
-
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-static int speyside_wm8962_set_bias_level_post(struct snd_soc_card *card,
-                                              struct snd_soc_dapm_context *dapm,
-                                              enum snd_soc_bias_level level)
-{
-       struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
-       int ret;
-
-       if (dapm->dev != codec_dai->dev)
-               return 0;
-
-       switch (level) {
-       case SND_SOC_BIAS_STANDBY:
-               ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK,
-                                            32768, SND_SOC_CLOCK_IN);
-               if (ret < 0) {
-                       pr_err("Failed to switch away from FLL: %d\n", ret);
-                       return ret;
-               }
-
-               ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL,
-                                         0, 0, 0);
-               if (ret < 0) {
-                       pr_err("Failed to stop FLL: %d\n", ret);
-                       return ret;
-               }
-               break;
-
-       default:
-               break;
-       }
-
-       dapm->bias_level = level;
-
-       return 0;
-}
-
-static int speyside_wm8962_hw_params(struct snd_pcm_substream *substream,
-                             struct snd_pcm_hw_params *params)
-{
-       sample_rate = params_rate(params);
-
-       return 0;
-}
-
-static struct snd_soc_ops speyside_wm8962_ops = {
-       .hw_params = speyside_wm8962_hw_params,
-};
-
-static struct snd_soc_dai_link speyside_wm8962_dai[] = {
-       {
-               .name = "CPU",
-               .stream_name = "CPU",
-               .cpu_dai_name = "samsung-i2s.0",
-               .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[] = {
-       SND_SOC_DAPM_HP("Headphone", NULL),
-       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),
-};
-
-static struct snd_soc_dapm_route audio_paths[] = {
-       { "Headphone", NULL, "HPOUTL" },
-       { "Headphone", NULL, "HPOUTR" },
-
-       { "Main Speaker", NULL, "SPKOUTL" },
-       { "Main Speaker", NULL, "SPKOUTR" },
-
-       { "Headset Mic", NULL, "MICBIAS" },
-       { "IN4L", NULL, "Headset Mic" },
-       { "IN4R", NULL, "Headset Mic" },
-
-       { "AMIC", NULL, "MICBIAS" },
-       { "IN1L", NULL, "AMIC" },
-       { "IN1R", NULL, "AMIC" },
-
-       { "DMIC", NULL, "MICBIAS" },
-       { "DMICDAT", NULL, "DMIC" },
-};
-
-static struct snd_soc_jack speyside_wm8962_headset;
-
-/* Headset jack detection DAPM pins */
-static struct snd_soc_jack_pin speyside_wm8962_headset_pins[] = {
-       {
-               .pin = "Headset Mic",
-               .mask = SND_JACK_MICROPHONE,
-       },
-       {
-               .pin = "Headphone",
-               .mask = SND_JACK_MICROPHONE,
-       },
-};
-
-static int speyside_wm8962_late_probe(struct snd_soc_card *card)
-{
-       struct snd_soc_codec *codec = card->rtd[0].codec;
-       struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
-       int ret;
-
-       ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK,
-                                    32768, SND_SOC_CLOCK_IN);
-       if (ret < 0)
-               return ret;
-
-       ret = snd_soc_jack_new(codec, "Headset",
-                              SND_JACK_HEADSET | SND_JACK_BTN_0,
-                              &speyside_wm8962_headset);
-       if (ret)
-               return ret;
-
-       ret = snd_soc_jack_add_pins(&speyside_wm8962_headset,
-                                   ARRAY_SIZE(speyside_wm8962_headset_pins),
-                                   speyside_wm8962_headset_pins);
-       if (ret)
-               return ret;
-
-       wm8962_mic_detect(codec, &speyside_wm8962_headset);
-
-       return 0;
-}
-
-static struct snd_soc_card speyside_wm8962 = {
-       .name = "Speyside WM8962",
-       .dai_link = speyside_wm8962_dai,
-       .num_links = ARRAY_SIZE(speyside_wm8962_dai),
-
-       .set_bias_level = speyside_wm8962_set_bias_level,
-       .set_bias_level_post = speyside_wm8962_set_bias_level_post,
-
-       .controls = controls,
-       .num_controls = ARRAY_SIZE(controls),
-       .dapm_widgets = widgets,
-       .num_dapm_widgets = ARRAY_SIZE(widgets),
-       .dapm_routes = audio_paths,
-       .num_dapm_routes = ARRAY_SIZE(audio_paths),
-
-       .late_probe = speyside_wm8962_late_probe,
-};
-
-static __devinit int speyside_wm8962_probe(struct platform_device *pdev)
-{
-       struct snd_soc_card *card = &speyside_wm8962;
-       int ret;
-
-       card->dev = &pdev->dev;
-
-       ret = snd_soc_register_card(card);
-       if (ret) {
-               dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
-                       ret);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int __devexit speyside_wm8962_remove(struct platform_device *pdev)
-{
-       struct snd_soc_card *card = platform_get_drvdata(pdev);
-
-       snd_soc_unregister_card(card);
-
-       return 0;
-}
-
-static struct platform_driver speyside_wm8962_driver = {
-       .driver = {
-               .name = "speyside-wm8962",
-               .owner = THIS_MODULE,
-               .pm = &snd_soc_pm_ops,
-       },
-       .probe = speyside_wm8962_probe,
-       .remove = __devexit_p(speyside_wm8962_remove),
-};
-
-static int __init speyside_wm8962_audio_init(void)
-{
-       return platform_driver_register(&speyside_wm8962_driver);
-}
-module_init(speyside_wm8962_audio_init);
-
-static void __exit speyside_wm8962_audio_exit(void)
-{
-       platform_driver_unregister(&speyside_wm8962_driver);
-}
-module_exit(speyside_wm8962_audio_exit);
-
-MODULE_DESCRIPTION("Speyside WM8962 audio support");
-MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:speyside-wm8962");
diff --git a/sound/soc/samsung/tobermory.c b/sound/soc/samsung/tobermory.c
new file mode 100644 (file)
index 0000000..6f91c65
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * Tobermory audio support
+ *
+ * Copyright 2011 Wolfson Microelectronics
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+
+#include "../codecs/wm8962.h"
+
+static int sample_rate = 44100;
+
+static int tobermory_set_bias_level(struct snd_soc_card *card,
+                                         struct snd_soc_dapm_context *dapm,
+                                         enum snd_soc_bias_level level)
+{
+       struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+       int ret;
+
+       if (dapm->dev != codec_dai->dev)
+               return 0;
+
+       switch (level) {
+       case SND_SOC_BIAS_PREPARE:
+               if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
+                       ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL,
+                                                 WM8962_FLL_MCLK, 32768,
+                                                 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,
+                                                    sample_rate * 512,
+                                                    SND_SOC_CLOCK_IN);
+                       if (ret < 0) {
+                               pr_err("Failed to set SYSCLK: %d\n", ret);
+                               return ret;
+                       }
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int tobermory_set_bias_level_post(struct snd_soc_card *card,
+                                              struct snd_soc_dapm_context *dapm,
+                                              enum snd_soc_bias_level level)
+{
+       struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+       int ret;
+
+       if (dapm->dev != codec_dai->dev)
+               return 0;
+
+       switch (level) {
+       case SND_SOC_BIAS_STANDBY:
+               ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK,
+                                            32768, SND_SOC_CLOCK_IN);
+               if (ret < 0) {
+                       pr_err("Failed to switch away from FLL: %d\n", ret);
+                       return ret;
+               }
+
+               ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL,
+                                         0, 0, 0);
+               if (ret < 0) {
+                       pr_err("Failed to stop FLL: %d\n", ret);
+                       return ret;
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       dapm->bias_level = level;
+
+       return 0;
+}
+
+static int tobermory_hw_params(struct snd_pcm_substream *substream,
+                             struct snd_pcm_hw_params *params)
+{
+       sample_rate = params_rate(params);
+
+       return 0;
+}
+
+static struct snd_soc_ops tobermory_ops = {
+       .hw_params = tobermory_hw_params,
+};
+
+static struct snd_soc_dai_link tobermory_dai[] = {
+       {
+               .name = "CPU",
+               .stream_name = "CPU",
+               .cpu_dai_name = "samsung-i2s.0",
+               .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 = &tobermory_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[] = {
+       SND_SOC_DAPM_HP("Headphone", NULL),
+       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),
+};
+
+static struct snd_soc_dapm_route audio_paths[] = {
+       { "Headphone", NULL, "HPOUTL" },
+       { "Headphone", NULL, "HPOUTR" },
+
+       { "Main Speaker", NULL, "SPKOUTL" },
+       { "Main Speaker", NULL, "SPKOUTR" },
+
+       { "Headset Mic", NULL, "MICBIAS" },
+       { "IN4L", NULL, "Headset Mic" },
+       { "IN4R", NULL, "Headset Mic" },
+
+       { "AMIC", NULL, "MICBIAS" },
+       { "IN1L", NULL, "AMIC" },
+       { "IN1R", NULL, "AMIC" },
+
+       { "DMIC", NULL, "MICBIAS" },
+       { "DMICDAT", NULL, "DMIC" },
+};
+
+static struct snd_soc_jack tobermory_headset;
+
+/* Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin tobermory_headset_pins[] = {
+       {
+               .pin = "Headset Mic",
+               .mask = SND_JACK_MICROPHONE,
+       },
+       {
+               .pin = "Headphone",
+               .mask = SND_JACK_MICROPHONE,
+       },
+};
+
+static int tobermory_late_probe(struct snd_soc_card *card)
+{
+       struct snd_soc_codec *codec = card->rtd[0].codec;
+       struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+       int ret;
+
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8962_SYSCLK_MCLK,
+                                    32768, SND_SOC_CLOCK_IN);
+       if (ret < 0)
+               return ret;
+
+       ret = snd_soc_jack_new(codec, "Headset",
+                              SND_JACK_HEADSET | SND_JACK_BTN_0,
+                              &tobermory_headset);
+       if (ret)
+               return ret;
+
+       ret = snd_soc_jack_add_pins(&tobermory_headset,
+                                   ARRAY_SIZE(tobermory_headset_pins),
+                                   tobermory_headset_pins);
+       if (ret)
+               return ret;
+
+       wm8962_mic_detect(codec, &tobermory_headset);
+
+       return 0;
+}
+
+static struct snd_soc_card tobermory = {
+       .name = "Tobermory",
+       .dai_link = tobermory_dai,
+       .num_links = ARRAY_SIZE(tobermory_dai),
+
+       .set_bias_level = tobermory_set_bias_level,
+       .set_bias_level_post = tobermory_set_bias_level_post,
+
+       .controls = controls,
+       .num_controls = ARRAY_SIZE(controls),
+       .dapm_widgets = widgets,
+       .num_dapm_widgets = ARRAY_SIZE(widgets),
+       .dapm_routes = audio_paths,
+       .num_dapm_routes = ARRAY_SIZE(audio_paths),
+       .fully_routed = true,
+
+       .late_probe = tobermory_late_probe,
+};
+
+static __devinit int tobermory_probe(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = &tobermory;
+       int ret;
+
+       card->dev = &pdev->dev;
+
+       ret = snd_soc_register_card(card);
+       if (ret) {
+               dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+                       ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int __devexit tobermory_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_card(card);
+
+       return 0;
+}
+
+static struct platform_driver tobermory_driver = {
+       .driver = {
+               .name = "tobermory",
+               .owner = THIS_MODULE,
+               .pm = &snd_soc_pm_ops,
+       },
+       .probe = tobermory_probe,
+       .remove = __devexit_p(tobermory_remove),
+};
+
+module_platform_driver(tobermory_driver);
+
+MODULE_DESCRIPTION("Tobermory audio support");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:tobermory");
index db74005..7da2018 100644 (file)
@@ -369,17 +369,7 @@ static struct platform_driver sh7760_pcm_driver = {
        .remove = __devexit_p(sh7760_soc_platform_remove),
 };
 
-static int __init snd_sh7760_pcm_init(void)
-{
-       return platform_driver_register(&sh7760_pcm_driver);
-}
-module_init(snd_sh7760_pcm_init);
-
-static void __exit snd_sh7760_pcm_exit(void)
-{
-       platform_driver_unregister(&sh7760_pcm_driver);
-}
-module_exit(snd_sh7760_pcm_exit);
+module_platform_driver(sh7760_pcm_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver");
index dff64b9..eb52778 100644 (file)
@@ -58,27 +58,23 @@ static struct platform_device *fsi_snd_device;
 static int fsi_ak4642_probe(struct platform_device *pdev)
 {
        int ret = -ENOMEM;
-       const struct platform_device_id *id_entry;
-       struct fsi_ak4642_data *pdata;
+       struct fsi_ak4642_info *pinfo = pdev->dev.platform_data;
 
-       id_entry = pdev->id_entry;
-       if (!id_entry) {
-               dev_err(&pdev->dev, "unknown fsi ak4642\n");
-               return -ENODEV;
+       if (!pinfo) {
+               dev_err(&pdev->dev, "no info for fsi ak4642\n");
+               goto out;
        }
 
-       pdata = (struct fsi_ak4642_data *)id_entry->driver_data;
-
-       fsi_snd_device = platform_device_alloc("soc-audio", pdata->id);
+       fsi_snd_device = platform_device_alloc("soc-audio", pinfo->id);
        if (!fsi_snd_device)
                goto out;
 
-       fsi_dai_link.name               = pdata->name;
-       fsi_dai_link.stream_name        = pdata->name;
-       fsi_dai_link.cpu_dai_name       = pdata->cpu_dai;
-       fsi_dai_link.platform_name      = pdata->platform;
-       fsi_dai_link.codec_name         = pdata->codec;
-       fsi_soc_card.name               = pdata->card;
+       fsi_dai_link.name               = pinfo->name;
+       fsi_dai_link.stream_name        = pinfo->name;
+       fsi_dai_link.cpu_dai_name       = pinfo->cpu_dai;
+       fsi_dai_link.platform_name      = pinfo->platform;
+       fsi_dai_link.codec_name         = pinfo->codec;
+       fsi_soc_card.name               = pinfo->card;
 
        platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
        ret = platform_device_add(fsi_snd_device);
@@ -96,114 +92,15 @@ static int fsi_ak4642_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct fsi_ak4642_data fsi_a_ak4642 = {
-       .name           = "AK4642",
-       .card           = "FSIA-AK4642",
-       .cpu_dai        = "fsia-dai",
-       .codec          = "ak4642-codec.0-0012",
-       .platform       = "sh_fsi.0",
-       .id             = FSI_PORT_A,
-};
-
-static struct fsi_ak4642_data fsi_b_ak4642 = {
-       .name           = "AK4642",
-       .card           = "FSIB-AK4642",
-       .cpu_dai        = "fsib-dai",
-       .codec          = "ak4642-codec.0-0012",
-       .platform       = "sh_fsi.0",
-       .id             = FSI_PORT_B,
-};
-
-static struct fsi_ak4642_data fsi_a_ak4643 = {
-       .name           = "AK4643",
-       .card           = "FSIA-AK4643",
-       .cpu_dai        = "fsia-dai",
-       .codec          = "ak4642-codec.0-0013",
-       .platform       = "sh_fsi.0",
-       .id             = FSI_PORT_A,
-};
-
-static struct fsi_ak4642_data fsi_b_ak4643 = {
-       .name           = "AK4643",
-       .card           = "FSIB-AK4643",
-       .cpu_dai        = "fsib-dai",
-       .codec          = "ak4642-codec.0-0013",
-       .platform       = "sh_fsi.0",
-       .id             = FSI_PORT_B,
-};
-
-static struct fsi_ak4642_data fsi2_a_ak4642 = {
-       .name           = "AK4642",
-       .card           = "FSI2A-AK4642",
-       .cpu_dai        = "fsia-dai",
-       .codec          = "ak4642-codec.0-0012",
-       .platform       = "sh_fsi2",
-       .id             = FSI_PORT_A,
-};
-
-static struct fsi_ak4642_data fsi2_b_ak4642 = {
-       .name           = "AK4642",
-       .card           = "FSI2B-AK4642",
-       .cpu_dai        = "fsib-dai",
-       .codec          = "ak4642-codec.0-0012",
-       .platform       = "sh_fsi2",
-       .id             = FSI_PORT_B,
-};
-
-static struct fsi_ak4642_data fsi2_a_ak4643 = {
-       .name           = "AK4643",
-       .card           = "FSI2A-AK4643",
-       .cpu_dai        = "fsia-dai",
-       .codec          = "ak4642-codec.0-0013",
-       .platform       = "sh_fsi2",
-       .id             = FSI_PORT_A,
-};
-
-static struct fsi_ak4642_data fsi2_b_ak4643 = {
-       .name           = "AK4643",
-       .card           = "FSI2B-AK4643",
-       .cpu_dai        = "fsib-dai",
-       .codec          = "ak4642-codec.0-0013",
-       .platform       = "sh_fsi2",
-       .id             = FSI_PORT_B,
-};
-
-static struct platform_device_id fsi_id_table[] = {
-       /* FSI */
-       { "sh_fsi_a_ak4642",    (kernel_ulong_t)&fsi_a_ak4642 },
-       { "sh_fsi_b_ak4642",    (kernel_ulong_t)&fsi_b_ak4642 },
-       { "sh_fsi_a_ak4643",    (kernel_ulong_t)&fsi_a_ak4643 },
-       { "sh_fsi_b_ak4643",    (kernel_ulong_t)&fsi_b_ak4643 },
-
-       /* FSI 2 */
-       { "sh_fsi2_a_ak4642",   (kernel_ulong_t)&fsi2_a_ak4642 },
-       { "sh_fsi2_b_ak4642",   (kernel_ulong_t)&fsi2_b_ak4642 },
-       { "sh_fsi2_a_ak4643",   (kernel_ulong_t)&fsi2_a_ak4643 },
-       { "sh_fsi2_b_ak4643",   (kernel_ulong_t)&fsi2_b_ak4643 },
-       {},
-};
-
 static struct platform_driver fsi_ak4642 = {
        .driver = {
                .name   = "fsi-ak4642-audio",
        },
        .probe          = fsi_ak4642_probe,
        .remove         = fsi_ak4642_remove,
-       .id_table       = fsi_id_table,
 };
 
-static int __init fsi_ak4642_init(void)
-{
-       return platform_driver_register(&fsi_ak4642);
-}
-
-static void __exit fsi_ak4642_exit(void)
-{
-       platform_driver_unregister(&fsi_ak4642);
-}
-
-module_init(fsi_ak4642_init);
-module_exit(fsi_ak4642_exit);
+module_platform_driver(fsi_ak4642);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Generic SH4 FSI-AK4642 sound card");
index 3ebebe7..621aea1 100644 (file)
@@ -110,18 +110,7 @@ static struct platform_driver fsi_hdmi = {
        .id_table       = fsi_id_table,
 };
 
-static int __init fsi_hdmi_init(void)
-{
-       return platform_driver_register(&fsi_hdmi);
-}
-
-static void __exit fsi_hdmi_exit(void)
-{
-       platform_driver_unregister(&fsi_hdmi);
-}
-
-module_init(fsi_hdmi_init);
-module_exit(fsi_hdmi_exit);
+module_platform_driver(fsi_hdmi);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Generic SH4 FSI-HDMI sound card");
index 3d7016e..a27c306 100644 (file)
@@ -32,7 +32,9 @@
 #define REG_DIDT       0x0020
 #define REG_DODT       0x0024
 #define REG_MUTE_ST    0x0028
+#define REG_OUT_DMAC   0x002C
 #define REG_OUT_SEL    0x0030
+#define REG_IN_DMAC    0x0038
 
 /* master register */
 #define MST_CLK_RST    0x0210
@@ -235,13 +237,13 @@ static void __fsi_reg_mask_set(u32 __iomem *reg, u32 mask, u32 data)
 }
 
 #define fsi_reg_write(p, r, d)\
-       __fsi_reg_write((u32)(p->base + REG_##r), d)
+       __fsi_reg_write((p->base + REG_##r), d)
 
 #define fsi_reg_read(p, r)\
-       __fsi_reg_read((u32)(p->base + REG_##r))
+       __fsi_reg_read((p->base + REG_##r))
 
 #define fsi_reg_mask_set(p, r, m, d)\
-       __fsi_reg_mask_set((u32)(p->base + REG_##r), m, d)
+       __fsi_reg_mask_set((p->base + REG_##r), m, d)
 
 #define fsi_master_read(p, r) _fsi_master_read(p, MST_##r)
 #define fsi_core_read(p, r)   _fsi_master_read(p, p->core->r)
@@ -886,6 +888,8 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
                          int is_play,
                          struct device *dev)
 {
+       struct fsi_master *master = fsi_get_master(fsi);
+       int fsi_ver = master->core->ver;
        u32 flags = fsi_get_info_flags(fsi);
        u32 data = 0;
 
@@ -920,6 +924,17 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
                fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD);
        }
 
+       /*
+        * FIXME
+        *
+        * FSI driver assumed that data package is in-back.
+        * FSI2 chip can select it.
+        */
+       if (fsi_ver >= 2) {
+               fsi_reg_write(fsi, OUT_DMAC,    (1 << 4));
+               fsi_reg_write(fsi, IN_DMAC,     (1 << 4));
+       }
+
        /* irq clear */
        fsi_irq_disable(fsi, is_play);
        fsi_irq_clear_status(fsi);
@@ -1081,7 +1096,7 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
        return ret;
 }
 
-static struct snd_soc_dai_ops fsi_dai_ops = {
+static const struct snd_soc_dai_ops fsi_dai_ops = {
        .startup        = fsi_dai_startup,
        .shutdown       = fsi_dai_shutdown,
        .trigger        = fsi_dai_trigger,
@@ -1453,18 +1468,7 @@ static struct platform_driver fsi_driver = {
        .id_table       = fsi_id_table,
 };
 
-static int __init fsi_mobile_init(void)
-{
-       return platform_driver_register(&fsi_driver);
-}
-
-static void __exit fsi_mobile_exit(void)
-{
-       platform_driver_unregister(&fsi_driver);
-}
-
-module_init(fsi_mobile_init);
-module_exit(fsi_mobile_exit);
+module_platform_driver(fsi_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SuperH onchip FSI audio driver");
index c87e3ff..3474d7b 100644 (file)
@@ -266,7 +266,7 @@ static int hac_hw_params(struct snd_pcm_substream *substream,
 #define AC97_FMTS      \
        SNDRV_PCM_FMTBIT_S16_LE
 
-static struct snd_soc_dai_ops hac_dai_ops = {
+static const struct snd_soc_dai_ops hac_dai_ops = {
        .hw_params      = hac_hw_params,
 };
 
@@ -332,17 +332,7 @@ static struct platform_driver hac_pcm_driver = {
        .remove = __devexit_p(hac_soc_platform_remove),
 };
 
-static int __init sh4_hac_pcm_init(void)
-{
-       return platform_driver_register(&hac_pcm_driver);
-}
-module_init(sh4_hac_pcm_init);
-
-static void __exit sh4_hac_pcm_exit(void)
-{
-       platform_driver_unregister(&hac_pcm_driver);
-}
-module_exit(sh4_hac_pcm_exit);
+module_platform_driver(hac_pcm_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver");
index edacfeb..11c6085 100644 (file)
@@ -707,7 +707,7 @@ epclkget:
        return ret;
 }
 
-static struct snd_soc_dai_ops siu_dai_ops = {
+static const struct snd_soc_dai_ops siu_dai_ops = {
        .startup        = siu_dai_startup,
        .shutdown       = siu_dai_shutdown,
        .prepare        = siu_dai_prepare,
@@ -852,18 +852,7 @@ static struct platform_driver siu_driver = {
        .remove         = __devexit_p(siu_remove),
 };
 
-static int __init siu_init(void)
-{
-       return platform_driver_register(&siu_driver);
-}
-
-static void __exit siu_exit(void)
-{
-       platform_driver_unregister(&siu_driver);
-}
-
-module_init(siu_init)
-module_exit(siu_exit)
+module_platform_driver(siu_driver);
 
 MODULE_AUTHOR("Carlos Munoz <carlos@kenati.com>");
 MODULE_DESCRIPTION("ALSA SoC SH7722 SIU driver");
index e0c621c..ff82b56 100644 (file)
@@ -332,7 +332,7 @@ static int ssi_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
         SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE |  \
         SNDRV_PCM_FMTBIT_S32_LE  | SNDRV_PCM_FMTBIT_U32_LE)
 
-static struct snd_soc_dai_ops ssi_dai_ops = {
+static const struct snd_soc_dai_ops ssi_dai_ops = {
        .startup        = ssi_startup,
        .shutdown       = ssi_shutdown,
        .trigger        = ssi_trigger,
@@ -401,17 +401,7 @@ static struct platform_driver sh4_ssi_driver = {
        .remove = __devexit_p(sh4_soc_dai_remove),
 };
 
-static int __init snd_sh4_ssi_init(void)
-{
-       return platform_driver_register(&sh4_ssi_driver);
-}
-module_init(snd_sh4_ssi_init);
-
-static void __exit snd_sh4_ssi_exit(void)
-{
-       platform_driver_unregister(&sh4_ssi_driver);
-}
-module_exit(snd_sh4_ssi_exit);
+module_platform_driver(sh4_ssi_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver");
index 9077aa4..18bb6b3 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
 #include <sound/soc.h>
-#include <linux/lzo.h>
 #include <linux/bitmap.h>
 #include <linux/rbtree.h>
 #include <linux/export.h>
@@ -439,378 +438,6 @@ err:
        return ret;
 }
 
-#ifdef CONFIG_SND_SOC_CACHE_LZO
-struct snd_soc_lzo_ctx {
-       void *wmem;
-       void *dst;
-       const void *src;
-       size_t src_len;
-       size_t dst_len;
-       size_t decompressed_size;
-       unsigned long *sync_bmp;
-       int sync_bmp_nbits;
-};
-
-#define LZO_BLOCK_NUM 8
-static int snd_soc_lzo_block_count(void)
-{
-       return LZO_BLOCK_NUM;
-}
-
-static int snd_soc_lzo_prepare(struct snd_soc_lzo_ctx *lzo_ctx)
-{
-       lzo_ctx->wmem = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
-       if (!lzo_ctx->wmem)
-               return -ENOMEM;
-       return 0;
-}
-
-static int snd_soc_lzo_compress(struct snd_soc_lzo_ctx *lzo_ctx)
-{
-       size_t compress_size;
-       int ret;
-
-       ret = lzo1x_1_compress(lzo_ctx->src, lzo_ctx->src_len,
-                              lzo_ctx->dst, &compress_size, lzo_ctx->wmem);
-       if (ret != LZO_E_OK || compress_size > lzo_ctx->dst_len)
-               return -EINVAL;
-       lzo_ctx->dst_len = compress_size;
-       return 0;
-}
-
-static int snd_soc_lzo_decompress(struct snd_soc_lzo_ctx *lzo_ctx)
-{
-       size_t dst_len;
-       int ret;
-
-       dst_len = lzo_ctx->dst_len;
-       ret = lzo1x_decompress_safe(lzo_ctx->src, lzo_ctx->src_len,
-                                   lzo_ctx->dst, &dst_len);
-       if (ret != LZO_E_OK || dst_len != lzo_ctx->dst_len)
-               return -EINVAL;
-       return 0;
-}
-
-static int snd_soc_lzo_compress_cache_block(struct snd_soc_codec *codec,
-               struct snd_soc_lzo_ctx *lzo_ctx)
-{
-       int ret;
-
-       lzo_ctx->dst_len = lzo1x_worst_compress(PAGE_SIZE);
-       lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
-       if (!lzo_ctx->dst) {
-               lzo_ctx->dst_len = 0;
-               return -ENOMEM;
-       }
-
-       ret = snd_soc_lzo_compress(lzo_ctx);
-       if (ret < 0)
-               return ret;
-       return 0;
-}
-
-static int snd_soc_lzo_decompress_cache_block(struct snd_soc_codec *codec,
-               struct snd_soc_lzo_ctx *lzo_ctx)
-{
-       int ret;
-
-       lzo_ctx->dst_len = lzo_ctx->decompressed_size;
-       lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
-       if (!lzo_ctx->dst) {
-               lzo_ctx->dst_len = 0;
-               return -ENOMEM;
-       }
-
-       ret = snd_soc_lzo_decompress(lzo_ctx);
-       if (ret < 0)
-               return ret;
-       return 0;
-}
-
-static inline int snd_soc_lzo_get_blkindex(struct snd_soc_codec *codec,
-               unsigned int reg)
-{
-       const struct snd_soc_codec_driver *codec_drv;
-
-       codec_drv = codec->driver;
-       return (reg * codec_drv->reg_word_size) /
-              DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
-}
-
-static inline int snd_soc_lzo_get_blkpos(struct snd_soc_codec *codec,
-               unsigned int reg)
-{
-       const struct snd_soc_codec_driver *codec_drv;
-
-       codec_drv = codec->driver;
-       return reg % (DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count()) /
-                     codec_drv->reg_word_size);
-}
-
-static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec)
-{
-       return DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
-}
-
-static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec)
-{
-       struct snd_soc_lzo_ctx **lzo_blocks;
-       unsigned int val;
-       int i;
-       int ret;
-
-       lzo_blocks = codec->reg_cache;
-       for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) {
-               WARN_ON(!snd_soc_codec_writable_register(codec, i));
-               ret = snd_soc_cache_read(codec, i, &val);
-               if (ret)
-                       return ret;
-               codec->cache_bypass = 1;
-               ret = snd_soc_write(codec, i, val);
-               codec->cache_bypass = 0;
-               if (ret)
-                       return ret;
-               dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
-                       i, val);
-       }
-
-       return 0;
-}
-
-static int snd_soc_lzo_cache_write(struct snd_soc_codec *codec,
-                                  unsigned int reg, unsigned int value)
-{
-       struct snd_soc_lzo_ctx *lzo_block, **lzo_blocks;
-       int ret, blkindex, blkpos;
-       size_t blksize, tmp_dst_len;
-       void *tmp_dst;
-
-       /* index of the compressed lzo block */
-       blkindex = snd_soc_lzo_get_blkindex(codec, reg);
-       /* register index within the decompressed block */
-       blkpos = snd_soc_lzo_get_blkpos(codec, reg);
-       /* size of the compressed block */
-       blksize = snd_soc_lzo_get_blksize(codec);
-       lzo_blocks = codec->reg_cache;
-       lzo_block = lzo_blocks[blkindex];
-
-       /* save the pointer and length of the compressed block */
-       tmp_dst = lzo_block->dst;
-       tmp_dst_len = lzo_block->dst_len;
-
-       /* prepare the source to be the compressed block */
-       lzo_block->src = lzo_block->dst;
-       lzo_block->src_len = lzo_block->dst_len;
-
-       /* decompress the block */
-       ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
-       if (ret < 0) {
-               kfree(lzo_block->dst);
-               goto out;
-       }
-
-       /* write the new value to the cache */
-       if (snd_soc_set_cache_val(lzo_block->dst, blkpos, value,
-                                 codec->driver->reg_word_size)) {
-               kfree(lzo_block->dst);
-               goto out;
-       }
-
-       /* prepare the source to be the decompressed block */
-       lzo_block->src = lzo_block->dst;
-       lzo_block->src_len = lzo_block->dst_len;
-
-       /* compress the block */
-       ret = snd_soc_lzo_compress_cache_block(codec, lzo_block);
-       if (ret < 0) {
-               kfree(lzo_block->dst);
-               kfree(lzo_block->src);
-               goto out;
-       }
-
-       /* set the bit so we know we have to sync this register */
-       set_bit(reg, lzo_block->sync_bmp);
-       kfree(tmp_dst);
-       kfree(lzo_block->src);
-       return 0;
-out:
-       lzo_block->dst = tmp_dst;
-       lzo_block->dst_len = tmp_dst_len;
-       return ret;
-}
-
-static int snd_soc_lzo_cache_read(struct snd_soc_codec *codec,
-                                 unsigned int reg, unsigned int *value)
-{
-       struct snd_soc_lzo_ctx *lzo_block, **lzo_blocks;
-       int ret, blkindex, blkpos;
-       size_t blksize, tmp_dst_len;
-       void *tmp_dst;
-
-       *value = 0;
-       /* index of the compressed lzo block */
-       blkindex = snd_soc_lzo_get_blkindex(codec, reg);
-       /* register index within the decompressed block */
-       blkpos = snd_soc_lzo_get_blkpos(codec, reg);
-       /* size of the compressed block */
-       blksize = snd_soc_lzo_get_blksize(codec);
-       lzo_blocks = codec->reg_cache;
-       lzo_block = lzo_blocks[blkindex];
-
-       /* save the pointer and length of the compressed block */
-       tmp_dst = lzo_block->dst;
-       tmp_dst_len = lzo_block->dst_len;
-
-       /* prepare the source to be the compressed block */
-       lzo_block->src = lzo_block->dst;
-       lzo_block->src_len = lzo_block->dst_len;
-
-       /* decompress the block */
-       ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
-       if (ret >= 0)
-               /* fetch the value from the cache */
-               *value = snd_soc_get_cache_val(lzo_block->dst, blkpos,
-                                              codec->driver->reg_word_size);
-
-       kfree(lzo_block->dst);
-       /* restore the pointer and length of the compressed block */
-       lzo_block->dst = tmp_dst;
-       lzo_block->dst_len = tmp_dst_len;
-       return 0;
-}
-
-static int snd_soc_lzo_cache_exit(struct snd_soc_codec *codec)
-{
-       struct snd_soc_lzo_ctx **lzo_blocks;
-       int i, blkcount;
-
-       lzo_blocks = codec->reg_cache;
-       if (!lzo_blocks)
-               return 0;
-
-       blkcount = snd_soc_lzo_block_count();
-       /*
-        * the pointer to the bitmap used for syncing the cache
-        * is shared amongst all lzo_blocks.  Ensure it is freed
-        * only once.
-        */
-       if (lzo_blocks[0])
-               kfree(lzo_blocks[0]->sync_bmp);
-       for (i = 0; i < blkcount; ++i) {
-               if (lzo_blocks[i]) {
-                       kfree(lzo_blocks[i]->wmem);
-                       kfree(lzo_blocks[i]->dst);
-               }
-               /* each lzo_block is a pointer returned by kmalloc or NULL */
-               kfree(lzo_blocks[i]);
-       }
-       kfree(lzo_blocks);
-       codec->reg_cache = NULL;
-       return 0;
-}
-
-static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
-{
-       struct snd_soc_lzo_ctx **lzo_blocks;
-       size_t bmp_size;
-       const struct snd_soc_codec_driver *codec_drv;
-       int ret, tofree, i, blksize, blkcount;
-       const char *p, *end;
-       unsigned long *sync_bmp;
-
-       ret = 0;
-       codec_drv = codec->driver;
-
-       /*
-        * If we have not been given a default register cache
-        * then allocate a dummy zero-ed out region, compress it
-        * and remember to free it afterwards.
-        */
-       tofree = 0;
-       if (!codec->reg_def_copy)
-               tofree = 1;
-
-       if (!codec->reg_def_copy) {
-               codec->reg_def_copy = kzalloc(codec->reg_size, GFP_KERNEL);
-               if (!codec->reg_def_copy)
-                       return -ENOMEM;
-       }
-
-       blkcount = snd_soc_lzo_block_count();
-       codec->reg_cache = kzalloc(blkcount * sizeof *lzo_blocks,
-                                  GFP_KERNEL);
-       if (!codec->reg_cache) {
-               ret = -ENOMEM;
-               goto err_tofree;
-       }
-       lzo_blocks = codec->reg_cache;
-
-       /*
-        * allocate a bitmap to be used when syncing the cache with
-        * the hardware.  Each time a register is modified, the corresponding
-        * bit is set in the bitmap, so we know that we have to sync
-        * that register.
-        */
-       bmp_size = codec_drv->reg_cache_size;
-       sync_bmp = kmalloc(BITS_TO_LONGS(bmp_size) * sizeof(long),
-                          GFP_KERNEL);
-       if (!sync_bmp) {
-               ret = -ENOMEM;
-               goto err;
-       }
-       bitmap_zero(sync_bmp, bmp_size);
-
-       /* allocate the lzo blocks and initialize them */
-       for (i = 0; i < blkcount; ++i) {
-               lzo_blocks[i] = kzalloc(sizeof **lzo_blocks,
-                                       GFP_KERNEL);
-               if (!lzo_blocks[i]) {
-                       kfree(sync_bmp);
-                       ret = -ENOMEM;
-                       goto err;
-               }
-               lzo_blocks[i]->sync_bmp = sync_bmp;
-               lzo_blocks[i]->sync_bmp_nbits = bmp_size;
-               /* alloc the working space for the compressed block */
-               ret = snd_soc_lzo_prepare(lzo_blocks[i]);
-               if (ret < 0)
-                       goto err;
-       }
-
-       blksize = snd_soc_lzo_get_blksize(codec);
-       p = codec->reg_def_copy;
-       end = codec->reg_def_copy + codec->reg_size;
-       /* compress the register map and fill the lzo blocks */
-       for (i = 0; i < blkcount; ++i, p += blksize) {
-               lzo_blocks[i]->src = p;
-               if (p + blksize > end)
-                       lzo_blocks[i]->src_len = end - p;
-               else
-                       lzo_blocks[i]->src_len = blksize;
-               ret = snd_soc_lzo_compress_cache_block(codec,
-                                                      lzo_blocks[i]);
-               if (ret < 0)
-                       goto err;
-               lzo_blocks[i]->decompressed_size =
-                       lzo_blocks[i]->src_len;
-       }
-
-       if (tofree) {
-               kfree(codec->reg_def_copy);
-               codec->reg_def_copy = NULL;
-       }
-       return 0;
-err:
-       snd_soc_cache_exit(codec);
-err_tofree:
-       if (tofree) {
-               kfree(codec->reg_def_copy);
-               codec->reg_def_copy = NULL;
-       }
-       return ret;
-}
-#endif
-
 static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
 {
        int i;
@@ -889,17 +516,6 @@ static const struct snd_soc_cache_ops cache_types[] = {
                .write = snd_soc_flat_cache_write,
                .sync = snd_soc_flat_cache_sync
        },
-#ifdef CONFIG_SND_SOC_CACHE_LZO
-       {
-               .id = SND_SOC_LZO_COMPRESSION,
-               .name = "LZO",
-               .init = snd_soc_lzo_cache_init,
-               .exit = snd_soc_lzo_cache_exit,
-               .read = snd_soc_lzo_cache_read,
-               .write = snd_soc_lzo_cache_write,
-               .sync = snd_soc_lzo_cache_sync
-       },
-#endif
        {
                .id = SND_SOC_RBTREE_COMPRESSION,
                .name = "rbtree",
index a5d3685..1252ab1 100644 (file)
@@ -412,7 +412,7 @@ static void soc_init_card_debugfs(struct snd_soc_card *card)
                                                     snd_soc_debugfs_root);
        if (!card->debugfs_card_root) {
                dev_warn(card->dev,
-                        "ASoC: Failed to create codec debugfs directory\n");
+                        "ASoC: Failed to create card debugfs directory\n");
                return;
        }
 
@@ -572,7 +572,7 @@ int snd_soc_suspend(struct device *dev)
                        switch (codec->dapm.bias_level) {
                        case SND_SOC_BIAS_STANDBY:
                        case SND_SOC_BIAS_OFF:
-                               codec->driver->suspend(codec, PMSG_SUSPEND);
+                               codec->driver->suspend(codec);
                                codec->suspended = 1;
                                codec->cache_sync = 1;
                                break;
@@ -709,6 +709,12 @@ int snd_soc_resume(struct device *dev)
        struct snd_soc_card *card = dev_get_drvdata(dev);
        int i, ac97_control = 0;
 
+       /* If the initialization of this soc device failed, there is no codec
+        * associated with it. Just bail out in this case.
+        */
+       if (list_empty(&card->codec_dev_list))
+               return 0;
+
        /* AC97 devices might have other drivers hanging off them so
         * need to resume immediately.  Other drivers don't have that
         * problem and may take a substantial amount of time to resume
@@ -735,7 +741,7 @@ EXPORT_SYMBOL_GPL(snd_soc_resume);
 #define snd_soc_resume NULL
 #endif
 
-static struct snd_soc_dai_ops null_dai_ops = {
+static const struct snd_soc_dai_ops null_dai_ops = {
 };
 
 static int soc_bind_dai_link(struct snd_soc_card *card, int num)
@@ -757,10 +763,11 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
        }
        /* no, then find CPU DAI from registered DAIs*/
        list_for_each_entry(cpu_dai, &dai_list, list) {
-               if (!strcmp(cpu_dai->name, dai_link->cpu_dai_name)) {
-                       rtd->cpu_dai = cpu_dai;
-                       goto find_codec;
-               }
+               if (strcmp(cpu_dai->name, dai_link->cpu_dai_name))
+                       continue;
+
+               rtd->cpu_dai = cpu_dai;
+               goto find_codec;
        }
        dev_dbg(card->dev, "CPU DAI %s not registered\n",
                        dai_link->cpu_dai_name);
@@ -773,22 +780,28 @@ find_codec:
 
        /* no, then find CODEC from registered CODECs*/
        list_for_each_entry(codec, &codec_list, list) {
-               if (!strcmp(codec->name, dai_link->codec_name)) {
-                       rtd->codec = codec;
-
-                       /* CODEC found, so find CODEC DAI from registered DAIs from this CODEC*/
-                       list_for_each_entry(codec_dai, &dai_list, list) {
-                               if (codec->dev == codec_dai->dev &&
-                                               !strcmp(codec_dai->name, dai_link->codec_dai_name)) {
-                                       rtd->codec_dai = codec_dai;
-                                       goto find_platform;
-                               }
-                       }
-                       dev_dbg(card->dev, "CODEC DAI %s not registered\n",
-                                       dai_link->codec_dai_name);
+               if (strcmp(codec->name, dai_link->codec_name))
+                       continue;
 
-                       goto find_platform;
+               rtd->codec = codec;
+
+               /*
+                * CODEC found, so find CODEC DAI from registered DAIs from
+                * this CODEC
+                */
+               list_for_each_entry(codec_dai, &dai_list, list) {
+                       if (codec->dev == codec_dai->dev &&
+                               !strcmp(codec_dai->name,
+                                       dai_link->codec_dai_name)) {
+
+                               rtd->codec_dai = codec_dai;
+                               goto find_platform;
+                       }
                }
+               dev_dbg(card->dev, "CODEC DAI %s not registered\n",
+                               dai_link->codec_dai_name);
+
+               goto find_platform;
        }
        dev_dbg(card->dev, "CODEC %s not registered\n",
                        dai_link->codec_name);
@@ -805,10 +818,11 @@ find_platform:
 
        /* no, then find one from the set of registered platforms */
        list_for_each_entry(platform, &platform_list, list) {
-               if (!strcmp(platform->name, platform_name)) {
-                       rtd->platform = platform;
-                       goto out;
-               }
+               if (strcmp(platform->name, platform_name))
+                       continue;
+
+               rtd->platform = platform;
+               goto out;
        }
 
        dev_dbg(card->dev, "platform %s not registered\n",
@@ -1482,6 +1496,10 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 
        snd_soc_dapm_new_widgets(&card->dapm);
 
+       if (card->fully_routed)
+               list_for_each_entry(codec, &card->codec_dev_list, card_list)
+                       snd_soc_dapm_auto_nc_codec_pins(codec);
+
        ret = snd_card_register(card->snd_card);
        if (ret < 0) {
                printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name);
index f42e8b9..e174d08 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/platform_device.h>
 #include <linux/jiffies.h>
 #include <linux/debugfs.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -339,6 +340,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
        case snd_soc_dapm_output:
        case snd_soc_dapm_adc:
        case snd_soc_dapm_input:
+       case snd_soc_dapm_siggen:
        case snd_soc_dapm_dac:
        case snd_soc_dapm_micbias:
        case snd_soc_dapm_vmid:
@@ -772,6 +774,11 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
                        return widget->inputs;
                }
 
+               /* signal generator */
+               if (widget->id == snd_soc_dapm_siggen) {
+                       widget->inputs = snd_soc_dapm_suspend_check(widget);
+                       return widget->inputs;
+               }
        }
 
        list_for_each_entry(path, &widget->sources, list_sink) {
@@ -1200,6 +1207,9 @@ static void dapm_pre_sequence_async(void *data, async_cookie_t cookie)
        /* If we're off and we're not supposed to be go into STANDBY */
        if (d->bias_level == SND_SOC_BIAS_OFF &&
            d->target_bias_level != SND_SOC_BIAS_OFF) {
+               if (d->dev)
+                       pm_runtime_get_sync(d->dev);
+
                ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
                if (ret != 0)
                        dev_err(d->dev,
@@ -1239,6 +1249,9 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
                ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_OFF);
                if (ret != 0)
                        dev_err(d->dev, "Failed to turn off bias: %d\n", ret);
+
+               if (d->dev)
+                       pm_runtime_put_sync(d->dev);
        }
 
        /* If we just powered up then move to active bias */
@@ -1982,6 +1995,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
        case snd_soc_dapm_out_drv:
        case snd_soc_dapm_input:
        case snd_soc_dapm_output:
+       case snd_soc_dapm_siggen:
        case snd_soc_dapm_micbias:
        case snd_soc_dapm_vmid:
        case snd_soc_dapm_pre:
@@ -2947,6 +2961,79 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);
 
+static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card,
+                                             struct snd_soc_dapm_widget *w)
+{
+       struct snd_soc_dapm_path *p;
+
+       list_for_each_entry(p, &card->paths, list) {
+               if ((p->source == w) || (p->sink == w)) {
+                       dev_dbg(card->dev,
+                           "... Path %s(id:%d dapm:%p) - %s(id:%d dapm:%p)\n",
+                           p->source->name, p->source->id, p->source->dapm,
+                           p->sink->name, p->sink->id, p->sink->dapm);
+
+                       /* Connected to something other than the codec */
+                       if (p->source->dapm != p->sink->dapm)
+                               return true;
+                       /*
+                        * Loopback connection from codec external pin to
+                        * codec external pin
+                        */
+                       if (p->sink->id == snd_soc_dapm_input) {
+                               switch (p->source->id) {
+                               case snd_soc_dapm_output:
+                               case snd_soc_dapm_micbias:
+                                       return true;
+                               default:
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       return false;
+}
+
+/**
+ * snd_soc_dapm_auto_nc_codec_pins - call snd_soc_dapm_nc_pin for unused pins
+ * @codec: The codec whose pins should be processed
+ *
+ * Automatically call snd_soc_dapm_nc_pin() for any external pins in the codec
+ * which are unused. Pins are used if they are connected externally to the
+ * codec, whether that be to some other device, or a loop-back connection to
+ * the codec itself.
+ */
+void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec)
+{
+       struct snd_soc_card *card = codec->card;
+       struct snd_soc_dapm_context *dapm = &codec->dapm;
+       struct snd_soc_dapm_widget *w;
+
+       dev_dbg(codec->dev, "Auto NC: DAPMs: card:%p codec:%p\n",
+               &card->dapm, &codec->dapm);
+
+       list_for_each_entry(w, &card->widgets, list) {
+               if (w->dapm != dapm)
+                       continue;
+               switch (w->id) {
+               case snd_soc_dapm_input:
+               case snd_soc_dapm_output:
+               case snd_soc_dapm_micbias:
+                       dev_dbg(codec->dev, "Auto NC: Checking widget %s\n",
+                               w->name);
+                       if (!snd_soc_dapm_widget_in_card_paths(card, w)) {
+                               dev_dbg(codec->dev,
+                                       "... Not in map; disabling\n");
+                               snd_soc_dapm_nc_pin(dapm, w->name);
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+
 /**
  * snd_soc_dapm_free - free dapm resources
  * @dapm: DAPM context
index ee15337..8aa7cec 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <sound/core.h>
@@ -77,6 +78,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;
        int ret = 0;
 
+       pm_runtime_get_sync(cpu_dai->dev);
+       pm_runtime_get_sync(codec_dai->dev);
+       pm_runtime_get_sync(platform->dev);
+
        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
        /* startup the audio subsystem */
@@ -233,6 +238,11 @@ platform_err:
                cpu_dai->driver->ops->shutdown(substream, cpu_dai);
 out:
        mutex_unlock(&rtd->pcm_mutex);
+
+       pm_runtime_put(platform->dev);
+       pm_runtime_put(codec_dai->dev);
+       pm_runtime_put(cpu_dai->dev);
+
        return ret;
 }
 
@@ -319,7 +329,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
        cpu_dai->runtime = NULL;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               if (unlikely(codec->ignore_pmdown_time)) {
+               if (codec->ignore_pmdown_time ||
+                   rtd->dai_link->ignore_pmdown_time) {
                        /* powered down playback stream now */
                        snd_soc_dapm_stream_event(rtd,
                                codec_dai->driver->playback.stream_name,
@@ -338,6 +349,11 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
        }
 
        mutex_unlock(&rtd->pcm_mutex);
+
+       pm_runtime_put(platform->dev);
+       pm_runtime_put(codec_dai->dev);
+       pm_runtime_put(cpu_dai->dev);
+
        return 0;
 }
 
index 0c12b98..4220bb0 100644 (file)
@@ -58,7 +58,36 @@ int snd_soc_params_to_bclk(struct snd_pcm_hw_params *params)
 }
 EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk);
 
-static struct snd_soc_platform_driver dummy_platform;
+static const struct snd_pcm_hardware dummy_dma_hardware = {
+       .formats                = 0xffffffff,
+       .channels_min           = 1,
+       .channels_max           = UINT_MAX,
+
+       /* Random values to keep userspace happy when checking constraints */
+       .info                   = SNDRV_PCM_INFO_INTERLEAVED |
+                                 SNDRV_PCM_INFO_BLOCK_TRANSFER,
+       .buffer_bytes_max       = 128*1024,
+       .period_bytes_min       = PAGE_SIZE,
+       .period_bytes_max       = PAGE_SIZE*2,
+       .periods_min            = 2,
+       .periods_max            = 128,
+};
+
+static int dummy_dma_open(struct snd_pcm_substream *substream)
+{
+       snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware);
+
+       return 0;
+}
+
+static struct snd_pcm_ops dummy_dma_ops = {
+       .open           = dummy_dma_open,
+       .ioctl          = snd_pcm_lib_ioctl,
+};
+
+static struct snd_soc_platform_driver dummy_platform = {
+       .ops = &dummy_dma_ops,
+};
 
 static __devinit int snd_soc_dummy_probe(struct platform_device *pdev)
 {
index 3b55a44..3b3c1ba 100644 (file)
@@ -172,11 +172,11 @@ static int __devinit tegra_das_probe(struct platform_device *pdev)
        if (das)
                return -ENODEV;
 
-       das = kzalloc(sizeof(struct tegra_das), GFP_KERNEL);
+       das = devm_kzalloc(&pdev->dev, sizeof(struct tegra_das), GFP_KERNEL);
        if (!das) {
                dev_err(&pdev->dev, "Can't allocate tegra_das\n");
                ret = -ENOMEM;
-               goto exit;
+               goto err;
        }
        das->dev = &pdev->dev;
 
@@ -184,22 +184,35 @@ static int __devinit tegra_das_probe(struct platform_device *pdev)
        if (!res) {
                dev_err(&pdev->dev, "No memory resource\n");
                ret = -ENODEV;
-               goto err_free;
+               goto err;
        }
 
-       region = request_mem_region(res->start, resource_size(res),
-                                       pdev->name);
+       region = devm_request_mem_region(&pdev->dev, res->start,
+                                        resource_size(res), pdev->name);
        if (!region) {
                dev_err(&pdev->dev, "Memory region already claimed\n");
                ret = -EBUSY;
-               goto err_free;
+               goto err;
        }
 
-       das->regs = ioremap(res->start, resource_size(res));
+       das->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
        if (!das->regs) {
                dev_err(&pdev->dev, "ioremap failed\n");
                ret = -ENOMEM;
-               goto err_release;
+               goto err;
+       }
+
+       ret = tegra_das_connect_dap_to_dac(TEGRA_DAS_DAP_ID_1,
+                                          TEGRA_DAS_DAP_SEL_DAC1);
+       if (ret) {
+               dev_err(&pdev->dev, "Can't set up DAS DAP connection\n");
+               goto err;
+       }
+       ret = tegra_das_connect_dac_to_dap(TEGRA_DAS_DAC_ID_1,
+                                          TEGRA_DAS_DAC_SEL_DAP1);
+       if (ret) {
+               dev_err(&pdev->dev, "Can't set up DAS DAC connection\n");
+               goto err;
        }
 
        tegra_das_debug_add(das);
@@ -208,58 +221,41 @@ static int __devinit tegra_das_probe(struct platform_device *pdev)
 
        return 0;
 
-err_release:
-       release_mem_region(res->start, resource_size(res));
-err_free:
-       kfree(das);
+err:
        das = NULL;
-exit:
        return ret;
 }
 
 static int __devexit tegra_das_remove(struct platform_device *pdev)
 {
-       struct resource *res;
-
        if (!das)
                return -ENODEV;
 
-       platform_set_drvdata(pdev, NULL);
-
        tegra_das_debug_remove(das);
 
-       iounmap(das->regs);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(res->start, resource_size(res));
-
-       kfree(das);
        das = NULL;
 
        return 0;
 }
 
+static const struct of_device_id tegra_das_of_match[] __devinitconst = {
+       { .compatible = "nvidia,tegra20-das", },
+       {},
+};
+
 static struct platform_driver tegra_das_driver = {
        .probe = tegra_das_probe,
        .remove = __devexit_p(tegra_das_remove),
        .driver = {
                .name = DRV_NAME,
+               .owner = THIS_MODULE,
+               .of_match_table = tegra_das_of_match,
        },
 };
-
-static int __init tegra_das_modinit(void)
-{
-       return platform_driver_register(&tegra_das_driver);
-}
-module_init(tegra_das_modinit);
-
-static void __exit tegra_das_modexit(void)
-{
-       platform_driver_unregister(&tegra_das_driver);
-}
-module_exit(tegra_das_modexit);
+module_platform_driver(tegra_das_driver);
 
 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
 MODULE_DESCRIPTION("Tegra DAS driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_das_of_match);
index 6728fab..33509de 100644 (file)
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/of.h>
 #include <mach/iomap.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 
-#include "tegra_das.h"
 #include "tegra_i2s.h"
 
 #define DRV_NAME "tegra-i2s"
@@ -99,13 +99,11 @@ static const struct file_operations tegra_i2s_debug_fops = {
        .release = single_release,
 };
 
-static void tegra_i2s_debug_add(struct tegra_i2s *i2s, int id)
+static void tegra_i2s_debug_add(struct tegra_i2s *i2s)
 {
-       char name[] = DRV_NAME ".0";
-
-       snprintf(name, sizeof(name), DRV_NAME".%1d", id);
-       i2s->debug = debugfs_create_file(name, S_IRUGO, snd_soc_debugfs_root,
-                                               i2s, &tegra_i2s_debug_fops);
+       i2s->debug = debugfs_create_file(i2s->dai.name, S_IRUGO,
+                                        snd_soc_debugfs_root, i2s,
+                                        &tegra_i2s_debug_fops);
 }
 
 static void tegra_i2s_debug_remove(struct tegra_i2s *i2s)
@@ -306,93 +304,54 @@ static int tegra_i2s_probe(struct snd_soc_dai *dai)
        return 0;
 }
 
-static struct snd_soc_dai_ops tegra_i2s_dai_ops = {
+static const struct snd_soc_dai_ops tegra_i2s_dai_ops = {
        .set_fmt        = tegra_i2s_set_fmt,
        .hw_params      = tegra_i2s_hw_params,
        .trigger        = tegra_i2s_trigger,
 };
 
-static struct snd_soc_dai_driver tegra_i2s_dai[] = {
-       {
-               .name = DRV_NAME ".0",
-               .probe = tegra_i2s_probe,
-               .playback = {
-                       .channels_min = 2,
-                       .channels_max = 2,
-                       .rates = SNDRV_PCM_RATE_8000_96000,
-                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
-               },
-               .capture = {
-                       .channels_min = 2,
-                       .channels_max = 2,
-                       .rates = SNDRV_PCM_RATE_8000_96000,
-                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
-               },
-               .ops = &tegra_i2s_dai_ops,
-               .symmetric_rates = 1,
+static const struct snd_soc_dai_driver tegra_i2s_dai_template = {
+       .probe = tegra_i2s_probe,
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000_96000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
        },
-       {
-               .name = DRV_NAME ".1",
-               .probe = tegra_i2s_probe,
-               .playback = {
-                       .channels_min = 2,
-                       .channels_max = 2,
-                       .rates = SNDRV_PCM_RATE_8000_96000,
-                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
-               },
-               .capture = {
-                       .channels_min = 2,
-                       .channels_max = 2,
-                       .rates = SNDRV_PCM_RATE_8000_96000,
-                       .formats = SNDRV_PCM_FMTBIT_S16_LE,
-               },
-               .ops = &tegra_i2s_dai_ops,
-               .symmetric_rates = 1,
+       .capture = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000_96000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
        },
+       .ops = &tegra_i2s_dai_ops,
+       .symmetric_rates = 1,
 };
 
 static __devinit int tegra_i2s_platform_probe(struct platform_device *pdev)
 {
        struct tegra_i2s * i2s;
        struct resource *mem, *memregion, *dmareq;
+       u32 of_dma[2];
+       u32 dma_ch;
        int ret;
 
-       if ((pdev->id < 0) ||
-               (pdev->id >= ARRAY_SIZE(tegra_i2s_dai))) {
-               dev_err(&pdev->dev, "ID %d out of range\n", pdev->id);
-               return -EINVAL;
-       }
-
-       /*
-        * FIXME: Until a codec driver exists for the tegra DAS, hard-code a
-        * 1:1 mapping between audio controllers and audio ports.
-        */
-       ret = tegra_das_connect_dap_to_dac(TEGRA_DAS_DAP_ID_1 + pdev->id,
-                                       TEGRA_DAS_DAP_SEL_DAC1 + pdev->id);
-       if (ret) {
-               dev_err(&pdev->dev, "Can't set up DAP connection\n");
-               return ret;
-       }
-       ret = tegra_das_connect_dac_to_dap(TEGRA_DAS_DAC_ID_1 + pdev->id,
-                                       TEGRA_DAS_DAC_SEL_DAP1 + pdev->id);
-       if (ret) {
-               dev_err(&pdev->dev, "Can't set up DAC connection\n");
-               return ret;
-       }
-
-       i2s = kzalloc(sizeof(struct tegra_i2s), GFP_KERNEL);
+       i2s = devm_kzalloc(&pdev->dev, sizeof(struct tegra_i2s), GFP_KERNEL);
        if (!i2s) {
                dev_err(&pdev->dev, "Can't allocate tegra_i2s\n");
                ret = -ENOMEM;
-               goto exit;
+               goto err;
        }
        dev_set_drvdata(&pdev->dev, i2s);
 
+       i2s->dai = tegra_i2s_dai_template;
+       i2s->dai.name = dev_name(&pdev->dev);
+
        i2s->clk_i2s = clk_get(&pdev->dev, NULL);
        if (IS_ERR(i2s->clk_i2s)) {
                dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
                ret = PTR_ERR(i2s->clk_i2s);
-               goto err_free;
+               goto err;
        }
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -404,104 +363,93 @@ static __devinit int tegra_i2s_platform_probe(struct platform_device *pdev)
 
        dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
        if (!dmareq) {
-               dev_err(&pdev->dev, "No DMA resource\n");
-               ret = -ENODEV;
-               goto err_clk_put;
+               if (of_property_read_u32_array(pdev->dev.of_node,
+                                       "nvidia,dma-request-selector",
+                                       of_dma, 2) < 0) {
+                       dev_err(&pdev->dev, "No DMA resource\n");
+                       ret = -ENODEV;
+                       goto err_clk_put;
+               }
+               dma_ch = of_dma[1];
+       } else {
+               dma_ch = dmareq->start;
        }
 
-       memregion = request_mem_region(mem->start, resource_size(mem),
-                                       DRV_NAME);
+       memregion = devm_request_mem_region(&pdev->dev, mem->start,
+                                           resource_size(mem), DRV_NAME);
        if (!memregion) {
                dev_err(&pdev->dev, "Memory region already claimed\n");
                ret = -EBUSY;
                goto err_clk_put;
        }
 
-       i2s->regs = ioremap(mem->start, resource_size(mem));
+       i2s->regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
        if (!i2s->regs) {
                dev_err(&pdev->dev, "ioremap failed\n");
                ret = -ENOMEM;
-               goto err_release;
+               goto err_clk_put;
        }
 
        i2s->capture_dma_data.addr = mem->start + TEGRA_I2S_FIFO2;
        i2s->capture_dma_data.wrap = 4;
        i2s->capture_dma_data.width = 32;
-       i2s->capture_dma_data.req_sel = dmareq->start;
+       i2s->capture_dma_data.req_sel = dma_ch;
 
        i2s->playback_dma_data.addr = mem->start + TEGRA_I2S_FIFO1;
        i2s->playback_dma_data.wrap = 4;
        i2s->playback_dma_data.width = 32;
-       i2s->playback_dma_data.req_sel = dmareq->start;
+       i2s->playback_dma_data.req_sel = dma_ch;
 
        i2s->reg_ctrl = TEGRA_I2S_CTRL_FIFO_FORMAT_PACKED;
 
-       ret = snd_soc_register_dai(&pdev->dev, &tegra_i2s_dai[pdev->id]);
+       ret = snd_soc_register_dai(&pdev->dev, &i2s->dai);
        if (ret) {
                dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
                ret = -ENOMEM;
-               goto err_unmap;
+               goto err_clk_put;
        }
 
-       tegra_i2s_debug_add(i2s, pdev->id);
+       tegra_i2s_debug_add(i2s);
 
        return 0;
 
-err_unmap:
-       iounmap(i2s->regs);
-err_release:
-       release_mem_region(mem->start, resource_size(mem));
 err_clk_put:
        clk_put(i2s->clk_i2s);
-err_free:
-       kfree(i2s);
-exit:
+err:
        return ret;
 }
 
 static int __devexit tegra_i2s_platform_remove(struct platform_device *pdev)
 {
        struct tegra_i2s *i2s = dev_get_drvdata(&pdev->dev);
-       struct resource *res;
 
        snd_soc_unregister_dai(&pdev->dev);
 
        tegra_i2s_debug_remove(i2s);
 
-       iounmap(i2s->regs);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(res->start, resource_size(res));
-
        clk_put(i2s->clk_i2s);
 
-       kfree(i2s);
-
        return 0;
 }
 
+static const struct of_device_id tegra_i2s_of_match[] __devinitconst = {
+       { .compatible = "nvidia,tegra20-i2s", },
+       {},
+};
+
 static struct platform_driver tegra_i2s_driver = {
        .driver = {
                .name = DRV_NAME,
                .owner = THIS_MODULE,
+               .of_match_table = tegra_i2s_of_match,
        },
        .probe = tegra_i2s_platform_probe,
        .remove = __devexit_p(tegra_i2s_platform_remove),
 };
-
-static int __init snd_tegra_i2s_init(void)
-{
-       return platform_driver_register(&tegra_i2s_driver);
-}
-module_init(snd_tegra_i2s_init);
-
-static void __exit snd_tegra_i2s_exit(void)
-{
-       platform_driver_unregister(&tegra_i2s_driver);
-}
-module_exit(snd_tegra_i2s_exit);
+module_platform_driver(tegra_i2s_driver);
 
 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
 MODULE_DESCRIPTION("Tegra I2S ASoC driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_i2s_of_match);
index 2b38a09..15ce1e2 100644 (file)
 #define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_TWELVE_SLOTS  (TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
 
 struct tegra_i2s {
+       struct snd_soc_dai_driver dai;
        struct clk *clk_i2s;
        int clk_refs;
        struct tegra_pcm_dma_params capture_dma_data;
index 436def1..90345ee 100644 (file)
@@ -392,18 +392,7 @@ static struct platform_driver tegra_pcm_driver = {
        .probe = tegra_pcm_platform_probe,
        .remove = __devexit_p(tegra_pcm_platform_remove),
 };
-
-static int __init snd_tegra_pcm_init(void)
-{
-       return platform_driver_register(&tegra_pcm_driver);
-}
-module_init(snd_tegra_pcm_init);
-
-static void __exit snd_tegra_pcm_exit(void)
-{
-       platform_driver_unregister(&tegra_pcm_driver);
-}
-module_exit(snd_tegra_pcm_exit);
+module_platform_driver(tegra_pcm_driver);
 
 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
 MODULE_DESCRIPTION("Tegra PCM ASoC driver");
index dd11d0c..475428c 100644 (file)
@@ -226,7 +226,7 @@ static int tegra_spdif_probe(struct snd_soc_dai *dai)
        return 0;
 }
 
-static struct snd_soc_dai_ops tegra_spdif_dai_ops = {
+static const struct snd_soc_dai_ops tegra_spdif_dai_ops = {
        .hw_params      = tegra_spdif_hw_params,
        .trigger        = tegra_spdif_trigger,
 };
@@ -352,17 +352,7 @@ static struct platform_driver tegra_spdif_driver = {
        .remove = __devexit_p(tegra_spdif_platform_remove),
 };
 
-static int __init snd_tegra_spdif_init(void)
-{
-       return platform_driver_register(&tegra_spdif_driver);
-}
-module_init(snd_tegra_spdif_init);
-
-static void __exit snd_tegra_spdif_exit(void)
-{
-       platform_driver_unregister(&tegra_spdif_driver);
-}
-module_exit(snd_tegra_spdif_exit);
+module_platform_driver(tegra_spdif_driver);
 
 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
 MODULE_DESCRIPTION("Tegra SPDIF ASoC driver");
index a81cf39..ba2d23e 100644 (file)
@@ -201,8 +201,8 @@ static const struct snd_soc_dapm_route harmony_audio_map[] = {
        {"Int Spk", NULL, "RON"},
        {"Int Spk", NULL, "LOP"},
        {"Int Spk", NULL, "LON"},
-       {"Mic Bias", NULL, "Mic Jack"},
-       {"IN1L", NULL, "Mic Bias"},
+       {"Mic Jack", NULL, "MICBIAS"},
+       {"IN1L", NULL, "Mic Jack"},
 };
 
 static const struct snd_soc_dapm_route seaboard_audio_map[] = {
@@ -212,8 +212,8 @@ static const struct snd_soc_dapm_route seaboard_audio_map[] = {
        {"Int Spk", NULL, "RON"},
        {"Int Spk", NULL, "LOP"},
        {"Int Spk", NULL, "LON"},
-       {"Mic Bias", NULL, "Mic Jack"},
-       {"IN1R", NULL, "Mic Bias"},
+       {"Mic Jack", NULL, "MICBIAS"},
+       {"IN1R", NULL, "Mic Jack"},
 };
 
 static const struct snd_soc_dapm_route kaen_audio_map[] = {
@@ -223,8 +223,8 @@ static const struct snd_soc_dapm_route kaen_audio_map[] = {
        {"Int Spk", NULL, "RON"},
        {"Int Spk", NULL, "LOP"},
        {"Int Spk", NULL, "LON"},
-       {"Mic Bias", NULL, "Mic Jack"},
-       {"IN2R", NULL, "Mic Bias"},
+       {"Mic Jack", NULL, "MICBIAS"},
+       {"IN2R", NULL, "Mic Jack"},
 };
 
 static const struct snd_soc_dapm_route aebl_audio_map[] = {
@@ -232,8 +232,8 @@ static const struct snd_soc_dapm_route aebl_audio_map[] = {
        {"Headphone Jack", NULL, "HPOUTL"},
        {"Int Spk", NULL, "LINEOUTR"},
        {"Int Spk", NULL, "LINEOUTL"},
-       {"Mic Bias", NULL, "Mic Jack"},
-       {"IN1R", NULL, "Mic Bias"},
+       {"Mic Jack", NULL, "MICBIAS"},
+       {"IN1R", NULL, "Mic Jack"},
 };
 
 static const struct snd_kcontrol_new tegra_wm8903_controls[] = {
@@ -316,28 +316,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
        wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE,
                                0);
 
-       snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
-
-       /* FIXME: Calculate automatically based on DAPM routes? */
-       if (!machine_is_harmony())
-               snd_soc_dapm_nc_pin(dapm, "IN1L");
-       if (!machine_is_seaboard() && !machine_is_aebl())
-               snd_soc_dapm_nc_pin(dapm, "IN1R");
-       snd_soc_dapm_nc_pin(dapm, "IN2L");
-       if (!machine_is_kaen())
-               snd_soc_dapm_nc_pin(dapm, "IN2R");
-       snd_soc_dapm_nc_pin(dapm, "IN3L");
-       snd_soc_dapm_nc_pin(dapm, "IN3R");
-
-       if (machine_is_aebl()) {
-               snd_soc_dapm_nc_pin(dapm, "LON");
-               snd_soc_dapm_nc_pin(dapm, "RON");
-               snd_soc_dapm_nc_pin(dapm, "ROP");
-               snd_soc_dapm_nc_pin(dapm, "LOP");
-       } else {
-               snd_soc_dapm_nc_pin(dapm, "LINEOUTR");
-               snd_soc_dapm_nc_pin(dapm, "LINEOUTL");
-       }
+       snd_soc_dapm_force_enable_pin(dapm, "MICBIAS");
 
        return 0;
 }
@@ -362,6 +341,7 @@ static struct snd_soc_card snd_soc_tegra_wm8903 = {
        .num_controls = ARRAY_SIZE(tegra_wm8903_controls),
        .dapm_widgets = tegra_wm8903_dapm_widgets,
        .num_dapm_widgets = ARRAY_SIZE(tegra_wm8903_dapm_widgets),
+       .fully_routed = true,
 };
 
 static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
@@ -377,17 +357,19 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       machine = kzalloc(sizeof(struct tegra_wm8903), GFP_KERNEL);
+       machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm8903),
+                              GFP_KERNEL);
        if (!machine) {
                dev_err(&pdev->dev, "Can't allocate tegra_wm8903 struct\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto err;
        }
 
        machine->pdata = pdata;
 
        ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
        if (ret)
-               goto err_free_machine;
+               goto err;
 
        card->dev = &pdev->dev;
        platform_set_drvdata(pdev, card);
@@ -418,8 +400,7 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
 
 err_fini_utils:
        tegra_asoc_utils_fini(&machine->util_data);
-err_free_machine:
-       kfree(machine);
+err:
        return ret;
 }
 
@@ -447,8 +428,6 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
 
        tegra_asoc_utils_fini(&machine->util_data);
 
-       kfree(machine);
-
        return 0;
 }
 
@@ -461,18 +440,7 @@ static struct platform_driver tegra_wm8903_driver = {
        .probe = tegra_wm8903_driver_probe,
        .remove = __devexit_p(tegra_wm8903_driver_remove),
 };
-
-static int __init tegra_wm8903_modinit(void)
-{
-       return platform_driver_register(&tegra_wm8903_driver);
-}
-module_init(tegra_wm8903_modinit);
-
-static void __exit tegra_wm8903_modexit(void)
-{
-       platform_driver_unregister(&tegra_wm8903_driver);
-}
-module_exit(tegra_wm8903_modexit);
+module_platform_driver(tegra_wm8903_driver);
 
 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
 MODULE_DESCRIPTION("Tegra+WM8903 machine ASoC driver");
index b3a7efa..7d95b76 100644 (file)
@@ -115,18 +115,6 @@ static const struct snd_soc_dapm_route trimslice_audio_map[] = {
        {"RLINEIN", NULL, "Line In"},
 };
 
-static int trimslice_asoc_init(struct snd_soc_pcm_runtime *rtd)
-{
-       struct snd_soc_codec *codec = rtd->codec;
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-       snd_soc_dapm_nc_pin(dapm, "LHPOUT");
-       snd_soc_dapm_nc_pin(dapm, "RHPOUT");
-       snd_soc_dapm_nc_pin(dapm, "MICIN");
-
-       return 0;
-}
-
 static struct snd_soc_dai_link trimslice_tlv320aic23_dai = {
        .name = "TLV320AIC23",
        .stream_name = "AIC23",
@@ -134,7 +122,6 @@ static struct snd_soc_dai_link trimslice_tlv320aic23_dai = {
        .platform_name = "tegra-pcm-audio",
        .cpu_dai_name = "tegra-i2s.0",
        .codec_dai_name = "tlv320aic23-hifi",
-       .init = trimslice_asoc_init,
        .ops = &trimslice_asoc_ops,
 };
 
@@ -147,6 +134,7 @@ static struct snd_soc_card snd_soc_trimslice = {
        .num_dapm_widgets = ARRAY_SIZE(trimslice_dapm_widgets),
        .dapm_routes = trimslice_audio_map,
        .num_dapm_routes = ARRAY_SIZE(trimslice_audio_map),
+       .fully_routed = true,
 };
 
 static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
@@ -155,15 +143,17 @@ static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
        struct tegra_trimslice *trimslice;
        int ret;
 
-       trimslice = kzalloc(sizeof(struct tegra_trimslice), GFP_KERNEL);
+       trimslice = devm_kzalloc(&pdev->dev, sizeof(struct tegra_trimslice),
+                                GFP_KERNEL);
        if (!trimslice) {
                dev_err(&pdev->dev, "Can't allocate tegra_trimslice\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto err;
        }
 
        ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev);
        if (ret)
-               goto err_free_trimslice;
+               goto err;
 
        card->dev = &pdev->dev;
        platform_set_drvdata(pdev, card);
@@ -180,8 +170,7 @@ static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
 
 err_fini_utils:
        tegra_asoc_utils_fini(&trimslice->util_data);
-err_free_trimslice:
-       kfree(trimslice);
+err:
        return ret;
 }
 
@@ -194,8 +183,6 @@ static int __devexit tegra_snd_trimslice_remove(struct platform_device *pdev)
 
        tegra_asoc_utils_fini(&trimslice->util_data);
 
-       kfree(trimslice);
-
        return 0;
 }
 
@@ -207,18 +194,7 @@ static struct platform_driver tegra_snd_trimslice_driver = {
        .probe = tegra_snd_trimslice_probe,
        .remove = __devexit_p(tegra_snd_trimslice_remove),
 };
-
-static int __init snd_tegra_trimslice_init(void)
-{
-       return platform_driver_register(&tegra_snd_trimslice_driver);
-}
-module_init(snd_tegra_trimslice_init);
-
-static void __exit snd_tegra_trimslice_exit(void)
-{
-       platform_driver_unregister(&tegra_snd_trimslice_driver);
-}
-module_exit(snd_tegra_trimslice_exit);
+module_platform_driver(tegra_snd_trimslice_driver);
 
 MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
 MODULE_DESCRIPTION("Trimslice machine ASoC driver");
index a4e3f55..28db4ca 100644 (file)
@@ -223,18 +223,7 @@ static struct platform_driver txx9aclc_ac97_driver = {
        },
 };
 
-static int __init txx9aclc_ac97_init(void)
-{
-       return platform_driver_register(&txx9aclc_ac97_driver);
-}
-
-static void __exit txx9aclc_ac97_exit(void)
-{
-       platform_driver_unregister(&txx9aclc_ac97_driver);
-}
-
-module_init(txx9aclc_ac97_init);
-module_exit(txx9aclc_ac97_exit);
+module_platform_driver(txx9aclc_ac97_driver);
 
 MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
 MODULE_DESCRIPTION("TXx9 ACLC AC97 driver");
index 3de99af..93931de 100644 (file)
@@ -438,17 +438,7 @@ static struct platform_driver txx9aclc_pcm_driver = {
        .remove = __devexit_p(txx9aclc_soc_platform_remove),
 };
 
-static int __init snd_txx9aclc_pcm_init(void)
-{
-       return platform_driver_register(&txx9aclc_pcm_driver);
-}
-module_init(snd_txx9aclc_pcm_init);
-
-static void __exit snd_txx9aclc_pcm_exit(void)
-{
-       platform_driver_unregister(&txx9aclc_pcm_driver);
-}
-module_exit(snd_txx9aclc_pcm_exit);
+module_platform_driver(txx9aclc_pcm_driver);
 
 MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
 MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver");