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 e8552782b440af99ed14a6e851e3db5ed47d05fd..2c1b2cb85399ffad456156f82110f898c889d1a5 100644 (file)
@@ -37,4 +37,5 @@ simtek
 sirf   SiRF Technology, Inc.
 stericsson     ST-Ericsson
 ti     Texas Instruments
+wlf    Wolfson Microelectronics
 xlnx   Xilinx
index 3e2ec9cbf3976d0d21c6ee90d7fe075a210a33eb..d50c14df34112ed2095942062bcaab90d90697bd 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 3523ab000f1f9a261efcb2ec983201e6f7270bee..0ad711e0158510c5d8073a28e108d109b89a7cce 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 d04b6544851031bf2800ebea7768e00e803fb67c..55c0e75f5edc314fdafe3693df34b6ab410f3398 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 4c865ece9ac4e9dc14aa4612ce7a780e59fed690..bb08d2d25dcf307662b72116b07c0beefc07660e 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 9c5e598e0e3d69f1aa5c36d29f7a416f301b38fe..a2908d49a6df56df9cf5cde31dd140ded06b4bdf 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 f0bdc5e3fe527a3a34d61b269a0ee0cc816a657e..3c57cdcdff4dfdcbdd70e94b2425a92bc63ca8fe 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 bf13ea355efcc5049642f78f9e2869609a0bff91..5c2f7751a33a2035dae3ba8e206c0f9dfa2472b5 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 b747c0ab9264ac3ed5d1894b8c67f471c7bc852d..b49723b21912c8b9b825eb6c5b197dbb8b675efd 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 efba163595db1dd6a981f426d3581351a0fbd8b6..9b00072a020fb5141060c5ee89cfe31edbd651be 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 47338c9791263e849a9db97b34fb9f777afa2145..5a7e27399729789054c5069ca14ab4738786266f 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 b00897a6c461978f1c075d317f48f8325659728b..3fb1f407d5e6e36cf0c9cff31d222bff0258b91f 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 8317b19a4972cb9ae0908cb0c6195448e55e0147..86e6a032a07833f3dbee4f8d399a6e63e61ef93a 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 9a155f9d0a12a627f968821d25f890cb71efc403..9b1aacaa82fedd0fcb63365fae33237627c496c9 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 17a4c17f19f5ff672030d448bb84ea5b3d8a354a..d26a9b784772d797e88a529f199342f277e32390 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 11cfb5953e06eb82c22f52319aa2c4ea31d7f99a..d9aa66be1994c5e12b3af589a11e75182e5b9238 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 cf7ccb76a8de8ad7f7a409aad3a703addd574d06..b310c5a3a958dfd1e71f026e9c2e527c93071b61 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 1381db853ef0f8b5d875c6ba220de0f90476add5..35e662d270e6141338669051a784c06a3fe9fbea 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 bee3c94f58b0736c57f361141e0ed32e58640317..d1fcc816ce9705c5aca82f68eb327d65618301cd 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 e7ea56bd5f82a94de94d4169c464e809d34dfb5e..a5c0bf19da78f01e823fc614c61528c30272a67c 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 f81d4c3f8956efa24d4becf3952b6242554a0866..60de05525c06f0d6d676ae2d062acfa890762655 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 71225090c49fc424a7ea1f6c0f2b5168e79480ba..354341ec0f42f1129adbaaf310366af46b866229 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 726bd651a105970053a726cdee18012ea96a508b..7771934b93e29af95448143c32cc9a9b933e0ea5 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 127477a5e0c775ad8778eaf0fba722f161ce8697..094a20723bc6dba62ff60233a72afaa588fba9c1 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 289312c14b99bf62d13355e7ae5e585bf297991f..80733331733fb103ef37d112b73bbb87310b1a2b 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 d7d04e26eee504524f7952c86825b44c5d7a4fa7..09699de9b33760813fcbae541d271ad3fa2a5342 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 177f7137a9c80e358aa4c6913cfafce00585e11d..dc4dae48aed951b41b1af0554baed69d6824c7f9 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 6bcf48f5884c169b0a5d61004bb91f7652647b35..cb53ad87d0a99a71a25e2af85ba2457939484ae0 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 0c6acd54714100b09401fac0278f4b412821f0b9..87daf456b1c9e6fffdc1eca455944d6487e4af36 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 e03c5ce01b304ef680e1790f4fd9c39d1313483d..5c1dc8a141abed9881a09d643b2181994340a319 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 56815c1d47b3fdb36f278e05894fc54a6ace93d7..fcff58390848d0d6d497a76748b200c1e09e1b8b 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 6d216259088935633c598bb72d0ce516fc31df96..f4e9dc4e262e6c63a6a5e1cf318c4b58cab3b431 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 7565e1576ffa47a04ab165423cda019eb53c7375..6ec3d41b9b6d2f712830a202a08210da4a886f79 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 00cc3e00b2fead767ca60cbc54e603b3521f960a..4dccf0374fe744fd54aaf379caf92e3eec5feda6 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 c95cc03d583dd747a80477fd54b9137dc9bccb61..4406f9a865aedfbe5bf55339e3f9c1a10699d1ab 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 a822d1ee1380057db79148c265785e933616d1b2..594f88217c746e0f8639988b9851c105e2f5c0e5 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 8df2a3b0cb3613d9bb1bdc2a2e918f5e5c7b3528..85ed39abe10eb2c41eedef391705edef5519b52d 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 e5550acba2c2c1614dc14a8d738fef611214f508..1a88fe9ce34ce22a0a586784655298d4aaaf7dd4 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 897cfa68a2a668789b8844c00167b51eb1a12887..0bc995fb6283a6e22f18aa3542059793525c9175 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 5ca122e51183a4531c612613c0bbf6c94da9f272..2d39123dd21a990576ca4b2b37d6ff0d438ad075 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 4584514d93d4fd21a92de37847d318951e824bf8..7c205e77d83aa8af2439955b56cecc9fc1e7419b 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 a2c7842e357b6c3aa899a9e93155bed9855c2bbf..9aa6e669e6ef8f81d3fce6c378226b5e80120fe0 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 e715186b430064a33c939b9863da91f734e2af54..1bbad4c16d289fe29f7c20702138db81f4f093d5 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 4e5c5726366b12f4f2377e15da2bdea4598e6e98..919322daf6dd5fd3f021d1364f679dbae5bf3a20 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 444747f0db26615992e360b6a162eaf7b9f9ac44..dd7be0dbbc58189ff153b1a7b5724967bd4caadd 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 120602130b5c0a667cc612ab97877d016bb5a667..c1b7d928c347c70943bc213f74c842983ab88931 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 1507eaa425a3a06d8114e6c42ca3d7e175c17b51..47338804999233d2aaf4b6e61b79322a95848d87 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 e3931cc5e66c6736d75fa053e7755acfda7a8b8e..9bba7f849464391778e5c33f0076c0e20b3ea44f 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 8d793e993e9a8a7110d2601141649a72072baee6..ee7a68dcefd2442b1650b16395025bc2eed39990 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 1ccf8dd47576ce4c746ffb54461c19f196acff43..637b114bea7f86c36d591f01cd9661b48c638d89 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 8b7e1c50d6e9df43d2a25956a698094eb2bb6738..6a6af567f02a9042cc280266762fe388fe8632ce 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 f9f08948e5e878f12d40a1f337d6d40c7247119e..ebd7b37b902bb4019dee2059a633c120d20cc4f7 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 9082e0f729f307d626cd467bc0c777993cd987f8..8103b938b8c001214858e9a628ae60908424cde3 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 d3b29dce6ed7f27c080e7059ed5fc067d0d3ad0a..152420ca78b88310a19537a9ced6836181424629 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 95d782d86e7d5fc906e122c23dd7ae48ff39fd4a..96296fd172f9b7ac60805341e0d06759abbc0d3c 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 77838586f3588ffc61960f70cfaea2a29b6bfccf..90184701480d64d78fb973fa35cf1ebcca9c8336 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 12c1bdef67323f5f260290c037ce23f50dff42de..9b4ee6c63d28c948eae4509edfc772e994ff786b 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 de9ff66d3721d5dd367b2fc3f60178d9d5ee9e7c..4f5c69f735a94a35bd560e2292035142e6458ab4 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 984b14bcb6054bfbaa3d5f84ac7d60613d0f5c2c..da97f024ec74891048921d70eea88dbf3dc3623c 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 46dbfd067f79647b7fca338eb85addd177eda966..4854b472d5fdb98ca5d6cae18863286a17f3b408 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 f1f237ecec2a6c43dcdf9ee31b72da7f0cdecff6..fef0f48330e4fdd8cc0bc12d892608c621a1d311 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 23d1bd5dadda36185e2c56702e7fd17a739f9a1a..f6fe846b6a6c3d76f8778140261c96b0ed7a65eb 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 8c3c8205d19e99016e47b1564aa58cbdf91b0bab..528510b8e5de4962441e1352bed424c7fae53c84 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 bc7067db8ae4ec54697c4163e23f97af3670bd19..ae55e31bfc721172c7210cc48b2c6706fc0d9831 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 b545b7d3722271dd14e43213a34992a0b5174525..e4ca61c18605027362f390466368cfced743befc 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 704bbde65737577aec3739fa4159307a70f61ee2..bfe46aa90362fe262b7894d0bd9451ad3042f23f 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 6fae765e3ad8baf3611f7251bd3240e2c6591a06..3e929f079a1f0eb4b3fa472482d68503703da8c4 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 e373f8f0690731874d0a153190951ddc564500fe..d73d28317c005d17e29504e723a802b00ac9e47a 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 ebbf63c79c34e2873088aa2faaf6bcce400d99a0..ba4f6f167a1304444a5e3c1b4eea4705fe30bffd 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 26d7b089fb9c27836c2a6721dceec1350bc5300f..c69dd022bea887335e55818e921926864f4e4fd9 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 208d2ee618558c980df83b9ad0b35de9920bd145..7dfd6e84796d339fddce5d586012c68d9c108911 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 9e7e964a5fa3fd1a8824c17c9dad4bbc60923909..dcf6f2a1600ae5726a60d0a7e11ef6e53d57d466 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 f7316519432c42dcdb6122bd17009672217ad72f..edcaa7ea548757b3825acb27a1af9fd958d9121b 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 27a078cbb6eb2542cb6bc0fa0be372b5a77cabac..f6e4f5ed9286891167b957197464b0c8ad3a51a2 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 d15695d1c27397a7b3f2966c1806584e5e9a39bc..250175755eb280ef2d7f63829bd4e6c90375d9d1 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 887d618f4a639720b7e0698e086333f203175a7a..f99baa0b8c39133b5cbc342368b4ac98f79cb365 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 6a1a7e705cd767ffd11365252c88b70fe7c98ad1..112a49d66e3967847517b495872baa606a967189 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 3cb3271c5fe2019501cde20e9f1b73f872476282..7dfc7b08114c3c1b41aaff73412ad50f69a0a290 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 bb82408ab8e1bb93f187dac610e5a1141501bd72..6648af6656c8469b67dab098502be136651ea0e0 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 b97ee5a75667399e77a5bcd7493432407d554cc2..d8e32a6262ee087ec13e73d24e57b936eefaa42b 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 78b2b50271e25893ade9c8b0ce3b0f0be6ab4e92..cc0566c22ec12ecfcf3f67d486b6330fea448f47 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 336de8f69a026e9a6da20af04f3b821d5ba69a33..60d08aeac22aec87fc50ce204ab3d60fcd860b28 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 7859bdcc93db4064cad1474a8fe2533e19026f1e..86d1fa38ed2e7d8afcf0d19f8eb8786232505c8e 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 b21c610051c0f53c03ab2f6c42bf9b12ef20dda9..81a26e1090b31d00e76a1e1dd486c96620ac8506 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 87d5ef188e29484fe303931c71cc45ac30005cce..6f963c50e76eec26dd530b91ce2c015abf5cd2d1 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 dc8a2b2bdc1ce73b939cc0455f7ba4931c153c2e..c7a61fbdae4bef13549ffa7a7b3bda495878c277 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 f798247ac1b2071e7316200be605734ed87faf6d..18e71014cc2e87a93d82abdca853b62d29ab8a54 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 73e11f022dedc944c1010064435b17402b96194c..3376e6fad2a2813f0f490785cfec710f7ceeb7f4 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 a7b8f301bad39b3ef7a691273d4d3ba4bf4b9097..8f4f469d64115cb52ae8c58fd60fcc78d9669e50 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 c5ca8cfea60f80f8de27cc5d12ad55f69bd900f2..83e45d2b3e848f0c444850642ce8498c85efe56f 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 a854989829911a62eae6fdf3cf3336b917f748c4..44aacf927ba99d6a533524b39859eac9d565c265 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 cd0ec0fd1dbab536579b296884275cc14828326a..aefb4f89be0eb23b108e01581e86a52299961904 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 a3b9cbb20ee9bc07ca849fbe4f7af593048da9c8..c2880907fcedc0e74aed4b377e697d5223bee579 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 0b6f056f73cc53a80ab0fedc5733641573bc4974..abcd82a93995b357ba8052b0559178912990923b 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 e9ce81a57b856af0d4cc57f510195f75bba8c7c7..9a18fae68204f790a19c75e7fc527e1b25d3a1f5 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 42d9039a49e93863ba3adfb046a5b8d1f43a8515..a234b70377fc1a8692d3d4fede2f18bea289f74c 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 970759636bdc508b10603aa7fd8da6765043ad7c..25cb6016f9d7f37ce7eb855c66930ba27f06bd90 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 35f3ad83dfb6670013652772268385b75cda481a..8c4c9591ec055103eb1cf3381ae3e3d969abac85 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 dc13be2a09c52b64b95aee07eb9d4061485c8b56..898979d23010e3f5f50cc00070c4d6d56b92b58f 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 07c9cc759e97706a308d0489bac40a0f0482fdd1..9166126bd31259f10fa56c7b224029e7f7a7b0cc 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 db7a6819499fa59a1597f5c93066149e08d3c2ac..7fea2c3bf7e77dbf16096709df41004cf88ffdbf 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 8212b3c8bfdd90da61cfe426344c13aa6deadae8..b1c8d3de08b25c5506cd47e6bc89773c91b8b15e 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 076bdb9930a15d6d50c4edd3d6009a7fad801089..0b76d1dca5eade12cfd3bfd640a665e1f0626b97 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 7488082851191ce120a8a66fd8704b53613b8189..e81705620718eacf785fc10ecab3d74a0adbebcb 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 04b027efd5c003df25769eb92e3ff7a74317a975..fc3d59e4908404491a1801765f29bbacabb3c15c 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 7e5ec03f6f8dd579d1bd43413fd1d007a1989bcb..8821af70e660b354e4672a5aa7c32fa5fd7fd3f9 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 f6aef58845c2dc31880529cdaa9510a96735e334..ff95e62c56b9a7ae211c3f2d508d9cff94132931 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 57ad22aacc516dc17e18042a98712266f761afa3..3941f50bf18787b57a9e99555c7f67a28b00eedc 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 ca75a818070804610d0b7c0d10554e48cbf2f1bd..e4c50ce7d9c0852bce267e0e13b41a759a810ae3 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 a9504710bb692e806655e785e5f35121ecf4afc1..b114c19f530ab89c30ea9daa24cc2a0eef143f85 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 aa05e6507f844a2ac90c970e939a92efc9de0ff7..19374a9e5ba6ce06fc721e768255fcdb1ea2d97b 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 bfdc52370ad02de96bd9cf1859614db91e682949..38b45566219530f1872fc509d8616eba79bfc916 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 f2ced71328b0a6cc7ee073a4099fd6fd6afe5b15..3fdea98f732ec3814dd96f2150ffa5fe4c6b4349 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 9ee072b859751ac16b3163c0f5a33833e5eb878a..d54a3ca5e19ee3c72550f464e0032d1caeca0bc3 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 3d0dc1591eccda191057f2d957823ebb79f55b1e..f18c554efc984832ec6b538cf896cfce5ae2d925 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 4ad8ebd290e3decbe79f181bbbd1af2a3b014d4f..d88b727d7f9924c230e05571afcd6d346119e865 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 285ef87e6704fd655d89170ce5e5307e25a36983..f31c754c8865abd5b21ee61c3e47b810f73721a6 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 de9ec9b8b7d9ae06e98bd58f01e28ff67b08f0e1..14039ea2f3e4a13d9e882fefe3c2dd4f387bb670 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 3c7198779c3173e1408daf2403dc794a5bf4e157..924548182d58f86257e1a4a2d9fde8125e67a8af 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 0293763debe5811160fb3b7cc23284a91df2a94a..8d4ea43d40a383298023165e517ed1c9de510063 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 2df253c185683cb0001b05e6d7c7ecd21c759147..2315b866d00278d5f1b635eebb11de7a22f5f426 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 9568c8a49f962da10d62a11ad58a8143cfd8619d..58fbf0a87b6a2e62a90a8c347bfd172de3b6b836 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 91d3c6dbeba3317758d747a6c6568cae625ea79e..be35b6468cb1f62130b96aa80e7a6fff8b2586e9 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 b444b297d0b2f442d9f5d1d1e1014227ce42128d..4af893601f00e2da9c33101de59ed42ff949904b 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 9352f1e088d27fd4053ce7b6e6796081c1daee92..4a6a7b5a61ba442583cce6d1d6e6338836130f70 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 41ca4d9ac20c0dff5aeb5d2666cae916237a0144..85d514d63a4c8862e9be6f7c4a751f1aa749a6ab 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 93ee28439be56f70dbdaec4a4689209df94f3243..cebde568d1919a0e961601b1e308be8ebb1accc8 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 bae510acdec8facfa985a966173c0512a92e8783..c0c86b3c6adf69076be221308d0fe0fcc48a1c08 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 2e9eba717d1a9adb1f15fe345276699c67c26fca..ab52963dd04c976a21fab1badfffb6f775f30de7 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 d29a9622964c20d32850c6f5c0ced435af22a1a7..e538edaae1f0dbd6d9cdd82f34bb8bc232b7b549 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 c9ab3ba9bcedf4269f3b9d9f00a146d0a7d4a8c8..7ee40da8dbb52021db9427ec84f7b2751236b7d5 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 eec8e143511665a538c6950a4f679ad217aad827..f472ea6ecf6b29febb42b0ffd837720821750376 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 9c982e47eb99308b377e7143d8024c19863b14c5..3eaf56a33964f33623e1ec488e1c4d9a16daa83a 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 f4f1355efc82ec9708e24993525d65aad9b54e1b..6ef3f11878c62ab7b4466679b64949fd89aa03cd 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 78eeb21e66964be9f2457083cf4217b5ac0d5fbd..5863406b459d95408f55beb9f9c7591764fa1097 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 645c980d6b80edd81b1f0886c013c34f884346d6..8f88f5a9c9852286edc87dbbba30693b1568d9aa 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 3cd35a02c28c7164f525f00f7375ac5ef4d6bbb1..1f2672b1e03e9267062ca42835aeea785db7c151 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 2b5252c9e37774963a55626e284878e7ff777414..d1d2c703eab2c75814e767b78439798ff6636ee9 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 646b58dda849192777adc69d66ab54bb14891928..40c92ead85a34526e4ce5d49c09e43595b8ae6c1 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 90117f8156e83c8da98b1f53fdb23573be4f9a03..b7b31f84c10b579432591d7d7caff670b1b6d9b7 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 7167cb6787dba44efdc25a4550d12d24bbb026c6..2b8479bfcd93b822c48daa1f4e6797cf679d8cec 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 84f33d4ea2cd5ec5461d0f8518c2462c3a58d544..2a61094075f86dfd40fff87787b2dba70804b36d 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 300e12118c0093722f1e2b5f527b8627cdbab116..ec187100367edd98585c27ecd9dfef908410ad20 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 7173df254a9150b0f69d527f7cd2f6ab02cfc7e3..2152ff5c04f66df8aacfcd4a2fa0e429f64af5a2 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 d5fe08cc5db7ec83efbfcb2b8b13d6094c2bf986..65bff3d30dd757909ca2e0a59bb6ec214b676d79 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 1f11525d97e805ade146e26fe45cf9eb48ed432c..70ce10c5d9982310a4ac1c6a5c82042ad6442bcd 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 51930b6a83af193f3f802df490df3f00b7930cd1..6b90c757cf4c1c60210ed6101bf0abc06bde6b95 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 3cd6158d83e13f486e8c564cbef8ac809b2d7af8..0678637abd66c6110524fa7bd3ee17d8e4abf8d9 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 099614e16651bb78c78e0c805aa56c72c97fe9e9..f7a62348e3fe022a3bc7ba4faa06b9e19f5c23a0 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 d00230a591b19efc8f4df849b7dbe07cb6cb665c..a2de9c42b702d4a841ba3dd0f8831b5d984273be 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 968cb316d5115cf0d99bebf6d1fb1a47aef3a4e8..1e00b33cc50884be16e404e8f37a55c1e0b1b7d3 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 2cde43321eecc44545a9a1415c9b96d1780f3766..33901d647b728ab761ba41befb91d9225935b4ce 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 ef15402a3bc4948311c69b4b69da9ebd7055ee58..4f59bbaba48f4fcb8ae70e0ced615f19ab71404e 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 0268cf989736f303a224fbd26b0db2e8bf97f2ed..3e066966d8783f8c7e558c9c8677b64406c6b17b 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 5c6c2457386e9145dfaa513697c425f372f1cbfd..e7803d34c425a35a8be366ccd5b9324b8eb41cad 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 ad36b095bb79ce268ba754a2dbe95446b510efc4..ffa00a2eb7704439341debdcf7cafe2310e4ce94 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 87cf2a5c2b2c2957e77fb17e94fa36038e6e318c..7b530327553ad998f0cdf81635e3af218418e414 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 31af405bda843cc691e755cc6bb4a0afec78925f..0ea4a5a96e06533e53ae95e5bebd60cdc16e7832 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 2c064a9824adf84d345829be5d6d80544df5c7d8..a5d4e80a9cf441140d017c8a0228770761999661 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 b133bfcc5848ea8f6ec3c7cab18772ac18bc07b9..738391757f2ccb1a5aa6a8883de0ba127fedea68 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 43fdc24f7e8d6fdf323f096fee6c01682c433a24..1cf2fe889f6adaa885c77bf2c74da9dd9f56a3d8 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 8df0fae21943b64d9bb99ffd462b679592a69742..456b7d723d6660176acbfb82436cf2f938985bab 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 4c05e2b8f4d2bf3bd09309c5e254e8bce02814b6..01d1f749cf021908ead5cb27e30966a17f144ca6 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 cd22a54b2f14b3cd408d64acbbc519786320f573..a5af7c42e62bb7ce641e13d3635c3c5312fc167b 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 d1989cde9f14d0d442531066f96b2a6e9c4f3525..50cda9ea915644baf3d93a02ec8b10e7e24d61d9 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 8f49e165f4d1dd40119143b3b971a2b2f964025c..c62d715235e29ac5fa20639271d79958a57fd853 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 cd33de1c5b7a88bead8fe1c3ee25ae1bb6752c32..210438261a49fab17aeb6fe857846e9bccba74e7 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 715e841c05072edeb469f1e99dc4aa60ad2821c5..f6bb211568769b897a2809a28679bf7aee373ace 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 29350428f1c2a4e5a078ca446eb6e076abaacb00..61c10bf503d229f7a191a12ceb17232b63af4597 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 cca693ae1bd444e5b12d7617f56a160453dafd9e..e53f8e473a78be51d13cff82f0cf17a7f5b24da3 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 23057020aa0fb01abff851ae0fa4e3f75d9cf30c..24f94714694719cafb485a9604a9e5b77dd282c8 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 df370286694f89de7dbfce2cba1a29ae3dfcf7ee..f04f4f72daa0548f9f8e158c9cc96129cf4951fc 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 dea5aa4aa6473a03231ff22e416bb61684c80046..0e12f4e0a76d60ac10dab9b70ad4e12f80e0d0c7 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 76dc74d24fc2ff7b50b9665b7443c56372c70b7c..1a13ab8b8e0da93d7c5bd6017bdd420c49cbc5e6 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 7fbeaec06eb4d514fdebb8aef5e4e1e568489b4c..259278f95cdf12b26bf167be757118c478bf4a69 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 9c0edad90d8b4b3591c7c3a23f4c03b9e42594c1..f0c790451bd6d1fb1f92e38140086fe68a67598a 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 ae8d6806966ba935cbbebd3ec11c5bdaa82ad8c4..37585b47f4e3c4a5ea48ce7513ef08093de7e08d 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 fe83d0d176be4b43d34bacc8f34e10e3973c234f..fb1bf2581efb1b224aadbdd040ec83feab61f88d 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 052fd758722eb0cdc2db322476546228d5e534e8..1fd723fb559d0e14b55bd4b2bf549f77a532ea5c 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 ccb8a6aa1817acec4d71f0b5988faaf547e35599..a04a4338fdac131e5542dc0a41c757e3ed5a46a7 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 36c6eaeffb026b226d39aedff9b97e4688621362..38e0defa7078a9cf57f4d9c8fd7c2a6c3336fdd0 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 4314647e735eff71a8f038263e2f0e4a640d8d24..bd11d25685847a0e597cfd30db4a75d35d444ced 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 41d17067cc739a05ac085443cdbe1fd6e984593e..0e25df4fa9e5cf20e380582a36082e23596d2f0b 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 6ede7dc6c10a9ef858ef6016c87f0abbd93fa9fe..52a0f634948ed00a368157af966b6fc10453730f 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 8671261ba16d3d831a72fc9ef74024f34af52939..52d471c1eeedc63b81be42aee5b337dded08725f 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 03d9fa4192fe611a9119986ce17ed9e18648ee4c..2735fa03b74b0dcfb7d1e14f3600e33f5a15176d 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 ffd2242e305f0827fb742f2c2339041d1859785f..a0f7d3cfa470b0857586b10021290aec5b4fd20f 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 35ed7eb8cff2e6793147cd52c2acec6a9d86e6b6..818dc57b0b2fd862675a59900543f24acaf6ab2b 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 ce5f056009a7d5770ae85d4bce9bfff73eb538b7..55c53d13bea63a5f2cd6bc5380c0c6366d153e32 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 6a8f38b6c3799800b2c283fd231f388584eeeaaf..478ff191ffb4ad20e8daf18b5a35fc750310387c 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 65c124831a0063f0b645062a13559348e5af367a..03ef9f3934347246aa6d4660f6d1bb1ef22239d8 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 0b8d1ee738a45ae82c2e3dc22efca0d2ab6c152a..0e73a7f718e42d2f66d47529b9f749685281093e 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 7edc1fb71fae05288eebd25ce16d82d122c83227..f313eca40fdc96cb5fcd39b1d4df3f4f18ee9358 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 8ad93ee2e92bfe312157b46eabbe251b9db35f9d..a57cfbc038e3cc1522c33b98d9fd648203948337 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 ac51c6d25c4291998bd7ffc6b4d51a0c0148923a..837ff341fd6dda45954f2ec34fd263f24a54d62e 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 11be5952a5066fa30163a3b51143b9dfb41b05e7..609abd51e55fef65ed8ec34157165b3e1a55b700 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 600676f709a927b2c4a568d03fd8869dafff721a..fdd6bedef9bd7d818dadf36049df53ed067d842d 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 3052f64b2403929a62fec3c8257aedec40c8a7a2..aaabdbaec19c6cf389f887669af54a3558f16aba 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 55efc2bdf0bd0a4fd73f938299764222601a5014..43c014f362f60643a9f5f4d798a2c651b6c0af1b 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 53aaa69eda0365c40a909573d7cbb23901311d75..f3417f2311b819bd4a3eb5590b26c338c162de05 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 8509d3c4366e76178c5cdb0a1a75573b9934b3a7..9d03beb40c86909e51671f531ef67e43fe73a0d8 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 16521e3ffc0c5af67712c1cdc1cd3c00e4ad501a..7b9bf93e3701edf92bd47b74d39c8d58de4f690e 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 a68b2644178477dd7fd6a5c0518498e4ff5da860..797c3d5e79e5a71d44fa07b246e0d851bc902d81 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 bff42bf370b9c8849874db4792150fad27328010..ff5d9194d11f3d19304c63833095e6e57db694c9 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 c41178efc9084b7c5fe3712bbb2e885f527bded5..baf97ebadd48a3bde8156b70b3674832090e4cff 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 48273216166e42dcd653f02c03f282290e875b4a..8644946973e57a0168c9bd2ce9491c82660ffa6e 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 1826acf20f7c96cf3fdca744d083c29f2bdfd837..8e523fd9189e562557b36b39671d9e12b7deefa2 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 05a47cf7f06e9345285fe57d7d1688049c7c23ea..beef63fca052bc8f66595e764b8bc6bafb84e579 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 7bbec25e6e158b824561da968d91ee811564858a..72185078ddf8ef6f40a78105a6af09a4f33bf1b4 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 558c64bbed2e66f0c02d0ecd600605f2bfc1e3fa..c4aa4d412fbf56e94a86b46f3a1775e01d325e1d 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 d125e79baf7f4bd74e2773402312d88183b1dc00..502798100f2196e79e26e99657da78b50279de13 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 5e4fd46b7200066d917e5f0a8e00fe9ffa328394..89b57b5c3e17c623ec92e96c246c8326b8a1c2c6 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 548c6ac6e7b06bdc5e9da816836a6bf3a90b7b6a..62b69fb6a08518821a7848c73c1035e325a20017 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 3a0dbfc793f0fc5d6c36b9bc924ec11ff07970ff..8bd1dc5706bf1f423f5d0c7d63a7316c5b9191d0 100644 (file)
@@ -12,6 +12,7 @@
  *
  */
 
+#include <linux/module.h>
 #include <sound/soc.h>
 
 static struct snd_soc_card smdk2443;
index 0677473e6b608ef5df677214258c87680687e640..49dfafbf3df6d6302537222a6695d62398023df9 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 f75e43997d5beb5b27a82f8d023eddd33311538e..ad9ac42522e2539faf84c6286cc1614573e441f2 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 da9c2a264d939d47c3ab4f6f5f65b406f7423d69..23c7fb71ddfa25f4559db84971d544fca1b9b2eb 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 468cff1bb1af62b24372a4abcb6a9d9ad4536c78..a5a56a12034554255cbe520313268ab617eef292 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 85bf541a771d05226b761d6d274e7affd8cba6e2..0222d863632303dd857828510047a0b7ab16c387 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 db74005f37ce78b69d7dffd873d4bc82775e8a64..7da20186b19e63bdf7efe6372a33b41190e82a2f 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 dff64b95f5dcf11671c282f850ea83af520c365b..eb52778d0f90c81bfd81cdf0c6edd7a5151215be 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 3ebebe706ad3bf732114cfd06ede04cf412b183d..621aea155ac1a27a7ad9f62478c5fbfee205215b 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 3d7016e128f9374d2febb9564f404ed02db6b4db..a27c30636b824d5d9289e4a4367fe4cf1e23f556 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 c87e3ff28a0a02957bbd37c2de21d96b661e569e..3474d7befe5ae537fc6e9862050f5e81dcce9daa 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 edacfeb13b94e3956589a999aeb78de2e2815635..11c608570820734f30eafd31d2bba8525f6a7e38 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 e0c621c0553b5606afab9530628c94b994f9e847..ff82b56a886093e43c5456b14592452478d5d4a2 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 9077aa4b3b4ed975da4430789ff3961810e8df0e..18bb6b3335e0424ad5a9830d466c930dc8560fcc 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 a5d3685a5d38049313391ddb8e174edd9c28a21b..1252ab1ebf6940a2652b028c2f41fc9c92a4b260 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 f42e8b9fb17db7baeabaf7152f81123773cdecd0..e174d0811dae33bd4907b7b3f766fa23d9334f7f 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 ee15337353fae5f2cf16f5ab86f94d13440dc6bd..8aa7cec6eab20f834d8910823a590a46807f579d 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 0c12b98484bdd8316418358b5cead696e8774c57..4220bb0f27301aa962964b9eb645fd0f5e51e17c 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 3b55a44146afc419c99fedd7d834dd826bd738e8..3b3c1ba4d235a2368a0540beddb67b1a54e6320a 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 6728fab8c411f05a4a7c10032ba9d0e87aa04c3b..33509de52540bd8c38aea1bbfb121fe20fe238d5 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 2b38a096f46cfb4427e03646a0fa3a51df53bb6c..15ce1e2e8bde1500d0641a8239eef0cca75e6003 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 436def1dfa39fee8b988fcbab0f14a74f277a438..90345ee138f3197121bbb353655f071f5b606a7f 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 dd11d0c63474cd6fb8b2b19fea96e4ab07c42829..475428cf270e01eba85cff0a042c2d358669e7aa 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 a81cf39257bf2ff8aa68df2b7a9ef408887f0ed7..ba2d23ea6424116b53889532930b8945e4a039a0 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 b3a7efa6d960c75eed9f764000eea0fd1f8d46fa..7d95b7697a7310a9c4bc8d50b2175a7b1b8d64c6 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 a4e3f5501847ec640e2851ce4a786668044405eb..28db4ca997ca2b6c3f768de842ea84f567f4fd25 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 3de99af8cb82ccf6def128632603825e57c9ab77..93931def0dce62b3a5e162d7c759ac82f33745f2 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");