summaryrefslogtreecommitdiff
path: root/sound/soc
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-03-05 15:07:33 +0100
committerTakashi Iwai <tiwai@suse.de>2012-03-05 15:07:33 +0100
commit650d6e25cde82fda425995ba77ed4b0ad3be5b8d (patch)
tree44ed9829a0b1797d4eea907aa1ed68273f7e3692 /sound/soc
parent6b21ed851624a03f11ea9ed3f229f56419e03686 (diff)
parentad20ff920c1fd217578e2c637dd50c1878a21c06 (diff)
Merge tag 'asoc-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into topic/asoc
This has been a very active release for ASoC, as well as the usual raft of bugfixes and driver updates there's quite a few framework enhancements. Most are either small or are laying the groundwork for user visible features (especially dynamic PCM), the most directly visible change is the dmaengine library. There's also a bunch of regmap API enhancements pulled into the tree so that either the framework or drivers can take advantage of the new features. Changes include: - Support for widgets not associated with a CODEC, an important part of the dynamic PCM framework. - A library factoring out the common code shared by dmaengine based DMA drivers contributed by Lars-Peter Clausen. This will save a lot of code and make it much easier to deploy enhancements to dmaengine. - Support for binary controls, used for providing runtime configuration of algorithm coefficients. - A new DAPM widget type for regulator supplies allowing drivers for devices that can power down unused supplies while active to do without any per-driver code. - DAPM widgets for DAIs, initially giving a speed boost for playback startup and shutdown and also the basis for CODEC<->CODEC DAI link support. - Support for specifying the number of significant bits on audio interfaces, useful for allowing applications to know how much effort to put into generating data for a larger sample format. - Conversion of the FSI driver used on some SH processors to DMAEngine. - New CODEC drivers for Maxim MAX9768 and Wolfson Microelectronics WM2200.
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/Kconfig3
-rw-r--r--sound/soc/Makefile3
-rw-r--r--sound/soc/atmel/snd-soc-afeb9260.c37
-rw-r--r--sound/soc/blackfin/bf5xx-ad1836.c17
-rw-r--r--sound/soc/blackfin/bf5xx-ad193x.c17
-rw-r--r--sound/soc/blackfin/bf5xx-ad73311.c29
-rw-r--r--sound/soc/blackfin/bf5xx-ssm2602.c20
-rw-r--r--sound/soc/blackfin/bfin-eval-adau1373.c13
-rw-r--r--sound/soc/blackfin/bfin-eval-adau1701.c16
-rw-r--r--sound/soc/blackfin/bfin-eval-adav80x.c13
-rw-r--r--sound/soc/codecs/Kconfig8
-rw-r--r--sound/soc/codecs/Makefile4
-rw-r--r--sound/soc/codecs/ad1836.c6
-rw-r--r--sound/soc/codecs/ad1980.c2
-rw-r--r--sound/soc/codecs/adau1373.c7
-rw-r--r--sound/soc/codecs/adau1701.c2
-rw-r--r--sound/soc/codecs/ak4104.c174
-rw-r--r--sound/soc/codecs/ak4535.c98
-rw-r--r--sound/soc/codecs/ak4535.h2
-rw-r--r--sound/soc/codecs/ak4642.c2
-rw-r--r--sound/soc/codecs/ak4671.c2
-rw-r--r--sound/soc/codecs/alc5623.c8
-rw-r--r--sound/soc/codecs/alc5632.c195
-rw-r--r--sound/soc/codecs/alc5632.h1
-rw-r--r--sound/soc/codecs/cq93vc.c2
-rw-r--r--sound/soc/codecs/cs4270.c4
-rw-r--r--sound/soc/codecs/cs4271.c2
-rw-r--r--sound/soc/codecs/cs42l73.c2
-rw-r--r--sound/soc/codecs/lm4857.c2
-rw-r--r--sound/soc/codecs/max9768.c247
-rw-r--r--sound/soc/codecs/max98088.c4
-rw-r--r--sound/soc/codecs/max98095.c6
-rw-r--r--sound/soc/codecs/max9877.c2
-rw-r--r--sound/soc/codecs/sn95031.c5
-rw-r--r--sound/soc/codecs/ssm2602.c2
-rw-r--r--sound/soc/codecs/stac9766.c2
-rw-r--r--sound/soc/codecs/tlv320aic23.c2
-rw-r--r--sound/soc/codecs/tlv320aic26.c2
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c2
-rw-r--r--sound/soc/codecs/tlv320aic3x.c66
-rw-r--r--sound/soc/codecs/tlv320aic3x.h9
-rw-r--r--sound/soc/codecs/tlv320dac33.c4
-rw-r--r--sound/soc/codecs/tpa6130a2.c4
-rw-r--r--sound/soc/codecs/twl4030.c35
-rw-r--r--sound/soc/codecs/twl6040.c2
-rw-r--r--sound/soc/codecs/uda134x.c6
-rw-r--r--sound/soc/codecs/wl1273.c2
-rw-r--r--sound/soc/codecs/wm2000.c31
-rw-r--r--sound/soc/codecs/wm2200.c2286
-rw-r--r--sound/soc/codecs/wm2200.h3674
-rw-r--r--sound/soc/codecs/wm5100.c306
-rw-r--r--sound/soc/codecs/wm8737.c2
-rw-r--r--sound/soc/codecs/wm8753.c15
-rw-r--r--sound/soc/codecs/wm8770.c5
-rw-r--r--sound/soc/codecs/wm8776.c8
-rw-r--r--sound/soc/codecs/wm8804.c2
-rw-r--r--sound/soc/codecs/wm8904.c18
-rw-r--r--sound/soc/codecs/wm8940.c2
-rw-r--r--sound/soc/codecs/wm8958-dsp2.c16
-rw-r--r--sound/soc/codecs/wm8960.c2
-rw-r--r--sound/soc/codecs/wm8961.c2
-rw-r--r--sound/soc/codecs/wm8962.c316
-rw-r--r--sound/soc/codecs/wm8988.c142
-rw-r--r--sound/soc/codecs/wm8990.c2
-rw-r--r--sound/soc/codecs/wm8991.c2
-rw-r--r--sound/soc/codecs/wm8993.c54
-rw-r--r--sound/soc/codecs/wm8993.h9
-rw-r--r--sound/soc/codecs/wm8994.c300
-rw-r--r--sound/soc/codecs/wm8994.h5
-rw-r--r--sound/soc/codecs/wm8995.c4
-rw-r--r--sound/soc/codecs/wm8996.c197
-rw-r--r--sound/soc/codecs/wm9081.c80
-rw-r--r--sound/soc/codecs/wm9090.c8
-rw-r--r--sound/soc/codecs/wm9705.c2
-rw-r--r--sound/soc/codecs/wm9712.c16
-rw-r--r--sound/soc/codecs/wm9713.c2
-rw-r--r--sound/soc/codecs/wm_hubs.c166
-rw-r--r--sound/soc/codecs/wm_hubs.h12
-rw-r--r--sound/soc/fsl/mpc5200_dma.c1
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c16
-rw-r--r--sound/soc/fsl/p1022_ds.c4
-rw-r--r--sound/soc/imx/Kconfig6
-rw-r--r--sound/soc/imx/imx-pcm-dma-mx2.c221
-rw-r--r--sound/soc/imx/imx-ssi.c30
-rw-r--r--sound/soc/kirkwood/kirkwood-openrd.c46
-rw-r--r--sound/soc/kirkwood/kirkwood-t5325.c47
-rw-r--r--sound/soc/mid-x86/mfld_machine.c2
-rw-r--r--sound/soc/mxs/Kconfig2
-rw-r--r--sound/soc/mxs/mxs-pcm.c157
-rw-r--r--sound/soc/mxs/mxs-pcm.h16
-rw-r--r--sound/soc/mxs/mxs-saif.c56
-rw-r--r--sound/soc/omap/ams-delta.c2
-rw-r--r--sound/soc/omap/n810.c17
-rw-r--r--sound/soc/omap/omap-mcbsp.c8
-rw-r--r--sound/soc/omap/omap-mcbsp.h2
-rw-r--r--sound/soc/omap/rx51.c25
-rw-r--r--sound/soc/pxa/corgi.c14
-rw-r--r--sound/soc/pxa/magician.c2
-rw-r--r--sound/soc/pxa/poodle.c14
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c10
-rw-r--r--sound/soc/pxa/raumfeld.c2
-rw-r--r--sound/soc/pxa/spitz.c14
-rw-r--r--sound/soc/pxa/tosa.c2
-rw-r--r--sound/soc/samsung/ac97.c4
-rw-r--r--sound/soc/samsung/i2s.c14
-rw-r--r--sound/soc/samsung/i2s.h2
-rw-r--r--sound/soc/samsung/littlemill.c3
-rw-r--r--sound/soc/samsung/neo1973_wm8753.c69
-rw-r--r--sound/soc/samsung/pcm.c4
-rw-r--r--sound/soc/samsung/s3c24xx_simtec.c6
-rw-r--r--sound/soc/samsung/smdk_wm8580.c4
-rw-r--r--sound/soc/samsung/smdk_wm9713.c4
-rw-r--r--sound/soc/sh/fsi.c918
-rw-r--r--sound/soc/soc-core.c357
-rw-r--r--sound/soc/soc-dapm.c366
-rw-r--r--sound/soc/soc-dmaengine-pcm.c287
-rw-r--r--sound/soc/soc-io.c6
-rw-r--r--sound/soc/soc-pcm.c68
-rw-r--r--sound/soc/tegra/tegra_alc5632.c130
119 files changed, 9357 insertions, 2380 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 35e662d270e6..91c985599d32 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -25,6 +25,9 @@ if SND_SOC
config SND_SOC_AC97_BUS
bool
+config SND_SOC_DMAENGINE_PCM
+ bool
+
# All the supported SoCs
source "sound/soc/atmel/Kconfig"
source "sound/soc/au1x/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 9ea8ac827adc..2feaf376e94b 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,6 +1,9 @@
snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
snd-soc-core-objs += soc-pcm.o soc-io.o
+snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o
+obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o
+
obj-$(CONFIG_SND_SOC) += snd-soc-core.o
obj-$(CONFIG_SND_SOC) += codecs/
obj-$(CONFIG_SND_SOC) += atmel/
diff --git a/sound/soc/atmel/snd-soc-afeb9260.c b/sound/soc/atmel/snd-soc-afeb9260.c
index 4ca667d477f9..f65f08beac31 100644
--- a/sound/soc/atmel/snd-soc-afeb9260.c
+++ b/sound/soc/atmel/snd-soc-afeb9260.c
@@ -46,29 +46,8 @@ static int afeb9260_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int err;
- /* Set codec DAI configuration */
- err = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S|
- SND_SOC_DAIFMT_NB_IF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (err < 0) {
- printk(KERN_ERR "can't set codec DAI configuration\n");
- return err;
- }
-
- /* Set cpu DAI configuration */
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_IF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (err < 0) {
- printk(KERN_ERR "can't set cpu DAI configuration\n");
- return err;
- }
-
/* Set the codec system clock for DAC and ADC */
err =
snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
@@ -91,7 +70,7 @@ static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Mic Jack", NULL),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route afeb9260_audio_map[] = {
{"Headphone Jack", NULL, "LHPOUT"},
{"Headphone Jack", NULL, "RHPOUT"},
@@ -106,13 +85,6 @@ static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- /* Add afeb9260 specific widgets */
- snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
- ARRAY_SIZE(tlv320aic23_dapm_widgets));
-
- /* Set up afeb9260 specific audio path audio_map */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
snd_soc_dapm_enable_pin(dapm, "Line In");
snd_soc_dapm_enable_pin(dapm, "Mic Jack");
@@ -129,6 +101,8 @@ static struct snd_soc_dai_link afeb9260_dai = {
.platform_name = "atmel_pcm-audio",
.codec_name = "tlv320aic23-codec.0-001a",
.init = afeb9260_tlv320aic23_init,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
+ SND_SOC_DAIFMT_CBM_CFM,
.ops = &afeb9260_ops,
};
@@ -138,6 +112,11 @@ static struct snd_soc_card snd_soc_machine_afeb9260 = {
.owner = THIS_MODULE,
.dai_link = &afeb9260_dai,
.num_links = 1,
+
+ .dapm_widgets = tlv320aic23_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
+ .dapm_routes = afeb9260_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(afeb9260_audio_map),
};
static struct platform_device *afeb9260_snd_device;
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c
index 60962ce6cd4d..d542d4063771 100644
--- a/sound/soc/blackfin/bf5xx-ad1836.c
+++ b/sound/soc/blackfin/bf5xx-ad1836.c
@@ -40,20 +40,8 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7};
int ret = 0;
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
/* set cpu DAI channel mapping */
ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map),
@@ -68,6 +56,9 @@ static struct snd_soc_ops bf5xx_ad1836_ops = {
.hw_params = bf5xx_ad1836_hw_params,
};
+#define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \
+ SND_SOC_DAIFMT_CBM_CFM)
+
static struct snd_soc_dai_link bf5xx_ad1836_dai[] = {
{
.name = "ad1836",
@@ -77,6 +68,7 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai[] = {
.platform_name = "bfin-tdm-pcm-audio",
.codec_name = "spi0.4",
.ops = &bf5xx_ad1836_ops,
+ .dai_fmt = BF5XX_AD1836_DAIFMT,
},
{
.name = "ad1836",
@@ -86,6 +78,7 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai[] = {
.platform_name = "bfin-tdm-pcm-audio",
.codec_name = "spi0.4",
.ops = &bf5xx_ad1836_ops,
+ .dai_fmt = BF5XX_AD1836_DAIFMT,
},
};
diff --git a/sound/soc/blackfin/bf5xx-ad193x.c b/sound/soc/blackfin/bf5xx-ad193x.c
index 2d8d82dbc159..0e55e9f2a514 100644
--- a/sound/soc/blackfin/bf5xx-ad193x.c
+++ b/sound/soc/blackfin/bf5xx-ad193x.c
@@ -60,18 +60,6 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
break;
}
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
/* set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk,
SND_SOC_CLOCK_IN);
@@ -92,6 +80,9 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+#define BF5XX_AD193X_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \
+ SND_SOC_DAIFMT_CBM_CFM)
+
static struct snd_soc_ops bf5xx_ad193x_ops = {
.hw_params = bf5xx_ad193x_hw_params,
};
@@ -105,6 +96,7 @@ static struct snd_soc_dai_link bf5xx_ad193x_dai[] = {
.platform_name = "bfin-tdm-pcm-audio",
.codec_name = "spi0.5",
.ops = &bf5xx_ad193x_ops,
+ .dai_fmt = BF5XX_AD193X_DAIFMT,
},
{
.name = "ad193x",
@@ -114,6 +106,7 @@ static struct snd_soc_dai_link bf5xx_ad193x_dai[] = {
.platform_name = "bfin-tdm-pcm-audio",
.codec_name = "spi0.5",
.ops = &bf5xx_ad193x_ops,
+ .dai_fmt = BF5XX_AD193X_DAIFMT,
},
};
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
index 8e49508596da..61cc91d4a028 100644
--- a/sound/soc/blackfin/bf5xx-ad73311.c
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -145,29 +145,8 @@ static int bf5xx_probe(struct snd_soc_card *card)
return 0;
}
-static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int ret = 0;
-
- pr_debug("%s rate %d format %x\n", __func__, params_rate(params),
- params_format(params));
-
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-
-static struct snd_soc_ops bf5xx_ad73311_ops = {
- .hw_params = bf5xx_ad73311_hw_params,
-};
+#define BF5XX_AD7311_DAI_FMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | \
+ SND_SOC_DAIFMT_CBM_CFM)
static struct snd_soc_dai_link bf5xx_ad73311_dai[] = {
{
@@ -177,7 +156,7 @@ static struct snd_soc_dai_link bf5xx_ad73311_dai[] = {
.codec_dai_name = "ad73311-hifi",
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "ad73311",
- .ops = &bf5xx_ad73311_ops,
+ .dai_fmt = BF5XX_AD7311_DAI_FMT,
},
{
.name = "ad73311",
@@ -186,7 +165,7 @@ static struct snd_soc_dai_link bf5xx_ad73311_dai[] = {
.codec_dai_name = "ad73311-hifi",
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "ad73311",
- .ops = &bf5xx_ad73311_ops,
+ .dai_fmt = BF5XX_AD7311_DAI_FMT,
},
};
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c
index 030303238042..df3ac73f8778 100644
--- a/sound/soc/blackfin/bf5xx-ssm2602.c
+++ b/sound/soc/blackfin/bf5xx-ssm2602.c
@@ -49,7 +49,6 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
unsigned int clk = 0;
int ret = 0;
@@ -75,21 +74,6 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
break;
}
- /*
- * CODEC is master for BCLK and LRC in this configuration.
- */
-
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
ret = snd_soc_dai_set_sysclk(codec_dai, SSM2602_SYSCLK, clk,
SND_SOC_CLOCK_IN);
if (ret < 0)
@@ -102,6 +86,10 @@ static struct snd_soc_ops bf5xx_ssm2602_ops = {
.hw_params = bf5xx_ssm2602_hw_params,
};
+/* CODEC is master for BCLK and LRC in this configuration. */
+#define BF5XX_SSM2602_DAIFMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \
+ SND_SOC_DAIFMT_CBM_CFM)
+
static struct snd_soc_dai_link bf5xx_ssm2602_dai[] = {
{
.name = "ssm2602",
diff --git a/sound/soc/blackfin/bfin-eval-adau1373.c b/sound/soc/blackfin/bfin-eval-adau1373.c
index 26b271c62efa..f3adbdbdd5e1 100644
--- a/sound/soc/blackfin/bfin-eval-adau1373.c
+++ b/sound/soc/blackfin/bfin-eval-adau1373.c
@@ -67,21 +67,10 @@ static int bfin_eval_adau1373_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
int ret;
int pll_rate;
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret)
- return ret;
-
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret)
- return ret;
-
switch (params_rate(params)) {
case 48000:
case 8000:
@@ -143,6 +132,8 @@ static struct snd_soc_dai_link bfin_eval_adau1373_dai = {
.codec_name = "adau1373.0-001a",
.ops = &bfin_eval_adau1373_ops,
.init = bfin_eval_adau1373_codec_init,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
};
static struct snd_soc_card bfin_eval_adau1373 = {
diff --git a/sound/soc/blackfin/bfin-eval-adau1701.c b/sound/soc/blackfin/bfin-eval-adau1701.c
index c0064fa1dca6..b0531fc9d814 100644
--- a/sound/soc/blackfin/bfin-eval-adau1701.c
+++ b/sound/soc/blackfin/bfin-eval-adau1701.c
@@ -37,20 +37,9 @@ static int bfin_eval_adau1701_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
int ret;
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret)
- return ret;
-
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret)
- return ret;
-
ret = snd_soc_dai_set_sysclk(codec_dai, ADAU1701_CLK_SRC_OSC, 12288000,
SND_SOC_CLOCK_IN);
@@ -61,6 +50,9 @@ static struct snd_soc_ops bfin_eval_adau1701_ops = {
.hw_params = bfin_eval_adau1701_hw_params,
};
+#define BFIN_EVAL_ADAU1701_DAI_FMT (SND_SOC_DAIFMT_I2S | \
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM)
+
static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = {
{
.name = "adau1701",
@@ -70,6 +62,7 @@ static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = {
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "adau1701.0-0034",
.ops = &bfin_eval_adau1701_ops,
+ .dai_fmt = BFIN_EVAL_ADAU1701_DAI_FMT,
},
{
.name = "adau1701",
@@ -79,6 +72,7 @@ static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = {
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "adau1701.0-0034",
.ops = &bfin_eval_adau1701_ops,
+ .dai_fmt = BFIN_EVAL_ADAU1701_DAI_FMT,
},
};
diff --git a/sound/soc/blackfin/bfin-eval-adav80x.c b/sound/soc/blackfin/bfin-eval-adav80x.c
index 4ef079f95e2e..84b09987b7f3 100644
--- a/sound/soc/blackfin/bfin-eval-adav80x.c
+++ b/sound/soc/blackfin/bfin-eval-adav80x.c
@@ -34,20 +34,9 @@ static int bfin_eval_adav80x_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
int ret;
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret)
- return ret;
-
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret)
- return ret;
-
ret = snd_soc_dai_set_pll(codec_dai, ADAV80X_PLL1, ADAV80X_PLL_SRC_XTAL,
27000000, params_rate(params) * 256);
if (ret)
@@ -88,6 +77,8 @@ static struct snd_soc_dai_link bfin_eval_adav80x_dais[] = {
.platform_name = "bfin-i2s-pcm-audio",
.init = bfin_eval_adav80x_codec_init,
.ops = &bfin_eval_adav80x_ops,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
},
};
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 7c205e77d83a..6508e8b790bb 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -40,6 +40,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_MAX98088 if I2C
select SND_SOC_MAX98095 if I2C
select SND_SOC_MAX9850 if I2C
+ select SND_SOC_MAX9768 if I2C
select SND_SOC_MAX9877 if I2C
select SND_SOC_PCM3008
select SND_SOC_RT5631 if I2C
@@ -62,6 +63,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WL1273 if MFD_WL1273_CORE
select SND_SOC_WM1250_EV1 if I2C
select SND_SOC_WM2000 if I2C
+ select SND_SOC_WM2200 if I2C
select SND_SOC_WM5100 if I2C
select SND_SOC_WM8350 if MFD_WM8350
select SND_SOC_WM8400 if MFD_WM8400
@@ -292,6 +294,9 @@ config SND_SOC_WM1250_EV1
config SND_SOC_WM2000
tristate
+config SND_SOC_WM2200
+ tristate
+
config SND_SOC_WM5100
tristate
@@ -425,6 +430,9 @@ config SND_SOC_WM9713
config SND_SOC_LM4857
tristate
+config SND_SOC_MAX9768
+ tristate
+
config SND_SOC_MAX9877
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index de8078178f86..6662eb0cdcc0 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -25,6 +25,7 @@ snd-soc-dmic-objs := dmic.o
snd-soc-jz4740-codec-objs := jz4740.o
snd-soc-l3-objs := l3.o
snd-soc-lm4857-objs := lm4857.o
+snd-soc-max9768-objs := max9768.o
snd-soc-max98088-objs := max98088.o
snd-soc-max98095-objs := max98095.o
snd-soc-max9850-objs := max9850.o
@@ -51,6 +52,7 @@ snd-soc-uda1380-objs := uda1380.o
snd-soc-wl1273-objs := wl1273.o
snd-soc-wm1250-ev1-objs := wm1250-ev1.o
snd-soc-wm2000-objs := wm2000.o
+snd-soc-wm2200-objs := wm2200.o
snd-soc-wm5100-objs := wm5100.o wm5100-tables.o
snd-soc-wm8350-objs := wm8350.o
snd-soc-wm8400-objs := wm8400.o
@@ -129,6 +131,7 @@ obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
+obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o
obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
@@ -153,6 +156,7 @@ obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o
obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o
+obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o
obj-$(CONFIG_SND_SOC_WM5100) += snd-soc-wm5100.o
obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index 982d201c2e86..12e3b4118557 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -277,7 +277,7 @@ static int ad1836_probe(struct snd_soc_codec *codec)
if (ad1836->type == AD1836) {
/* left/right diff:PGA/MUX */
snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A);
- ret = snd_soc_add_controls(codec, ad1836_controls,
+ ret = snd_soc_add_codec_controls(codec, ad1836_controls,
ARRAY_SIZE(ad1836_controls));
if (ret)
return ret;
@@ -285,11 +285,11 @@ static int ad1836_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, AD1836_ADC_CTRL3, 0x00);
}
- ret = snd_soc_add_controls(codec, ad183x_dac_controls, num_dacs * 2);
+ ret = snd_soc_add_codec_controls(codec, ad183x_dac_controls, num_dacs * 2);
if (ret)
return ret;
- ret = snd_soc_add_controls(codec, ad183x_adc_controls, num_adcs);
+ ret = snd_soc_add_codec_controls(codec, ad183x_adc_controls, num_adcs);
if (ret)
return ret;
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 9bba7f849464..8c39dddd7d00 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -228,7 +228,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)
ext_status = ac97_read(codec, AC97_EXTENDED_STATUS);
ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800);
- snd_soc_add_controls(codec, ad1980_snd_ac97_controls,
+ snd_soc_add_codec_controls(codec, ad1980_snd_ac97_controls,
ARRAY_SIZE(ad1980_snd_ac97_controls));
return 0;
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index 971ba4529171..44f59064d8de 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -1244,8 +1244,6 @@ static int adau1373_probe(struct snd_soc_codec *codec)
return ret;
}
- codec->dapm.idle_bias_off = true;
-
if (pdata) {
if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting))
return -EINVAL;
@@ -1259,7 +1257,7 @@ static int adau1373_probe(struct snd_soc_codec *codec)
pdata->drc_setting[i]);
}
- snd_soc_add_controls(codec, adau1373_drc_controls,
+ snd_soc_add_codec_controls(codec, adau1373_drc_controls,
pdata->num_drc);
val = 0;
@@ -1284,7 +1282,7 @@ static int adau1373_probe(struct snd_soc_codec *codec)
}
if (!lineout_differential) {
- snd_soc_add_controls(codec, adau1373_lineout2_controls,
+ snd_soc_add_codec_controls(codec, adau1373_lineout2_controls,
ARRAY_SIZE(adau1373_lineout2_controls));
}
@@ -1340,6 +1338,7 @@ static struct snd_soc_codec_driver adau1373_codec_driver = {
.suspend = adau1373_suspend,
.resume = adau1373_resume,
.set_bias_level = adau1373_set_bias_level,
+ .idle_bias_off = true,
.reg_cache_size = ARRAY_SIZE(adau1373_default_regs),
.reg_cache_default = adau1373_default_regs,
.reg_word_size = sizeof(uint8_t),
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 6b325ea03869..78e9ce48bb99 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -457,7 +457,6 @@ static int adau1701_probe(struct snd_soc_codec *codec)
{
int ret;
- codec->dapm.idle_bias_off = 1;
codec->control_data = to_i2c_client(codec->dev);
ret = adau1701_load_firmware(codec);
@@ -473,6 +472,7 @@ static int adau1701_probe(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver adau1701_codec_drv = {
.probe = adau1701_probe,
.set_bias_level = adau1701_set_bias_level,
+ .idle_bias_off = true,
.reg_cache_size = ADAU1701_NUM_REGS,
.reg_word_size = sizeof(u16),
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index d27b5e4cce99..ceb96ecf5588 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -46,75 +46,15 @@
#define DRV_NAME "ak4104-codec"
struct ak4104_private {
- enum snd_soc_control_type control_type;
- void *control_data;
+ struct regmap *regmap;
};
-static int ak4104_fill_cache(struct snd_soc_codec *codec)
-{
- int i;
- u8 *reg_cache = codec->reg_cache;
- struct spi_device *spi = codec->control_data;
-
- for (i = 0; i < codec->driver->reg_cache_size; i++) {
- int ret = spi_w8r8(spi, i | AK4104_READ);
- if (ret < 0) {
- dev_err(&spi->dev, "SPI write failure\n");
- return ret;
- }
-
- reg_cache[i] = ret;
- }
-
- return 0;
-}
-
-static unsigned int ak4104_read_reg_cache(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- u8 *reg_cache = codec->reg_cache;
-
- if (reg >= codec->driver->reg_cache_size)
- return -EINVAL;
-
- return reg_cache[reg];
-}
-
-static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- u8 *cache = codec->reg_cache;
- struct spi_device *spi = codec->control_data;
-
- if (reg >= codec->driver->reg_cache_size)
- return -EINVAL;
-
- /* only write to the hardware if value has changed */
- if (cache[reg] != value) {
- u8 tmp[2] = { (reg & AK4104_REG_MASK) | AK4104_WRITE, value };
-
- if (spi_write(spi, tmp, sizeof(tmp))) {
- dev_err(&spi->dev, "SPI write failed\n");
- return -EIO;
- }
-
- cache[reg] = value;
- }
-
- return 0;
-}
-
static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int format)
{
struct snd_soc_codec *codec = codec_dai->codec;
int val = 0;
-
- val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
- if (val < 0)
- return val;
-
- val &= ~(AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1);
+ int ret;
/* set DAI format */
switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -135,7 +75,13 @@ static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
return -EINVAL;
- return ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
+ ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
+ AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1,
+ val);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
static int ak4104_hw_params(struct snd_pcm_substream *substream,
@@ -148,7 +94,7 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
/* set the IEC958 bits: consumer mode, no copyright bit */
val |= IEC958_AES0_CON_NOT_COPYRIGHT;
- ak4104_spi_write(codec, AK4104_REG_CHN_STATUS(0), val);
+ snd_soc_write(codec, AK4104_REG_CHN_STATUS(0), val);
val = 0;
@@ -167,7 +113,7 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- return ak4104_spi_write(codec, AK4104_REG_CHN_STATUS(3), val);
+ return snd_soc_write(codec, AK4104_REG_CHN_STATUS(3), val);
}
static const struct snd_soc_dai_ops ak4101_dai_ops = {
@@ -192,67 +138,57 @@ static struct snd_soc_dai_driver ak4104_dai = {
static int ak4104_probe(struct snd_soc_codec *codec)
{
struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
- int ret, val;
-
- codec->control_data = ak4104->control_data;
+ int ret;
- /* read all regs and fill the cache */
- ret = ak4104_fill_cache(codec);
- if (ret < 0) {
- dev_err(codec->dev, "failed to fill register cache\n");
+ codec->control_data = ak4104->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+ if (ret != 0)
return ret;
- }
-
- /* read the 'reserved' register - according to the datasheet, it
- * should contain 0x5b. Not a good way to verify the presence of
- * the device, but there is no hardware ID register. */
- if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) !=
- AK4104_RESERVED_VAL)
- return -ENODEV;
/* set power-up and non-reset bits */
- val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
- val |= AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN;
- ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
+ ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
+ AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
+ AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
if (ret < 0)
return ret;
/* enable transmitter */
- val = ak4104_read_reg_cache(codec, AK4104_REG_TX);
- val |= AK4104_TX_TXE;
- ret = ak4104_spi_write(codec, AK4104_REG_TX, val);
+ ret = snd_soc_update_bits(codec, AK4104_REG_TX,
+ AK4104_TX_TXE, AK4104_TX_TXE);
if (ret < 0)
return ret;
- dev_info(codec->dev, "SPI device initialized\n");
return 0;
}
static int ak4104_remove(struct snd_soc_codec *codec)
{
- int val, ret;
-
- val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
- if (val < 0)
- return val;
-
- /* clear power-up and non-reset bits */
- val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
- ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
+ snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
+ AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0);
- return ret;
+ return 0;
}
static struct snd_soc_codec_driver soc_codec_device_ak4104 = {
.probe = ak4104_probe,
.remove = ak4104_remove,
- .reg_cache_size = AK4104_NUM_REGS,
- .reg_word_size = sizeof(u8),
+};
+
+static const struct regmap_config ak4104_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = AK4104_NUM_REGS - 1,
+ .read_flag_mask = AK4104_READ,
+ .write_flag_mask = AK4104_WRITE,
+
+ .cache_type = REGCACHE_RBTREE,
};
static int ak4104_spi_probe(struct spi_device *spi)
{
struct ak4104_private *ak4104;
+ unsigned int val;
int ret;
spi->bits_per_word = 8;
@@ -266,17 +202,41 @@ static int ak4104_spi_probe(struct spi_device *spi)
if (ak4104 == NULL)
return -ENOMEM;
- ak4104->control_data = spi;
- ak4104->control_type = SND_SOC_SPI;
+ ak4104->regmap = regmap_init_spi(spi, &ak4104_regmap);
+ if (IS_ERR(ak4104->regmap)) {
+ ret = PTR_ERR(ak4104->regmap);
+ return ret;
+ }
+
+ /* read the 'reserved' register - according to the datasheet, it
+ * should contain 0x5b. Not a good way to verify the presence of
+ * the device, but there is no hardware ID register. */
+ ret = regmap_read(ak4104->regmap, AK4104_REG_RESERVED, &val);
+ if (ret != 0)
+ goto err;
+ if (val != AK4104_RESERVED_VAL) {
+ ret = -ENODEV;
+ goto err;
+ }
+
spi_set_drvdata(spi, ak4104);
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_device_ak4104, &ak4104_dai, 1);
+ if (ret != 0)
+ goto err;
+
+ return 0;
+
+err:
+ regmap_exit(ak4104->regmap);
return ret;
}
static int __devexit ak4104_spi_remove(struct spi_device *spi)
{
+ struct ak4104_private *ak4101 = spi_get_drvdata(spi);
+ regmap_exit(ak4101->regmap);
snd_soc_unregister_codec(&spi->dev);
return 0;
}
@@ -290,17 +250,7 @@ static struct spi_driver ak4104_spi_driver = {
.remove = __devexit_p(ak4104_spi_remove),
};
-static int __init ak4104_init(void)
-{
- return spi_register_driver(&ak4104_spi_driver);
-}
-module_init(ak4104_init);
-
-static void __exit ak4104_exit(void)
-{
- spi_unregister_driver(&ak4104_spi_driver);
-}
-module_exit(ak4104_exit);
+module_spi_driver(ak4104_spi_driver);
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
MODULE_DESCRIPTION("Asahi Kasei AK4104 ALSA SoC driver");
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 9e809e05d066..838ae8b22b50 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -27,24 +28,43 @@
#include "ak4535.h"
-#define AK4535_VERSION "0.3"
-
/* codec private data */
struct ak4535_priv {
+ struct regmap *regmap;
unsigned int sysclk;
- enum snd_soc_control_type control_type;
};
/*
* ak4535 register cache
*/
-static const u8 ak4535_reg[AK4535_CACHEREGNUM] = {
- 0x00, 0x80, 0x00, 0x03,
- 0x02, 0x00, 0x11, 0x01,
- 0x00, 0x40, 0x36, 0x10,
- 0x00, 0x00, 0x57, 0x00,
+static const struct reg_default ak4535_reg_defaults[] = {
+ { 0, 0x00 },
+ { 1, 0x80 },
+ { 2, 0x00 },
+ { 3, 0x03 },
+ { 4, 0x02 },
+ { 5, 0x00 },
+ { 6, 0x11 },
+ { 7, 0x01 },
+ { 8, 0x00 },
+ { 9, 0x40 },
+ { 10, 0x36 },
+ { 11, 0x10 },
+ { 12, 0x00 },
+ { 13, 0x00 },
+ { 14, 0x57 },
};
+static bool ak4535_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case AK4535_STATUS:
+ return true;
+ default:
+ return false;
+ }
+}
+
static const char *ak4535_mono_gain[] = {"+6dB", "-17dB"};
static const char *ak4535_mono_out[] = {"(L + R)/2", "Hi-Z"};
static const char *ak4535_hp_out[] = {"Stereo", "Mono"};
@@ -372,9 +392,8 @@ static int ak4535_probe(struct snd_soc_codec *codec)
struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
int ret;
- printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4535->control_type);
+ codec->control_data = ak4535->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -382,7 +401,7 @@ static int ak4535_probe(struct snd_soc_codec *codec)
/* power on device */
ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, ak4535_snd_controls,
+ snd_soc_add_codec_controls(codec, ak4535_snd_controls,
ARRAY_SIZE(ak4535_snd_controls));
return 0;
}
@@ -394,22 +413,30 @@ static int ak4535_remove(struct snd_soc_codec *codec)
return 0;
}
+static const struct regmap_config ak4535_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = AK4535_STATUS,
+ .volatile_reg = ak4535_volatile,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = ak4535_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(ak4535_reg_defaults),
+};
+
static struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
.probe = ak4535_probe,
.remove = ak4535_remove,
.suspend = ak4535_suspend,
.resume = ak4535_resume,
.set_bias_level = ak4535_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(ak4535_reg),
- .reg_word_size = sizeof(u8),
- .reg_cache_default = ak4535_reg,
.dapm_widgets = ak4535_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(ak4535_dapm_widgets),
.dapm_routes = ak4535_audio_map,
.num_dapm_routes = ARRAY_SIZE(ak4535_audio_map),
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -421,17 +448,29 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
if (ak4535 == NULL)
return -ENOMEM;
+ ak4535->regmap = regmap_init_i2c(i2c, &ak4535_regmap);
+ if (IS_ERR(ak4535->regmap)) {
+ ret = PTR_ERR(ak4535->regmap);
+ dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
+ return ret;
+ }
+
i2c_set_clientdata(i2c, ak4535);
- ak4535->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_ak4535, &ak4535_dai, 1);
+ if (ret != 0)
+ regmap_exit(ak4535->regmap);
+
return ret;
}
static __devexit int ak4535_i2c_remove(struct i2c_client *client)
{
+ struct ak4535_priv *ak4535 = i2c_get_clientdata(client);
+
snd_soc_unregister_codec(&client->dev);
+ regmap_exit(ak4535->regmap);
return 0;
}
@@ -443,36 +482,15 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id);
static struct i2c_driver ak4535_i2c_driver = {
.driver = {
- .name = "ak4535-codec",
+ .name = "ak4535",
.owner = THIS_MODULE,
},
.probe = ak4535_i2c_probe,
.remove = __devexit_p(ak4535_i2c_remove),
.id_table = ak4535_i2c_id,
};
-#endif
-static int __init ak4535_modinit(void)
-{
- int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- ret = i2c_add_driver(&ak4535_i2c_driver);
- if (ret != 0) {
- printk(KERN_ERR "Failed to register AK4535 I2C driver: %d\n",
- ret);
- }
-#endif
- return ret;
-}
-module_init(ak4535_modinit);
-
-static void __exit ak4535_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_del_driver(&ak4535_i2c_driver);
-#endif
-}
-module_exit(ak4535_exit);
+module_i2c_driver(ak4535_i2c_driver);
MODULE_DESCRIPTION("Soc AK4535 driver");
MODULE_AUTHOR("Richard Purdie");
diff --git a/sound/soc/codecs/ak4535.h b/sound/soc/codecs/ak4535.h
index 0431e5f634a2..402de1d274bf 100644
--- a/sound/soc/codecs/ak4535.h
+++ b/sound/soc/codecs/ak4535.h
@@ -34,6 +34,4 @@
#define AK4535_VOL 0xe
#define AK4535_STATUS 0xf
-#define AK4535_CACHEREGNUM 0x10
-
#endif
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 5ef70b5d27e4..16bd1e7d2384 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -476,7 +476,7 @@ static int ak4642_probe(struct snd_soc_codec *codec)
return ret;
}
- snd_soc_add_controls(codec, ak4642_snd_controls,
+ snd_soc_add_codec_controls(codec, ak4642_snd_controls,
ARRAY_SIZE(ak4642_snd_controls));
ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index a53b152e6a07..5fb7c2a80e6d 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -628,7 +628,7 @@ static int ak4671_probe(struct snd_soc_codec *codec)
return ret;
}
- snd_soc_add_controls(codec, ak4671_snd_controls,
+ snd_soc_add_codec_controls(codec, ak4671_snd_controls,
ARRAY_SIZE(ak4671_snd_controls));
ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index 08f24198c8da..d47b62ddb210 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -925,22 +925,22 @@ static int alc5623_probe(struct snd_soc_codec *codec)
switch (alc5623->id) {
case 0x21:
- snd_soc_add_controls(codec, alc5621_vol_snd_controls,
+ snd_soc_add_codec_controls(codec, alc5621_vol_snd_controls,
ARRAY_SIZE(alc5621_vol_snd_controls));
break;
case 0x22:
- snd_soc_add_controls(codec, alc5622_vol_snd_controls,
+ snd_soc_add_codec_controls(codec, alc5622_vol_snd_controls,
ARRAY_SIZE(alc5622_vol_snd_controls));
break;
case 0x23:
- snd_soc_add_controls(codec, alc5623_vol_snd_controls,
+ snd_soc_add_codec_controls(codec, alc5623_vol_snd_controls,
ARRAY_SIZE(alc5623_vol_snd_controls));
break;
default:
return -EINVAL;
}
- snd_soc_add_controls(codec, alc5623_snd_controls,
+ snd_soc_add_codec_controls(codec, alc5623_snd_controls,
ARRAY_SIZE(alc5623_snd_controls));
snd_soc_dapm_new_controls(dapm, alc5623_dapm_widgets,
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c
index af9c27ae02f0..e2111e0ccad7 100644
--- a/sound/soc/codecs/alc5632.c
+++ b/sound/soc/codecs/alc5632.c
@@ -145,15 +145,14 @@ static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0);
/* -16.5db min scale, 1.5db steps, no mute */
static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0);
static const unsigned int boost_tlv[] = {
- TLV_DB_RANGE_HEAD(3),
- 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
- 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
- 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
+ TLV_DB_RANGE_HEAD(2),
+ 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0),
+ 1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0),
};
/* 0db min scale, 6 db steps, no mute */
static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0);
/* 0db min scalem 0.75db steps, no mute */
-static const DECLARE_TLV_DB_SCALE(vdac_tlv, -3525, 075, 0);
+static const DECLARE_TLV_DB_SCALE(vdac_tlv, -3525, 75, 0);
static const struct snd_kcontrol_new alc5632_vol_snd_controls[] = {
/* left starts at bit 8, right at bit 0 */
@@ -176,26 +175,32 @@ static const struct snd_kcontrol_new alc5632_snd_controls[] = {
ALC5632_AUX_OUT_VOL, 15, 7, 1, 1),
SOC_SINGLE_TLV("Voice DAC Playback Volume",
ALC5632_VOICE_DAC_VOL, 0, 63, 0, vdac_tlv),
- SOC_SINGLE_TLV("Phone Capture Volume",
+ SOC_SINGLE("Voice DAC Playback Switch",
+ ALC5632_VOICE_DAC_VOL, 12, 1, 1),
+ SOC_SINGLE_TLV("Phone Playback Volume",
ALC5632_PHONE_IN_VOL, 8, 31, 1, vol_tlv),
- SOC_DOUBLE_TLV("LineIn Capture Volume",
+ SOC_DOUBLE_TLV("LineIn Playback Volume",
ALC5632_LINE_IN_VOL, 8, 0, 31, 1, vol_tlv),
SOC_DOUBLE_TLV("Master Playback Volume",
ALC5632_STEREO_DAC_IN_VOL, 8, 0, 63, 1, vdac_tlv),
SOC_DOUBLE("Master Playback Switch",
ALC5632_STEREO_DAC_IN_VOL, 15, 7, 1, 1),
- SOC_SINGLE_TLV("Mic1 Capture Volume",
+ SOC_SINGLE_TLV("Mic1 Playback Volume",
ALC5632_MIC_VOL, 8, 31, 1, vol_tlv),
- SOC_SINGLE_TLV("Mic2 Capture Volume",
+ SOC_SINGLE_TLV("Mic2 Playback Volume",
ALC5632_MIC_VOL, 0, 31, 1, vol_tlv),
SOC_DOUBLE_TLV("Rec Capture Volume",
ALC5632_ADC_REC_GAIN, 8, 0, 31, 0, adc_rec_tlv),
SOC_SINGLE_TLV("Mic 1 Boost Volume",
- ALC5632_MIC_CTRL, 10, 2, 0, boost_tlv),
+ ALC5632_MIC_CTRL, 10, 3, 0, boost_tlv),
SOC_SINGLE_TLV("Mic 2 Boost Volume",
- ALC5632_MIC_CTRL, 8, 2, 0, boost_tlv),
- SOC_SINGLE_TLV("Digital Boost Volume",
+ ALC5632_MIC_CTRL, 8, 3, 0, boost_tlv),
+ SOC_SINGLE_TLV("DMIC Boost Capture Volume",
ALC5632_DIGI_BOOST_CTRL, 0, 7, 0, dig_tlv),
+ SOC_SINGLE("DMIC En Capture Switch",
+ ALC5632_DIGI_BOOST_CTRL, 15, 1, 0),
+ SOC_SINGLE("DMIC PreFilter Capture Switch",
+ ALC5632_DIGI_BOOST_CTRL, 12, 1, 0),
};
/*
@@ -244,36 +249,48 @@ SOC_DAPM_SINGLE("VOICE2SPK Playback Switch", ALC5632_VOICE_DAC_VOL, 14, 1, 1),
/* Left Record Mixer */
static const struct snd_kcontrol_new alc5632_captureL_mixer_controls[] = {
-SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5632_ADC_REC_MIXER, 14, 1, 1),
-SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5632_ADC_REC_MIXER, 13, 1, 1),
-SOC_DAPM_SINGLE("LineInL Capture Switch", ALC5632_ADC_REC_MIXER, 12, 1, 1),
-SOC_DAPM_SINGLE("Left Phone Capture Switch", ALC5632_ADC_REC_MIXER, 11, 1, 1),
-SOC_DAPM_SINGLE("HPMixerL Capture Switch", ALC5632_ADC_REC_MIXER, 10, 1, 1),
-SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5632_ADC_REC_MIXER, 9, 1, 1),
-SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5632_ADC_REC_MIXER, 8, 1, 1),
+SOC_DAPM_SINGLE("MIC12REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 14, 1, 1),
+SOC_DAPM_SINGLE("MIC22REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 13, 1, 1),
+SOC_DAPM_SINGLE("LIL2REC Capture Switch", ALC5632_ADC_REC_MIXER, 12, 1, 1),
+SOC_DAPM_SINGLE("PH2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 11, 1, 1),
+SOC_DAPM_SINGLE("HPL2REC Capture Switch", ALC5632_ADC_REC_MIXER, 10, 1, 1),
+SOC_DAPM_SINGLE("SPK2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 9, 1, 1),
+SOC_DAPM_SINGLE("MONO2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 8, 1, 1),
};
/* Right Record Mixer */
static const struct snd_kcontrol_new alc5632_captureR_mixer_controls[] = {
-SOC_DAPM_SINGLE("Mic1 Capture Switch", ALC5632_ADC_REC_MIXER, 6, 1, 1),
-SOC_DAPM_SINGLE("Mic2 Capture Switch", ALC5632_ADC_REC_MIXER, 5, 1, 1),
-SOC_DAPM_SINGLE("LineInR Capture Switch", ALC5632_ADC_REC_MIXER, 4, 1, 1),
-SOC_DAPM_SINGLE("Right Phone Capture Switch", ALC5632_ADC_REC_MIXER, 3, 1, 1),
-SOC_DAPM_SINGLE("HPMixerR Capture Switch", ALC5632_ADC_REC_MIXER, 2, 1, 1),
-SOC_DAPM_SINGLE("SPKMixer Capture Switch", ALC5632_ADC_REC_MIXER, 1, 1, 1),
-SOC_DAPM_SINGLE("MonoMixer Capture Switch", ALC5632_ADC_REC_MIXER, 0, 1, 1),
+SOC_DAPM_SINGLE("MIC12REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 6, 1, 1),
+SOC_DAPM_SINGLE("MIC22REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 5, 1, 1),
+SOC_DAPM_SINGLE("LIR2REC Capture Switch", ALC5632_ADC_REC_MIXER, 4, 1, 1),
+SOC_DAPM_SINGLE("PH2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 3, 1, 1),
+SOC_DAPM_SINGLE("HPR2REC Capture Switch", ALC5632_ADC_REC_MIXER, 2, 1, 1),
+SOC_DAPM_SINGLE("SPK2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 1, 1, 1),
+SOC_DAPM_SINGLE("MONO2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 0, 1, 1),
};
-static const char *alc5632_spk_n_sour_sel[] = {
+/* Dmic Mixer */
+static const struct snd_kcontrol_new alc5632_dmicl_mixer_controls[] = {
+SOC_DAPM_SINGLE("DMICL2ADC Capture Switch", ALC5632_DIGI_BOOST_CTRL, 7, 1, 1),
+};
+static const struct snd_kcontrol_new alc5632_dmicr_mixer_controls[] = {
+SOC_DAPM_SINGLE("DMICR2ADC Capture Switch", ALC5632_DIGI_BOOST_CTRL, 6, 1, 1),
+};
+
+static const char * const alc5632_spk_n_sour_sel[] = {
"RN/-R", "RP/+R", "LN/-R", "Mute"};
-static const char *alc5632_hpl_out_input_sel[] = {
+static const char * const alc5632_hpl_out_input_sel[] = {
"Vmid", "HP Left Mix"};
-static const char *alc5632_hpr_out_input_sel[] = {
+static const char * const alc5632_hpr_out_input_sel[] = {
"Vmid", "HP Right Mix"};
-static const char *alc5632_spkout_input_sel[] = {
+static const char * const alc5632_spkout_input_sel[] = {
"Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
-static const char *alc5632_aux_out_input_sel[] = {
+static const char * const alc5632_aux_out_input_sel[] = {
"Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
+static const char * const alc5632_adcr_func_sel[] = {
+ "Stereo ADC", "Voice ADC"};
+static const char * const alc5632_i2s_out_sel[] = {
+ "ADC LR", "Voice Stereo Digital"};
/* auxout output mux */
static const struct soc_enum alc5632_aux_out_input_enum =
@@ -312,6 +329,17 @@ static const struct soc_enum alc5632_amp_enum =
static const struct snd_kcontrol_new alc5632_amp_mux_controls =
SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum);
+/* ADC output select */
+static const struct soc_enum alc5632_adcr_func_enum =
+ SOC_ENUM_SINGLE(ALC5632_DAC_FUNC_SELECT, 5, 2, alc5632_adcr_func_sel);
+static const struct snd_kcontrol_new alc5632_adcr_func_controls =
+ SOC_DAPM_ENUM("ADCR Mux", alc5632_adcr_func_enum);
+
+/* I2S out select */
+static const struct soc_enum alc5632_i2s_out_enum =
+ SOC_ENUM_SINGLE(ALC5632_I2S_OUT_CTL, 5, 2, alc5632_i2s_out_sel);
+static const struct snd_kcontrol_new alc5632_i2s_out_controls =
+ SOC_DAPM_ENUM("I2SOut Mux", alc5632_i2s_out_enum);
static const struct snd_soc_dapm_widget alc5632_dapm_widgets[] = {
/* Muxes */
@@ -325,6 +353,10 @@ SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0,
&alc5632_hpr_out_mux_controls),
SND_SOC_DAPM_MUX("SpeakerOut N Mux", SND_SOC_NOPM, 0, 0,
&alc5632_spkoutn_mux_controls),
+SND_SOC_DAPM_MUX("ADCR Mux", SND_SOC_NOPM, 0, 0,
+ &alc5632_adcr_func_controls),
+SND_SOC_DAPM_MUX("I2SOut Mux", ALC5632_PWR_MANAG_ADD1, 11, 0,
+ &alc5632_i2s_out_controls),
/* output mixers */
SND_SOC_DAPM_MIXER("HP Mix", SND_SOC_NOPM, 0, 0,
@@ -343,6 +375,12 @@ SND_SOC_DAPM_MIXER("Mono Mix", ALC5632_PWR_MANAG_ADD2, 2, 0,
SND_SOC_DAPM_MIXER("Speaker Mix", ALC5632_PWR_MANAG_ADD2, 3, 0,
&alc5632_speaker_mixer_controls[0],
ARRAY_SIZE(alc5632_speaker_mixer_controls)),
+SND_SOC_DAPM_MIXER("DMICL Mix", SND_SOC_NOPM, 0, 0,
+ &alc5632_dmicl_mixer_controls[0],
+ ARRAY_SIZE(alc5632_dmicl_mixer_controls)),
+SND_SOC_DAPM_MIXER("DMICR Mix", SND_SOC_NOPM, 0, 0,
+ &alc5632_dmicr_mixer_controls[0],
+ ARRAY_SIZE(alc5632_dmicr_mixer_controls)),
/* input mixers */
SND_SOC_DAPM_MIXER("Left Capture Mix", ALC5632_PWR_MANAG_ADD2, 1, 0,
@@ -352,20 +390,28 @@ SND_SOC_DAPM_MIXER("Right Capture Mix", ALC5632_PWR_MANAG_ADD2, 0, 0,
&alc5632_captureR_mixer_controls[0],
ARRAY_SIZE(alc5632_captureR_mixer_controls)),
-SND_SOC_DAPM_DAC("Left DAC", "HiFi Playback",
- ALC5632_PWR_MANAG_ADD2, 9, 0),
-SND_SOC_DAPM_DAC("Right DAC", "HiFi Playback",
- ALC5632_PWR_MANAG_ADD2, 8, 0),
+SND_SOC_DAPM_AIF_IN("AIFRXL", "Left HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIFRXR", "Right HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIFTXL", "Left HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIFTXR", "Right HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("VAIFRX", "Voice Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("VAIFTX", "Voice Capture", 0, SND_SOC_NOPM, 0, 0),
+
+SND_SOC_DAPM_DAC("Voice DAC", NULL, ALC5632_PWR_MANAG_ADD2, 10, 0),
+SND_SOC_DAPM_DAC("Left DAC", NULL, ALC5632_PWR_MANAG_ADD2, 9, 0),
+SND_SOC_DAPM_DAC("Right DAC", NULL, ALC5632_PWR_MANAG_ADD2, 8, 0),
+SND_SOC_DAPM_ADC("Left ADC", NULL, ALC5632_PWR_MANAG_ADD2, 7, 0),
+SND_SOC_DAPM_ADC("Right ADC", NULL, ALC5632_PWR_MANAG_ADD2, 6, 0),
+
SND_SOC_DAPM_MIXER("DAC Left Channel", ALC5632_PWR_MANAG_ADD1, 15, 0, NULL, 0),
SND_SOC_DAPM_MIXER("DAC Right Channel",
ALC5632_PWR_MANAG_ADD1, 14, 0, NULL, 0),
SND_SOC_DAPM_MIXER("I2S Mix", ALC5632_PWR_MANAG_ADD1, 11, 0, NULL, 0),
SND_SOC_DAPM_MIXER("Phone Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("Line Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
-SND_SOC_DAPM_ADC("Left ADC", "HiFi Capture",
- ALC5632_PWR_MANAG_ADD2, 7, 0),
-SND_SOC_DAPM_ADC("Right ADC", "HiFi Capture",
- ALC5632_PWR_MANAG_ADD2, 6, 0),
+SND_SOC_DAPM_MIXER("Voice Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("ADCLR", SND_SOC_NOPM, 0, 0, NULL, 0),
+
SND_SOC_DAPM_PGA("Left Headphone", ALC5632_PWR_MANAG_ADD3, 11, 0, NULL, 0),
SND_SOC_DAPM_PGA("Right Headphone", ALC5632_PWR_MANAG_ADD3, 10, 0, NULL, 0),
SND_SOC_DAPM_PGA("Left Speaker", ALC5632_PWR_MANAG_ADD3, 13, 0, NULL, 0),
@@ -393,10 +439,12 @@ SND_SOC_DAPM_OUTPUT("HPL"),
SND_SOC_DAPM_OUTPUT("HPR"),
SND_SOC_DAPM_OUTPUT("SPKOUT"),
SND_SOC_DAPM_OUTPUT("SPKOUTN"),
+
SND_SOC_DAPM_INPUT("LINEINL"),
SND_SOC_DAPM_INPUT("LINEINR"),
SND_SOC_DAPM_INPUT("PHONEP"),
SND_SOC_DAPM_INPUT("PHONEN"),
+SND_SOC_DAPM_INPUT("DMICDAT"),
SND_SOC_DAPM_INPUT("MIC1"),
SND_SOC_DAPM_INPUT("MIC2"),
SND_SOC_DAPM_VMID("Vmid"),
@@ -404,6 +452,10 @@ SND_SOC_DAPM_VMID("Vmid"),
static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
+ /* Playback streams */
+ {"Left DAC", NULL, "AIFRXL"},
+ {"Right DAC", NULL, "AIFRXR"},
+
/* virtual mixer - mixes left & right channels */
{"I2S Mix", NULL, "Left DAC"},
{"I2S Mix", NULL, "Right DAC"},
@@ -426,9 +478,12 @@ static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
{"HP Mix", "PHONE2HP Playback Switch", "Phone Mix"},
{"HP Mix", "MIC12HP Playback Switch", "MIC1 PGA"},
{"HP Mix", "MIC22HP Playback Switch", "MIC2 PGA"},
-
+ {"HP Mix", "VOICE2HP Playback Switch", "Voice Mix"},
{"HPR Mix", "DACR2HP Playback Switch", "DAC Right Channel"},
{"HPL Mix", "DACL2HP Playback Switch", "DAC Left Channel"},
+ {"HPOut Mix", NULL, "HP Mix"},
+ {"HPOut Mix", NULL, "HPR Mix"},
+ {"HPOut Mix", NULL, "HPL Mix"},
/* speaker mixer */
{"Speaker Mix", "LI2SPK Playback Switch", "Line Mix"},
@@ -436,35 +491,34 @@ static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
{"Speaker Mix", "MIC12SPK Playback Switch", "MIC1 PGA"},
{"Speaker Mix", "MIC22SPK Playback Switch", "MIC2 PGA"},
{"Speaker Mix", "DAC2SPK Playback Switch", "DAC Left Channel"},
-
-
+ {"Speaker Mix", "VOICE2SPK Playback Switch", "Voice Mix"},
/* mono mixer */
{"Mono Mix", "ADC2MONO_L Playback Switch", "Left Capture Mix"},
{"Mono Mix", "ADC2MONO_R Playback Switch", "Right Capture Mix"},
{"Mono Mix", "LI2MONO Playback Switch", "Line Mix"},
- {"Mono Mix", "VOICE2MONO Playback Switch", "Phone Mix"},
{"Mono Mix", "MIC12MONO Playback Switch", "MIC1 PGA"},
{"Mono Mix", "MIC22MONO Playback Switch", "MIC2 PGA"},
{"Mono Mix", "DAC2MONO Playback Switch", "DAC Left Channel"},
+ {"Mono Mix", "VOICE2MONO Playback Switch", "Voice Mix"},
/* Left record mixer */
- {"Left Capture Mix", "LineInL Capture Switch", "LINEINL"},
- {"Left Capture Mix", "Left Phone Capture Switch", "PHONEN"},
- {"Left Capture Mix", "Mic1 Capture Switch", "MIC1 Pre Amp"},
- {"Left Capture Mix", "Mic2 Capture Switch", "MIC2 Pre Amp"},
- {"Left Capture Mix", "HPMixerL Capture Switch", "HPL Mix"},
- {"Left Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
- {"Left Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
+ {"Left Capture Mix", "LIL2REC Capture Switch", "LINEINL"},
+ {"Left Capture Mix", "PH2REC_L Capture Switch", "PHONEN"},
+ {"Left Capture Mix", "MIC12REC_L Capture Switch", "MIC1 Pre Amp"},
+ {"Left Capture Mix", "MIC22REC_L Capture Switch", "MIC2 Pre Amp"},
+ {"Left Capture Mix", "HPL2REC Capture Switch", "HPL Mix"},
+ {"Left Capture Mix", "SPK2REC_L Capture Switch", "Speaker Mix"},
+ {"Left Capture Mix", "MONO2REC_L Capture Switch", "Mono Mix"},
/*Right record mixer */
- {"Right Capture Mix", "LineInR Capture Switch", "LINEINR"},
- {"Right Capture Mix", "Right Phone Capture Switch", "PHONEP"},
- {"Right Capture Mix", "Mic1 Capture Switch", "MIC1 Pre Amp"},
- {"Right Capture Mix", "Mic2 Capture Switch", "MIC2 Pre Amp"},
- {"Right Capture Mix", "HPMixerR Capture Switch", "HPR Mix"},
- {"Right Capture Mix", "SPKMixer Capture Switch", "Speaker Mix"},
- {"Right Capture Mix", "MonoMixer Capture Switch", "Mono Mix"},
+ {"Right Capture Mix", "LIR2REC Capture Switch", "LINEINR"},
+ {"Right Capture Mix", "PH2REC_R Capture Switch", "PHONEP"},
+ {"Right Capture Mix", "MIC12REC_R Capture Switch", "MIC1 Pre Amp"},
+ {"Right Capture Mix", "MIC22REC_R Capture Switch", "MIC2 Pre Amp"},
+ {"Right Capture Mix", "HPR2REC Capture Switch", "HPR Mix"},
+ {"Right Capture Mix", "SPK2REC_R Capture Switch", "Speaker Mix"},
+ {"Right Capture Mix", "MONO2REC_R Capture Switch", "Mono Mix"},
/* headphone left mux */
{"Left Headphone Mux", "HP Left Mix", "HPL Mix"},
@@ -504,10 +558,30 @@ static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
/* left ADC */
{"Left ADC", NULL, "Left Capture Mix"},
+ {"DMICL Mix", "DMICL2ADC Capture Switch", "DMICDAT"},
+ {"Left ADC", NULL, "DMICL Mix"},
+ {"ADCLR", NULL, "Left ADC"},
/* right ADC */
- {"Right ADC", NULL, "Right Capture Mix"},
-
+ {"Right ADC", NULL, "Right Capture Mix"},
+ {"DMICR Mix", "DMICR2ADC Capture Switch", "DMICDAT"},
+ {"Right ADC", NULL, "DMICR Mix"},
+ {"ADCR Mux", "Stereo ADC", "Right ADC"},
+ {"ADCR Mux", "Voice ADC", "Right ADC"},
+ {"ADCLR", NULL, "ADCR Mux"},
+ {"VAIFTX", NULL, "ADCR Mux"},
+
+ /* Digital I2S out */
+ {"I2SOut Mux", "ADC LR", "ADCLR"},
+ {"I2SOut Mux", "Voice Stereo Digital", "VAIFRX"},
+ {"AIFTXL", NULL, "I2SOut Mux"},
+ {"AIFTXR", NULL, "I2SOut Mux"},
+
+ /* Voice Mix */
+ {"Voice DAC", NULL, "VAIFRX"},
+ {"Voice Mix", NULL, "Voice DAC"},
+
+ /* Speaker Output */
{"SpeakerOut N Mux", "RN/-R", "Left Speaker"},
{"SpeakerOut N Mux", "RP/+R", "Left Speaker"},
{"SpeakerOut N Mux", "LN/-R", "Left Speaker"},
@@ -714,6 +788,7 @@ static int alc5632_set_dai_sysclk(struct snd_soc_dai *codec_dai,
struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
switch (freq) {
+ case 4096000:
case 8192000:
case 11289600:
case 12288000:
@@ -994,7 +1069,7 @@ static int alc5632_probe(struct snd_soc_codec *codec)
switch (alc5632->id) {
case 0x5c:
- snd_soc_add_controls(codec, alc5632_vol_snd_controls,
+ snd_soc_add_codec_controls(codec, alc5632_vol_snd_controls,
ARRAY_SIZE(alc5632_vol_snd_controls));
break;
default:
diff --git a/sound/soc/codecs/alc5632.h b/sound/soc/codecs/alc5632.h
index 357651ec074e..1b5bda594ea3 100644
--- a/sound/soc/codecs/alc5632.h
+++ b/sound/soc/codecs/alc5632.h
@@ -51,6 +51,7 @@
#define ALC5632_ADC_REC_MONOMIX (1 << 0)
#define ALC5632_VOICE_DAC_VOL 0x18 /* voice dac vol */
+#define ALC5632_I2S_OUT_CTL 0x1A /* undocumented reg. found in path scheme */
/* ALC5632_OUTPUT_MIXER_CTRL : */
/* same remark as for reg 2 line vs speaker */
#define ALC5632_OUTPUT_MIXER_CTRL 0x1C /* out mix ctrl */
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
index 06d2ea18a54c..064cd6a93516 100644
--- a/sound/soc/codecs/cq93vc.c
+++ b/sound/soc/codecs/cq93vc.c
@@ -157,7 +157,7 @@ static int cq93vc_probe(struct snd_soc_codec *codec)
codec->control_data = davinci_vc;
/* Set controls */
- snd_soc_add_controls(codec, cq93vc_snd_controls,
+ snd_soc_add_codec_controls(codec, cq93vc_snd_controls,
ARRAY_SIZE(cq93vc_snd_controls));
/* Off, with power on */
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 055536645da9..1d672f528662 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -521,7 +521,7 @@ static int cs4270_probe(struct snd_soc_codec *codec)
}
/* Add the non-DAPM controls */
- ret = snd_soc_add_controls(codec, cs4270_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, cs4270_snd_controls,
ARRAY_SIZE(cs4270_snd_controls));
if (ret < 0) {
dev_err(codec->dev, "failed to add controls\n");
@@ -715,7 +715,7 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);
*/
static struct i2c_driver cs4270_i2c_driver = {
.driver = {
- .name = "cs4270-codec",
+ .name = "cs4270",
.owner = THIS_MODULE,
},
.id_table = cs4270_id,
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index f6fe846b6a6c..bf7141280a74 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -513,7 +513,7 @@ static int cs4271_probe(struct snd_soc_codec *codec)
/* Power-up sequence requires 85 uS */
udelay(85);
- return snd_soc_add_controls(codec, cs4271_snd_controls,
+ return snd_soc_add_codec_controls(codec, cs4271_snd_controls,
ARRAY_SIZE(cs4271_snd_controls));
}
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index 9d38db8f1919..78979b3e0e95 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -1113,7 +1113,7 @@ static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream,
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;
+ priv->config[id].spc |= MCK_SCLK_MCLK;
} else {
/* CS42L73 Slave */
priv->config[id].spc &= 0xFC;
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
index 319039240e0f..ba4fafb93e56 100644
--- a/sound/soc/codecs/lm4857.c
+++ b/sound/soc/codecs/lm4857.c
@@ -179,7 +179,7 @@ static int lm4857_probe(struct snd_soc_codec *codec)
codec->control_data = lm4857->i2c;
- ret = snd_soc_add_controls(codec, lm4857_controls,
+ ret = snd_soc_add_codec_controls(codec, lm4857_controls,
ARRAY_SIZE(lm4857_controls));
if (ret)
return ret;
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c
new file mode 100644
index 000000000000..17b3ec2d05cb
--- /dev/null
+++ b/sound/soc/codecs/max9768.c
@@ -0,0 +1,247 @@
+/*
+ * MAX9768 AMP driver
+ *
+ * Copyright (C) 2011, 2012 by Wolfram Sang, Pengutronix e.K.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/regmap.h>
+
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <sound/max9768.h>
+
+/* "Registers" */
+#define MAX9768_VOL 0
+#define MAX9768_CTRL 3
+
+/* Commands */
+#define MAX9768_CTRL_PWM 0x15
+#define MAX9768_CTRL_FILTERLESS 0x16
+
+struct max9768 {
+ struct regmap *regmap;
+ int mute_gpio;
+ int shdn_gpio;
+ u32 flags;
+};
+
+static struct reg_default max9768_default_regs[] = {
+ { 0, 0 },
+ { 3, MAX9768_CTRL_FILTERLESS},
+};
+
+static int max9768_get_gpio(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+ int val = gpio_get_value_cansleep(max9768->mute_gpio);
+
+ ucontrol->value.integer.value[0] = !val;
+
+ return 0;
+}
+
+static int max9768_set_gpio(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+
+ gpio_set_value_cansleep(max9768->mute_gpio, !ucontrol->value.integer.value[0]);
+
+ return 0;
+}
+
+static const unsigned int volume_tlv[] = {
+ TLV_DB_RANGE_HEAD(43),
+ 0, 0, TLV_DB_SCALE_ITEM(-16150, 0, 0),
+ 1, 1, TLV_DB_SCALE_ITEM(-9280, 0, 0),
+ 2, 2, TLV_DB_SCALE_ITEM(-9030, 0, 0),
+ 3, 3, TLV_DB_SCALE_ITEM(-8680, 0, 0),
+ 4, 4, TLV_DB_SCALE_ITEM(-8430, 0, 0),
+ 5, 5, TLV_DB_SCALE_ITEM(-8080, 0, 0),
+ 6, 6, TLV_DB_SCALE_ITEM(-7830, 0, 0),
+ 7, 7, TLV_DB_SCALE_ITEM(-7470, 0, 0),
+ 8, 8, TLV_DB_SCALE_ITEM(-7220, 0, 0),
+ 9, 9, TLV_DB_SCALE_ITEM(-6870, 0, 0),
+ 10, 10, TLV_DB_SCALE_ITEM(-6620, 0, 0),
+ 11, 11, TLV_DB_SCALE_ITEM(-6270, 0, 0),
+ 12, 12, TLV_DB_SCALE_ITEM(-6020, 0, 0),
+ 13, 13, TLV_DB_SCALE_ITEM(-5670, 0, 0),
+ 14, 14, TLV_DB_SCALE_ITEM(-5420, 0, 0),
+ 15, 17, TLV_DB_SCALE_ITEM(-5060, 250, 0),
+ 18, 18, TLV_DB_SCALE_ITEM(-4370, 0, 0),
+ 19, 19, TLV_DB_SCALE_ITEM(-4210, 0, 0),
+ 20, 20, TLV_DB_SCALE_ITEM(-3960, 0, 0),
+ 21, 21, TLV_DB_SCALE_ITEM(-3760, 0, 0),
+ 22, 22, TLV_DB_SCALE_ITEM(-3600, 0, 0),
+ 23, 23, TLV_DB_SCALE_ITEM(-3340, 0, 0),
+ 24, 24, TLV_DB_SCALE_ITEM(-3150, 0, 0),
+ 25, 25, TLV_DB_SCALE_ITEM(-2980, 0, 0),
+ 26, 26, TLV_DB_SCALE_ITEM(-2720, 0, 0),
+ 27, 27, TLV_DB_SCALE_ITEM(-2520, 0, 0),
+ 28, 30, TLV_DB_SCALE_ITEM(-2350, 190, 0),
+ 31, 31, TLV_DB_SCALE_ITEM(-1750, 0, 0),
+ 32, 34, TLV_DB_SCALE_ITEM(-1640, 100, 0),
+ 35, 37, TLV_DB_SCALE_ITEM(-1310, 110, 0),
+ 38, 39, TLV_DB_SCALE_ITEM(-990, 100, 0),
+ 40, 40, TLV_DB_SCALE_ITEM(-710, 0, 0),
+ 41, 41, TLV_DB_SCALE_ITEM(-600, 0, 0),
+ 42, 42, TLV_DB_SCALE_ITEM(-500, 0, 0),
+ 43, 43, TLV_DB_SCALE_ITEM(-340, 0, 0),
+ 44, 44, TLV_DB_SCALE_ITEM(-190, 0, 0),
+ 45, 45, TLV_DB_SCALE_ITEM(-50, 0, 0),
+ 46, 46, TLV_DB_SCALE_ITEM(50, 0, 0),
+ 47, 50, TLV_DB_SCALE_ITEM(120, 40, 0),
+ 51, 57, TLV_DB_SCALE_ITEM(290, 50, 0),
+ 58, 58, TLV_DB_SCALE_ITEM(650, 0, 0),
+ 59, 62, TLV_DB_SCALE_ITEM(700, 60, 0),
+ 63, 63, TLV_DB_SCALE_ITEM(950, 0, 0),
+};
+
+static const struct snd_kcontrol_new max9768_volume[] = {
+ SOC_SINGLE_TLV("Playback Volume", MAX9768_VOL, 0, 63, 0, volume_tlv),
+};
+
+static const struct snd_kcontrol_new max9768_mute[] = {
+ SOC_SINGLE_BOOL_EXT("Playback Switch", 0, max9768_get_gpio, max9768_set_gpio),
+};
+
+static int max9768_probe(struct snd_soc_codec *codec)
+{
+ struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ codec->control_data = max9768->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 2, 6, SND_SOC_REGMAP);
+ if (ret)
+ return ret;
+
+ if (max9768->flags & MAX9768_FLAG_CLASSIC_PWM) {
+ ret = snd_soc_write(codec, MAX9768_CTRL, MAX9768_CTRL_PWM);
+ if (ret)
+ return ret;
+ }
+
+ if (gpio_is_valid(max9768->mute_gpio)) {
+ ret = snd_soc_add_codec_controls(codec, max9768_mute,
+ ARRAY_SIZE(max9768_mute));
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_codec_driver max9768_codec_driver = {
+ .probe = max9768_probe,
+ .controls = max9768_volume,
+ .num_controls = ARRAY_SIZE(max9768_volume),
+};
+
+static const struct regmap_config max9768_i2c_regmap_config = {
+ .reg_bits = 2,
+ .val_bits = 6,
+ .max_register = 3,
+ .reg_defaults = max9768_default_regs,
+ .num_reg_defaults = ARRAY_SIZE(max9768_default_regs),
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int __devinit max9768_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct max9768 *max9768;
+ struct max9768_pdata *pdata = client->dev.platform_data;
+ int err;
+
+ max9768 = devm_kzalloc(&client->dev, sizeof(*max9768), GFP_KERNEL);
+ if (!max9768)
+ return -ENOMEM;
+
+ if (pdata) {
+ /* Mute on powerup to avoid clicks */
+ err = gpio_request_one(pdata->mute_gpio, GPIOF_INIT_HIGH, "MAX9768 Mute");
+ max9768->mute_gpio = err ?: pdata->mute_gpio;
+
+ /* Activate chip by releasing shutdown, enables I2C */
+ err = gpio_request_one(pdata->shdn_gpio, GPIOF_INIT_HIGH, "MAX9768 Shutdown");
+ max9768->shdn_gpio = err ?: pdata->shdn_gpio;
+
+ max9768->flags = pdata->flags;
+ } else {
+ max9768->shdn_gpio = -EINVAL;
+ max9768->mute_gpio = -EINVAL;
+ }
+
+ i2c_set_clientdata(client, max9768);
+
+ max9768->regmap = regmap_init_i2c(client, &max9768_i2c_regmap_config);
+ if (IS_ERR(max9768->regmap)) {
+ err = PTR_ERR(max9768->regmap);
+ goto err_gpio_free;
+ }
+
+ err = snd_soc_register_codec(&client->dev, &max9768_codec_driver, NULL, 0);
+ if (err)
+ goto err_regmap_free;
+
+ return 0;
+
+ err_regmap_free:
+ regmap_exit(max9768->regmap);
+ err_gpio_free:
+ if (gpio_is_valid(max9768->shdn_gpio))
+ gpio_free(max9768->shdn_gpio);
+ if (gpio_is_valid(max9768->mute_gpio))
+ gpio_free(max9768->mute_gpio);
+
+ return err;
+}
+
+static int __devexit max9768_i2c_remove(struct i2c_client *client)
+{
+ struct max9768 *max9768 = i2c_get_clientdata(client);
+
+ snd_soc_unregister_codec(&client->dev);
+ regmap_exit(max9768->regmap);
+
+ if (gpio_is_valid(max9768->shdn_gpio))
+ gpio_free(max9768->shdn_gpio);
+ if (gpio_is_valid(max9768->mute_gpio))
+ gpio_free(max9768->mute_gpio);
+
+ return 0;
+}
+
+static const struct i2c_device_id max9768_i2c_id[] = {
+ { "max9768", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max9768_i2c_id);
+
+static struct i2c_driver max9768_i2c_driver = {
+ .driver = {
+ .name = "max9768",
+ .owner = THIS_MODULE,
+ },
+ .probe = max9768_i2c_probe,
+ .remove = __devexit_p(max9768_i2c_remove),
+ .id_table = max9768_i2c_id,
+};
+module_i2c_driver(max9768_i2c_driver);
+
+MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_DESCRIPTION("ASoC MAX9768 amplifier driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index 006efcfe6dda..af7324b79dd0 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -1908,7 +1908,7 @@ static void max98088_handle_eq_pdata(struct snd_soc_codec *codec)
max98088->eq_enum.texts = max98088->eq_texts;
max98088->eq_enum.max = max98088->eq_textcnt;
- ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+ ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
if (ret != 0)
dev_err(codec->dev, "Failed to add EQ control: %d\n", ret);
}
@@ -2030,7 +2030,7 @@ static int max98088_probe(struct snd_soc_codec *codec)
max98088_handle_pdata(codec);
- snd_soc_add_controls(codec, max98088_snd_controls,
+ snd_soc_add_codec_controls(codec, max98088_snd_controls,
ARRAY_SIZE(max98088_snd_controls));
err_access:
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index fcfa7497d7b7..0bb511a0388d 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -1284,7 +1284,7 @@ static const struct snd_soc_dapm_route max98095_audio_map[] = {
static int max98095_add_widgets(struct snd_soc_codec *codec)
{
- snd_soc_add_controls(codec, max98095_snd_controls,
+ snd_soc_add_codec_controls(codec, max98095_snd_controls,
ARRAY_SIZE(max98095_snd_controls));
return 0;
@@ -1984,7 +1984,7 @@ static void max98095_handle_eq_pdata(struct snd_soc_codec *codec)
max98095->eq_enum.texts = max98095->eq_texts;
max98095->eq_enum.max = max98095->eq_textcnt;
- ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+ ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
if (ret != 0)
dev_err(codec->dev, "Failed to add EQ control: %d\n", ret);
}
@@ -2139,7 +2139,7 @@ static void max98095_handle_bq_pdata(struct snd_soc_codec *codec)
max98095->bq_enum.texts = max98095->bq_texts;
max98095->bq_enum.max = max98095->bq_textcnt;
- ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+ ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
if (ret != 0)
dev_err(codec->dev, "Failed to add Biquad control: %d\n", ret);
}
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c
index dcf6f2a1600a..3a2ba3d8fd6d 100644
--- a/sound/soc/codecs/max9877.c
+++ b/sound/soc/codecs/max9877.c
@@ -253,7 +253,7 @@ static const struct snd_kcontrol_new max9877_controls[] = {
/* This function is called from ASoC machine driver */
int max9877_add_controls(struct snd_soc_codec *codec)
{
- return snd_soc_add_controls(codec, max9877_controls,
+ return snd_soc_add_codec_controls(codec, max9877_controls,
ARRAY_SIZE(max9877_controls));
}
EXPORT_SYMBOL_GPL(max9877_add_controls);
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index f99baa0b8c39..50dbdb9357ea 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -827,8 +827,6 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
{
pr_debug("codec_probe called\n");
- codec->dapm.idle_bias_off = 1;
-
/* PCM interface config
* This sets the pcm rx slot conguration to max 6 slots
* for max 4 dais (2 stereo and 2 mono)
@@ -871,7 +869,7 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, SN95031_SSR2, 0x10);
snd_soc_write(codec, SN95031_SSR3, 0x40);
- snd_soc_add_controls(codec, sn95031_snd_controls,
+ snd_soc_add_codec_controls(codec, sn95031_snd_controls,
ARRAY_SIZE(sn95031_snd_controls));
return 0;
@@ -891,6 +889,7 @@ struct snd_soc_codec_driver sn95031_codec = {
.read = sn95031_read,
.write = sn95031_write,
.set_bias_level = sn95031_set_vaud_bias,
+ .idle_bias_off = true,
.dapm_widgets = sn95031_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(sn95031_dapm_widgets),
.dapm_routes = sn95031_audio_map,
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 333dd98af39c..de2b20544ceb 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -548,7 +548,7 @@ static int ssm2602_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, SSM2602_ROUT1V,
ROUT1V_RLHP_BOTH, ROUT1V_RLHP_BOTH);
- ret = snd_soc_add_controls(codec, ssm2602_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, ssm2602_snd_controls,
ARRAY_SIZE(ssm2602_snd_controls));
if (ret)
return ret;
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index cc0566c22ec1..982e437799a8 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -355,7 +355,7 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec)
stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, stac9766_snd_ac97_controls,
+ snd_soc_add_codec_controls(codec, stac9766_snd_ac97_controls,
ARRAY_SIZE(stac9766_snd_ac97_controls));
return 0;
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index dfa41a96599b..16d55f91a653 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -593,7 +593,7 @@ static int tlv320aic23_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1);
- snd_soc_add_controls(codec, tlv320aic23_snd_controls,
+ snd_soc_add_codec_controls(codec, tlv320aic23_snd_controls,
ARRAY_SIZE(tlv320aic23_snd_controls));
return 0;
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index a038daec682b..802064b5030d 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -389,7 +389,7 @@ static int aic26_probe(struct snd_soc_codec *codec)
/* register controls */
dev_dbg(codec->dev, "Registering controls\n");
- err = snd_soc_add_controls(codec, aic26_snd_controls,
+ err = snd_soc_add_codec_controls(codec, aic26_snd_controls,
ARRAY_SIZE(aic26_snd_controls));
WARN_ON(err < 0);
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 372b0b83bd9f..b0a73d37ed52 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -671,7 +671,7 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
}
aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, aic32x4_snd_controls,
+ snd_soc_add_codec_controls(codec, aic32x4_snd_controls,
ARRAY_SIZE(aic32x4_snd_controls));
aic32x4_add_widgets(codec);
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 492f22f8a4d7..8d20f6ec20f3 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -121,30 +121,6 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
0x00, 0x00, 0x02, /* 100 */
};
-/*
- * read from the aic3x register space. Only use for this function is if
- * wanting to read volatile bits from those registers that has both read-only
- * and read/write bits. All other cases should use snd_soc_read.
- */
-static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
- u8 *value)
-{
- u8 *cache = codec->reg_cache;
-
- if (codec->cache_only)
- return -EINVAL;
- if (reg >= AIC3X_CACHEREGNUM)
- return -1;
-
- codec->cache_bypass = 1;
- *value = snd_soc_read(codec, reg);
- codec->cache_bypass = 0;
-
- cache[reg] = *value;
-
- return 0;
-}
-
#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, \
@@ -1185,25 +1161,6 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state)
-{
- u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
- u8 bit = gpio ? 3: 0;
- u8 val = snd_soc_read(codec, reg) & ~(1 << bit);
- snd_soc_write(codec, reg, val | (!!state << bit));
-}
-EXPORT_SYMBOL_GPL(aic3x_set_gpio);
-
-int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio)
-{
- u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
- u8 val = 0, bit = gpio ? 2 : 1;
-
- aic3x_read(codec, reg, &val);
- return (val >> bit) & 1;
-}
-EXPORT_SYMBOL_GPL(aic3x_get_gpio);
-
void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
int headset_debounce, int button_debounce)
{
@@ -1221,23 +1178,6 @@ void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
snd_soc_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val);
}
-EXPORT_SYMBOL_GPL(aic3x_set_headset_detection);
-
-int aic3x_headset_detected(struct snd_soc_codec *codec)
-{
- u8 val = 0;
- aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
- return (val >> 4) & 1;
-}
-EXPORT_SYMBOL_GPL(aic3x_headset_detected);
-
-int aic3x_button_pressed(struct snd_soc_codec *codec)
-{
- u8 val = 0;
- aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
- return (val >> 5) & 1;
-}
-EXPORT_SYMBOL_GPL(aic3x_button_pressed);
#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000
#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
@@ -1377,7 +1317,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
INIT_LIST_HEAD(&aic3x->list);
aic3x->codec = codec;
- codec->dapm.idle_bias_off = 1;
ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type);
if (ret != 0) {
@@ -1426,10 +1365,10 @@ static int aic3x_probe(struct snd_soc_codec *codec)
(aic3x->setup->gpio_func[1] & 0xf) << 4);
}
- snd_soc_add_controls(codec, aic3x_snd_controls,
+ snd_soc_add_codec_controls(codec, aic3x_snd_controls,
ARRAY_SIZE(aic3x_snd_controls));
if (aic3x->model == AIC3X_MODEL_3007)
- snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
+ snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
aic3x_add_widgets(codec);
list_add(&aic3x->list, &reset_list);
@@ -1471,6 +1410,7 @@ static int aic3x_remove(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
.set_bias_level = aic3x_set_bias_level,
+ .idle_bias_off = true,
.reg_cache_size = ARRAY_SIZE(aic3x_reg),
.reg_word_size = sizeof(u8),
.reg_cache_default = aic3x_reg,
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index 06a19784b162..6f097fb60683 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -212,9 +212,6 @@
/* Default input volume */
#define DEFAULT_GAIN 0x20
-void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state);
-int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio);
-
/* headset detection / button API */
/* The AIC3x supports detection of stereo headsets (GND + left + right signal)
@@ -252,10 +249,4 @@ enum {
#define AIC3X_BUTTON_DEBOUNCE_SHIFT 0
#define AIC3X_BUTTON_DEBOUNCE_MASK 3
-/* see the enums above for valid parameters to this function */
-void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
- int headset_debounce, int button_debounce);
-int aic3x_headset_detected(struct snd_soc_codec *codec);
-int aic3x_button_pressed(struct snd_soc_codec *codec);
-
#endif /* _AIC3X_H */
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index c06c3e4b9127..4587ddd0fbf8 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -1395,7 +1395,6 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
codec->control_data = dac33->control_data;
codec->hw_write = (hw_write_t) i2c_master_send;
- codec->dapm.idle_bias_off = 1;
dac33->codec = codec;
/* Read the tlv320dac33 ID registers */
@@ -1438,7 +1437,7 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
/* Only add the FIFO controls, if we have valid IRQ number */
if (dac33->irq >= 0)
- snd_soc_add_controls(codec, dac33_mode_snd_controls,
+ snd_soc_add_codec_controls(codec, dac33_mode_snd_controls,
ARRAY_SIZE(dac33_mode_snd_controls));
err_power:
@@ -1476,6 +1475,7 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = {
.read = dac33_read_reg_cache,
.write = dac33_write_locked,
.set_bias_level = dac33_set_bias_level,
+ .idle_bias_off = true,
.reg_cache_size = ARRAY_SIZE(dac33_reg),
.reg_word_size = sizeof(u8),
.reg_cache_default = dac33_reg,
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index 363b99dad8e9..6fe4aa3ac544 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -351,10 +351,10 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec)
data = i2c_get_clientdata(tpa6130a2_client);
if (data->id == TPA6140A2)
- return snd_soc_add_controls(codec, tpa6140a2_controls,
+ return snd_soc_add_codec_controls(codec, tpa6140a2_controls,
ARRAY_SIZE(tpa6140a2_controls));
else
- return snd_soc_add_controls(codec, tpa6130a2_controls,
+ return snd_soc_add_codec_controls(codec, tpa6130a2_controls,
ARRAY_SIZE(tpa6130a2_controls));
}
EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index a193f5fa4b3a..170cf9a8fc79 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -1002,8 +1002,8 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol,
unsigned short mask, bitmask;
if (twl4030->configured) {
- printk(KERN_ERR "twl4030 operation mode cannot be "
- "changed on-the-fly\n");
+ dev_err(codec->dev,
+ "operation mode cannot be changed on-the-fly\n");
return -EBUSY;
}
@@ -1800,7 +1800,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
mode |= TWL4030_APLL_RATE_96000;
break;
default:
- printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n",
+ dev_err(codec->dev, "%s: unknown rate %d\n", __func__,
params_rate(params));
return -EINVAL;
}
@@ -1817,7 +1817,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
format |= TWL4030_DATA_WIDTH_32S_24W;
break;
default:
- printk(KERN_ERR "TWL4030 hw params: unknown format %d\n",
+ dev_err(codec->dev, "%s: unknown format %d\n", __func__,
params_format(params));
return -EINVAL;
}
@@ -1867,13 +1867,13 @@ static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
case 38400000:
break;
default:
- dev_err(codec->dev, "Unsupported APLL mclk: %u\n", freq);
+ dev_err(codec->dev, "Unsupported HFCLKIN: %u\n", freq);
return -EINVAL;
}
if ((freq / 1000) != twl4030->sysclk) {
dev_err(codec->dev,
- "Mismatch in APLL mclk: %u (configured: %u)\n",
+ "Mismatch in HFCLKIN: %u (configured: %u)\n",
freq, twl4030->sysclk * 1000);
return -EINVAL;
}
@@ -1983,9 +1983,9 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream,
* not available.
*/
if (twl4030->sysclk != 26000) {
- dev_err(codec->dev, "The board is configured for %u Hz, while"
- "the Voice interface needs 26MHz APLL mclk\n",
- twl4030->sysclk * 1000);
+ dev_err(codec->dev,
+ "%s: HFCLKIN is %u KHz, voice interface needs 26MHz\n",
+ __func__, twl4030->sysclk);
return -EINVAL;
}
@@ -1996,8 +1996,8 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream,
& TWL4030_OPT_MODE;
if (mode != TWL4030_OPTION_2) {
- printk(KERN_ERR "TWL4030 voice startup: "
- "the codec mode is not option2\n");
+ dev_err(codec->dev, "%s: the codec mode is not option2\n",
+ __func__);
return -EINVAL;
}
@@ -2038,7 +2038,7 @@ static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
mode |= TWL4030_SEL_16K;
break;
default:
- printk(KERN_ERR "TWL4030 voice hw params: unknown rate %d\n",
+ dev_err(codec->dev, "%s: unknown rate %d\n", __func__,
params_rate(params));
return -EINVAL;
}
@@ -2067,13 +2067,14 @@ static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai,
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
if (freq != 26000000) {
- dev_err(codec->dev, "Unsupported APLL mclk: %u, the Voice"
- "interface needs 26MHz APLL mclk\n", freq);
+ dev_err(codec->dev,
+ "%s: HFCLKIN is %u KHz, voice interface needs 26MHz\n",
+ __func__, freq / 1000);
return -EINVAL;
}
if ((freq / 1000) != twl4030->sysclk) {
dev_err(codec->dev,
- "Mismatch in APLL mclk: %u (configured: %u)\n",
+ "Mismatch in HFCLKIN: %u (configured: %u)\n",
freq, twl4030->sysclk * 1000);
return -EINVAL;
}
@@ -2221,13 +2222,12 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL);
if (twl4030 == NULL) {
- printk("Can not allocate memroy\n");
+ dev_err(codec->dev, "Can not allocate memory\n");
return -ENOMEM;
}
snd_soc_codec_set_drvdata(codec, twl4030);
/* Set the defaults, and power up the codec */
twl4030->sysclk = twl4030_audio_get_mclk() / 1000;
- codec->dapm.idle_bias_off = 1;
twl4030_init_chip(codec);
@@ -2253,6 +2253,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
.read = twl4030_read_reg_cache,
.write = twl4030_write,
.set_bias_level = twl4030_set_bias_level,
+ .idle_bias_off = true,
.reg_cache_size = sizeof(twl4030_reg),
.reg_word_size = sizeof(u8),
.reg_cache_default = twl4030_reg,
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 1a64edf671a2..2d8c6b825e57 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -1540,7 +1540,6 @@ static int twl6040_probe(struct snd_soc_codec *codec)
priv->codec = codec;
codec->control_data = dev_get_drvdata(codec->dev->parent);
- codec->ignore_pmdown_time = 1;
if (pdata && pdata->hs_left_step && pdata->hs_right_step) {
priv->hs_left_step = pdata->hs_left_step;
@@ -1626,6 +1625,7 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
.reg_cache_size = ARRAY_SIZE(twl6040_reg),
.reg_word_size = sizeof(u8),
.reg_cache_default = twl6040_reg,
+ .ignore_pmdown_time = true,
.controls = twl6040_snd_controls,
.num_controls = ARRAY_SIZE(twl6040_snd_controls),
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index 8f4f469d6411..797b0dde2c68 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -531,15 +531,15 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec)
switch (pd->model) {
case UDA134X_UDA1340:
case UDA134X_UDA1344:
- ret = snd_soc_add_controls(codec, uda1340_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, uda1340_snd_controls,
ARRAY_SIZE(uda1340_snd_controls));
break;
case UDA134X_UDA1341:
- ret = snd_soc_add_controls(codec, uda1341_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, uda1341_snd_controls,
ARRAY_SIZE(uda1341_snd_controls));
break;
case UDA134X_UDA1345:
- ret = snd_soc_add_controls(codec, uda1345_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, uda1345_snd_controls,
ARRAY_SIZE(uda1345_snd_controls));
break;
default:
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index 44aacf927ba9..3d868dc40092 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -464,7 +464,7 @@ static int wl1273_probe(struct snd_soc_codec *codec)
snd_soc_codec_set_drvdata(codec, wl1273);
- r = snd_soc_add_controls(codec, wl1273_controls,
+ r = snd_soc_add_codec_controls(codec, wl1273_controls,
ARRAY_SIZE(wl1273_controls));
if (r)
kfree(wl1273);
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index c2880907fced..a75c3766aede 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -733,8 +733,9 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
struct wm2000_priv *wm2000;
struct wm2000_platform_data *pdata;
const char *filename;
- const struct firmware *fw;
- int reg, ret;
+ const struct firmware *fw = NULL;
+ int ret;
+ int reg;
u16 id;
wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv),
@@ -751,7 +752,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
ret = PTR_ERR(wm2000->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
ret);
- goto err;
+ goto out;
}
/* Verify that this is a WM2000 */
@@ -763,7 +764,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_regmap;
+ goto out_regmap_exit;
}
reg = wm2000_read(i2c, WM2000_REG_REVISON);
@@ -782,7 +783,7 @@ 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_regmap;
+ goto out_regmap_exit;
}
/* Pre-cook the concatenation of the register address onto the image */
@@ -793,15 +794,13 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
if (wm2000->anc_download == NULL) {
dev_err(&i2c->dev, "Out of memory\n");
ret = -ENOMEM;
- goto err_fw;
+ goto out_regmap_exit;
}
wm2000->anc_download[0] = 0x80;
wm2000->anc_download[1] = 0x00;
memcpy(wm2000->anc_download + 2, fw->data, fw->size);
- release_firmware(fw);
-
wm2000->anc_eng_ena = 1;
wm2000->anc_active = 1;
wm2000->spk_ena = 1;
@@ -809,18 +808,14 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
wm2000_reset(wm2000);
- ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000,
- NULL, 0);
- if (ret != 0)
- goto err_fw;
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0);
+ if (!ret)
+ goto out;
- return 0;
-
-err_fw:
- release_firmware(fw);
-err_regmap:
+out_regmap_exit:
regmap_exit(wm2000->regmap);
-err:
+out:
+ release_firmware(fw);
return ret;
}
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c
new file mode 100644
index 000000000000..acbdc5fde923
--- /dev/null
+++ b/sound/soc/codecs/wm2200.c
@@ -0,0 +1,2286 @@
+/*
+ * wm2200.c -- WM2200 ALSA SoC Audio driver
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/gcd.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/fixed.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/wm2200.h>
+
+#include "wm2200.h"
+
+/* The code assumes DCVDD is generated internally */
+#define WM2200_NUM_CORE_SUPPLIES 2
+static const char *wm2200_core_supply_names[WM2200_NUM_CORE_SUPPLIES] = {
+ "DBVDD",
+ "LDOVDD",
+};
+
+struct wm2200_fll {
+ int fref;
+ int fout;
+ int src;
+ struct completion lock;
+};
+
+/* codec private data */
+struct wm2200_priv {
+ struct regmap *regmap;
+ struct device *dev;
+ struct snd_soc_codec *codec;
+ struct wm2200_pdata pdata;
+ struct regulator_bulk_data core_supplies[WM2200_NUM_CORE_SUPPLIES];
+
+ struct completion fll_lock;
+ int fll_fout;
+ int fll_fref;
+ int fll_src;
+
+ int rev;
+ int sysclk;
+};
+
+static struct reg_default wm2200_reg_defaults[] = {
+ { 0x000B, 0x0000 }, /* R11 - Tone Generator 1 */
+ { 0x0102, 0x0000 }, /* R258 - Clocking 3 */
+ { 0x0103, 0x0011 }, /* R259 - Clocking 4 */
+ { 0x0111, 0x0000 }, /* R273 - FLL Control 1 */
+ { 0x0112, 0x0000 }, /* R274 - FLL Control 2 */
+ { 0x0113, 0x0000 }, /* R275 - FLL Control 3 */
+ { 0x0114, 0x0000 }, /* R276 - FLL Control 4 */
+ { 0x0116, 0x0177 }, /* R278 - FLL Control 6 */
+ { 0x0117, 0x0004 }, /* R279 - FLL Control 7 */
+ { 0x0119, 0x0000 }, /* R281 - FLL EFS 1 */
+ { 0x011A, 0x0002 }, /* R282 - FLL EFS 2 */
+ { 0x0200, 0x0000 }, /* R512 - Mic Charge Pump 1 */
+ { 0x0201, 0x03FF }, /* R513 - Mic Charge Pump 2 */
+ { 0x0202, 0x9BDE }, /* R514 - DM Charge Pump 1 */
+ { 0x020C, 0x0000 }, /* R524 - Mic Bias Ctrl 1 */
+ { 0x020D, 0x0000 }, /* R525 - Mic Bias Ctrl 2 */
+ { 0x020F, 0x0000 }, /* R527 - Ear Piece Ctrl 1 */
+ { 0x0210, 0x0000 }, /* R528 - Ear Piece Ctrl 2 */
+ { 0x0301, 0x0000 }, /* R769 - Input Enables */
+ { 0x0302, 0x2240 }, /* R770 - IN1L Control */
+ { 0x0303, 0x0040 }, /* R771 - IN1R Control */
+ { 0x0304, 0x2240 }, /* R772 - IN2L Control */
+ { 0x0305, 0x0040 }, /* R773 - IN2R Control */
+ { 0x0306, 0x2240 }, /* R774 - IN3L Control */
+ { 0x0307, 0x0040 }, /* R775 - IN3R Control */
+ { 0x030A, 0x0000 }, /* R778 - RXANC_SRC */
+ { 0x030B, 0x0022 }, /* R779 - Input Volume Ramp */
+ { 0x030C, 0x0180 }, /* R780 - ADC Digital Volume 1L */
+ { 0x030D, 0x0180 }, /* R781 - ADC Digital Volume 1R */
+ { 0x030E, 0x0180 }, /* R782 - ADC Digital Volume 2L */
+ { 0x030F, 0x0180 }, /* R783 - ADC Digital Volume 2R */
+ { 0x0310, 0x0180 }, /* R784 - ADC Digital Volume 3L */
+ { 0x0311, 0x0180 }, /* R785 - ADC Digital Volume 3R */
+ { 0x0400, 0x0000 }, /* R1024 - Output Enables */
+ { 0x0401, 0x0000 }, /* R1025 - DAC Volume Limit 1L */
+ { 0x0402, 0x0000 }, /* R1026 - DAC Volume Limit 1R */
+ { 0x0403, 0x0000 }, /* R1027 - DAC Volume Limit 2L */
+ { 0x0404, 0x0000 }, /* R1028 - DAC Volume Limit 2R */
+ { 0x0409, 0x0000 }, /* R1033 - DAC AEC Control 1 */
+ { 0x040A, 0x0022 }, /* R1034 - Output Volume Ramp */
+ { 0x040B, 0x0180 }, /* R1035 - DAC Digital Volume 1L */
+ { 0x040C, 0x0180 }, /* R1036 - DAC Digital Volume 1R */
+ { 0x040D, 0x0180 }, /* R1037 - DAC Digital Volume 2L */
+ { 0x040E, 0x0180 }, /* R1038 - DAC Digital Volume 2R */
+ { 0x0417, 0x0069 }, /* R1047 - PDM 1 */
+ { 0x0418, 0x0000 }, /* R1048 - PDM 2 */
+ { 0x0500, 0x0000 }, /* R1280 - Audio IF 1_1 */
+ { 0x0501, 0x0008 }, /* R1281 - Audio IF 1_2 */
+ { 0x0502, 0x0000 }, /* R1282 - Audio IF 1_3 */
+ { 0x0503, 0x0000 }, /* R1283 - Audio IF 1_4 */
+ { 0x0504, 0x0000 }, /* R1284 - Audio IF 1_5 */
+ { 0x0505, 0x0001 }, /* R1285 - Audio IF 1_6 */
+ { 0x0506, 0x0001 }, /* R1286 - Audio IF 1_7 */
+ { 0x0507, 0x0000 }, /* R1287 - Audio IF 1_8 */
+ { 0x0508, 0x0000 }, /* R1288 - Audio IF 1_9 */
+ { 0x0509, 0x0000 }, /* R1289 - Audio IF 1_10 */
+ { 0x050A, 0x0000 }, /* R1290 - Audio IF 1_11 */
+ { 0x050B, 0x0000 }, /* R1291 - Audio IF 1_12 */
+ { 0x050C, 0x0000 }, /* R1292 - Audio IF 1_13 */
+ { 0x050D, 0x0000 }, /* R1293 - Audio IF 1_14 */
+ { 0x050E, 0x0000 }, /* R1294 - Audio IF 1_15 */
+ { 0x050F, 0x0000 }, /* R1295 - Audio IF 1_16 */
+ { 0x0510, 0x0000 }, /* R1296 - Audio IF 1_17 */
+ { 0x0511, 0x0000 }, /* R1297 - Audio IF 1_18 */
+ { 0x0512, 0x0000 }, /* R1298 - Audio IF 1_19 */
+ { 0x0513, 0x0000 }, /* R1299 - Audio IF 1_20 */
+ { 0x0514, 0x0000 }, /* R1300 - Audio IF 1_21 */
+ { 0x0515, 0x0001 }, /* R1301 - Audio IF 1_22 */
+ { 0x0600, 0x0000 }, /* R1536 - OUT1LMIX Input 1 Source */
+ { 0x0601, 0x0080 }, /* R1537 - OUT1LMIX Input 1 Volume */
+ { 0x0602, 0x0000 }, /* R1538 - OUT1LMIX Input 2 Source */
+ { 0x0603, 0x0080 }, /* R1539 - OUT1LMIX Input 2 Volume */
+ { 0x0604, 0x0000 }, /* R1540 - OUT1LMIX Input 3 Source */
+ { 0x0605, 0x0080 }, /* R1541 - OUT1LMIX Input 3 Volume */
+ { 0x0606, 0x0000 }, /* R1542 - OUT1LMIX Input 4 Source */
+ { 0x0607, 0x0080 }, /* R1543 - OUT1LMIX Input 4 Volume */
+ { 0x0608, 0x0000 }, /* R1544 - OUT1RMIX Input 1 Source */
+ { 0x0609, 0x0080 }, /* R1545 - OUT1RMIX Input 1 Volume */
+ { 0x060A, 0x0000 }, /* R1546 - OUT1RMIX Input 2 Source */
+ { 0x060B, 0x0080 }, /* R1547 - OUT1RMIX Input 2 Volume */
+ { 0x060C, 0x0000 }, /* R1548 - OUT1RMIX Input 3 Source */
+ { 0x060D, 0x0080 }, /* R1549 - OUT1RMIX Input 3 Volume */
+ { 0x060E, 0x0000 }, /* R1550 - OUT1RMIX Input 4 Source */
+ { 0x060F, 0x0080 }, /* R1551 - OUT1RMIX Input 4 Volume */
+ { 0x0610, 0x0000 }, /* R1552 - OUT2LMIX Input 1 Source */
+ { 0x0611, 0x0080 }, /* R1553 - OUT2LMIX Input 1 Volume */
+ { 0x0612, 0x0000 }, /* R1554 - OUT2LMIX Input 2 Source */
+ { 0x0613, 0x0080 }, /* R1555 - OUT2LMIX Input 2 Volume */
+ { 0x0614, 0x0000 }, /* R1556 - OUT2LMIX Input 3 Source */
+ { 0x0615, 0x0080 }, /* R1557 - OUT2LMIX Input 3 Volume */
+ { 0x0616, 0x0000 }, /* R1558 - OUT2LMIX Input 4 Source */
+ { 0x0617, 0x0080 }, /* R1559 - OUT2LMIX Input 4 Volume */
+ { 0x0618, 0x0000 }, /* R1560 - OUT2RMIX Input 1 Source */
+ { 0x0619, 0x0080 }, /* R1561 - OUT2RMIX Input 1 Volume */
+ { 0x061A, 0x0000 }, /* R1562 - OUT2RMIX Input 2 Source */
+ { 0x061B, 0x0080 }, /* R1563 - OUT2RMIX Input 2 Volume */
+ { 0x061C, 0x0000 }, /* R1564 - OUT2RMIX Input 3 Source */
+ { 0x061D, 0x0080 }, /* R1565 - OUT2RMIX Input 3 Volume */
+ { 0x061E, 0x0000 }, /* R1566 - OUT2RMIX Input 4 Source */
+ { 0x061F, 0x0080 }, /* R1567 - OUT2RMIX Input 4 Volume */
+ { 0x0620, 0x0000 }, /* R1568 - AIF1TX1MIX Input 1 Source */
+ { 0x0621, 0x0080 }, /* R1569 - AIF1TX1MIX Input 1 Volume */
+ { 0x0622, 0x0000 }, /* R1570 - AIF1TX1MIX Input 2 Source */
+ { 0x0623, 0x0080 }, /* R1571 - AIF1TX1MIX Input 2 Volume */
+ { 0x0624, 0x0000 }, /* R1572 - AIF1TX1MIX Input 3 Source */
+ { 0x0625, 0x0080 }, /* R1573 - AIF1TX1MIX Input 3 Volume */
+ { 0x0626, 0x0000 }, /* R1574 - AIF1TX1MIX Input 4 Source */
+ { 0x0627, 0x0080 }, /* R1575 - AIF1TX1MIX Input 4 Volume */
+ { 0x0628, 0x0000 }, /* R1576 - AIF1TX2MIX Input 1 Source */
+ { 0x0629, 0x0080 }, /* R1577 - AIF1TX2MIX Input 1 Volume */
+ { 0x062A, 0x0000 }, /* R1578 - AIF1TX2MIX Input 2 Source */
+ { 0x062B, 0x0080 }, /* R1579 - AIF1TX2MIX Input 2 Volume */
+ { 0x062C, 0x0000 }, /* R1580 - AIF1TX2MIX Input 3 Source */
+ { 0x062D, 0x0080 }, /* R1581 - AIF1TX2MIX Input 3 Volume */
+ { 0x062E, 0x0000 }, /* R1582 - AIF1TX2MIX Input 4 Source */
+ { 0x062F, 0x0080 }, /* R1583 - AIF1TX2MIX Input 4 Volume */
+ { 0x0630, 0x0000 }, /* R1584 - AIF1TX3MIX Input 1 Source */
+ { 0x0631, 0x0080 }, /* R1585 - AIF1TX3MIX Input 1 Volume */
+ { 0x0632, 0x0000 }, /* R1586 - AIF1TX3MIX Input 2 Source */
+ { 0x0633, 0x0080 }, /* R1587 - AIF1TX3MIX Input 2 Volume */
+ { 0x0634, 0x0000 }, /* R1588 - AIF1TX3MIX Input 3 Source */
+ { 0x0635, 0x0080 }, /* R1589 - AIF1TX3MIX Input 3 Volume */
+ { 0x0636, 0x0000 }, /* R1590 - AIF1TX3MIX Input 4 Source */
+ { 0x0637, 0x0080 }, /* R1591 - AIF1TX3MIX Input 4 Volume */
+ { 0x0638, 0x0000 }, /* R1592 - AIF1TX4MIX Input 1 Source */
+ { 0x0639, 0x0080 }, /* R1593 - AIF1TX4MIX Input 1 Volume */
+ { 0x063A, 0x0000 }, /* R1594 - AIF1TX4MIX Input 2 Source */
+ { 0x063B, 0x0080 }, /* R1595 - AIF1TX4MIX Input 2 Volume */
+ { 0x063C, 0x0000 }, /* R1596 - AIF1TX4MIX Input 3 Source */
+ { 0x063D, 0x0080 }, /* R1597 - AIF1TX4MIX Input 3 Volume */
+ { 0x063E, 0x0000 }, /* R1598 - AIF1TX4MIX Input 4 Source */
+ { 0x063F, 0x0080 }, /* R1599 - AIF1TX4MIX Input 4 Volume */
+ { 0x0640, 0x0000 }, /* R1600 - AIF1TX5MIX Input 1 Source */
+ { 0x0641, 0x0080 }, /* R1601 - AIF1TX5MIX Input 1 Volume */
+ { 0x0642, 0x0000 }, /* R1602 - AIF1TX5MIX Input 2 Source */
+ { 0x0643, 0x0080 }, /* R1603 - AIF1TX5MIX Input 2 Volume */
+ { 0x0644, 0x0000 }, /* R1604 - AIF1TX5MIX Input 3 Source */
+ { 0x0645, 0x0080 }, /* R1605 - AIF1TX5MIX Input 3 Volume */
+ { 0x0646, 0x0000 }, /* R1606 - AIF1TX5MIX Input 4 Source */
+ { 0x0647, 0x0080 }, /* R1607 - AIF1TX5MIX Input 4 Volume */
+ { 0x0648, 0x0000 }, /* R1608 - AIF1TX6MIX Input 1 Source */
+ { 0x0649, 0x0080 }, /* R1609 - AIF1TX6MIX Input 1 Volume */
+ { 0x064A, 0x0000 }, /* R1610 - AIF1TX6MIX Input 2 Source */
+ { 0x064B, 0x0080 }, /* R1611 - AIF1TX6MIX Input 2 Volume */
+ { 0x064C, 0x0000 }, /* R1612 - AIF1TX6MIX Input 3 Source */
+ { 0x064D, 0x0080 }, /* R1613 - AIF1TX6MIX Input 3 Volume */
+ { 0x064E, 0x0000 }, /* R1614 - AIF1TX6MIX Input 4 Source */
+ { 0x064F, 0x0080 }, /* R1615 - AIF1TX6MIX Input 4 Volume */
+ { 0x0650, 0x0000 }, /* R1616 - EQLMIX Input 1 Source */
+ { 0x0651, 0x0080 }, /* R1617 - EQLMIX Input 1 Volume */
+ { 0x0652, 0x0000 }, /* R1618 - EQLMIX Input 2 Source */
+ { 0x0653, 0x0080 }, /* R1619 - EQLMIX Input 2 Volume */
+ { 0x0654, 0x0000 }, /* R1620 - EQLMIX Input 3 Source */
+ { 0x0655, 0x0080 }, /* R1621 - EQLMIX Input 3 Volume */
+ { 0x0656, 0x0000 }, /* R1622 - EQLMIX Input 4 Source */
+ { 0x0657, 0x0080 }, /* R1623 - EQLMIX Input 4 Volume */
+ { 0x0658, 0x0000 }, /* R1624 - EQRMIX Input 1 Source */
+ { 0x0659, 0x0080 }, /* R1625 - EQRMIX Input 1 Volume */
+ { 0x065A, 0x0000 }, /* R1626 - EQRMIX Input 2 Source */
+ { 0x065B, 0x0080 }, /* R1627 - EQRMIX Input 2 Volume */
+ { 0x065C, 0x0000 }, /* R1628 - EQRMIX Input 3 Source */
+ { 0x065D, 0x0080 }, /* R1629 - EQRMIX Input 3 Volume */
+ { 0x065E, 0x0000 }, /* R1630 - EQRMIX Input 4 Source */
+ { 0x065F, 0x0080 }, /* R1631 - EQRMIX Input 4 Volume */
+ { 0x0660, 0x0000 }, /* R1632 - LHPF1MIX Input 1 Source */
+ { 0x0661, 0x0080 }, /* R1633 - LHPF1MIX Input 1 Volume */
+ { 0x0662, 0x0000 }, /* R1634 - LHPF1MIX Input 2 Source */
+ { 0x0663, 0x0080 }, /* R1635 - LHPF1MIX Input 2 Volume */
+ { 0x0664, 0x0000 }, /* R1636 - LHPF1MIX Input 3 Source */
+ { 0x0665, 0x0080 }, /* R1637 - LHPF1MIX Input 3 Volume */
+ { 0x0666, 0x0000 }, /* R1638 - LHPF1MIX Input 4 Source */
+ { 0x0667, 0x0080 }, /* R1639 - LHPF1MIX Input 4 Volume */
+ { 0x0668, 0x0000 }, /* R1640 - LHPF2MIX Input 1 Source */
+ { 0x0669, 0x0080 }, /* R1641 - LHPF2MIX Input 1 Volume */
+ { 0x066A, 0x0000 }, /* R1642 - LHPF2MIX Input 2 Source */
+ { 0x066B, 0x0080 }, /* R1643 - LHPF2MIX Input 2 Volume */
+ { 0x066C, 0x0000 }, /* R1644 - LHPF2MIX Input 3 Source */
+ { 0x066D, 0x0080 }, /* R1645 - LHPF2MIX Input 3 Volume */
+ { 0x066E, 0x0000 }, /* R1646 - LHPF2MIX Input 4 Source */
+ { 0x066F, 0x0080 }, /* R1647 - LHPF2MIX Input 4 Volume */
+ { 0x0670, 0x0000 }, /* R1648 - DSP1LMIX Input 1 Source */
+ { 0x0671, 0x0080 }, /* R1649 - DSP1LMIX Input 1 Volume */
+ { 0x0672, 0x0000 }, /* R1650 - DSP1LMIX Input 2 Source */
+ { 0x0673, 0x0080 }, /* R1651 - DSP1LMIX Input 2 Volume */
+ { 0x0674, 0x0000 }, /* R1652 - DSP1LMIX Input 3 Source */
+ { 0x0675, 0x0080 }, /* R1653 - DSP1LMIX Input 3 Volume */
+ { 0x0676, 0x0000 }, /* R1654 - DSP1LMIX Input 4 Source */
+ { 0x0677, 0x0080 }, /* R1655 - DSP1LMIX Input 4 Volume */
+ { 0x0678, 0x0000 }, /* R1656 - DSP1RMIX Input 1 Source */
+ { 0x0679, 0x0080 }, /* R1657 - DSP1RMIX Input 1 Volume */
+ { 0x067A, 0x0000 }, /* R1658 - DSP1RMIX Input 2 Source */
+ { 0x067B, 0x0080 }, /* R1659 - DSP1RMIX Input 2 Volume */
+ { 0x067C, 0x0000 }, /* R1660 - DSP1RMIX Input 3 Source */
+ { 0x067D, 0x0080 }, /* R1661 - DSP1RMIX Input 3 Volume */
+ { 0x067E, 0x0000 }, /* R1662 - DSP1RMIX Input 4 Source */
+ { 0x067F, 0x0080 }, /* R1663 - DSP1RMIX Input 4 Volume */
+ { 0x0680, 0x0000 }, /* R1664 - DSP1AUX1MIX Input 1 Source */
+ { 0x0681, 0x0000 }, /* R1665 - DSP1AUX2MIX Input 1 Source */
+ { 0x0682, 0x0000 }, /* R1666 - DSP1AUX3MIX Input 1 Source */
+ { 0x0683, 0x0000 }, /* R1667 - DSP1AUX4MIX Input 1 Source */
+ { 0x0684, 0x0000 }, /* R1668 - DSP1AUX5MIX Input 1 Source */
+ { 0x0685, 0x0000 }, /* R1669 - DSP1AUX6MIX Input 1 Source */
+ { 0x0686, 0x0000 }, /* R1670 - DSP2LMIX Input 1 Source */
+ { 0x0687, 0x0080 }, /* R1671 - DSP2LMIX Input 1 Volume */
+ { 0x0688, 0x0000 }, /* R1672 - DSP2LMIX Input 2 Source */
+ { 0x0689, 0x0080 }, /* R1673 - DSP2LMIX Input 2 Volume */
+ { 0x068A, 0x0000 }, /* R1674 - DSP2LMIX Input 3 Source */
+ { 0x068B, 0x0080 }, /* R1675 - DSP2LMIX Input 3 Volume */
+ { 0x068C, 0x0000 }, /* R1676 - DSP2LMIX Input 4 Source */
+ { 0x068D, 0x0080 }, /* R1677 - DSP2LMIX Input 4 Volume */
+ { 0x068E, 0x0000 }, /* R1678 - DSP2RMIX Input 1 Source */
+ { 0x068F, 0x0080 }, /* R1679 - DSP2RMIX Input 1 Volume */
+ { 0x0690, 0x0000 }, /* R1680 - DSP2RMIX Input 2 Source */
+ { 0x0691, 0x0080 }, /* R1681 - DSP2RMIX Input 2 Volume */
+ { 0x0692, 0x0000 }, /* R1682 - DSP2RMIX Input 3 Source */
+ { 0x0693, 0x0080 }, /* R1683 - DSP2RMIX Input 3 Volume */
+ { 0x0694, 0x0000 }, /* R1684 - DSP2RMIX Input 4 Source */
+ { 0x0695, 0x0080 }, /* R1685 - DSP2RMIX Input 4 Volume */
+ { 0x0696, 0x0000 }, /* R1686 - DSP2AUX1MIX Input 1 Source */
+ { 0x0697, 0x0000 }, /* R1687 - DSP2AUX2MIX Input 1 Source */
+ { 0x0698, 0x0000 }, /* R1688 - DSP2AUX3MIX Input 1 Source */
+ { 0x0699, 0x0000 }, /* R1689 - DSP2AUX4MIX Input 1 Source */
+ { 0x069A, 0x0000 }, /* R1690 - DSP2AUX5MIX Input 1 Source */
+ { 0x069B, 0x0000 }, /* R1691 - DSP2AUX6MIX Input 1 Source */
+ { 0x0700, 0xA101 }, /* R1792 - GPIO CTRL 1 */
+ { 0x0701, 0xA101 }, /* R1793 - GPIO CTRL 2 */
+ { 0x0702, 0xA101 }, /* R1794 - GPIO CTRL 3 */
+ { 0x0703, 0xA101 }, /* R1795 - GPIO CTRL 4 */
+ { 0x0709, 0x0000 }, /* R1801 - Misc Pad Ctrl 1 */
+ { 0x0801, 0x00FF }, /* R2049 - Interrupt Status 1 Mask */
+ { 0x0804, 0xFFFF }, /* R2052 - Interrupt Status 2 Mask */
+ { 0x0808, 0x0000 }, /* R2056 - Interrupt Control */
+ { 0x0900, 0x0000 }, /* R2304 - EQL_1 */
+ { 0x0901, 0x0000 }, /* R2305 - EQL_2 */
+ { 0x0902, 0x0000 }, /* R2306 - EQL_3 */
+ { 0x0903, 0x0000 }, /* R2307 - EQL_4 */
+ { 0x0904, 0x0000 }, /* R2308 - EQL_5 */
+ { 0x0905, 0x0000 }, /* R2309 - EQL_6 */
+ { 0x0906, 0x0000 }, /* R2310 - EQL_7 */
+ { 0x0907, 0x0000 }, /* R2311 - EQL_8 */
+ { 0x0908, 0x0000 }, /* R2312 - EQL_9 */
+ { 0x0909, 0x0000 }, /* R2313 - EQL_10 */
+ { 0x090A, 0x0000 }, /* R2314 - EQL_11 */
+ { 0x090B, 0x0000 }, /* R2315 - EQL_12 */
+ { 0x090C, 0x0000 }, /* R2316 - EQL_13 */
+ { 0x090D, 0x0000 }, /* R2317 - EQL_14 */
+ { 0x090E, 0x0000 }, /* R2318 - EQL_15 */
+ { 0x090F, 0x0000 }, /* R2319 - EQL_16 */
+ { 0x0910, 0x0000 }, /* R2320 - EQL_17 */
+ { 0x0911, 0x0000 }, /* R2321 - EQL_18 */
+ { 0x0912, 0x0000 }, /* R2322 - EQL_19 */
+ { 0x0913, 0x0000 }, /* R2323 - EQL_20 */
+ { 0x0916, 0x0000 }, /* R2326 - EQR_1 */
+ { 0x0917, 0x0000 }, /* R2327 - EQR_2 */
+ { 0x0918, 0x0000 }, /* R2328 - EQR_3 */
+ { 0x0919, 0x0000 }, /* R2329 - EQR_4 */
+ { 0x091A, 0x0000 }, /* R2330 - EQR_5 */
+ { 0x091B, 0x0000 }, /* R2331 - EQR_6 */
+ { 0x091C, 0x0000 }, /* R2332 - EQR_7 */
+ { 0x091D, 0x0000 }, /* R2333 - EQR_8 */
+ { 0x091E, 0x0000 }, /* R2334 - EQR_9 */
+ { 0x091F, 0x0000 }, /* R2335 - EQR_10 */
+ { 0x0920, 0x0000 }, /* R2336 - EQR_11 */
+ { 0x0921, 0x0000 }, /* R2337 - EQR_12 */
+ { 0x0922, 0x0000 }, /* R2338 - EQR_13 */
+ { 0x0923, 0x0000 }, /* R2339 - EQR_14 */
+ { 0x0924, 0x0000 }, /* R2340 - EQR_15 */
+ { 0x0925, 0x0000 }, /* R2341 - EQR_16 */
+ { 0x0926, 0x0000 }, /* R2342 - EQR_17 */
+ { 0x0927, 0x0000 }, /* R2343 - EQR_18 */
+ { 0x0928, 0x0000 }, /* R2344 - EQR_19 */
+ { 0x0929, 0x0000 }, /* R2345 - EQR_20 */
+ { 0x093E, 0x0000 }, /* R2366 - HPLPF1_1 */
+ { 0x093F, 0x0000 }, /* R2367 - HPLPF1_2 */
+ { 0x0942, 0x0000 }, /* R2370 - HPLPF2_1 */
+ { 0x0943, 0x0000 }, /* R2371 - HPLPF2_2 */
+ { 0x0A00, 0x0000 }, /* R2560 - DSP1 Control 1 */
+ { 0x0A02, 0x0000 }, /* R2562 - DSP1 Control 2 */
+ { 0x0A03, 0x0000 }, /* R2563 - DSP1 Control 3 */
+ { 0x0A04, 0x0000 }, /* R2564 - DSP1 Control 4 */
+ { 0x0A06, 0x0000 }, /* R2566 - DSP1 Control 5 */
+ { 0x0A07, 0x0000 }, /* R2567 - DSP1 Control 6 */
+ { 0x0A08, 0x0000 }, /* R2568 - DSP1 Control 7 */
+ { 0x0A09, 0x0000 }, /* R2569 - DSP1 Control 8 */
+ { 0x0A0A, 0x0000 }, /* R2570 - DSP1 Control 9 */
+ { 0x0A0B, 0x0000 }, /* R2571 - DSP1 Control 10 */
+ { 0x0A0C, 0x0000 }, /* R2572 - DSP1 Control 11 */
+ { 0x0A0D, 0x0000 }, /* R2573 - DSP1 Control 12 */
+ { 0x0A0F, 0x0000 }, /* R2575 - DSP1 Control 13 */
+ { 0x0A10, 0x0000 }, /* R2576 - DSP1 Control 14 */
+ { 0x0A11, 0x0000 }, /* R2577 - DSP1 Control 15 */
+ { 0x0A12, 0x0000 }, /* R2578 - DSP1 Control 16 */
+ { 0x0A13, 0x0000 }, /* R2579 - DSP1 Control 17 */
+ { 0x0A14, 0x0000 }, /* R2580 - DSP1 Control 18 */
+ { 0x0A16, 0x0000 }, /* R2582 - DSP1 Control 19 */
+ { 0x0A17, 0x0000 }, /* R2583 - DSP1 Control 20 */
+ { 0x0A18, 0x0000 }, /* R2584 - DSP1 Control 21 */
+ { 0x0A1A, 0x1800 }, /* R2586 - DSP1 Control 22 */
+ { 0x0A1B, 0x1000 }, /* R2587 - DSP1 Control 23 */
+ { 0x0A1C, 0x0400 }, /* R2588 - DSP1 Control 24 */
+ { 0x0A1E, 0x0000 }, /* R2590 - DSP1 Control 25 */
+ { 0x0A20, 0x0000 }, /* R2592 - DSP1 Control 26 */
+ { 0x0A21, 0x0000 }, /* R2593 - DSP1 Control 27 */
+ { 0x0A22, 0x0000 }, /* R2594 - DSP1 Control 28 */
+ { 0x0A23, 0x0000 }, /* R2595 - DSP1 Control 29 */
+ { 0x0A24, 0x0000 }, /* R2596 - DSP1 Control 30 */
+ { 0x0A26, 0x0000 }, /* R2598 - DSP1 Control 31 */
+ { 0x0B00, 0x0000 }, /* R2816 - DSP2 Control 1 */
+ { 0x0B02, 0x0000 }, /* R2818 - DSP2 Control 2 */
+ { 0x0B03, 0x0000 }, /* R2819 - DSP2 Control 3 */
+ { 0x0B04, 0x0000 }, /* R2820 - DSP2 Control 4 */
+ { 0x0B06, 0x0000 }, /* R2822 - DSP2 Control 5 */
+ { 0x0B07, 0x0000 }, /* R2823 - DSP2 Control 6 */
+ { 0x0B08, 0x0000 }, /* R2824 - DSP2 Control 7 */
+ { 0x0B09, 0x0000 }, /* R2825 - DSP2 Control 8 */
+ { 0x0B0A, 0x0000 }, /* R2826 - DSP2 Control 9 */
+ { 0x0B0B, 0x0000 }, /* R2827 - DSP2 Control 10 */
+ { 0x0B0C, 0x0000 }, /* R2828 - DSP2 Control 11 */
+ { 0x0B0D, 0x0000 }, /* R2829 - DSP2 Control 12 */
+ { 0x0B0F, 0x0000 }, /* R2831 - DSP2 Control 13 */
+ { 0x0B10, 0x0000 }, /* R2832 - DSP2 Control 14 */
+ { 0x0B11, 0x0000 }, /* R2833 - DSP2 Control 15 */
+ { 0x0B12, 0x0000 }, /* R2834 - DSP2 Control 16 */
+ { 0x0B13, 0x0000 }, /* R2835 - DSP2 Control 17 */
+ { 0x0B14, 0x0000 }, /* R2836 - DSP2 Control 18 */
+ { 0x0B16, 0x0000 }, /* R2838 - DSP2 Control 19 */
+ { 0x0B17, 0x0000 }, /* R2839 - DSP2 Control 20 */
+ { 0x0B18, 0x0000 }, /* R2840 - DSP2 Control 21 */
+ { 0x0B1A, 0x0800 }, /* R2842 - DSP2 Control 22 */
+ { 0x0B1B, 0x1000 }, /* R2843 - DSP2 Control 23 */
+ { 0x0B1C, 0x0400 }, /* R2844 - DSP2 Control 24 */
+ { 0x0B1E, 0x0000 }, /* R2846 - DSP2 Control 25 */
+ { 0x0B20, 0x0000 }, /* R2848 - DSP2 Control 26 */
+ { 0x0B21, 0x0000 }, /* R2849 - DSP2 Control 27 */
+ { 0x0B22, 0x0000 }, /* R2850 - DSP2 Control 28 */
+ { 0x0B23, 0x0000 }, /* R2851 - DSP2 Control 29 */
+ { 0x0B24, 0x0000 }, /* R2852 - DSP2 Control 30 */
+ { 0x0B26, 0x0000 }, /* R2854 - DSP2 Control 31 */
+};
+
+static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM2200_SOFTWARE_RESET:
+ case WM2200_DEVICE_REVISION:
+ case WM2200_ADPS1_IRQ0:
+ case WM2200_ADPS1_IRQ1:
+ case WM2200_INTERRUPT_STATUS_1:
+ case WM2200_INTERRUPT_STATUS_2:
+ case WM2200_INTERRUPT_RAW_STATUS_2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool wm2200_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM2200_SOFTWARE_RESET:
+ case WM2200_DEVICE_REVISION:
+ case WM2200_TONE_GENERATOR_1:
+ case WM2200_CLOCKING_3:
+ case WM2200_CLOCKING_4:
+ case WM2200_FLL_CONTROL_1:
+ case WM2200_FLL_CONTROL_2:
+ case WM2200_FLL_CONTROL_3:
+ case WM2200_FLL_CONTROL_4:
+ case WM2200_FLL_CONTROL_6:
+ case WM2200_FLL_CONTROL_7:
+ case WM2200_FLL_EFS_1:
+ case WM2200_FLL_EFS_2:
+ case WM2200_MIC_CHARGE_PUMP_1:
+ case WM2200_MIC_CHARGE_PUMP_2:
+ case WM2200_DM_CHARGE_PUMP_1:
+ case WM2200_MIC_BIAS_CTRL_1:
+ case WM2200_MIC_BIAS_CTRL_2:
+ case WM2200_EAR_PIECE_CTRL_1:
+ case WM2200_EAR_PIECE_CTRL_2:
+ case WM2200_INPUT_ENABLES:
+ case WM2200_IN1L_CONTROL:
+ case WM2200_IN1R_CONTROL:
+ case WM2200_IN2L_CONTROL:
+ case WM2200_IN2R_CONTROL:
+ case WM2200_IN3L_CONTROL:
+ case WM2200_IN3R_CONTROL:
+ case WM2200_RXANC_SRC:
+ case WM2200_INPUT_VOLUME_RAMP:
+ case WM2200_ADC_DIGITAL_VOLUME_1L:
+ case WM2200_ADC_DIGITAL_VOLUME_1R:
+ case WM2200_ADC_DIGITAL_VOLUME_2L:
+ case WM2200_ADC_DIGITAL_VOLUME_2R:
+ case WM2200_ADC_DIGITAL_VOLUME_3L:
+ case WM2200_ADC_DIGITAL_VOLUME_3R:
+ case WM2200_OUTPUT_ENABLES:
+ case WM2200_DAC_VOLUME_LIMIT_1L:
+ case WM2200_DAC_VOLUME_LIMIT_1R:
+ case WM2200_DAC_VOLUME_LIMIT_2L:
+ case WM2200_DAC_VOLUME_LIMIT_2R:
+ case WM2200_DAC_AEC_CONTROL_1:
+ case WM2200_OUTPUT_VOLUME_RAMP:
+ case WM2200_DAC_DIGITAL_VOLUME_1L:
+ case WM2200_DAC_DIGITAL_VOLUME_1R:
+ case WM2200_DAC_DIGITAL_VOLUME_2L:
+ case WM2200_DAC_DIGITAL_VOLUME_2R:
+ case WM2200_PDM_1:
+ case WM2200_PDM_2:
+ case WM2200_AUDIO_IF_1_1:
+ case WM2200_AUDIO_IF_1_2:
+ case WM2200_AUDIO_IF_1_3:
+ case WM2200_AUDIO_IF_1_4:
+ case WM2200_AUDIO_IF_1_5:
+ case WM2200_AUDIO_IF_1_6:
+ case WM2200_AUDIO_IF_1_7:
+ case WM2200_AUDIO_IF_1_8:
+ case WM2200_AUDIO_IF_1_9:
+ case WM2200_AUDIO_IF_1_10:
+ case WM2200_AUDIO_IF_1_11:
+ case WM2200_AUDIO_IF_1_12:
+ case WM2200_AUDIO_IF_1_13:
+ case WM2200_AUDIO_IF_1_14:
+ case WM2200_AUDIO_IF_1_15:
+ case WM2200_AUDIO_IF_1_16:
+ case WM2200_AUDIO_IF_1_17:
+ case WM2200_AUDIO_IF_1_18:
+ case WM2200_AUDIO_IF_1_19:
+ case WM2200_AUDIO_IF_1_20:
+ case WM2200_AUDIO_IF_1_21:
+ case WM2200_AUDIO_IF_1_22:
+ case WM2200_OUT1LMIX_INPUT_1_SOURCE:
+ case WM2200_OUT1LMIX_INPUT_1_VOLUME:
+ case WM2200_OUT1LMIX_INPUT_2_SOURCE:
+ case WM2200_OUT1LMIX_INPUT_2_VOLUME:
+ case WM2200_OUT1LMIX_INPUT_3_SOURCE:
+ case WM2200_OUT1LMIX_INPUT_3_VOLUME:
+ case WM2200_OUT1LMIX_INPUT_4_SOURCE:
+ case WM2200_OUT1LMIX_INPUT_4_VOLUME:
+ case WM2200_OUT1RMIX_INPUT_1_SOURCE:
+ case WM2200_OUT1RMIX_INPUT_1_VOLUME:
+ case WM2200_OUT1RMIX_INPUT_2_SOURCE:
+ case WM2200_OUT1RMIX_INPUT_2_VOLUME:
+ case WM2200_OUT1RMIX_INPUT_3_SOURCE:
+ case WM2200_OUT1RMIX_INPUT_3_VOLUME:
+ case WM2200_OUT1RMIX_INPUT_4_SOURCE:
+ case WM2200_OUT1RMIX_INPUT_4_VOLUME:
+ case WM2200_OUT2LMIX_INPUT_1_SOURCE:
+ case WM2200_OUT2LMIX_INPUT_1_VOLUME:
+ case WM2200_OUT2LMIX_INPUT_2_SOURCE:
+ case WM2200_OUT2LMIX_INPUT_2_VOLUME:
+ case WM2200_OUT2LMIX_INPUT_3_SOURCE:
+ case WM2200_OUT2LMIX_INPUT_3_VOLUME:
+ case WM2200_OUT2LMIX_INPUT_4_SOURCE:
+ case WM2200_OUT2LMIX_INPUT_4_VOLUME:
+ case WM2200_OUT2RMIX_INPUT_1_SOURCE:
+ case WM2200_OUT2RMIX_INPUT_1_VOLUME:
+ case WM2200_OUT2RMIX_INPUT_2_SOURCE:
+ case WM2200_OUT2RMIX_INPUT_2_VOLUME:
+ case WM2200_OUT2RMIX_INPUT_3_SOURCE:
+ case WM2200_OUT2RMIX_INPUT_3_VOLUME:
+ case WM2200_OUT2RMIX_INPUT_4_SOURCE:
+ case WM2200_OUT2RMIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX1MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX1MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX1MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX1MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX1MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX1MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX1MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX1MIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX2MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX2MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX2MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX2MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX2MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX2MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX2MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX2MIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX3MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX3MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX3MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX3MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX3MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX3MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX3MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX3MIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX4MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX4MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX4MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX4MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX4MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX4MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX4MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX4MIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX5MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX5MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX5MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX5MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX5MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX5MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX5MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX5MIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX6MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX6MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX6MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX6MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX6MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX6MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX6MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX6MIX_INPUT_4_VOLUME:
+ case WM2200_EQLMIX_INPUT_1_SOURCE:
+ case WM2200_EQLMIX_INPUT_1_VOLUME:
+ case WM2200_EQLMIX_INPUT_2_SOURCE:
+ case WM2200_EQLMIX_INPUT_2_VOLUME:
+ case WM2200_EQLMIX_INPUT_3_SOURCE:
+ case WM2200_EQLMIX_INPUT_3_VOLUME:
+ case WM2200_EQLMIX_INPUT_4_SOURCE:
+ case WM2200_EQLMIX_INPUT_4_VOLUME:
+ case WM2200_EQRMIX_INPUT_1_SOURCE:
+ case WM2200_EQRMIX_INPUT_1_VOLUME:
+ case WM2200_EQRMIX_INPUT_2_SOURCE:
+ case WM2200_EQRMIX_INPUT_2_VOLUME:
+ case WM2200_EQRMIX_INPUT_3_SOURCE:
+ case WM2200_EQRMIX_INPUT_3_VOLUME:
+ case WM2200_EQRMIX_INPUT_4_SOURCE:
+ case WM2200_EQRMIX_INPUT_4_VOLUME:
+ case WM2200_LHPF1MIX_INPUT_1_SOURCE:
+ case WM2200_LHPF1MIX_INPUT_1_VOLUME:
+ case WM2200_LHPF1MIX_INPUT_2_SOURCE:
+ case WM2200_LHPF1MIX_INPUT_2_VOLUME:
+ case WM2200_LHPF1MIX_INPUT_3_SOURCE:
+ case WM2200_LHPF1MIX_INPUT_3_VOLUME:
+ case WM2200_LHPF1MIX_INPUT_4_SOURCE:
+ case WM2200_LHPF1MIX_INPUT_4_VOLUME:
+ case WM2200_LHPF2MIX_INPUT_1_SOURCE:
+ case WM2200_LHPF2MIX_INPUT_1_VOLUME:
+ case WM2200_LHPF2MIX_INPUT_2_SOURCE:
+ case WM2200_LHPF2MIX_INPUT_2_VOLUME:
+ case WM2200_LHPF2MIX_INPUT_3_SOURCE:
+ case WM2200_LHPF2MIX_INPUT_3_VOLUME:
+ case WM2200_LHPF2MIX_INPUT_4_SOURCE:
+ case WM2200_LHPF2MIX_INPUT_4_VOLUME:
+ case WM2200_DSP1LMIX_INPUT_1_SOURCE:
+ case WM2200_DSP1LMIX_INPUT_1_VOLUME:
+ case WM2200_DSP1LMIX_INPUT_2_SOURCE:
+ case WM2200_DSP1LMIX_INPUT_2_VOLUME:
+ case WM2200_DSP1LMIX_INPUT_3_SOURCE:
+ case WM2200_DSP1LMIX_INPUT_3_VOLUME:
+ case WM2200_DSP1LMIX_INPUT_4_SOURCE:
+ case WM2200_DSP1LMIX_INPUT_4_VOLUME:
+ case WM2200_DSP1RMIX_INPUT_1_SOURCE:
+ case WM2200_DSP1RMIX_INPUT_1_VOLUME:
+ case WM2200_DSP1RMIX_INPUT_2_SOURCE:
+ case WM2200_DSP1RMIX_INPUT_2_VOLUME:
+ case WM2200_DSP1RMIX_INPUT_3_SOURCE:
+ case WM2200_DSP1RMIX_INPUT_3_VOLUME:
+ case WM2200_DSP1RMIX_INPUT_4_SOURCE:
+ case WM2200_DSP1RMIX_INPUT_4_VOLUME:
+ case WM2200_DSP1AUX1MIX_INPUT_1_SOURCE:
+ case WM2200_DSP1AUX2MIX_INPUT_1_SOURCE:
+ case WM2200_DSP1AUX3MIX_INPUT_1_SOURCE:
+ case WM2200_DSP1AUX4MIX_INPUT_1_SOURCE:
+ case WM2200_DSP1AUX5MIX_INPUT_1_SOURCE:
+ case WM2200_DSP1AUX6MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2LMIX_INPUT_1_SOURCE:
+ case WM2200_DSP2LMIX_INPUT_1_VOLUME:
+ case WM2200_DSP2LMIX_INPUT_2_SOURCE:
+ case WM2200_DSP2LMIX_INPUT_2_VOLUME:
+ case WM2200_DSP2LMIX_INPUT_3_SOURCE:
+ case WM2200_DSP2LMIX_INPUT_3_VOLUME:
+ case WM2200_DSP2LMIX_INPUT_4_SOURCE:
+ case WM2200_DSP2LMIX_INPUT_4_VOLUME:
+ case WM2200_DSP2RMIX_INPUT_1_SOURCE:
+ case WM2200_DSP2RMIX_INPUT_1_VOLUME:
+ case WM2200_DSP2RMIX_INPUT_2_SOURCE:
+ case WM2200_DSP2RMIX_INPUT_2_VOLUME:
+ case WM2200_DSP2RMIX_INPUT_3_SOURCE:
+ case WM2200_DSP2RMIX_INPUT_3_VOLUME:
+ case WM2200_DSP2RMIX_INPUT_4_SOURCE:
+ case WM2200_DSP2RMIX_INPUT_4_VOLUME:
+ case WM2200_DSP2AUX1MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2AUX2MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2AUX3MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2AUX4MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2AUX5MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2AUX6MIX_INPUT_1_SOURCE:
+ case WM2200_GPIO_CTRL_1:
+ case WM2200_GPIO_CTRL_2:
+ case WM2200_GPIO_CTRL_3:
+ case WM2200_GPIO_CTRL_4:
+ case WM2200_ADPS1_IRQ0:
+ case WM2200_ADPS1_IRQ1:
+ case WM2200_MISC_PAD_CTRL_1:
+ case WM2200_INTERRUPT_STATUS_1:
+ case WM2200_INTERRUPT_STATUS_1_MASK:
+ case WM2200_INTERRUPT_STATUS_2:
+ case WM2200_INTERRUPT_RAW_STATUS_2:
+ case WM2200_INTERRUPT_STATUS_2_MASK:
+ case WM2200_INTERRUPT_CONTROL:
+ case WM2200_EQL_1:
+ case WM2200_EQL_2:
+ case WM2200_EQL_3:
+ case WM2200_EQL_4:
+ case WM2200_EQL_5:
+ case WM2200_EQL_6:
+ case WM2200_EQL_7:
+ case WM2200_EQL_8:
+ case WM2200_EQL_9:
+ case WM2200_EQL_10:
+ case WM2200_EQL_11:
+ case WM2200_EQL_12:
+ case WM2200_EQL_13:
+ case WM2200_EQL_14:
+ case WM2200_EQL_15:
+ case WM2200_EQL_16:
+ case WM2200_EQL_17:
+ case WM2200_EQL_18:
+ case WM2200_EQL_19:
+ case WM2200_EQL_20:
+ case WM2200_EQR_1:
+ case WM2200_EQR_2:
+ case WM2200_EQR_3:
+ case WM2200_EQR_4:
+ case WM2200_EQR_5:
+ case WM2200_EQR_6:
+ case WM2200_EQR_7:
+ case WM2200_EQR_8:
+ case WM2200_EQR_9:
+ case WM2200_EQR_10:
+ case WM2200_EQR_11:
+ case WM2200_EQR_12:
+ case WM2200_EQR_13:
+ case WM2200_EQR_14:
+ case WM2200_EQR_15:
+ case WM2200_EQR_16:
+ case WM2200_EQR_17:
+ case WM2200_EQR_18:
+ case WM2200_EQR_19:
+ case WM2200_EQR_20:
+ case WM2200_HPLPF1_1:
+ case WM2200_HPLPF1_2:
+ case WM2200_HPLPF2_1:
+ case WM2200_HPLPF2_2:
+ case WM2200_DSP1_CONTROL_1:
+ case WM2200_DSP1_CONTROL_2:
+ case WM2200_DSP1_CONTROL_3:
+ case WM2200_DSP1_CONTROL_4:
+ case WM2200_DSP1_CONTROL_5:
+ case WM2200_DSP1_CONTROL_6:
+ case WM2200_DSP1_CONTROL_7:
+ case WM2200_DSP1_CONTROL_8:
+ case WM2200_DSP1_CONTROL_9:
+ case WM2200_DSP1_CONTROL_10:
+ case WM2200_DSP1_CONTROL_11:
+ case WM2200_DSP1_CONTROL_12:
+ case WM2200_DSP1_CONTROL_13:
+ case WM2200_DSP1_CONTROL_14:
+ case WM2200_DSP1_CONTROL_15:
+ case WM2200_DSP1_CONTROL_16:
+ case WM2200_DSP1_CONTROL_17:
+ case WM2200_DSP1_CONTROL_18:
+ case WM2200_DSP1_CONTROL_19:
+ case WM2200_DSP1_CONTROL_20:
+ case WM2200_DSP1_CONTROL_21:
+ case WM2200_DSP1_CONTROL_22:
+ case WM2200_DSP1_CONTROL_23:
+ case WM2200_DSP1_CONTROL_24:
+ case WM2200_DSP1_CONTROL_25:
+ case WM2200_DSP1_CONTROL_26:
+ case WM2200_DSP1_CONTROL_27:
+ case WM2200_DSP1_CONTROL_28:
+ case WM2200_DSP1_CONTROL_29:
+ case WM2200_DSP1_CONTROL_30:
+ case WM2200_DSP1_CONTROL_31:
+ case WM2200_DSP2_CONTROL_1:
+ case WM2200_DSP2_CONTROL_2:
+ case WM2200_DSP2_CONTROL_3:
+ case WM2200_DSP2_CONTROL_4:
+ case WM2200_DSP2_CONTROL_5:
+ case WM2200_DSP2_CONTROL_6:
+ case WM2200_DSP2_CONTROL_7:
+ case WM2200_DSP2_CONTROL_8:
+ case WM2200_DSP2_CONTROL_9:
+ case WM2200_DSP2_CONTROL_10:
+ case WM2200_DSP2_CONTROL_11:
+ case WM2200_DSP2_CONTROL_12:
+ case WM2200_DSP2_CONTROL_13:
+ case WM2200_DSP2_CONTROL_14:
+ case WM2200_DSP2_CONTROL_15:
+ case WM2200_DSP2_CONTROL_16:
+ case WM2200_DSP2_CONTROL_17:
+ case WM2200_DSP2_CONTROL_18:
+ case WM2200_DSP2_CONTROL_19:
+ case WM2200_DSP2_CONTROL_20:
+ case WM2200_DSP2_CONTROL_21:
+ case WM2200_DSP2_CONTROL_22:
+ case WM2200_DSP2_CONTROL_23:
+ case WM2200_DSP2_CONTROL_24:
+ case WM2200_DSP2_CONTROL_25:
+ case WM2200_DSP2_CONTROL_26:
+ case WM2200_DSP2_CONTROL_27:
+ case WM2200_DSP2_CONTROL_28:
+ case WM2200_DSP2_CONTROL_29:
+ case WM2200_DSP2_CONTROL_30:
+ case WM2200_DSP2_CONTROL_31:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct reg_default wm2200_reva_patch[] = {
+ { 0x07, 0x0003 },
+ { 0x102, 0x0200 },
+ { 0x203, 0x0084 },
+ { 0x201, 0x83FF },
+ { 0x20C, 0x0062 },
+ { 0x20D, 0x0062 },
+ { 0x207, 0x2002 },
+ { 0x208, 0x20C0 },
+ { 0x21D, 0x01C0 },
+ { 0x50A, 0x0001 },
+ { 0x50B, 0x0002 },
+ { 0x50C, 0x0003 },
+ { 0x50D, 0x0004 },
+ { 0x50E, 0x0005 },
+ { 0x510, 0x0001 },
+ { 0x511, 0x0002 },
+ { 0x512, 0x0003 },
+ { 0x513, 0x0004 },
+ { 0x514, 0x0005 },
+ { 0x515, 0x0000 },
+ { 0x201, 0x8084 },
+ { 0x202, 0xBBDE },
+ { 0x203, 0x00EC },
+ { 0x500, 0x8000 },
+ { 0x507, 0x1820 },
+ { 0x508, 0x1820 },
+ { 0x505, 0x0300 },
+ { 0x506, 0x0300 },
+ { 0x302, 0x2280 },
+ { 0x303, 0x0080 },
+ { 0x304, 0x2280 },
+ { 0x305, 0x0080 },
+ { 0x306, 0x2280 },
+ { 0x307, 0x0080 },
+ { 0x401, 0x0080 },
+ { 0x402, 0x0080 },
+ { 0x417, 0x3069 },
+ { 0x900, 0x6318 },
+ { 0x901, 0x6300 },
+ { 0x902, 0x0FC8 },
+ { 0x903, 0x03FE },
+ { 0x904, 0x00E0 },
+ { 0x905, 0x1EC4 },
+ { 0x906, 0xF136 },
+ { 0x907, 0x0409 },
+ { 0x908, 0x04CC },
+ { 0x909, 0x1C9B },
+ { 0x90A, 0xF337 },
+ { 0x90B, 0x040B },
+ { 0x90C, 0x0CBB },
+ { 0x90D, 0x16F8 },
+ { 0x90E, 0xF7D9 },
+ { 0x90F, 0x040A },
+ { 0x910, 0x1F14 },
+ { 0x911, 0x058C },
+ { 0x912, 0x0563 },
+ { 0x913, 0x4000 },
+ { 0x916, 0x6318 },
+ { 0x917, 0x6300 },
+ { 0x918, 0x0FC8 },
+ { 0x919, 0x03FE },
+ { 0x91A, 0x00E0 },
+ { 0x91B, 0x1EC4 },
+ { 0x91C, 0xF136 },
+ { 0x91D, 0x0409 },
+ { 0x91E, 0x04CC },
+ { 0x91F, 0x1C9B },
+ { 0x920, 0xF337 },
+ { 0x921, 0x040B },
+ { 0x922, 0x0CBB },
+ { 0x923, 0x16F8 },
+ { 0x924, 0xF7D9 },
+ { 0x925, 0x040A },
+ { 0x926, 0x1F14 },
+ { 0x927, 0x058C },
+ { 0x928, 0x0563 },
+ { 0x929, 0x4000 },
+ { 0x709, 0x2000 },
+ { 0x207, 0x200E },
+ { 0x208, 0x20D4 },
+ { 0x20A, 0x0080 },
+ { 0x07, 0x0000 },
+};
+
+static int wm2200_reset(struct wm2200_priv *wm2200)
+{
+ if (wm2200->pdata.reset) {
+ gpio_set_value_cansleep(wm2200->pdata.reset, 0);
+ gpio_set_value_cansleep(wm2200->pdata.reset, 1);
+
+ return 0;
+ } else {
+ return regmap_write(wm2200->regmap, WM2200_SOFTWARE_RESET,
+ 0x2200);
+ }
+}
+
+static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0);
+static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
+static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
+
+static const char *wm2200_mixer_texts[] = {
+ "None",
+ "Tone Generator",
+ "AEC loopback",
+ "IN1L",
+ "IN1R",
+ "IN2L",
+ "IN2R",
+ "IN3L",
+ "IN3R",
+ "AIF1RX1",
+ "AIF1RX2",
+ "AIF1RX3",
+ "AIF1RX4",
+ "AIF1RX5",
+ "AIF1RX6",
+ "EQL",
+ "EQR",
+ "LHPF1",
+ "LHPF2",
+ "LHPF3",
+ "LHPF4",
+ "DSP1.1",
+ "DSP1.2",
+ "DSP1.3",
+ "DSP1.4",
+ "DSP1.5",
+ "DSP1.6",
+ "DSP2.1",
+ "DSP2.2",
+ "DSP2.3",
+ "DSP2.4",
+ "DSP2.5",
+ "DSP2.6",
+};
+
+static int wm2200_mixer_values[] = {
+ 0x00,
+ 0x04, /* Tone */
+ 0x08, /* AEC */
+ 0x10, /* Input */
+ 0x11,
+ 0x12,
+ 0x13,
+ 0x14,
+ 0x15,
+ 0x20, /* AIF */
+ 0x21,
+ 0x22,
+ 0x23,
+ 0x24,
+ 0x25,
+ 0x50, /* EQ */
+ 0x51,
+ 0x52,
+ 0x60, /* LHPF1 */
+ 0x61, /* LHPF2 */
+ 0x68, /* DSP1 */
+ 0x69,
+ 0x6a,
+ 0x6b,
+ 0x6c,
+ 0x6d,
+ 0x70, /* DSP2 */
+ 0x71,
+ 0x72,
+ 0x73,
+ 0x74,
+ 0x75,
+};
+
+#define WM2200_MIXER_CONTROLS(name, base) \
+ SOC_SINGLE_TLV(name " Input 1 Volume", base + 1 , \
+ WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+ SOC_SINGLE_TLV(name " Input 2 Volume", base + 3 , \
+ WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+ SOC_SINGLE_TLV(name " Input 3 Volume", base + 5 , \
+ WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+ SOC_SINGLE_TLV(name " Input 4 Volume", base + 7 , \
+ WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv)
+
+#define WM2200_MUX_ENUM_DECL(name, reg) \
+ SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \
+ wm2200_mixer_texts, wm2200_mixer_values)
+
+#define WM2200_MUX_CTL_DECL(name) \
+ const struct snd_kcontrol_new name##_mux = \
+ SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+
+#define WM2200_MIXER_ENUMS(name, base_reg) \
+ static WM2200_MUX_ENUM_DECL(name##_in1_enum, base_reg); \
+ static WM2200_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \
+ static WM2200_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \
+ static WM2200_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \
+ static WM2200_MUX_CTL_DECL(name##_in1); \
+ static WM2200_MUX_CTL_DECL(name##_in2); \
+ static WM2200_MUX_CTL_DECL(name##_in3); \
+ static WM2200_MUX_CTL_DECL(name##_in4)
+
+static const struct snd_kcontrol_new wm2200_snd_controls[] = {
+SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL,
+ WM2200_IN1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN2 High Performance Switch", WM2200_IN2L_CONTROL,
+ WM2200_IN2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN3 High Performance Switch", WM2200_IN3L_CONTROL,
+ WM2200_IN3_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R_TLV("IN1 Volume", WM2200_IN1L_CONTROL, WM2200_IN1R_CONTROL,
+ WM2200_IN1L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN2 Volume", WM2200_IN2L_CONTROL, WM2200_IN2R_CONTROL,
+ WM2200_IN2L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN3 Volume", WM2200_IN3L_CONTROL, WM2200_IN3R_CONTROL,
+ WM2200_IN3L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
+
+SOC_DOUBLE_R("IN1 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+ WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN2 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+ WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN3 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+ WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_MUTE_SHIFT, 1, 1),
+
+SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_1L,
+ WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_DIG_VOL_SHIFT,
+ 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_2L,
+ WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_DIG_VOL_SHIFT,
+ 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_3L,
+ WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_DIG_VOL_SHIFT,
+ 0xbf, 0, digital_tlv),
+
+SOC_SINGLE("OUT1 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_1L,
+ WM2200_OUT1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("OUT2 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_2L,
+ WM2200_OUT2_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R("OUT1 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_1L,
+ WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R_TLV("OUT1 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_1L,
+ WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_VOL_SHIFT, 0x9f, 0,
+ digital_tlv),
+SOC_DOUBLE_R_TLV("OUT1 Volume", WM2200_DAC_VOLUME_LIMIT_1L,
+ WM2200_DAC_VOLUME_LIMIT_1R, WM2200_OUT1L_PGA_VOL_SHIFT,
+ 0x46, 0, out_tlv),
+
+SOC_DOUBLE_R("OUT2 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_2L,
+ WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L,
+ WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0,
+ digital_tlv),
+SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT,
+ WM2200_SPK1R_MUTE_SHIFT, 1, 0),
+};
+
+WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(OUT1R, WM2200_OUT1RMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(OUT2L, WM2200_OUT2LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(OUT2R, WM2200_OUT2RMIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(AIF1TX1, WM2200_AIF1TX1MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX2, WM2200_AIF1TX2MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX3, WM2200_AIF1TX3MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX4, WM2200_AIF1TX4MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX5, WM2200_AIF1TX5MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX6, WM2200_AIF1TX6MIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(EQL, WM2200_EQLMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(EQR, WM2200_EQRMIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(DSP1L, WM2200_DSP1LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
+
+#define WM2200_MUX(name, ctrl) \
+ SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+
+#define WM2200_MIXER_WIDGETS(name, name_str) \
+ WM2200_MUX(name_str " Input 1", &name##_in1_mux), \
+ WM2200_MUX(name_str " Input 2", &name##_in2_mux), \
+ WM2200_MUX(name_str " Input 3", &name##_in3_mux), \
+ WM2200_MUX(name_str " Input 4", &name##_in4_mux), \
+ SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
+
+#define WM2200_MIXER_INPUT_ROUTES(name) \
+ { name, "Tone Generator", "Tone Generator" }, \
+ { name, "IN1L", "IN1L PGA" }, \
+ { name, "IN1R", "IN1R PGA" }, \
+ { name, "IN2L", "IN2L PGA" }, \
+ { name, "IN2R", "IN2R PGA" }, \
+ { name, "IN3L", "IN3L PGA" }, \
+ { name, "IN3R", "IN3R PGA" }, \
+ { name, "DSP1.1", "DSP1" }, \
+ { name, "DSP1.2", "DSP1" }, \
+ { name, "DSP1.3", "DSP1" }, \
+ { name, "DSP1.4", "DSP1" }, \
+ { name, "DSP1.5", "DSP1" }, \
+ { name, "DSP1.6", "DSP1" }, \
+ { name, "DSP2.1", "DSP2" }, \
+ { name, "DSP2.2", "DSP2" }, \
+ { name, "DSP2.3", "DSP2" }, \
+ { name, "DSP2.4", "DSP2" }, \
+ { name, "DSP2.5", "DSP2" }, \
+ { name, "DSP2.6", "DSP2" }, \
+ { name, "AIF1RX1", "AIF1RX1" }, \
+ { name, "AIF1RX2", "AIF1RX2" }, \
+ { name, "AIF1RX3", "AIF1RX3" }, \
+ { name, "AIF1RX4", "AIF1RX4" }, \
+ { name, "AIF1RX5", "AIF1RX5" }, \
+ { name, "AIF1RX6", "AIF1RX6" }, \
+ { name, "EQL", "EQL" }, \
+ { name, "EQR", "EQR" }, \
+ { name, "LHPF1", "LHPF1" }, \
+ { name, "LHPF2", "LHPF2" }
+
+#define WM2200_MIXER_ROUTES(widget, name) \
+ { widget, NULL, name " Mixer" }, \
+ { name " Mixer", NULL, name " Input 1" }, \
+ { name " Mixer", NULL, name " Input 2" }, \
+ { name " Mixer", NULL, name " Input 3" }, \
+ { name " Mixer", NULL, name " Input 4" }, \
+ WM2200_MIXER_INPUT_ROUTES(name " Input 1"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Input 2"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Input 4")
+
+static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_SUPPLY("CP1", WM2200_DM_CHARGE_PUMP_1, WM2200_CPDM_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_SUPPLY("CP2", WM2200_MIC_CHARGE_PUMP_1, WM2200_CPMIC_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS1", WM2200_MIC_BIAS_CTRL_1, WM2200_MICB1_ENA_SHIFT,
+ 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", WM2200_MIC_BIAS_CTRL_2, WM2200_MICB2_ENA_SHIFT,
+ 0, NULL, 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
+SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20),
+
+SND_SOC_DAPM_INPUT("IN1L"),
+SND_SOC_DAPM_INPUT("IN1R"),
+SND_SOC_DAPM_INPUT("IN2L"),
+SND_SOC_DAPM_INPUT("IN2R"),
+SND_SOC_DAPM_INPUT("IN3L"),
+SND_SOC_DAPM_INPUT("IN3R"),
+
+SND_SOC_DAPM_SIGGEN("TONE"),
+SND_SOC_DAPM_PGA("Tone Generator", WM2200_TONE_GENERATOR_1,
+ WM2200_TONE_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("IN1L PGA", WM2200_INPUT_ENABLES, WM2200_IN1L_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("IN1R PGA", WM2200_INPUT_ENABLES, WM2200_IN1R_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("IN2L PGA", WM2200_INPUT_ENABLES, WM2200_IN2L_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("IN2R PGA", WM2200_INPUT_ENABLES, WM2200_IN2R_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("IN3L PGA", WM2200_INPUT_ENABLES, WM2200_IN3L_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("IN3R PGA", WM2200_INPUT_ENABLES, WM2200_IN3R_ENA_SHIFT, 0,
+ NULL, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX1", "Playback", 0,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", "Playback", 1,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", "Playback", 2,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", "Playback", 3,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX5", "Playback", 4,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX6", "Playback", 5,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX6_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA("EQL", WM2200_EQL_1, WM2200_EQL_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQR", WM2200_EQR_1, WM2200_EQR_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0,
+ NULL, 0),
+
+SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
+SND_SOC_DAPM_PGA_E("DSP2", SND_SOC_NOPM, 1, 0, NULL, 0, NULL, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", "Capture", 1,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", "Capture", 2,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", "Capture", 3,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES,
+ WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES,
+ WM2200_OUT1R_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_LP", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_LP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_LP", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_OUTP_LP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LP", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_RMV_SHRT_LP_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_LN", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_LN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_LN", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_OUTP_LN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LN", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_RMV_SHRT_LN_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_RP", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_RP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_RP", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_OUTP_RP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RP", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_RMV_SHRT_RP_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_RN", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_RN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_RN", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_OUTP_RN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RN", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_RMV_SHRT_RN_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("OUT2L", WM2200_OUTPUT_ENABLES, WM2200_OUT2L_ENA_SHIFT,
+ 0, NULL, 0),
+SND_SOC_DAPM_PGA("OUT2R", WM2200_OUTPUT_ENABLES, WM2200_OUT2R_ENA_SHIFT,
+ 0, NULL, 0),
+
+SND_SOC_DAPM_OUTPUT("EPOUTLN"),
+SND_SOC_DAPM_OUTPUT("EPOUTLP"),
+SND_SOC_DAPM_OUTPUT("EPOUTRN"),
+SND_SOC_DAPM_OUTPUT("EPOUTRP"),
+SND_SOC_DAPM_OUTPUT("SPK"),
+
+WM2200_MIXER_WIDGETS(EQL, "EQL"),
+WM2200_MIXER_WIDGETS(EQR, "EQR"),
+
+WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"),
+WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"),
+
+WM2200_MIXER_WIDGETS(DSP1L, "DSP1L"),
+WM2200_MIXER_WIDGETS(DSP1R, "DSP1R"),
+WM2200_MIXER_WIDGETS(DSP2L, "DSP2L"),
+WM2200_MIXER_WIDGETS(DSP2R, "DSP2R"),
+
+WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
+WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
+WM2200_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
+WM2200_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
+WM2200_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
+WM2200_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
+
+WM2200_MIXER_WIDGETS(OUT1L, "OUT1L"),
+WM2200_MIXER_WIDGETS(OUT1R, "OUT1R"),
+WM2200_MIXER_WIDGETS(OUT2L, "OUT2L"),
+WM2200_MIXER_WIDGETS(OUT2R, "OUT2R"),
+};
+
+static const struct snd_soc_dapm_route wm2200_dapm_routes[] = {
+ /* Everything needs SYSCLK but only hook up things on the edge
+ * of the chip */
+ { "IN1L", NULL, "SYSCLK" },
+ { "IN1R", NULL, "SYSCLK" },
+ { "IN2L", NULL, "SYSCLK" },
+ { "IN2R", NULL, "SYSCLK" },
+ { "IN3L", NULL, "SYSCLK" },
+ { "IN3R", NULL, "SYSCLK" },
+ { "OUT1L", NULL, "SYSCLK" },
+ { "OUT1R", NULL, "SYSCLK" },
+ { "OUT2L", NULL, "SYSCLK" },
+ { "OUT2R", NULL, "SYSCLK" },
+ { "AIF1RX1", NULL, "SYSCLK" },
+ { "AIF1RX2", NULL, "SYSCLK" },
+ { "AIF1RX3", NULL, "SYSCLK" },
+ { "AIF1RX4", NULL, "SYSCLK" },
+ { "AIF1RX5", NULL, "SYSCLK" },
+ { "AIF1RX6", NULL, "SYSCLK" },
+ { "AIF1TX1", NULL, "SYSCLK" },
+ { "AIF1TX2", NULL, "SYSCLK" },
+ { "AIF1TX3", NULL, "SYSCLK" },
+ { "AIF1TX4", NULL, "SYSCLK" },
+ { "AIF1TX5", NULL, "SYSCLK" },
+ { "AIF1TX6", NULL, "SYSCLK" },
+
+ { "IN1L", NULL, "AVDD" },
+ { "IN1R", NULL, "AVDD" },
+ { "IN2L", NULL, "AVDD" },
+ { "IN2R", NULL, "AVDD" },
+ { "IN3L", NULL, "AVDD" },
+ { "IN3R", NULL, "AVDD" },
+ { "OUT1L", NULL, "AVDD" },
+ { "OUT1R", NULL, "AVDD" },
+
+ { "IN1L PGA", NULL, "IN1L" },
+ { "IN1R PGA", NULL, "IN1R" },
+ { "IN2L PGA", NULL, "IN2L" },
+ { "IN2R PGA", NULL, "IN2R" },
+ { "IN3L PGA", NULL, "IN3L" },
+ { "IN3R PGA", NULL, "IN3R" },
+
+ { "Tone Generator", NULL, "TONE" },
+
+ { "CP2", NULL, "CPVDD" },
+ { "MICBIAS1", NULL, "CP2" },
+ { "MICBIAS2", NULL, "CP2" },
+
+ { "CP1", NULL, "CPVDD" },
+ { "EPD_LN", NULL, "CP1" },
+ { "EPD_LP", NULL, "CP1" },
+ { "EPD_RN", NULL, "CP1" },
+ { "EPD_RP", NULL, "CP1" },
+
+ { "EPD_LP", NULL, "OUT1L" },
+ { "EPD_OUTP_LP", NULL, "EPD_LP" },
+ { "EPD_RMV_SHRT_LP", NULL, "EPD_OUTP_LP" },
+ { "EPOUTLP", NULL, "EPD_RMV_SHRT_LP" },
+
+ { "EPD_LN", NULL, "OUT1L" },
+ { "EPD_OUTP_LN", NULL, "EPD_LN" },
+ { "EPD_RMV_SHRT_LN", NULL, "EPD_OUTP_LN" },
+ { "EPOUTLN", NULL, "EPD_RMV_SHRT_LN" },
+
+ { "EPD_RP", NULL, "OUT1R" },
+ { "EPD_OUTP_RP", NULL, "EPD_RP" },
+ { "EPD_RMV_SHRT_RP", NULL, "EPD_OUTP_RP" },
+ { "EPOUTRP", NULL, "EPD_RMV_SHRT_RP" },
+
+ { "EPD_RN", NULL, "OUT1R" },
+ { "EPD_OUTP_RN", NULL, "EPD_RN" },
+ { "EPD_RMV_SHRT_RN", NULL, "EPD_OUTP_RN" },
+ { "EPOUTRN", NULL, "EPD_RMV_SHRT_RN" },
+
+ { "SPK", NULL, "OUT2L" },
+ { "SPK", NULL, "OUT2R" },
+
+ WM2200_MIXER_ROUTES("DSP1", "DSP1L"),
+ WM2200_MIXER_ROUTES("DSP1", "DSP1R"),
+ WM2200_MIXER_ROUTES("DSP2", "DSP2L"),
+ WM2200_MIXER_ROUTES("DSP2", "DSP2R"),
+
+ WM2200_MIXER_ROUTES("OUT1L", "OUT1L"),
+ WM2200_MIXER_ROUTES("OUT1R", "OUT1R"),
+ WM2200_MIXER_ROUTES("OUT2L", "OUT2L"),
+ WM2200_MIXER_ROUTES("OUT2R", "OUT2R"),
+
+ WM2200_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
+ WM2200_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
+ WM2200_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
+ WM2200_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
+ WM2200_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
+ WM2200_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
+
+ WM2200_MIXER_ROUTES("EQL", "EQL"),
+ WM2200_MIXER_ROUTES("EQR", "EQR"),
+
+ WM2200_MIXER_ROUTES("LHPF1", "LHPF1"),
+ WM2200_MIXER_ROUTES("LHPF2", "LHPF2"),
+};
+
+static int wm2200_probe(struct snd_soc_codec *codec)
+{
+ struct wm2200_priv *wm2200 = dev_get_drvdata(codec->dev);
+ int ret;
+
+ wm2200->codec = codec;
+ codec->control_data = wm2200->regmap;
+ codec->dapm.bias_level = SND_SOC_BIAS_OFF;
+
+ ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ int lrclk, bclk, fmt_val;
+
+ lrclk = 0;
+ bclk = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ fmt_val = 0;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ fmt_val = 1;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ fmt_val = 2;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ fmt_val = 3;
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported DAI format %d\n",
+ fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ case SND_SOC_DAIFMT_CBS_CFM:
+ lrclk |= WM2200_AIF1TX_LRCLK_MSTR;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFS:
+ bclk |= WM2200_AIF1_BCLK_MSTR;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ lrclk |= WM2200_AIF1TX_LRCLK_MSTR;
+ bclk |= WM2200_AIF1_BCLK_MSTR;
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported master mode %d\n",
+ fmt & SND_SOC_DAIFMT_MASTER_MASK);
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ bclk |= WM2200_AIF1_BCLK_INV;
+ lrclk |= WM2200_AIF1TX_LRCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ bclk |= WM2200_AIF1_BCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ lrclk |= WM2200_AIF1TX_LRCLK_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1, WM2200_AIF1_BCLK_MSTR |
+ WM2200_AIF1_BCLK_INV, bclk);
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2,
+ WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
+ lrclk);
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_3,
+ WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
+ lrclk);
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5,
+ WM2200_AIF1_FMT_MASK << 1, fmt_val << 1);
+
+ return 0;
+}
+
+static int wm2200_sr_code[] = {
+ 0,
+ 12000,
+ 24000,
+ 48000,
+ 96000,
+ 192000,
+ 384000,
+ 768000,
+ 0,
+ 11025,
+ 22050,
+ 44100,
+ 88200,
+ 176400,
+ 352800,
+ 705600,
+ 4000,
+ 8000,
+ 16000,
+ 32000,
+ 64000,
+ 128000,
+ 256000,
+ 512000,
+};
+
+#define WM2200_NUM_BCLK_RATES 12
+
+static int wm2200_bclk_rates_dat[WM2200_NUM_BCLK_RATES] = {
+ 6144000,
+ 3072000,
+ 2048000,
+ 1536000,
+ 768000,
+ 512000,
+ 384000,
+ 256000,
+ 192000,
+ 128000,
+ 96000,
+ 64000,
+};
+
+static int wm2200_bclk_rates_cd[WM2200_NUM_BCLK_RATES] = {
+ 5644800,
+ 2882400,
+ 1881600,
+ 1411200,
+ 705600,
+ 470400,
+ 352800,
+ 176400,
+ 117600,
+ 88200,
+ 58800,
+};
+
+static int wm2200_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
+ int i, bclk, lrclk, wl, fl, sr_code;
+ int *bclk_rates;
+
+ /* Data sizes if not using TDM */
+ wl = snd_pcm_format_width(params_format(params));
+ if (wl < 0)
+ return wl;
+ fl = snd_soc_params_to_frame_size(params);
+ if (fl < 0)
+ return fl;
+
+ dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n",
+ wl, fl);
+
+ /* Target BCLK rate */
+ bclk = snd_soc_params_to_bclk(params);
+ if (bclk < 0)
+ return bclk;
+
+ if (!wm2200->sysclk) {
+ dev_err(codec->dev, "SYSCLK has no rate set\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm2200_sr_code); i++)
+ if (wm2200_sr_code[i] == params_rate(params))
+ break;
+ if (i == ARRAY_SIZE(wm2200_sr_code)) {
+ dev_err(codec->dev, "Unsupported sample rate: %dHz\n",
+ params_rate(params));
+ return -EINVAL;
+ }
+ sr_code = i;
+
+ dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz SYSCLK\n",
+ bclk, wm2200->sysclk);
+
+ if (wm2200->sysclk % 4000)
+ bclk_rates = wm2200_bclk_rates_cd;
+ else
+ bclk_rates = wm2200_bclk_rates_dat;
+
+ for (i = 0; i < WM2200_NUM_BCLK_RATES; i++)
+ if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0))
+ break;
+ if (i == WM2200_NUM_BCLK_RATES) {
+ dev_err(codec->dev,
+ "No valid BCLK for %dHz found from %dHz SYSCLK\n",
+ bclk, wm2200->sysclk);
+ return -EINVAL;
+ }
+
+ bclk = i;
+ dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]);
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1,
+ WM2200_AIF1_BCLK_DIV_MASK, bclk);
+
+ lrclk = bclk_rates[bclk] / params_rate(params);
+ dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+ dai->symmetric_rates)
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_7,
+ WM2200_AIF1RX_BCPF_MASK, lrclk);
+ else
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_6,
+ WM2200_AIF1TX_BCPF_MASK, lrclk);
+
+ i = (wl << WM2200_AIF1TX_WL_SHIFT) | wl;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_9,
+ WM2200_AIF1RX_WL_MASK |
+ WM2200_AIF1RX_SLOT_LEN_MASK, i);
+ else
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_8,
+ WM2200_AIF1TX_WL_MASK |
+ WM2200_AIF1TX_SLOT_LEN_MASK, i);
+
+ snd_soc_update_bits(codec, WM2200_CLOCKING_4,
+ WM2200_SAMPLE_RATE_1_MASK, sr_code);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops wm2200_dai_ops = {
+ .set_fmt = wm2200_set_fmt,
+ .hw_params = wm2200_hw_params,
+};
+
+static int wm2200_set_sysclk(struct snd_soc_codec *codec, int clk_id,
+ int source, unsigned int freq, int dir)
+{
+ struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
+ int fval;
+
+ switch (clk_id) {
+ case WM2200_CLK_SYSCLK:
+ break;
+
+ default:
+ dev_err(codec->dev, "Unknown clock %d\n", clk_id);
+ return -EINVAL;
+ }
+
+ switch (source) {
+ case WM2200_CLKSRC_MCLK1:
+ case WM2200_CLKSRC_MCLK2:
+ case WM2200_CLKSRC_FLL:
+ case WM2200_CLKSRC_BCLK1:
+ break;
+ default:
+ dev_err(codec->dev, "Invalid source %d\n", source);
+ return -EINVAL;
+ }
+
+ switch (freq) {
+ case 22579200:
+ case 24576000:
+ fval = 2;
+ break;
+ default:
+ dev_err(codec->dev, "Invalid clock rate: %d\n", freq);
+ return -EINVAL;
+ }
+
+ /* TODO: Check if MCLKs are in use and enable/disable pulls to
+ * match.
+ */
+
+ snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_FREQ_MASK |
+ WM2200_SYSCLK_SRC_MASK,
+ fval << WM2200_SYSCLK_FREQ_SHIFT | source);
+
+ wm2200->sysclk = freq;
+
+ return 0;
+}
+
+struct _fll_div {
+ u16 fll_fratio;
+ u16 fll_outdiv;
+ u16 fll_refclk_div;
+ u16 n;
+ u16 theta;
+ u16 lambda;
+};
+
+static struct {
+ unsigned int min;
+ unsigned int max;
+ u16 fll_fratio;
+ int ratio;
+} fll_fratios[] = {
+ { 0, 64000, 4, 16 },
+ { 64000, 128000, 3, 8 },
+ { 128000, 256000, 2, 4 },
+ { 256000, 1000000, 1, 2 },
+ { 1000000, 13500000, 0, 1 },
+};
+
+static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
+ unsigned int Fout)
+{
+ unsigned int target;
+ unsigned int div;
+ unsigned int fratio, gcd_fll;
+ int i;
+
+ /* Fref must be <=13.5MHz */
+ div = 1;
+ fll_div->fll_refclk_div = 0;
+ while ((Fref / div) > 13500000) {
+ div *= 2;
+ fll_div->fll_refclk_div++;
+
+ if (div > 8) {
+ pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
+ Fref);
+ return -EINVAL;
+ }
+ }
+
+ pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
+
+ /* Apply the division for our remaining calculations */
+ Fref /= div;
+
+ /* Fvco should be 90-100MHz; don't check the upper bound */
+ div = 2;
+ while (Fout * div < 90000000) {
+ div++;
+ if (div > 64) {
+ pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
+ Fout);
+ return -EINVAL;
+ }
+ }
+ target = Fout * div;
+ fll_div->fll_outdiv = div - 1;
+
+ pr_debug("FLL Fvco=%dHz\n", target);
+
+ /* Find an appropraite FLL_FRATIO and factor it out of the target */
+ for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
+ if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
+ fll_div->fll_fratio = fll_fratios[i].fll_fratio;
+ fratio = fll_fratios[i].ratio;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(fll_fratios)) {
+ pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
+ return -EINVAL;
+ }
+
+ fll_div->n = target / (fratio * Fref);
+
+ if (target % Fref == 0) {
+ fll_div->theta = 0;
+ fll_div->lambda = 0;
+ } else {
+ gcd_fll = gcd(target, fratio * Fref);
+
+ fll_div->theta = (target - (fll_div->n * fratio * Fref))
+ / gcd_fll;
+ fll_div->lambda = (fratio * Fref) / gcd_fll;
+ }
+
+ pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
+ fll_div->n, fll_div->theta, fll_div->lambda);
+ pr_debug("FLL_FRATIO=%x(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
+ fll_div->fll_fratio, fratio, fll_div->fll_outdiv,
+ fll_div->fll_refclk_div);
+
+ return 0;
+}
+
+static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
+ unsigned int Fref, unsigned int Fout)
+{
+ struct i2c_client *i2c = to_i2c_client(codec->dev);
+ struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
+ struct _fll_div factors;
+ int ret, i, timeout;
+
+ if (!Fout) {
+ dev_dbg(codec->dev, "FLL disabled");
+
+ if (wm2200->fll_fout)
+ pm_runtime_put(codec->dev);
+
+ wm2200->fll_fout = 0;
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1,
+ WM2200_FLL_ENA, 0);
+ return 0;
+ }
+
+ switch (source) {
+ case WM2200_FLL_SRC_MCLK1:
+ case WM2200_FLL_SRC_MCLK2:
+ case WM2200_FLL_SRC_BCLK:
+ break;
+ default:
+ dev_err(codec->dev, "Invalid FLL source %d\n", source);
+ return -EINVAL;
+ }
+
+ ret = fll_factors(&factors, Fref, Fout);
+ if (ret < 0)
+ return ret;
+
+ /* Disable the FLL while we reconfigure */
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1, WM2200_FLL_ENA, 0);
+
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_2,
+ WM2200_FLL_OUTDIV_MASK | WM2200_FLL_FRATIO_MASK,
+ (factors.fll_outdiv << WM2200_FLL_OUTDIV_SHIFT) |
+ factors.fll_fratio);
+ if (factors.theta) {
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3,
+ WM2200_FLL_FRACN_ENA,
+ WM2200_FLL_FRACN_ENA);
+ snd_soc_update_bits(codec, WM2200_FLL_EFS_2,
+ WM2200_FLL_EFS_ENA,
+ WM2200_FLL_EFS_ENA);
+ } else {
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3,
+ WM2200_FLL_FRACN_ENA, 0);
+ snd_soc_update_bits(codec, WM2200_FLL_EFS_2,
+ WM2200_FLL_EFS_ENA, 0);
+ }
+
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_4, WM2200_FLL_THETA_MASK,
+ factors.theta);
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_6, WM2200_FLL_N_MASK,
+ factors.n);
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_7,
+ WM2200_FLL_CLK_REF_DIV_MASK |
+ WM2200_FLL_CLK_REF_SRC_MASK,
+ (factors.fll_refclk_div
+ << WM2200_FLL_CLK_REF_DIV_SHIFT) | source);
+ snd_soc_update_bits(codec, WM2200_FLL_EFS_1,
+ WM2200_FLL_LAMBDA_MASK, factors.lambda);
+
+ /* Clear any pending completions */
+ try_wait_for_completion(&wm2200->fll_lock);
+
+ pm_runtime_get_sync(codec->dev);
+
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1,
+ WM2200_FLL_ENA, WM2200_FLL_ENA);
+
+ if (i2c->irq)
+ timeout = 2;
+ else
+ timeout = 50;
+
+ snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_ENA,
+ WM2200_SYSCLK_ENA);
+
+ /* Poll for the lock; will use the interrupt to exit quickly */
+ for (i = 0; i < timeout; i++) {
+ if (i2c->irq) {
+ ret = wait_for_completion_timeout(&wm2200->fll_lock,
+ msecs_to_jiffies(25));
+ if (ret > 0)
+ break;
+ } else {
+ msleep(1);
+ }
+
+ ret = snd_soc_read(codec,
+ WM2200_INTERRUPT_RAW_STATUS_2);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "Failed to read FLL status: %d\n",
+ ret);
+ continue;
+ }
+ if (ret & WM2200_FLL_LOCK_STS)
+ break;
+ }
+ if (i == timeout) {
+ dev_err(codec->dev, "FLL lock timed out\n");
+ pm_runtime_put(codec->dev);
+ return -ETIMEDOUT;
+ }
+
+ wm2200->fll_src = source;
+ wm2200->fll_fref = Fref;
+ wm2200->fll_fout = Fout;
+
+ dev_dbg(codec->dev, "FLL running %dHz->%dHz\n", Fref, Fout);
+
+ return 0;
+}
+
+static int wm2200_dai_probe(struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int val = 0;
+ int ret;
+
+ ret = snd_soc_read(codec, WM2200_GPIO_CTRL_1);
+ if (ret >= 0) {
+ if ((ret & WM2200_GP1_FN_MASK) != 0) {
+ dai->symmetric_rates = true;
+ val = WM2200_AIF1TX_LRCLK_SRC;
+ }
+ } else {
+ dev_err(codec->dev, "Failed to read GPIO 1 config: %d\n", ret);
+ }
+
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2,
+ WM2200_AIF1TX_LRCLK_SRC, val);
+
+ return 0;
+}
+
+#define WM2200_RATES SNDRV_PCM_RATE_8000_48000
+
+#define WM2200_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver wm2200_dai = {
+ .name = "wm2200",
+ .probe = wm2200_dai_probe,
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = WM2200_RATES,
+ .formats = WM2200_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = WM2200_RATES,
+ .formats = WM2200_FORMATS,
+ },
+ .ops = &wm2200_dai_ops,
+};
+
+static struct snd_soc_codec_driver soc_codec_wm2200 = {
+ .probe = wm2200_probe,
+
+ .idle_bias_off = true,
+ .ignore_pmdown_time = true,
+ .set_sysclk = wm2200_set_sysclk,
+ .set_pll = wm2200_set_fll,
+
+ .controls = wm2200_snd_controls,
+ .num_controls = ARRAY_SIZE(wm2200_snd_controls),
+ .dapm_widgets = wm2200_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm2200_dapm_widgets),
+ .dapm_routes = wm2200_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm2200_dapm_routes),
+};
+
+static irqreturn_t wm2200_irq(int irq, void *data)
+{
+ struct wm2200_priv *wm2200 = data;
+ unsigned int val, mask;
+ int ret;
+
+ ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, &val);
+ if (ret != 0) {
+ dev_err(wm2200->dev, "Failed to read IRQ status: %d\n", ret);
+ return IRQ_NONE;
+ }
+
+ ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2_MASK,
+ &mask);
+ if (ret != 0) {
+ dev_warn(wm2200->dev, "Failed to read IRQ mask: %d\n", ret);
+ mask = 0;
+ }
+
+ val &= ~mask;
+
+ if (val & WM2200_FLL_LOCK_EINT) {
+ dev_dbg(wm2200->dev, "FLL locked\n");
+ complete(&wm2200->fll_lock);
+ }
+
+ if (val) {
+ regmap_write(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, val);
+
+ return IRQ_HANDLED;
+ } else {
+ return IRQ_NONE;
+ }
+}
+
+static const struct regmap_config wm2200_regmap = {
+ .reg_bits = 16,
+ .val_bits = 16,
+
+ .max_register = WM2200_MAX_REGISTER,
+ .reg_defaults = wm2200_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults),
+ .volatile_reg = wm2200_volatile_register,
+ .readable_reg = wm2200_readable_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static const unsigned int wm2200_dig_vu[] = {
+ WM2200_DAC_DIGITAL_VOLUME_1L,
+ WM2200_DAC_DIGITAL_VOLUME_1R,
+ WM2200_DAC_DIGITAL_VOLUME_2L,
+ WM2200_DAC_DIGITAL_VOLUME_2R,
+ WM2200_ADC_DIGITAL_VOLUME_1L,
+ WM2200_ADC_DIGITAL_VOLUME_1R,
+ WM2200_ADC_DIGITAL_VOLUME_2L,
+ WM2200_ADC_DIGITAL_VOLUME_2R,
+ WM2200_ADC_DIGITAL_VOLUME_3L,
+ WM2200_ADC_DIGITAL_VOLUME_3R,
+};
+
+static const unsigned int wm2200_mic_ctrl_reg[] = {
+ WM2200_IN1L_CONTROL,
+ WM2200_IN2L_CONTROL,
+ WM2200_IN3L_CONTROL,
+};
+
+static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct wm2200_pdata *pdata = dev_get_platdata(&i2c->dev);
+ struct wm2200_priv *wm2200;
+ unsigned int reg;
+ int ret, i;
+
+ wm2200 = devm_kzalloc(&i2c->dev, sizeof(struct wm2200_priv),
+ GFP_KERNEL);
+ if (wm2200 == NULL)
+ return -ENOMEM;
+
+ wm2200->dev = &i2c->dev;
+ init_completion(&wm2200->fll_lock);
+
+ wm2200->regmap = regmap_init_i2c(i2c, &wm2200_regmap);
+ if (IS_ERR(wm2200->regmap)) {
+ ret = PTR_ERR(wm2200->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto err;
+ }
+
+ if (pdata)
+ wm2200->pdata = *pdata;
+
+ i2c_set_clientdata(i2c, wm2200);
+
+ for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++)
+ wm2200->core_supplies[i].supply = wm2200_core_supply_names[i];
+
+ ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
+ ret);
+ goto err_regmap;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
+ ret);
+ goto err_core;
+ }
+
+ if (wm2200->pdata.ldo_ena) {
+ ret = gpio_request_one(wm2200->pdata.ldo_ena,
+ GPIOF_OUT_INIT_HIGH, "WM2200 LDOENA");
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
+ wm2200->pdata.ldo_ena, ret);
+ goto err_enable;
+ }
+ msleep(2);
+ }
+
+ if (wm2200->pdata.reset) {
+ ret = gpio_request_one(wm2200->pdata.reset,
+ GPIOF_OUT_INIT_HIGH, "WM2200 /RESET");
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
+ wm2200->pdata.reset, ret);
+ goto err_ldo;
+ }
+ }
+
+ ret = regmap_read(wm2200->regmap, WM2200_SOFTWARE_RESET, &reg);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
+ goto err_reset;
+ }
+ switch (reg) {
+ case 0x2200:
+ break;
+
+ default:
+ dev_err(&i2c->dev, "Device is not a WM2200, ID is %x\n", reg);
+ ret = -EINVAL;
+ goto err_reset;
+ }
+
+ ret = regmap_read(wm2200->regmap, WM2200_DEVICE_REVISION, &reg);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read revision register\n");
+ goto err_reset;
+ }
+
+ wm2200->rev = reg & WM2200_DEVICE_REVISION_MASK;
+
+ dev_info(&i2c->dev, "revision %c\n", wm2200->rev + 'A');
+
+ switch (wm2200->rev) {
+ case 0:
+ ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch,
+ ARRAY_SIZE(wm2200_reva_patch));
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register patch: %d\n",
+ ret);
+ }
+ break;
+ default:
+ break;
+ }
+
+ ret = wm2200_reset(wm2200);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to issue reset\n");
+ goto err_reset;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm2200->pdata.gpio_defaults); i++) {
+ if (!wm2200->pdata.gpio_defaults[i])
+ continue;
+
+ regmap_write(wm2200->regmap, WM2200_GPIO_CTRL_1 + i,
+ wm2200->pdata.gpio_defaults[i]);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm2200_dig_vu); i++)
+ regmap_update_bits(wm2200->regmap, wm2200_dig_vu[i],
+ WM2200_OUT_VU, WM2200_OUT_VU);
+
+ /* Assign slots 1-6 to channels 1-6 for both TX and RX */
+ for (i = 0; i < 6; i++) {
+ regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_10 + i, i);
+ regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_16 + i, i);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm2200->pdata.in_mode); i++) {
+ regmap_update_bits(wm2200->regmap, wm2200_mic_ctrl_reg[i],
+ WM2200_IN1_MODE_MASK |
+ WM2200_IN1_DMIC_SUP_MASK,
+ (wm2200->pdata.in_mode[i] <<
+ WM2200_IN1_MODE_SHIFT) |
+ (wm2200->pdata.dmic_sup[i] <<
+ WM2200_IN1_DMIC_SUP_SHIFT));
+ }
+
+ if (i2c->irq) {
+ ret = request_threaded_irq(i2c->irq, NULL, wm2200_irq,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "wm2200", wm2200);
+ if (ret == 0)
+ regmap_update_bits(wm2200->regmap,
+ WM2200_INTERRUPT_STATUS_2_MASK,
+ WM2200_FLL_LOCK_EINT, 0);
+ else
+ dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
+ i2c->irq, ret);
+ }
+
+ pm_runtime_set_active(&i2c->dev);
+ pm_runtime_enable(&i2c->dev);
+ pm_request_idle(&i2c->dev);
+
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_wm2200,
+ &wm2200_dai, 1);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+ goto err_pm_runtime;
+ }
+
+ return 0;
+
+err_pm_runtime:
+ pm_runtime_disable(&i2c->dev);
+err_reset:
+ if (wm2200->pdata.reset) {
+ gpio_set_value_cansleep(wm2200->pdata.reset, 0);
+ gpio_free(wm2200->pdata.reset);
+ }
+err_ldo:
+ if (wm2200->pdata.ldo_ena) {
+ gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
+ gpio_free(wm2200->pdata.ldo_ena);
+ }
+err_enable:
+ regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+err_core:
+ regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+err_regmap:
+ regmap_exit(wm2200->regmap);
+err:
+ return ret;
+}
+
+static __devexit int wm2200_i2c_remove(struct i2c_client *i2c)
+{
+ struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c);
+
+ snd_soc_unregister_codec(&i2c->dev);
+ if (i2c->irq)
+ free_irq(i2c->irq, wm2200);
+ if (wm2200->pdata.reset) {
+ gpio_set_value_cansleep(wm2200->pdata.reset, 0);
+ gpio_free(wm2200->pdata.reset);
+ }
+ if (wm2200->pdata.ldo_ena) {
+ gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
+ gpio_free(wm2200->pdata.ldo_ena);
+ }
+ regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+ regmap_exit(wm2200->regmap);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int wm2200_runtime_suspend(struct device *dev)
+{
+ struct wm2200_priv *wm2200 = dev_get_drvdata(dev);
+
+ regcache_cache_only(wm2200->regmap, true);
+ regcache_mark_dirty(wm2200->regmap);
+ if (wm2200->pdata.ldo_ena)
+ gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
+ regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+
+ return 0;
+}
+
+static int wm2200_runtime_resume(struct device *dev)
+{
+ struct wm2200_priv *wm2200 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+ if (ret != 0) {
+ dev_err(dev, "Failed to enable supplies: %d\n",
+ ret);
+ return ret;
+ }
+
+ if (wm2200->pdata.ldo_ena) {
+ gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 1);
+ msleep(2);
+ }
+
+ regcache_cache_only(wm2200->regmap, false);
+ regcache_sync(wm2200->regmap);
+
+ return 0;
+}
+#endif
+
+static struct dev_pm_ops wm2200_pm = {
+ SET_RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume,
+ NULL)
+};
+
+static const struct i2c_device_id wm2200_i2c_id[] = {
+ { "wm2200", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id);
+
+static struct i2c_driver wm2200_i2c_driver = {
+ .driver = {
+ .name = "wm2200",
+ .owner = THIS_MODULE,
+ .pm = &wm2200_pm,
+ },
+ .probe = wm2200_i2c_probe,
+ .remove = __devexit_p(wm2200_i2c_remove),
+ .id_table = wm2200_i2c_id,
+};
+
+static int __init wm2200_modinit(void)
+{
+ return i2c_add_driver(&wm2200_i2c_driver);
+}
+module_init(wm2200_modinit);
+
+static void __exit wm2200_exit(void)
+{
+ i2c_del_driver(&wm2200_i2c_driver);
+}
+module_exit(wm2200_exit);
+
+MODULE_DESCRIPTION("ASoC WM2200 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm2200.h b/sound/soc/codecs/wm2200.h
new file mode 100644
index 000000000000..5d719d6b4a8d
--- /dev/null
+++ b/sound/soc/codecs/wm2200.h
@@ -0,0 +1,3674 @@
+/*
+ * wm2200.h - WM2200 audio codec interface
+ *
+ * Copyright 2012 Wolfson Microelectronics PLC.
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _WM2200_H
+#define _WM2200_H
+
+#define WM2200_CLK_SYSCLK 1
+
+#define WM2200_CLKSRC_MCLK1 0
+#define WM2200_CLKSRC_MCLK2 1
+#define WM2200_CLKSRC_FLL 4
+#define WM2200_CLKSRC_BCLK1 8
+
+#define WM2200_FLL_SRC_MCLK1 0
+#define WM2200_FLL_SRC_MCLK2 1
+#define WM2200_FLL_SRC_BCLK 2
+
+/*
+ * Register values.
+ */
+#define WM2200_SOFTWARE_RESET 0x00
+#define WM2200_DEVICE_REVISION 0x01
+#define WM2200_TONE_GENERATOR_1 0x0B
+#define WM2200_CLOCKING_3 0x102
+#define WM2200_CLOCKING_4 0x103
+#define WM2200_FLL_CONTROL_1 0x111
+#define WM2200_FLL_CONTROL_2 0x112
+#define WM2200_FLL_CONTROL_3 0x113
+#define WM2200_FLL_CONTROL_4 0x114
+#define WM2200_FLL_CONTROL_6 0x116
+#define WM2200_FLL_CONTROL_7 0x117
+#define WM2200_FLL_EFS_1 0x119
+#define WM2200_FLL_EFS_2 0x11A
+#define WM2200_MIC_CHARGE_PUMP_1 0x200
+#define WM2200_MIC_CHARGE_PUMP_2 0x201
+#define WM2200_DM_CHARGE_PUMP_1 0x202
+#define WM2200_MIC_BIAS_CTRL_1 0x20C
+#define WM2200_MIC_BIAS_CTRL_2 0x20D
+#define WM2200_EAR_PIECE_CTRL_1 0x20F
+#define WM2200_EAR_PIECE_CTRL_2 0x210
+#define WM2200_INPUT_ENABLES 0x301
+#define WM2200_IN1L_CONTROL 0x302
+#define WM2200_IN1R_CONTROL 0x303
+#define WM2200_IN2L_CONTROL 0x304
+#define WM2200_IN2R_CONTROL 0x305
+#define WM2200_IN3L_CONTROL 0x306
+#define WM2200_IN3R_CONTROL 0x307
+#define WM2200_RXANC_SRC 0x30A
+#define WM2200_INPUT_VOLUME_RAMP 0x30B
+#define WM2200_ADC_DIGITAL_VOLUME_1L 0x30C
+#define WM2200_ADC_DIGITAL_VOLUME_1R 0x30D
+#define WM2200_ADC_DIGITAL_VOLUME_2L 0x30E
+#define WM2200_ADC_DIGITAL_VOLUME_2R 0x30F
+#define WM2200_ADC_DIGITAL_VOLUME_3L 0x310
+#define WM2200_ADC_DIGITAL_VOLUME_3R 0x311
+#define WM2200_OUTPUT_ENABLES 0x400
+#define WM2200_DAC_VOLUME_LIMIT_1L 0x401
+#define WM2200_DAC_VOLUME_LIMIT_1R 0x402
+#define WM2200_DAC_VOLUME_LIMIT_2L 0x403
+#define WM2200_DAC_VOLUME_LIMIT_2R 0x404
+#define WM2200_DAC_AEC_CONTROL_1 0x409
+#define WM2200_OUTPUT_VOLUME_RAMP 0x40A
+#define WM2200_DAC_DIGITAL_VOLUME_1L 0x40B
+#define WM2200_DAC_DIGITAL_VOLUME_1R 0x40C
+#define WM2200_DAC_DIGITAL_VOLUME_2L 0x40D
+#define WM2200_DAC_DIGITAL_VOLUME_2R 0x40E
+#define WM2200_PDM_1 0x417
+#define WM2200_PDM_2 0x418
+#define WM2200_AUDIO_IF_1_1 0x500
+#define WM2200_AUDIO_IF_1_2 0x501
+#define WM2200_AUDIO_IF_1_3 0x502
+#define WM2200_AUDIO_IF_1_4 0x503
+#define WM2200_AUDIO_IF_1_5 0x504
+#define WM2200_AUDIO_IF_1_6 0x505
+#define WM2200_AUDIO_IF_1_7 0x506
+#define WM2200_AUDIO_IF_1_8 0x507
+#define WM2200_AUDIO_IF_1_9 0x508
+#define WM2200_AUDIO_IF_1_10 0x509
+#define WM2200_AUDIO_IF_1_11 0x50A
+#define WM2200_AUDIO_IF_1_12 0x50B
+#define WM2200_AUDIO_IF_1_13 0x50C
+#define WM2200_AUDIO_IF_1_14 0x50D
+#define WM2200_AUDIO_IF_1_15 0x50E
+#define WM2200_AUDIO_IF_1_16 0x50F
+#define WM2200_AUDIO_IF_1_17 0x510
+#define WM2200_AUDIO_IF_1_18 0x511
+#define WM2200_AUDIO_IF_1_19 0x512
+#define WM2200_AUDIO_IF_1_20 0x513
+#define WM2200_AUDIO_IF_1_21 0x514
+#define WM2200_AUDIO_IF_1_22 0x515
+#define WM2200_OUT1LMIX_INPUT_1_SOURCE 0x600
+#define WM2200_OUT1LMIX_INPUT_1_VOLUME 0x601
+#define WM2200_OUT1LMIX_INPUT_2_SOURCE 0x602
+#define WM2200_OUT1LMIX_INPUT_2_VOLUME 0x603
+#define WM2200_OUT1LMIX_INPUT_3_SOURCE 0x604
+#define WM2200_OUT1LMIX_INPUT_3_VOLUME 0x605
+#define WM2200_OUT1LMIX_INPUT_4_SOURCE 0x606
+#define WM2200_OUT1LMIX_INPUT_4_VOLUME 0x607
+#define WM2200_OUT1RMIX_INPUT_1_SOURCE 0x608
+#define WM2200_OUT1RMIX_INPUT_1_VOLUME 0x609
+#define WM2200_OUT1RMIX_INPUT_2_SOURCE 0x60A
+#define WM2200_OUT1RMIX_INPUT_2_VOLUME 0x60B
+#define WM2200_OUT1RMIX_INPUT_3_SOURCE 0x60C
+#define WM2200_OUT1RMIX_INPUT_3_VOLUME 0x60D
+#define WM2200_OUT1RMIX_INPUT_4_SOURCE 0x60E
+#define WM2200_OUT1RMIX_INPUT_4_VOLUME 0x60F
+#define WM2200_OUT2LMIX_INPUT_1_SOURCE 0x610
+#define WM2200_OUT2LMIX_INPUT_1_VOLUME 0x611
+#define WM2200_OUT2LMIX_INPUT_2_SOURCE 0x612
+#define WM2200_OUT2LMIX_INPUT_2_VOLUME 0x613
+#define WM2200_OUT2LMIX_INPUT_3_SOURCE 0x614
+#define WM2200_OUT2LMIX_INPUT_3_VOLUME 0x615
+#define WM2200_OUT2LMIX_INPUT_4_SOURCE 0x616
+#define WM2200_OUT2LMIX_INPUT_4_VOLUME 0x617
+#define WM2200_OUT2RMIX_INPUT_1_SOURCE 0x618
+#define WM2200_OUT2RMIX_INPUT_1_VOLUME 0x619
+#define WM2200_OUT2RMIX_INPUT_2_SOURCE 0x61A
+#define WM2200_OUT2RMIX_INPUT_2_VOLUME 0x61B
+#define WM2200_OUT2RMIX_INPUT_3_SOURCE 0x61C
+#define WM2200_OUT2RMIX_INPUT_3_VOLUME 0x61D
+#define WM2200_OUT2RMIX_INPUT_4_SOURCE 0x61E
+#define WM2200_OUT2RMIX_INPUT_4_VOLUME 0x61F
+#define WM2200_AIF1TX1MIX_INPUT_1_SOURCE 0x620
+#define WM2200_AIF1TX1MIX_INPUT_1_VOLUME 0x621
+#define WM2200_AIF1TX1MIX_INPUT_2_SOURCE 0x622
+#define WM2200_AIF1TX1MIX_INPUT_2_VOLUME 0x623
+#define WM2200_AIF1TX1MIX_INPUT_3_SOURCE 0x624
+#define WM2200_AIF1TX1MIX_INPUT_3_VOLUME 0x625
+#define WM2200_AIF1TX1MIX_INPUT_4_SOURCE 0x626
+#define WM2200_AIF1TX1MIX_INPUT_4_VOLUME 0x627
+#define WM2200_AIF1TX2MIX_INPUT_1_SOURCE 0x628
+#define WM2200_AIF1TX2MIX_INPUT_1_VOLUME 0x629
+#define WM2200_AIF1TX2MIX_INPUT_2_SOURCE 0x62A
+#define WM2200_AIF1TX2MIX_INPUT_2_VOLUME 0x62B
+#define WM2200_AIF1TX2MIX_INPUT_3_SOURCE 0x62C
+#define WM2200_AIF1TX2MIX_INPUT_3_VOLUME 0x62D
+#define WM2200_AIF1TX2MIX_INPUT_4_SOURCE 0x62E
+#define WM2200_AIF1TX2MIX_INPUT_4_VOLUME 0x62F
+#define WM2200_AIF1TX3MIX_INPUT_1_SOURCE 0x630
+#define WM2200_AIF1TX3MIX_INPUT_1_VOLUME 0x631
+#define WM2200_AIF1TX3MIX_INPUT_2_SOURCE 0x632
+#define WM2200_AIF1TX3MIX_INPUT_2_VOLUME 0x633
+#define WM2200_AIF1TX3MIX_INPUT_3_SOURCE 0x634
+#define WM2200_AIF1TX3MIX_INPUT_3_VOLUME 0x635
+#define WM2200_AIF1TX3MIX_INPUT_4_SOURCE 0x636
+#define WM2200_AIF1TX3MIX_INPUT_4_VOLUME 0x637
+#define WM2200_AIF1TX4MIX_INPUT_1_SOURCE 0x638
+#define WM2200_AIF1TX4MIX_INPUT_1_VOLUME 0x639
+#define WM2200_AIF1TX4MIX_INPUT_2_SOURCE 0x63A
+#define WM2200_AIF1TX4MIX_INPUT_2_VOLUME 0x63B
+#define WM2200_AIF1TX4MIX_INPUT_3_SOURCE 0x63C
+#define WM2200_AIF1TX4MIX_INPUT_3_VOLUME 0x63D
+#define WM2200_AIF1TX4MIX_INPUT_4_SOURCE 0x63E
+#define WM2200_AIF1TX4MIX_INPUT_4_VOLUME 0x63F
+#define WM2200_AIF1TX5MIX_INPUT_1_SOURCE 0x640
+#define WM2200_AIF1TX5MIX_INPUT_1_VOLUME 0x641
+#define WM2200_AIF1TX5MIX_INPUT_2_SOURCE 0x642
+#define WM2200_AIF1TX5MIX_INPUT_2_VOLUME 0x643
+#define WM2200_AIF1TX5MIX_INPUT_3_SOURCE 0x644
+#define WM2200_AIF1TX5MIX_INPUT_3_VOLUME 0x645
+#define WM2200_AIF1TX5MIX_INPUT_4_SOURCE 0x646
+#define WM2200_AIF1TX5MIX_INPUT_4_VOLUME 0x647
+#define WM2200_AIF1TX6MIX_INPUT_1_SOURCE 0x648
+#define WM2200_AIF1TX6MIX_INPUT_1_VOLUME 0x649
+#define WM2200_AIF1TX6MIX_INPUT_2_SOURCE 0x64A
+#define WM2200_AIF1TX6MIX_INPUT_2_VOLUME 0x64B
+#define WM2200_AIF1TX6MIX_INPUT_3_SOURCE 0x64C
+#define WM2200_AIF1TX6MIX_INPUT_3_VOLUME 0x64D
+#define WM2200_AIF1TX6MIX_INPUT_4_SOURCE 0x64E
+#define WM2200_AIF1TX6MIX_INPUT_4_VOLUME 0x64F
+#define WM2200_EQLMIX_INPUT_1_SOURCE 0x650
+#define WM2200_EQLMIX_INPUT_1_VOLUME 0x651
+#define WM2200_EQLMIX_INPUT_2_SOURCE 0x652
+#define WM2200_EQLMIX_INPUT_2_VOLUME 0x653
+#define WM2200_EQLMIX_INPUT_3_SOURCE 0x654
+#define WM2200_EQLMIX_INPUT_3_VOLUME 0x655
+#define WM2200_EQLMIX_INPUT_4_SOURCE 0x656
+#define WM2200_EQLMIX_INPUT_4_VOLUME 0x657
+#define WM2200_EQRMIX_INPUT_1_SOURCE 0x658
+#define WM2200_EQRMIX_INPUT_1_VOLUME 0x659
+#define WM2200_EQRMIX_INPUT_2_SOURCE 0x65A
+#define WM2200_EQRMIX_INPUT_2_VOLUME 0x65B
+#define WM2200_EQRMIX_INPUT_3_SOURCE 0x65C
+#define WM2200_EQRMIX_INPUT_3_VOLUME 0x65D
+#define WM2200_EQRMIX_INPUT_4_SOURCE 0x65E
+#define WM2200_EQRMIX_INPUT_4_VOLUME 0x65F
+#define WM2200_LHPF1MIX_INPUT_1_SOURCE 0x660
+#define WM2200_LHPF1MIX_INPUT_1_VOLUME 0x661
+#define WM2200_LHPF1MIX_INPUT_2_SOURCE 0x662
+#define WM2200_LHPF1MIX_INPUT_2_VOLUME 0x663
+#define WM2200_LHPF1MIX_INPUT_3_SOURCE 0x664
+#define WM2200_LHPF1MIX_INPUT_3_VOLUME 0x665
+#define WM2200_LHPF1MIX_INPUT_4_SOURCE 0x666
+#define WM2200_LHPF1MIX_INPUT_4_VOLUME 0x667
+#define WM2200_LHPF2MIX_INPUT_1_SOURCE 0x668
+#define WM2200_LHPF2MIX_INPUT_1_VOLUME 0x669
+#define WM2200_LHPF2MIX_INPUT_2_SOURCE 0x66A
+#define WM2200_LHPF2MIX_INPUT_2_VOLUME 0x66B
+#define WM2200_LHPF2MIX_INPUT_3_SOURCE 0x66C
+#define WM2200_LHPF2MIX_INPUT_3_VOLUME 0x66D
+#define WM2200_LHPF2MIX_INPUT_4_SOURCE 0x66E
+#define WM2200_LHPF2MIX_INPUT_4_VOLUME 0x66F
+#define WM2200_DSP1LMIX_INPUT_1_SOURCE 0x670
+#define WM2200_DSP1LMIX_INPUT_1_VOLUME 0x671
+#define WM2200_DSP1LMIX_INPUT_2_SOURCE 0x672
+#define WM2200_DSP1LMIX_INPUT_2_VOLUME 0x673
+#define WM2200_DSP1LMIX_INPUT_3_SOURCE 0x674
+#define WM2200_DSP1LMIX_INPUT_3_VOLUME 0x675
+#define WM2200_DSP1LMIX_INPUT_4_SOURCE 0x676
+#define WM2200_DSP1LMIX_INPUT_4_VOLUME 0x677
+#define WM2200_DSP1RMIX_INPUT_1_SOURCE 0x678
+#define WM2200_DSP1RMIX_INPUT_1_VOLUME 0x679
+#define WM2200_DSP1RMIX_INPUT_2_SOURCE 0x67A
+#define WM2200_DSP1RMIX_INPUT_2_VOLUME 0x67B
+#define WM2200_DSP1RMIX_INPUT_3_SOURCE 0x67C
+#define WM2200_DSP1RMIX_INPUT_3_VOLUME 0x67D
+#define WM2200_DSP1RMIX_INPUT_4_SOURCE 0x67E
+#define WM2200_DSP1RMIX_INPUT_4_VOLUME 0x67F
+#define WM2200_DSP1AUX1MIX_INPUT_1_SOURCE 0x680
+#define WM2200_DSP1AUX2MIX_INPUT_1_SOURCE 0x681
+#define WM2200_DSP1AUX3MIX_INPUT_1_SOURCE 0x682
+#define WM2200_DSP1AUX4MIX_INPUT_1_SOURCE 0x683
+#define WM2200_DSP1AUX5MIX_INPUT_1_SOURCE 0x684
+#define WM2200_DSP1AUX6MIX_INPUT_1_SOURCE 0x685
+#define WM2200_DSP2LMIX_INPUT_1_SOURCE 0x686
+#define WM2200_DSP2LMIX_INPUT_1_VOLUME 0x687
+#define WM2200_DSP2LMIX_INPUT_2_SOURCE 0x688
+#define WM2200_DSP2LMIX_INPUT_2_VOLUME 0x689
+#define WM2200_DSP2LMIX_INPUT_3_SOURCE 0x68A
+#define WM2200_DSP2LMIX_INPUT_3_VOLUME 0x68B
+#define WM2200_DSP2LMIX_INPUT_4_SOURCE 0x68C
+#define WM2200_DSP2LMIX_INPUT_4_VOLUME 0x68D
+#define WM2200_DSP2RMIX_INPUT_1_SOURCE 0x68E
+#define WM2200_DSP2RMIX_INPUT_1_VOLUME 0x68F
+#define WM2200_DSP2RMIX_INPUT_2_SOURCE 0x690
+#define WM2200_DSP2RMIX_INPUT_2_VOLUME 0x691
+#define WM2200_DSP2RMIX_INPUT_3_SOURCE 0x692
+#define WM2200_DSP2RMIX_INPUT_3_VOLUME 0x693
+#define WM2200_DSP2RMIX_INPUT_4_SOURCE 0x694
+#define WM2200_DSP2RMIX_INPUT_4_VOLUME 0x695
+#define WM2200_DSP2AUX1MIX_INPUT_1_SOURCE 0x696
+#define WM2200_DSP2AUX2MIX_INPUT_1_SOURCE 0x697
+#define WM2200_DSP2AUX3MIX_INPUT_1_SOURCE 0x698
+#define WM2200_DSP2AUX4MIX_INPUT_1_SOURCE 0x699
+#define WM2200_DSP2AUX5MIX_INPUT_1_SOURCE 0x69A
+#define WM2200_DSP2AUX6MIX_INPUT_1_SOURCE 0x69B
+#define WM2200_GPIO_CTRL_1 0x700
+#define WM2200_GPIO_CTRL_2 0x701
+#define WM2200_GPIO_CTRL_3 0x702
+#define WM2200_GPIO_CTRL_4 0x703
+#define WM2200_ADPS1_IRQ0 0x707
+#define WM2200_ADPS1_IRQ1 0x708
+#define WM2200_MISC_PAD_CTRL_1 0x709
+#define WM2200_INTERRUPT_STATUS_1 0x800
+#define WM2200_INTERRUPT_STATUS_1_MASK 0x801
+#define WM2200_INTERRUPT_STATUS_2 0x802
+#define WM2200_INTERRUPT_RAW_STATUS_2 0x803
+#define WM2200_INTERRUPT_STATUS_2_MASK 0x804
+#define WM2200_INTERRUPT_CONTROL 0x808
+#define WM2200_EQL_1 0x900
+#define WM2200_EQL_2 0x901
+#define WM2200_EQL_3 0x902
+#define WM2200_EQL_4 0x903
+#define WM2200_EQL_5 0x904
+#define WM2200_EQL_6 0x905
+#define WM2200_EQL_7 0x906
+#define WM2200_EQL_8 0x907
+#define WM2200_EQL_9 0x908
+#define WM2200_EQL_10 0x909
+#define WM2200_EQL_11 0x90A
+#define WM2200_EQL_12 0x90B
+#define WM2200_EQL_13 0x90C
+#define WM2200_EQL_14 0x90D
+#define WM2200_EQL_15 0x90E
+#define WM2200_EQL_16 0x90F
+#define WM2200_EQL_17 0x910
+#define WM2200_EQL_18 0x911
+#define WM2200_EQL_19 0x912
+#define WM2200_EQL_20 0x913
+#define WM2200_EQR_1 0x916
+#define WM2200_EQR_2 0x917
+#define WM2200_EQR_3 0x918
+#define WM2200_EQR_4 0x919
+#define WM2200_EQR_5 0x91A
+#define WM2200_EQR_6 0x91B
+#define WM2200_EQR_7 0x91C
+#define WM2200_EQR_8 0x91D
+#define WM2200_EQR_9 0x91E
+#define WM2200_EQR_10 0x91F
+#define WM2200_EQR_11 0x920
+#define WM2200_EQR_12 0x921
+#define WM2200_EQR_13 0x922
+#define WM2200_EQR_14 0x923
+#define WM2200_EQR_15 0x924
+#define WM2200_EQR_16 0x925
+#define WM2200_EQR_17 0x926
+#define WM2200_EQR_18 0x927
+#define WM2200_EQR_19 0x928
+#define WM2200_EQR_20 0x929
+#define WM2200_HPLPF1_1 0x93E
+#define WM2200_HPLPF1_2 0x93F
+#define WM2200_HPLPF2_1 0x942
+#define WM2200_HPLPF2_2 0x943
+#define WM2200_DSP1_CONTROL_1 0xA00
+#define WM2200_DSP1_CONTROL_2 0xA02
+#define WM2200_DSP1_CONTROL_3 0xA03
+#define WM2200_DSP1_CONTROL_4 0xA04
+#define WM2200_DSP1_CONTROL_5 0xA06
+#define WM2200_DSP1_CONTROL_6 0xA07
+#define WM2200_DSP1_CONTROL_7 0xA08
+#define WM2200_DSP1_CONTROL_8 0xA09
+#define WM2200_DSP1_CONTROL_9 0xA0A
+#define WM2200_DSP1_CONTROL_10 0xA0B
+#define WM2200_DSP1_CONTROL_11 0xA0C
+#define WM2200_DSP1_CONTROL_12 0xA0D
+#define WM2200_DSP1_CONTROL_13 0xA0F
+#define WM2200_DSP1_CONTROL_14 0xA10
+#define WM2200_DSP1_CONTROL_15 0xA11
+#define WM2200_DSP1_CONTROL_16 0xA12
+#define WM2200_DSP1_CONTROL_17 0xA13
+#define WM2200_DSP1_CONTROL_18 0xA14
+#define WM2200_DSP1_CONTROL_19 0xA16
+#define WM2200_DSP1_CONTROL_20 0xA17
+#define WM2200_DSP1_CONTROL_21 0xA18
+#define WM2200_DSP1_CONTROL_22 0xA1A
+#define WM2200_DSP1_CONTROL_23 0xA1B
+#define WM2200_DSP1_CONTROL_24 0xA1C
+#define WM2200_DSP1_CONTROL_25 0xA1E
+#define WM2200_DSP1_CONTROL_26 0xA20
+#define WM2200_DSP1_CONTROL_27 0xA21
+#define WM2200_DSP1_CONTROL_28 0xA22
+#define WM2200_DSP1_CONTROL_29 0xA23
+#define WM2200_DSP1_CONTROL_30 0xA24
+#define WM2200_DSP1_CONTROL_31 0xA26
+#define WM2200_DSP2_CONTROL_1 0xB00
+#define WM2200_DSP2_CONTROL_2 0xB02
+#define WM2200_DSP2_CONTROL_3 0xB03
+#define WM2200_DSP2_CONTROL_4 0xB04
+#define WM2200_DSP2_CONTROL_5 0xB06
+#define WM2200_DSP2_CONTROL_6 0xB07
+#define WM2200_DSP2_CONTROL_7 0xB08
+#define WM2200_DSP2_CONTROL_8 0xB09
+#define WM2200_DSP2_CONTROL_9 0xB0A
+#define WM2200_DSP2_CONTROL_10 0xB0B
+#define WM2200_DSP2_CONTROL_11 0xB0C
+#define WM2200_DSP2_CONTROL_12 0xB0D
+#define WM2200_DSP2_CONTROL_13 0xB0F
+#define WM2200_DSP2_CONTROL_14 0xB10
+#define WM2200_DSP2_CONTROL_15 0xB11
+#define WM2200_DSP2_CONTROL_16 0xB12
+#define WM2200_DSP2_CONTROL_17 0xB13
+#define WM2200_DSP2_CONTROL_18 0xB14
+#define WM2200_DSP2_CONTROL_19 0xB16
+#define WM2200_DSP2_CONTROL_20 0xB17
+#define WM2200_DSP2_CONTROL_21 0xB18
+#define WM2200_DSP2_CONTROL_22 0xB1A
+#define WM2200_DSP2_CONTROL_23 0xB1B
+#define WM2200_DSP2_CONTROL_24 0xB1C
+#define WM2200_DSP2_CONTROL_25 0xB1E
+#define WM2200_DSP2_CONTROL_26 0xB20
+#define WM2200_DSP2_CONTROL_27 0xB21
+#define WM2200_DSP2_CONTROL_28 0xB22
+#define WM2200_DSP2_CONTROL_29 0xB23
+#define WM2200_DSP2_CONTROL_30 0xB24
+#define WM2200_DSP2_CONTROL_31 0xB26
+#define WM2200_ANC_CTRL1 0xD00
+#define WM2200_ANC_CTRL2 0xD01
+#define WM2200_ANC_CTRL3 0xD02
+#define WM2200_ANC_CTRL7 0xD08
+#define WM2200_ANC_CTRL8 0xD09
+#define WM2200_ANC_CTRL9 0xD0A
+#define WM2200_ANC_CTRL10 0xD0B
+#define WM2200_ANC_CTRL11 0xD0C
+#define WM2200_ANC_CTRL12 0xD0D
+#define WM2200_ANC_CTRL13 0xD0E
+#define WM2200_ANC_CTRL14 0xD0F
+#define WM2200_ANC_CTRL15 0xD10
+#define WM2200_ANC_CTRL16 0xD11
+#define WM2200_ANC_CTRL17 0xD12
+#define WM2200_ANC_CTRL18 0xD15
+#define WM2200_ANC_CTRL19 0xD16
+#define WM2200_ANC_CTRL20 0xD17
+#define WM2200_ANC_CTRL21 0xD18
+#define WM2200_ANC_CTRL22 0xD19
+#define WM2200_ANC_CTRL23 0xD1A
+#define WM2200_ANC_CTRL24 0xD1B
+#define WM2200_ANC_CTRL25 0xD1C
+#define WM2200_ANC_CTRL26 0xD1D
+#define WM2200_ANC_CTRL27 0xD1E
+#define WM2200_ANC_CTRL28 0xD1F
+#define WM2200_ANC_CTRL29 0xD20
+#define WM2200_ANC_CTRL30 0xD21
+#define WM2200_ANC_CTRL31 0xD23
+#define WM2200_ANC_CTRL32 0xD24
+#define WM2200_ANC_CTRL33 0xD25
+#define WM2200_ANC_CTRL34 0xD27
+#define WM2200_ANC_CTRL35 0xD28
+#define WM2200_ANC_CTRL36 0xD29
+#define WM2200_ANC_CTRL37 0xD2A
+#define WM2200_ANC_CTRL38 0xD2B
+#define WM2200_ANC_CTRL39 0xD2C
+#define WM2200_ANC_CTRL40 0xD2D
+#define WM2200_ANC_CTRL41 0xD2E
+#define WM2200_ANC_CTRL42 0xD2F
+#define WM2200_ANC_CTRL43 0xD30
+#define WM2200_ANC_CTRL44 0xD31
+#define WM2200_ANC_CTRL45 0xD32
+#define WM2200_ANC_CTRL46 0xD33
+#define WM2200_ANC_CTRL47 0xD34
+#define WM2200_ANC_CTRL48 0xD35
+#define WM2200_ANC_CTRL49 0xD36
+#define WM2200_ANC_CTRL50 0xD37
+#define WM2200_ANC_CTRL51 0xD38
+#define WM2200_ANC_CTRL52 0xD39
+#define WM2200_ANC_CTRL53 0xD3A
+#define WM2200_ANC_CTRL54 0xD3B
+#define WM2200_ANC_CTRL55 0xD3C
+#define WM2200_ANC_CTRL56 0xD3D
+#define WM2200_ANC_CTRL57 0xD3E
+#define WM2200_ANC_CTRL58 0xD3F
+#define WM2200_ANC_CTRL59 0xD40
+#define WM2200_ANC_CTRL60 0xD41
+#define WM2200_ANC_CTRL61 0xD42
+#define WM2200_ANC_CTRL62 0xD43
+#define WM2200_ANC_CTRL63 0xD44
+#define WM2200_ANC_CTRL64 0xD45
+#define WM2200_ANC_CTRL65 0xD46
+#define WM2200_ANC_CTRL66 0xD47
+#define WM2200_ANC_CTRL67 0xD48
+#define WM2200_ANC_CTRL68 0xD49
+#define WM2200_ANC_CTRL69 0xD4A
+#define WM2200_ANC_CTRL70 0xD4B
+#define WM2200_ANC_CTRL71 0xD4C
+#define WM2200_ANC_CTRL72 0xD4D
+#define WM2200_ANC_CTRL73 0xD4E
+#define WM2200_ANC_CTRL74 0xD4F
+#define WM2200_ANC_CTRL75 0xD50
+#define WM2200_ANC_CTRL76 0xD51
+#define WM2200_ANC_CTRL77 0xD52
+#define WM2200_ANC_CTRL78 0xD53
+#define WM2200_ANC_CTRL79 0xD54
+#define WM2200_ANC_CTRL80 0xD55
+#define WM2200_ANC_CTRL81 0xD56
+#define WM2200_ANC_CTRL82 0xD57
+#define WM2200_ANC_CTRL83 0xD58
+#define WM2200_ANC_CTRL84 0xD5B
+#define WM2200_ANC_CTRL85 0xD5C
+#define WM2200_ANC_CTRL86 0xD5F
+#define WM2200_ANC_CTRL87 0xD60
+#define WM2200_ANC_CTRL88 0xD61
+#define WM2200_ANC_CTRL89 0xD62
+#define WM2200_ANC_CTRL90 0xD63
+#define WM2200_ANC_CTRL91 0xD64
+#define WM2200_ANC_CTRL92 0xD65
+#define WM2200_ANC_CTRL93 0xD66
+#define WM2200_ANC_CTRL94 0xD67
+#define WM2200_ANC_CTRL95 0xD68
+#define WM2200_ANC_CTRL96 0xD69
+#define WM2200_DSP1_DM_0 0x3000
+#define WM2200_DSP1_DM_1 0x3001
+#define WM2200_DSP1_DM_2 0x3002
+#define WM2200_DSP1_DM_3 0x3003
+#define WM2200_DSP1_DM_2044 0x37FC
+#define WM2200_DSP1_DM_2045 0x37FD
+#define WM2200_DSP1_DM_2046 0x37FE
+#define WM2200_DSP1_DM_2047 0x37FF
+#define WM2200_DSP1_PM_0 0x3800
+#define WM2200_DSP1_PM_1 0x3801
+#define WM2200_DSP1_PM_2 0x3802
+#define WM2200_DSP1_PM_3 0x3803
+#define WM2200_DSP1_PM_4 0x3804
+#define WM2200_DSP1_PM_5 0x3805
+#define WM2200_DSP1_PM_762 0x3AFA
+#define WM2200_DSP1_PM_763 0x3AFB
+#define WM2200_DSP1_PM_764 0x3AFC
+#define WM2200_DSP1_PM_765 0x3AFD
+#define WM2200_DSP1_PM_766 0x3AFE
+#define WM2200_DSP1_PM_767 0x3AFF
+#define WM2200_DSP1_ZM_0 0x3C00
+#define WM2200_DSP1_ZM_1 0x3C01
+#define WM2200_DSP1_ZM_2 0x3C02
+#define WM2200_DSP1_ZM_3 0x3C03
+#define WM2200_DSP1_ZM_1020 0x3FFC
+#define WM2200_DSP1_ZM_1021 0x3FFD
+#define WM2200_DSP1_ZM_1022 0x3FFE
+#define WM2200_DSP1_ZM_1023 0x3FFF
+#define WM2200_DSP2_DM_0 0x4000
+#define WM2200_DSP2_DM_1 0x4001
+#define WM2200_DSP2_DM_2 0x4002
+#define WM2200_DSP2_DM_3 0x4003
+#define WM2200_DSP2_DM_2044 0x47FC
+#define WM2200_DSP2_DM_2045 0x47FD
+#define WM2200_DSP2_DM_2046 0x47FE
+#define WM2200_DSP2_DM_2047 0x47FF
+#define WM2200_DSP2_PM_0 0x4800
+#define WM2200_DSP2_PM_1 0x4801
+#define WM2200_DSP2_PM_2 0x4802
+#define WM2200_DSP2_PM_3 0x4803
+#define WM2200_DSP2_PM_4 0x4804
+#define WM2200_DSP2_PM_5 0x4805
+#define WM2200_DSP2_PM_762 0x4AFA
+#define WM2200_DSP2_PM_763 0x4AFB
+#define WM2200_DSP2_PM_764 0x4AFC
+#define WM2200_DSP2_PM_765 0x4AFD
+#define WM2200_DSP2_PM_766 0x4AFE
+#define WM2200_DSP2_PM_767 0x4AFF
+#define WM2200_DSP2_ZM_0 0x4C00
+#define WM2200_DSP2_ZM_1 0x4C01
+#define WM2200_DSP2_ZM_2 0x4C02
+#define WM2200_DSP2_ZM_3 0x4C03
+#define WM2200_DSP2_ZM_1020 0x4FFC
+#define WM2200_DSP2_ZM_1021 0x4FFD
+#define WM2200_DSP2_ZM_1022 0x4FFE
+#define WM2200_DSP2_ZM_1023 0x4FFF
+
+#define WM2200_REGISTER_COUNT 494
+#define WM2200_MAX_REGISTER 0x4FFF
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - software reset
+ */
+#define WM2200_SW_RESET_CHIP_ID1_MASK 0xFFFF /* SW_RESET_CHIP_ID1 - [15:0] */
+#define WM2200_SW_RESET_CHIP_ID1_SHIFT 0 /* SW_RESET_CHIP_ID1 - [15:0] */
+#define WM2200_SW_RESET_CHIP_ID1_WIDTH 16 /* SW_RESET_CHIP_ID1 - [15:0] */
+
+/*
+ * R1 (0x01) - Device Revision
+ */
+#define WM2200_DEVICE_REVISION_MASK 0x000F /* DEVICE_REVISION - [3:0] */
+#define WM2200_DEVICE_REVISION_SHIFT 0 /* DEVICE_REVISION - [3:0] */
+#define WM2200_DEVICE_REVISION_WIDTH 4 /* DEVICE_REVISION - [3:0] */
+
+/*
+ * R11 (0x0B) - Tone Generator 1
+ */
+#define WM2200_TONE_ENA 0x0001 /* TONE_ENA */
+#define WM2200_TONE_ENA_MASK 0x0001 /* TONE_ENA */
+#define WM2200_TONE_ENA_SHIFT 0 /* TONE_ENA */
+#define WM2200_TONE_ENA_WIDTH 1 /* TONE_ENA */
+
+/*
+ * R258 (0x102) - Clocking 3
+ */
+#define WM2200_SYSCLK_FREQ_MASK 0x0700 /* SYSCLK_FREQ - [10:8] */
+#define WM2200_SYSCLK_FREQ_SHIFT 8 /* SYSCLK_FREQ - [10:8] */
+#define WM2200_SYSCLK_FREQ_WIDTH 3 /* SYSCLK_FREQ - [10:8] */
+#define WM2200_SYSCLK_ENA 0x0040 /* SYSCLK_ENA */
+#define WM2200_SYSCLK_ENA_MASK 0x0040 /* SYSCLK_ENA */
+#define WM2200_SYSCLK_ENA_SHIFT 6 /* SYSCLK_ENA */
+#define WM2200_SYSCLK_ENA_WIDTH 1 /* SYSCLK_ENA */
+#define WM2200_SYSCLK_SRC_MASK 0x000F /* SYSCLK_SRC - [3:0] */
+#define WM2200_SYSCLK_SRC_SHIFT 0 /* SYSCLK_SRC - [3:0] */
+#define WM2200_SYSCLK_SRC_WIDTH 4 /* SYSCLK_SRC - [3:0] */
+
+/*
+ * R259 (0x103) - Clocking 4
+ */
+#define WM2200_SAMPLE_RATE_1_MASK 0x001F /* SAMPLE_RATE_1 - [4:0] */
+#define WM2200_SAMPLE_RATE_1_SHIFT 0 /* SAMPLE_RATE_1 - [4:0] */
+#define WM2200_SAMPLE_RATE_1_WIDTH 5 /* SAMPLE_RATE_1 - [4:0] */
+
+/*
+ * R273 (0x111) - FLL Control 1
+ */
+#define WM2200_FLL_ENA 0x0001 /* FLL_ENA */
+#define WM2200_FLL_ENA_MASK 0x0001 /* FLL_ENA */
+#define WM2200_FLL_ENA_SHIFT 0 /* FLL_ENA */
+#define WM2200_FLL_ENA_WIDTH 1 /* FLL_ENA */
+
+/*
+ * R274 (0x112) - FLL Control 2
+ */
+#define WM2200_FLL_OUTDIV_MASK 0x3F00 /* FLL_OUTDIV - [13:8] */
+#define WM2200_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [13:8] */
+#define WM2200_FLL_OUTDIV_WIDTH 6 /* FLL_OUTDIV - [13:8] */
+#define WM2200_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */
+#define WM2200_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */
+#define WM2200_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */
+
+/*
+ * R275 (0x113) - FLL Control 3
+ */
+#define WM2200_FLL_FRACN_ENA 0x0001 /* FLL_FRACN_ENA */
+#define WM2200_FLL_FRACN_ENA_MASK 0x0001 /* FLL_FRACN_ENA */
+#define WM2200_FLL_FRACN_ENA_SHIFT 0 /* FLL_FRACN_ENA */
+#define WM2200_FLL_FRACN_ENA_WIDTH 1 /* FLL_FRACN_ENA */
+
+/*
+ * R276 (0x114) - FLL Control 4
+ */
+#define WM2200_FLL_THETA_MASK 0xFFFF /* FLL_THETA - [15:0] */
+#define WM2200_FLL_THETA_SHIFT 0 /* FLL_THETA - [15:0] */
+#define WM2200_FLL_THETA_WIDTH 16 /* FLL_THETA - [15:0] */
+
+/*
+ * R278 (0x116) - FLL Control 6
+ */
+#define WM2200_FLL_N_MASK 0x03FF /* FLL_N - [9:0] */
+#define WM2200_FLL_N_SHIFT 0 /* FLL_N - [9:0] */
+#define WM2200_FLL_N_WIDTH 10 /* FLL_N - [9:0] */
+
+/*
+ * R279 (0x117) - FLL Control 7
+ */
+#define WM2200_FLL_CLK_REF_DIV_MASK 0x0030 /* FLL_CLK_REF_DIV - [5:4] */
+#define WM2200_FLL_CLK_REF_DIV_SHIFT 4 /* FLL_CLK_REF_DIV - [5:4] */
+#define WM2200_FLL_CLK_REF_DIV_WIDTH 2 /* FLL_CLK_REF_DIV - [5:4] */
+#define WM2200_FLL_CLK_REF_SRC_MASK 0x0003 /* FLL_CLK_REF_SRC - [1:0] */
+#define WM2200_FLL_CLK_REF_SRC_SHIFT 0 /* FLL_CLK_REF_SRC - [1:0] */
+#define WM2200_FLL_CLK_REF_SRC_WIDTH 2 /* FLL_CLK_REF_SRC - [1:0] */
+
+/*
+ * R281 (0x119) - FLL EFS 1
+ */
+#define WM2200_FLL_LAMBDA_MASK 0xFFFF /* FLL_LAMBDA - [15:0] */
+#define WM2200_FLL_LAMBDA_SHIFT 0 /* FLL_LAMBDA - [15:0] */
+#define WM2200_FLL_LAMBDA_WIDTH 16 /* FLL_LAMBDA - [15:0] */
+
+/*
+ * R282 (0x11A) - FLL EFS 2
+ */
+#define WM2200_FLL_EFS_ENA 0x0001 /* FLL_EFS_ENA */
+#define WM2200_FLL_EFS_ENA_MASK 0x0001 /* FLL_EFS_ENA */
+#define WM2200_FLL_EFS_ENA_SHIFT 0 /* FLL_EFS_ENA */
+#define WM2200_FLL_EFS_ENA_WIDTH 1 /* FLL_EFS_ENA */
+
+/*
+ * R512 (0x200) - Mic Charge Pump 1
+ */
+#define WM2200_CPMIC_BYPASS_MODE 0x0020 /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_BYPASS_MODE_MASK 0x0020 /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_BYPASS_MODE_SHIFT 5 /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_BYPASS_MODE_WIDTH 1 /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_ENA 0x0001 /* CPMIC_ENA */
+#define WM2200_CPMIC_ENA_MASK 0x0001 /* CPMIC_ENA */
+#define WM2200_CPMIC_ENA_SHIFT 0 /* CPMIC_ENA */
+#define WM2200_CPMIC_ENA_WIDTH 1 /* CPMIC_ENA */
+
+/*
+ * R513 (0x201) - Mic Charge Pump 2
+ */
+#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_MASK 0xF800 /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */
+#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_SHIFT 11 /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */
+#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_WIDTH 5 /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */
+
+/*
+ * R514 (0x202) - DM Charge Pump 1
+ */
+#define WM2200_CPDM_ENA 0x0001 /* CPDM_ENA */
+#define WM2200_CPDM_ENA_MASK 0x0001 /* CPDM_ENA */
+#define WM2200_CPDM_ENA_SHIFT 0 /* CPDM_ENA */
+#define WM2200_CPDM_ENA_WIDTH 1 /* CPDM_ENA */
+
+/*
+ * R524 (0x20C) - Mic Bias Ctrl 1
+ */
+#define WM2200_MICB1_DISCH 0x0040 /* MICB1_DISCH */
+#define WM2200_MICB1_DISCH_MASK 0x0040 /* MICB1_DISCH */
+#define WM2200_MICB1_DISCH_SHIFT 6 /* MICB1_DISCH */
+#define WM2200_MICB1_DISCH_WIDTH 1 /* MICB1_DISCH */
+#define WM2200_MICB1_RATE 0x0020 /* MICB1_RATE */
+#define WM2200_MICB1_RATE_MASK 0x0020 /* MICB1_RATE */
+#define WM2200_MICB1_RATE_SHIFT 5 /* MICB1_RATE */
+#define WM2200_MICB1_RATE_WIDTH 1 /* MICB1_RATE */
+#define WM2200_MICB1_LVL_MASK 0x001C /* MICB1_LVL - [4:2] */
+#define WM2200_MICB1_LVL_SHIFT 2 /* MICB1_LVL - [4:2] */
+#define WM2200_MICB1_LVL_WIDTH 3 /* MICB1_LVL - [4:2] */
+#define WM2200_MICB1_MODE 0x0002 /* MICB1_MODE */
+#define WM2200_MICB1_MODE_MASK 0x0002 /* MICB1_MODE */
+#define WM2200_MICB1_MODE_SHIFT 1 /* MICB1_MODE */
+#define WM2200_MICB1_MODE_WIDTH 1 /* MICB1_MODE */
+#define WM2200_MICB1_ENA 0x0001 /* MICB1_ENA */
+#define WM2200_MICB1_ENA_MASK 0x0001 /* MICB1_ENA */
+#define WM2200_MICB1_ENA_SHIFT 0 /* MICB1_ENA */
+#define WM2200_MICB1_ENA_WIDTH 1 /* MICB1_ENA */
+
+/*
+ * R525 (0x20D) - Mic Bias Ctrl 2
+ */
+#define WM2200_MICB2_DISCH 0x0040 /* MICB2_DISCH */
+#define WM2200_MICB2_DISCH_MASK 0x0040 /* MICB2_DISCH */
+#define WM2200_MICB2_DISCH_SHIFT 6 /* MICB2_DISCH */
+#define WM2200_MICB2_DISCH_WIDTH 1 /* MICB2_DISCH */
+#define WM2200_MICB2_RATE 0x0020 /* MICB2_RATE */
+#define WM2200_MICB2_RATE_MASK 0x0020 /* MICB2_RATE */
+#define WM2200_MICB2_RATE_SHIFT 5 /* MICB2_RATE */
+#define WM2200_MICB2_RATE_WIDTH 1 /* MICB2_RATE */
+#define WM2200_MICB2_LVL_MASK 0x001C /* MICB2_LVL - [4:2] */
+#define WM2200_MICB2_LVL_SHIFT 2 /* MICB2_LVL - [4:2] */
+#define WM2200_MICB2_LVL_WIDTH 3 /* MICB2_LVL - [4:2] */
+#define WM2200_MICB2_MODE 0x0002 /* MICB2_MODE */
+#define WM2200_MICB2_MODE_MASK 0x0002 /* MICB2_MODE */
+#define WM2200_MICB2_MODE_SHIFT 1 /* MICB2_MODE */
+#define WM2200_MICB2_MODE_WIDTH 1 /* MICB2_MODE */
+#define WM2200_MICB2_ENA 0x0001 /* MICB2_ENA */
+#define WM2200_MICB2_ENA_MASK 0x0001 /* MICB2_ENA */
+#define WM2200_MICB2_ENA_SHIFT 0 /* MICB2_ENA */
+#define WM2200_MICB2_ENA_WIDTH 1 /* MICB2_ENA */
+
+/*
+ * R527 (0x20F) - Ear Piece Ctrl 1
+ */
+#define WM2200_EPD_LP_ENA 0x4000 /* EPD_LP_ENA */
+#define WM2200_EPD_LP_ENA_MASK 0x4000 /* EPD_LP_ENA */
+#define WM2200_EPD_LP_ENA_SHIFT 14 /* EPD_LP_ENA */
+#define WM2200_EPD_LP_ENA_WIDTH 1 /* EPD_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA 0x2000 /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA_MASK 0x2000 /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA_SHIFT 13 /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA_WIDTH 1 /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_RMV_SHRT_LP 0x1000 /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_RMV_SHRT_LP_MASK 0x1000 /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_RMV_SHRT_LP_SHIFT 12 /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_RMV_SHRT_LP_WIDTH 1 /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_LN_ENA 0x0800 /* EPD_LN_ENA */
+#define WM2200_EPD_LN_ENA_MASK 0x0800 /* EPD_LN_ENA */
+#define WM2200_EPD_LN_ENA_SHIFT 11 /* EPD_LN_ENA */
+#define WM2200_EPD_LN_ENA_WIDTH 1 /* EPD_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA 0x0400 /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA_MASK 0x0400 /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA_SHIFT 10 /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA_WIDTH 1 /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_RMV_SHRT_LN 0x0200 /* EPD_RMV_SHRT_LN */
+#define WM2200_EPD_RMV_SHRT_LN_MASK 0x0200 /* EPD_RMV_SHRT_LN */
+#define WM2200_EPD_RMV_SHRT_LN_SHIFT 9 /* EPD_RMV_SHRT_LN */
+#define WM2200_EPD_RMV_SHRT_LN_WIDTH 1 /* EPD_RMV_SHRT_LN */
+
+/*
+ * R528 (0x210) - Ear Piece Ctrl 2
+ */
+#define WM2200_EPD_RP_ENA 0x4000 /* EPD_RP_ENA */
+#define WM2200_EPD_RP_ENA_MASK 0x4000 /* EPD_RP_ENA */
+#define WM2200_EPD_RP_ENA_SHIFT 14 /* EPD_RP_ENA */
+#define WM2200_EPD_RP_ENA_WIDTH 1 /* EPD_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA 0x2000 /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA_MASK 0x2000 /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA_SHIFT 13 /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA_WIDTH 1 /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_RMV_SHRT_RP 0x1000 /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RMV_SHRT_RP_MASK 0x1000 /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RMV_SHRT_RP_SHIFT 12 /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RMV_SHRT_RP_WIDTH 1 /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RN_ENA 0x0800 /* EPD_RN_ENA */
+#define WM2200_EPD_RN_ENA_MASK 0x0800 /* EPD_RN_ENA */
+#define WM2200_EPD_RN_ENA_SHIFT 11 /* EPD_RN_ENA */
+#define WM2200_EPD_RN_ENA_WIDTH 1 /* EPD_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA 0x0400 /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA_MASK 0x0400 /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA_SHIFT 10 /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA_WIDTH 1 /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_RMV_SHRT_RN 0x0200 /* EPD_RMV_SHRT_RN */
+#define WM2200_EPD_RMV_SHRT_RN_MASK 0x0200 /* EPD_RMV_SHRT_RN */
+#define WM2200_EPD_RMV_SHRT_RN_SHIFT 9 /* EPD_RMV_SHRT_RN */
+#define WM2200_EPD_RMV_SHRT_RN_WIDTH 1 /* EPD_RMV_SHRT_RN */
+
+/*
+ * R769 (0x301) - Input Enables
+ */
+#define WM2200_IN3L_ENA 0x0020 /* IN3L_ENA */
+#define WM2200_IN3L_ENA_MASK 0x0020 /* IN3L_ENA */
+#define WM2200_IN3L_ENA_SHIFT 5 /* IN3L_ENA */
+#define WM2200_IN3L_ENA_WIDTH 1 /* IN3L_ENA */
+#define WM2200_IN3R_ENA 0x0010 /* IN3R_ENA */
+#define WM2200_IN3R_ENA_MASK 0x0010 /* IN3R_ENA */
+#define WM2200_IN3R_ENA_SHIFT 4 /* IN3R_ENA */
+#define WM2200_IN3R_ENA_WIDTH 1 /* IN3R_ENA */
+#define WM2200_IN2L_ENA 0x0008 /* IN2L_ENA */
+#define WM2200_IN2L_ENA_MASK 0x0008 /* IN2L_ENA */
+#define WM2200_IN2L_ENA_SHIFT 3 /* IN2L_ENA */
+#define WM2200_IN2L_ENA_WIDTH 1 /* IN2L_ENA */
+#define WM2200_IN2R_ENA 0x0004 /* IN2R_ENA */
+#define WM2200_IN2R_ENA_MASK 0x0004 /* IN2R_ENA */
+#define WM2200_IN2R_ENA_SHIFT 2 /* IN2R_ENA */
+#define WM2200_IN2R_ENA_WIDTH 1 /* IN2R_ENA */
+#define WM2200_IN1L_ENA 0x0002 /* IN1L_ENA */
+#define WM2200_IN1L_ENA_MASK 0x0002 /* IN1L_ENA */
+#define WM2200_IN1L_ENA_SHIFT 1 /* IN1L_ENA */
+#define WM2200_IN1L_ENA_WIDTH 1 /* IN1L_ENA */
+#define WM2200_IN1R_ENA 0x0001 /* IN1R_ENA */
+#define WM2200_IN1R_ENA_MASK 0x0001 /* IN1R_ENA */
+#define WM2200_IN1R_ENA_SHIFT 0 /* IN1R_ENA */
+#define WM2200_IN1R_ENA_WIDTH 1 /* IN1R_ENA */
+
+/*
+ * R770 (0x302) - IN1L Control
+ */
+#define WM2200_IN1_OSR 0x2000 /* IN1_OSR */
+#define WM2200_IN1_OSR_MASK 0x2000 /* IN1_OSR */
+#define WM2200_IN1_OSR_SHIFT 13 /* IN1_OSR */
+#define WM2200_IN1_OSR_WIDTH 1 /* IN1_OSR */
+#define WM2200_IN1_DMIC_SUP_MASK 0x1800 /* IN1_DMIC_SUP - [12:11] */
+#define WM2200_IN1_DMIC_SUP_SHIFT 11 /* IN1_DMIC_SUP - [12:11] */
+#define WM2200_IN1_DMIC_SUP_WIDTH 2 /* IN1_DMIC_SUP - [12:11] */
+#define WM2200_IN1_MODE_MASK 0x0600 /* IN1_MODE - [10:9] */
+#define WM2200_IN1_MODE_SHIFT 9 /* IN1_MODE - [10:9] */
+#define WM2200_IN1_MODE_WIDTH 2 /* IN1_MODE - [10:9] */
+#define WM2200_IN1L_PGA_VOL_MASK 0x00FE /* IN1L_PGA_VOL - [7:1] */
+#define WM2200_IN1L_PGA_VOL_SHIFT 1 /* IN1L_PGA_VOL - [7:1] */
+#define WM2200_IN1L_PGA_VOL_WIDTH 7 /* IN1L_PGA_VOL - [7:1] */
+
+/*
+ * R771 (0x303) - IN1R Control
+ */
+#define WM2200_IN1R_PGA_VOL_MASK 0x00FE /* IN1R_PGA_VOL - [7:1] */
+#define WM2200_IN1R_PGA_VOL_SHIFT 1 /* IN1R_PGA_VOL - [7:1] */
+#define WM2200_IN1R_PGA_VOL_WIDTH 7 /* IN1R_PGA_VOL - [7:1] */
+
+/*
+ * R772 (0x304) - IN2L Control
+ */
+#define WM2200_IN2_OSR 0x2000 /* IN2_OSR */
+#define WM2200_IN2_OSR_MASK 0x2000 /* IN2_OSR */
+#define WM2200_IN2_OSR_SHIFT 13 /* IN2_OSR */
+#define WM2200_IN2_OSR_WIDTH 1 /* IN2_OSR */
+#define WM2200_IN2_DMIC_SUP_MASK 0x1800 /* IN2_DMIC_SUP - [12:11] */
+#define WM2200_IN2_DMIC_SUP_SHIFT 11 /* IN2_DMIC_SUP - [12:11] */
+#define WM2200_IN2_DMIC_SUP_WIDTH 2 /* IN2_DMIC_SUP - [12:11] */
+#define WM2200_IN2_MODE_MASK 0x0600 /* IN2_MODE - [10:9] */
+#define WM2200_IN2_MODE_SHIFT 9 /* IN2_MODE - [10:9] */
+#define WM2200_IN2_MODE_WIDTH 2 /* IN2_MODE - [10:9] */
+#define WM2200_IN2L_PGA_VOL_MASK 0x00FE /* IN2L_PGA_VOL - [7:1] */
+#define WM2200_IN2L_PGA_VOL_SHIFT 1 /* IN2L_PGA_VOL - [7:1] */
+#define WM2200_IN2L_PGA_VOL_WIDTH 7 /* IN2L_PGA_VOL - [7:1] */
+
+/*
+ * R773 (0x305) - IN2R Control
+ */
+#define WM2200_IN2R_PGA_VOL_MASK 0x00FE /* IN2R_PGA_VOL - [7:1] */
+#define WM2200_IN2R_PGA_VOL_SHIFT 1 /* IN2R_PGA_VOL - [7:1] */
+#define WM2200_IN2R_PGA_VOL_WIDTH 7 /* IN2R_PGA_VOL - [7:1] */
+
+/*
+ * R774 (0x306) - IN3L Control
+ */
+#define WM2200_IN3_OSR 0x2000 /* IN3_OSR */
+#define WM2200_IN3_OSR_MASK 0x2000 /* IN3_OSR */
+#define WM2200_IN3_OSR_SHIFT 13 /* IN3_OSR */
+#define WM2200_IN3_OSR_WIDTH 1 /* IN3_OSR */
+#define WM2200_IN3_DMIC_SUP_MASK 0x1800 /* IN3_DMIC_SUP - [12:11] */
+#define WM2200_IN3_DMIC_SUP_SHIFT 11 /* IN3_DMIC_SUP - [12:11] */
+#define WM2200_IN3_DMIC_SUP_WIDTH 2 /* IN3_DMIC_SUP - [12:11] */
+#define WM2200_IN3_MODE_MASK 0x0600 /* IN3_MODE - [10:9] */
+#define WM2200_IN3_MODE_SHIFT 9 /* IN3_MODE - [10:9] */
+#define WM2200_IN3_MODE_WIDTH 2 /* IN3_MODE - [10:9] */
+#define WM2200_IN3L_PGA_VOL_MASK 0x00FE /* IN3L_PGA_VOL - [7:1] */
+#define WM2200_IN3L_PGA_VOL_SHIFT 1 /* IN3L_PGA_VOL - [7:1] */
+#define WM2200_IN3L_PGA_VOL_WIDTH 7 /* IN3L_PGA_VOL - [7:1] */
+
+/*
+ * R775 (0x307) - IN3R Control
+ */
+#define WM2200_IN3R_PGA_VOL_MASK 0x00FE /* IN3R_PGA_VOL - [7:1] */
+#define WM2200_IN3R_PGA_VOL_SHIFT 1 /* IN3R_PGA_VOL - [7:1] */
+#define WM2200_IN3R_PGA_VOL_WIDTH 7 /* IN3R_PGA_VOL - [7:1] */
+
+/*
+ * R778 (0x30A) - RXANC_SRC
+ */
+#define WM2200_IN_RXANC_SEL_MASK 0x0007 /* IN_RXANC_SEL - [2:0] */
+#define WM2200_IN_RXANC_SEL_SHIFT 0 /* IN_RXANC_SEL - [2:0] */
+#define WM2200_IN_RXANC_SEL_WIDTH 3 /* IN_RXANC_SEL - [2:0] */
+
+/*
+ * R779 (0x30B) - Input Volume Ramp
+ */
+#define WM2200_IN_VD_RAMP_MASK 0x0070 /* IN_VD_RAMP - [6:4] */
+#define WM2200_IN_VD_RAMP_SHIFT 4 /* IN_VD_RAMP - [6:4] */
+#define WM2200_IN_VD_RAMP_WIDTH 3 /* IN_VD_RAMP - [6:4] */
+#define WM2200_IN_VI_RAMP_MASK 0x0007 /* IN_VI_RAMP - [2:0] */
+#define WM2200_IN_VI_RAMP_SHIFT 0 /* IN_VI_RAMP - [2:0] */
+#define WM2200_IN_VI_RAMP_WIDTH 3 /* IN_VI_RAMP - [2:0] */
+
+/*
+ * R780 (0x30C) - ADC Digital Volume 1L
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN1L_MUTE 0x0100 /* IN1L_MUTE */
+#define WM2200_IN1L_MUTE_MASK 0x0100 /* IN1L_MUTE */
+#define WM2200_IN1L_MUTE_SHIFT 8 /* IN1L_MUTE */
+#define WM2200_IN1L_MUTE_WIDTH 1 /* IN1L_MUTE */
+#define WM2200_IN1L_DIG_VOL_MASK 0x00FF /* IN1L_DIG_VOL - [7:0] */
+#define WM2200_IN1L_DIG_VOL_SHIFT 0 /* IN1L_DIG_VOL - [7:0] */
+#define WM2200_IN1L_DIG_VOL_WIDTH 8 /* IN1L_DIG_VOL - [7:0] */
+
+/*
+ * R781 (0x30D) - ADC Digital Volume 1R
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN1R_MUTE 0x0100 /* IN1R_MUTE */
+#define WM2200_IN1R_MUTE_MASK 0x0100 /* IN1R_MUTE */
+#define WM2200_IN1R_MUTE_SHIFT 8 /* IN1R_MUTE */
+#define WM2200_IN1R_MUTE_WIDTH 1 /* IN1R_MUTE */
+#define WM2200_IN1R_DIG_VOL_MASK 0x00FF /* IN1R_DIG_VOL - [7:0] */
+#define WM2200_IN1R_DIG_VOL_SHIFT 0 /* IN1R_DIG_VOL - [7:0] */
+#define WM2200_IN1R_DIG_VOL_WIDTH 8 /* IN1R_DIG_VOL - [7:0] */
+
+/*
+ * R782 (0x30E) - ADC Digital Volume 2L
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN2L_MUTE 0x0100 /* IN2L_MUTE */
+#define WM2200_IN2L_MUTE_MASK 0x0100 /* IN2L_MUTE */
+#define WM2200_IN2L_MUTE_SHIFT 8 /* IN2L_MUTE */
+#define WM2200_IN2L_MUTE_WIDTH 1 /* IN2L_MUTE */
+#define WM2200_IN2L_DIG_VOL_MASK 0x00FF /* IN2L_DIG_VOL - [7:0] */
+#define WM2200_IN2L_DIG_VOL_SHIFT 0 /* IN2L_DIG_VOL - [7:0] */
+#define WM2200_IN2L_DIG_VOL_WIDTH 8 /* IN2L_DIG_VOL - [7:0] */
+
+/*
+ * R783 (0x30F) - ADC Digital Volume 2R
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN2R_MUTE 0x0100 /* IN2R_MUTE */
+#define WM2200_IN2R_MUTE_MASK 0x0100 /* IN2R_MUTE */
+#define WM2200_IN2R_MUTE_SHIFT 8 /* IN2R_MUTE */
+#define WM2200_IN2R_MUTE_WIDTH 1 /* IN2R_MUTE */
+#define WM2200_IN2R_DIG_VOL_MASK 0x00FF /* IN2R_DIG_VOL - [7:0] */
+#define WM2200_IN2R_DIG_VOL_SHIFT 0 /* IN2R_DIG_VOL - [7:0] */
+#define WM2200_IN2R_DIG_VOL_WIDTH 8 /* IN2R_DIG_VOL - [7:0] */
+
+/*
+ * R784 (0x310) - ADC Digital Volume 3L
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN3L_MUTE 0x0100 /* IN3L_MUTE */
+#define WM2200_IN3L_MUTE_MASK 0x0100 /* IN3L_MUTE */
+#define WM2200_IN3L_MUTE_SHIFT 8 /* IN3L_MUTE */
+#define WM2200_IN3L_MUTE_WIDTH 1 /* IN3L_MUTE */
+#define WM2200_IN3L_DIG_VOL_MASK 0x00FF /* IN3L_DIG_VOL - [7:0] */
+#define WM2200_IN3L_DIG_VOL_SHIFT 0 /* IN3L_DIG_VOL - [7:0] */
+#define WM2200_IN3L_DIG_VOL_WIDTH 8 /* IN3L_DIG_VOL - [7:0] */
+
+/*
+ * R785 (0x311) - ADC Digital Volume 3R
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN3R_MUTE 0x0100 /* IN3R_MUTE */
+#define WM2200_IN3R_MUTE_MASK 0x0100 /* IN3R_MUTE */
+#define WM2200_IN3R_MUTE_SHIFT 8 /* IN3R_MUTE */
+#define WM2200_IN3R_MUTE_WIDTH 1 /* IN3R_MUTE */
+#define WM2200_IN3R_DIG_VOL_MASK 0x00FF /* IN3R_DIG_VOL - [7:0] */
+#define WM2200_IN3R_DIG_VOL_SHIFT 0 /* IN3R_DIG_VOL - [7:0] */
+#define WM2200_IN3R_DIG_VOL_WIDTH 8 /* IN3R_DIG_VOL - [7:0] */
+
+/*
+ * R1024 (0x400) - Output Enables
+ */
+#define WM2200_OUT2L_ENA 0x0008 /* OUT2L_ENA */
+#define WM2200_OUT2L_ENA_MASK 0x0008 /* OUT2L_ENA */
+#define WM2200_OUT2L_ENA_SHIFT 3 /* OUT2L_ENA */
+#define WM2200_OUT2L_ENA_WIDTH 1 /* OUT2L_ENA */
+#define WM2200_OUT2R_ENA 0x0004 /* OUT2R_ENA */
+#define WM2200_OUT2R_ENA_MASK 0x0004 /* OUT2R_ENA */
+#define WM2200_OUT2R_ENA_SHIFT 2 /* OUT2R_ENA */
+#define WM2200_OUT2R_ENA_WIDTH 1 /* OUT2R_ENA */
+#define WM2200_OUT1L_ENA 0x0002 /* OUT1L_ENA */
+#define WM2200_OUT1L_ENA_MASK 0x0002 /* OUT1L_ENA */
+#define WM2200_OUT1L_ENA_SHIFT 1 /* OUT1L_ENA */
+#define WM2200_OUT1L_ENA_WIDTH 1 /* OUT1L_ENA */
+#define WM2200_OUT1R_ENA 0x0001 /* OUT1R_ENA */
+#define WM2200_OUT1R_ENA_MASK 0x0001 /* OUT1R_ENA */
+#define WM2200_OUT1R_ENA_SHIFT 0 /* OUT1R_ENA */
+#define WM2200_OUT1R_ENA_WIDTH 1 /* OUT1R_ENA */
+
+/*
+ * R1025 (0x401) - DAC Volume Limit 1L
+ */
+#define WM2200_OUT1_OSR 0x2000 /* OUT1_OSR */
+#define WM2200_OUT1_OSR_MASK 0x2000 /* OUT1_OSR */
+#define WM2200_OUT1_OSR_SHIFT 13 /* OUT1_OSR */
+#define WM2200_OUT1_OSR_WIDTH 1 /* OUT1_OSR */
+#define WM2200_OUT1L_ANC_SRC 0x0800 /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_ANC_SRC_MASK 0x0800 /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_ANC_SRC_SHIFT 11 /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_ANC_SRC_WIDTH 1 /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_PGA_VOL_MASK 0x00FE /* OUT1L_PGA_VOL - [7:1] */
+#define WM2200_OUT1L_PGA_VOL_SHIFT 1 /* OUT1L_PGA_VOL - [7:1] */
+#define WM2200_OUT1L_PGA_VOL_WIDTH 7 /* OUT1L_PGA_VOL - [7:1] */
+
+/*
+ * R1026 (0x402) - DAC Volume Limit 1R
+ */
+#define WM2200_OUT1R_ANC_SRC 0x0800 /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_ANC_SRC_MASK 0x0800 /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_ANC_SRC_SHIFT 11 /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_ANC_SRC_WIDTH 1 /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_PGA_VOL_MASK 0x00FE /* OUT1R_PGA_VOL - [7:1] */
+#define WM2200_OUT1R_PGA_VOL_SHIFT 1 /* OUT1R_PGA_VOL - [7:1] */
+#define WM2200_OUT1R_PGA_VOL_WIDTH 7 /* OUT1R_PGA_VOL - [7:1] */
+
+/*
+ * R1027 (0x403) - DAC Volume Limit 2L
+ */
+#define WM2200_OUT2_OSR 0x2000 /* OUT2_OSR */
+#define WM2200_OUT2_OSR_MASK 0x2000 /* OUT2_OSR */
+#define WM2200_OUT2_OSR_SHIFT 13 /* OUT2_OSR */
+#define WM2200_OUT2_OSR_WIDTH 1 /* OUT2_OSR */
+#define WM2200_OUT2L_ANC_SRC 0x0800 /* OUT2L_ANC_SRC */
+#define WM2200_OUT2L_ANC_SRC_MASK 0x0800 /* OUT2L_ANC_SRC */
+#define WM2200_OUT2L_ANC_SRC_SHIFT 11 /* OUT2L_ANC_SRC */
+#define WM2200_OUT2L_ANC_SRC_WIDTH 1 /* OUT2L_ANC_SRC */
+
+/*
+ * R1028 (0x404) - DAC Volume Limit 2R
+ */
+#define WM2200_OUT2R_ANC_SRC 0x0800 /* OUT2R_ANC_SRC */
+#define WM2200_OUT2R_ANC_SRC_MASK 0x0800 /* OUT2R_ANC_SRC */
+#define WM2200_OUT2R_ANC_SRC_SHIFT 11 /* OUT2R_ANC_SRC */
+#define WM2200_OUT2R_ANC_SRC_WIDTH 1 /* OUT2R_ANC_SRC */
+
+/*
+ * R1033 (0x409) - DAC AEC Control 1
+ */
+#define WM2200_AEC_LOOPBACK_ENA 0x0004 /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_ENA_MASK 0x0004 /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_ENA_SHIFT 2 /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_ENA_WIDTH 1 /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_SRC_MASK 0x0003 /* AEC_LOOPBACK_SRC - [1:0] */
+#define WM2200_AEC_LOOPBACK_SRC_SHIFT 0 /* AEC_LOOPBACK_SRC - [1:0] */
+#define WM2200_AEC_LOOPBACK_SRC_WIDTH 2 /* AEC_LOOPBACK_SRC - [1:0] */
+
+/*
+ * R1034 (0x40A) - Output Volume Ramp
+ */
+#define WM2200_OUT_VD_RAMP_MASK 0x0070 /* OUT_VD_RAMP - [6:4] */
+#define WM2200_OUT_VD_RAMP_SHIFT 4 /* OUT_VD_RAMP - [6:4] */
+#define WM2200_OUT_VD_RAMP_WIDTH 3 /* OUT_VD_RAMP - [6:4] */
+#define WM2200_OUT_VI_RAMP_MASK 0x0007 /* OUT_VI_RAMP - [2:0] */
+#define WM2200_OUT_VI_RAMP_SHIFT 0 /* OUT_VI_RAMP - [2:0] */
+#define WM2200_OUT_VI_RAMP_WIDTH 3 /* OUT_VI_RAMP - [2:0] */
+
+/*
+ * R1035 (0x40B) - DAC Digital Volume 1L
+ */
+#define WM2200_OUT_VU 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM2200_OUT1L_MUTE 0x0100 /* OUT1L_MUTE */
+#define WM2200_OUT1L_MUTE_MASK 0x0100 /* OUT1L_MUTE */
+#define WM2200_OUT1L_MUTE_SHIFT 8 /* OUT1L_MUTE */
+#define WM2200_OUT1L_MUTE_WIDTH 1 /* OUT1L_MUTE */
+#define WM2200_OUT1L_VOL_MASK 0x00FF /* OUT1L_VOL - [7:0] */
+#define WM2200_OUT1L_VOL_SHIFT 0 /* OUT1L_VOL - [7:0] */
+#define WM2200_OUT1L_VOL_WIDTH 8 /* OUT1L_VOL - [7:0] */
+
+/*
+ * R1036 (0x40C) - DAC Digital Volume 1R
+ */
+#define WM2200_OUT_VU 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM2200_OUT1R_MUTE 0x0100 /* OUT1R_MUTE */
+#define WM2200_OUT1R_MUTE_MASK 0x0100 /* OUT1R_MUTE */
+#define WM2200_OUT1R_MUTE_SHIFT 8 /* OUT1R_MUTE */
+#define WM2200_OUT1R_MUTE_WIDTH 1 /* OUT1R_MUTE */
+#define WM2200_OUT1R_VOL_MASK 0x00FF /* OUT1R_VOL - [7:0] */
+#define WM2200_OUT1R_VOL_SHIFT 0 /* OUT1R_VOL - [7:0] */
+#define WM2200_OUT1R_VOL_WIDTH 8 /* OUT1R_VOL - [7:0] */
+
+/*
+ * R1037 (0x40D) - DAC Digital Volume 2L
+ */
+#define WM2200_OUT_VU 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM2200_OUT2L_MUTE 0x0100 /* OUT2L_MUTE */
+#define WM2200_OUT2L_MUTE_MASK 0x0100 /* OUT2L_MUTE */
+#define WM2200_OUT2L_MUTE_SHIFT 8 /* OUT2L_MUTE */
+#define WM2200_OUT2L_MUTE_WIDTH 1 /* OUT2L_MUTE */
+#define WM2200_OUT2L_VOL_MASK 0x00FF /* OUT2L_VOL - [7:0] */
+#define WM2200_OUT2L_VOL_SHIFT 0 /* OUT2L_VOL - [7:0] */
+#define WM2200_OUT2L_VOL_WIDTH 8 /* OUT2L_VOL - [7:0] */
+
+/*
+ * R1038 (0x40E) - DAC Digital Volume 2R
+ */
+#define WM2200_OUT_VU 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM2200_OUT2R_MUTE 0x0100 /* OUT2R_MUTE */
+#define WM2200_OUT2R_MUTE_MASK 0x0100 /* OUT2R_MUTE */
+#define WM2200_OUT2R_MUTE_SHIFT 8 /* OUT2R_MUTE */
+#define WM2200_OUT2R_MUTE_WIDTH 1 /* OUT2R_MUTE */
+#define WM2200_OUT2R_VOL_MASK 0x00FF /* OUT2R_VOL - [7:0] */
+#define WM2200_OUT2R_VOL_SHIFT 0 /* OUT2R_VOL - [7:0] */
+#define WM2200_OUT2R_VOL_WIDTH 8 /* OUT2R_VOL - [7:0] */
+
+/*
+ * R1047 (0x417) - PDM 1
+ */
+#define WM2200_SPK1R_MUTE 0x2000 /* SPK1R_MUTE */
+#define WM2200_SPK1R_MUTE_MASK 0x2000 /* SPK1R_MUTE */
+#define WM2200_SPK1R_MUTE_SHIFT 13 /* SPK1R_MUTE */
+#define WM2200_SPK1R_MUTE_WIDTH 1 /* SPK1R_MUTE */
+#define WM2200_SPK1L_MUTE 0x1000 /* SPK1L_MUTE */
+#define WM2200_SPK1L_MUTE_MASK 0x1000 /* SPK1L_MUTE */
+#define WM2200_SPK1L_MUTE_SHIFT 12 /* SPK1L_MUTE */
+#define WM2200_SPK1L_MUTE_WIDTH 1 /* SPK1L_MUTE */
+#define WM2200_SPK1_MUTE_ENDIAN 0x0100 /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_ENDIAN_MASK 0x0100 /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_ENDIAN_SHIFT 8 /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_ENDIAN_WIDTH 1 /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_SEQL_MASK 0x00FF /* SPK1_MUTE_SEQL - [7:0] */
+#define WM2200_SPK1_MUTE_SEQL_SHIFT 0 /* SPK1_MUTE_SEQL - [7:0] */
+#define WM2200_SPK1_MUTE_SEQL_WIDTH 8 /* SPK1_MUTE_SEQL - [7:0] */
+
+/*
+ * R1048 (0x418) - PDM 2
+ */
+#define WM2200_SPK1_FMT 0x0001 /* SPK1_FMT */
+#define WM2200_SPK1_FMT_MASK 0x0001 /* SPK1_FMT */
+#define WM2200_SPK1_FMT_SHIFT 0 /* SPK1_FMT */
+#define WM2200_SPK1_FMT_WIDTH 1 /* SPK1_FMT */
+
+/*
+ * R1280 (0x500) - Audio IF 1_1
+ */
+#define WM2200_AIF1_BCLK_INV 0x0040 /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_INV_MASK 0x0040 /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_INV_SHIFT 6 /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_INV_WIDTH 1 /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_FRC 0x0020 /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_FRC_MASK 0x0020 /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_FRC_SHIFT 5 /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_FRC_WIDTH 1 /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_MSTR 0x0010 /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_MSTR_MASK 0x0010 /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_MSTR_SHIFT 4 /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_MSTR_WIDTH 1 /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_DIV_MASK 0x000F /* AIF1_BCLK_DIV - [3:0] */
+#define WM2200_AIF1_BCLK_DIV_SHIFT 0 /* AIF1_BCLK_DIV - [3:0] */
+#define WM2200_AIF1_BCLK_DIV_WIDTH 4 /* AIF1_BCLK_DIV - [3:0] */
+
+/*
+ * R1281 (0x501) - Audio IF 1_2
+ */
+#define WM2200_AIF1TX_DAT_TRI 0x0020 /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_DAT_TRI_MASK 0x0020 /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_DAT_TRI_SHIFT 5 /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_DAT_TRI_WIDTH 1 /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_LRCLK_SRC 0x0008 /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_SRC_MASK 0x0008 /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_SRC_SHIFT 3 /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_SRC_WIDTH 1 /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_INV 0x0004 /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_INV_MASK 0x0004 /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_INV_SHIFT 2 /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_INV_WIDTH 1 /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_FRC 0x0002 /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_FRC_MASK 0x0002 /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_FRC_SHIFT 1 /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_FRC_WIDTH 1 /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_MSTR 0x0001 /* AIF1TX_LRCLK_MSTR */
+#define WM2200_AIF1TX_LRCLK_MSTR_MASK 0x0001 /* AIF1TX_LRCLK_MSTR */
+#define WM2200_AIF1TX_LRCLK_MSTR_SHIFT 0 /* AIF1TX_LRCLK_MSTR */
+#define WM2200_AIF1TX_LRCLK_MSTR_WIDTH 1 /* AIF1TX_LRCLK_MSTR */
+
+/*
+ * R1282 (0x502) - Audio IF 1_3
+ */
+#define WM2200_AIF1RX_LRCLK_INV 0x0004 /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_INV_MASK 0x0004 /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_INV_SHIFT 2 /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_INV_WIDTH 1 /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_FRC 0x0002 /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_FRC_MASK 0x0002 /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_FRC_SHIFT 1 /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_FRC_WIDTH 1 /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_MSTR 0x0001 /* AIF1RX_LRCLK_MSTR */
+#define WM2200_AIF1RX_LRCLK_MSTR_MASK 0x0001 /* AIF1RX_LRCLK_MSTR */
+#define WM2200_AIF1RX_LRCLK_MSTR_SHIFT 0 /* AIF1RX_LRCLK_MSTR */
+#define WM2200_AIF1RX_LRCLK_MSTR_WIDTH 1 /* AIF1RX_LRCLK_MSTR */
+
+/*
+ * R1283 (0x503) - Audio IF 1_4
+ */
+#define WM2200_AIF1_TRI 0x0040 /* AIF1_TRI */
+#define WM2200_AIF1_TRI_MASK 0x0040 /* AIF1_TRI */
+#define WM2200_AIF1_TRI_SHIFT 6 /* AIF1_TRI */
+#define WM2200_AIF1_TRI_WIDTH 1 /* AIF1_TRI */
+
+/*
+ * R1284 (0x504) - Audio IF 1_5
+ */
+#define WM2200_AIF1_FMT_MASK 0x0007 /* AIF1_FMT - [2:0] */
+#define WM2200_AIF1_FMT_SHIFT 0 /* AIF1_FMT - [2:0] */
+#define WM2200_AIF1_FMT_WIDTH 3 /* AIF1_FMT - [2:0] */
+
+/*
+ * R1285 (0x505) - Audio IF 1_6
+ */
+#define WM2200_AIF1TX_BCPF_MASK 0x07FF /* AIF1TX_BCPF - [10:0] */
+#define WM2200_AIF1TX_BCPF_SHIFT 0 /* AIF1TX_BCPF - [10:0] */
+#define WM2200_AIF1TX_BCPF_WIDTH 11 /* AIF1TX_BCPF - [10:0] */
+
+/*
+ * R1286 (0x506) - Audio IF 1_7
+ */
+#define WM2200_AIF1RX_BCPF_MASK 0x07FF /* AIF1RX_BCPF - [10:0] */
+#define WM2200_AIF1RX_BCPF_SHIFT 0 /* AIF1RX_BCPF - [10:0] */
+#define WM2200_AIF1RX_BCPF_WIDTH 11 /* AIF1RX_BCPF - [10:0] */
+
+/*
+ * R1287 (0x507) - Audio IF 1_8
+ */
+#define WM2200_AIF1TX_WL_MASK 0x3F00 /* AIF1TX_WL - [13:8] */
+#define WM2200_AIF1TX_WL_SHIFT 8 /* AIF1TX_WL - [13:8] */
+#define WM2200_AIF1TX_WL_WIDTH 6 /* AIF1TX_WL - [13:8] */
+#define WM2200_AIF1TX_SLOT_LEN_MASK 0x00FF /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1TX_SLOT_LEN_SHIFT 0 /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1TX_SLOT_LEN_WIDTH 8 /* AIF1TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1288 (0x508) - Audio IF 1_9
+ */
+#define WM2200_AIF1RX_WL_MASK 0x3F00 /* AIF1RX_WL - [13:8] */
+#define WM2200_AIF1RX_WL_SHIFT 8 /* AIF1RX_WL - [13:8] */
+#define WM2200_AIF1RX_WL_WIDTH 6 /* AIF1RX_WL - [13:8] */
+#define WM2200_AIF1RX_SLOT_LEN_MASK 0x00FF /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1RX_SLOT_LEN_SHIFT 0 /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1RX_SLOT_LEN_WIDTH 8 /* AIF1RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1289 (0x509) - Audio IF 1_10
+ */
+#define WM2200_AIF1TX1_SLOT_MASK 0x003F /* AIF1TX1_SLOT - [5:0] */
+#define WM2200_AIF1TX1_SLOT_SHIFT 0 /* AIF1TX1_SLOT - [5:0] */
+#define WM2200_AIF1TX1_SLOT_WIDTH 6 /* AIF1TX1_SLOT - [5:0] */
+
+/*
+ * R1290 (0x50A) - Audio IF 1_11
+ */
+#define WM2200_AIF1TX2_SLOT_MASK 0x003F /* AIF1TX2_SLOT - [5:0] */
+#define WM2200_AIF1TX2_SLOT_SHIFT 0 /* AIF1TX2_SLOT - [5:0] */
+#define WM2200_AIF1TX2_SLOT_WIDTH 6 /* AIF1TX2_SLOT - [5:0] */
+
+/*
+ * R1291 (0x50B) - Audio IF 1_12
+ */
+#define WM2200_AIF1TX3_SLOT_MASK 0x003F /* AIF1TX3_SLOT - [5:0] */
+#define WM2200_AIF1TX3_SLOT_SHIFT 0 /* AIF1TX3_SLOT - [5:0] */
+#define WM2200_AIF1TX3_SLOT_WIDTH 6 /* AIF1TX3_SLOT - [5:0] */
+
+/*
+ * R1292 (0x50C) - Audio IF 1_13
+ */
+#define WM2200_AIF1TX4_SLOT_MASK 0x003F /* AIF1TX4_SLOT - [5:0] */
+#define WM2200_AIF1TX4_SLOT_SHIFT 0 /* AIF1TX4_SLOT - [5:0] */
+#define WM2200_AIF1TX4_SLOT_WIDTH 6 /* AIF1TX4_SLOT - [5:0] */
+
+/*
+ * R1293 (0x50D) - Audio IF 1_14
+ */
+#define WM2200_AIF1TX5_SLOT_MASK 0x003F /* AIF1TX5_SLOT - [5:0] */
+#define WM2200_AIF1TX5_SLOT_SHIFT 0 /* AIF1TX5_SLOT - [5:0] */
+#define WM2200_AIF1TX5_SLOT_WIDTH 6 /* AIF1TX5_SLOT - [5:0] */
+
+/*
+ * R1294 (0x50E) - Audio IF 1_15
+ */
+#define WM2200_AIF1TX6_SLOT_MASK 0x003F /* AIF1TX6_SLOT - [5:0] */
+#define WM2200_AIF1TX6_SLOT_SHIFT 0 /* AIF1TX6_SLOT - [5:0] */
+#define WM2200_AIF1TX6_SLOT_WIDTH 6 /* AIF1TX6_SLOT - [5:0] */
+
+/*
+ * R1295 (0x50F) - Audio IF 1_16
+ */
+#define WM2200_AIF1RX1_SLOT_MASK 0x003F /* AIF1RX1_SLOT - [5:0] */
+#define WM2200_AIF1RX1_SLOT_SHIFT 0 /* AIF1RX1_SLOT - [5:0] */
+#define WM2200_AIF1RX1_SLOT_WIDTH 6 /* AIF1RX1_SLOT - [5:0] */
+
+/*
+ * R1296 (0x510) - Audio IF 1_17
+ */
+#define WM2200_AIF1RX2_SLOT_MASK 0x003F /* AIF1RX2_SLOT - [5:0] */
+#define WM2200_AIF1RX2_SLOT_SHIFT 0 /* AIF1RX2_SLOT - [5:0] */
+#define WM2200_AIF1RX2_SLOT_WIDTH 6 /* AIF1RX2_SLOT - [5:0] */
+
+/*
+ * R1297 (0x511) - Audio IF 1_18
+ */
+#define WM2200_AIF1RX3_SLOT_MASK 0x003F /* AIF1RX3_SLOT - [5:0] */
+#define WM2200_AIF1RX3_SLOT_SHIFT 0 /* AIF1RX3_SLOT - [5:0] */
+#define WM2200_AIF1RX3_SLOT_WIDTH 6 /* AIF1RX3_SLOT - [5:0] */
+
+/*
+ * R1298 (0x512) - Audio IF 1_19
+ */
+#define WM2200_AIF1RX4_SLOT_MASK 0x003F /* AIF1RX4_SLOT - [5:0] */
+#define WM2200_AIF1RX4_SLOT_SHIFT 0 /* AIF1RX4_SLOT - [5:0] */
+#define WM2200_AIF1RX4_SLOT_WIDTH 6 /* AIF1RX4_SLOT - [5:0] */
+
+/*
+ * R1299 (0x513) - Audio IF 1_20
+ */
+#define WM2200_AIF1RX5_SLOT_MASK 0x003F /* AIF1RX5_SLOT - [5:0] */
+#define WM2200_AIF1RX5_SLOT_SHIFT 0 /* AIF1RX5_SLOT - [5:0] */
+#define WM2200_AIF1RX5_SLOT_WIDTH 6 /* AIF1RX5_SLOT - [5:0] */
+
+/*
+ * R1300 (0x514) - Audio IF 1_21
+ */
+#define WM2200_AIF1RX6_SLOT_MASK 0x003F /* AIF1RX6_SLOT - [5:0] */
+#define WM2200_AIF1RX6_SLOT_SHIFT 0 /* AIF1RX6_SLOT - [5:0] */
+#define WM2200_AIF1RX6_SLOT_WIDTH 6 /* AIF1RX6_SLOT - [5:0] */
+
+/*
+ * R1301 (0x515) - Audio IF 1_22
+ */
+#define WM2200_AIF1RX6_ENA 0x0800 /* AIF1RX6_ENA */
+#define WM2200_AIF1RX6_ENA_MASK 0x0800 /* AIF1RX6_ENA */
+#define WM2200_AIF1RX6_ENA_SHIFT 11 /* AIF1RX6_ENA */
+#define WM2200_AIF1RX6_ENA_WIDTH 1 /* AIF1RX6_ENA */
+#define WM2200_AIF1RX5_ENA 0x0400 /* AIF1RX5_ENA */
+#define WM2200_AIF1RX5_ENA_MASK 0x0400 /* AIF1RX5_ENA */
+#define WM2200_AIF1RX5_ENA_SHIFT 10 /* AIF1RX5_ENA */
+#define WM2200_AIF1RX5_ENA_WIDTH 1 /* AIF1RX5_ENA */
+#define WM2200_AIF1RX4_ENA 0x0200 /* AIF1RX4_ENA */
+#define WM2200_AIF1RX4_ENA_MASK 0x0200 /* AIF1RX4_ENA */
+#define WM2200_AIF1RX4_ENA_SHIFT 9 /* AIF1RX4_ENA */
+#define WM2200_AIF1RX4_ENA_WIDTH 1 /* AIF1RX4_ENA */
+#define WM2200_AIF1RX3_ENA 0x0100 /* AIF1RX3_ENA */
+#define WM2200_AIF1RX3_ENA_MASK 0x0100 /* AIF1RX3_ENA */
+#define WM2200_AIF1RX3_ENA_SHIFT 8 /* AIF1RX3_ENA */
+#define WM2200_AIF1RX3_ENA_WIDTH 1 /* AIF1RX3_ENA */
+#define WM2200_AIF1RX2_ENA 0x0080 /* AIF1RX2_ENA */
+#define WM2200_AIF1RX2_ENA_MASK 0x0080 /* AIF1RX2_ENA */
+#define WM2200_AIF1RX2_ENA_SHIFT 7 /* AIF1RX2_ENA */
+#define WM2200_AIF1RX2_ENA_WIDTH 1 /* AIF1RX2_ENA */
+#define WM2200_AIF1RX1_ENA 0x0040 /* AIF1RX1_ENA */
+#define WM2200_AIF1RX1_ENA_MASK 0x0040 /* AIF1RX1_ENA */
+#define WM2200_AIF1RX1_ENA_SHIFT 6 /* AIF1RX1_ENA */
+#define WM2200_AIF1RX1_ENA_WIDTH 1 /* AIF1RX1_ENA */
+#define WM2200_AIF1TX6_ENA 0x0020 /* AIF1TX6_ENA */
+#define WM2200_AIF1TX6_ENA_MASK 0x0020 /* AIF1TX6_ENA */
+#define WM2200_AIF1TX6_ENA_SHIFT 5 /* AIF1TX6_ENA */
+#define WM2200_AIF1TX6_ENA_WIDTH 1 /* AIF1TX6_ENA */
+#define WM2200_AIF1TX5_ENA 0x0010 /* AIF1TX5_ENA */
+#define WM2200_AIF1TX5_ENA_MASK 0x0010 /* AIF1TX5_ENA */
+#define WM2200_AIF1TX5_ENA_SHIFT 4 /* AIF1TX5_ENA */
+#define WM2200_AIF1TX5_ENA_WIDTH 1 /* AIF1TX5_ENA */
+#define WM2200_AIF1TX4_ENA 0x0008 /* AIF1TX4_ENA */
+#define WM2200_AIF1TX4_ENA_MASK 0x0008 /* AIF1TX4_ENA */
+#define WM2200_AIF1TX4_ENA_SHIFT 3 /* AIF1TX4_ENA */
+#define WM2200_AIF1TX4_ENA_WIDTH 1 /* AIF1TX4_ENA */
+#define WM2200_AIF1TX3_ENA 0x0004 /* AIF1TX3_ENA */
+#define WM2200_AIF1TX3_ENA_MASK 0x0004 /* AIF1TX3_ENA */
+#define WM2200_AIF1TX3_ENA_SHIFT 2 /* AIF1TX3_ENA */
+#define WM2200_AIF1TX3_ENA_WIDTH 1 /* AIF1TX3_ENA */
+#define WM2200_AIF1TX2_ENA 0x0002 /* AIF1TX2_ENA */
+#define WM2200_AIF1TX2_ENA_MASK 0x0002 /* AIF1TX2_ENA */
+#define WM2200_AIF1TX2_ENA_SHIFT 1 /* AIF1TX2_ENA */
+#define WM2200_AIF1TX2_ENA_WIDTH 1 /* AIF1TX2_ENA */
+#define WM2200_AIF1TX1_ENA 0x0001 /* AIF1TX1_ENA */
+#define WM2200_AIF1TX1_ENA_MASK 0x0001 /* AIF1TX1_ENA */
+#define WM2200_AIF1TX1_ENA_SHIFT 0 /* AIF1TX1_ENA */
+#define WM2200_AIF1TX1_ENA_WIDTH 1 /* AIF1TX1_ENA */
+
+/*
+ * R1536 (0x600) - OUT1LMIX Input 1 Source
+ */
+#define WM2200_OUT1LMIX_SRC1_MASK 0x007F /* OUT1LMIX_SRC1 - [6:0] */
+#define WM2200_OUT1LMIX_SRC1_SHIFT 0 /* OUT1LMIX_SRC1 - [6:0] */
+#define WM2200_OUT1LMIX_SRC1_WIDTH 7 /* OUT1LMIX_SRC1 - [6:0] */
+
+/*
+ * R1537 (0x601) - OUT1LMIX Input 1 Volume
+ */
+#define WM2200_OUT1LMIX_VOL1_MASK 0x00FE /* OUT1LMIX_VOL1 - [7:1] */
+#define WM2200_OUT1LMIX_VOL1_SHIFT 1 /* OUT1LMIX_VOL1 - [7:1] */
+#define WM2200_OUT1LMIX_VOL1_WIDTH 7 /* OUT1LMIX_VOL1 - [7:1] */
+
+/*
+ * R1538 (0x602) - OUT1LMIX Input 2 Source
+ */
+#define WM2200_OUT1LMIX_SRC2_MASK 0x007F /* OUT1LMIX_SRC2 - [6:0] */
+#define WM2200_OUT1LMIX_SRC2_SHIFT 0 /* OUT1LMIX_SRC2 - [6:0] */
+#define WM2200_OUT1LMIX_SRC2_WIDTH 7 /* OUT1LMIX_SRC2 - [6:0] */
+
+/*
+ * R1539 (0x603) - OUT1LMIX Input 2 Volume
+ */
+#define WM2200_OUT1LMIX_VOL2_MASK 0x00FE /* OUT1LMIX_VOL2 - [7:1] */
+#define WM2200_OUT1LMIX_VOL2_SHIFT 1 /* OUT1LMIX_VOL2 - [7:1] */
+#define WM2200_OUT1LMIX_VOL2_WIDTH 7 /* OUT1LMIX_VOL2 - [7:1] */
+
+/*
+ * R1540 (0x604) - OUT1LMIX Input 3 Source
+ */
+#define WM2200_OUT1LMIX_SRC3_MASK 0x007F /* OUT1LMIX_SRC3 - [6:0] */
+#define WM2200_OUT1LMIX_SRC3_SHIFT 0 /* OUT1LMIX_SRC3 - [6:0] */
+#define WM2200_OUT1LMIX_SRC3_WIDTH 7 /* OUT1LMIX_SRC3 - [6:0] */
+
+/*
+ * R1541 (0x605) - OUT1LMIX Input 3 Volume
+ */
+#define WM2200_OUT1LMIX_VOL3_MASK 0x00FE /* OUT1LMIX_VOL3 - [7:1] */
+#define WM2200_OUT1LMIX_VOL3_SHIFT 1 /* OUT1LMIX_VOL3 - [7:1] */
+#define WM2200_OUT1LMIX_VOL3_WIDTH 7 /* OUT1LMIX_VOL3 - [7:1] */
+
+/*
+ * R1542 (0x606) - OUT1LMIX Input 4 Source
+ */
+#define WM2200_OUT1LMIX_SRC4_MASK 0x007F /* OUT1LMIX_SRC4 - [6:0] */
+#define WM2200_OUT1LMIX_SRC4_SHIFT 0 /* OUT1LMIX_SRC4 - [6:0] */
+#define WM2200_OUT1LMIX_SRC4_WIDTH 7 /* OUT1LMIX_SRC4 - [6:0] */
+
+/*
+ * R1543 (0x607) - OUT1LMIX Input 4 Volume
+ */
+#define WM2200_OUT1LMIX_VOL4_MASK 0x00FE /* OUT1LMIX_VOL4 - [7:1] */
+#define WM2200_OUT1LMIX_VOL4_SHIFT 1 /* OUT1LMIX_VOL4 - [7:1] */
+#define WM2200_OUT1LMIX_VOL4_WIDTH 7 /* OUT1LMIX_VOL4 - [7:1] */
+
+/*
+ * R1544 (0x608) - OUT1RMIX Input 1 Source
+ */
+#define WM2200_OUT1RMIX_SRC1_MASK 0x007F /* OUT1RMIX_SRC1 - [6:0] */
+#define WM2200_OUT1RMIX_SRC1_SHIFT 0 /* OUT1RMIX_SRC1 - [6:0] */
+#define WM2200_OUT1RMIX_SRC1_WIDTH 7 /* OUT1RMIX_SRC1 - [6:0] */
+
+/*
+ * R1545 (0x609) - OUT1RMIX Input 1 Volume
+ */
+#define WM2200_OUT1RMIX_VOL1_MASK 0x00FE /* OUT1RMIX_VOL1 - [7:1] */
+#define WM2200_OUT1RMIX_VOL1_SHIFT 1 /* OUT1RMIX_VOL1 - [7:1] */
+#define WM2200_OUT1RMIX_VOL1_WIDTH 7 /* OUT1RMIX_VOL1 - [7:1] */
+
+/*
+ * R1546 (0x60A) - OUT1RMIX Input 2 Source
+ */
+#define WM2200_OUT1RMIX_SRC2_MASK 0x007F /* OUT1RMIX_SRC2 - [6:0] */
+#define WM2200_OUT1RMIX_SRC2_SHIFT 0 /* OUT1RMIX_SRC2 - [6:0] */
+#define WM2200_OUT1RMIX_SRC2_WIDTH 7 /* OUT1RMIX_SRC2 - [6:0] */
+
+/*
+ * R1547 (0x60B) - OUT1RMIX Input 2 Volume
+ */
+#define WM2200_OUT1RMIX_VOL2_MASK 0x00FE /* OUT1RMIX_VOL2 - [7:1] */
+#define WM2200_OUT1RMIX_VOL2_SHIFT 1 /* OUT1RMIX_VOL2 - [7:1] */
+#define WM2200_OUT1RMIX_VOL2_WIDTH 7 /* OUT1RMIX_VOL2 - [7:1] */
+
+/*
+ * R1548 (0x60C) - OUT1RMIX Input 3 Source
+ */
+#define WM2200_OUT1RMIX_SRC3_MASK 0x007F /* OUT1RMIX_SRC3 - [6:0] */
+#define WM2200_OUT1RMIX_SRC3_SHIFT 0 /* OUT1RMIX_SRC3 - [6:0] */
+#define WM2200_OUT1RMIX_SRC3_WIDTH 7 /* OUT1RMIX_SRC3 - [6:0] */
+
+/*
+ * R1549 (0x60D) - OUT1RMIX Input 3 Volume
+ */
+#define WM2200_OUT1RMIX_VOL3_MASK 0x00FE /* OUT1RMIX_VOL3 - [7:1] */
+#define WM2200_OUT1RMIX_VOL3_SHIFT 1 /* OUT1RMIX_VOL3 - [7:1] */
+#define WM2200_OUT1RMIX_VOL3_WIDTH 7 /* OUT1RMIX_VOL3 - [7:1] */
+
+/*
+ * R1550 (0x60E) - OUT1RMIX Input 4 Source
+ */
+#define WM2200_OUT1RMIX_SRC4_MASK 0x007F /* OUT1RMIX_SRC4 - [6:0] */
+#define WM2200_OUT1RMIX_SRC4_SHIFT 0 /* OUT1RMIX_SRC4 - [6:0] */
+#define WM2200_OUT1RMIX_SRC4_WIDTH 7 /* OUT1RMIX_SRC4 - [6:0] */
+
+/*
+ * R1551 (0x60F) - OUT1RMIX Input 4 Volume
+ */
+#define WM2200_OUT1RMIX_VOL4_MASK 0x00FE /* OUT1RMIX_VOL4 - [7:1] */
+#define WM2200_OUT1RMIX_VOL4_SHIFT 1 /* OUT1RMIX_VOL4 - [7:1] */
+#define WM2200_OUT1RMIX_VOL4_WIDTH 7 /* OUT1RMIX_VOL4 - [7:1] */
+
+/*
+ * R1552 (0x610) - OUT2LMIX Input 1 Source
+ */
+#define WM2200_OUT2LMIX_SRC1_MASK 0x007F /* OUT2LMIX_SRC1 - [6:0] */
+#define WM2200_OUT2LMIX_SRC1_SHIFT 0 /* OUT2LMIX_SRC1 - [6:0] */
+#define WM2200_OUT2LMIX_SRC1_WIDTH 7 /* OUT2LMIX_SRC1 - [6:0] */
+
+/*
+ * R1553 (0x611) - OUT2LMIX Input 1 Volume
+ */
+#define WM2200_OUT2LMIX_VOL1_MASK 0x00FE /* OUT2LMIX_VOL1 - [7:1] */
+#define WM2200_OUT2LMIX_VOL1_SHIFT 1 /* OUT2LMIX_VOL1 - [7:1] */
+#define WM2200_OUT2LMIX_VOL1_WIDTH 7 /* OUT2LMIX_VOL1 - [7:1] */
+
+/*
+ * R1554 (0x612) - OUT2LMIX Input 2 Source
+ */
+#define WM2200_OUT2LMIX_SRC2_MASK 0x007F /* OUT2LMIX_SRC2 - [6:0] */
+#define WM2200_OUT2LMIX_SRC2_SHIFT 0 /* OUT2LMIX_SRC2 - [6:0] */
+#define WM2200_OUT2LMIX_SRC2_WIDTH 7 /* OUT2LMIX_SRC2 - [6:0] */
+
+/*
+ * R1555 (0x613) - OUT2LMIX Input 2 Volume
+ */
+#define WM2200_OUT2LMIX_VOL2_MASK 0x00FE /* OUT2LMIX_VOL2 - [7:1] */
+#define WM2200_OUT2LMIX_VOL2_SHIFT 1 /* OUT2LMIX_VOL2 - [7:1] */
+#define WM2200_OUT2LMIX_VOL2_WIDTH 7 /* OUT2LMIX_VOL2 - [7:1] */
+
+/*
+ * R1556 (0x614) - OUT2LMIX Input 3 Source
+ */
+#define WM2200_OUT2LMIX_SRC3_MASK 0x007F /* OUT2LMIX_SRC3 - [6:0] */
+#define WM2200_OUT2LMIX_SRC3_SHIFT 0 /* OUT2LMIX_SRC3 - [6:0] */
+#define WM2200_OUT2LMIX_SRC3_WIDTH 7 /* OUT2LMIX_SRC3 - [6:0] */
+
+/*
+ * R1557 (0x615) - OUT2LMIX Input 3 Volume
+ */
+#define WM2200_OUT2LMIX_VOL3_MASK 0x00FE /* OUT2LMIX_VOL3 - [7:1] */
+#define WM2200_OUT2LMIX_VOL3_SHIFT 1 /* OUT2LMIX_VOL3 - [7:1] */
+#define WM2200_OUT2LMIX_VOL3_WIDTH 7 /* OUT2LMIX_VOL3 - [7:1] */
+
+/*
+ * R1558 (0x616) - OUT2LMIX Input 4 Source
+ */
+#define WM2200_OUT2LMIX_SRC4_MASK 0x007F /* OUT2LMIX_SRC4 - [6:0] */
+#define WM2200_OUT2LMIX_SRC4_SHIFT 0 /* OUT2LMIX_SRC4 - [6:0] */
+#define WM2200_OUT2LMIX_SRC4_WIDTH 7 /* OUT2LMIX_SRC4 - [6:0] */
+
+/*
+ * R1559 (0x617) - OUT2LMIX Input 4 Volume
+ */
+#define WM2200_OUT2LMIX_VOL4_MASK 0x00FE /* OUT2LMIX_VOL4 - [7:1] */
+#define WM2200_OUT2LMIX_VOL4_SHIFT 1 /* OUT2LMIX_VOL4 - [7:1] */
+#define WM2200_OUT2LMIX_VOL4_WIDTH 7 /* OUT2LMIX_VOL4 - [7:1] */
+
+/*
+ * R1560 (0x618) - OUT2RMIX Input 1 Source
+ */
+#define WM2200_OUT2RMIX_SRC1_MASK 0x007F /* OUT2RMIX_SRC1 - [6:0] */
+#define WM2200_OUT2RMIX_SRC1_SHIFT 0 /* OUT2RMIX_SRC1 - [6:0] */
+#define WM2200_OUT2RMIX_SRC1_WIDTH 7 /* OUT2RMIX_SRC1 - [6:0] */
+
+/*
+ * R1561 (0x619) - OUT2RMIX Input 1 Volume
+ */
+#define WM2200_OUT2RMIX_VOL1_MASK 0x00FE /* OUT2RMIX_VOL1 - [7:1] */
+#define WM2200_OUT2RMIX_VOL1_SHIFT 1 /* OUT2RMIX_VOL1 - [7:1] */
+#define WM2200_OUT2RMIX_VOL1_WIDTH 7 /* OUT2RMIX_VOL1 - [7:1] */
+
+/*
+ * R1562 (0x61A) - OUT2RMIX Input 2 Source
+ */
+#define WM2200_OUT2RMIX_SRC2_MASK 0x007F /* OUT2RMIX_SRC2 - [6:0] */
+#define WM2200_OUT2RMIX_SRC2_SHIFT 0 /* OUT2RMIX_SRC2 - [6:0] */
+#define WM2200_OUT2RMIX_SRC2_WIDTH 7 /* OUT2RMIX_SRC2 - [6:0] */
+
+/*
+ * R1563 (0x61B) - OUT2RMIX Input 2 Volume
+ */
+#define WM2200_OUT2RMIX_VOL2_MASK 0x00FE /* OUT2RMIX_VOL2 - [7:1] */
+#define WM2200_OUT2RMIX_VOL2_SHIFT 1 /* OUT2RMIX_VOL2 - [7:1] */
+#define WM2200_OUT2RMIX_VOL2_WIDTH 7 /* OUT2RMIX_VOL2 - [7:1] */
+
+/*
+ * R1564 (0x61C) - OUT2RMIX Input 3 Source
+ */
+#define WM2200_OUT2RMIX_SRC3_MASK 0x007F /* OUT2RMIX_SRC3 - [6:0] */
+#define WM2200_OUT2RMIX_SRC3_SHIFT 0 /* OUT2RMIX_SRC3 - [6:0] */
+#define WM2200_OUT2RMIX_SRC3_WIDTH 7 /* OUT2RMIX_SRC3 - [6:0] */
+
+/*
+ * R1565 (0x61D) - OUT2RMIX Input 3 Volume
+ */
+#define WM2200_OUT2RMIX_VOL3_MASK 0x00FE /* OUT2RMIX_VOL3 - [7:1] */
+#define WM2200_OUT2RMIX_VOL3_SHIFT 1 /* OUT2RMIX_VOL3 - [7:1] */
+#define WM2200_OUT2RMIX_VOL3_WIDTH 7 /* OUT2RMIX_VOL3 - [7:1] */
+
+/*
+ * R1566 (0x61E) - OUT2RMIX Input 4 Source
+ */
+#define WM2200_OUT2RMIX_SRC4_MASK 0x007F /* OUT2RMIX_SRC4 - [6:0] */
+#define WM2200_OUT2RMIX_SRC4_SHIFT 0 /* OUT2RMIX_SRC4 - [6:0] */
+#define WM2200_OUT2RMIX_SRC4_WIDTH 7 /* OUT2RMIX_SRC4 - [6:0] */
+
+/*
+ * R1567 (0x61F) - OUT2RMIX Input 4 Volume
+ */
+#define WM2200_OUT2RMIX_VOL4_MASK 0x00FE /* OUT2RMIX_VOL4 - [7:1] */
+#define WM2200_OUT2RMIX_VOL4_SHIFT 1 /* OUT2RMIX_VOL4 - [7:1] */
+#define WM2200_OUT2RMIX_VOL4_WIDTH 7 /* OUT2RMIX_VOL4 - [7:1] */
+
+/*
+ * R1568 (0x620) - AIF1TX1MIX Input 1 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC1_MASK 0x007F /* AIF1TX1MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC1_SHIFT 0 /* AIF1TX1MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC1_WIDTH 7 /* AIF1TX1MIX_SRC1 - [6:0] */
+
+/*
+ * R1569 (0x621) - AIF1TX1MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL1_MASK 0x00FE /* AIF1TX1MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL1_SHIFT 1 /* AIF1TX1MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL1_WIDTH 7 /* AIF1TX1MIX_VOL1 - [7:1] */
+
+/*
+ * R1570 (0x622) - AIF1TX1MIX Input 2 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC2_MASK 0x007F /* AIF1TX1MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC2_SHIFT 0 /* AIF1TX1MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC2_WIDTH 7 /* AIF1TX1MIX_SRC2 - [6:0] */
+
+/*
+ * R1571 (0x623) - AIF1TX1MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL2_MASK 0x00FE /* AIF1TX1MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL2_SHIFT 1 /* AIF1TX1MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL2_WIDTH 7 /* AIF1TX1MIX_VOL2 - [7:1] */
+
+/*
+ * R1572 (0x624) - AIF1TX1MIX Input 3 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC3_MASK 0x007F /* AIF1TX1MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC3_SHIFT 0 /* AIF1TX1MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC3_WIDTH 7 /* AIF1TX1MIX_SRC3 - [6:0] */
+
+/*
+ * R1573 (0x625) - AIF1TX1MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL3_MASK 0x00FE /* AIF1TX1MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL3_SHIFT 1 /* AIF1TX1MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL3_WIDTH 7 /* AIF1TX1MIX_VOL3 - [7:1] */
+
+/*
+ * R1574 (0x626) - AIF1TX1MIX Input 4 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC4_MASK 0x007F /* AIF1TX1MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC4_SHIFT 0 /* AIF1TX1MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC4_WIDTH 7 /* AIF1TX1MIX_SRC4 - [6:0] */
+
+/*
+ * R1575 (0x627) - AIF1TX1MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL4_MASK 0x00FE /* AIF1TX1MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL4_SHIFT 1 /* AIF1TX1MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL4_WIDTH 7 /* AIF1TX1MIX_VOL4 - [7:1] */
+
+/*
+ * R1576 (0x628) - AIF1TX2MIX Input 1 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC1_MASK 0x007F /* AIF1TX2MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC1_SHIFT 0 /* AIF1TX2MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC1_WIDTH 7 /* AIF1TX2MIX_SRC1 - [6:0] */
+
+/*
+ * R1577 (0x629) - AIF1TX2MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL1_MASK 0x00FE /* AIF1TX2MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL1_SHIFT 1 /* AIF1TX2MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL1_WIDTH 7 /* AIF1TX2MIX_VOL1 - [7:1] */
+
+/*
+ * R1578 (0x62A) - AIF1TX2MIX Input 2 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC2_MASK 0x007F /* AIF1TX2MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC2_SHIFT 0 /* AIF1TX2MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC2_WIDTH 7 /* AIF1TX2MIX_SRC2 - [6:0] */
+
+/*
+ * R1579 (0x62B) - AIF1TX2MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL2_MASK 0x00FE /* AIF1TX2MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL2_SHIFT 1 /* AIF1TX2MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL2_WIDTH 7 /* AIF1TX2MIX_VOL2 - [7:1] */
+
+/*
+ * R1580 (0x62C) - AIF1TX2MIX Input 3 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC3_MASK 0x007F /* AIF1TX2MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC3_SHIFT 0 /* AIF1TX2MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC3_WIDTH 7 /* AIF1TX2MIX_SRC3 - [6:0] */
+
+/*
+ * R1581 (0x62D) - AIF1TX2MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL3_MASK 0x00FE /* AIF1TX2MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL3_SHIFT 1 /* AIF1TX2MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL3_WIDTH 7 /* AIF1TX2MIX_VOL3 - [7:1] */
+
+/*
+ * R1582 (0x62E) - AIF1TX2MIX Input 4 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC4_MASK 0x007F /* AIF1TX2MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC4_SHIFT 0 /* AIF1TX2MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC4_WIDTH 7 /* AIF1TX2MIX_SRC4 - [6:0] */
+
+/*
+ * R1583 (0x62F) - AIF1TX2MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL4_MASK 0x00FE /* AIF1TX2MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL4_SHIFT 1 /* AIF1TX2MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL4_WIDTH 7 /* AIF1TX2MIX_VOL4 - [7:1] */
+
+/*
+ * R1584 (0x630) - AIF1TX3MIX Input 1 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC1_MASK 0x007F /* AIF1TX3MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC1_SHIFT 0 /* AIF1TX3MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC1_WIDTH 7 /* AIF1TX3MIX_SRC1 - [6:0] */
+
+/*
+ * R1585 (0x631) - AIF1TX3MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL1_MASK 0x00FE /* AIF1TX3MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL1_SHIFT 1 /* AIF1TX3MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL1_WIDTH 7 /* AIF1TX3MIX_VOL1 - [7:1] */
+
+/*
+ * R1586 (0x632) - AIF1TX3MIX Input 2 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC2_MASK 0x007F /* AIF1TX3MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC2_SHIFT 0 /* AIF1TX3MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC2_WIDTH 7 /* AIF1TX3MIX_SRC2 - [6:0] */
+
+/*
+ * R1587 (0x633) - AIF1TX3MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL2_MASK 0x00FE /* AIF1TX3MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL2_SHIFT 1 /* AIF1TX3MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL2_WIDTH 7 /* AIF1TX3MIX_VOL2 - [7:1] */
+
+/*
+ * R1588 (0x634) - AIF1TX3MIX Input 3 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC3_MASK 0x007F /* AIF1TX3MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC3_SHIFT 0 /* AIF1TX3MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC3_WIDTH 7 /* AIF1TX3MIX_SRC3 - [6:0] */
+
+/*
+ * R1589 (0x635) - AIF1TX3MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL3_MASK 0x00FE /* AIF1TX3MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL3_SHIFT 1 /* AIF1TX3MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL3_WIDTH 7 /* AIF1TX3MIX_VOL3 - [7:1] */
+
+/*
+ * R1590 (0x636) - AIF1TX3MIX Input 4 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC4_MASK 0x007F /* AIF1TX3MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC4_SHIFT 0 /* AIF1TX3MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC4_WIDTH 7 /* AIF1TX3MIX_SRC4 - [6:0] */
+
+/*
+ * R1591 (0x637) - AIF1TX3MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL4_MASK 0x00FE /* AIF1TX3MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL4_SHIFT 1 /* AIF1TX3MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL4_WIDTH 7 /* AIF1TX3MIX_VOL4 - [7:1] */
+
+/*
+ * R1592 (0x638) - AIF1TX4MIX Input 1 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC1_MASK 0x007F /* AIF1TX4MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC1_SHIFT 0 /* AIF1TX4MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC1_WIDTH 7 /* AIF1TX4MIX_SRC1 - [6:0] */
+
+/*
+ * R1593 (0x639) - AIF1TX4MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL1_MASK 0x00FE /* AIF1TX4MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL1_SHIFT 1 /* AIF1TX4MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL1_WIDTH 7 /* AIF1TX4MIX_VOL1 - [7:1] */
+
+/*
+ * R1594 (0x63A) - AIF1TX4MIX Input 2 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC2_MASK 0x007F /* AIF1TX4MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC2_SHIFT 0 /* AIF1TX4MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC2_WIDTH 7 /* AIF1TX4MIX_SRC2 - [6:0] */
+
+/*
+ * R1595 (0x63B) - AIF1TX4MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL2_MASK 0x00FE /* AIF1TX4MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL2_SHIFT 1 /* AIF1TX4MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL2_WIDTH 7 /* AIF1TX4MIX_VOL2 - [7:1] */
+
+/*
+ * R1596 (0x63C) - AIF1TX4MIX Input 3 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC3_MASK 0x007F /* AIF1TX4MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC3_SHIFT 0 /* AIF1TX4MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC3_WIDTH 7 /* AIF1TX4MIX_SRC3 - [6:0] */
+
+/*
+ * R1597 (0x63D) - AIF1TX4MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL3_MASK 0x00FE /* AIF1TX4MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL3_SHIFT 1 /* AIF1TX4MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL3_WIDTH 7 /* AIF1TX4MIX_VOL3 - [7:1] */
+
+/*
+ * R1598 (0x63E) - AIF1TX4MIX Input 4 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC4_MASK 0x007F /* AIF1TX4MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC4_SHIFT 0 /* AIF1TX4MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC4_WIDTH 7 /* AIF1TX4MIX_SRC4 - [6:0] */
+
+/*
+ * R1599 (0x63F) - AIF1TX4MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL4_MASK 0x00FE /* AIF1TX4MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL4_SHIFT 1 /* AIF1TX4MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL4_WIDTH 7 /* AIF1TX4MIX_VOL4 - [7:1] */
+
+/*
+ * R1600 (0x640) - AIF1TX5MIX Input 1 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC1_MASK 0x007F /* AIF1TX5MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC1_SHIFT 0 /* AIF1TX5MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC1_WIDTH 7 /* AIF1TX5MIX_SRC1 - [6:0] */
+
+/*
+ * R1601 (0x641) - AIF1TX5MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL1_MASK 0x00FE /* AIF1TX5MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL1_SHIFT 1 /* AIF1TX5MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL1_WIDTH 7 /* AIF1TX5MIX_VOL1 - [7:1] */
+
+/*
+ * R1602 (0x642) - AIF1TX5MIX Input 2 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC2_MASK 0x007F /* AIF1TX5MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC2_SHIFT 0 /* AIF1TX5MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC2_WIDTH 7 /* AIF1TX5MIX_SRC2 - [6:0] */
+
+/*
+ * R1603 (0x643) - AIF1TX5MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL2_MASK 0x00FE /* AIF1TX5MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL2_SHIFT 1 /* AIF1TX5MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL2_WIDTH 7 /* AIF1TX5MIX_VOL2 - [7:1] */
+
+/*
+ * R1604 (0x644) - AIF1TX5MIX Input 3 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC3_MASK 0x007F /* AIF1TX5MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC3_SHIFT 0 /* AIF1TX5MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC3_WIDTH 7 /* AIF1TX5MIX_SRC3 - [6:0] */
+
+/*
+ * R1605 (0x645) - AIF1TX5MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL3_MASK 0x00FE /* AIF1TX5MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL3_SHIFT 1 /* AIF1TX5MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL3_WIDTH 7 /* AIF1TX5MIX_VOL3 - [7:1] */
+
+/*
+ * R1606 (0x646) - AIF1TX5MIX Input 4 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC4_MASK 0x007F /* AIF1TX5MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC4_SHIFT 0 /* AIF1TX5MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC4_WIDTH 7 /* AIF1TX5MIX_SRC4 - [6:0] */
+
+/*
+ * R1607 (0x647) - AIF1TX5MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL4_MASK 0x00FE /* AIF1TX5MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL4_SHIFT 1 /* AIF1TX5MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL4_WIDTH 7 /* AIF1TX5MIX_VOL4 - [7:1] */
+
+/*
+ * R1608 (0x648) - AIF1TX6MIX Input 1 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC1_MASK 0x007F /* AIF1TX6MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC1_SHIFT 0 /* AIF1TX6MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC1_WIDTH 7 /* AIF1TX6MIX_SRC1 - [6:0] */
+
+/*
+ * R1609 (0x649) - AIF1TX6MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL1_MASK 0x00FE /* AIF1TX6MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL1_SHIFT 1 /* AIF1TX6MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL1_WIDTH 7 /* AIF1TX6MIX_VOL1 - [7:1] */
+
+/*
+ * R1610 (0x64A) - AIF1TX6MIX Input 2 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC2_MASK 0x007F /* AIF1TX6MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC2_SHIFT 0 /* AIF1TX6MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC2_WIDTH 7 /* AIF1TX6MIX_SRC2 - [6:0] */
+
+/*
+ * R1611 (0x64B) - AIF1TX6MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL2_MASK 0x00FE /* AIF1TX6MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL2_SHIFT 1 /* AIF1TX6MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL2_WIDTH 7 /* AIF1TX6MIX_VOL2 - [7:1] */
+
+/*
+ * R1612 (0x64C) - AIF1TX6MIX Input 3 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC3_MASK 0x007F /* AIF1TX6MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC3_SHIFT 0 /* AIF1TX6MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC3_WIDTH 7 /* AIF1TX6MIX_SRC3 - [6:0] */
+
+/*
+ * R1613 (0x64D) - AIF1TX6MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL3_MASK 0x00FE /* AIF1TX6MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL3_SHIFT 1 /* AIF1TX6MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL3_WIDTH 7 /* AIF1TX6MIX_VOL3 - [7:1] */
+
+/*
+ * R1614 (0x64E) - AIF1TX6MIX Input 4 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC4_MASK 0x007F /* AIF1TX6MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC4_SHIFT 0 /* AIF1TX6MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC4_WIDTH 7 /* AIF1TX6MIX_SRC4 - [6:0] */
+
+/*
+ * R1615 (0x64F) - AIF1TX6MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL4_MASK 0x00FE /* AIF1TX6MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL4_SHIFT 1 /* AIF1TX6MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL4_WIDTH 7 /* AIF1TX6MIX_VOL4 - [7:1] */
+
+/*
+ * R1616 (0x650) - EQLMIX Input 1 Source
+ */
+#define WM2200_EQLMIX_SRC1_MASK 0x007F /* EQLMIX_SRC1 - [6:0] */
+#define WM2200_EQLMIX_SRC1_SHIFT 0 /* EQLMIX_SRC1 - [6:0] */
+#define WM2200_EQLMIX_SRC1_WIDTH 7 /* EQLMIX_SRC1 - [6:0] */
+
+/*
+ * R1617 (0x651) - EQLMIX Input 1 Volume
+ */
+#define WM2200_EQLMIX_VOL1_MASK 0x00FE /* EQLMIX_VOL1 - [7:1] */
+#define WM2200_EQLMIX_VOL1_SHIFT 1 /* EQLMIX_VOL1 - [7:1] */
+#define WM2200_EQLMIX_VOL1_WIDTH 7 /* EQLMIX_VOL1 - [7:1] */
+
+/*
+ * R1618 (0x652) - EQLMIX Input 2 Source
+ */
+#define WM2200_EQLMIX_SRC2_MASK 0x007F /* EQLMIX_SRC2 - [6:0] */
+#define WM2200_EQLMIX_SRC2_SHIFT 0 /* EQLMIX_SRC2 - [6:0] */
+#define WM2200_EQLMIX_SRC2_WIDTH 7 /* EQLMIX_SRC2 - [6:0] */
+
+/*
+ * R1619 (0x653) - EQLMIX Input 2 Volume
+ */
+#define WM2200_EQLMIX_VOL2_MASK 0x00FE /* EQLMIX_VOL2 - [7:1] */
+#define WM2200_EQLMIX_VOL2_SHIFT 1 /* EQLMIX_VOL2 - [7:1] */
+#define WM2200_EQLMIX_VOL2_WIDTH 7 /* EQLMIX_VOL2 - [7:1] */
+
+/*
+ * R1620 (0x654) - EQLMIX Input 3 Source
+ */
+#define WM2200_EQLMIX_SRC3_MASK 0x007F /* EQLMIX_SRC3 - [6:0] */
+#define WM2200_EQLMIX_SRC3_SHIFT 0 /* EQLMIX_SRC3 - [6:0] */
+#define WM2200_EQLMIX_SRC3_WIDTH 7 /* EQLMIX_SRC3 - [6:0] */
+
+/*
+ * R1621 (0x655) - EQLMIX Input 3 Volume
+ */
+#define WM2200_EQLMIX_VOL3_MASK 0x00FE /* EQLMIX_VOL3 - [7:1] */
+#define WM2200_EQLMIX_VOL3_SHIFT 1 /* EQLMIX_VOL3 - [7:1] */
+#define WM2200_EQLMIX_VOL3_WIDTH 7 /* EQLMIX_VOL3 - [7:1] */
+
+/*
+ * R1622 (0x656) - EQLMIX Input 4 Source
+ */
+#define WM2200_EQLMIX_SRC4_MASK 0x007F /* EQLMIX_SRC4 - [6:0] */
+#define WM2200_EQLMIX_SRC4_SHIFT 0 /* EQLMIX_SRC4 - [6:0] */
+#define WM2200_EQLMIX_SRC4_WIDTH 7 /* EQLMIX_SRC4 - [6:0] */
+
+/*
+ * R1623 (0x657) - EQLMIX Input 4 Volume
+ */
+#define WM2200_EQLMIX_VOL4_MASK 0x00FE /* EQLMIX_VOL4 - [7:1] */
+#define WM2200_EQLMIX_VOL4_SHIFT 1 /* EQLMIX_VOL4 - [7:1] */
+#define WM2200_EQLMIX_VOL4_WIDTH 7 /* EQLMIX_VOL4 - [7:1] */
+
+/*
+ * R1624 (0x658) - EQRMIX Input 1 Source
+ */
+#define WM2200_EQRMIX_SRC1_MASK 0x007F /* EQRMIX_SRC1 - [6:0] */
+#define WM2200_EQRMIX_SRC1_SHIFT 0 /* EQRMIX_SRC1 - [6:0] */
+#define WM2200_EQRMIX_SRC1_WIDTH 7 /* EQRMIX_SRC1 - [6:0] */
+
+/*
+ * R1625 (0x659) - EQRMIX Input 1 Volume
+ */
+#define WM2200_EQRMIX_VOL1_MASK 0x00FE /* EQRMIX_VOL1 - [7:1] */
+#define WM2200_EQRMIX_VOL1_SHIFT 1 /* EQRMIX_VOL1 - [7:1] */
+#define WM2200_EQRMIX_VOL1_WIDTH 7 /* EQRMIX_VOL1 - [7:1] */
+
+/*
+ * R1626 (0x65A) - EQRMIX Input 2 Source
+ */
+#define WM2200_EQRMIX_SRC2_MASK 0x007F /* EQRMIX_SRC2 - [6:0] */
+#define WM2200_EQRMIX_SRC2_SHIFT 0 /* EQRMIX_SRC2 - [6:0] */
+#define WM2200_EQRMIX_SRC2_WIDTH 7 /* EQRMIX_SRC2 - [6:0] */
+
+/*
+ * R1627 (0x65B) - EQRMIX Input 2 Volume
+ */
+#define WM2200_EQRMIX_VOL2_MASK 0x00FE /* EQRMIX_VOL2 - [7:1] */
+#define WM2200_EQRMIX_VOL2_SHIFT 1 /* EQRMIX_VOL2 - [7:1] */
+#define WM2200_EQRMIX_VOL2_WIDTH 7 /* EQRMIX_VOL2 - [7:1] */
+
+/*
+ * R1628 (0x65C) - EQRMIX Input 3 Source
+ */
+#define WM2200_EQRMIX_SRC3_MASK 0x007F /* EQRMIX_SRC3 - [6:0] */
+#define WM2200_EQRMIX_SRC3_SHIFT 0 /* EQRMIX_SRC3 - [6:0] */
+#define WM2200_EQRMIX_SRC3_WIDTH 7 /* EQRMIX_SRC3 - [6:0] */
+
+/*
+ * R1629 (0x65D) - EQRMIX Input 3 Volume
+ */
+#define WM2200_EQRMIX_VOL3_MASK 0x00FE /* EQRMIX_VOL3 - [7:1] */
+#define WM2200_EQRMIX_VOL3_SHIFT 1 /* EQRMIX_VOL3 - [7:1] */
+#define WM2200_EQRMIX_VOL3_WIDTH 7 /* EQRMIX_VOL3 - [7:1] */
+
+/*
+ * R1630 (0x65E) - EQRMIX Input 4 Source
+ */
+#define WM2200_EQRMIX_SRC4_MASK 0x007F /* EQRMIX_SRC4 - [6:0] */
+#define WM2200_EQRMIX_SRC4_SHIFT 0 /* EQRMIX_SRC4 - [6:0] */
+#define WM2200_EQRMIX_SRC4_WIDTH 7 /* EQRMIX_SRC4 - [6:0] */
+
+/*
+ * R1631 (0x65F) - EQRMIX Input 4 Volume
+ */
+#define WM2200_EQRMIX_VOL4_MASK 0x00FE /* EQRMIX_VOL4 - [7:1] */
+#define WM2200_EQRMIX_VOL4_SHIFT 1 /* EQRMIX_VOL4 - [7:1] */
+#define WM2200_EQRMIX_VOL4_WIDTH 7 /* EQRMIX_VOL4 - [7:1] */
+
+/*
+ * R1632 (0x660) - LHPF1MIX Input 1 Source
+ */
+#define WM2200_LHPF1MIX_SRC1_MASK 0x007F /* LHPF1MIX_SRC1 - [6:0] */
+#define WM2200_LHPF1MIX_SRC1_SHIFT 0 /* LHPF1MIX_SRC1 - [6:0] */
+#define WM2200_LHPF1MIX_SRC1_WIDTH 7 /* LHPF1MIX_SRC1 - [6:0] */
+
+/*
+ * R1633 (0x661) - LHPF1MIX Input 1 Volume
+ */
+#define WM2200_LHPF1MIX_VOL1_MASK 0x00FE /* LHPF1MIX_VOL1 - [7:1] */
+#define WM2200_LHPF1MIX_VOL1_SHIFT 1 /* LHPF1MIX_VOL1 - [7:1] */
+#define WM2200_LHPF1MIX_VOL1_WIDTH 7 /* LHPF1MIX_VOL1 - [7:1] */
+
+/*
+ * R1634 (0x662) - LHPF1MIX Input 2 Source
+ */
+#define WM2200_LHPF1MIX_SRC2_MASK 0x007F /* LHPF1MIX_SRC2 - [6:0] */
+#define WM2200_LHPF1MIX_SRC2_SHIFT 0 /* LHPF1MIX_SRC2 - [6:0] */
+#define WM2200_LHPF1MIX_SRC2_WIDTH 7 /* LHPF1MIX_SRC2 - [6:0] */
+
+/*
+ * R1635 (0x663) - LHPF1MIX Input 2 Volume
+ */
+#define WM2200_LHPF1MIX_VOL2_MASK 0x00FE /* LHPF1MIX_VOL2 - [7:1] */
+#define WM2200_LHPF1MIX_VOL2_SHIFT 1 /* LHPF1MIX_VOL2 - [7:1] */
+#define WM2200_LHPF1MIX_VOL2_WIDTH 7 /* LHPF1MIX_VOL2 - [7:1] */
+
+/*
+ * R1636 (0x664) - LHPF1MIX Input 3 Source
+ */
+#define WM2200_LHPF1MIX_SRC3_MASK 0x007F /* LHPF1MIX_SRC3 - [6:0] */
+#define WM2200_LHPF1MIX_SRC3_SHIFT 0 /* LHPF1MIX_SRC3 - [6:0] */
+#define WM2200_LHPF1MIX_SRC3_WIDTH 7 /* LHPF1MIX_SRC3 - [6:0] */
+
+/*
+ * R1637 (0x665) - LHPF1MIX Input 3 Volume
+ */
+#define WM2200_LHPF1MIX_VOL3_MASK 0x00FE /* LHPF1MIX_VOL3 - [7:1] */
+#define WM2200_LHPF1MIX_VOL3_SHIFT 1 /* LHPF1MIX_VOL3 - [7:1] */
+#define WM2200_LHPF1MIX_VOL3_WIDTH 7 /* LHPF1MIX_VOL3 - [7:1] */
+
+/*
+ * R1638 (0x666) - LHPF1MIX Input 4 Source
+ */
+#define WM2200_LHPF1MIX_SRC4_MASK 0x007F /* LHPF1MIX_SRC4 - [6:0] */
+#define WM2200_LHPF1MIX_SRC4_SHIFT 0 /* LHPF1MIX_SRC4 - [6:0] */
+#define WM2200_LHPF1MIX_SRC4_WIDTH 7 /* LHPF1MIX_SRC4 - [6:0] */
+
+/*
+ * R1639 (0x667) - LHPF1MIX Input 4 Volume
+ */
+#define WM2200_LHPF1MIX_VOL4_MASK 0x00FE /* LHPF1MIX_VOL4 - [7:1] */
+#define WM2200_LHPF1MIX_VOL4_SHIFT 1 /* LHPF1MIX_VOL4 - [7:1] */
+#define WM2200_LHPF1MIX_VOL4_WIDTH 7 /* LHPF1MIX_VOL4 - [7:1] */
+
+/*
+ * R1640 (0x668) - LHPF2MIX Input 1 Source
+ */
+#define WM2200_LHPF2MIX_SRC1_MASK 0x007F /* LHPF2MIX_SRC1 - [6:0] */
+#define WM2200_LHPF2MIX_SRC1_SHIFT 0 /* LHPF2MIX_SRC1 - [6:0] */
+#define WM2200_LHPF2MIX_SRC1_WIDTH 7 /* LHPF2MIX_SRC1 - [6:0] */
+
+/*
+ * R1641 (0x669) - LHPF2MIX Input 1 Volume
+ */
+#define WM2200_LHPF2MIX_VOL1_MASK 0x00FE /* LHPF2MIX_VOL1 - [7:1] */
+#define WM2200_LHPF2MIX_VOL1_SHIFT 1 /* LHPF2MIX_VOL1 - [7:1] */
+#define WM2200_LHPF2MIX_VOL1_WIDTH 7 /* LHPF2MIX_VOL1 - [7:1] */
+
+/*
+ * R1642 (0x66A) - LHPF2MIX Input 2 Source
+ */
+#define WM2200_LHPF2MIX_SRC2_MASK 0x007F /* LHPF2MIX_SRC2 - [6:0] */
+#define WM2200_LHPF2MIX_SRC2_SHIFT 0 /* LHPF2MIX_SRC2 - [6:0] */
+#define WM2200_LHPF2MIX_SRC2_WIDTH 7 /* LHPF2MIX_SRC2 - [6:0] */
+
+/*
+ * R1643 (0x66B) - LHPF2MIX Input 2 Volume
+ */
+#define WM2200_LHPF2MIX_VOL2_MASK 0x00FE /* LHPF2MIX_VOL2 - [7:1] */
+#define WM2200_LHPF2MIX_VOL2_SHIFT 1 /* LHPF2MIX_VOL2 - [7:1] */
+#define WM2200_LHPF2MIX_VOL2_WIDTH 7 /* LHPF2MIX_VOL2 - [7:1] */
+
+/*
+ * R1644 (0x66C) - LHPF2MIX Input 3 Source
+ */
+#define WM2200_LHPF2MIX_SRC3_MASK 0x007F /* LHPF2MIX_SRC3 - [6:0] */
+#define WM2200_LHPF2MIX_SRC3_SHIFT 0 /* LHPF2MIX_SRC3 - [6:0] */
+#define WM2200_LHPF2MIX_SRC3_WIDTH 7 /* LHPF2MIX_SRC3 - [6:0] */
+
+/*
+ * R1645 (0x66D) - LHPF2MIX Input 3 Volume
+ */
+#define WM2200_LHPF2MIX_VOL3_MASK 0x00FE /* LHPF2MIX_VOL3 - [7:1] */
+#define WM2200_LHPF2MIX_VOL3_SHIFT 1 /* LHPF2MIX_VOL3 - [7:1] */
+#define WM2200_LHPF2MIX_VOL3_WIDTH 7 /* LHPF2MIX_VOL3 - [7:1] */
+
+/*
+ * R1646 (0x66E) - LHPF2MIX Input 4 Source
+ */
+#define WM2200_LHPF2MIX_SRC4_MASK 0x007F /* LHPF2MIX_SRC4 - [6:0] */
+#define WM2200_LHPF2MIX_SRC4_SHIFT 0 /* LHPF2MIX_SRC4 - [6:0] */
+#define WM2200_LHPF2MIX_SRC4_WIDTH 7 /* LHPF2MIX_SRC4 - [6:0] */
+
+/*
+ * R1647 (0x66F) - LHPF2MIX Input 4 Volume
+ */
+#define WM2200_LHPF2MIX_VOL4_MASK 0x00FE /* LHPF2MIX_VOL4 - [7:1] */
+#define WM2200_LHPF2MIX_VOL4_SHIFT 1 /* LHPF2MIX_VOL4 - [7:1] */
+#define WM2200_LHPF2MIX_VOL4_WIDTH 7 /* LHPF2MIX_VOL4 - [7:1] */
+
+/*
+ * R1648 (0x670) - DSP1LMIX Input 1 Source
+ */
+#define WM2200_DSP1LMIX_SRC1_MASK 0x007F /* DSP1LMIX_SRC1 - [6:0] */
+#define WM2200_DSP1LMIX_SRC1_SHIFT 0 /* DSP1LMIX_SRC1 - [6:0] */
+#define WM2200_DSP1LMIX_SRC1_WIDTH 7 /* DSP1LMIX_SRC1 - [6:0] */
+
+/*
+ * R1649 (0x671) - DSP1LMIX Input 1 Volume
+ */
+#define WM2200_DSP1LMIX_VOL1_MASK 0x00FE /* DSP1LMIX_VOL1 - [7:1] */
+#define WM2200_DSP1LMIX_VOL1_SHIFT 1 /* DSP1LMIX_VOL1 - [7:1] */
+#define WM2200_DSP1LMIX_VOL1_WIDTH 7 /* DSP1LMIX_VOL1 - [7:1] */
+
+/*
+ * R1650 (0x672) - DSP1LMIX Input 2 Source
+ */
+#define WM2200_DSP1LMIX_SRC2_MASK 0x007F /* DSP1LMIX_SRC2 - [6:0] */
+#define WM2200_DSP1LMIX_SRC2_SHIFT 0 /* DSP1LMIX_SRC2 - [6:0] */
+#define WM2200_DSP1LMIX_SRC2_WIDTH 7 /* DSP1LMIX_SRC2 - [6:0] */
+
+/*
+ * R1651 (0x673) - DSP1LMIX Input 2 Volume
+ */
+#define WM2200_DSP1LMIX_VOL2_MASK 0x00FE /* DSP1LMIX_VOL2 - [7:1] */
+#define WM2200_DSP1LMIX_VOL2_SHIFT 1 /* DSP1LMIX_VOL2 - [7:1] */
+#define WM2200_DSP1LMIX_VOL2_WIDTH 7 /* DSP1LMIX_VOL2 - [7:1] */
+
+/*
+ * R1652 (0x674) - DSP1LMIX Input 3 Source
+ */
+#define WM2200_DSP1LMIX_SRC3_MASK 0x007F /* DSP1LMIX_SRC3 - [6:0] */
+#define WM2200_DSP1LMIX_SRC3_SHIFT 0 /* DSP1LMIX_SRC3 - [6:0] */
+#define WM2200_DSP1LMIX_SRC3_WIDTH 7 /* DSP1LMIX_SRC3 - [6:0] */
+
+/*
+ * R1653 (0x675) - DSP1LMIX Input 3 Volume
+ */
+#define WM2200_DSP1LMIX_VOL3_MASK 0x00FE /* DSP1LMIX_VOL3 - [7:1] */
+#define WM2200_DSP1LMIX_VOL3_SHIFT 1 /* DSP1LMIX_VOL3 - [7:1] */
+#define WM2200_DSP1LMIX_VOL3_WIDTH 7 /* DSP1LMIX_VOL3 - [7:1] */
+
+/*
+ * R1654 (0x676) - DSP1LMIX Input 4 Source
+ */
+#define WM2200_DSP1LMIX_SRC4_MASK 0x007F /* DSP1LMIX_SRC4 - [6:0] */
+#define WM2200_DSP1LMIX_SRC4_SHIFT 0 /* DSP1LMIX_SRC4 - [6:0] */
+#define WM2200_DSP1LMIX_SRC4_WIDTH 7 /* DSP1LMIX_SRC4 - [6:0] */
+
+/*
+ * R1655 (0x677) - DSP1LMIX Input 4 Volume
+ */
+#define WM2200_DSP1LMIX_VOL4_MASK 0x00FE /* DSP1LMIX_VOL4 - [7:1] */
+#define WM2200_DSP1LMIX_VOL4_SHIFT 1 /* DSP1LMIX_VOL4 - [7:1] */
+#define WM2200_DSP1LMIX_VOL4_WIDTH 7 /* DSP1LMIX_VOL4 - [7:1] */
+
+/*
+ * R1656 (0x678) - DSP1RMIX Input 1 Source
+ */
+#define WM2200_DSP1RMIX_SRC1_MASK 0x007F /* DSP1RMIX_SRC1 - [6:0] */
+#define WM2200_DSP1RMIX_SRC1_SHIFT 0 /* DSP1RMIX_SRC1 - [6:0] */
+#define WM2200_DSP1RMIX_SRC1_WIDTH 7 /* DSP1RMIX_SRC1 - [6:0] */
+
+/*
+ * R1657 (0x679) - DSP1RMIX Input 1 Volume
+ */
+#define WM2200_DSP1RMIX_VOL1_MASK 0x00FE /* DSP1RMIX_VOL1 - [7:1] */
+#define WM2200_DSP1RMIX_VOL1_SHIFT 1 /* DSP1RMIX_VOL1 - [7:1] */
+#define WM2200_DSP1RMIX_VOL1_WIDTH 7 /* DSP1RMIX_VOL1 - [7:1] */
+
+/*
+ * R1658 (0x67A) - DSP1RMIX Input 2 Source
+ */
+#define WM2200_DSP1RMIX_SRC2_MASK 0x007F /* DSP1RMIX_SRC2 - [6:0] */
+#define WM2200_DSP1RMIX_SRC2_SHIFT 0 /* DSP1RMIX_SRC2 - [6:0] */
+#define WM2200_DSP1RMIX_SRC2_WIDTH 7 /* DSP1RMIX_SRC2 - [6:0] */
+
+/*
+ * R1659 (0x67B) - DSP1RMIX Input 2 Volume
+ */
+#define WM2200_DSP1RMIX_VOL2_MASK 0x00FE /* DSP1RMIX_VOL2 - [7:1] */
+#define WM2200_DSP1RMIX_VOL2_SHIFT 1 /* DSP1RMIX_VOL2 - [7:1] */
+#define WM2200_DSP1RMIX_VOL2_WIDTH 7 /* DSP1RMIX_VOL2 - [7:1] */
+
+/*
+ * R1660 (0x67C) - DSP1RMIX Input 3 Source
+ */
+#define WM2200_DSP1RMIX_SRC3_MASK 0x007F /* DSP1RMIX_SRC3 - [6:0] */
+#define WM2200_DSP1RMIX_SRC3_SHIFT 0 /* DSP1RMIX_SRC3 - [6:0] */
+#define WM2200_DSP1RMIX_SRC3_WIDTH 7 /* DSP1RMIX_SRC3 - [6:0] */
+
+/*
+ * R1661 (0x67D) - DSP1RMIX Input 3 Volume
+ */
+#define WM2200_DSP1RMIX_VOL3_MASK 0x00FE /* DSP1RMIX_VOL3 - [7:1] */
+#define WM2200_DSP1RMIX_VOL3_SHIFT 1 /* DSP1RMIX_VOL3 - [7:1] */
+#define WM2200_DSP1RMIX_VOL3_WIDTH 7 /* DSP1RMIX_VOL3 - [7:1] */
+
+/*
+ * R1662 (0x67E) - DSP1RMIX Input 4 Source
+ */
+#define WM2200_DSP1RMIX_SRC4_MASK 0x007F /* DSP1RMIX_SRC4 - [6:0] */
+#define WM2200_DSP1RMIX_SRC4_SHIFT 0 /* DSP1RMIX_SRC4 - [6:0] */
+#define WM2200_DSP1RMIX_SRC4_WIDTH 7 /* DSP1RMIX_SRC4 - [6:0] */
+
+/*
+ * R1663 (0x67F) - DSP1RMIX Input 4 Volume
+ */
+#define WM2200_DSP1RMIX_VOL4_MASK 0x00FE /* DSP1RMIX_VOL4 - [7:1] */
+#define WM2200_DSP1RMIX_VOL4_SHIFT 1 /* DSP1RMIX_VOL4 - [7:1] */
+#define WM2200_DSP1RMIX_VOL4_WIDTH 7 /* DSP1RMIX_VOL4 - [7:1] */
+
+/*
+ * R1664 (0x680) - DSP1AUX1MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX1MIX_SRC1_MASK 0x007F /* DSP1AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX1MIX_SRC1_SHIFT 0 /* DSP1AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX1MIX_SRC1_WIDTH 7 /* DSP1AUX1MIX_SRC1 - [6:0] */
+
+/*
+ * R1665 (0x681) - DSP1AUX2MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX2MIX_SRC1_MASK 0x007F /* DSP1AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX2MIX_SRC1_SHIFT 0 /* DSP1AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX2MIX_SRC1_WIDTH 7 /* DSP1AUX2MIX_SRC1 - [6:0] */
+
+/*
+ * R1666 (0x682) - DSP1AUX3MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX3MIX_SRC1_MASK 0x007F /* DSP1AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX3MIX_SRC1_SHIFT 0 /* DSP1AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX3MIX_SRC1_WIDTH 7 /* DSP1AUX3MIX_SRC1 - [6:0] */
+
+/*
+ * R1667 (0x683) - DSP1AUX4MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX4MIX_SRC1_MASK 0x007F /* DSP1AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX4MIX_SRC1_SHIFT 0 /* DSP1AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX4MIX_SRC1_WIDTH 7 /* DSP1AUX4MIX_SRC1 - [6:0] */
+
+/*
+ * R1668 (0x684) - DSP1AUX5MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX5MIX_SRC1_MASK 0x007F /* DSP1AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX5MIX_SRC1_SHIFT 0 /* DSP1AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX5MIX_SRC1_WIDTH 7 /* DSP1AUX5MIX_SRC1 - [6:0] */
+
+/*
+ * R1669 (0x685) - DSP1AUX6MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX6MIX_SRC1_MASK 0x007F /* DSP1AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX6MIX_SRC1_SHIFT 0 /* DSP1AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX6MIX_SRC1_WIDTH 7 /* DSP1AUX6MIX_SRC1 - [6:0] */
+
+/*
+ * R1670 (0x686) - DSP2LMIX Input 1 Source
+ */
+#define WM2200_DSP2LMIX_SRC1_MASK 0x007F /* DSP2LMIX_SRC1 - [6:0] */
+#define WM2200_DSP2LMIX_SRC1_SHIFT 0 /* DSP2LMIX_SRC1 - [6:0] */
+#define WM2200_DSP2LMIX_SRC1_WIDTH 7 /* DSP2LMIX_SRC1 - [6:0] */
+
+/*
+ * R1671 (0x687) - DSP2LMIX Input 1 Volume
+ */
+#define WM2200_DSP2LMIX_VOL1_MASK 0x00FE /* DSP2LMIX_VOL1 - [7:1] */
+#define WM2200_DSP2LMIX_VOL1_SHIFT 1 /* DSP2LMIX_VOL1 - [7:1] */
+#define WM2200_DSP2LMIX_VOL1_WIDTH 7 /* DSP2LMIX_VOL1 - [7:1] */
+
+/*
+ * R1672 (0x688) - DSP2LMIX Input 2 Source
+ */
+#define WM2200_DSP2LMIX_SRC2_MASK 0x007F /* DSP2LMIX_SRC2 - [6:0] */
+#define WM2200_DSP2LMIX_SRC2_SHIFT 0 /* DSP2LMIX_SRC2 - [6:0] */
+#define WM2200_DSP2LMIX_SRC2_WIDTH 7 /* DSP2LMIX_SRC2 - [6:0] */
+
+/*
+ * R1673 (0x689) - DSP2LMIX Input 2 Volume
+ */
+#define WM2200_DSP2LMIX_VOL2_MASK 0x00FE /* DSP2LMIX_VOL2 - [7:1] */
+#define WM2200_DSP2LMIX_VOL2_SHIFT 1 /* DSP2LMIX_VOL2 - [7:1] */
+#define WM2200_DSP2LMIX_VOL2_WIDTH 7 /* DSP2LMIX_VOL2 - [7:1] */
+
+/*
+ * R1674 (0x68A) - DSP2LMIX Input 3 Source
+ */
+#define WM2200_DSP2LMIX_SRC3_MASK 0x007F /* DSP2LMIX_SRC3 - [6:0] */
+#define WM2200_DSP2LMIX_SRC3_SHIFT 0 /* DSP2LMIX_SRC3 - [6:0] */
+#define WM2200_DSP2LMIX_SRC3_WIDTH 7 /* DSP2LMIX_SRC3 - [6:0] */
+
+/*
+ * R1675 (0x68B) - DSP2LMIX Input 3 Volume
+ */
+#define WM2200_DSP2LMIX_VOL3_MASK 0x00FE /* DSP2LMIX_VOL3 - [7:1] */
+#define WM2200_DSP2LMIX_VOL3_SHIFT 1 /* DSP2LMIX_VOL3 - [7:1] */
+#define WM2200_DSP2LMIX_VOL3_WIDTH 7 /* DSP2LMIX_VOL3 - [7:1] */
+
+/*
+ * R1676 (0x68C) - DSP2LMIX Input 4 Source
+ */
+#define WM2200_DSP2LMIX_SRC4_MASK 0x007F /* DSP2LMIX_SRC4 - [6:0] */
+#define WM2200_DSP2LMIX_SRC4_SHIFT 0 /* DSP2LMIX_SRC4 - [6:0] */
+#define WM2200_DSP2LMIX_SRC4_WIDTH 7 /* DSP2LMIX_SRC4 - [6:0] */
+
+/*
+ * R1677 (0x68D) - DSP2LMIX Input 4 Volume
+ */
+#define WM2200_DSP2LMIX_VOL4_MASK 0x00FE /* DSP2LMIX_VOL4 - [7:1] */
+#define WM2200_DSP2LMIX_VOL4_SHIFT 1 /* DSP2LMIX_VOL4 - [7:1] */
+#define WM2200_DSP2LMIX_VOL4_WIDTH 7 /* DSP2LMIX_VOL4 - [7:1] */
+
+/*
+ * R1678 (0x68E) - DSP2RMIX Input 1 Source
+ */
+#define WM2200_DSP2RMIX_SRC1_MASK 0x007F /* DSP2RMIX_SRC1 - [6:0] */
+#define WM2200_DSP2RMIX_SRC1_SHIFT 0 /* DSP2RMIX_SRC1 - [6:0] */
+#define WM2200_DSP2RMIX_SRC1_WIDTH 7 /* DSP2RMIX_SRC1 - [6:0] */
+
+/*
+ * R1679 (0x68F) - DSP2RMIX Input 1 Volume
+ */
+#define WM2200_DSP2RMIX_VOL1_MASK 0x00FE /* DSP2RMIX_VOL1 - [7:1] */
+#define WM2200_DSP2RMIX_VOL1_SHIFT 1 /* DSP2RMIX_VOL1 - [7:1] */
+#define WM2200_DSP2RMIX_VOL1_WIDTH 7 /* DSP2RMIX_VOL1 - [7:1] */
+
+/*
+ * R1680 (0x690) - DSP2RMIX Input 2 Source
+ */
+#define WM2200_DSP2RMIX_SRC2_MASK 0x007F /* DSP2RMIX_SRC2 - [6:0] */
+#define WM2200_DSP2RMIX_SRC2_SHIFT 0 /* DSP2RMIX_SRC2 - [6:0] */
+#define WM2200_DSP2RMIX_SRC2_WIDTH 7 /* DSP2RMIX_SRC2 - [6:0] */
+
+/*
+ * R1681 (0x691) - DSP2RMIX Input 2 Volume
+ */
+#define WM2200_DSP2RMIX_VOL2_MASK 0x00FE /* DSP2RMIX_VOL2 - [7:1] */
+#define WM2200_DSP2RMIX_VOL2_SHIFT 1 /* DSP2RMIX_VOL2 - [7:1] */
+#define WM2200_DSP2RMIX_VOL2_WIDTH 7 /* DSP2RMIX_VOL2 - [7:1] */
+
+/*
+ * R1682 (0x692) - DSP2RMIX Input 3 Source
+ */
+#define WM2200_DSP2RMIX_SRC3_MASK 0x007F /* DSP2RMIX_SRC3 - [6:0] */
+#define WM2200_DSP2RMIX_SRC3_SHIFT 0 /* DSP2RMIX_SRC3 - [6:0] */
+#define WM2200_DSP2RMIX_SRC3_WIDTH 7 /* DSP2RMIX_SRC3 - [6:0] */
+
+/*
+ * R1683 (0x693) - DSP2RMIX Input 3 Volume
+ */
+#define WM2200_DSP2RMIX_VOL3_MASK 0x00FE /* DSP2RMIX_VOL3 - [7:1] */
+#define WM2200_DSP2RMIX_VOL3_SHIFT 1 /* DSP2RMIX_VOL3 - [7:1] */
+#define WM2200_DSP2RMIX_VOL3_WIDTH 7 /* DSP2RMIX_VOL3 - [7:1] */
+
+/*
+ * R1684 (0x694) - DSP2RMIX Input 4 Source
+ */
+#define WM2200_DSP2RMIX_SRC4_MASK 0x007F /* DSP2RMIX_SRC4 - [6:0] */
+#define WM2200_DSP2RMIX_SRC4_SHIFT 0 /* DSP2RMIX_SRC4 - [6:0] */
+#define WM2200_DSP2RMIX_SRC4_WIDTH 7 /* DSP2RMIX_SRC4 - [6:0] */
+
+/*
+ * R1685 (0x695) - DSP2RMIX Input 4 Volume
+ */
+#define WM2200_DSP2RMIX_VOL4_MASK 0x00FE /* DSP2RMIX_VOL4 - [7:1] */
+#define WM2200_DSP2RMIX_VOL4_SHIFT 1 /* DSP2RMIX_VOL4 - [7:1] */
+#define WM2200_DSP2RMIX_VOL4_WIDTH 7 /* DSP2RMIX_VOL4 - [7:1] */
+
+/*
+ * R1686 (0x696) - DSP2AUX1MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX1MIX_SRC1_MASK 0x007F /* DSP2AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX1MIX_SRC1_SHIFT 0 /* DSP2AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX1MIX_SRC1_WIDTH 7 /* DSP2AUX1MIX_SRC1 - [6:0] */
+
+/*
+ * R1687 (0x697) - DSP2AUX2MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX2MIX_SRC1_MASK 0x007F /* DSP2AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX2MIX_SRC1_SHIFT 0 /* DSP2AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX2MIX_SRC1_WIDTH 7 /* DSP2AUX2MIX_SRC1 - [6:0] */
+
+/*
+ * R1688 (0x698) - DSP2AUX3MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX3MIX_SRC1_MASK 0x007F /* DSP2AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX3MIX_SRC1_SHIFT 0 /* DSP2AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX3MIX_SRC1_WIDTH 7 /* DSP2AUX3MIX_SRC1 - [6:0] */
+
+/*
+ * R1689 (0x699) - DSP2AUX4MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX4MIX_SRC1_MASK 0x007F /* DSP2AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX4MIX_SRC1_SHIFT 0 /* DSP2AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX4MIX_SRC1_WIDTH 7 /* DSP2AUX4MIX_SRC1 - [6:0] */
+
+/*
+ * R1690 (0x69A) - DSP2AUX5MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX5MIX_SRC1_MASK 0x007F /* DSP2AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX5MIX_SRC1_SHIFT 0 /* DSP2AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX5MIX_SRC1_WIDTH 7 /* DSP2AUX5MIX_SRC1 - [6:0] */
+
+/*
+ * R1691 (0x69B) - DSP2AUX6MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX6MIX_SRC1_MASK 0x007F /* DSP2AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX6MIX_SRC1_SHIFT 0 /* DSP2AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX6MIX_SRC1_WIDTH 7 /* DSP2AUX6MIX_SRC1 - [6:0] */
+
+/*
+ * R1792 (0x700) - GPIO CTRL 1
+ */
+#define WM2200_GP1_DIR 0x8000 /* GP1_DIR */
+#define WM2200_GP1_DIR_MASK 0x8000 /* GP1_DIR */
+#define WM2200_GP1_DIR_SHIFT 15 /* GP1_DIR */
+#define WM2200_GP1_DIR_WIDTH 1 /* GP1_DIR */
+#define WM2200_GP1_PU 0x4000 /* GP1_PU */
+#define WM2200_GP1_PU_MASK 0x4000 /* GP1_PU */
+#define WM2200_GP1_PU_SHIFT 14 /* GP1_PU */
+#define WM2200_GP1_PU_WIDTH 1 /* GP1_PU */
+#define WM2200_GP1_PD 0x2000 /* GP1_PD */
+#define WM2200_GP1_PD_MASK 0x2000 /* GP1_PD */
+#define WM2200_GP1_PD_SHIFT 13 /* GP1_PD */
+#define WM2200_GP1_PD_WIDTH 1 /* GP1_PD */
+#define WM2200_GP1_POL 0x0400 /* GP1_POL */
+#define WM2200_GP1_POL_MASK 0x0400 /* GP1_POL */
+#define WM2200_GP1_POL_SHIFT 10 /* GP1_POL */
+#define WM2200_GP1_POL_WIDTH 1 /* GP1_POL */
+#define WM2200_GP1_OP_CFG 0x0200 /* GP1_OP_CFG */
+#define WM2200_GP1_OP_CFG_MASK 0x0200 /* GP1_OP_CFG */
+#define WM2200_GP1_OP_CFG_SHIFT 9 /* GP1_OP_CFG */
+#define WM2200_GP1_OP_CFG_WIDTH 1 /* GP1_OP_CFG */
+#define WM2200_GP1_DB 0x0100 /* GP1_DB */
+#define WM2200_GP1_DB_MASK 0x0100 /* GP1_DB */
+#define WM2200_GP1_DB_SHIFT 8 /* GP1_DB */
+#define WM2200_GP1_DB_WIDTH 1 /* GP1_DB */
+#define WM2200_GP1_LVL 0x0040 /* GP1_LVL */
+#define WM2200_GP1_LVL_MASK 0x0040 /* GP1_LVL */
+#define WM2200_GP1_LVL_SHIFT 6 /* GP1_LVL */
+#define WM2200_GP1_LVL_WIDTH 1 /* GP1_LVL */
+#define WM2200_GP1_FN_MASK 0x003F /* GP1_FN - [5:0] */
+#define WM2200_GP1_FN_SHIFT 0 /* GP1_FN - [5:0] */
+#define WM2200_GP1_FN_WIDTH 6 /* GP1_FN - [5:0] */
+
+/*
+ * R1793 (0x701) - GPIO CTRL 2
+ */
+#define WM2200_GP2_DIR 0x8000 /* GP2_DIR */
+#define WM2200_GP2_DIR_MASK 0x8000 /* GP2_DIR */
+#define WM2200_GP2_DIR_SHIFT 15 /* GP2_DIR */
+#define WM2200_GP2_DIR_WIDTH 1 /* GP2_DIR */
+#define WM2200_GP2_PU 0x4000 /* GP2_PU */
+#define WM2200_GP2_PU_MASK 0x4000 /* GP2_PU */
+#define WM2200_GP2_PU_SHIFT 14 /* GP2_PU */
+#define WM2200_GP2_PU_WIDTH 1 /* GP2_PU */
+#define WM2200_GP2_PD 0x2000 /* GP2_PD */
+#define WM2200_GP2_PD_MASK 0x2000 /* GP2_PD */
+#define WM2200_GP2_PD_SHIFT 13 /* GP2_PD */
+#define WM2200_GP2_PD_WIDTH 1 /* GP2_PD */
+#define WM2200_GP2_POL 0x0400 /* GP2_POL */
+#define WM2200_GP2_POL_MASK 0x0400 /* GP2_POL */
+#define WM2200_GP2_POL_SHIFT 10 /* GP2_POL */
+#define WM2200_GP2_POL_WIDTH 1 /* GP2_POL */
+#define WM2200_GP2_OP_CFG 0x0200 /* GP2_OP_CFG */
+#define WM2200_GP2_OP_CFG_MASK 0x0200 /* GP2_OP_CFG */
+#define WM2200_GP2_OP_CFG_SHIFT 9 /* GP2_OP_CFG */
+#define WM2200_GP2_OP_CFG_WIDTH 1 /* GP2_OP_CFG */
+#define WM2200_GP2_DB 0x0100 /* GP2_DB */
+#define WM2200_GP2_DB_MASK 0x0100 /* GP2_DB */
+#define WM2200_GP2_DB_SHIFT 8 /* GP2_DB */
+#define WM2200_GP2_DB_WIDTH 1 /* GP2_DB */
+#define WM2200_GP2_LVL 0x0040 /* GP2_LVL */
+#define WM2200_GP2_LVL_MASK 0x0040 /* GP2_LVL */
+#define WM2200_GP2_LVL_SHIFT 6 /* GP2_LVL */
+#define WM2200_GP2_LVL_WIDTH 1 /* GP2_LVL */
+#define WM2200_GP2_FN_MASK 0x003F /* GP2_FN - [5:0] */
+#define WM2200_GP2_FN_SHIFT 0 /* GP2_FN - [5:0] */
+#define WM2200_GP2_FN_WIDTH 6 /* GP2_FN - [5:0] */
+
+/*
+ * R1794 (0x702) - GPIO CTRL 3
+ */
+#define WM2200_GP3_DIR 0x8000 /* GP3_DIR */
+#define WM2200_GP3_DIR_MASK 0x8000 /* GP3_DIR */
+#define WM2200_GP3_DIR_SHIFT 15 /* GP3_DIR */
+#define WM2200_GP3_DIR_WIDTH 1 /* GP3_DIR */
+#define WM2200_GP3_PU 0x4000 /* GP3_PU */
+#define WM2200_GP3_PU_MASK 0x4000 /* GP3_PU */
+#define WM2200_GP3_PU_SHIFT 14 /* GP3_PU */
+#define WM2200_GP3_PU_WIDTH 1 /* GP3_PU */
+#define WM2200_GP3_PD 0x2000 /* GP3_PD */
+#define WM2200_GP3_PD_MASK 0x2000 /* GP3_PD */
+#define WM2200_GP3_PD_SHIFT 13 /* GP3_PD */
+#define WM2200_GP3_PD_WIDTH 1 /* GP3_PD */
+#define WM2200_GP3_POL 0x0400 /* GP3_POL */
+#define WM2200_GP3_POL_MASK 0x0400 /* GP3_POL */
+#define WM2200_GP3_POL_SHIFT 10 /* GP3_POL */
+#define WM2200_GP3_POL_WIDTH 1 /* GP3_POL */
+#define WM2200_GP3_OP_CFG 0x0200 /* GP3_OP_CFG */
+#define WM2200_GP3_OP_CFG_MASK 0x0200 /* GP3_OP_CFG */
+#define WM2200_GP3_OP_CFG_SHIFT 9 /* GP3_OP_CFG */
+#define WM2200_GP3_OP_CFG_WIDTH 1 /* GP3_OP_CFG */
+#define WM2200_GP3_DB 0x0100 /* GP3_DB */
+#define WM2200_GP3_DB_MASK 0x0100 /* GP3_DB */
+#define WM2200_GP3_DB_SHIFT 8 /* GP3_DB */
+#define WM2200_GP3_DB_WIDTH 1 /* GP3_DB */
+#define WM2200_GP3_LVL 0x0040 /* GP3_LVL */
+#define WM2200_GP3_LVL_MASK 0x0040 /* GP3_LVL */
+#define WM2200_GP3_LVL_SHIFT 6 /* GP3_LVL */
+#define WM2200_GP3_LVL_WIDTH 1 /* GP3_LVL */
+#define WM2200_GP3_FN_MASK 0x003F /* GP3_FN - [5:0] */
+#define WM2200_GP3_FN_SHIFT 0 /* GP3_FN - [5:0] */
+#define WM2200_GP3_FN_WIDTH 6 /* GP3_FN - [5:0] */
+
+/*
+ * R1795 (0x703) - GPIO CTRL 4
+ */
+#define WM2200_GP4_DIR 0x8000 /* GP4_DIR */
+#define WM2200_GP4_DIR_MASK 0x8000 /* GP4_DIR */
+#define WM2200_GP4_DIR_SHIFT 15 /* GP4_DIR */
+#define WM2200_GP4_DIR_WIDTH 1 /* GP4_DIR */
+#define WM2200_GP4_PU 0x4000 /* GP4_PU */
+#define WM2200_GP4_PU_MASK 0x4000 /* GP4_PU */
+#define WM2200_GP4_PU_SHIFT 14 /* GP4_PU */
+#define WM2200_GP4_PU_WIDTH 1 /* GP4_PU */
+#define WM2200_GP4_PD 0x2000 /* GP4_PD */
+#define WM2200_GP4_PD_MASK 0x2000 /* GP4_PD */
+#define WM2200_GP4_PD_SHIFT 13 /* GP4_PD */
+#define WM2200_GP4_PD_WIDTH 1 /* GP4_PD */
+#define WM2200_GP4_POL 0x0400 /* GP4_POL */
+#define WM2200_GP4_POL_MASK 0x0400 /* GP4_POL */
+#define WM2200_GP4_POL_SHIFT 10 /* GP4_POL */
+#define WM2200_GP4_POL_WIDTH 1 /* GP4_POL */
+#define WM2200_GP4_OP_CFG 0x0200 /* GP4_OP_CFG */
+#define WM2200_GP4_OP_CFG_MASK 0x0200 /* GP4_OP_CFG */
+#define WM2200_GP4_OP_CFG_SHIFT 9 /* GP4_OP_CFG */
+#define WM2200_GP4_OP_CFG_WIDTH 1 /* GP4_OP_CFG */
+#define WM2200_GP4_DB 0x0100 /* GP4_DB */
+#define WM2200_GP4_DB_MASK 0x0100 /* GP4_DB */
+#define WM2200_GP4_DB_SHIFT 8 /* GP4_DB */
+#define WM2200_GP4_DB_WIDTH 1 /* GP4_DB */
+#define WM2200_GP4_LVL 0x0040 /* GP4_LVL */
+#define WM2200_GP4_LVL_MASK 0x0040 /* GP4_LVL */
+#define WM2200_GP4_LVL_SHIFT 6 /* GP4_LVL */
+#define WM2200_GP4_LVL_WIDTH 1 /* GP4_LVL */
+#define WM2200_GP4_FN_MASK 0x003F /* GP4_FN - [5:0] */
+#define WM2200_GP4_FN_SHIFT 0 /* GP4_FN - [5:0] */
+#define WM2200_GP4_FN_WIDTH 6 /* GP4_FN - [5:0] */
+
+/*
+ * R1799 (0x707) - ADPS1 IRQ0
+ */
+#define WM2200_DSP_IRQ1 0x0002 /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ1_MASK 0x0002 /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ1_SHIFT 1 /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ1_WIDTH 1 /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ0 0x0001 /* DSP_IRQ0 */
+#define WM2200_DSP_IRQ0_MASK 0x0001 /* DSP_IRQ0 */
+#define WM2200_DSP_IRQ0_SHIFT 0 /* DSP_IRQ0 */
+#define WM2200_DSP_IRQ0_WIDTH 1 /* DSP_IRQ0 */
+
+/*
+ * R1800 (0x708) - ADPS1 IRQ1
+ */
+#define WM2200_DSP_IRQ3 0x0002 /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ3_MASK 0x0002 /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ3_SHIFT 1 /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ3_WIDTH 1 /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ2 0x0001 /* DSP_IRQ2 */
+#define WM2200_DSP_IRQ2_MASK 0x0001 /* DSP_IRQ2 */
+#define WM2200_DSP_IRQ2_SHIFT 0 /* DSP_IRQ2 */
+#define WM2200_DSP_IRQ2_WIDTH 1 /* DSP_IRQ2 */
+
+/*
+ * R1801 (0x709) - Misc Pad Ctrl 1
+ */
+#define WM2200_LDO1ENA_PD 0x8000 /* LDO1ENA_PD */
+#define WM2200_LDO1ENA_PD_MASK 0x8000 /* LDO1ENA_PD */
+#define WM2200_LDO1ENA_PD_SHIFT 15 /* LDO1ENA_PD */
+#define WM2200_LDO1ENA_PD_WIDTH 1 /* LDO1ENA_PD */
+#define WM2200_MCLK2_PD 0x2000 /* MCLK2_PD */
+#define WM2200_MCLK2_PD_MASK 0x2000 /* MCLK2_PD */
+#define WM2200_MCLK2_PD_SHIFT 13 /* MCLK2_PD */
+#define WM2200_MCLK2_PD_WIDTH 1 /* MCLK2_PD */
+#define WM2200_MCLK1_PD 0x1000 /* MCLK1_PD */
+#define WM2200_MCLK1_PD_MASK 0x1000 /* MCLK1_PD */
+#define WM2200_MCLK1_PD_SHIFT 12 /* MCLK1_PD */
+#define WM2200_MCLK1_PD_WIDTH 1 /* MCLK1_PD */
+#define WM2200_DACLRCLK1_PU 0x0400 /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PU_MASK 0x0400 /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PU_SHIFT 10 /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PU_WIDTH 1 /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PD 0x0200 /* DACLRCLK1_PD */
+#define WM2200_DACLRCLK1_PD_MASK 0x0200 /* DACLRCLK1_PD */
+#define WM2200_DACLRCLK1_PD_SHIFT 9 /* DACLRCLK1_PD */
+#define WM2200_DACLRCLK1_PD_WIDTH 1 /* DACLRCLK1_PD */
+#define WM2200_BCLK1_PU 0x0100 /* BCLK1_PU */
+#define WM2200_BCLK1_PU_MASK 0x0100 /* BCLK1_PU */
+#define WM2200_BCLK1_PU_SHIFT 8 /* BCLK1_PU */
+#define WM2200_BCLK1_PU_WIDTH 1 /* BCLK1_PU */
+#define WM2200_BCLK1_PD 0x0080 /* BCLK1_PD */
+#define WM2200_BCLK1_PD_MASK 0x0080 /* BCLK1_PD */
+#define WM2200_BCLK1_PD_SHIFT 7 /* BCLK1_PD */
+#define WM2200_BCLK1_PD_WIDTH 1 /* BCLK1_PD */
+#define WM2200_DACDAT1_PU 0x0040 /* DACDAT1_PU */
+#define WM2200_DACDAT1_PU_MASK 0x0040 /* DACDAT1_PU */
+#define WM2200_DACDAT1_PU_SHIFT 6 /* DACDAT1_PU */
+#define WM2200_DACDAT1_PU_WIDTH 1 /* DACDAT1_PU */
+#define WM2200_DACDAT1_PD 0x0020 /* DACDAT1_PD */
+#define WM2200_DACDAT1_PD_MASK 0x0020 /* DACDAT1_PD */
+#define WM2200_DACDAT1_PD_SHIFT 5 /* DACDAT1_PD */
+#define WM2200_DACDAT1_PD_WIDTH 1 /* DACDAT1_PD */
+#define WM2200_DMICDAT3_PD 0x0010 /* DMICDAT3_PD */
+#define WM2200_DMICDAT3_PD_MASK 0x0010 /* DMICDAT3_PD */
+#define WM2200_DMICDAT3_PD_SHIFT 4 /* DMICDAT3_PD */
+#define WM2200_DMICDAT3_PD_WIDTH 1 /* DMICDAT3_PD */
+#define WM2200_DMICDAT2_PD 0x0008 /* DMICDAT2_PD */
+#define WM2200_DMICDAT2_PD_MASK 0x0008 /* DMICDAT2_PD */
+#define WM2200_DMICDAT2_PD_SHIFT 3 /* DMICDAT2_PD */
+#define WM2200_DMICDAT2_PD_WIDTH 1 /* DMICDAT2_PD */
+#define WM2200_DMICDAT1_PD 0x0004 /* DMICDAT1_PD */
+#define WM2200_DMICDAT1_PD_MASK 0x0004 /* DMICDAT1_PD */
+#define WM2200_DMICDAT1_PD_SHIFT 2 /* DMICDAT1_PD */
+#define WM2200_DMICDAT1_PD_WIDTH 1 /* DMICDAT1_PD */
+#define WM2200_RSTB_PU 0x0002 /* RSTB_PU */
+#define WM2200_RSTB_PU_MASK 0x0002 /* RSTB_PU */
+#define WM2200_RSTB_PU_SHIFT 1 /* RSTB_PU */
+#define WM2200_RSTB_PU_WIDTH 1 /* RSTB_PU */
+#define WM2200_ADDR_PD 0x0001 /* ADDR_PD */
+#define WM2200_ADDR_PD_MASK 0x0001 /* ADDR_PD */
+#define WM2200_ADDR_PD_SHIFT 0 /* ADDR_PD */
+#define WM2200_ADDR_PD_WIDTH 1 /* ADDR_PD */
+
+/*
+ * R2048 (0x800) - Interrupt Status 1
+ */
+#define WM2200_DSP_IRQ0_EINT 0x0080 /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ0_EINT_MASK 0x0080 /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ0_EINT_SHIFT 7 /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ0_EINT_WIDTH 1 /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ1_EINT 0x0040 /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ1_EINT_MASK 0x0040 /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ1_EINT_SHIFT 6 /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ1_EINT_WIDTH 1 /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ2_EINT 0x0020 /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ2_EINT_MASK 0x0020 /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ2_EINT_SHIFT 5 /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ2_EINT_WIDTH 1 /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ3_EINT 0x0010 /* DSP_IRQ3_EINT */
+#define WM2200_DSP_IRQ3_EINT_MASK 0x0010 /* DSP_IRQ3_EINT */
+#define WM2200_DSP_IRQ3_EINT_SHIFT 4 /* DSP_IRQ3_EINT */
+#define WM2200_DSP_IRQ3_EINT_WIDTH 1 /* DSP_IRQ3_EINT */
+#define WM2200_GP4_EINT 0x0008 /* GP4_EINT */
+#define WM2200_GP4_EINT_MASK 0x0008 /* GP4_EINT */
+#define WM2200_GP4_EINT_SHIFT 3 /* GP4_EINT */
+#define WM2200_GP4_EINT_WIDTH 1 /* GP4_EINT */
+#define WM2200_GP3_EINT 0x0004 /* GP3_EINT */
+#define WM2200_GP3_EINT_MASK 0x0004 /* GP3_EINT */
+#define WM2200_GP3_EINT_SHIFT 2 /* GP3_EINT */
+#define WM2200_GP3_EINT_WIDTH 1 /* GP3_EINT */
+#define WM2200_GP2_EINT 0x0002 /* GP2_EINT */
+#define WM2200_GP2_EINT_MASK 0x0002 /* GP2_EINT */
+#define WM2200_GP2_EINT_SHIFT 1 /* GP2_EINT */
+#define WM2200_GP2_EINT_WIDTH 1 /* GP2_EINT */
+#define WM2200_GP1_EINT 0x0001 /* GP1_EINT */
+#define WM2200_GP1_EINT_MASK 0x0001 /* GP1_EINT */
+#define WM2200_GP1_EINT_SHIFT 0 /* GP1_EINT */
+#define WM2200_GP1_EINT_WIDTH 1 /* GP1_EINT */
+
+/*
+ * R2049 (0x801) - Interrupt Status 1 Mask
+ */
+#define WM2200_IM_DSP_IRQ0_EINT 0x0080 /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ0_EINT_MASK 0x0080 /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ0_EINT_SHIFT 7 /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ0_EINT_WIDTH 1 /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT 0x0040 /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT_MASK 0x0040 /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT_SHIFT 6 /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT_WIDTH 1 /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT 0x0020 /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT_MASK 0x0020 /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT_SHIFT 5 /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT_WIDTH 1 /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT 0x0010 /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT_MASK 0x0010 /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT_SHIFT 4 /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT_WIDTH 1 /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_GP4_EINT 0x0008 /* IM_GP4_EINT */
+#define WM2200_IM_GP4_EINT_MASK 0x0008 /* IM_GP4_EINT */
+#define WM2200_IM_GP4_EINT_SHIFT 3 /* IM_GP4_EINT */
+#define WM2200_IM_GP4_EINT_WIDTH 1 /* IM_GP4_EINT */
+#define WM2200_IM_GP3_EINT 0x0004 /* IM_GP3_EINT */
+#define WM2200_IM_GP3_EINT_MASK 0x0004 /* IM_GP3_EINT */
+#define WM2200_IM_GP3_EINT_SHIFT 2 /* IM_GP3_EINT */
+#define WM2200_IM_GP3_EINT_WIDTH 1 /* IM_GP3_EINT */
+#define WM2200_IM_GP2_EINT 0x0002 /* IM_GP2_EINT */
+#define WM2200_IM_GP2_EINT_MASK 0x0002 /* IM_GP2_EINT */
+#define WM2200_IM_GP2_EINT_SHIFT 1 /* IM_GP2_EINT */
+#define WM2200_IM_GP2_EINT_WIDTH 1 /* IM_GP2_EINT */
+#define WM2200_IM_GP1_EINT 0x0001 /* IM_GP1_EINT */
+#define WM2200_IM_GP1_EINT_MASK 0x0001 /* IM_GP1_EINT */
+#define WM2200_IM_GP1_EINT_SHIFT 0 /* IM_GP1_EINT */
+#define WM2200_IM_GP1_EINT_WIDTH 1 /* IM_GP1_EINT */
+
+/*
+ * R2050 (0x802) - Interrupt Status 2
+ */
+#define WM2200_WSEQ_BUSY_EINT 0x0100 /* WSEQ_BUSY_EINT */
+#define WM2200_WSEQ_BUSY_EINT_MASK 0x0100 /* WSEQ_BUSY_EINT */
+#define WM2200_WSEQ_BUSY_EINT_SHIFT 8 /* WSEQ_BUSY_EINT */
+#define WM2200_WSEQ_BUSY_EINT_WIDTH 1 /* WSEQ_BUSY_EINT */
+#define WM2200_FLL_LOCK_EINT 0x0002 /* FLL_LOCK_EINT */
+#define WM2200_FLL_LOCK_EINT_MASK 0x0002 /* FLL_LOCK_EINT */
+#define WM2200_FLL_LOCK_EINT_SHIFT 1 /* FLL_LOCK_EINT */
+#define WM2200_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */
+#define WM2200_CLKGEN_EINT 0x0001 /* CLKGEN_EINT */
+#define WM2200_CLKGEN_EINT_MASK 0x0001 /* CLKGEN_EINT */
+#define WM2200_CLKGEN_EINT_SHIFT 0 /* CLKGEN_EINT */
+#define WM2200_CLKGEN_EINT_WIDTH 1 /* CLKGEN_EINT */
+
+/*
+ * R2051 (0x803) - Interrupt Raw Status 2
+ */
+#define WM2200_WSEQ_BUSY_STS 0x0100 /* WSEQ_BUSY_STS */
+#define WM2200_WSEQ_BUSY_STS_MASK 0x0100 /* WSEQ_BUSY_STS */
+#define WM2200_WSEQ_BUSY_STS_SHIFT 8 /* WSEQ_BUSY_STS */
+#define WM2200_WSEQ_BUSY_STS_WIDTH 1 /* WSEQ_BUSY_STS */
+#define WM2200_FLL_LOCK_STS 0x0002 /* FLL_LOCK_STS */
+#define WM2200_FLL_LOCK_STS_MASK 0x0002 /* FLL_LOCK_STS */
+#define WM2200_FLL_LOCK_STS_SHIFT 1 /* FLL_LOCK_STS */
+#define WM2200_FLL_LOCK_STS_WIDTH 1 /* FLL_LOCK_STS */
+#define WM2200_CLKGEN_STS 0x0001 /* CLKGEN_STS */
+#define WM2200_CLKGEN_STS_MASK 0x0001 /* CLKGEN_STS */
+#define WM2200_CLKGEN_STS_SHIFT 0 /* CLKGEN_STS */
+#define WM2200_CLKGEN_STS_WIDTH 1 /* CLKGEN_STS */
+
+/*
+ * R2052 (0x804) - Interrupt Status 2 Mask
+ */
+#define WM2200_IM_WSEQ_BUSY_EINT 0x0100 /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_WSEQ_BUSY_EINT_MASK 0x0100 /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_WSEQ_BUSY_EINT_SHIFT 8 /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_WSEQ_BUSY_EINT_WIDTH 1 /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_FLL_LOCK_EINT 0x0002 /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_FLL_LOCK_EINT_MASK 0x0002 /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_FLL_LOCK_EINT_SHIFT 1 /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_CLKGEN_EINT 0x0001 /* IM_CLKGEN_EINT */
+#define WM2200_IM_CLKGEN_EINT_MASK 0x0001 /* IM_CLKGEN_EINT */
+#define WM2200_IM_CLKGEN_EINT_SHIFT 0 /* IM_CLKGEN_EINT */
+#define WM2200_IM_CLKGEN_EINT_WIDTH 1 /* IM_CLKGEN_EINT */
+
+/*
+ * R2056 (0x808) - Interrupt Control
+ */
+#define WM2200_IM_IRQ 0x0001 /* IM_IRQ */
+#define WM2200_IM_IRQ_MASK 0x0001 /* IM_IRQ */
+#define WM2200_IM_IRQ_SHIFT 0 /* IM_IRQ */
+#define WM2200_IM_IRQ_WIDTH 1 /* IM_IRQ */
+
+/*
+ * R2304 (0x900) - EQL_1
+ */
+#define WM2200_EQL_B1_GAIN_MASK 0xF800 /* EQL_B1_GAIN - [15:11] */
+#define WM2200_EQL_B1_GAIN_SHIFT 11 /* EQL_B1_GAIN - [15:11] */
+#define WM2200_EQL_B1_GAIN_WIDTH 5 /* EQL_B1_GAIN - [15:11] */
+#define WM2200_EQL_B2_GAIN_MASK 0x07C0 /* EQL_B2_GAIN - [10:6] */
+#define WM2200_EQL_B2_GAIN_SHIFT 6 /* EQL_B2_GAIN - [10:6] */
+#define WM2200_EQL_B2_GAIN_WIDTH 5 /* EQL_B2_GAIN - [10:6] */
+#define WM2200_EQL_B3_GAIN_MASK 0x003E /* EQL_B3_GAIN - [5:1] */
+#define WM2200_EQL_B3_GAIN_SHIFT 1 /* EQL_B3_GAIN - [5:1] */
+#define WM2200_EQL_B3_GAIN_WIDTH 5 /* EQL_B3_GAIN - [5:1] */
+#define WM2200_EQL_ENA 0x0001 /* EQL_ENA */
+#define WM2200_EQL_ENA_MASK 0x0001 /* EQL_ENA */
+#define WM2200_EQL_ENA_SHIFT 0 /* EQL_ENA */
+#define WM2200_EQL_ENA_WIDTH 1 /* EQL_ENA */
+
+/*
+ * R2305 (0x901) - EQL_2
+ */
+#define WM2200_EQL_B4_GAIN_MASK 0xF800 /* EQL_B4_GAIN - [15:11] */
+#define WM2200_EQL_B4_GAIN_SHIFT 11 /* EQL_B4_GAIN - [15:11] */
+#define WM2200_EQL_B4_GAIN_WIDTH 5 /* EQL_B4_GAIN - [15:11] */
+#define WM2200_EQL_B5_GAIN_MASK 0x07C0 /* EQL_B5_GAIN - [10:6] */
+#define WM2200_EQL_B5_GAIN_SHIFT 6 /* EQL_B5_GAIN - [10:6] */
+#define WM2200_EQL_B5_GAIN_WIDTH 5 /* EQL_B5_GAIN - [10:6] */
+
+/*
+ * R2306 (0x902) - EQL_3
+ */
+#define WM2200_EQL_B1_A_MASK 0xFFFF /* EQL_B1_A - [15:0] */
+#define WM2200_EQL_B1_A_SHIFT 0 /* EQL_B1_A - [15:0] */
+#define WM2200_EQL_B1_A_WIDTH 16 /* EQL_B1_A - [15:0] */
+
+/*
+ * R2307 (0x903) - EQL_4
+ */
+#define WM2200_EQL_B1_B_MASK 0xFFFF /* EQL_B1_B - [15:0] */
+#define WM2200_EQL_B1_B_SHIFT 0 /* EQL_B1_B - [15:0] */
+#define WM2200_EQL_B1_B_WIDTH 16 /* EQL_B1_B - [15:0] */
+
+/*
+ * R2308 (0x904) - EQL_5
+ */
+#define WM2200_EQL_B1_PG_MASK 0xFFFF /* EQL_B1_PG - [15:0] */
+#define WM2200_EQL_B1_PG_SHIFT 0 /* EQL_B1_PG - [15:0] */
+#define WM2200_EQL_B1_PG_WIDTH 16 /* EQL_B1_PG - [15:0] */
+
+/*
+ * R2309 (0x905) - EQL_6
+ */
+#define WM2200_EQL_B2_A_MASK 0xFFFF /* EQL_B2_A - [15:0] */
+#define WM2200_EQL_B2_A_SHIFT 0 /* EQL_B2_A - [15:0] */
+#define WM2200_EQL_B2_A_WIDTH 16 /* EQL_B2_A - [15:0] */
+
+/*
+ * R2310 (0x906) - EQL_7
+ */
+#define WM2200_EQL_B2_B_MASK 0xFFFF /* EQL_B2_B - [15:0] */
+#define WM2200_EQL_B2_B_SHIFT 0 /* EQL_B2_B - [15:0] */
+#define WM2200_EQL_B2_B_WIDTH 16 /* EQL_B2_B - [15:0] */
+
+/*
+ * R2311 (0x907) - EQL_8
+ */
+#define WM2200_EQL_B2_C_MASK 0xFFFF /* EQL_B2_C - [15:0] */
+#define WM2200_EQL_B2_C_SHIFT 0 /* EQL_B2_C - [15:0] */
+#define WM2200_EQL_B2_C_WIDTH 16 /* EQL_B2_C - [15:0] */
+
+/*
+ * R2312 (0x908) - EQL_9
+ */
+#define WM2200_EQL_B2_PG_MASK 0xFFFF /* EQL_B2_PG - [15:0] */
+#define WM2200_EQL_B2_PG_SHIFT 0 /* EQL_B2_PG - [15:0] */
+#define WM2200_EQL_B2_PG_WIDTH 16 /* EQL_B2_PG - [15:0] */
+
+/*
+ * R2313 (0x909) - EQL_10
+ */
+#define WM2200_EQL_B3_A_MASK 0xFFFF /* EQL_B3_A - [15:0] */
+#define WM2200_EQL_B3_A_SHIFT 0 /* EQL_B3_A - [15:0] */
+#define WM2200_EQL_B3_A_WIDTH 16 /* EQL_B3_A - [15:0] */
+
+/*
+ * R2314 (0x90A) - EQL_11
+ */
+#define WM2200_EQL_B3_B_MASK 0xFFFF /* EQL_B3_B - [15:0] */
+#define WM2200_EQL_B3_B_SHIFT 0 /* EQL_B3_B - [15:0] */
+#define WM2200_EQL_B3_B_WIDTH 16 /* EQL_B3_B - [15:0] */
+
+/*
+ * R2315 (0x90B) - EQL_12
+ */
+#define WM2200_EQL_B3_C_MASK 0xFFFF /* EQL_B3_C - [15:0] */
+#define WM2200_EQL_B3_C_SHIFT 0 /* EQL_B3_C - [15:0] */
+#define WM2200_EQL_B3_C_WIDTH 16 /* EQL_B3_C - [15:0] */
+
+/*
+ * R2316 (0x90C) - EQL_13
+ */
+#define WM2200_EQL_B3_PG_MASK 0xFFFF /* EQL_B3_PG - [15:0] */
+#define WM2200_EQL_B3_PG_SHIFT 0 /* EQL_B3_PG - [15:0] */
+#define WM2200_EQL_B3_PG_WIDTH 16 /* EQL_B3_PG - [15:0] */
+
+/*
+ * R2317 (0x90D) - EQL_14
+ */
+#define WM2200_EQL_B4_A_MASK 0xFFFF /* EQL_B4_A - [15:0] */
+#define WM2200_EQL_B4_A_SHIFT 0 /* EQL_B4_A - [15:0] */
+#define WM2200_EQL_B4_A_WIDTH 16 /* EQL_B4_A - [15:0] */
+
+/*
+ * R2318 (0x90E) - EQL_15
+ */
+#define WM2200_EQL_B4_B_MASK 0xFFFF /* EQL_B4_B - [15:0] */
+#define WM2200_EQL_B4_B_SHIFT 0 /* EQL_B4_B - [15:0] */
+#define WM2200_EQL_B4_B_WIDTH 16 /* EQL_B4_B - [15:0] */
+
+/*
+ * R2319 (0x90F) - EQL_16
+ */
+#define WM2200_EQL_B4_C_MASK 0xFFFF /* EQL_B4_C - [15:0] */
+#define WM2200_EQL_B4_C_SHIFT 0 /* EQL_B4_C - [15:0] */
+#define WM2200_EQL_B4_C_WIDTH 16 /* EQL_B4_C - [15:0] */
+
+/*
+ * R2320 (0x910) - EQL_17
+ */
+#define WM2200_EQL_B4_PG_MASK 0xFFFF /* EQL_B4_PG - [15:0] */
+#define WM2200_EQL_B4_PG_SHIFT 0 /* EQL_B4_PG - [15:0] */
+#define WM2200_EQL_B4_PG_WIDTH 16 /* EQL_B4_PG - [15:0] */
+
+/*
+ * R2321 (0x911) - EQL_18
+ */
+#define WM2200_EQL_B5_A_MASK 0xFFFF /* EQL_B5_A - [15:0] */
+#define WM2200_EQL_B5_A_SHIFT 0 /* EQL_B5_A - [15:0] */
+#define WM2200_EQL_B5_A_WIDTH 16 /* EQL_B5_A - [15:0] */
+
+/*
+ * R2322 (0x912) - EQL_19
+ */
+#define WM2200_EQL_B5_B_MASK 0xFFFF /* EQL_B5_B - [15:0] */
+#define WM2200_EQL_B5_B_SHIFT 0 /* EQL_B5_B - [15:0] */
+#define WM2200_EQL_B5_B_WIDTH 16 /* EQL_B5_B - [15:0] */
+
+/*
+ * R2323 (0x913) - EQL_20
+ */
+#define WM2200_EQL_B5_PG_MASK 0xFFFF /* EQL_B5_PG - [15:0] */
+#define WM2200_EQL_B5_PG_SHIFT 0 /* EQL_B5_PG - [15:0] */
+#define WM2200_EQL_B5_PG_WIDTH 16 /* EQL_B5_PG - [15:0] */
+
+/*
+ * R2326 (0x916) - EQR_1
+ */
+#define WM2200_EQR_B1_GAIN_MASK 0xF800 /* EQR_B1_GAIN - [15:11] */
+#define WM2200_EQR_B1_GAIN_SHIFT 11 /* EQR_B1_GAIN - [15:11] */
+#define WM2200_EQR_B1_GAIN_WIDTH 5 /* EQR_B1_GAIN - [15:11] */
+#define WM2200_EQR_B2_GAIN_MASK 0x07C0 /* EQR_B2_GAIN - [10:6] */
+#define WM2200_EQR_B2_GAIN_SHIFT 6 /* EQR_B2_GAIN - [10:6] */
+#define WM2200_EQR_B2_GAIN_WIDTH 5 /* EQR_B2_GAIN - [10:6] */
+#define WM2200_EQR_B3_GAIN_MASK 0x003E /* EQR_B3_GAIN - [5:1] */
+#define WM2200_EQR_B3_GAIN_SHIFT 1 /* EQR_B3_GAIN - [5:1] */
+#define WM2200_EQR_B3_GAIN_WIDTH 5 /* EQR_B3_GAIN - [5:1] */
+#define WM2200_EQR_ENA 0x0001 /* EQR_ENA */
+#define WM2200_EQR_ENA_MASK 0x0001 /* EQR_ENA */
+#define WM2200_EQR_ENA_SHIFT 0 /* EQR_ENA */
+#define WM2200_EQR_ENA_WIDTH 1 /* EQR_ENA */
+
+/*
+ * R2327 (0x917) - EQR_2
+ */
+#define WM2200_EQR_B4_GAIN_MASK 0xF800 /* EQR_B4_GAIN - [15:11] */
+#define WM2200_EQR_B4_GAIN_SHIFT 11 /* EQR_B4_GAIN - [15:11] */
+#define WM2200_EQR_B4_GAIN_WIDTH 5 /* EQR_B4_GAIN - [15:11] */
+#define WM2200_EQR_B5_GAIN_MASK 0x07C0 /* EQR_B5_GAIN - [10:6] */
+#define WM2200_EQR_B5_GAIN_SHIFT 6 /* EQR_B5_GAIN - [10:6] */
+#define WM2200_EQR_B5_GAIN_WIDTH 5 /* EQR_B5_GAIN - [10:6] */
+
+/*
+ * R2328 (0x918) - EQR_3
+ */
+#define WM2200_EQR_B1_A_MASK 0xFFFF /* EQR_B1_A - [15:0] */
+#define WM2200_EQR_B1_A_SHIFT 0 /* EQR_B1_A - [15:0] */
+#define WM2200_EQR_B1_A_WIDTH 16 /* EQR_B1_A - [15:0] */
+
+/*
+ * R2329 (0x919) - EQR_4
+ */
+#define WM2200_EQR_B1_B_MASK 0xFFFF /* EQR_B1_B - [15:0] */
+#define WM2200_EQR_B1_B_SHIFT 0 /* EQR_B1_B - [15:0] */
+#define WM2200_EQR_B1_B_WIDTH 16 /* EQR_B1_B - [15:0] */
+
+/*
+ * R2330 (0x91A) - EQR_5
+ */
+#define WM2200_EQR_B1_PG_MASK 0xFFFF /* EQR_B1_PG - [15:0] */
+#define WM2200_EQR_B1_PG_SHIFT 0 /* EQR_B1_PG - [15:0] */
+#define WM2200_EQR_B1_PG_WIDTH 16 /* EQR_B1_PG - [15:0] */
+
+/*
+ * R2331 (0x91B) - EQR_6
+ */
+#define WM2200_EQR_B2_A_MASK 0xFFFF /* EQR_B2_A - [15:0] */
+#define WM2200_EQR_B2_A_SHIFT 0 /* EQR_B2_A - [15:0] */
+#define WM2200_EQR_B2_A_WIDTH 16 /* EQR_B2_A - [15:0] */
+
+/*
+ * R2332 (0x91C) - EQR_7
+ */
+#define WM2200_EQR_B2_B_MASK 0xFFFF /* EQR_B2_B - [15:0] */
+#define WM2200_EQR_B2_B_SHIFT 0 /* EQR_B2_B - [15:0] */
+#define WM2200_EQR_B2_B_WIDTH 16 /* EQR_B2_B - [15:0] */
+
+/*
+ * R2333 (0x91D) - EQR_8
+ */
+#define WM2200_EQR_B2_C_MASK 0xFFFF /* EQR_B2_C - [15:0] */
+#define WM2200_EQR_B2_C_SHIFT 0 /* EQR_B2_C - [15:0] */
+#define WM2200_EQR_B2_C_WIDTH 16 /* EQR_B2_C - [15:0] */
+
+/*
+ * R2334 (0x91E) - EQR_9
+ */
+#define WM2200_EQR_B2_PG_MASK 0xFFFF /* EQR_B2_PG - [15:0] */
+#define WM2200_EQR_B2_PG_SHIFT 0 /* EQR_B2_PG - [15:0] */
+#define WM2200_EQR_B2_PG_WIDTH 16 /* EQR_B2_PG - [15:0] */
+
+/*
+ * R2335 (0x91F) - EQR_10
+ */
+#define WM2200_EQR_B3_A_MASK 0xFFFF /* EQR_B3_A - [15:0] */
+#define WM2200_EQR_B3_A_SHIFT 0 /* EQR_B3_A - [15:0] */
+#define WM2200_EQR_B3_A_WIDTH 16 /* EQR_B3_A - [15:0] */
+
+/*
+ * R2336 (0x920) - EQR_11
+ */
+#define WM2200_EQR_B3_B_MASK 0xFFFF /* EQR_B3_B - [15:0] */
+#define WM2200_EQR_B3_B_SHIFT 0 /* EQR_B3_B - [15:0] */
+#define WM2200_EQR_B3_B_WIDTH 16 /* EQR_B3_B - [15:0] */
+
+/*
+ * R2337 (0x921) - EQR_12
+ */
+#define WM2200_EQR_B3_C_MASK 0xFFFF /* EQR_B3_C - [15:0] */
+#define WM2200_EQR_B3_C_SHIFT 0 /* EQR_B3_C - [15:0] */
+#define WM2200_EQR_B3_C_WIDTH 16 /* EQR_B3_C - [15:0] */
+
+/*
+ * R2338 (0x922) - EQR_13
+ */
+#define WM2200_EQR_B3_PG_MASK 0xFFFF /* EQR_B3_PG - [15:0] */
+#define WM2200_EQR_B3_PG_SHIFT 0 /* EQR_B3_PG - [15:0] */
+#define WM2200_EQR_B3_PG_WIDTH 16 /* EQR_B3_PG - [15:0] */
+
+/*
+ * R2339 (0x923) - EQR_14
+ */
+#define WM2200_EQR_B4_A_MASK 0xFFFF /* EQR_B4_A - [15:0] */
+#define WM2200_EQR_B4_A_SHIFT 0 /* EQR_B4_A - [15:0] */
+#define WM2200_EQR_B4_A_WIDTH 16 /* EQR_B4_A - [15:0] */
+
+/*
+ * R2340 (0x924) - EQR_15
+ */
+#define WM2200_EQR_B4_B_MASK 0xFFFF /* EQR_B4_B - [15:0] */
+#define WM2200_EQR_B4_B_SHIFT 0 /* EQR_B4_B - [15:0] */
+#define WM2200_EQR_B4_B_WIDTH 16 /* EQR_B4_B - [15:0] */
+
+/*
+ * R2341 (0x925) - EQR_16
+ */
+#define WM2200_EQR_B4_C_MASK 0xFFFF /* EQR_B4_C - [15:0] */
+#define WM2200_EQR_B4_C_SHIFT 0 /* EQR_B4_C - [15:0] */
+#define WM2200_EQR_B4_C_WIDTH 16 /* EQR_B4_C - [15:0] */
+
+/*
+ * R2342 (0x926) - EQR_17
+ */
+#define WM2200_EQR_B4_PG_MASK 0xFFFF /* EQR_B4_PG - [15:0] */
+#define WM2200_EQR_B4_PG_SHIFT 0 /* EQR_B4_PG - [15:0] */
+#define WM2200_EQR_B4_PG_WIDTH 16 /* EQR_B4_PG - [15:0] */
+
+/*
+ * R2343 (0x927) - EQR_18
+ */
+#define WM2200_EQR_B5_A_MASK 0xFFFF /* EQR_B5_A - [15:0] */
+#define WM2200_EQR_B5_A_SHIFT 0 /* EQR_B5_A - [15:0] */
+#define WM2200_EQR_B5_A_WIDTH 16 /* EQR_B5_A - [15:0] */
+
+/*
+ * R2344 (0x928) - EQR_19
+ */
+#define WM2200_EQR_B5_B_MASK 0xFFFF /* EQR_B5_B - [15:0] */
+#define WM2200_EQR_B5_B_SHIFT 0 /* EQR_B5_B - [15:0] */
+#define WM2200_EQR_B5_B_WIDTH 16 /* EQR_B5_B - [15:0] */
+
+/*
+ * R2345 (0x929) - EQR_20
+ */
+#define WM2200_EQR_B5_PG_MASK 0xFFFF /* EQR_B5_PG - [15:0] */
+#define WM2200_EQR_B5_PG_SHIFT 0 /* EQR_B5_PG - [15:0] */
+#define WM2200_EQR_B5_PG_WIDTH 16 /* EQR_B5_PG - [15:0] */
+
+/*
+ * R2366 (0x93E) - HPLPF1_1
+ */
+#define WM2200_LHPF1_MODE 0x0002 /* LHPF1_MODE */
+#define WM2200_LHPF1_MODE_MASK 0x0002 /* LHPF1_MODE */
+#define WM2200_LHPF1_MODE_SHIFT 1 /* LHPF1_MODE */
+#define WM2200_LHPF1_MODE_WIDTH 1 /* LHPF1_MODE */
+#define WM2200_LHPF1_ENA 0x0001 /* LHPF1_ENA */
+#define WM2200_LHPF1_ENA_MASK 0x0001 /* LHPF1_ENA */
+#define WM2200_LHPF1_ENA_SHIFT 0 /* LHPF1_ENA */
+#define WM2200_LHPF1_ENA_WIDTH 1 /* LHPF1_ENA */
+
+/*
+ * R2367 (0x93F) - HPLPF1_2
+ */
+#define WM2200_LHPF1_COEFF_MASK 0xFFFF /* LHPF1_COEFF - [15:0] */
+#define WM2200_LHPF1_COEFF_SHIFT 0 /* LHPF1_COEFF - [15:0] */
+#define WM2200_LHPF1_COEFF_WIDTH 16 /* LHPF1_COEFF - [15:0] */
+
+/*
+ * R2370 (0x942) - HPLPF2_1
+ */
+#define WM2200_LHPF2_MODE 0x0002 /* LHPF2_MODE */
+#define WM2200_LHPF2_MODE_MASK 0x0002 /* LHPF2_MODE */
+#define WM2200_LHPF2_MODE_SHIFT 1 /* LHPF2_MODE */
+#define WM2200_LHPF2_MODE_WIDTH 1 /* LHPF2_MODE */
+#define WM2200_LHPF2_ENA 0x0001 /* LHPF2_ENA */
+#define WM2200_LHPF2_ENA_MASK 0x0001 /* LHPF2_ENA */
+#define WM2200_LHPF2_ENA_SHIFT 0 /* LHPF2_ENA */
+#define WM2200_LHPF2_ENA_WIDTH 1 /* LHPF2_ENA */
+
+/*
+ * R2371 (0x943) - HPLPF2_2
+ */
+#define WM2200_LHPF2_COEFF_MASK 0xFFFF /* LHPF2_COEFF - [15:0] */
+#define WM2200_LHPF2_COEFF_SHIFT 0 /* LHPF2_COEFF - [15:0] */
+#define WM2200_LHPF2_COEFF_WIDTH 16 /* LHPF2_COEFF - [15:0] */
+
+/*
+ * R2560 (0xA00) - DSP1 Control 1
+ */
+#define WM2200_DSP1_RW_SEQUENCE_ENA 0x0001 /* DSP1_RW_SEQUENCE_ENA */
+#define WM2200_DSP1_RW_SEQUENCE_ENA_MASK 0x0001 /* DSP1_RW_SEQUENCE_ENA */
+#define WM2200_DSP1_RW_SEQUENCE_ENA_SHIFT 0 /* DSP1_RW_SEQUENCE_ENA */
+#define WM2200_DSP1_RW_SEQUENCE_ENA_WIDTH 1 /* DSP1_RW_SEQUENCE_ENA */
+
+/*
+ * R2562 (0xA02) - DSP1 Control 2
+ */
+#define WM2200_DSP1_PAGE_BASE_PM_0_MASK 0xFF00 /* DSP1_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_PM_0_SHIFT 8 /* DSP1_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_PM_0_WIDTH 8 /* DSP1_PAGE_BASE_PM - [15:8] */
+
+/*
+ * R2563 (0xA03) - DSP1 Control 3
+ */
+#define WM2200_DSP1_PAGE_BASE_DM_0_MASK 0xFF00 /* DSP1_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_DM_0_SHIFT 8 /* DSP1_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_DM_0_WIDTH 8 /* DSP1_PAGE_BASE_DM - [15:8] */
+
+/*
+ * R2564 (0xA04) - DSP1 Control 4
+ */
+#define WM2200_DSP1_PAGE_BASE_ZM_0_MASK 0xFF00 /* DSP1_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_ZM_0_SHIFT 8 /* DSP1_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_ZM_0_WIDTH 8 /* DSP1_PAGE_BASE_ZM - [15:8] */
+
+/*
+ * R2566 (0xA06) - DSP1 Control 5
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2567 (0xA07) - DSP1 Control 6
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2568 (0xA08) - DSP1 Control 7
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2569 (0xA09) - DSP1 Control 8
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2570 (0xA0A) - DSP1 Control 9
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2571 (0xA0B) - DSP1 Control 10
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2572 (0xA0C) - DSP1 Control 11
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+
+/*
+ * R2573 (0xA0D) - DSP1 Control 12
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+
+/*
+ * R2575 (0xA0F) - DSP1 Control 13
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2576 (0xA10) - DSP1 Control 14
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2577 (0xA11) - DSP1 Control 15
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2578 (0xA12) - DSP1 Control 16
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2579 (0xA13) - DSP1 Control 17
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2580 (0xA14) - DSP1 Control 18
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2582 (0xA16) - DSP1 Control 19
+ */
+#define WM2200_DSP1_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP1_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP1_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+
+/*
+ * R2583 (0xA17) - DSP1 Control 20
+ */
+#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_MASK 0x00FF /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_SHIFT 0 /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_WIDTH 8 /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */
+
+/*
+ * R2584 (0xA18) - DSP1 Control 21
+ */
+#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_MASK 0x003F /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_SHIFT 0 /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_WIDTH 6 /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */
+
+/*
+ * R2586 (0xA1A) - DSP1 Control 22
+ */
+#define WM2200_DSP1_DM_SIZE_MASK 0xFFFF /* DSP1_DM_SIZE - [15:0] */
+#define WM2200_DSP1_DM_SIZE_SHIFT 0 /* DSP1_DM_SIZE - [15:0] */
+#define WM2200_DSP1_DM_SIZE_WIDTH 16 /* DSP1_DM_SIZE - [15:0] */
+
+/*
+ * R2587 (0xA1B) - DSP1 Control 23
+ */
+#define WM2200_DSP1_PM_SIZE_MASK 0xFFFF /* DSP1_PM_SIZE - [15:0] */
+#define WM2200_DSP1_PM_SIZE_SHIFT 0 /* DSP1_PM_SIZE - [15:0] */
+#define WM2200_DSP1_PM_SIZE_WIDTH 16 /* DSP1_PM_SIZE - [15:0] */
+
+/*
+ * R2588 (0xA1C) - DSP1 Control 24
+ */
+#define WM2200_DSP1_ZM_SIZE_MASK 0xFFFF /* DSP1_ZM_SIZE - [15:0] */
+#define WM2200_DSP1_ZM_SIZE_SHIFT 0 /* DSP1_ZM_SIZE - [15:0] */
+#define WM2200_DSP1_ZM_SIZE_WIDTH 16 /* DSP1_ZM_SIZE - [15:0] */
+
+/*
+ * R2590 (0xA1E) - DSP1 Control 25
+ */
+#define WM2200_DSP1_PING_FULL 0x8000 /* DSP1_PING_FULL */
+#define WM2200_DSP1_PING_FULL_MASK 0x8000 /* DSP1_PING_FULL */
+#define WM2200_DSP1_PING_FULL_SHIFT 15 /* DSP1_PING_FULL */
+#define WM2200_DSP1_PING_FULL_WIDTH 1 /* DSP1_PING_FULL */
+#define WM2200_DSP1_PONG_FULL 0x4000 /* DSP1_PONG_FULL */
+#define WM2200_DSP1_PONG_FULL_MASK 0x4000 /* DSP1_PONG_FULL */
+#define WM2200_DSP1_PONG_FULL_SHIFT 14 /* DSP1_PONG_FULL */
+#define WM2200_DSP1_PONG_FULL_WIDTH 1 /* DSP1_PONG_FULL */
+#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_MASK 0x00FF /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_SHIFT 0 /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_WIDTH 8 /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */
+
+/*
+ * R2592 (0xA20) - DSP1 Control 26
+ */
+#define WM2200_DSP1_SCRATCH_0_MASK 0xFFFF /* DSP1_SCRATCH_0 - [15:0] */
+#define WM2200_DSP1_SCRATCH_0_SHIFT 0 /* DSP1_SCRATCH_0 - [15:0] */
+#define WM2200_DSP1_SCRATCH_0_WIDTH 16 /* DSP1_SCRATCH_0 - [15:0] */
+
+/*
+ * R2593 (0xA21) - DSP1 Control 27
+ */
+#define WM2200_DSP1_SCRATCH_1_MASK 0xFFFF /* DSP1_SCRATCH_1 - [15:0] */
+#define WM2200_DSP1_SCRATCH_1_SHIFT 0 /* DSP1_SCRATCH_1 - [15:0] */
+#define WM2200_DSP1_SCRATCH_1_WIDTH 16 /* DSP1_SCRATCH_1 - [15:0] */
+
+/*
+ * R2594 (0xA22) - DSP1 Control 28
+ */
+#define WM2200_DSP1_SCRATCH_2_MASK 0xFFFF /* DSP1_SCRATCH_2 - [15:0] */
+#define WM2200_DSP1_SCRATCH_2_SHIFT 0 /* DSP1_SCRATCH_2 - [15:0] */
+#define WM2200_DSP1_SCRATCH_2_WIDTH 16 /* DSP1_SCRATCH_2 - [15:0] */
+
+/*
+ * R2595 (0xA23) - DSP1 Control 29
+ */
+#define WM2200_DSP1_SCRATCH_3_MASK 0xFFFF /* DSP1_SCRATCH_3 - [15:0] */
+#define WM2200_DSP1_SCRATCH_3_SHIFT 0 /* DSP1_SCRATCH_3 - [15:0] */
+#define WM2200_DSP1_SCRATCH_3_WIDTH 16 /* DSP1_SCRATCH_3 - [15:0] */
+
+/*
+ * R2596 (0xA24) - DSP1 Control 30
+ */
+#define WM2200_DSP1_DBG_CLK_ENA 0x0008 /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_DBG_CLK_ENA_MASK 0x0008 /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_DBG_CLK_ENA_SHIFT 3 /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_DBG_CLK_ENA_WIDTH 1 /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_SYS_ENA 0x0004 /* DSP1_SYS_ENA */
+#define WM2200_DSP1_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */
+#define WM2200_DSP1_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */
+#define WM2200_DSP1_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */
+#define WM2200_DSP1_CORE_ENA 0x0002 /* DSP1_CORE_ENA */
+#define WM2200_DSP1_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */
+#define WM2200_DSP1_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */
+#define WM2200_DSP1_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */
+#define WM2200_DSP1_START 0x0001 /* DSP1_START */
+#define WM2200_DSP1_START_MASK 0x0001 /* DSP1_START */
+#define WM2200_DSP1_START_SHIFT 0 /* DSP1_START */
+#define WM2200_DSP1_START_WIDTH 1 /* DSP1_START */
+
+/*
+ * R2598 (0xA26) - DSP1 Control 31
+ */
+#define WM2200_DSP1_CLK_RATE_MASK 0x0018 /* DSP1_CLK_RATE - [4:3] */
+#define WM2200_DSP1_CLK_RATE_SHIFT 3 /* DSP1_CLK_RATE - [4:3] */
+#define WM2200_DSP1_CLK_RATE_WIDTH 2 /* DSP1_CLK_RATE - [4:3] */
+#define WM2200_DSP1_CLK_AVAIL 0x0004 /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_AVAIL_MASK 0x0004 /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_AVAIL_SHIFT 2 /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_AVAIL_WIDTH 1 /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_REQ_MASK 0x0003 /* DSP1_CLK_REQ - [1:0] */
+#define WM2200_DSP1_CLK_REQ_SHIFT 0 /* DSP1_CLK_REQ - [1:0] */
+#define WM2200_DSP1_CLK_REQ_WIDTH 2 /* DSP1_CLK_REQ - [1:0] */
+
+/*
+ * R2816 (0xB00) - DSP2 Control 1
+ */
+#define WM2200_DSP2_RW_SEQUENCE_ENA 0x0001 /* DSP2_RW_SEQUENCE_ENA */
+#define WM2200_DSP2_RW_SEQUENCE_ENA_MASK 0x0001 /* DSP2_RW_SEQUENCE_ENA */
+#define WM2200_DSP2_RW_SEQUENCE_ENA_SHIFT 0 /* DSP2_RW_SEQUENCE_ENA */
+#define WM2200_DSP2_RW_SEQUENCE_ENA_WIDTH 1 /* DSP2_RW_SEQUENCE_ENA */
+
+/*
+ * R2818 (0xB02) - DSP2 Control 2
+ */
+#define WM2200_DSP2_PAGE_BASE_PM_0_MASK 0xFF00 /* DSP2_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_PM_0_SHIFT 8 /* DSP2_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_PM_0_WIDTH 8 /* DSP2_PAGE_BASE_PM - [15:8] */
+
+/*
+ * R2819 (0xB03) - DSP2 Control 3
+ */
+#define WM2200_DSP2_PAGE_BASE_DM_0_MASK 0xFF00 /* DSP2_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_DM_0_SHIFT 8 /* DSP2_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_DM_0_WIDTH 8 /* DSP2_PAGE_BASE_DM - [15:8] */
+
+/*
+ * R2820 (0xB04) - DSP2 Control 4
+ */
+#define WM2200_DSP2_PAGE_BASE_ZM_0_MASK 0xFF00 /* DSP2_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_ZM_0_SHIFT 8 /* DSP2_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_ZM_0_WIDTH 8 /* DSP2_PAGE_BASE_ZM - [15:8] */
+
+/*
+ * R2822 (0xB06) - DSP2 Control 5
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2823 (0xB07) - DSP2 Control 6
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2824 (0xB08) - DSP2 Control 7
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2825 (0xB09) - DSP2 Control 8
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2826 (0xB0A) - DSP2 Control 9
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2827 (0xB0B) - DSP2 Control 10
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2828 (0xB0C) - DSP2 Control 11
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+
+/*
+ * R2829 (0xB0D) - DSP2 Control 12
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+
+/*
+ * R2831 (0xB0F) - DSP2 Control 13
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2832 (0xB10) - DSP2 Control 14
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2833 (0xB11) - DSP2 Control 15
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2834 (0xB12) - DSP2 Control 16
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2835 (0xB13) - DSP2 Control 17
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2836 (0xB14) - DSP2 Control 18
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2838 (0xB16) - DSP2 Control 19
+ */
+#define WM2200_DSP2_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP2_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP2_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */
+
+/*
+ * R2839 (0xB17) - DSP2 Control 20
+ */
+#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_MASK 0x00FF /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_SHIFT 0 /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_WIDTH 8 /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */
+
+/*
+ * R2840 (0xB18) - DSP2 Control 21
+ */
+#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_MASK 0x003F /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_SHIFT 0 /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_WIDTH 6 /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */
+
+/*
+ * R2842 (0xB1A) - DSP2 Control 22
+ */
+#define WM2200_DSP2_DM_SIZE_MASK 0xFFFF /* DSP2_DM_SIZE - [15:0] */
+#define WM2200_DSP2_DM_SIZE_SHIFT 0 /* DSP2_DM_SIZE - [15:0] */
+#define WM2200_DSP2_DM_SIZE_WIDTH 16 /* DSP2_DM_SIZE - [15:0] */
+
+/*
+ * R2843 (0xB1B) - DSP2 Control 23
+ */
+#define WM2200_DSP2_PM_SIZE_MASK 0xFFFF /* DSP2_PM_SIZE - [15:0] */
+#define WM2200_DSP2_PM_SIZE_SHIFT 0 /* DSP2_PM_SIZE - [15:0] */
+#define WM2200_DSP2_PM_SIZE_WIDTH 16 /* DSP2_PM_SIZE - [15:0] */
+
+/*
+ * R2844 (0xB1C) - DSP2 Control 24
+ */
+#define WM2200_DSP2_ZM_SIZE_MASK 0xFFFF /* DSP2_ZM_SIZE - [15:0] */
+#define WM2200_DSP2_ZM_SIZE_SHIFT 0 /* DSP2_ZM_SIZE - [15:0] */
+#define WM2200_DSP2_ZM_SIZE_WIDTH 16 /* DSP2_ZM_SIZE - [15:0] */
+
+/*
+ * R2846 (0xB1E) - DSP2 Control 25
+ */
+#define WM2200_DSP2_PING_FULL 0x8000 /* DSP2_PING_FULL */
+#define WM2200_DSP2_PING_FULL_MASK 0x8000 /* DSP2_PING_FULL */
+#define WM2200_DSP2_PING_FULL_SHIFT 15 /* DSP2_PING_FULL */
+#define WM2200_DSP2_PING_FULL_WIDTH 1 /* DSP2_PING_FULL */
+#define WM2200_DSP2_PONG_FULL 0x4000 /* DSP2_PONG_FULL */
+#define WM2200_DSP2_PONG_FULL_MASK 0x4000 /* DSP2_PONG_FULL */
+#define WM2200_DSP2_PONG_FULL_SHIFT 14 /* DSP2_PONG_FULL */
+#define WM2200_DSP2_PONG_FULL_WIDTH 1 /* DSP2_PONG_FULL */
+#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_MASK 0x00FF /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_SHIFT 0 /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_WIDTH 8 /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */
+
+/*
+ * R2848 (0xB20) - DSP2 Control 26
+ */
+#define WM2200_DSP2_SCRATCH_0_MASK 0xFFFF /* DSP2_SCRATCH_0 - [15:0] */
+#define WM2200_DSP2_SCRATCH_0_SHIFT 0 /* DSP2_SCRATCH_0 - [15:0] */
+#define WM2200_DSP2_SCRATCH_0_WIDTH 16 /* DSP2_SCRATCH_0 - [15:0] */
+
+/*
+ * R2849 (0xB21) - DSP2 Control 27
+ */
+#define WM2200_DSP2_SCRATCH_1_MASK 0xFFFF /* DSP2_SCRATCH_1 - [15:0] */
+#define WM2200_DSP2_SCRATCH_1_SHIFT 0 /* DSP2_SCRATCH_1 - [15:0] */
+#define WM2200_DSP2_SCRATCH_1_WIDTH 16 /* DSP2_SCRATCH_1 - [15:0] */
+
+/*
+ * R2850 (0xB22) - DSP2 Control 28
+ */
+#define WM2200_DSP2_SCRATCH_2_MASK 0xFFFF /* DSP2_SCRATCH_2 - [15:0] */
+#define WM2200_DSP2_SCRATCH_2_SHIFT 0 /* DSP2_SCRATCH_2 - [15:0] */
+#define WM2200_DSP2_SCRATCH_2_WIDTH 16 /* DSP2_SCRATCH_2 - [15:0] */
+
+/*
+ * R2851 (0xB23) - DSP2 Control 29
+ */
+#define WM2200_DSP2_SCRATCH_3_MASK 0xFFFF /* DSP2_SCRATCH_3 - [15:0] */
+#define WM2200_DSP2_SCRATCH_3_SHIFT 0 /* DSP2_SCRATCH_3 - [15:0] */
+#define WM2200_DSP2_SCRATCH_3_WIDTH 16 /* DSP2_SCRATCH_3 - [15:0] */
+
+/*
+ * R2852 (0xB24) - DSP2 Control 30
+ */
+#define WM2200_DSP2_DBG_CLK_ENA 0x0008 /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_DBG_CLK_ENA_MASK 0x0008 /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_DBG_CLK_ENA_SHIFT 3 /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_DBG_CLK_ENA_WIDTH 1 /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_SYS_ENA 0x0004 /* DSP2_SYS_ENA */
+#define WM2200_DSP2_SYS_ENA_MASK 0x0004 /* DSP2_SYS_ENA */
+#define WM2200_DSP2_SYS_ENA_SHIFT 2 /* DSP2_SYS_ENA */
+#define WM2200_DSP2_SYS_ENA_WIDTH 1 /* DSP2_SYS_ENA */
+#define WM2200_DSP2_CORE_ENA 0x0002 /* DSP2_CORE_ENA */
+#define WM2200_DSP2_CORE_ENA_MASK 0x0002 /* DSP2_CORE_ENA */
+#define WM2200_DSP2_CORE_ENA_SHIFT 1 /* DSP2_CORE_ENA */
+#define WM2200_DSP2_CORE_ENA_WIDTH 1 /* DSP2_CORE_ENA */
+#define WM2200_DSP2_START 0x0001 /* DSP2_START */
+#define WM2200_DSP2_START_MASK 0x0001 /* DSP2_START */
+#define WM2200_DSP2_START_SHIFT 0 /* DSP2_START */
+#define WM2200_DSP2_START_WIDTH 1 /* DSP2_START */
+
+/*
+ * R2854 (0xB26) - DSP2 Control 31
+ */
+#define WM2200_DSP2_CLK_RATE_MASK 0x0018 /* DSP2_CLK_RATE - [4:3] */
+#define WM2200_DSP2_CLK_RATE_SHIFT 3 /* DSP2_CLK_RATE - [4:3] */
+#define WM2200_DSP2_CLK_RATE_WIDTH 2 /* DSP2_CLK_RATE - [4:3] */
+#define WM2200_DSP2_CLK_AVAIL 0x0004 /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_AVAIL_MASK 0x0004 /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_AVAIL_SHIFT 2 /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_AVAIL_WIDTH 1 /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_REQ_MASK 0x0003 /* DSP2_CLK_REQ - [1:0] */
+#define WM2200_DSP2_CLK_REQ_SHIFT 0 /* DSP2_CLK_REQ - [1:0] */
+#define WM2200_DSP2_CLK_REQ_WIDTH 2 /* DSP2_CLK_REQ - [1:0] */
+
+#endif
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index 714256e609c1..b9c185ce64e4 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -18,6 +18,7 @@
#include <linux/gcd.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/fixed.h>
#include <linux/slab.h>
@@ -55,9 +56,6 @@ struct wm5100_priv {
struct snd_soc_codec *codec;
struct regulator_bulk_data core_supplies[WM5100_NUM_CORE_SUPPLIES];
- struct regulator *cpvdd;
- struct regulator *dbvdd2;
- struct regulator *dbvdd3;
int rev;
@@ -74,6 +72,7 @@ struct wm5100_priv {
bool jack_detecting;
bool jack_mic;
int jack_mode;
+ int jack_flips;
struct wm5100_fll fll[2];
@@ -710,6 +709,8 @@ WM5100_MIXER_CONTROLS("EQ4", WM5100_EQ4MIX_INPUT_1_SOURCE),
WM5100_MIXER_CONTROLS("DRC1L", WM5100_DRC1LMIX_INPUT_1_SOURCE),
WM5100_MIXER_CONTROLS("DRC1R", WM5100_DRC1RMIX_INPUT_1_SOURCE),
+SND_SOC_BYTES_MASK("DRC", WM5100_DRC1_CTRL1, 5,
+ WM5100_DRCL_ENA | WM5100_DRCR_ENA),
WM5100_MIXER_CONTROLS("LHPF1", WM5100_HPLP1MIX_INPUT_1_SOURCE),
WM5100_MIXER_CONTROLS("LHPF2", WM5100_HPLP2MIX_INPUT_1_SOURCE),
@@ -777,85 +778,6 @@ static int wm5100_out_ev(struct snd_soc_dapm_widget *w,
return 0;
}
-static int wm5100_cp_ev(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol,
- int event)
-{
- struct snd_soc_codec *codec = w->codec;
- struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
- int ret;
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- ret = regulator_enable(wm5100->cpvdd);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to enable CPVDD: %d\n",
- ret);
- return ret;
- }
- return ret;
-
- case SND_SOC_DAPM_POST_PMD:
- ret = regulator_disable_deferred(wm5100->cpvdd, 20);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to disable CPVDD: %d\n",
- ret);
- return ret;
- }
- return ret;
-
- default:
- BUG();
- return 0;
- }
-}
-
-static int wm5100_dbvdd_ev(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol,
- int event)
-{
- struct snd_soc_codec *codec = w->codec;
- struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
- struct regulator *regulator;
- int ret;
-
- switch (w->shift) {
- case 2:
- regulator = wm5100->dbvdd2;
- break;
- case 3:
- regulator = wm5100->dbvdd3;
- break;
- default:
- BUG();
- return 0;
- }
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- ret = regulator_enable(regulator);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n",
- w->shift, ret);
- return ret;
- }
- return ret;
-
- case SND_SOC_DAPM_POST_PMD:
- ret = regulator_disable(regulator);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n",
- w->shift, ret);
- return ret;
- }
- return ret;
-
- default:
- BUG();
- return 0;
- }
-}
-
static void wm5100_log_status3(struct wm5100_priv *wm5100, int val)
{
if (val & WM5100_SPK_SHUTDOWN_WARN_EINT)
@@ -926,18 +848,16 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", WM5100_CLOCKING_3, WM5100_SYSCLK_ENA_SHIFT, 0,
SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT,
0, NULL, 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
+SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0),
+
SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0,
- wm5100_cp_ev,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ NULL, 0),
SND_SOC_DAPM_SUPPLY("CP2", WM5100_MIC_CHARGE_PUMP_1, WM5100_CP2_ENA_SHIFT, 0,
NULL, 0),
SND_SOC_DAPM_SUPPLY("CP2 Active", WM5100_MIC_CHARGE_PUMP_1,
- WM5100_CP2_BYPASS_SHIFT, 1, wm5100_cp_ev,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-SND_SOC_DAPM_SUPPLY("DBVDD2", SND_SOC_NOPM, 2, 0, wm5100_dbvdd_ev,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-SND_SOC_DAPM_SUPPLY("DBVDD3", SND_SOC_NOPM, 3, 0, wm5100_dbvdd_ev,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ WM5100_CP2_BYPASS_SHIFT, 1, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS1", WM5100_MIC_BIAS_CTRL_1, WM5100_MICB1_ENA_SHIFT,
0, NULL, 0),
@@ -1148,6 +1068,9 @@ SND_SOC_DAPM_POST("Post", wm5100_post_ev),
};
static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
+ { "CP1", NULL, "CPVDD" },
+ { "CP2 Active", NULL, "CPVDD" },
+
{ "IN1L", NULL, "SYSCLK" },
{ "IN1R", NULL, "SYSCLK" },
{ "IN2L", NULL, "SYSCLK" },
@@ -1342,54 +1265,6 @@ static const __devinitdata struct reg_default wm5100_reva_patches[] = {
{ WM5100_AUDIO_IF_3_19, 1 },
};
-static int wm5100_set_bias_level(struct snd_soc_codec *codec,
- enum snd_soc_bias_level level)
-{
- struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
- int ret;
-
- switch (level) {
- case SND_SOC_BIAS_ON:
- break;
-
- case SND_SOC_BIAS_PREPARE:
- break;
-
- case SND_SOC_BIAS_STANDBY:
- if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
- ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
- wm5100->core_supplies);
- if (ret != 0) {
- dev_err(codec->dev,
- "Failed to enable supplies: %d\n",
- ret);
- return ret;
- }
-
- if (wm5100->pdata.ldo_ena) {
- gpio_set_value_cansleep(wm5100->pdata.ldo_ena,
- 1);
- msleep(2);
- }
-
- regcache_cache_only(wm5100->regmap, false);
- regcache_sync(wm5100->regmap);
- }
- break;
-
- case SND_SOC_BIAS_OFF:
- regcache_cache_only(wm5100->regmap, true);
- if (wm5100->pdata.ldo_ena)
- gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
- regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
- wm5100->core_supplies);
- break;
- }
- codec->dapm.bias_level = level;
-
- return 0;
-}
-
static int wm5100_dai_to_base(struct snd_soc_dai *dai)
{
switch (dai->id) {
@@ -1917,6 +1792,8 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
if (!Fout) {
dev_dbg(codec->dev, "FLL%d disabled", fll_id);
+ if (fll->fout)
+ pm_runtime_put(codec->dev);
fll->fout = 0;
snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0);
return 0;
@@ -1961,6 +1838,8 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
/* Clear any pending completions */
try_wait_for_completion(&fll->lock);
+ pm_runtime_get_sync(codec->dev);
+
snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, WM5100_FLL1_ENA);
if (i2c->irq)
@@ -1995,6 +1874,7 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
}
if (i == timeout) {
dev_err(codec->dev, "FLL%d lock timed out\n", fll_id);
+ pm_runtime_put(codec->dev);
return -ETIMEDOUT;
}
@@ -2119,6 +1999,19 @@ static void wm5100_set_detect_mode(struct wm5100_priv *wm5100, int the_mode)
wm5100->jack_mode);
}
+static void wm5100_report_headphone(struct wm5100_priv *wm5100)
+{
+ dev_dbg(wm5100->dev, "Headphone detected\n");
+ wm5100->jack_detecting = false;
+ snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,
+ SND_JACK_HEADPHONE);
+
+ /* Increase the detection rate a bit for responsiveness. */
+ regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
+ WM5100_ACCDET_RATE_MASK,
+ 7 << WM5100_ACCDET_RATE_SHIFT);
+}
+
static void wm5100_micd_irq(struct wm5100_priv *wm5100)
{
unsigned int val;
@@ -2143,6 +2036,7 @@ static void wm5100_micd_irq(struct wm5100_priv *wm5100)
dev_dbg(wm5100->dev, "Jack removal detected\n");
wm5100->jack_mic = false;
wm5100->jack_detecting = true;
+ wm5100->jack_flips = 0;
snd_soc_jack_report(wm5100->jack, 0,
SND_JACK_LINEOUT | SND_JACK_HEADSET |
SND_JACK_BTN_0);
@@ -2161,6 +2055,7 @@ static void wm5100_micd_irq(struct wm5100_priv *wm5100)
if (wm5100->jack_detecting) {
dev_dbg(wm5100->dev, "Microphone detected\n");
wm5100->jack_mic = true;
+ wm5100->jack_detecting = false;
snd_soc_jack_report(wm5100->jack,
SND_JACK_HEADSET,
SND_JACK_HEADSET | SND_JACK_BTN_0);
@@ -2181,10 +2076,16 @@ static void wm5100_micd_irq(struct wm5100_priv *wm5100)
/* If we detected a lower impedence during initial startup
* then we probably have the wrong polarity, flip it. Don't
* do this for the lowest impedences to speed up detection of
- * plain headphones.
+ * plain headphones and give up if neither polarity looks
+ * sensible.
*/
if (wm5100->jack_detecting && (val & 0x3f8)) {
- wm5100_set_detect_mode(wm5100, !wm5100->jack_mode);
+ wm5100->jack_flips++;
+
+ if (wm5100->jack_flips > 1)
+ wm5100_report_headphone(wm5100);
+ else
+ wm5100_set_detect_mode(wm5100, !wm5100->jack_mode);
return;
}
@@ -2198,16 +2099,7 @@ static void wm5100_micd_irq(struct wm5100_priv *wm5100)
snd_soc_jack_report(wm5100->jack, SND_JACK_BTN_0,
SND_JACK_BTN_0);
} else if (wm5100->jack_detecting) {
- dev_dbg(wm5100->dev, "Headphone detected\n");
- snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,
- SND_JACK_HEADPHONE);
-
- /* Increase the detection rate a bit for
- * responsiveness.
- */
- regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
- WM5100_ACCDET_RATE_MASK,
- 7 << WM5100_ACCDET_RATE_SHIFT);
+ wm5100_report_headphone(wm5100);
}
}
}
@@ -2219,6 +2111,7 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
if (jack) {
wm5100->jack = jack;
wm5100->jack_detecting = true;
+ wm5100->jack_flips = 0;
wm5100_set_detect_mode(wm5100, 0);
@@ -2458,9 +2351,6 @@ static int wm5100_probe(struct snd_soc_codec *codec)
return ret;
}
- regcache_cache_only(wm5100->regmap, true);
-
-
for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++)
snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU,
WM5100_OUT_VU);
@@ -2486,14 +2376,6 @@ static int wm5100_probe(struct snd_soc_codec *codec)
}
}
- /* We'll get woken up again when the system has something useful
- * for us to do.
- */
- if (wm5100->pdata.ldo_ena)
- gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
- regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
- wm5100->core_supplies);
-
return 0;
err_gpio:
@@ -2525,7 +2407,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5100 = {
.set_sysclk = wm5100_set_sysclk,
.set_pll = wm5100_set_fll,
- .set_bias_level = wm5100_set_bias_level,
.idle_bias_off = 1,
.reg_cache_size = WM5100_MAX_REGISTER,
.volatile_register = wm5100_soc_volatile,
@@ -2551,6 +2432,13 @@ static const struct regmap_config wm5100_regmap = {
.cache_type = REGCACHE_RBTREE,
};
+static const unsigned int wm5100_mic_ctrl_reg[] = {
+ WM5100_IN1L_CONTROL,
+ WM5100_IN2L_CONTROL,
+ WM5100_IN3L_CONTROL,
+ WM5100_IN4L_CONTROL,
+};
+
static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -2585,41 +2473,21 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
for (i = 0; i < ARRAY_SIZE(wm5100->core_supplies); i++)
wm5100->core_supplies[i].supply = wm5100_core_supply_names[i];
- ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm5100->core_supplies),
- wm5100->core_supplies);
+ ret = devm_regulator_bulk_get(&i2c->dev,
+ ARRAY_SIZE(wm5100->core_supplies),
+ wm5100->core_supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
ret);
goto err_regmap;
}
- wm5100->cpvdd = regulator_get(&i2c->dev, "CPVDD");
- if (IS_ERR(wm5100->cpvdd)) {
- ret = PTR_ERR(wm5100->cpvdd);
- dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret);
- goto err_core;
- }
-
- wm5100->dbvdd2 = regulator_get(&i2c->dev, "DBVDD2");
- if (IS_ERR(wm5100->dbvdd2)) {
- ret = PTR_ERR(wm5100->dbvdd2);
- dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret);
- goto err_cpvdd;
- }
-
- wm5100->dbvdd3 = regulator_get(&i2c->dev, "DBVDD3");
- if (IS_ERR(wm5100->dbvdd3)) {
- ret = PTR_ERR(wm5100->dbvdd3);
- dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret);
- goto err_dbvdd2;
- }
-
ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
wm5100->core_supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
ret);
- goto err_dbvdd3;
+ goto err_regmap;
}
if (wm5100->pdata.ldo_ena) {
@@ -2701,7 +2569,7 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
}
for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) {
- regmap_update_bits(wm5100->regmap, WM5100_IN1L_CONTROL,
+ regmap_update_bits(wm5100->regmap, wm5100_mic_ctrl_reg[i],
WM5100_IN1_MODE_MASK |
WM5100_IN1_DMIC_SUP_MASK,
(wm5100->pdata.in_mode[i] <<
@@ -2762,6 +2630,10 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
}
}
+ pm_runtime_set_active(&i2c->dev);
+ pm_runtime_enable(&i2c->dev);
+ pm_request_idle(&i2c->dev);
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm5100, wm5100_dai,
ARRAY_SIZE(wm5100_dai));
@@ -2788,15 +2660,6 @@ err_ldo:
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
wm5100->core_supplies);
-err_dbvdd3:
- regulator_put(wm5100->dbvdd3);
-err_dbvdd2:
- regulator_put(wm5100->dbvdd2);
-err_cpvdd:
- regulator_put(wm5100->cpvdd);
-err_core:
- regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
- wm5100->core_supplies);
err_regmap:
regmap_exit(wm5100->regmap);
err:
@@ -2819,16 +2682,56 @@ static __devexit int wm5100_i2c_remove(struct i2c_client *i2c)
gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
gpio_free(wm5100->pdata.ldo_ena);
}
- regulator_put(wm5100->dbvdd3);
- regulator_put(wm5100->dbvdd2);
- regulator_put(wm5100->cpvdd);
- regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies),
- wm5100->core_supplies);
regmap_exit(wm5100->regmap);
return 0;
}
+#ifdef CONFIG_PM_RUNTIME
+static int wm5100_runtime_suspend(struct device *dev)
+{
+ struct wm5100_priv *wm5100 = dev_get_drvdata(dev);
+
+ regcache_cache_only(wm5100->regmap, true);
+ regcache_mark_dirty(wm5100->regmap);
+ if (wm5100->pdata.ldo_ena)
+ gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+ regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
+ wm5100->core_supplies);
+
+ return 0;
+}
+
+static int wm5100_runtime_resume(struct device *dev)
+{
+ struct wm5100_priv *wm5100 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
+ wm5100->core_supplies);
+ if (ret != 0) {
+ dev_err(dev, "Failed to enable supplies: %d\n",
+ ret);
+ return ret;
+ }
+
+ if (wm5100->pdata.ldo_ena) {
+ gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 1);
+ msleep(2);
+ }
+
+ regcache_cache_only(wm5100->regmap, false);
+ regcache_sync(wm5100->regmap);
+
+ return 0;
+}
+#endif
+
+static struct dev_pm_ops wm5100_pm = {
+ SET_RUNTIME_PM_OPS(wm5100_runtime_suspend, wm5100_runtime_resume,
+ NULL)
+};
+
static const struct i2c_device_id wm5100_i2c_id[] = {
{ "wm5100", 0 },
{ }
@@ -2839,6 +2742,7 @@ static struct i2c_driver wm5100_i2c_driver = {
.driver = {
.name = "wm5100",
.owner = THIS_MODULE,
+ .pm = &wm5100_pm,
},
.probe = wm5100_i2c_probe,
.remove = __devexit_p(wm5100_i2c_remove),
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c
index ff95e62c56b9..4fe9d191e277 100644
--- a/sound/soc/codecs/wm8737.c
+++ b/sound/soc/codecs/wm8737.c
@@ -599,7 +599,7 @@ static int wm8737_probe(struct snd_soc_codec *codec)
/* Bias level configuration will have done an extra enable */
regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies);
- snd_soc_add_controls(codec, wm8737_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8737_snd_controls,
ARRAY_SIZE(wm8737_snd_controls));
wm8737_add_widgets(codec);
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 21ed75de41f3..e27e7b62b365 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -1557,7 +1557,8 @@ static int __devinit wm8753_spi_probe(struct spi_device *spi)
struct wm8753_priv *wm8753;
int ret;
- wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
+ wm8753 = devm_kzalloc(&spi->dev, sizeof(struct wm8753_priv),
+ GFP_KERNEL);
if (wm8753 == NULL)
return -ENOMEM;
@@ -1577,10 +1578,12 @@ static int __devinit wm8753_spi_probe(struct spi_device *spi)
dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret);
goto err_regmap;
}
+
+ return 0;
+
err_regmap:
regmap_exit(wm8753->regmap);
err:
- kfree(wm8753);
return ret;
}
@@ -1612,7 +1615,8 @@ static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
struct wm8753_priv *wm8753;
int ret;
- wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
+ wm8753 = devm_kzalloc(&i2c->dev, sizeof(struct wm8753_priv),
+ GFP_KERNEL);
if (wm8753 == NULL)
return -ENOMEM;
@@ -1632,10 +1636,12 @@ static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
goto err_regmap;
}
+
+ return 0;
+
err_regmap:
regmap_exit(wm8753->regmap);
err:
- kfree(wm8753);
return ret;
}
@@ -1645,7 +1651,6 @@ static __devexit int wm8753_i2c_remove(struct i2c_client *client)
snd_soc_unregister_codec(&client->dev);
regmap_exit(wm8753->regmap);
- kfree(wm8753);
return 0;
}
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c
index 19374a9e5ba6..a5127b4ff9e1 100644
--- a/sound/soc/codecs/wm8770.c
+++ b/sound/soc/codecs/wm8770.c
@@ -580,8 +580,6 @@ static int wm8770_probe(struct snd_soc_codec *codec)
wm8770 = snd_soc_codec_get_drvdata(codec);
wm8770->codec = codec;
- codec->dapm.idle_bias_off = 1;
-
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8770->control_type);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -643,7 +641,7 @@ static int wm8770_probe(struct snd_soc_codec *codec)
/* mute all DACs */
snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10);
- snd_soc_add_controls(codec, wm8770_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8770_snd_controls,
ARRAY_SIZE(wm8770_snd_controls));
snd_soc_dapm_new_controls(&codec->dapm, wm8770_dapm_widgets,
ARRAY_SIZE(wm8770_dapm_widgets));
@@ -679,6 +677,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8770 = {
.suspend = wm8770_suspend,
.resume = wm8770_resume,
.set_bias_level = wm8770_set_bias_level,
+ .idle_bias_off = true,
.reg_cache_size = ARRAY_SIZE(wm8770_reg_defs),
.reg_word_size = sizeof (u16),
.reg_cache_default = wm8770_reg_defs
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index 33e97d1d8f46..a19db5a0a17a 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -30,6 +30,11 @@
#include "wm8776.h"
+enum wm8776_chip_type {
+ WM8775 = 1,
+ WM8776,
+};
+
/* codec private data */
struct wm8776_priv {
enum snd_soc_control_type control_type;
@@ -512,7 +517,8 @@ static __devexit int wm8776_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id wm8776_i2c_id[] = {
- { "wm8776", 0 },
+ { "wm8775", WM8775 },
+ { "wm8776", WM8776 },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id);
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index 8abe3757a979..7ee8dcf1fe32 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -549,7 +549,6 @@ static int wm8804_probe(struct snd_soc_codec *codec)
wm8804 = snd_soc_codec_get_drvdata(codec);
- codec->dapm.idle_bias_off = 1;
codec->control_data = wm8804->regmap;
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
@@ -678,6 +677,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
.suspend = wm8804_suspend,
.resume = wm8804_resume,
.set_bias_level = wm8804_set_bias_level,
+ .idle_bias_off = true,
.controls = wm8804_snd_controls,
.num_controls = ARRAY_SIZE(wm8804_snd_controls),
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 14afc1193343..65d525d74c54 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -1176,11 +1176,11 @@ static int wm8904_add_widgets(struct snd_soc_codec *codec)
switch (wm8904->devtype) {
case WM8904:
- snd_soc_add_controls(codec, wm8904_adc_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8904_adc_snd_controls,
ARRAY_SIZE(wm8904_adc_snd_controls));
- snd_soc_add_controls(codec, wm8904_dac_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8904_dac_snd_controls,
ARRAY_SIZE(wm8904_dac_snd_controls));
- snd_soc_add_controls(codec, wm8904_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8904_snd_controls,
ARRAY_SIZE(wm8904_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8904_adc_dapm_widgets,
@@ -1201,7 +1201,7 @@ static int wm8904_add_widgets(struct snd_soc_codec *codec)
break;
case WM8912:
- snd_soc_add_controls(codec, wm8904_dac_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8904_dac_snd_controls,
ARRAY_SIZE(wm8904_dac_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8904_dac_dapm_widgets,
@@ -2020,7 +2020,7 @@ static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec)
wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts;
wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts;
- ret = snd_soc_add_controls(codec, &control, 1);
+ ret = snd_soc_add_codec_controls(codec, &control, 1);
if (ret != 0)
dev_err(codec->dev,
"Failed to add ReTune Mobile control: %d\n", ret);
@@ -2033,7 +2033,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
int ret, i;
if (!pdata) {
- snd_soc_add_controls(codec, wm8904_eq_controls,
+ snd_soc_add_codec_controls(codec, wm8904_eq_controls,
ARRAY_SIZE(wm8904_eq_controls));
return;
}
@@ -2061,7 +2061,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
wm8904->drc_enum.max = pdata->num_drc_cfgs;
wm8904->drc_enum.texts = wm8904->drc_texts;
- ret = snd_soc_add_controls(codec, &control, 1);
+ ret = snd_soc_add_codec_controls(codec, &control, 1);
if (ret != 0)
dev_err(codec->dev,
"Failed to add DRC mode control: %d\n", ret);
@@ -2075,7 +2075,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
if (pdata->num_retune_mobile_cfgs)
wm8904_handle_retune_mobile_pdata(codec);
else
- snd_soc_add_controls(codec, wm8904_eq_controls,
+ snd_soc_add_codec_controls(codec, wm8904_eq_controls,
ARRAY_SIZE(wm8904_eq_controls));
}
@@ -2088,7 +2088,6 @@ static int wm8904_probe(struct snd_soc_codec *codec)
int ret, i;
codec->cache_sync = 1;
- codec->dapm.idle_bias_off = 1;
codec->control_data = wm8904->regmap;
switch (wm8904->devtype) {
@@ -2237,6 +2236,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8904 = {
.suspend = wm8904_suspend,
.resume = wm8904_resume,
.set_bias_level = wm8904_set_bias_level,
+ .idle_bias_off = true,
};
static const struct regmap_config wm8904_regmap = {
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index ae1933ed3e07..d2883affea3b 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -717,7 +717,7 @@ static int wm8940_probe(struct snd_soc_codec *codec)
return ret;
}
- ret = snd_soc_add_controls(codec, wm8940_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, wm8940_snd_controls,
ARRAY_SIZE(wm8940_snd_controls));
if (ret)
return ret;
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
index 8d4ea43d40a3..1332692ef81b 100644
--- a/sound/soc/codecs/wm8958-dsp2.c
+++ b/sound/soc/codecs/wm8958-dsp2.c
@@ -55,7 +55,7 @@ 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 (%d bytes)\n",
+ dev_err(codec->dev, "%s: firmware too short (%zd bytes)\n",
name, fw->size);
goto err;
}
@@ -920,11 +920,11 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
wm8994->dsp_active = -1;
- snd_soc_add_controls(codec, wm8958_mbc_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8958_mbc_snd_controls,
ARRAY_SIZE(wm8958_mbc_snd_controls));
- snd_soc_add_controls(codec, wm8958_vss_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8958_vss_snd_controls,
ARRAY_SIZE(wm8958_vss_snd_controls));
- snd_soc_add_controls(codec, wm8958_enh_eq_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8958_enh_eq_snd_controls,
ARRAY_SIZE(wm8958_enh_eq_snd_controls));
@@ -958,7 +958,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
wm8994->mbc_enum.max = pdata->num_mbc_cfgs;
wm8994->mbc_enum.texts = wm8994->mbc_texts;
- ret = snd_soc_add_controls(wm8994->codec, control, 1);
+ ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
if (ret != 0)
dev_err(wm8994->codec->dev,
"Failed to add MBC mode controls: %d\n", ret);
@@ -986,7 +986,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
wm8994->vss_enum.max = pdata->num_vss_cfgs;
wm8994->vss_enum.texts = wm8994->vss_texts;
- ret = snd_soc_add_controls(wm8994->codec, control, 1);
+ ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
if (ret != 0)
dev_err(wm8994->codec->dev,
"Failed to add VSS mode controls: %d\n", ret);
@@ -1015,7 +1015,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs;
wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts;
- ret = snd_soc_add_controls(wm8994->codec, control, 1);
+ ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
if (ret != 0)
dev_err(wm8994->codec->dev,
"Failed to add VSS HPFmode controls: %d\n",
@@ -1045,7 +1045,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs;
wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts;
- ret = snd_soc_add_controls(wm8994->codec, control, 1);
+ ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
if (ret != 0)
dev_err(wm8994->codec->dev,
"Failed to add enhanced EQ controls: %d\n",
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index e5caae32e541..840d72086d04 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -940,7 +940,7 @@ static int wm8960_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, WM8960_LOUT2, 0x100, 0x100);
snd_soc_update_bits(codec, WM8960_ROUT2, 0x100, 0x100);
- snd_soc_add_controls(codec, wm8960_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8960_snd_controls,
ARRAY_SIZE(wm8960_snd_controls));
wm8960_add_widgets(codec);
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index 4f20c72a0f1d..05ea7c274093 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -1022,7 +1022,7 @@ static int wm8961_probe(struct snd_soc_codec *codec)
wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, wm8961_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8961_snd_controls,
ARRAY_SIZE(wm8961_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8961_dapm_widgets,
ARRAY_SIZE(wm8961_dapm_widgets));
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index cc4049e9174b..445d2090661c 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -20,6 +20,7 @@
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/input.h>
+#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
@@ -96,7 +97,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) { \
- regcache_cache_only(wm8962->regmap, true); \
+ regcache_mark_dirty(wm8962->regmap); \
} \
return 0; \
}
@@ -207,8 +208,6 @@ static struct reg_default wm8962_reg[] = {
{ 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 */
@@ -1832,65 +1831,6 @@ SOC_SINGLE_TLV("SPKOUTR Mixer DACR Volume", WM8962_SPEAKER_MIXER_5,
4, 1, 0, inmix_tlv),
};
-static int sysclk_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_codec *codec = w->codec;
- struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
- unsigned long timeout;
- int src;
- int fll;
-
- /* Ignore attempts to run the event during startup */
- if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
- return 0;
-
- src = snd_soc_read(codec, WM8962_CLOCKING2) & WM8962_SYSCLK_SRC_MASK;
-
- switch (src) {
- case 0: /* MCLK */
- fll = 0;
- break;
- case 0x200: /* FLL */
- fll = 1;
- break;
- default:
- dev_err(codec->dev, "Unknown SYSCLK source %x\n", src);
- return -EINVAL;
- }
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- if (fll) {
- try_wait_for_completion(&wm8962->fll_lock);
-
- snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
- WM8962_FLL_ENA, WM8962_FLL_ENA);
-
- timeout = msecs_to_jiffies(5);
- timeout = wait_for_completion_timeout(&wm8962->fll_lock,
- timeout);
-
- if (wm8962->irq && timeout == 0)
- dev_err(codec->dev,
- "Timed out starting FLL\n");
- }
- break;
-
- case SND_SOC_DAPM_POST_PMD:
- if (fll)
- snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
- WM8962_FLL_ENA, 0);
- break;
-
- default:
- BUG();
- return -EINVAL;
- }
-
- return 0;
-}
-
static int cp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -2176,8 +2116,7 @@ SND_SOC_DAPM_INPUT("DMICDAT"),
SND_SOC_DAPM_SUPPLY("MICBIAS", WM8962_PWR_MGMT_1, 1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Class G", WM8962_CHARGE_PUMP_B, 0, 1, NULL, 0),
-SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event,
SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0),
@@ -2291,9 +2230,11 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = {
{ "STL", "Left", "ADCL" },
{ "STL", "Right", "ADCR" },
+ { "STL", NULL, "Class G" },
{ "STR", "Left", "ADCL" },
{ "STR", "Right", "ADCR" },
+ { "STR", NULL, "Class G" },
{ "DACL", NULL, "SYSCLK" },
{ "DACL", NULL, "TOCLK" },
@@ -2405,13 +2346,13 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec)
struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
struct snd_soc_dapm_context *dapm = &codec->dapm;
- snd_soc_add_controls(codec, wm8962_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8962_snd_controls,
ARRAY_SIZE(wm8962_snd_controls));
if (pdata && pdata->spk_mono)
- snd_soc_add_controls(codec, wm8962_spk_mono_controls,
+ snd_soc_add_codec_controls(codec, wm8962_spk_mono_controls,
ARRAY_SIZE(wm8962_spk_mono_controls));
else
- snd_soc_add_controls(codec, wm8962_spk_stereo_controls,
+ snd_soc_add_codec_controls(codec, wm8962_spk_stereo_controls,
ARRAY_SIZE(wm8962_spk_stereo_controls));
@@ -2445,7 +2386,7 @@ static const int bclk_divs[] = {
};
static const int sysclk_rates[] = {
- 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536,
+ 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536, 3072, 6144
};
static void wm8962_configure_bclk(struct snd_soc_codec *codec)
@@ -2479,6 +2420,8 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
return;
}
+ dev_dbg(codec->dev, "Selected sysclk ratio %d\n", sysclk_rates[i]);
+
snd_soc_update_bits(codec, WM8962_CLOCKING_4,
WM8962_SYSCLK_RATE_MASK, clocking4);
@@ -2537,9 +2480,6 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
static int wm8962_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
- int ret;
-
if (level == codec->dapm.bias_level)
return 0;
@@ -2556,51 +2496,15 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec,
break;
case SND_SOC_BIAS_STANDBY:
- if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
- ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
- wm8962->supplies);
- if (ret != 0) {
- dev_err(codec->dev,
- "Failed to enable supplies: %d\n",
- ret);
- return ret;
- }
-
- regcache_cache_only(wm8962->regmap, false);
- regcache_sync(wm8962->regmap);
-
- snd_soc_update_bits(codec, WM8962_ANTI_POP,
- WM8962_STARTUP_BIAS_ENA |
- WM8962_VMID_BUF_ENA,
- WM8962_STARTUP_BIAS_ENA |
- WM8962_VMID_BUF_ENA);
-
- /* Bias enable at 2*50k for ramp */
- snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
- WM8962_VMID_SEL_MASK |
- WM8962_BIAS_ENA,
- WM8962_BIAS_ENA | 0x180);
-
- msleep(5);
- }
-
/* VMID 2*250k */
snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
WM8962_VMID_SEL_MASK, 0x100);
break;
case SND_SOC_BIAS_OFF:
- snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
- WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, 0);
-
- snd_soc_update_bits(codec, WM8962_ANTI_POP,
- WM8962_STARTUP_BIAS_ENA |
- WM8962_VMID_BUF_ENA, 0);
-
- regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies),
- wm8962->supplies);
break;
}
+
codec->dapm.bias_level = level;
return 0;
}
@@ -2634,6 +2538,9 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
int adctl3 = 0;
wm8962->bclk = snd_soc_params_to_bclk(params);
+ if (params_channels(params) == 1)
+ wm8962->bclk *= 2;
+
wm8962->lrclk = params_rate(params);
for (i = 0; i < ARRAY_SIZE(sr_vals); i++) {
@@ -2654,13 +2561,13 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
case SNDRV_PCM_FORMAT_S16_LE:
break;
case SNDRV_PCM_FORMAT_S20_3LE:
- aif0 |= 0x40;
+ aif0 |= 0x4;
break;
case SNDRV_PCM_FORMAT_S24_LE:
- aif0 |= 0x80;
+ aif0 |= 0x8;
break;
case SNDRV_PCM_FORMAT_S32_LE:
- aif0 |= 0xc0;
+ aif0 |= 0xc;
break;
default:
return -EINVAL;
@@ -2672,7 +2579,8 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
WM8962_SAMPLE_RATE_INT_MODE |
WM8962_SAMPLE_RATE_MASK, adctl3);
- wm8962_configure_bclk(codec);
+ if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
+ wm8962_configure_bclk(codec);
return 0;
}
@@ -2702,6 +2610,8 @@ static int wm8962_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
wm8962->sysclk_rate = freq;
+ wm8962_configure_bclk(codec);
+
return 0;
}
@@ -2880,8 +2790,7 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
struct _fll_div fll_div;
unsigned long timeout;
int ret;
- int fll1 = snd_soc_read(codec, WM8962_FLL_CONTROL_1) & WM8962_FLL_ENA;
- int sysclk = snd_soc_read(codec, WM8962_CLOCKING2) & WM8962_SYSCLK_ENA;
+ int fll1 = 0;
/* Any change? */
if (source == wm8962->fll_src && Fref == wm8962->fll_fref &&
@@ -2897,6 +2806,8 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
WM8962_FLL_ENA, 0);
+ pm_runtime_put(codec->dev);
+
return 0;
}
@@ -2904,6 +2815,9 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
if (ret != 0)
return ret;
+ /* Parameters good, disable so we can reprogram */
+ snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_ENA, 0);
+
switch (fll_id) {
case WM8962_FLL_MCLK:
case WM8962_FLL_BCLK:
@@ -2942,12 +2856,11 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
try_wait_for_completion(&wm8962->fll_lock);
- if (sysclk)
- fll1 |= WM8962_FLL_ENA;
+ pm_runtime_get_sync(codec->dev);
snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK |
- WM8962_FLL_ENA, fll1);
+ WM8962_FLL_ENA, fll1 | WM8962_FLL_ENA);
dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
@@ -3008,14 +2921,14 @@ static struct snd_soc_dai_driver wm8962_dai = {
.name = "wm8962",
.playback = {
.stream_name = "Playback",
- .channels_min = 2,
+ .channels_min = 1,
.channels_max = 2,
.rates = WM8962_RATES,
.formats = WM8962_FORMATS,
},
.capture = {
.stream_name = "Capture",
- .channels_min = 2,
+ .channels_min = 1,
.channels_max = 2,
.rates = WM8962_RATES,
.formats = WM8962_FORMATS,
@@ -3056,54 +2969,73 @@ static void wm8962_mic_work(struct work_struct *work)
static irqreturn_t wm8962_irq(int irq, void *data)
{
- struct snd_soc_codec *codec = data;
- struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
- int mask;
- int active;
- int reg;
+ struct device *dev = data;
+ struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+ unsigned int mask;
+ unsigned int active;
+ int reg, ret;
- mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK);
+ ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2_MASK,
+ &mask);
+ if (ret != 0) {
+ dev_err(dev, "Failed to read interrupt mask: %d\n",
+ ret);
+ return IRQ_NONE;
+ }
+
+ ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, &active);
+ if (ret != 0) {
+ dev_err(dev, "Failed to read interrupt: %d\n", ret);
+ return IRQ_NONE;
+ }
- active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
active &= ~mask;
if (!active)
return IRQ_NONE;
/* Acknowledge the interrupts */
- snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active);
+ ret = regmap_write(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, active);
+ if (ret != 0)
+ dev_warn(dev, "Failed to ack interrupt: %d\n", ret);
if (active & WM8962_FLL_LOCK_EINT) {
- dev_dbg(codec->dev, "FLL locked\n");
+ dev_dbg(dev, "FLL locked\n");
complete(&wm8962->fll_lock);
}
if (active & WM8962_FIFOS_ERR_EINT)
- dev_err(codec->dev, "FIFO error\n");
+ dev_err(dev, "FIFO error\n");
if (active & WM8962_TEMP_SHUT_EINT) {
- dev_crit(codec->dev, "Thermal shutdown\n");
+ dev_crit(dev, "Thermal shutdown\n");
- reg = snd_soc_read(codec, WM8962_THERMAL_SHUTDOWN_STATUS);
+ ret = regmap_read(wm8962->regmap,
+ WM8962_THERMAL_SHUTDOWN_STATUS, &reg);
+ if (ret != 0) {
+ dev_warn(dev, "Failed to read thermal status: %d\n",
+ ret);
+ reg = 0;
+ }
if (reg & WM8962_TEMP_ERR_HP)
- dev_crit(codec->dev, "Headphone thermal error\n");
+ dev_crit(dev, "Headphone thermal error\n");
if (reg & WM8962_TEMP_WARN_HP)
- dev_crit(codec->dev, "Headphone thermal warning\n");
+ dev_crit(dev, "Headphone thermal warning\n");
if (reg & WM8962_TEMP_ERR_SPK)
- dev_crit(codec->dev, "Speaker thermal error\n");
+ dev_crit(dev, "Speaker thermal error\n");
if (reg & WM8962_TEMP_WARN_SPK)
- dev_crit(codec->dev, "Speaker thermal warning\n");
+ dev_crit(dev, "Speaker thermal warning\n");
}
if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) {
- dev_dbg(codec->dev, "Microphone event detected\n");
+ dev_dbg(dev, "Microphone event detected\n");
#ifndef CONFIG_SND_SOC_WM8962_MODULE
- trace_snd_soc_jack_irq(dev_name(codec->dev));
+ trace_snd_soc_jack_irq(dev_name(dev));
#endif
- pm_wakeup_event(codec->dev, 300);
+ pm_wakeup_event(dev, 300);
schedule_delayed_work(&wm8962->mic_work,
msecs_to_jiffies(250));
@@ -3584,7 +3516,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)
ret = request_threaded_irq(wm8962->irq, NULL, wm8962_irq,
trigger | IRQF_ONESHOT,
- "wm8962", codec);
+ "wm8962", codec->dev);
if (ret != 0) {
dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
wm8962->irq, ret);
@@ -3622,20 +3554,19 @@ static int wm8962_remove(struct snd_soc_codec *codec)
return 0;
}
-static int wm8962_soc_volatile(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- return true;
-}
-
-
static struct snd_soc_codec_driver soc_codec_dev_wm8962 = {
.probe = wm8962_probe,
.remove = wm8962_remove,
.set_bias_level = wm8962_set_bias_level,
.set_pll = wm8962_set_fll,
- .reg_cache_size = WM8962_MAX_REGISTER,
- .volatile_register = wm8962_soc_volatile,
+ .idle_bias_off = true,
+};
+
+/* Improve power consumption for IN4 DC measurement mode */
+static const struct reg_default wm8962_dc_measure[] = {
+ { 0xfd, 0x1 },
+ { 0xcc, 0x40 },
+ { 0xfd, 0 },
};
static const struct regmap_config wm8962_regmap = {
@@ -3653,6 +3584,7 @@ static const struct regmap_config wm8962_regmap = {
static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
+ struct wm8962_pdata *pdata = dev_get_platdata(&i2c->dev);
struct wm8962_priv *wm8962;
unsigned int reg;
int ret, i;
@@ -3706,7 +3638,7 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
}
if (reg != 0x6243) {
dev_err(&i2c->dev,
- "Device is not a WM8962, ID %x != 0x6243\n", ret);
+ "Device is not a WM8962, ID %x != 0x6243\n", reg);
ret = -EINVAL;
goto err_regmap;
}
@@ -3731,7 +3663,19 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
goto err_regmap;
}
- regcache_cache_only(wm8962->regmap, true);
+ if (pdata && pdata->in4_dc_measure) {
+ ret = regmap_register_patch(wm8962->regmap,
+ wm8962_dc_measure,
+ ARRAY_SIZE(wm8962_dc_measure));
+ if (ret != 0)
+ dev_err(&i2c->dev,
+ "Failed to configure for DC mesurement: %d\n",
+ ret);
+ }
+
+ pm_runtime_set_active(&i2c->dev);
+ pm_runtime_enable(&i2c->dev);
+ pm_request_idle(&i2c->dev);
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8962, &wm8962_dai, 1);
@@ -3763,6 +3707,65 @@ static __devexit int wm8962_i2c_remove(struct i2c_client *client)
return 0;
}
+#ifdef CONFIG_PM_RUNTIME
+static int wm8962_runtime_resume(struct device *dev)
+{
+ struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
+ wm8962->supplies);
+ if (ret != 0) {
+ dev_err(dev,
+ "Failed to enable supplies: %d\n", ret);
+ return ret;
+ }
+
+ regcache_cache_only(wm8962->regmap, false);
+ regcache_sync(wm8962->regmap);
+
+ regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP,
+ WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA,
+ WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA);
+
+ /* Bias enable at 2*50k for ramp */
+ regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
+ WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA,
+ WM8962_BIAS_ENA | 0x180);
+
+ msleep(5);
+
+ /* VMID back to 2x250k for standby */
+ regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
+ WM8962_VMID_SEL_MASK, 0x100);
+
+ return 0;
+}
+
+static int wm8962_runtime_suspend(struct device *dev)
+{
+ struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+
+ regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
+ WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, 0);
+
+ regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP,
+ WM8962_STARTUP_BIAS_ENA |
+ WM8962_VMID_BUF_ENA, 0);
+
+ regcache_cache_only(wm8962->regmap, true);
+
+ regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies),
+ wm8962->supplies);
+
+ return 0;
+}
+#endif
+
+static struct dev_pm_ops wm8962_pm = {
+ SET_RUNTIME_PM_OPS(wm8962_runtime_suspend, wm8962_runtime_resume, NULL)
+};
+
static const struct i2c_device_id wm8962_i2c_id[] = {
{ "wm8962", 0 },
{ }
@@ -3773,23 +3776,14 @@ static struct i2c_driver wm8962_i2c_driver = {
.driver = {
.name = "wm8962",
.owner = THIS_MODULE,
+ .pm = &wm8962_pm,
},
.probe = wm8962_i2c_probe,
.remove = __devexit_p(wm8962_i2c_remove),
.id_table = wm8962_i2c_id,
};
-static int __init wm8962_modinit(void)
-{
- return i2c_add_driver(&wm8962_i2c_driver);
-}
-module_init(wm8962_modinit);
-
-static void __exit wm8962_exit(void)
-{
- i2c_del_driver(&wm8962_i2c_driver);
-}
-module_exit(wm8962_exit);
+module_i2c_driver(wm8962_i2c_driver);
MODULE_DESCRIPTION("ASoC WM8962 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index 4ef9d4cb7d7c..6cdf6a2bc283 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -33,24 +33,89 @@
* We can't read the WM8988 register space when we
* are using 2 wire for device control, so we cache them instead.
*/
-static const u16 wm8988_reg[] = {
- 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */
- 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */
- 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */
- 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */
- 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */
- 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */
- 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */
- 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */
- 0x0079, 0x0079, 0x0079, /* 40 */
+static const struct reg_default wm8988_reg_defaults[] = {
+ { 0, 0x0097 },
+ { 1, 0x0097 },
+ { 2, 0x0079 },
+ { 3, 0x0079 },
+ { 5, 0x0008 },
+ { 7, 0x000a },
+ { 8, 0x0000 },
+ { 10, 0x00ff },
+ { 11, 0x00ff },
+ { 12, 0x000f },
+ { 13, 0x000f },
+ { 16, 0x0000 },
+ { 17, 0x007b },
+ { 18, 0x0000 },
+ { 19, 0x0032 },
+ { 20, 0x0000 },
+ { 21, 0x00c3 },
+ { 22, 0x00c3 },
+ { 23, 0x00c0 },
+ { 24, 0x0000 },
+ { 25, 0x0000 },
+ { 26, 0x0000 },
+ { 27, 0x0000 },
+ { 31, 0x0000 },
+ { 32, 0x0000 },
+ { 33, 0x0000 },
+ { 34, 0x0050 },
+ { 35, 0x0050 },
+ { 36, 0x0050 },
+ { 37, 0x0050 },
+ { 40, 0x0079 },
+ { 41, 0x0079 },
+ { 42, 0x0079 },
};
+static bool wm8988_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8988_LINVOL:
+ case WM8988_RINVOL:
+ case WM8988_LOUT1V:
+ case WM8988_ROUT1V:
+ case WM8988_ADCDAC:
+ case WM8988_IFACE:
+ case WM8988_SRATE:
+ case WM8988_LDAC:
+ case WM8988_RDAC:
+ case WM8988_BASS:
+ case WM8988_TREBLE:
+ case WM8988_RESET:
+ case WM8988_3D:
+ case WM8988_ALC1:
+ case WM8988_ALC2:
+ case WM8988_ALC3:
+ case WM8988_NGATE:
+ case WM8988_LADC:
+ case WM8988_RADC:
+ case WM8988_ADCTL1:
+ case WM8988_ADCTL2:
+ case WM8988_PWR1:
+ case WM8988_PWR2:
+ case WM8988_ADCTL3:
+ case WM8988_ADCIN:
+ case WM8988_LADCIN:
+ case WM8988_RADCIN:
+ case WM8988_LOUTM1:
+ case WM8988_LOUTM2:
+ case WM8988_ROUTM1:
+ case WM8988_ROUTM2:
+ case WM8988_LOUT2V:
+ case WM8988_ROUT2V:
+ case WM8988_LPPB:
+ return true;
+ default:
+ return false;
+ }
+}
+
/* codec private data */
struct wm8988_priv {
+ struct regmap *regmap;
unsigned int sysclk;
- enum snd_soc_control_type control_type;
struct snd_pcm_hw_constraint_list *sysclk_constraints;
};
@@ -661,6 +726,7 @@ static int wm8988_mute(struct snd_soc_dai *dai, int mute)
static int wm8988_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1;
switch (level) {
@@ -674,7 +740,7 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
- snd_soc_cache_sync(codec);
+ regcache_sync(wm8988->regmap);
/* VREF, VMID=2x5k */
snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
@@ -730,7 +796,10 @@ static struct snd_soc_dai_driver wm8988_dai = {
static int wm8988_suspend(struct snd_soc_codec *codec)
{
+ struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
+
wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ regcache_mark_dirty(wm8988->regmap);
return 0;
}
@@ -745,7 +814,8 @@ static int wm8988_probe(struct snd_soc_codec *codec)
struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type);
+ codec->control_data = wm8988->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -781,9 +851,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8988 = {
.suspend = wm8988_suspend,
.resume = wm8988_resume,
.set_bias_level = wm8988_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm8988_reg),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8988_reg,
.controls = wm8988_snd_controls,
.num_controls = ARRAY_SIZE(wm8988_snd_controls),
@@ -793,6 +860,18 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8988 = {
.num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes),
};
+static struct regmap_config wm8988_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+
+ .max_register = WM8988_LPPB,
+ .writeable_reg = wm8988_writeable,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8988_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8988_reg_defaults),
+};
+
#if defined(CONFIG_SPI_MASTER)
static int __devinit wm8988_spi_probe(struct spi_device *spi)
{
@@ -804,18 +883,28 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
if (wm8988 == NULL)
return -ENOMEM;
- wm8988->control_type = SND_SOC_SPI;
+ wm8988->regmap = regmap_init_spi(spi, &wm8988_regmap);
+ if (IS_ERR(wm8988->regmap)) {
+ ret = PTR_ERR(wm8988->regmap);
+ dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);
+ return ret;
+ }
+
spi_set_drvdata(spi, wm8988);
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8988, &wm8988_dai, 1);
+ if (ret != 0)
+ regmap_exit(wm8988->regmap);
return ret;
}
static int __devexit wm8988_spi_remove(struct spi_device *spi)
{
+ struct wm8988_priv *wm8988 = spi_get_drvdata(spi);
snd_soc_unregister_codec(&spi->dev);
+ regmap_exit(wm8988->regmap);
return 0;
}
@@ -842,16 +931,27 @@ static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
i2c_set_clientdata(i2c, wm8988);
- wm8988->control_type = SND_SOC_I2C;
+
+ wm8988->regmap = regmap_init_i2c(i2c, &wm8988_regmap);
+ if (IS_ERR(wm8988->regmap)) {
+ ret = PTR_ERR(wm8988->regmap);
+ dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
+ return ret;
+ }
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8988, &wm8988_dai, 1);
+ if (ret != 0)
+ regmap_exit(wm8988->regmap);
+
return ret;
}
static __devexit int wm8988_i2c_remove(struct i2c_client *client)
{
+ struct wm8988_priv *wm8988 = i2c_get_clientdata(client);
snd_soc_unregister_codec(&client->dev);
+ regmap_exit(wm8988->regmap);
return 0;
}
@@ -863,7 +963,7 @@ MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
static struct i2c_driver wm8988_i2c_driver = {
.driver = {
- .name = "wm8988-codec",
+ .name = "wm8988",
.owner = THIS_MODULE,
},
.probe = wm8988_i2c_probe,
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index e538edaae1f0..9d242351e6e8 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -1356,7 +1356,7 @@ static int wm8990_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
- snd_soc_add_controls(codec, wm8990_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8990_snd_controls,
ARRAY_SIZE(wm8990_snd_controls));
wm8990_add_widgets(codec);
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
index 7ee40da8dbb5..9ac31ba9b82e 100644
--- a/sound/soc/codecs/wm8991.c
+++ b/sound/soc/codecs/wm8991.c
@@ -1297,7 +1297,7 @@ static int wm8991_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
snd_soc_write(codec, WM8991_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
- snd_soc_add_controls(codec, wm8991_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8991_snd_controls,
ARRAY_SIZE(wm8991_snd_controls));
snd_soc_dapm_new_controls(&codec->dapm, wm8991_dapm_widgets,
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index dd687c3a84f9..d256a9340644 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -61,8 +61,9 @@ static struct reg_default wm8993_reg_defaults[] = {
{ 18, 0x0000 }, /* R18 - GPIO CTRL 1 */
{ 19, 0x0010 }, /* R19 - GPIO1 */
{ 20, 0x0000 }, /* R20 - IRQ_DEBOUNCE */
- { 21, 0x8000 }, /* R22 - GPIOCTRL 2 */
- { 22, 0x0800 }, /* R23 - GPIO_POL */
+ { 21, 0x0000 }, /* R21 - Inputs Clamp */
+ { 22, 0x8000 }, /* R22 - GPIOCTRL 2 */
+ { 23, 0x0800 }, /* R23 - GPIO_POL */
{ 24, 0x008B }, /* R24 - Left Line Input 1&2 Volume */
{ 25, 0x008B }, /* R25 - Left Line Input 3&4 Volume */
{ 26, 0x008B }, /* R26 - Right Line Input 1&2 Volume */
@@ -1057,6 +1058,8 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
int ret;
+ wm_hubs_set_bias_level(codec, level);
+
switch (level) {
case SND_SOC_BIAS_ON:
case SND_SOC_BIAS_PREPARE:
@@ -1077,10 +1080,7 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
regcache_cache_only(wm8993->regmap, false);
regcache_sync(wm8993->regmap);
- /* Tune DC servo configuration */
- snd_soc_write(codec, 0x44, 3);
- snd_soc_write(codec, 0x56, 3);
- snd_soc_write(codec, 0x44, 0);
+ wm_hubs_vmid_ena(codec);
/* Bring up VMID with fast soft start */
snd_soc_update_bits(codec, WM8993_ANTIPOP2,
@@ -1609,13 +1609,13 @@ static int wm8993_probe(struct snd_soc_codec *codec)
if (ret != 0)
return ret;
- snd_soc_add_controls(codec, wm8993_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8993_snd_controls,
ARRAY_SIZE(wm8993_snd_controls));
if (wm8993->pdata.num_retune_configs != 0) {
dev_dbg(codec->dev, "Using ReTune Mobile\n");
} else {
dev_dbg(codec->dev, "No ReTune Mobile, using normal EQ\n");
- snd_soc_add_controls(codec, wm8993_eq_controls,
+ snd_soc_add_codec_controls(codec, wm8993_eq_controls,
ARRAY_SIZE(wm8993_eq_controls));
}
@@ -1627,6 +1627,12 @@ static int wm8993_probe(struct snd_soc_codec *codec)
wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff,
wm8993->pdata.lineout2_diff);
+ /* If the line outputs are differential then we aren't presenting
+ * VMID as an output and can disable it.
+ */
+ if (wm8993->pdata.lineout1_diff && wm8993->pdata.lineout2_diff)
+ codec->dapm.idle_bias_off = 1;
+
return 0;
}
@@ -1691,6 +1697,13 @@ static int wm8993_resume(struct snd_soc_codec *codec)
#define wm8993_resume NULL
#endif
+/* Tune DC servo configuration */
+static struct reg_default wm8993_regmap_patch[] = {
+ { 0x44, 3 },
+ { 0x56, 3 },
+ { 0x44, 0 },
+};
+
static const struct regmap_config wm8993_regmap = {
.reg_bits = 8,
.val_bits = 16,
@@ -1769,6 +1782,12 @@ static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
if (ret != 0)
goto err_enable;
+ ret = regmap_register_patch(wm8993->regmap, wm8993_regmap_patch,
+ ARRAY_SIZE(wm8993_regmap_patch));
+ if (ret != 0)
+ dev_warn(wm8993->dev, "Failed to apply regmap patch: %d\n",
+ ret);
+
if (i2c->irq) {
/* Put GPIO1 into interrupt mode (only GPIO1 can output IRQ) */
ret = regmap_update_bits(wm8993->regmap, WM8993_GPIO1,
@@ -1840,24 +1859,7 @@ static struct i2c_driver wm8993_i2c_driver = {
.id_table = wm8993_i2c_id,
};
-static int __init wm8993_modinit(void)
-{
- int ret = 0;
- ret = i2c_add_driver(&wm8993_i2c_driver);
- if (ret != 0) {
- pr_err("WM8993: Unable to register I2C driver: %d\n",
- ret);
- }
- return ret;
-}
-module_init(wm8993_modinit);
-
-static void __exit wm8993_exit(void)
-{
- i2c_del_driver(&wm8993_i2c_driver);
-}
-module_exit(wm8993_exit);
-
+module_i2c_driver(wm8993_i2c_driver);
MODULE_DESCRIPTION("ASoC WM8993 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm8993.h b/sound/soc/codecs/wm8993.h
index 2184617b9611..4478b40c86e3 100644
--- a/sound/soc/codecs/wm8993.h
+++ b/sound/soc/codecs/wm8993.h
@@ -31,6 +31,7 @@
#define WM8993_GPIO_CTRL_1 0x12
#define WM8993_GPIO1 0x13
#define WM8993_IRQ_DEBOUNCE 0x14
+#define WM8993_INPUTS_CLAMP_REG 0x15
#define WM8993_GPIOCTRL_2 0x16
#define WM8993_GPIO_POL 0x17
#define WM8993_LEFT_LINE_INPUT_1_2_VOLUME 0x18
@@ -656,6 +657,14 @@
#define WM8993_GPIO1_DB_WIDTH 1 /* GPIO1_DB */
/*
+ * R21 (0x15) - Inputs Clamp
+ */
+#define WM8993_INPUTS_CLAMP 0x0040 /* INPUTS_CLAMP */
+#define WM8993_INPUTS_CLAMP_MASK 0x0040 /* INPUTS_CLAMP */
+#define WM8993_INPUTS_CLAMP_SHIFT 7 /* INPUTS_CLAMP */
+#define WM8993_INPUTS_CLAMP_WIDTH 1 /* INPUTS_CLAMP */
+
+/*
* R22 (0x16) - GPIOCTRL 2
*/
#define WM8993_IM_JD2_EINT 0x2000 /* IM_JD2_EINT */
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index b047bfada709..2417ef9316ed 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -685,15 +685,37 @@ SOC_SINGLE_TLV("MIXINL IN1RP Boost Volume", WM8994_INPUT_MIXER_1, 8, 1, 0,
static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ u16 old = snd_soc_read(codec, WM8994_ANTIPOP_2)
+ & WM1811_JACKDET_MODE_MASK;
+
+ if (!wm8994->jackdet || !wm8994->jack_cb)
+ return;
if (wm8994->active_refcount)
mode = WM1811_JACKDET_MODE_AUDIO;
+ if (mode == old)
+ return;
+
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
WM1811_JACKDET_MODE_MASK, mode);
- if (mode == WM1811_JACKDET_MODE_MIC)
- msleep(2);
+ switch (mode) {
+ case WM1811_JACKDET_MODE_MIC:
+ case WM1811_JACKDET_MODE_AUDIO:
+ switch (old) {
+ case WM1811_JACKDET_MODE_MIC:
+ case WM1811_JACKDET_MODE_AUDIO:
+ break;
+ default:
+ msleep(2);
+ break;
+ }
+
+ default:
+ break;
+ }
+
}
static void active_reference(struct snd_soc_codec *codec)
@@ -707,15 +729,8 @@ static void active_reference(struct snd_soc_codec *codec)
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);
- }
- }
+ /* If we're using jack detection go into audio mode */
+ wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_AUDIO);
mutex_unlock(&wm8994->accdet_lock);
}
@@ -734,16 +749,12 @@ static void active_dereference(struct snd_soc_codec *codec)
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;
+ 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);
- }
+ wm1811_jackdet_set_mode(codec, mode);
}
mutex_unlock(&wm8994->accdet_lock);
@@ -770,20 +781,33 @@ static void vmid_reference(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ pm_runtime_get_sync(codec->dev);
+
wm8994->vmid_refcount++;
dev_dbg(codec->dev, "Referencing VMID, refcount is now %d\n",
wm8994->vmid_refcount);
if (wm8994->vmid_refcount == 1) {
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
+ WM8994_LINEOUT_VMID_BUF_ENA |
+ WM8994_LINEOUT1_DISCH |
+ WM8994_LINEOUT2_DISCH,
+ WM8994_LINEOUT_VMID_BUF_ENA);
+
+ wm_hubs_vmid_ena(codec);
+
/* Startup bias, VMID ramp & buffer */
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_BIAS_SRC |
+ WM8994_VMID_DISCH |
WM8994_STARTUP_BIAS_ENA |
WM8994_VMID_BUF_ENA |
WM8994_VMID_RAMP_MASK,
+ WM8994_BIAS_SRC |
WM8994_STARTUP_BIAS_ENA |
WM8994_VMID_BUF_ENA |
- (0x11 << WM8994_VMID_RAMP_SHIFT));
+ (0x2 << WM8994_VMID_RAMP_SHIFT));
/* Main bias enable, VMID=2x40k */
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
@@ -791,7 +815,11 @@ static void vmid_reference(struct snd_soc_codec *codec)
WM8994_VMID_SEL_MASK,
WM8994_BIAS_ENA | 0x2);
- msleep(20);
+ msleep(50);
+
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_VMID_RAMP_MASK | WM8994_BIAS_SRC,
+ 0);
}
}
@@ -821,6 +849,10 @@ static void vmid_dereference(struct snd_soc_codec *codec)
WM8994_BIAS_ENA |
WM8994_VMID_SEL_MASK, 0);
+ /* Discharge VMID */
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_VMID_DISCH, WM8994_VMID_DISCH);
+
/* Discharge line */
snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
WM8994_LINEOUT1_DISCH |
@@ -837,6 +869,8 @@ static void vmid_dereference(struct snd_soc_codec *codec)
WM8994_VMID_BUF_ENA |
WM8994_VMID_RAMP_MASK, 0);
}
+
+ pm_runtime_put(codec->dev);
}
static int vmid_event(struct snd_soc_dapm_widget *w,
@@ -1450,17 +1484,17 @@ SND_SOC_DAPM_AIF_IN_E("AIF2DACR", NULL, 0,
WM8994_POWER_MANAGEMENT_5, 12, 0, wm8958_aif_ev,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-SND_SOC_DAPM_AIF_IN("AIF1DACDAT", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_IN("AIF2DACDAT", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1ADCDAT", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("AIF2ADCDAT", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF1DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF2DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1ADCDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2ADCDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_MUX("AIF1DAC Mux", SND_SOC_NOPM, 0, 0, &aif1dac_mux),
SND_SOC_DAPM_MUX("AIF2DAC Mux", SND_SOC_NOPM, 0, 0, &aif2dac_mux),
SND_SOC_DAPM_MUX("AIF2ADC Mux", SND_SOC_NOPM, 0, 0, &aif2adc_mux),
-SND_SOC_DAPM_AIF_IN("AIF3DACDAT", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF3DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_SUPPLY("TOCLK", WM8994_CLOCKING_1, 4, 0, NULL, 0),
@@ -1575,6 +1609,14 @@ static const struct snd_soc_dapm_route intercon[] = {
{ "TOCLK", NULL, "CLK_SYS" },
+ { "AIF1DACDAT", NULL, "AIF1 Playback" },
+ { "AIF2DACDAT", NULL, "AIF2 Playback" },
+ { "AIF3DACDAT", NULL, "AIF3 Playback" },
+
+ { "AIF1 Capture", NULL, "AIF1ADCDAT" },
+ { "AIF2 Capture", NULL, "AIF2ADCDAT" },
+ { "AIF3 Capture", NULL, "AIF3ADCDAT" },
+
/* AIF1 outputs */
{ "AIF1ADC1L", NULL, "AIF1ADC1L Mixer" },
{ "AIF1ADC1L Mixer", "ADC/DMIC Switch", "ADCL Mux" },
@@ -1887,7 +1929,8 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
WM8994_FLL1_OUTDIV_MASK |
WM8994_FLL1_FRATIO_MASK, reg);
- snd_soc_write(codec, WM8994_FLL1_CONTROL_3 + reg_offset, fll.k);
+ snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_3 + reg_offset,
+ WM8994_FLL1_K_MASK, fll.k);
snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_4 + reg_offset,
WM8994_FLL1_N_MASK,
@@ -2065,6 +2108,8 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = wm8994->wm8994;
+ wm_hubs_set_bias_level(codec, level);
+
switch (level) {
case SND_SOC_BIAS_ON:
break;
@@ -2159,6 +2204,7 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
wm8994->cur_fw = NULL;
break;
}
+
codec->dapm.bias_level = level;
return 0;
@@ -2759,13 +2805,6 @@ static int wm8994_resume(struct snd_soc_codec *codec)
codec->cache_only = 0;
}
- /* Restore the registers */
- ret = snd_soc_cache_sync(codec);
- if (ret != 0)
- dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
-
- wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
if (!wm8994->fll_suspend[i].out)
continue;
@@ -2867,7 +2906,7 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts;
wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts;
- ret = snd_soc_add_controls(wm8994->codec, controls,
+ ret = snd_soc_add_codec_controls(wm8994->codec, controls,
ARRAY_SIZE(controls));
if (ret != 0)
dev_err(wm8994->codec->dev,
@@ -2920,7 +2959,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
wm8994->drc_enum.max = pdata->num_drc_cfgs;
wm8994->drc_enum.texts = wm8994->drc_texts;
- ret = snd_soc_add_controls(wm8994->codec, controls,
+ ret = snd_soc_add_codec_controls(wm8994->codec, controls,
ARRAY_SIZE(controls));
if (ret != 0)
dev_err(wm8994->codec->dev,
@@ -2936,7 +2975,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
if (pdata->num_retune_mobile_cfgs)
wm8994_handle_retune_mobile_pdata(wm8994);
else
- snd_soc_add_controls(wm8994->codec, wm8994_eq_controls,
+ snd_soc_add_codec_controls(wm8994->codec, wm8994_eq_controls,
ARRAY_SIZE(wm8994_eq_controls));
for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) {
@@ -2953,8 +2992,6 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
* @codec: WM8994 codec
* @jack: jack to report detection events on
* @micbias: microphone bias to detect on
- * @det: value to report for presence detection
- * @shrt: value to report for short detection
*
* Enable microphone detection via IRQ on the WM8994. If GPIOs are
* being used to bring out signals to the processor then only platform
@@ -2965,43 +3002,63 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
* and micbias2_lvl platform data members.
*/
int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
- int micbias, int det, int shrt)
+ int micbias)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994_micdet *micdet;
struct wm8994 *control = wm8994->wm8994;
- int reg;
+ int reg, ret;
- if (control->type != WM8994)
+ if (control->type != WM8994) {
+ dev_warn(codec->dev, "Not a WM8994\n");
return -EINVAL;
+ }
switch (micbias) {
case 1:
micdet = &wm8994->micdet[0];
+ if (jack)
+ ret = snd_soc_dapm_force_enable_pin(&codec->dapm,
+ "MICBIAS1");
+ else
+ ret = snd_soc_dapm_disable_pin(&codec->dapm,
+ "MICBIAS1");
break;
case 2:
micdet = &wm8994->micdet[1];
+ if (jack)
+ ret = snd_soc_dapm_force_enable_pin(&codec->dapm,
+ "MICBIAS1");
+ else
+ ret = snd_soc_dapm_disable_pin(&codec->dapm,
+ "MICBIAS1");
break;
default:
+ dev_warn(codec->dev, "Invalid MICBIAS %d\n", micbias);
return -EINVAL;
- }
+ }
+
+ if (ret != 0)
+ dev_warn(codec->dev, "Failed to configure MICBIAS%d: %d\n",
+ micbias, ret);
- dev_dbg(codec->dev, "Configuring microphone detection on %d: %x %x\n",
- micbias, det, shrt);
+ dev_dbg(codec->dev, "Configuring microphone detection on %d %p\n",
+ micbias, jack);
/* Store the configuration */
micdet->jack = jack;
- micdet->det = det;
- micdet->shrt = shrt;
+ micdet->detecting = true;
/* If either of the jacks is set up then enable detection */
if (wm8994->micdet[0].jack || wm8994->micdet[1].jack)
reg = WM8994_MICD_ENA;
- else
+ else
reg = 0;
snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg);
+ snd_soc_dapm_sync(&codec->dapm);
+
return 0;
}
EXPORT_SYMBOL_GPL(wm8994_mic_detect);
@@ -3027,20 +3084,42 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
dev_dbg(codec->dev, "Microphone status: %x\n", reg);
report = 0;
- if (reg & WM8994_MIC1_DET_STS)
- report |= priv->micdet[0].det;
- if (reg & WM8994_MIC1_SHRT_STS)
- report |= priv->micdet[0].shrt;
+ if (reg & WM8994_MIC1_DET_STS) {
+ if (priv->micdet[0].detecting)
+ report = SND_JACK_HEADSET;
+ }
+ if (reg & WM8994_MIC1_SHRT_STS) {
+ if (priv->micdet[0].detecting)
+ report = SND_JACK_HEADPHONE;
+ else
+ report |= SND_JACK_BTN_0;
+ }
+ if (report)
+ priv->micdet[0].detecting = false;
+ else
+ priv->micdet[0].detecting = true;
+
snd_soc_jack_report(priv->micdet[0].jack, report,
- priv->micdet[0].det | priv->micdet[0].shrt);
+ SND_JACK_HEADSET | SND_JACK_BTN_0);
report = 0;
- if (reg & WM8994_MIC2_DET_STS)
- report |= priv->micdet[1].det;
- if (reg & WM8994_MIC2_SHRT_STS)
- report |= priv->micdet[1].shrt;
+ if (reg & WM8994_MIC2_DET_STS) {
+ if (priv->micdet[1].detecting)
+ report = SND_JACK_HEADSET;
+ }
+ if (reg & WM8994_MIC2_SHRT_STS) {
+ if (priv->micdet[1].detecting)
+ report = SND_JACK_HEADPHONE;
+ else
+ report |= SND_JACK_BTN_0;
+ }
+ if (report)
+ priv->micdet[1].detecting = false;
+ else
+ priv->micdet[1].detecting = true;
+
snd_soc_jack_report(priv->micdet[1].jack, report,
- priv->micdet[1].det | priv->micdet[1].shrt);
+ SND_JACK_HEADSET | SND_JACK_BTN_0);
return IRQ_HANDLED;
}
@@ -3089,7 +3168,7 @@ static void wm8958_default_micdet(u16 status, void *data)
}
- if (wm8994->mic_detecting && status & 0x4) {
+ if (wm8994->mic_detecting && status & 0xfc) {
dev_dbg(codec->dev, "Detected headphone\n");
wm8994->mic_detecting = false;
@@ -3103,6 +3182,14 @@ static void wm8958_default_micdet(u16 status, void *data)
snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
WM8958_MICD_ENA, 0);
+ if (wm8994->pdata->jd_ext_cap) {
+ mutex_lock(&codec->mutex);
+ snd_soc_dapm_disable_pin(&codec->dapm,
+ "MICBIAS2");
+ snd_soc_dapm_sync(&codec->dapm);
+ mutex_unlock(&codec->mutex);
+ }
+
wm1811_jackdet_set_mode(codec,
WM1811_JACKDET_MODE_JACK);
}
@@ -3157,21 +3244,52 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
snd_soc_jack_report(wm8994->micdet[0].jack,
SND_JACK_MECHANICAL, SND_JACK_MECHANICAL);
+ snd_soc_update_bits(codec, WM8958_MICBIAS2,
+ WM8958_MICB2_DISCH, 0);
+
+ /* Disable debounce while inserted */
+ snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
+ WM1811_JACKDET_DB, 0);
+
/*
* 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);
+
+ /* If required for an external cap force MICBIAS on */
+ if (wm8994->pdata->jd_ext_cap) {
+ mutex_lock(&codec->mutex);
+ snd_soc_dapm_force_enable_pin(&codec->dapm,
+ "MICBIAS2");
+ snd_soc_dapm_sync(&codec->dapm);
+ mutex_unlock(&codec->mutex);
+ }
} else {
dev_dbg(codec->dev, "Jack not detected\n");
+ snd_soc_update_bits(codec, WM8958_MICBIAS2,
+ WM8958_MICB2_DISCH, WM8958_MICB2_DISCH);
+
+ if (wm8994->pdata->jd_ext_cap) {
+ mutex_lock(&codec->mutex);
+ snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
+ snd_soc_dapm_sync(&codec->dapm);
+ mutex_unlock(&codec->mutex);
+ }
+
snd_soc_jack_report(wm8994->micdet[0].jack, 0,
SND_JACK_MECHANICAL | SND_JACK_HEADSET |
wm8994->btn_mask);
+ /* Enable debounce while removed */
+ snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
+ WM1811_JACKDET_DB, WM1811_JACKDET_DB);
+
wm8994->mic_detecting = false;
wm8994->jack_mic = false;
snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
@@ -3223,6 +3341,7 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
}
snd_soc_dapm_force_enable_pin(&codec->dapm, "CLK_SYS");
+ snd_soc_dapm_sync(&codec->dapm);
wm8994->micdet[0].jack = jack;
wm8994->jack_cb = cb;
@@ -3253,6 +3372,9 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
* otherwise jump straight to microphone detection.
*/
if (wm8994->jackdet) {
+ snd_soc_update_bits(codec, WM8958_MICBIAS2,
+ WM8958_MICB2_DISCH,
+ WM8958_MICB2_DISCH);
snd_soc_update_bits(codec, WM8994_LDO_1,
WM8994_LDO1_DISCH, 0);
wm1811_jackdet_set_mode(codec,
@@ -3265,7 +3387,9 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
} else {
snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
WM8958_MICD_ENA, 0);
+ wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_NONE);
snd_soc_dapm_disable_pin(&codec->dapm, "CLK_SYS");
+ snd_soc_dapm_sync(&codec->dapm);
}
return 0;
@@ -3363,23 +3487,16 @@ static irqreturn_t wm8994_temp_shut(int irq, void *data)
static int wm8994_codec_probe(struct snd_soc_codec *codec)
{
struct wm8994 *control = dev_get_drvdata(codec->dev->parent);
- struct wm8994_priv *wm8994;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
unsigned int reg;
int ret, i;
+ wm8994->codec = codec;
codec->control_data = control->regmap;
- wm8994 = devm_kzalloc(codec->dev, sizeof(struct wm8994_priv),
- GFP_KERNEL);
- if (wm8994 == NULL)
- return -ENOMEM;
- snd_soc_codec_set_drvdata(codec, wm8994);
-
snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
- wm8994->wm8994 = dev_get_drvdata(codec->dev->parent);
- wm8994->pdata = dev_get_platdata(codec->dev->parent);
wm8994->codec = codec;
mutex_init(&wm8994->accdet_lock);
@@ -3394,12 +3511,20 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
WM8994_IRQ_MIC1_DET;
pm_runtime_enable(codec->dev);
- pm_runtime_resume(codec->dev);
+ pm_runtime_idle(codec->dev);
+
+ /* By default use idle_bias_off, will override for WM8994 */
+ codec->dapm.idle_bias_off = 1;
/* Set revision-specific configuration */
wm8994->revision = snd_soc_read(codec, WM8994_CHIP_REVISION);
switch (control->type) {
case WM8994:
+ /* Single ended line outputs should have VMID on. */
+ if (!wm8994->pdata->lineout1_diff ||
+ !wm8994->pdata->lineout2_diff)
+ codec->dapm.idle_bias_off = 0;
+
switch (wm8994->revision) {
case 2:
case 3:
@@ -3417,11 +3542,14 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
case WM8958:
wm8994->hubs.dcs_readback_mode = 1;
+ wm8994->hubs.hp_startup_mode = 1;
break;
case WM1811:
wm8994->hubs.dcs_readback_mode = 2;
wm8994->hubs.no_series_update = 1;
+ wm8994->hubs.hp_startup_mode = 1;
+ wm8994->hubs.no_cache_class_w = true;
switch (wm8994->revision) {
case 0:
@@ -3538,6 +3666,9 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
wm8994->fll_locked_irq = false;
}
+ /* Make sure we can read from the GPIOs if they're inputs */
+ pm_runtime_get_sync(codec->dev);
+
/* Remember if AIFnLRCLK is configured as a GPIO. This should be
* configured on init - if a system wants to do this dynamically
* at runtime we can deal with that then.
@@ -3566,7 +3697,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
wm8994->lrclk_shared[1] = 0;
}
- wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ pm_runtime_put(codec->dev);
/* Latch volume updates (right only; we always do left then right). */
snd_soc_update_bits(codec, WM8994_AIF1_DAC1_LEFT_VOLUME,
@@ -3644,7 +3775,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
wm8994_handle_pdata(wm8994);
wm_hubs_add_analogue_controls(codec);
- snd_soc_add_controls(codec, wm8994_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8994_snd_controls,
ARRAY_SIZE(wm8994_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8994_dapm_widgets,
ARRAY_SIZE(wm8994_dapm_widgets));
@@ -3670,7 +3801,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
}
break;
case WM8958:
- snd_soc_add_controls(codec, wm8958_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8958_snd_controls,
ARRAY_SIZE(wm8958_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
ARRAY_SIZE(wm8958_dapm_widgets));
@@ -3692,7 +3823,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
break;
case WM1811:
- snd_soc_add_controls(codec, wm8958_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8958_snd_controls,
ARRAY_SIZE(wm8958_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
ARRAY_SIZE(wm8958_dapm_widgets));
@@ -3821,24 +3952,27 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec)
return 0;
}
-static int wm8994_soc_volatile(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- return true;
-}
-
static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
.probe = wm8994_codec_probe,
.remove = wm8994_codec_remove,
.suspend = wm8994_suspend,
.resume = wm8994_resume,
.set_bias_level = wm8994_set_bias_level,
- .reg_cache_size = WM8994_MAX_REGISTER,
- .volatile_register = wm8994_soc_volatile,
};
static int __devinit wm8994_probe(struct platform_device *pdev)
{
+ struct wm8994_priv *wm8994;
+
+ wm8994 = devm_kzalloc(&pdev->dev, sizeof(struct wm8994_priv),
+ GFP_KERNEL);
+ if (wm8994 == NULL)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, wm8994);
+
+ wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent);
+ wm8994->pdata = dev_get_platdata(pdev->dev.parent);
+
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994,
wm8994_dai, ARRAY_SIZE(wm8994_dai));
}
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index c3a42474ab19..f996d14766d9 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -35,7 +35,7 @@
typedef void (*wm8958_micdet_cb)(u16 status, void *data);
int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
- int micbias, int det, int shrt);
+ int micbias);
int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
wm8958_micdet_cb cb, void *cb_data);
@@ -46,8 +46,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec);
struct wm8994_micdet {
struct snd_soc_jack *jack;
- int det;
- int shrt;
+ bool detecting;
};
/* codec private data */
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index c8aada597d70..28c89b094c6e 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -2047,7 +2047,6 @@ static int wm8995_probe(struct snd_soc_codec *codec)
int i;
int ret;
- codec->dapm.idle_bias_off = 1;
wm8995 = snd_soc_codec_get_drvdata(codec);
wm8995->codec = codec;
@@ -2137,7 +2136,7 @@ static int wm8995_probe(struct snd_soc_codec *codec)
wm8995_update_class_w(codec);
- snd_soc_add_controls(codec, wm8995_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8995_snd_controls,
ARRAY_SIZE(wm8995_snd_controls));
snd_soc_dapm_new_controls(&codec->dapm, wm8995_dapm_widgets,
ARRAY_SIZE(wm8995_dapm_widgets));
@@ -2241,6 +2240,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8995 = {
.suspend = wm8995_suspend,
.resume = wm8995_resume,
.set_bias_level = wm8995_set_bias_level,
+ .idle_bias_off = true,
};
static struct regmap_config wm8995_regmap = {
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 8e8f8d1fef91..9376b19941b6 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -73,7 +73,6 @@ struct wm8996_priv {
struct regulator_bulk_data supplies[WM8996_NUM_SUPPLIES];
struct notifier_block disable_nb[WM8996_NUM_SUPPLIES];
- struct regulator *cpvdd;
int bg_ena;
struct wm8996_pdata pdata;
@@ -90,6 +89,7 @@ struct wm8996_priv {
struct snd_soc_jack *jack;
bool detecting;
bool jack_mic;
+ int jack_flips;
wm8996_polarity_fn polarity_cb;
#ifdef CONFIG_GPIOLIB
@@ -108,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) { \
- regcache_cache_only(wm8996->regmap, true); \
+ regcache_mark_dirty(wm8996->regmap); \
} \
return 0; \
}
@@ -716,10 +716,16 @@ SOC_SINGLE("DSP2 EQ Switch", WM8996_DSP2_RX_EQ_GAINS_1, 0, 1, 0),
SOC_SINGLE("DSP1 DRC TXL Switch", WM8996_DSP1_DRC_1, 0, 1, 0),
SOC_SINGLE("DSP1 DRC TXR Switch", WM8996_DSP1_DRC_1, 1, 1, 0),
SOC_SINGLE("DSP1 DRC RX Switch", WM8996_DSP1_DRC_1, 2, 1, 0),
+SND_SOC_BYTES_MASK("DSP1 DRC", WM8996_DSP1_DRC_1, 5,
+ WM8996_DSP1RX_DRC_ENA | WM8996_DSP1TXL_DRC_ENA |
+ WM8996_DSP1TXR_DRC_ENA),
SOC_SINGLE("DSP2 DRC TXL Switch", WM8996_DSP2_DRC_1, 0, 1, 0),
SOC_SINGLE("DSP2 DRC TXR Switch", WM8996_DSP2_DRC_1, 1, 1, 0),
SOC_SINGLE("DSP2 DRC RX Switch", WM8996_DSP2_DRC_1, 2, 1, 0),
+SND_SOC_BYTES_MASK("DSP2 DRC", WM8996_DSP2_DRC_1, 5,
+ WM8996_DSP2RX_DRC_ENA | WM8996_DSP2TXL_DRC_ENA |
+ WM8996_DSP2TXR_DRC_ENA),
};
static const struct snd_kcontrol_new wm8996_eq_controls[] = {
@@ -792,29 +798,18 @@ static int bg_event(struct snd_soc_dapm_widget *w,
static int cp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
- struct snd_soc_codec *codec = w->codec;
- struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- ret = regulator_enable(wm8996->cpvdd);
- if (ret != 0)
- dev_err(codec->dev, "Failed to enable CPVDD: %d\n",
- ret);
- break;
case SND_SOC_DAPM_POST_PMU:
msleep(5);
break;
- case SND_SOC_DAPM_POST_PMD:
- regulator_disable_deferred(wm8996->cpvdd, 20);
- break;
default:
BUG();
ret = -EINVAL;
}
- return ret;
+ return 0;
}
static int rmv_short_event(struct snd_soc_dapm_widget *w,
@@ -1116,11 +1111,12 @@ SND_SOC_DAPM_INPUT("IN2RP"),
SND_SOC_DAPM_INPUT("DMIC1DAT"),
SND_SOC_DAPM_INPUT("DMIC2DAT"),
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0),
@@ -1179,41 +1175,25 @@ SND_SOC_DAPM_DAC("DAC2R", NULL, WM8996_POWER_MANAGEMENT_5, 2, 0),
SND_SOC_DAPM_DAC("DAC1L", NULL, WM8996_POWER_MANAGEMENT_5, 1, 0),
SND_SOC_DAPM_DAC("DAC1R", NULL, WM8996_POWER_MANAGEMENT_5, 0, 0),
-SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0,
- WM8996_POWER_MANAGEMENT_4, 9, 0),
-SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 1,
- WM8996_POWER_MANAGEMENT_4, 8, 0),
-
-SND_SOC_DAPM_AIF_OUT("AIF2TX1", "AIF2 Capture", 0,
- WM8996_POWER_MANAGEMENT_6, 9, 0),
-SND_SOC_DAPM_AIF_OUT("AIF2TX0", "AIF2 Capture", 1,
- WM8996_POWER_MANAGEMENT_6, 8, 0),
-
-SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5,
- WM8996_POWER_MANAGEMENT_4, 5, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX4", "AIF1 Playback", 4,
- WM8996_POWER_MANAGEMENT_4, 4, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX3", "AIF1 Playback", 3,
- WM8996_POWER_MANAGEMENT_4, 3, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX2", "AIF1 Playback", 2,
- WM8996_POWER_MANAGEMENT_4, 2, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX1", "AIF1 Playback", 1,
- WM8996_POWER_MANAGEMENT_4, 1, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX0", "AIF1 Playback", 0,
- WM8996_POWER_MANAGEMENT_4, 0, 0),
-
-SND_SOC_DAPM_AIF_OUT("AIF1TX5", "AIF1 Capture", 5,
- WM8996_POWER_MANAGEMENT_6, 5, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX4", "AIF1 Capture", 4,
- WM8996_POWER_MANAGEMENT_6, 4, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX3", "AIF1 Capture", 3,
- WM8996_POWER_MANAGEMENT_6, 3, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX2", "AIF1 Capture", 2,
- WM8996_POWER_MANAGEMENT_6, 2, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX1", "AIF1 Capture", 1,
- WM8996_POWER_MANAGEMENT_6, 1, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX0", "AIF1 Capture", 0,
- WM8996_POWER_MANAGEMENT_6, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, WM8996_POWER_MANAGEMENT_4, 9, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX0", NULL, 1, WM8996_POWER_MANAGEMENT_4, 8, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, WM8996_POWER_MANAGEMENT_6, 9, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX0", NULL, 1, WM8996_POWER_MANAGEMENT_6, 8, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 5, WM8996_POWER_MANAGEMENT_4, 5, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 4, WM8996_POWER_MANAGEMENT_4, 4, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 3, WM8996_POWER_MANAGEMENT_4, 3, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 2, WM8996_POWER_MANAGEMENT_4, 2, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 1, WM8996_POWER_MANAGEMENT_4, 1, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX0", NULL, 0, WM8996_POWER_MANAGEMENT_4, 0, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 5, WM8996_POWER_MANAGEMENT_6, 5, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 4, WM8996_POWER_MANAGEMENT_6, 4, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 3, WM8996_POWER_MANAGEMENT_6, 3, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 2, WM8996_POWER_MANAGEMENT_6, 2, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 1, WM8996_POWER_MANAGEMENT_6, 1, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX0", NULL, 0, WM8996_POWER_MANAGEMENT_6, 0, 0),
/* We route as stereo pairs so define some dummy widgets to squash
* things down for now. RXA = 0,1, RXB = 2,3 and so on */
@@ -1279,6 +1259,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
{ "AIFCLK", NULL, "SYSCLK" },
{ "SYSDSPCLK", NULL, "SYSCLK" },
{ "Charge Pump", NULL, "SYSCLK" },
+ { "Charge Pump", NULL, "CPVDD" },
{ "MICB1", NULL, "LDO2" },
{ "MICB1", NULL, "MICB1 Audio" },
@@ -1287,6 +1268,26 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
{ "MICB2", NULL, "MICB2 Audio" },
{ "MICB2", NULL, "Bandgap" },
+ { "AIF1RX0", NULL, "AIF1 Playback" },
+ { "AIF1RX1", NULL, "AIF1 Playback" },
+ { "AIF1RX2", NULL, "AIF1 Playback" },
+ { "AIF1RX3", NULL, "AIF1 Playback" },
+ { "AIF1RX4", NULL, "AIF1 Playback" },
+ { "AIF1RX5", NULL, "AIF1 Playback" },
+
+ { "AIF2RX0", NULL, "AIF2 Playback" },
+ { "AIF2RX1", NULL, "AIF2 Playback" },
+
+ { "AIF1 Capture", NULL, "AIF1TX0" },
+ { "AIF1 Capture", NULL, "AIF1TX1" },
+ { "AIF1 Capture", NULL, "AIF1TX2" },
+ { "AIF1 Capture", NULL, "AIF1TX3" },
+ { "AIF1 Capture", NULL, "AIF1TX4" },
+ { "AIF1 Capture", NULL, "AIF1TX5" },
+
+ { "AIF2 Capture", NULL, "AIF2TX0" },
+ { "AIF2 Capture", NULL, "AIF2TX1" },
+
{ "IN1L PGA", NULL, "IN2LN" },
{ "IN1L PGA", NULL, "IN2LP" },
{ "IN1L PGA", NULL, "IN1LN" },
@@ -1719,6 +1720,7 @@ static int wm8996_reset(struct wm8996_priv *wm8996)
{
if (wm8996->pdata.ldo_ena > 0) {
gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
+ gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1);
return 0;
} else {
return regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET,
@@ -2437,6 +2439,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
wm8996->jack = jack;
wm8996->detecting = true;
wm8996->polarity_cb = polarity_cb;
+ wm8996->jack_flips = 0;
if (wm8996->polarity_cb)
wm8996->polarity_cb(codec, 0);
@@ -2552,6 +2555,19 @@ static void wm8996_hpdet_start(struct snd_soc_codec *codec)
WM8996_HP_POLL, WM8996_HP_POLL);
}
+static void wm8996_report_headphone(struct snd_soc_codec *codec)
+{
+ dev_dbg(codec->dev, "Headphone detected\n");
+ wm8996_hpdet_start(codec);
+
+ /* Increase the detection rate a bit for responsiveness. */
+ snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
+ WM8996_MICD_RATE_MASK |
+ WM8996_MICD_BIAS_STARTTIME_MASK,
+ 7 << WM8996_MICD_RATE_SHIFT |
+ 7 << WM8996_MICD_BIAS_STARTTIME_SHIFT);
+}
+
static void wm8996_micd(struct snd_soc_codec *codec)
{
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
@@ -2571,6 +2587,7 @@ static void wm8996_micd(struct snd_soc_codec *codec)
dev_dbg(codec->dev, "Jack removal detected\n");
wm8996->jack_mic = false;
wm8996->detecting = true;
+ wm8996->jack_flips = 0;
snd_soc_jack_report(wm8996->jack, 0,
SND_JACK_LINEOUT | SND_JACK_HEADSET |
SND_JACK_BTN_0);
@@ -2611,9 +2628,17 @@ static void wm8996_micd(struct snd_soc_codec *codec)
/* If we detected a lower impedence during initial startup
* then we probably have the wrong polarity, flip it. Don't
* do this for the lowest impedences to speed up detection of
- * plain headphones.
+ * plain headphones. If both polarities report a low
+ * impedence then give up and report headphones.
*/
if (wm8996->detecting && (val & 0x3f0)) {
+ wm8996->jack_flips++;
+
+ if (wm8996->jack_flips > 1) {
+ wm8996_report_headphone(codec);
+ return;
+ }
+
reg = snd_soc_read(codec, WM8996_ACCESSORY_DETECT_MODE_2);
reg ^= WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC |
WM8996_MICD_BIAS_SRC;
@@ -2640,17 +2665,7 @@ static void wm8996_micd(struct snd_soc_codec *codec)
snd_soc_jack_report(wm8996->jack, SND_JACK_BTN_0,
SND_JACK_BTN_0);
} else if (wm8996->detecting) {
- dev_dbg(codec->dev, "Headphone detected\n");
- wm8996_hpdet_start(codec);
-
- /* Increase the detection rate a bit for
- * responsiveness.
- */
- snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
- WM8996_MICD_RATE_MASK |
- WM8996_MICD_BIAS_STARTTIME_MASK,
- 7 << WM8996_MICD_RATE_SHIFT |
- 7 << WM8996_MICD_BIAS_STARTTIME_SHIFT);
+ wm8996_report_headphone(codec);
}
}
}
@@ -2767,7 +2782,7 @@ static void wm8996_retune_mobile_pdata(struct snd_soc_codec *codec)
wm8996->retune_mobile_enum.max = wm8996->num_retune_mobile_texts;
wm8996->retune_mobile_enum.texts = wm8996->retune_mobile_texts;
- ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+ ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
if (ret != 0)
dev_err(codec->dev,
"Failed to add ReTune Mobile controls: %d\n", ret);
@@ -2790,7 +2805,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
int ret;
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
struct i2c_client *i2c = to_i2c_client(codec->dev);
- struct snd_soc_dapm_context *dapm = &codec->dapm;
int i, irq_flags;
wm8996->codec = codec;
@@ -2798,8 +2812,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
init_completion(&wm8996->dcs_done);
init_completion(&wm8996->fll_lock);
- dapm->idle_bias_off = true;
-
codec->control_data = wm8996->regmap;
ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
@@ -2965,7 +2977,7 @@ static int wm8996_probe(struct snd_soc_codec *codec)
if (wm8996->pdata.num_retune_mobile_cfgs)
wm8996_retune_mobile_pdata(codec);
else
- snd_soc_add_controls(codec, wm8996_eq_controls,
+ snd_soc_add_codec_controls(codec, wm8996_eq_controls,
ARRAY_SIZE(wm8996_eq_controls));
/* If the TX LRCLK pins are not in LRCLK mode configure the
@@ -3037,22 +3049,16 @@ static int wm8996_remove(struct snd_soc_codec *codec)
for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
regulator_unregister_notifier(wm8996->supplies[i].consumer,
&wm8996->disable_nb[i]);
- regulator_put(wm8996->cpvdd);
regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
return 0;
}
-static int wm8996_soc_volatile_register(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- return true;
-}
-
static struct snd_soc_codec_driver soc_codec_dev_wm8996 = {
.probe = wm8996_probe,
.remove = wm8996_remove,
.set_bias_level = wm8996_set_bias_level,
+ .idle_bias_off = true,
.seq_notifier = wm8996_seq_notifier,
.controls = wm8996_snd_controls,
.num_controls = ARRAY_SIZE(wm8996_snd_controls),
@@ -3061,8 +3067,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8996 = {
.dapm_routes = wm8996_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(wm8996_dapm_routes),
.set_pll = wm8996_set_fll,
- .reg_cache_size = WM8996_MAX_REGISTER,
- .volatile_register = wm8996_soc_volatile_register,
};
#define WM8996_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
@@ -3152,25 +3156,18 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
wm8996->supplies[i].supply = wm8996_supply_names[i];
- ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8996->supplies),
- wm8996->supplies);
+ ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8996->supplies),
+ wm8996->supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
goto err_gpio;
}
- wm8996->cpvdd = regulator_get(&i2c->dev, "CPVDD");
- if (IS_ERR(wm8996->cpvdd)) {
- ret = PTR_ERR(wm8996->cpvdd);
- dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret);
- goto err_get;
- }
-
ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies),
wm8996->supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
- goto err_cpvdd;
+ goto err_gpio;
}
if (wm8996->pdata.ldo_ena > 0) {
@@ -3191,7 +3188,7 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
goto err_regmap;
}
if (reg != 0x8915) {
- dev_err(&i2c->dev, "Device is not a WM8996, ID %x\n", ret);
+ dev_err(&i2c->dev, "Device is not a WM8996, ID %x\n", reg);
ret = -EINVAL;
goto err_regmap;
}
@@ -3232,10 +3229,6 @@ err_enable:
if (wm8996->pdata.ldo_ena > 0)
gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
-err_cpvdd:
- regulator_put(wm8996->cpvdd);
-err_get:
- regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
err_gpio:
if (wm8996->pdata.ldo_ena > 0)
gpio_free(wm8996->pdata.ldo_ena);
@@ -3250,8 +3243,6 @@ static __devexit int wm8996_i2c_remove(struct i2c_client *client)
snd_soc_unregister_codec(&client->dev);
wm8996_free_gpio(wm8996);
- regulator_put(wm8996->cpvdd);
- regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
regmap_exit(wm8996->regmap);
if (wm8996->pdata.ldo_ena > 0) {
gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
@@ -3276,25 +3267,7 @@ static struct i2c_driver wm8996_i2c_driver = {
.id_table = wm8996_i2c_id,
};
-static int __init wm8996_modinit(void)
-{
- int ret;
-
- ret = i2c_add_driver(&wm8996_i2c_driver);
- if (ret != 0) {
- printk(KERN_ERR "Failed to register WM8996 I2C driver: %d\n",
- ret);
- }
-
- return ret;
-}
-module_init(wm8996_modinit);
-
-static void __exit wm8996_exit(void)
-{
- i2c_del_driver(&wm8996_i2c_driver);
-}
-module_exit(wm8996_exit);
+module_i2c_driver(wm8996_i2c_driver);
MODULE_DESCRIPTION("ASoC WM8996 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index a6bab392700e..076c126ed9b1 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -824,6 +824,8 @@ static const struct snd_soc_dapm_route wm9081_audio_paths[] = {
static int wm9081_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
+
switch (level) {
case SND_SOC_BIAS_ON:
break;
@@ -841,6 +843,9 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY:
/* Initial cold start */
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ regcache_cache_only(wm9081->regmap, false);
+ regcache_sync(wm9081->regmap);
+
/* Disable LINEOUT discharge */
snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL,
WM9081_LINEOUT_DISCH, 0);
@@ -892,6 +897,8 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec,
snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL,
WM9081_LINEOUT_DISCH,
WM9081_LINEOUT_DISCH);
+
+ regcache_cache_only(wm9081->regmap, true);
break;
}
@@ -1258,7 +1265,6 @@ static int wm9081_probe(struct snd_soc_codec *codec)
{
struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
int ret;
- u16 reg;
codec->control_data = wm9081->regmap;
@@ -1268,16 +1274,6 @@ static int wm9081_probe(struct snd_soc_codec *codec)
return ret;
}
- reg = 0;
- if (wm9081->pdata.irq_high)
- reg |= WM9081_IRQ_POL;
- if (!wm9081->pdata.irq_cmos)
- reg |= WM9081_IRQ_OP_CTRL;
- snd_soc_update_bits(codec, WM9081_INTERRUPT_CONTROL,
- WM9081_IRQ_POL | WM9081_IRQ_OP_CTRL, reg);
-
- wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
/* Enable zero cross by default */
snd_soc_update_bits(codec, WM9081_ANALOGUE_LINEOUT,
WM9081_LINEOUTZC, WM9081_LINEOUTZC);
@@ -1287,7 +1283,7 @@ static int wm9081_probe(struct snd_soc_codec *codec)
if (!wm9081->pdata.num_retune_configs) {
dev_dbg(codec->dev,
"No ReTune Mobile data, using normal EQ\n");
- snd_soc_add_controls(codec, wm9081_eq_controls,
+ snd_soc_add_codec_controls(codec, wm9081_eq_controls,
ARRAY_SIZE(wm9081_eq_controls));
}
@@ -1300,38 +1296,15 @@ static int wm9081_remove(struct snd_soc_codec *codec)
return 0;
}
-#ifdef CONFIG_PM
-static int wm9081_suspend(struct snd_soc_codec *codec)
-{
- wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- return 0;
-}
-
-static int wm9081_resume(struct snd_soc_codec *codec)
-{
- struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
-
- regcache_sync(wm9081->regmap);
-
- wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
- return 0;
-}
-#else
-#define wm9081_suspend NULL
-#define wm9081_resume NULL
-#endif
-
static struct snd_soc_codec_driver soc_codec_dev_wm9081 = {
.probe = wm9081_probe,
.remove = wm9081_remove,
- .suspend = wm9081_suspend,
- .resume = wm9081_resume,
.set_sysclk = wm9081_set_sysclk,
.set_bias_level = wm9081_set_bias_level,
+ .idle_bias_off = true,
+
.controls = wm9081_snd_controls,
.num_controls = ARRAY_SIZE(wm9081_snd_controls),
.dapm_widgets = wm9081_dapm_widgets,
@@ -1395,6 +1368,16 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev),
sizeof(wm9081->pdata));
+ reg = 0;
+ if (wm9081->pdata.irq_high)
+ reg |= WM9081_IRQ_POL;
+ if (!wm9081->pdata.irq_cmos)
+ reg |= WM9081_IRQ_OP_CTRL;
+ regmap_update_bits(wm9081->regmap, WM9081_INTERRUPT_CONTROL,
+ WM9081_IRQ_POL | WM9081_IRQ_OP_CTRL, reg);
+
+ regcache_cache_only(wm9081->regmap, true);
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm9081, &wm9081_dai, 1);
if (ret < 0)
@@ -1435,28 +1418,7 @@ static struct i2c_driver wm9081_i2c_driver = {
};
#endif
-static int __init wm9081_modinit(void)
-{
- int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- ret = i2c_add_driver(&wm9081_i2c_driver);
- if (ret != 0) {
- printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n",
- ret);
- }
-#endif
- return ret;
-}
-module_init(wm9081_modinit);
-
-static void __exit wm9081_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_del_driver(&wm9081_i2c_driver);
-#endif
-}
-module_exit(wm9081_exit);
-
+module_i2c_driver(wm9081_i2c_driver);
MODULE_DESCRIPTION("ASoC WM9081 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index a2b9208a08f0..4b263b6edf13 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -433,7 +433,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
- snd_soc_add_controls(codec, wm9090_controls,
+ snd_soc_add_codec_controls(codec, wm9090_controls,
ARRAY_SIZE(wm9090_controls));
if (wm9090->pdata.lin1_diff) {
@@ -442,7 +442,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
} else {
snd_soc_dapm_add_routes(dapm, audio_map_in1_se,
ARRAY_SIZE(audio_map_in1_se));
- snd_soc_add_controls(codec, wm9090_in1_se_controls,
+ snd_soc_add_codec_controls(codec, wm9090_in1_se_controls,
ARRAY_SIZE(wm9090_in1_se_controls));
}
@@ -452,7 +452,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
} else {
snd_soc_dapm_add_routes(dapm, audio_map_in2_se,
ARRAY_SIZE(audio_map_in2_se));
- snd_soc_add_controls(codec, wm9090_in2_se_controls,
+ snd_soc_add_codec_controls(codec, wm9090_in2_se_controls,
ARRAY_SIZE(wm9090_in2_se_controls));
}
@@ -639,7 +639,7 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
if (ret < 0)
goto err;
if (reg != 0x9093) {
- dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", ret);
+ dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", reg);
ret = -ENODEV;
goto err;
}
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index 40c92ead85a3..cacc6a86b46f 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -351,7 +351,7 @@ static int wm9705_soc_probe(struct snd_soc_codec *codec)
if (ret)
goto reset_err;
- snd_soc_add_controls(codec, wm9705_snd_ac97_controls,
+ snd_soc_add_codec_controls(codec, wm9705_snd_ac97_controls,
ARRAY_SIZE(wm9705_snd_ac97_controls));
return 0;
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index b7b31f84c10b..b342ae50bcd6 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -20,10 +20,9 @@
#include <sound/ac97_codec.h>
#include <sound/initval.h>
#include <sound/soc.h>
+#include <sound/tlv.h>
#include "wm9712.h"
-#define WM9712_VERSION "0.4"
-
static unsigned int ac97_read(struct snd_soc_codec *codec,
unsigned int reg);
static int ac97_write(struct snd_soc_codec *codec,
@@ -71,6 +70,9 @@ static const char *wm9712_rec_sel[] = {"Mic", "NC", "NC", "Speaker Mixer",
static const char *wm9712_ng_type[] = {"Constant Gain", "Mute"};
static const char *wm9712_diff_sel[] = {"Mic", "Line"};
+static const DECLARE_TLV_DB_SCALE(main_tlv, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 2000, 0);
+
static const struct soc_enum wm9712_enum[] = {
SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9712_alc_select),
SOC_ENUM_SINGLE(AC97_VIDEO, 12, 4, wm9712_alc_mux),
@@ -149,9 +151,9 @@ SOC_ENUM("Capture Volume Steps", wm9712_enum[6]),
SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
-SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
-SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
-SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
+SOC_SINGLE_TLV("Mic 1 Volume", AC97_MIC, 8, 31, 1, main_tlv),
+SOC_SINGLE_TLV("Mic 2 Volume", AC97_MIC, 0, 31, 1, main_tlv),
+SOC_SINGLE_TLV("Mic Boost Volume", AC97_MIC, 7, 1, 0, boost_tlv),
};
/* We have to create a fake left and right HP mixers because
@@ -619,8 +621,6 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)
{
int ret = 0;
- printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION);
-
ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
if (ret < 0) {
printk(KERN_ERR "wm9712: failed to register AC97 codec\n");
@@ -637,7 +637,7 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)
ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, wm9712_snd_ac97_controls,
+ snd_soc_add_codec_controls(codec, wm9712_snd_ac97_controls,
ARRAY_SIZE(wm9712_snd_ac97_controls));
return 0;
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 2b8479bfcd93..2d22cc70d536 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -1216,7 +1216,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)
reg = ac97_read(codec, AC97_CD) & 0x7fff;
ac97_write(codec, AC97_CD, reg);
- snd_soc_add_controls(codec, wm9713_snd_ac97_controls,
+ snd_soc_add_codec_controls(codec, wm9713_snd_ac97_controls,
ARRAY_SIZE(wm9713_snd_ac97_controls));
return 0;
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 2a61094075f8..c08d1c2f346f 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -172,7 +172,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
break;
default:
WARN(1, "Unknown DCS readback method\n");
- break;
+ return;
}
dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r);
@@ -207,7 +207,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
/* Save the callibrated offset if we're in class W mode and
* therefore don't have any analogue signal mixed in. */
- if (hubs->class_w)
+ if (hubs->class_w && !hubs->no_cache_class_w)
hubs->class_w_dcs = dcs_cfg;
}
@@ -500,6 +500,36 @@ static int earpiece_event(struct snd_soc_dapm_widget *w,
return 0;
}
+static int lineout_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *control, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+ bool *flag;
+
+ switch (w->shift) {
+ case WM8993_LINEOUT1N_ENA_SHIFT:
+ flag = &hubs->lineout1n_ena;
+ break;
+ case WM8993_LINEOUT1P_ENA_SHIFT:
+ flag = &hubs->lineout1p_ena;
+ break;
+ case WM8993_LINEOUT2N_ENA_SHIFT:
+ flag = &hubs->lineout2n_ena;
+ break;
+ case WM8993_LINEOUT2P_ENA_SHIFT:
+ flag = &hubs->lineout2p_ena;
+ break;
+ default:
+ WARN(1, "Unknown line output");
+ return -EINVAL;
+ }
+
+ *flag = SND_SOC_DAPM_EVENT_ON(event);
+
+ return 0;
+}
+
static const struct snd_kcontrol_new in1l_pga[] = {
SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0),
SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0),
@@ -586,14 +616,14 @@ SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
};
static const struct snd_kcontrol_new line2_mix[] = {
-SOC_DAPM_SINGLE("IN2R Switch", WM8993_LINE_MIXER2, 2, 1, 0),
-SOC_DAPM_SINGLE("IN2L Switch", WM8993_LINE_MIXER2, 1, 1, 0),
+SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER2, 2, 1, 0),
+SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER2, 1, 1, 0),
SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
};
static const struct snd_kcontrol_new line2n_mix[] = {
-SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
-SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
+SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
+SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
};
static const struct snd_kcontrol_new line2p_mix[] = {
@@ -613,6 +643,8 @@ SND_SOC_DAPM_INPUT("IN2RP:VXRP"),
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_SUPPLY("LINEOUT_VMID_BUF", WM8993_ANTIPOP1, 7, 0, NULL, 0),
+
SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
in1l_pga, ARRAY_SIZE(in1l_pga)),
SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0,
@@ -638,9 +670,8 @@ SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Headphone Supply", SND_SOC_NOPM, 0, 0, hp_supply_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
-SND_SOC_DAPM_PGA_E("Headphone PGA", SND_SOC_NOPM, 0, 0,
- NULL, 0,
- hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("Headphone PGA", SND_SOC_NOPM, 0, 0, NULL, 0,
+ hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
earpiece_mixer, ARRAY_SIZE(earpiece_mixer)),
@@ -654,10 +685,10 @@ SND_SOC_DAPM_MIXER("SPKR Boost", SND_SOC_NOPM, 0, 0,
right_speaker_boost, ARRAY_SIZE(right_speaker_boost)),
SND_SOC_DAPM_SUPPLY("TSHUT", WM8993_POWER_MANAGEMENT_2, 14, 0, NULL, 0),
-SND_SOC_DAPM_PGA("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
- NULL, 0),
-SND_SOC_DAPM_PGA("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
- NULL, 0),
+SND_SOC_DAPM_OUT_DRV("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
+ NULL, 0),
+SND_SOC_DAPM_OUT_DRV("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
+ NULL, 0),
SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0,
line1_mix, ARRAY_SIZE(line1_mix)),
@@ -673,14 +704,18 @@ SND_SOC_DAPM_MIXER("LINEOUT2N Mixer", SND_SOC_NOPM, 0, 0,
SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0,
line2p_mix, ARRAY_SIZE(line2p_mix)),
-SND_SOC_DAPM_PGA("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
- NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
- NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
- NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
- NULL, 0),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
+ NULL, 0, lineout_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
+ NULL, 0, lineout_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
+ NULL, 0, lineout_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
+ NULL, 0, lineout_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
@@ -834,9 +869,11 @@ static const struct snd_soc_dapm_route lineout1_diff_routes[] = {
};
static const struct snd_soc_dapm_route lineout1_se_routes[] = {
+ { "LINEOUT1N Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" },
{ "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" },
+ { "LINEOUT1P Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" },
{ "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" },
@@ -844,8 +881,8 @@ static const struct snd_soc_dapm_route lineout1_se_routes[] = {
};
static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
- { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" },
- { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" },
+ { "LINEOUT2 Mixer", "IN1L Switch", "IN1L PGA" },
+ { "LINEOUT2 Mixer", "IN1R Switch", "IN1R PGA" },
{ "LINEOUT2 Mixer", "Output Switch", "Right Output PGA" },
{ "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" },
@@ -853,9 +890,11 @@ static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
};
static const struct snd_soc_dapm_route lineout2_se_routes[] = {
+ { "LINEOUT2N Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" },
{ "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" },
+ { "LINEOUT2P Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" },
{ "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" },
@@ -895,7 +934,7 @@ int wm_hubs_add_analogue_controls(struct snd_soc_codec *codec)
WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU,
WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU);
- snd_soc_add_controls(codec, analogue_snd_controls,
+ snd_soc_add_codec_controls(codec, analogue_snd_controls,
ARRAY_SIZE(analogue_snd_controls));
snd_soc_dapm_new_controls(dapm, analogue_dapm_widgets,
@@ -943,6 +982,11 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
int jd_scthr, int jd_thr, int micbias1_lvl,
int micbias2_lvl)
{
+ struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+
+ hubs->lineout1_se = !lineout1_diff;
+ hubs->lineout2_se = !lineout2_diff;
+
if (!lineout1_diff)
snd_soc_update_bits(codec, WM8993_LINE_MIXER1,
WM8993_LINEOUT1_MODE,
@@ -952,12 +996,6 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
WM8993_LINEOUT2_MODE,
WM8993_LINEOUT2_MODE);
- /* If the line outputs are differential then we aren't presenting
- * VMID as an output and can disable it.
- */
- if (lineout1_diff && lineout2_diff)
- codec->dapm.idle_bias_off = 1;
-
if (lineout1fb)
snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB);
@@ -978,6 +1016,74 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
}
EXPORT_SYMBOL_GPL(wm_hubs_handle_analogue_pdata);
+void wm_hubs_vmid_ena(struct snd_soc_codec *codec)
+{
+ struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+ int val = 0;
+
+ if (hubs->lineout1_se)
+ val |= WM8993_LINEOUT1N_ENA | WM8993_LINEOUT1P_ENA;
+
+ if (hubs->lineout2_se)
+ val |= WM8993_LINEOUT2N_ENA | WM8993_LINEOUT2P_ENA;
+
+ /* Enable the line outputs while we power up */
+ snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_3, val, val);
+}
+EXPORT_SYMBOL_GPL(wm_hubs_vmid_ena);
+
+void wm_hubs_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+ int val;
+
+ switch (level) {
+ case SND_SOC_BIAS_STANDBY:
+ /* Clamp the inputs to VMID while we ramp to charge caps */
+ snd_soc_update_bits(codec, WM8993_INPUTS_CLAMP_REG,
+ WM8993_INPUTS_CLAMP, WM8993_INPUTS_CLAMP);
+ break;
+
+ case SND_SOC_BIAS_ON:
+ /* Turn off any unneded single ended outputs */
+ val = 0;
+
+ if (hubs->lineout1_se && hubs->lineout1n_ena)
+ val |= WM8993_LINEOUT1N_ENA;
+
+ if (hubs->lineout1_se && hubs->lineout1p_ena)
+ val |= WM8993_LINEOUT1P_ENA;
+
+ if (hubs->lineout2_se && hubs->lineout2n_ena)
+ val |= WM8993_LINEOUT2N_ENA;
+
+ if (hubs->lineout2_se && hubs->lineout2p_ena)
+ val |= WM8993_LINEOUT2P_ENA;
+
+ snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_3,
+ WM8993_LINEOUT1N_ENA |
+ WM8993_LINEOUT1P_ENA |
+ WM8993_LINEOUT2N_ENA |
+ WM8993_LINEOUT2P_ENA,
+ val);
+
+ if (!hubs->lineout1n_ena && !hubs->lineout1p_ena &&
+ !hubs->lineout2n_ena && !hubs->lineout2p_ena)
+ snd_soc_update_bits(codec, WM8993_ANTIPOP1,
+ WM8993_LINEOUT_VMID_BUF_ENA, 0);
+
+ /* Remove the input clamps */
+ snd_soc_update_bits(codec, WM8993_INPUTS_CLAMP_REG,
+ WM8993_INPUTS_CLAMP, 0);
+ break;
+
+ default:
+ break;
+ }
+}
+EXPORT_SYMBOL_GPL(wm_hubs_set_bias_level);
+
MODULE_DESCRIPTION("Shared support for Wolfson hubs products");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h
index c674c7a502a6..5705276f4943 100644
--- a/sound/soc/codecs/wm_hubs.h
+++ b/sound/soc/codecs/wm_hubs.h
@@ -30,9 +30,18 @@ struct wm_hubs_data {
int series_startup;
int no_series_update;
+ bool no_cache_class_w;
bool class_w;
u16 class_w_dcs;
+ bool lineout1_se;
+ bool lineout1n_ena;
+ bool lineout1p_ena;
+
+ bool lineout2_se;
+ bool lineout2n_ena;
+ bool lineout2p_ena;
+
bool dcs_done_irq;
struct completion dcs_done;
};
@@ -46,5 +55,8 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *,
int micbias1_lvl, int micbias2_lvl);
extern irqreturn_t wm_hubs_dcs_done(int irq, void *data);
+extern void wm_hubs_vmid_ena(struct snd_soc_codec *codec);
+extern void wm_hubs_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level);
#endif
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index 33adbf1e40d6..9a3f7c5ab687 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/of_device.h>
+#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/of_platform.h>
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 0ea4a5a96e06..fcf9302f59b4 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -245,7 +245,7 @@ static int get_parent_cell_index(struct device_node *np)
* 'struct device' It's ugly and hackish, but it works.
*
* The dev_name for such devices include the bus number and I2C address. For
- * example, "cs4270-codec.0-004f".
+ * example, "cs4270.0-004f".
*/
static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
{
@@ -267,13 +267,13 @@ static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
if (!i2c)
return -ENODEV;
- snprintf(buf, len, "%s-codec.%u-%04x", temp, i2c->adapter->nr, addr);
+ snprintf(buf, len, "%s.%u-%04x", temp, i2c->adapter->nr, addr);
return 0;
}
static int get_dma_channel(struct device_node *ssi_np,
- const char *compatible,
+ const char *name,
struct snd_soc_dai_link *dai,
unsigned int *dma_channel_id,
unsigned int *dma_id)
@@ -283,7 +283,7 @@ static int get_dma_channel(struct device_node *ssi_np,
const u32 *iprop;
int ret;
- dma_channel_np = get_node_by_phandle_name(ssi_np, compatible,
+ dma_channel_np = get_node_by_phandle_name(ssi_np, name,
"fsl,ssi-dma-channel");
if (!dma_channel_np)
return -EINVAL;
@@ -336,12 +336,8 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
const char *sprop;
const u32 *iprop;
- /* We are only interested in SSIs with a codec phandle in them,
- * so let's make sure this SSI has one. The MPC8610 HPCD only
- * knows about the CS4270 codec, so reject anything else.
- */
- codec_np = get_node_by_phandle_name(np, "codec-handle",
- "cirrus,cs4270");
+ /* Find the codec node for this SSI. */
+ codec_np = of_parse_phandle(np, "codec-handle", 0);
if (!codec_np) {
dev_err(dev, "invalid codec node\n");
return -EINVAL;
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
index a5d4e80a9cf4..d32ec4646d25 100644
--- a/sound/soc/fsl/p1022_ds.c
+++ b/sound/soc/fsl/p1022_ds.c
@@ -276,7 +276,7 @@ static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
}
static int get_dma_channel(struct device_node *ssi_np,
- const char *compatible,
+ const char *name,
struct snd_soc_dai_link *dai,
unsigned int *dma_channel_id,
unsigned int *dma_id)
@@ -286,7 +286,7 @@ static int get_dma_channel(struct device_node *ssi_np,
const u32 *iprop;
int ret;
- dma_channel_np = get_node_by_phandle_name(ssi_np, compatible,
+ dma_channel_np = get_node_by_phandle_name(ssi_np, name,
"fsl,ssi-dma-channel");
if (!dma_channel_np)
return -EINVAL;
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index 738391757f2c..aa4294bf49b2 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -1,9 +1,6 @@
menuconfig SND_IMX_SOC
tristate "SoC Audio for Freescale i.MX CPUs"
depends on ARCH_MXC
- select SND_PCM
- select FIQ
- select SND_SOC_AC97_BUS
help
Say Y or M if you want to add support for codecs attached to
the i.MX SSI interface.
@@ -12,9 +9,11 @@ menuconfig SND_IMX_SOC
if SND_IMX_SOC
config SND_MXC_SOC_FIQ
+ select FIQ
tristate
config SND_MXC_SOC_MX2
+ select SND_SOC_DMAENGINE_PCM
tristate
config SND_MXC_SOC_WM1133_EV1
@@ -38,6 +37,7 @@ config SND_SOC_MX27VIS_AIC32X4
config SND_SOC_PHYCORE_AC97
tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards"
depends on MACH_PCM043 || MACH_PCA100
+ select SND_SOC_AC97_BUS
select SND_SOC_WM9712
select SND_MXC_SOC_FIQ
help
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
index 5780c9b9d569..471e2218c971 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
@@ -27,212 +27,54 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
#include <mach/dma.h>
#include "imx-ssi.h"
-struct imx_pcm_runtime_data {
- int period_bytes;
- int periods;
- int dma;
- unsigned long offset;
- unsigned long size;
- void *buf;
- int period_time;
- struct dma_async_tx_descriptor *desc;
- struct dma_chan *dma_chan;
- struct imx_dma_data dma_data;
-};
-
-static void audio_dma_irq(void *data)
-{
- struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-
- iprtd->offset += iprtd->period_bytes;
- iprtd->offset %= iprtd->period_bytes * iprtd->periods;
-
- snd_pcm_period_elapsed(substream);
-}
-
static bool filter(struct dma_chan *chan, void *param)
{
- struct imx_pcm_runtime_data *iprtd = param;
-
if (!imx_dma_is_general_purpose(chan))
return false;
- chan->private = &iprtd->dma_data;
+ chan->private = param;
- return true;
+ return true;
}
-static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream,
+static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
struct imx_pcm_dma_params *dma_params;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
struct dma_slave_config slave_config;
- dma_cap_mask_t mask;
- enum dma_slave_buswidth buswidth;
int ret;
dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
- iprtd->dma_data.peripheral_type = IMX_DMATYPE_SSI;
- iprtd->dma_data.priority = DMA_PRIO_HIGH;
- iprtd->dma_data.dma_request = dma_params->dma;
-
- /* Try to grab a DMA channel */
- if (!iprtd->dma_chan) {
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
- if (!iprtd->dma_chan)
- return -EINVAL;
- }
-
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
- buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
- break;
- case SNDRV_PCM_FORMAT_S20_3LE:
- case SNDRV_PCM_FORMAT_S24_LE:
- buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
- break;
- default:
- return 0;
- }
+ ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config);
+ if (ret)
+ return ret;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- slave_config.direction = DMA_MEM_TO_DEV;
slave_config.dst_addr = dma_params->dma_addr;
- slave_config.dst_addr_width = buswidth;
slave_config.dst_maxburst = dma_params->burstsize;
} else {
- slave_config.direction = DMA_DEV_TO_MEM;
slave_config.src_addr = dma_params->dma_addr;
- slave_config.src_addr_width = buswidth;
slave_config.src_maxburst = dma_params->burstsize;
}
- ret = dmaengine_slave_config(iprtd->dma_chan, &slave_config);
+ ret = dmaengine_slave_config(chan, &slave_config);
if (ret)
return ret;
- return 0;
-}
-
-static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
- unsigned long dma_addr;
- struct dma_chan *chan;
- struct imx_pcm_dma_params *dma_params;
- int ret;
-
- dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
- ret = imx_ssi_dma_alloc(substream, params);
- if (ret)
- return ret;
- chan = iprtd->dma_chan;
-
- iprtd->size = params_buffer_bytes(params);
- iprtd->periods = params_periods(params);
- iprtd->period_bytes = params_period_bytes(params);
- iprtd->offset = 0;
- iprtd->period_time = HZ / (params_rate(params) /
- params_period_size(params));
-
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- dma_addr = runtime->dma_addr;
-
- iprtd->buf = (unsigned int *)substream->dma_buffer.area;
-
- iprtd->desc = chan->device->device_prep_dma_cyclic(chan, dma_addr,
- iprtd->period_bytes * iprtd->periods,
- iprtd->period_bytes,
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
- if (!iprtd->desc) {
- dev_err(&chan->dev->device, "cannot prepare slave dma\n");
- return -EINVAL;
- }
-
- iprtd->desc->callback = audio_dma_irq;
- iprtd->desc->callback_param = substream;
-
- return 0;
-}
-
-static int snd_imx_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-
- if (iprtd->dma_chan) {
- dma_release_channel(iprtd->dma_chan);
- iprtd->dma_chan = NULL;
- }
-
- return 0;
-}
-
-static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct imx_pcm_dma_params *dma_params;
-
- dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-
return 0;
}
-static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- dmaengine_submit(iprtd->desc);
-
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- dmaengine_terminate_all(iprtd->dma_chan);
-
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static snd_pcm_uframes_t snd_imx_pcm_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-
- pr_debug("%s: %ld %ld\n", __func__, iprtd->offset,
- bytes_to_frames(substream->runtime, iprtd->offset));
-
- return bytes_to_frames(substream->runtime, iprtd->offset);
-}
-
static struct snd_pcm_hardware snd_imx_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -254,33 +96,37 @@ static struct snd_pcm_hardware snd_imx_hardware = {
static int snd_imx_open(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct imx_pcm_dma_params *dma_params;
+ struct imx_dma_data *dma_data;
int ret;
- iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
- if (iprtd == NULL)
- return -ENOMEM;
- runtime->private_data = iprtd;
+ snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
- ret = snd_pcm_hw_constraint_integer(substream->runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0) {
- kfree(iprtd);
- return ret;
+ dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+
+ dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL);
+ dma_data->peripheral_type = IMX_DMATYPE_SSI;
+ dma_data->priority = DMA_PRIO_HIGH;
+ dma_data->dma_request = dma_params->dma;
+
+ ret = snd_dmaengine_pcm_open(substream, filter, dma_data);
+ if (ret) {
+ kfree(dma_data);
+ return 0;
}
- snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
+ snd_dmaengine_pcm_set_data(substream, dma_data);
return 0;
}
static int snd_imx_close(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
+ struct imx_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
- kfree(iprtd);
+ snd_dmaengine_pcm_close(substream);
+ kfree(dma_data);
return 0;
}
@@ -290,10 +136,8 @@ static struct snd_pcm_ops imx_pcm_ops = {
.close = snd_imx_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_imx_pcm_hw_params,
- .hw_free = snd_imx_pcm_hw_free,
- .prepare = snd_imx_pcm_prepare,
- .trigger = snd_imx_pcm_trigger,
- .pointer = snd_imx_pcm_pointer,
+ .trigger = snd_dmaengine_pcm_trigger,
+ .pointer = snd_dmaengine_pcm_pointer,
.mmap = snd_imx_pcm_mmap,
};
@@ -305,11 +149,6 @@ static struct snd_soc_platform_driver imx_soc_platform_mx2 = {
static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
{
- struct imx_ssi *ssi = platform_get_drvdata(pdev);
-
- ssi->dma_params_tx.burstsize = 6;
- ssi->dma_params_rx.burstsize = 4;
-
return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2);
}
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index 01d1f749cf02..25c623115a9f 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -233,6 +233,23 @@ static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
return 0;
}
+static int imx_ssi_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
+ struct imx_pcm_dma_params *dma_data;
+
+ /* Tx/Rx config */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dma_data = &ssi->dma_params_tx;
+ else
+ dma_data = &ssi->dma_params_rx;
+
+ snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
+
+ return 0;
+}
+
/*
* Should only be called when port is inactive (i.e. SSIEN = 0),
* although can be called multiple times by upper layers.
@@ -242,23 +259,17 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
- struct imx_pcm_dma_params *dma_data;
u32 reg, sccr;
/* Tx/Rx config */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
reg = SSI_STCCR;
- dma_data = &ssi->dma_params_tx;
- } else {
+ else
reg = SSI_SRCCR;
- dma_data = &ssi->dma_params_rx;
- }
if (ssi->flags & IMX_SSI_SYN)
reg = SSI_STCCR;
- snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
-
sccr = readl(ssi->base + reg) & ~SSI_STCCR_WL_MASK;
/* DAI data (word) size */
@@ -343,6 +354,7 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
}
static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
+ .startup = imx_ssi_startup,
.hw_params = imx_ssi_hw_params,
.set_fmt = imx_ssi_set_dai_fmt,
.set_clkdiv = imx_ssi_set_dai_clkdiv,
@@ -656,7 +668,7 @@ static int imx_ssi_probe(struct platform_device *pdev)
ssi->dma_params_rx.dma_addr = res->start + SSI_SRX0;
ssi->dma_params_tx.dma_addr = res->start + SSI_STX0;
- ssi->dma_params_tx.burstsize = 4;
+ ssi->dma_params_tx.burstsize = 6;
ssi->dma_params_rx.burstsize = 4;
res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0");
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c
index 55d2ed3df30d..80bd59c33be4 100644
--- a/sound/soc/kirkwood/kirkwood-openrd.c
+++ b/sound/soc/kirkwood/kirkwood-openrd.c
@@ -71,41 +71,41 @@ static struct snd_soc_card openrd_client = {
.num_links = ARRAY_SIZE(openrd_client_dai),
};
-static struct platform_device *openrd_client_snd_device;
-
-static int __init openrd_client_init(void)
+static int __devinit openrd_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &openrd_client;
int ret;
- if (!machine_is_openrd_client() && !machine_is_openrd_ultimate())
- return 0;
-
- openrd_client_snd_device = platform_device_alloc("soc-audio", -1);
- if (!openrd_client_snd_device)
- return -ENOMEM;
-
- platform_set_drvdata(openrd_client_snd_device,
- &openrd_client);
-
- ret = platform_device_add(openrd_client_snd_device);
- if (ret) {
- printk(KERN_ERR "%s: platform_device_add failed\n", __func__);
- platform_device_put(openrd_client_snd_device);
- }
+ card->dev = &pdev->dev;
+ ret = snd_soc_register_card(card);
+ if (ret)
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
return ret;
}
-static void __exit openrd_client_exit(void)
+static int __devexit openrd_remove(struct platform_device *pdev)
{
- platform_device_unregister(openrd_client_snd_device);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+ return 0;
}
-module_init(openrd_client_init);
-module_exit(openrd_client_exit);
+static struct platform_driver openrd_driver = {
+ .driver = {
+ .name = "openrd-client-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = openrd_probe,
+ .remove = __devexit_p(openrd_remove),
+};
+
+module_platform_driver(openrd_driver);
/* Module information */
MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
MODULE_DESCRIPTION("ALSA SoC OpenRD Client");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:soc-audio");
+MODULE_ALIAS("platform:openrd-client-audio");
diff --git a/sound/soc/kirkwood/kirkwood-t5325.c b/sound/soc/kirkwood/kirkwood-t5325.c
index b47cc4e9b746..f8983635f7ef 100644
--- a/sound/soc/kirkwood/kirkwood-t5325.c
+++ b/sound/soc/kirkwood/kirkwood-t5325.c
@@ -80,7 +80,6 @@ static struct snd_soc_dai_link t5325_dai[] = {
},
};
-
static struct snd_soc_card t5325 = {
.name = "t5325",
.owner = THIS_MODULE,
@@ -93,38 +92,40 @@ static struct snd_soc_card t5325 = {
.num_dapm_routes = ARRAY_SIZE(t5325_route),
};
-static struct platform_device *t5325_snd_device;
-
-static int __init t5325_init(void)
+static int __devinit t5325_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &t5325;
int ret;
- if (!machine_is_t5325())
- return 0;
-
- t5325_snd_device = platform_device_alloc("soc-audio", -1);
- if (!t5325_snd_device)
- return -ENOMEM;
-
- platform_set_drvdata(t5325_snd_device,
- &t5325);
-
- ret = platform_device_add(t5325_snd_device);
- if (ret) {
- printk(KERN_ERR "%s: platform_device_add failed\n", __func__);
- platform_device_put(t5325_snd_device);
- }
+ card->dev = &pdev->dev;
+ ret = snd_soc_register_card(card);
+ if (ret)
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
return ret;
}
-module_init(t5325_init);
-static void __exit t5325_exit(void)
+static int __devexit t5325_remove(struct platform_device *pdev)
{
- platform_device_unregister(t5325_snd_device);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+ return 0;
}
-module_exit(t5325_exit);
+
+static struct platform_driver t5325_driver = {
+ .driver = {
+ .name = "t5325-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = t5325_probe,
+ .remove = __devexit_p(t5325_remove),
+};
+
+module_platform_driver(t5325_driver);
MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
MODULE_DESCRIPTION("ALSA SoC t5325 audio client");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:t5325-audio");
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c
index 6f77eef0f131..2937e54da49e 100644
--- a/sound/soc/mid-x86/mfld_machine.c
+++ b/sound/soc/mid-x86/mfld_machine.c
@@ -235,7 +235,7 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
snd_soc_dapm_enable_pin(dapm, "Headphones");
snd_soc_dapm_enable_pin(dapm, "Mic");
- ret_val = snd_soc_add_controls(codec, mfld_snd_controls,
+ ret_val = snd_soc_add_codec_controls(codec, mfld_snd_controls,
ARRAY_SIZE(mfld_snd_controls));
if (ret_val) {
pr_err("soc_add_controls failed %d", ret_val);
diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig
index e4ba8d5f25fa..99a997f19bb9 100644
--- a/sound/soc/mxs/Kconfig
+++ b/sound/soc/mxs/Kconfig
@@ -1,7 +1,7 @@
menuconfig SND_MXS_SOC
tristate "SoC Audio for Freescale MXS CPUs"
depends on ARCH_MXS
- select SND_PCM
+ select SND_SOC_DMAENGINE_PCM
help
Say Y or M if you want to add support for codecs attached to
the MXS SAIF interface.
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
index 105f42a394df..6ca1f46d84a4 100644
--- a/sound/soc/mxs/mxs-pcm.c
+++ b/sound/soc/mxs/mxs-pcm.c
@@ -34,10 +34,16 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
#include <mach/dma.h>
#include "mxs-pcm.h"
+struct mxs_pcm_dma_data {
+ struct mxs_dma_data dma_data;
+ struct mxs_pcm_dma_params *dma_params;
+};
+
static struct snd_pcm_hardware snd_mxs_hardware = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -58,21 +64,10 @@ static struct snd_pcm_hardware snd_mxs_hardware = {
};
-static void audio_dma_irq(void *data)
-{
- struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
-
- iprtd->offset += iprtd->period_bytes;
- iprtd->offset %= iprtd->period_bytes * iprtd->periods;
- snd_pcm_period_elapsed(substream);
-}
-
static bool filter(struct dma_chan *chan, void *param)
{
- struct mxs_pcm_runtime_data *iprtd = param;
- struct mxs_pcm_dma_params *dma_params = iprtd->dma_params;
+ struct mxs_pcm_dma_data *pcm_dma_data = param;
+ struct mxs_pcm_dma_params *dma_params = pcm_dma_data->dma_params;
if (!mxs_dma_is_apbx(chan))
return false;
@@ -80,150 +75,51 @@ static bool filter(struct dma_chan *chan, void *param)
if (chan->chan_id != dma_params->chan_num)
return false;
- chan->private = &iprtd->dma_data;
+ chan->private = &pcm_dma_data->dma_data;
return true;
}
-static int mxs_dma_alloc(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
- dma_cap_mask_t mask;
-
- iprtd->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- iprtd->dma_data.chan_irq = iprtd->dma_params->chan_irq;
- iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
- if (!iprtd->dma_chan)
- return -EINVAL;
-
- return 0;
-}
-
static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
- unsigned long dma_addr;
- struct dma_chan *chan;
- int ret;
-
- ret = mxs_dma_alloc(substream, params);
- if (ret)
- return ret;
- chan = iprtd->dma_chan;
-
- iprtd->size = params_buffer_bytes(params);
- iprtd->periods = params_periods(params);
- iprtd->period_bytes = params_period_bytes(params);
- iprtd->offset = 0;
- iprtd->period_time = HZ / (params_rate(params) /
- params_period_size(params));
-
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- dma_addr = runtime->dma_addr;
-
- iprtd->buf = substream->dma_buffer.area;
-
- iprtd->desc = chan->device->device_prep_dma_cyclic(chan, dma_addr,
- iprtd->period_bytes * iprtd->periods,
- iprtd->period_bytes,
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
- if (!iprtd->desc) {
- dev_err(&chan->dev->device, "cannot prepare slave dma\n");
- return -EINVAL;
- }
-
- iprtd->desc->callback = audio_dma_irq;
- iprtd->desc->callback_param = substream;
-
- return 0;
-}
-
-static int snd_mxs_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
-
- if (iprtd->dma_chan) {
- dma_release_channel(iprtd->dma_chan);
- iprtd->dma_chan = NULL;
- }
-
- return 0;
-}
-
-static int snd_mxs_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- dmaengine_submit(iprtd->desc);
-
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- dmaengine_terminate_all(iprtd->dma_chan);
-
- break;
- default:
- return -EINVAL;
- }
-
return 0;
}
-static snd_pcm_uframes_t snd_mxs_pcm_pointer(
- struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
-
- return bytes_to_frames(substream->runtime, iprtd->offset);
-}
-
static int snd_mxs_open(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mxs_pcm_runtime_data *iprtd;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct mxs_pcm_dma_data *pcm_dma_data;
int ret;
- iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
- if (iprtd == NULL)
+ pcm_dma_data = kzalloc(sizeof(*pcm_dma_data), GFP_KERNEL);
+ if (pcm_dma_data == NULL)
return -ENOMEM;
- runtime->private_data = iprtd;
- ret = snd_pcm_hw_constraint_integer(substream->runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0) {
- kfree(iprtd);
+ pcm_dma_data->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+ pcm_dma_data->dma_data.chan_irq = pcm_dma_data->dma_params->chan_irq;
+
+ ret = snd_dmaengine_pcm_open(substream, filter, pcm_dma_data);
+ if (ret) {
+ kfree(pcm_dma_data);
return ret;
}
snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware);
+ snd_dmaengine_pcm_set_data(substream, pcm_dma_data);
+
return 0;
}
static int snd_mxs_close(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
+ struct mxs_pcm_dma_data *pcm_dma_data = snd_dmaengine_pcm_get_data(substream);
- kfree(iprtd);
+ snd_dmaengine_pcm_close(substream);
+ kfree(pcm_dma_data);
return 0;
}
@@ -244,9 +140,8 @@ static struct snd_pcm_ops mxs_pcm_ops = {
.close = snd_mxs_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_mxs_pcm_hw_params,
- .hw_free = snd_mxs_pcm_hw_free,
- .trigger = snd_mxs_pcm_trigger,
- .pointer = snd_mxs_pcm_pointer,
+ .trigger = snd_dmaengine_pcm_trigger,
+ .pointer = snd_dmaengine_pcm_pointer,
.mmap = snd_mxs_pcm_mmap,
};
diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h
index f55ac4f7a76a..5f01a9124b3d 100644
--- a/sound/soc/mxs/mxs-pcm.h
+++ b/sound/soc/mxs/mxs-pcm.h
@@ -19,25 +19,9 @@
#ifndef _MXS_PCM_H
#define _MXS_PCM_H
-#include <mach/dma.h>
-
struct mxs_pcm_dma_params {
int chan_irq;
int chan_num;
};
-struct mxs_pcm_runtime_data {
- int period_bytes;
- int periods;
- int dma;
- unsigned long offset;
- unsigned long size;
- void *buf;
- int period_time;
- struct dma_async_tx_descriptor *desc;
- struct dma_chan *dma_chan;
- struct mxs_dma_data dma_data;
- struct mxs_pcm_dma_params *dma_params;
-};
-
#endif
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index dccfb37a9626..12be05b16880 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -124,6 +124,8 @@ static int mxs_saif_set_clk(struct mxs_saif *saif,
*
* If MCLK is not used, we just set saif clk to 512*fs.
*/
+ clk_prepare_enable(master_saif->clk);
+
if (master_saif->mclk_in_use) {
if (mclk % 32 == 0) {
scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
@@ -133,6 +135,7 @@ static int mxs_saif_set_clk(struct mxs_saif *saif,
ret = clk_set_rate(master_saif->clk, 384 * rate);
} else {
/* SAIF MCLK should be either 32x or 48x */
+ clk_disable_unprepare(master_saif->clk);
return -EINVAL;
}
} else {
@@ -140,6 +143,8 @@ static int mxs_saif_set_clk(struct mxs_saif *saif,
scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
}
+ clk_disable_unprepare(master_saif->clk);
+
if (ret)
return ret;
@@ -625,7 +630,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
if (pdev->id >= ARRAY_SIZE(mxs_saif))
return -EINVAL;
- saif = kzalloc(sizeof(*saif), GFP_KERNEL);
+ saif = devm_kzalloc(&pdev->dev, sizeof(*saif), GFP_KERNEL);
if (!saif)
return -ENOMEM;
@@ -650,29 +655,16 @@ static int mxs_saif_probe(struct platform_device *pdev)
ret = PTR_ERR(saif->clk);
dev_err(&pdev->dev, "Cannot get the clock: %d\n",
ret);
- goto failed_clk;
+ return ret;
}
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!iores) {
- ret = -ENODEV;
- dev_err(&pdev->dev, "failed to get io resource: %d\n",
- ret);
- goto failed_get_resource;
- }
-
- if (!request_mem_region(iores->start, resource_size(iores),
- "mxs-saif")) {
- dev_err(&pdev->dev, "request_mem_region failed\n");
- ret = -EBUSY;
- goto failed_get_resource;
- }
- saif->base = ioremap(iores->start, resource_size(iores));
+ saif->base = devm_request_and_ioremap(&pdev->dev, iores);
if (!saif->base) {
dev_err(&pdev->dev, "ioremap failed\n");
ret = -ENODEV;
- goto failed_ioremap;
+ goto failed_get_resource;
}
dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -680,7 +672,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
ret = -ENODEV;
dev_err(&pdev->dev, "failed to get dma resource: %d\n",
ret);
- goto failed_ioremap;
+ goto failed_get_resource;
}
saif->dma_param.chan_num = dmares->start;
@@ -689,14 +681,15 @@ static int mxs_saif_probe(struct platform_device *pdev)
ret = saif->irq;
dev_err(&pdev->dev, "failed to get irq resource: %d\n",
ret);
- goto failed_get_irq1;
+ goto failed_get_resource;
}
saif->dev = &pdev->dev;
- ret = request_irq(saif->irq, mxs_saif_irq, 0, "mxs-saif", saif);
+ ret = devm_request_irq(&pdev->dev, saif->irq, mxs_saif_irq, 0,
+ "mxs-saif", saif);
if (ret) {
dev_err(&pdev->dev, "failed to request irq\n");
- goto failed_get_irq1;
+ goto failed_get_resource;
}
saif->dma_param.chan_irq = platform_get_irq(pdev, 1);
@@ -704,7 +697,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
ret = saif->dma_param.chan_irq;
dev_err(&pdev->dev, "failed to get dma irq resource: %d\n",
ret);
- goto failed_get_irq2;
+ goto failed_get_resource;
}
platform_set_drvdata(pdev, saif);
@@ -712,7 +705,7 @@ static int mxs_saif_probe(struct platform_device *pdev)
ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai);
if (ret) {
dev_err(&pdev->dev, "register DAI failed\n");
- goto failed_register;
+ goto failed_get_resource;
}
saif->soc_platform_pdev = platform_device_alloc(
@@ -735,36 +728,19 @@ failed_pdev_add:
platform_device_put(saif->soc_platform_pdev);
failed_pdev_alloc:
snd_soc_unregister_dai(&pdev->dev);
-failed_register:
-failed_get_irq2:
- free_irq(saif->irq, saif);
-failed_get_irq1:
- iounmap(saif->base);
-failed_ioremap:
- release_mem_region(iores->start, resource_size(iores));
failed_get_resource:
clk_put(saif->clk);
-failed_clk:
- kfree(saif);
return ret;
}
static int __devexit mxs_saif_remove(struct platform_device *pdev)
{
- struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct mxs_saif *saif = platform_get_drvdata(pdev);
platform_device_unregister(saif->soc_platform_pdev);
-
snd_soc_unregister_dai(&pdev->dev);
-
- iounmap(saif->base);
- release_mem_region(res->start, resource_size(res));
- free_irq(saif->irq, saif);
-
clk_put(saif->clk);
- kfree(saif);
return 0;
}
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index a67f4370bc9f..78563bbbbf01 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -570,7 +570,7 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_disable_pin(dapm, "AGCOUT");
/* Add virtual switch */
- ret = snd_soc_add_controls(codec, ams_delta_audio_controls,
+ ret = snd_soc_add_codec_controls(codec, ams_delta_audio_controls,
ARRAY_SIZE(ams_delta_audio_controls));
if (ret)
dev_warn(card->dev,
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index 597be412f1e4..c292bf0fd19c 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -55,9 +55,8 @@ static int n810_spk_func;
static int n810_jack_func;
static int n810_dmic_func;
-static void n810_ext_control(struct snd_soc_codec *codec)
+static void n810_ext_control(struct snd_soc_dapm_context *dapm)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
int hp = 0, line1l = 0;
switch (n810_jack_func) {
@@ -102,7 +101,7 @@ static int n810_startup(struct snd_pcm_substream *substream)
snd_pcm_hw_constraint_minmax(runtime,
SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
- n810_ext_control(codec);
+ n810_ext_control(&codec->dapm);
return clk_enable(sys_clkout2);
}
@@ -142,13 +141,13 @@ static int n810_get_spk(struct snd_kcontrol *kcontrol,
static int n810_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (n810_spk_func == ucontrol->value.integer.value[0])
return 0;
n810_spk_func = ucontrol->value.integer.value[0];
- n810_ext_control(codec);
+ n810_ext_control(&card->dapm);
return 1;
}
@@ -164,13 +163,13 @@ static int n810_get_jack(struct snd_kcontrol *kcontrol,
static int n810_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (n810_jack_func == ucontrol->value.integer.value[0])
return 0;
n810_jack_func = ucontrol->value.integer.value[0];
- n810_ext_control(codec);
+ n810_ext_control(&card->dapm);
return 1;
}
@@ -186,13 +185,13 @@ static int n810_get_input(struct snd_kcontrol *kcontrol,
static int n810_set_input(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (n810_dmic_func == ucontrol->value.integer.value[0])
return 0;
n810_dmic_func = ucontrol->value.integer.value[0];
- n810_ext_control(codec);
+ n810_ext_control(&card->dapm);
return 1;
}
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 017371913ec3..1287b870f221 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -744,17 +744,17 @@ static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = {
omap_mcbsp3_set_st_ch1_volume),
};
-int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id)
+int omap_mcbsp_st_add_controls(struct snd_soc_dai *dai)
{
if (!cpu_is_omap34xx())
return -ENODEV;
- switch (mcbsp_id) {
+ switch (dai->id) {
case 1: /* McBSP 2 */
- return snd_soc_add_controls(codec, omap_mcbsp2_st_controls,
+ return snd_soc_add_dai_controls(dai, omap_mcbsp2_st_controls,
ARRAY_SIZE(omap_mcbsp2_st_controls));
case 2: /* McBSP 3 */
- return snd_soc_add_controls(codec, omap_mcbsp3_st_controls,
+ return snd_soc_add_dai_controls(dai, omap_mcbsp3_st_controls,
ARRAY_SIZE(omap_mcbsp3_st_controls));
default:
break;
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
index 65cde9d3807b..476fe2add703 100644
--- a/sound/soc/omap/omap-mcbsp.h
+++ b/sound/soc/omap/omap-mcbsp.h
@@ -59,6 +59,6 @@ enum omap_mcbsp_div {
#define NUM_LINKS 5
#endif
-int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id);
+int omap_mcbsp_st_add_controls(struct snd_soc_dai *dai);
#endif
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index fada6ef43eea..58936c730a87 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -59,9 +59,8 @@ static int rx51_spk_func;
static int rx51_dmic_func;
static int rx51_jack_func;
-static void rx51_ext_control(struct snd_soc_codec *codec)
+static void rx51_ext_control(struct snd_soc_dapm_context *dapm)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
int hp = 0, hs = 0, tvout = 0;
switch (rx51_jack_func) {
@@ -102,11 +101,11 @@ static int rx51_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_card *card = rtd->card;
snd_pcm_hw_constraint_minmax(runtime,
SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
- rx51_ext_control(codec);
+ rx51_ext_control(&card->dapm);
return 0;
}
@@ -138,13 +137,13 @@ static int rx51_get_spk(struct snd_kcontrol *kcontrol,
static int rx51_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (rx51_spk_func == ucontrol->value.integer.value[0])
return 0;
rx51_spk_func = ucontrol->value.integer.value[0];
- rx51_ext_control(codec);
+ rx51_ext_control(&card->dapm);
return 1;
}
@@ -184,13 +183,13 @@ static int rx51_get_input(struct snd_kcontrol *kcontrol,
static int rx51_set_input(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (rx51_dmic_func == ucontrol->value.integer.value[0])
return 0;
rx51_dmic_func = ucontrol->value.integer.value[0];
- rx51_ext_control(codec);
+ rx51_ext_control(&card->dapm);
return 1;
}
@@ -206,13 +205,13 @@ static int rx51_get_jack(struct snd_kcontrol *kcontrol,
static int rx51_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (rx51_jack_func == ucontrol->value.integer.value[0])
return 0;
rx51_jack_func = ucontrol->value.integer.value[0];
- rx51_ext_control(codec);
+ rx51_ext_control(&card->dapm);
return 1;
}
@@ -297,7 +296,7 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "LINE1R");
/* Add RX-51 specific controls */
- err = snd_soc_add_controls(codec, aic34_rx51_controls,
+ err = snd_soc_add_card_controls(rtd->card, aic34_rx51_controls,
ARRAY_SIZE(aic34_rx51_controls));
if (err < 0)
return err;
@@ -314,7 +313,7 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
return err;
snd_soc_limit_volume(codec, "TPA6130A2 Headphone Playback Volume", 42);
- err = omap_mcbsp_st_add_controls(codec, 1);
+ err = omap_mcbsp_st_add_controls(rtd->cpu_dai);
if (err < 0)
return err;
@@ -335,7 +334,7 @@ static int rx51_aic34b_init(struct snd_soc_dapm_context *dapm)
{
int err;
- err = snd_soc_add_controls(dapm->codec, aic34_rx51_controlsb,
+ err = snd_soc_add_card_controls(dapm->card, aic34_rx51_controlsb,
ARRAY_SIZE(aic34_rx51_controlsb));
if (err < 0)
return err;
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index bc21944851c4..863367ad89ce 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -45,10 +45,8 @@
static int corgi_jack_func;
static int corgi_spk_func;
-static void corgi_ext_control(struct snd_soc_codec *codec)
+static void corgi_ext_control(struct snd_soc_dapm_context *dapm)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
/* set up jack connection */
switch (corgi_jack_func) {
case CORGI_HP:
@@ -104,7 +102,7 @@ static int corgi_startup(struct snd_pcm_substream *substream)
mutex_lock(&codec->mutex);
/* check the jack status at stream startup */
- corgi_ext_control(codec);
+ corgi_ext_control(&codec->dapm);
mutex_unlock(&codec->mutex);
@@ -173,13 +171,13 @@ static int corgi_get_jack(struct snd_kcontrol *kcontrol,
static int corgi_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (corgi_jack_func == ucontrol->value.integer.value[0])
return 0;
corgi_jack_func = ucontrol->value.integer.value[0];
- corgi_ext_control(codec);
+ corgi_ext_control(&card->dapm);
return 1;
}
@@ -193,13 +191,13 @@ static int corgi_get_spk(struct snd_kcontrol *kcontrol,
static int corgi_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (corgi_spk_func == ucontrol->value.integer.value[0])
return 0;
corgi_spk_func = ucontrol->value.integer.value[0];
- corgi_ext_control(codec);
+ corgi_ext_control(&card->dapm);
return 1;
}
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c
index 3f7a8ecb9720..aace19e0fe2c 100644
--- a/sound/soc/pxa/magician.c
+++ b/sound/soc/pxa/magician.c
@@ -411,7 +411,7 @@ static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "VINR");
/* Add magician specific controls */
- err = snd_soc_add_controls(codec, uda1380_magician_controls,
+ err = snd_soc_add_codec_controls(codec, uda1380_magician_controls,
ARRAY_SIZE(uda1380_magician_controls));
if (err < 0)
return err;
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index fd0ed10c6fe7..d2cc81735036 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -43,10 +43,8 @@
static int poodle_jack_func;
static int poodle_spk_func;
-static void poodle_ext_control(struct snd_soc_codec *codec)
+static void poodle_ext_control(struct snd_soc_dapm_context *dapm)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
/* set up jack connection */
if (poodle_jack_func == POODLE_HP) {
/* set = unmute headphone */
@@ -81,7 +79,7 @@ static int poodle_startup(struct snd_pcm_substream *substream)
mutex_lock(&codec->mutex);
/* check the jack status at stream startup */
- poodle_ext_control(codec);
+ poodle_ext_control(&codec->dapm);
mutex_unlock(&codec->mutex);
@@ -152,13 +150,13 @@ static int poodle_get_jack(struct snd_kcontrol *kcontrol,
static int poodle_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (poodle_jack_func == ucontrol->value.integer.value[0])
return 0;
poodle_jack_func = ucontrol->value.integer.value[0];
- poodle_ext_control(codec);
+ poodle_ext_control(&card->dapm);
return 1;
}
@@ -172,13 +170,13 @@ static int poodle_get_spk(struct snd_kcontrol *kcontrol,
static int poodle_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (poodle_spk_func == ucontrol->value.integer.value[0])
return 0;
poodle_spk_func = ucontrol->value.integer.value[0];
- poodle_ext_control(codec);
+ poodle_ext_control(&card->dapm);
return 1;
}
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 837ff341fd6d..4800d5fe568d 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -103,7 +103,7 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
#define pxa2xx_ac97_resume NULL
#endif
-static int pxa2xx_ac97_probe(struct snd_soc_dai *dai)
+static int __devinit pxa2xx_ac97_probe(struct snd_soc_dai *dai)
{
return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev));
}
@@ -179,7 +179,7 @@ static const struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = {
* There is only 1 physical AC97 interface for pxa2xx, but it
* has extra fifo's that can be used for aux DACs and ADCs.
*/
-static struct snd_soc_dai_driver pxa_ac97_dai[] = {
+static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = {
{
.name = "pxa2xx-ac97",
.ac97_control = 1,
@@ -244,13 +244,13 @@ static __devinit int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
* driver to do interesting things with the clocking to get us up
* and running.
*/
- return snd_soc_register_dais(&pdev->dev, pxa_ac97_dai,
- ARRAY_SIZE(pxa_ac97_dai));
+ return snd_soc_register_dais(&pdev->dev, pxa_ac97_dai_driver,
+ ARRAY_SIZE(pxa_ac97_dai_driver));
}
static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev)
{
- snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai));
+ snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai_driver));
return 0;
}
diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c
index ba1545188ec6..083706595495 100644
--- a/sound/soc/pxa/raumfeld.c
+++ b/sound/soc/pxa/raumfeld.c
@@ -232,7 +232,7 @@ static struct snd_soc_ops raumfeld_ak4104_ops = {
.cpu_dai_name = "pxa-ssp-dai.0", \
.platform_name = "pxa-pcm-audio", \
.codec_dai_name = "cs4270-hifi", \
- .codec_name = "cs4270-codec.0-0048", \
+ .codec_name = "cs4270.0-0048", \
.ops = &raumfeld_cs4270_ops, \
}
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index 90c5245c4742..fc052d8247ff 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -44,10 +44,8 @@ static int spitz_jack_func;
static int spitz_spk_func;
static int spitz_mic_gpio;
-static void spitz_ext_control(struct snd_soc_codec *codec)
+static void spitz_ext_control(struct snd_soc_dapm_context *dapm)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
if (spitz_spk_func == SPITZ_SPK_ON)
snd_soc_dapm_enable_pin(dapm, "Ext Spk");
else
@@ -113,7 +111,7 @@ static int spitz_startup(struct snd_pcm_substream *substream)
mutex_lock(&codec->mutex);
/* check the jack status at stream startup */
- spitz_ext_control(codec);
+ spitz_ext_control(&codec->dapm);
mutex_unlock(&codec->mutex);
@@ -173,13 +171,13 @@ static int spitz_get_jack(struct snd_kcontrol *kcontrol,
static int spitz_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (spitz_jack_func == ucontrol->value.integer.value[0])
return 0;
spitz_jack_func = ucontrol->value.integer.value[0];
- spitz_ext_control(codec);
+ spitz_ext_control(&card->dapm);
return 1;
}
@@ -193,13 +191,13 @@ static int spitz_get_spk(struct snd_kcontrol *kcontrol,
static int spitz_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (spitz_spk_func == ucontrol->value.integer.value[0])
return 0;
spitz_spk_func = ucontrol->value.integer.value[0];
- spitz_ext_control(codec);
+ spitz_ext_control(&card->dapm);
return 1;
}
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index 564ef08a89f2..2aec63f3706a 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -197,7 +197,7 @@ static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "MONOOUT");
/* add tosa specific controls */
- err = snd_soc_add_controls(codec, tosa_controls,
+ err = snd_soc_add_codec_controls(codec, tosa_controls,
ARRAY_SIZE(tosa_controls));
if (err < 0)
return err;
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index 7b9bf93e3701..3d04c1fa6781 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -4,7 +4,7 @@
* Evolved from s3c2443-ac97.c
*
* Copyright (c) 2010 Samsung Electronics Co. Ltd
- * Author: Jaswinder Singh <jassi.brar@samsung.com>
+ * Author: Jaswinder Singh <jassisinghbrar@gmail.com>
* Credits: Graeme Gregory, Sean Choi
*
* This program is free software; you can redistribute it and/or modify
@@ -511,7 +511,7 @@ static struct platform_driver s3c_ac97_driver = {
module_platform_driver(s3c_ac97_driver);
-MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
+MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
MODULE_DESCRIPTION("AC97 driver for the Samsung SoC");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:samsung-ac97");
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 87a874dc7a35..6553b19c70c7 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -3,7 +3,7 @@
* ALSA SoC Audio Layer - Samsung I2S Controller driver
*
* Copyright (c) 2010 Samsung Electronics Co. Ltd.
- * Jaswinder Singh <jassi.brar@samsung.com>
+ * Jaswinder Singh <jassisinghbrar@gmail.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
@@ -761,15 +761,13 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
local_irq_save(flags);
- if (capture)
+ if (capture) {
i2s_rxctrl(i2s, 0);
- else
- i2s_txctrl(i2s, 0);
-
- if (capture)
i2s_fifo(i2s, FIC_RXFLUSH);
- else
+ } else {
+ i2s_txctrl(i2s, 0);
i2s_fifo(i2s, FIC_TXFLUSH);
+ }
local_irq_restore(flags);
break;
@@ -1143,7 +1141,7 @@ static struct platform_driver samsung_i2s_driver = {
module_platform_driver(samsung_i2s_driver);
/* Module information */
-MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
+MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
MODULE_DESCRIPTION("Samsung I2S Interface");
MODULE_ALIAS("platform:samsung-i2s");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/i2s.h b/sound/soc/samsung/i2s.h
index 8e15f6a616d1..d420a7ca56ca 100644
--- a/sound/soc/samsung/i2s.h
+++ b/sound/soc/samsung/i2s.h
@@ -3,7 +3,7 @@
* ALSA SoC Audio Layer - Samsung I2S Controller driver
*
* Copyright (c) 2010 Samsung Electronics Co. Ltd.
- * Jaswinder Singh <jassi.brar@samsung.com>
+ * Jaswinder Singh <jassisinghbrar@gmail.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
diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
index 9dd818bde06f..e7416851bf7d 100644
--- a/sound/soc/samsung/littlemill.c
+++ b/sound/soc/samsung/littlemill.c
@@ -189,6 +189,9 @@ static int littlemill_late_probe(struct snd_soc_card *card)
/* This will check device compatibility itself */
wm8958_mic_detect(codec, &littlemill_headset, NULL, NULL);
+ /* As will this */
+ wm8994_mic_detect(codec, &littlemill_headset, 1);
+
return 0;
}
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c
index 7ac0ba2025c3..24bdb321269a 100644
--- a/sound/soc/samsung/neo1973_wm8753.c
+++ b/sound/soc/samsung/neo1973_wm8753.c
@@ -230,8 +230,6 @@ static const struct snd_kcontrol_new neo1973_wm8753_controls[] = {
/* GTA02 specific routes and controls */
-#ifdef CONFIG_MACH_NEO1973_GTA02
-
static int gta02_speaker_enabled;
static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
@@ -298,7 +296,7 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
if (ret)
return ret;
- ret = snd_soc_add_controls(codec, neo1973_gta02_wm8753_controls,
+ ret = snd_soc_add_card_controls(codec->card, neo1973_gta02_wm8753_controls,
ARRAY_SIZE(neo1973_gta02_wm8753_controls));
if (ret)
return ret;
@@ -311,10 +309,6 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
return 0;
}
-#else
-static int neo1973_gta02_wm8753_init(struct snd_soc_code *codec) { return 0; }
-#endif
-
static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
@@ -322,10 +316,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
int ret;
/* set up NC codec pins */
- if (machine_is_neo1973_gta01()) {
- snd_soc_dapm_nc_pin(dapm, "LOUT2");
- snd_soc_dapm_nc_pin(dapm, "ROUT2");
- }
snd_soc_dapm_nc_pin(dapm, "OUT3");
snd_soc_dapm_nc_pin(dapm, "OUT4");
snd_soc_dapm_nc_pin(dapm, "LINE1");
@@ -338,7 +328,7 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
return ret;
/* add neo1973 specific controls */
- ret = snd_soc_add_controls(codec, neo1973_wm8753_controls,
+ ret = snd_soc_add_card_controls(rtd->card, neo1973_wm8753_controls,
ARRAY_SIZE(neo1973_wm8753_controls));
if (ret)
return ret;
@@ -370,50 +360,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}
-/* GTA01 specific controls */
-
-#ifdef CONFIG_MACH_NEO1973_GTA01
-
-static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = {
- {"Amp IN", NULL, "ROUT1"},
- {"Amp IN", NULL, "LOUT1"},
-
- {"Handset Spk", NULL, "Amp EP"},
- {"Stereo Out", NULL, "Amp LS"},
- {"Headphone", NULL, "Amp HP"},
-};
-
-static const struct snd_soc_dapm_widget neo1973_lm4857_dapm_widgets[] = {
- SND_SOC_DAPM_SPK("Handset Spk", NULL),
- SND_SOC_DAPM_SPK("Stereo Out", NULL),
- SND_SOC_DAPM_HP("Headphone", NULL),
-};
-
-static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm)
-{
- int ret;
-
- ret = snd_soc_dapm_new_controls(dapm, neo1973_lm4857_dapm_widgets,
- ARRAY_SIZE(neo1973_lm4857_dapm_widgets));
- if (ret)
- return ret;
-
- ret = snd_soc_dapm_add_routes(dapm, neo1973_lm4857_routes,
- ARRAY_SIZE(neo1973_lm4857_routes));
- if (ret)
- return ret;
-
- snd_soc_dapm_ignore_suspend(dapm, "Stereo Out");
- snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
- snd_soc_dapm_ignore_suspend(dapm, "Headphone");
-
- return 0;
-}
-
-#else
-static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) { return 0; };
-#endif
-
static struct snd_soc_dai_link neo1973_dai[] = {
{ /* Hifi Playback - for similatious use with voice below */
.name = "WM8753",
@@ -440,11 +386,6 @@ static struct snd_soc_aux_dev neo1973_aux_devs[] = {
.name = "dfbmcs320",
.codec_name = "dfbmcs320.0",
},
- {
- .name = "lm4857",
- .codec_name = "lm4857.0-007c",
- .init = neo1973_lm4857_init,
- },
};
static struct snd_soc_codec_conf neo1973_codec_conf[] = {
@@ -454,14 +395,10 @@ static struct snd_soc_codec_conf neo1973_codec_conf[] = {
},
};
-#ifdef CONFIG_MACH_NEO1973_GTA02
static const struct gpio neo1973_gta02_gpios[] = {
{ GTA02_GPIO_HP_IN, GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" },
{ GTA02_GPIO_AMP_SHUT, GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" },
};
-#else
-static const struct gpio neo1973_gta02_gpios[] = {};
-#endif
static struct snd_soc_card neo1973 = {
.name = "neo1973",
@@ -480,7 +417,7 @@ static int __init neo1973_init(void)
{
int ret;
- if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02())
+ if (!machine_is_neo1973_gta02())
return -ENODEV;
if (machine_is_neo1973_gta02()) {
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index 56780206c000..b7b2a1f91425 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -3,7 +3,7 @@
* ALSA SoC Audio Layer - S3C PCM-Controller driver
*
* Copyright (c) 2009 Samsung Electronics Co. Ltd
- * Author: Jaswinder Singh <jassi.brar@samsung.com>
+ * Author: Jaswinder Singh <jassisinghbrar@gmail.com>
* based upon I2S drivers by Ben Dooks.
*
* This program is free software; you can redistribute it and/or modify
@@ -639,7 +639,7 @@ static struct platform_driver s3c_pcm_driver = {
module_platform_driver(s3c_pcm_driver);
/* Module information */
-MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
+MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
MODULE_DESCRIPTION("S3C PCM Controller Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:samsung-pcm");
diff --git a/sound/soc/samsung/s3c24xx_simtec.c b/sound/soc/samsung/s3c24xx_simtec.c
index a253bcc1646a..656d5afe4ca9 100644
--- a/sound/soc/samsung/s3c24xx_simtec.c
+++ b/sound/soc/samsung/s3c24xx_simtec.c
@@ -134,18 +134,18 @@ static const struct snd_kcontrol_new amp_unmute_controls[] = {
void simtec_audio_init(struct snd_soc_pcm_runtime *rtd)
{
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_card *card = rtd->card;
if (pdata->amp_gpio > 0) {
pr_debug("%s: adding amp routes\n", __func__);
- snd_soc_add_controls(codec, amp_unmute_controls,
+ snd_soc_add_card_controls(card, amp_unmute_controls,
ARRAY_SIZE(amp_unmute_controls));
}
if (pdata->amp_gain[0] > 0) {
pr_debug("%s: adding amp controls\n", __func__);
- snd_soc_add_controls(codec, amp_gain_controls,
+ snd_soc_add_card_controls(card, amp_gain_controls,
ARRAY_SIZE(amp_gain_controls));
}
}
diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c
index bff8758e7f20..ade2809cf393 100644
--- a/sound/soc/samsung/smdk_wm8580.c
+++ b/sound/soc/samsung/smdk_wm8580.c
@@ -2,7 +2,7 @@
* smdk_wm8580.c
*
* Copyright (c) 2009 Samsung Electronics Co. Ltd
- * Author: Jaswinder Singh <jassi.brar@samsung.com>
+ * Author: Jaswinder Singh <jassisinghbrar@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -253,6 +253,6 @@ static void __exit smdk_audio_exit(void)
}
module_exit(smdk_audio_exit);
-MODULE_AUTHOR("Jaswinder Singh, jassi.brar@samsung.com");
+MODULE_AUTHOR("Jaswinder Singh, jassisinghbrar@gmail.com");
MODULE_DESCRIPTION("ALSA SoC SMDK WM8580");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/smdk_wm9713.c b/sound/soc/samsung/smdk_wm9713.c
index 8e26a730fcdc..55b2ca7f3290 100644
--- a/sound/soc/samsung/smdk_wm9713.c
+++ b/sound/soc/samsung/smdk_wm9713.c
@@ -2,7 +2,7 @@
* smdk_wm9713.c -- SoC audio for SMDK
*
* Copyright 2010 Samsung Electronics Co. Ltd.
- * Author: Jaswinder Singh Brar <jassi.brar@samsung.com>
+ * Author: Jaswinder Singh Brar <jassisinghbrar@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -103,6 +103,6 @@ module_init(smdk_init);
module_exit(smdk_exit);
/* Module information */
-MODULE_AUTHOR("Jaswinder Singh Brar, jassi.brar@samsung.com");
+MODULE_AUTHOR("Jaswinder Singh Brar, jassisinghbrar@gmail.com");
MODULE_DESCRIPTION("ALSA SoC SMDK+WM9713");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index db6c89a28bda..378cc5b056d7 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -13,8 +13,11 @@
*/
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/io.h>
+#include <linux/scatterlist.h>
+#include <linux/sh_dma.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <sound/soc.h>
@@ -53,6 +56,7 @@
/* DO_FMT */
/* DI_FMT */
+#define CR_BWS_MASK (0x3 << 20) /* FSI2 */
#define CR_BWS_24 (0x0 << 20) /* FSI2 */
#define CR_BWS_16 (0x1 << 20) /* FSI2 */
#define CR_BWS_20 (0x2 << 20) /* FSI2 */
@@ -68,6 +72,15 @@
#define CR_TDM (0x4 << 4)
#define CR_TDM_D (0x5 << 4)
+/* OUT_DMAC */
+/* IN_DMAC */
+#define VDMD_MASK (0x3 << 4)
+#define VDMD_FRONT (0x0 << 4) /* Package in front */
+#define VDMD_BACK (0x1 << 4) /* Package in back */
+#define VDMD_STREAM (0x2 << 4) /* Stream mode(16bit * 2) */
+
+#define DMA_ON (0x1 << 0)
+
/* DOFF_CTL */
/* DIFF_CTL */
#define IRQ_HALF 0x00100000
@@ -116,7 +129,7 @@
#define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
-typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int enable);
+typedef int (*set_rate_func)(struct device *dev, int rate, int enable);
/*
* FSI driver use below type name for variable
@@ -159,22 +172,41 @@ typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int ena
* struct
*/
+struct fsi_stream_handler;
struct fsi_stream {
- struct snd_pcm_substream *substream;
+ /*
+ * these are initialized by fsi_stream_init()
+ */
+ struct snd_pcm_substream *substream;
int fifo_sample_capa; /* sample capacity of FSI FIFO */
int buff_sample_capa; /* sample capacity of ALSA buffer */
int buff_sample_pos; /* sample position of ALSA buffer */
int period_samples; /* sample number / 1 period */
int period_pos; /* current period position */
-
+ int sample_width; /* sample width */
int uerr_num;
int oerr_num;
+
+ /*
+ * thse are initialized by fsi_handler_init()
+ */
+ struct fsi_stream_handler *handler;
+ struct fsi_priv *priv;
+
+ /*
+ * these are for DMAEngine
+ */
+ struct dma_chan *chan;
+ struct sh_dmae_slave slave; /* see fsi_handler_init() */
+ struct tasklet_struct tasklet;
+ dma_addr_t dma;
};
struct fsi_priv {
void __iomem *base;
struct fsi_master *master;
+ struct sh_fsi_port_info *info;
struct fsi_stream playback;
struct fsi_stream capture;
@@ -189,6 +221,20 @@ struct fsi_priv {
long rate;
};
+struct fsi_stream_handler {
+ int (*init)(struct fsi_priv *fsi, struct fsi_stream *io);
+ int (*quit)(struct fsi_priv *fsi, struct fsi_stream *io);
+ int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io);
+ int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io);
+ int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io);
+ void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io,
+ int enable);
+};
+#define fsi_stream_handler_call(io, func, args...) \
+ (!(io) ? -ENODEV : \
+ !((io)->handler->func) ? 0 : \
+ (io)->handler->func(args))
+
struct fsi_core {
int ver;
@@ -205,10 +251,11 @@ struct fsi_master {
struct fsi_priv fsia;
struct fsi_priv fsib;
struct fsi_core *core;
- struct sh_fsi_platform_info *info;
spinlock_t lock;
};
+static int fsi_stream_is_play(struct fsi_priv *fsi, struct fsi_stream *io);
+
/*
* basic read write function
*/
@@ -295,6 +342,11 @@ static int fsi_is_spdif(struct fsi_priv *fsi)
return fsi->spdif;
}
+static int fsi_is_play(struct snd_pcm_substream *substream)
+{
+ return substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+}
+
static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -317,44 +369,25 @@ static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream)
return fsi_get_priv_frm_dai(fsi_get_dai(substream));
}
-static set_rate_func fsi_get_info_set_rate(struct fsi_master *master)
+static set_rate_func fsi_get_info_set_rate(struct fsi_priv *fsi)
{
- if (!master->info)
+ if (!fsi->info)
return NULL;
- return master->info->set_rate;
+ return fsi->info->set_rate;
}
static u32 fsi_get_info_flags(struct fsi_priv *fsi)
{
- int is_porta = fsi_is_port_a(fsi);
- struct fsi_master *master = fsi_get_master(fsi);
-
- if (!master->info)
+ if (!fsi->info)
return 0;
- return is_porta ? master->info->porta_flags :
- master->info->portb_flags;
-}
-
-static inline int fsi_stream_is_play(int stream)
-{
- return stream == SNDRV_PCM_STREAM_PLAYBACK;
+ return fsi->info->flags;
}
-static inline int fsi_is_play(struct snd_pcm_substream *substream)
-{
- return fsi_stream_is_play(substream->stream);
-}
-
-static inline struct fsi_stream *fsi_get_stream(struct fsi_priv *fsi,
- int is_play)
-{
- return is_play ? &fsi->playback : &fsi->capture;
-}
-
-static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play)
+static u32 fsi_get_port_shift(struct fsi_priv *fsi, struct fsi_stream *io)
{
+ int is_play = fsi_stream_is_play(fsi, io);
int is_porta = fsi_is_port_a(fsi);
u32 shift;
@@ -376,26 +409,81 @@ static int fsi_sample2frame(struct fsi_priv *fsi, int samples)
return samples / fsi->chan_num;
}
+static int fsi_get_current_fifo_samples(struct fsi_priv *fsi,
+ struct fsi_stream *io)
+{
+ int is_play = fsi_stream_is_play(fsi, io);
+ u32 status;
+ int frames;
+
+ status = is_play ?
+ fsi_reg_read(fsi, DOFF_ST) :
+ fsi_reg_read(fsi, DIFF_ST);
+
+ frames = 0x1ff & (status >> 8);
+
+ return fsi_frame2sample(fsi, frames);
+}
+
+static void fsi_count_fifo_err(struct fsi_priv *fsi)
+{
+ u32 ostatus = fsi_reg_read(fsi, DOFF_ST);
+ u32 istatus = fsi_reg_read(fsi, DIFF_ST);
+
+ if (ostatus & ERR_OVER)
+ fsi->playback.oerr_num++;
+
+ if (ostatus & ERR_UNDER)
+ fsi->playback.uerr_num++;
+
+ if (istatus & ERR_OVER)
+ fsi->capture.oerr_num++;
+
+ if (istatus & ERR_UNDER)
+ fsi->capture.uerr_num++;
+
+ fsi_reg_write(fsi, DOFF_ST, 0);
+ fsi_reg_write(fsi, DIFF_ST, 0);
+}
+
+/*
+ * fsi_stream_xx() function
+ */
+static inline int fsi_stream_is_play(struct fsi_priv *fsi,
+ struct fsi_stream *io)
+{
+ return &fsi->playback == io;
+}
+
+static inline struct fsi_stream *fsi_stream_get(struct fsi_priv *fsi,
+ struct snd_pcm_substream *substream)
+{
+ return fsi_is_play(substream) ? &fsi->playback : &fsi->capture;
+}
+
static int fsi_stream_is_working(struct fsi_priv *fsi,
- int is_play)
+ struct fsi_stream *io)
{
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
struct fsi_master *master = fsi_get_master(fsi);
unsigned long flags;
int ret;
spin_lock_irqsave(&master->lock, flags);
- ret = !!io->substream;
+ ret = !!(io->substream && io->substream->runtime);
spin_unlock_irqrestore(&master->lock, flags);
return ret;
}
-static void fsi_stream_push(struct fsi_priv *fsi,
- int is_play,
+static struct fsi_priv *fsi_stream_to_priv(struct fsi_stream *io)
+{
+ return io->priv;
+}
+
+static void fsi_stream_init(struct fsi_priv *fsi,
+ struct fsi_stream *io,
struct snd_pcm_substream *substream)
{
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsi_master *master = fsi_get_master(fsi);
unsigned long flags;
@@ -406,14 +494,15 @@ static void fsi_stream_push(struct fsi_priv *fsi,
io->buff_sample_pos = 0;
io->period_samples = fsi_frame2sample(fsi, runtime->period_size);
io->period_pos = 0;
+ io->sample_width = samples_to_bytes(runtime, 1);
io->oerr_num = -1; /* ignore 1st err */
io->uerr_num = -1; /* ignore 1st err */
+ fsi_stream_handler_call(io, init, fsi, io);
spin_unlock_irqrestore(&master->lock, flags);
}
-static void fsi_stream_pop(struct fsi_priv *fsi, int is_play)
+static void fsi_stream_quit(struct fsi_priv *fsi, struct fsi_stream *io)
{
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
struct snd_soc_dai *dai = fsi_get_dai(io->substream);
struct fsi_master *master = fsi_get_master(fsi);
unsigned long flags;
@@ -426,127 +515,87 @@ static void fsi_stream_pop(struct fsi_priv *fsi, int is_play)
if (io->uerr_num > 0)
dev_err(dai->dev, "under_run = %d\n", io->uerr_num);
+ fsi_stream_handler_call(io, quit, fsi, io);
io->substream = NULL;
io->buff_sample_capa = 0;
io->buff_sample_pos = 0;
io->period_samples = 0;
io->period_pos = 0;
+ io->sample_width = 0;
io->oerr_num = 0;
io->uerr_num = 0;
spin_unlock_irqrestore(&master->lock, flags);
}
-static int fsi_get_current_fifo_samples(struct fsi_priv *fsi, int is_play)
+static int fsi_stream_transfer(struct fsi_stream *io)
{
- u32 status;
- int frames;
+ struct fsi_priv *fsi = fsi_stream_to_priv(io);
+ if (!fsi)
+ return -EIO;
- status = is_play ?
- fsi_reg_read(fsi, DOFF_ST) :
- fsi_reg_read(fsi, DIFF_ST);
-
- frames = 0x1ff & (status >> 8);
-
- return fsi_frame2sample(fsi, frames);
+ return fsi_stream_handler_call(io, transfer, fsi, io);
}
-static void fsi_count_fifo_err(struct fsi_priv *fsi)
-{
- u32 ostatus = fsi_reg_read(fsi, DOFF_ST);
- u32 istatus = fsi_reg_read(fsi, DIFF_ST);
+#define fsi_stream_start(fsi, io)\
+ fsi_stream_handler_call(io, start_stop, fsi, io, 1)
- if (ostatus & ERR_OVER)
- fsi->playback.oerr_num++;
-
- if (ostatus & ERR_UNDER)
- fsi->playback.uerr_num++;
-
- if (istatus & ERR_OVER)
- fsi->capture.oerr_num++;
-
- if (istatus & ERR_UNDER)
- fsi->capture.uerr_num++;
+#define fsi_stream_stop(fsi, io)\
+ fsi_stream_handler_call(io, start_stop, fsi, io, 0)
- fsi_reg_write(fsi, DOFF_ST, 0);
- fsi_reg_write(fsi, DIFF_ST, 0);
-}
-
-/*
- * dma function
- */
-
-static u8 *fsi_dma_get_area(struct fsi_priv *fsi, int stream)
+static int fsi_stream_probe(struct fsi_priv *fsi)
{
- int is_play = fsi_stream_is_play(stream);
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
- struct snd_pcm_runtime *runtime = io->substream->runtime;
+ struct fsi_stream *io;
+ int ret1, ret2;
- return runtime->dma_area +
- samples_to_bytes(runtime, io->buff_sample_pos);
-}
+ io = &fsi->playback;
+ ret1 = fsi_stream_handler_call(io, probe, fsi, io);
-static void fsi_dma_soft_push16(struct fsi_priv *fsi, int num)
-{
- u16 *start;
- int i;
+ io = &fsi->capture;
+ ret2 = fsi_stream_handler_call(io, probe, fsi, io);
- start = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK);
+ if (ret1 < 0)
+ return ret1;
+ if (ret2 < 0)
+ return ret2;
- for (i = 0; i < num; i++)
- fsi_reg_write(fsi, DODT, ((u32)*(start + i) << 8));
-}
-
-static void fsi_dma_soft_pop16(struct fsi_priv *fsi, int num)
-{
- u16 *start;
- int i;
-
- start = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE);
-
-
- for (i = 0; i < num; i++)
- *(start + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8);
+ return 0;
}
-static void fsi_dma_soft_push32(struct fsi_priv *fsi, int num)
+static int fsi_stream_remove(struct fsi_priv *fsi)
{
- u32 *start;
- int i;
-
- start = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK);
+ struct fsi_stream *io;
+ int ret1, ret2;
+ io = &fsi->playback;
+ ret1 = fsi_stream_handler_call(io, remove, fsi, io);
- for (i = 0; i < num; i++)
- fsi_reg_write(fsi, DODT, *(start + i));
-}
-
-static void fsi_dma_soft_pop32(struct fsi_priv *fsi, int num)
-{
- u32 *start;
- int i;
+ io = &fsi->capture;
+ ret2 = fsi_stream_handler_call(io, remove, fsi, io);
- start = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE);
+ if (ret1 < 0)
+ return ret1;
+ if (ret2 < 0)
+ return ret2;
- for (i = 0; i < num; i++)
- *(start + i) = fsi_reg_read(fsi, DIDT);
+ return 0;
}
/*
* irq function
*/
-static void fsi_irq_enable(struct fsi_priv *fsi, int is_play)
+static void fsi_irq_enable(struct fsi_priv *fsi, struct fsi_stream *io)
{
- u32 data = AB_IO(1, fsi_get_port_shift(fsi, is_play));
+ u32 data = AB_IO(1, fsi_get_port_shift(fsi, io));
struct fsi_master *master = fsi_get_master(fsi);
fsi_core_mask_set(master, imsk, data, data);
fsi_core_mask_set(master, iemsk, data, data);
}
-static void fsi_irq_disable(struct fsi_priv *fsi, int is_play)
+static void fsi_irq_disable(struct fsi_priv *fsi, struct fsi_stream *io)
{
- u32 data = AB_IO(1, fsi_get_port_shift(fsi, is_play));
+ u32 data = AB_IO(1, fsi_get_port_shift(fsi, io));
struct fsi_master *master = fsi_get_master(fsi);
fsi_core_mask_set(master, imsk, data, 0);
@@ -563,8 +612,8 @@ static void fsi_irq_clear_status(struct fsi_priv *fsi)
u32 data = 0;
struct fsi_master *master = fsi_get_master(fsi);
- data |= AB_IO(1, fsi_get_port_shift(fsi, 0));
- data |= AB_IO(1, fsi_get_port_shift(fsi, 1));
+ data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->playback));
+ data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->capture));
/* clear interrupt factor */
fsi_core_mask_set(master, int_st, data, 0);
@@ -600,11 +649,14 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
long rate, int enable)
{
struct fsi_master *master = fsi_get_master(fsi);
- set_rate_func set_rate = fsi_get_info_set_rate(master);
+ set_rate_func set_rate = fsi_get_info_set_rate(fsi);
int fsi_ver = master->core->ver;
int ret;
- ret = set_rate(dev, fsi_is_port_a(fsi), rate, enable);
+ if (!set_rate)
+ return 0;
+
+ ret = set_rate(dev, rate, enable);
if (ret < 0) /* error */
return ret;
@@ -671,96 +723,64 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
return ret;
}
-#define fsi_port_start(f, i) __fsi_port_clk_ctrl(f, i, 1)
-#define fsi_port_stop(f, i) __fsi_port_clk_ctrl(f, i, 0)
-static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int is_play, int enable)
+/*
+ * pio data transfer handler
+ */
+static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples)
{
- struct fsi_master *master = fsi_get_master(fsi);
- u32 clk = fsi_is_port_a(fsi) ? CRA : CRB;
+ u16 *buf = (u16 *)_buf;
+ int i;
- if (enable)
- fsi_irq_enable(fsi, is_play);
- else
- fsi_irq_disable(fsi, is_play);
+ for (i = 0; i < samples; i++)
+ fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8));
+}
- if (fsi_is_clk_master(fsi))
- fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
+static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int samples)
+{
+ u16 *buf = (u16 *)_buf;
+ int i;
+
+ for (i = 0; i < samples; i++)
+ *(buf + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8);
}
-/*
- * ctrl function
- */
-static void fsi_fifo_init(struct fsi_priv *fsi,
- int is_play,
- struct device *dev)
+static void fsi_pio_push32(struct fsi_priv *fsi, u8 *_buf, int samples)
{
- struct fsi_master *master = fsi_get_master(fsi);
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
- u32 shift, i;
- int frame_capa;
+ u32 *buf = (u32 *)_buf;
+ int i;
- /* get on-chip RAM capacity */
- shift = fsi_master_read(master, FIFO_SZ);
- shift >>= fsi_get_port_shift(fsi, is_play);
- shift &= FIFO_SZ_MASK;
- frame_capa = 256 << shift;
- dev_dbg(dev, "fifo = %d words\n", frame_capa);
+ for (i = 0; i < samples; i++)
+ fsi_reg_write(fsi, DODT, *(buf + i));
+}
- /*
- * The maximum number of sample data varies depending
- * on the number of channels selected for the format.
- *
- * FIFOs are used in 4-channel units in 3-channel mode
- * and in 8-channel units in 5- to 7-channel mode
- * meaning that more FIFOs than the required size of DPRAM
- * are used.
- *
- * ex) if 256 words of DP-RAM is connected
- * 1 channel: 256 (256 x 1 = 256)
- * 2 channels: 128 (128 x 2 = 256)
- * 3 channels: 64 ( 64 x 3 = 192)
- * 4 channels: 64 ( 64 x 4 = 256)
- * 5 channels: 32 ( 32 x 5 = 160)
- * 6 channels: 32 ( 32 x 6 = 192)
- * 7 channels: 32 ( 32 x 7 = 224)
- * 8 channels: 32 ( 32 x 8 = 256)
- */
- for (i = 1; i < fsi->chan_num; i <<= 1)
- frame_capa >>= 1;
- dev_dbg(dev, "%d channel %d store\n",
- fsi->chan_num, frame_capa);
+static void fsi_pio_pop32(struct fsi_priv *fsi, u8 *_buf, int samples)
+{
+ u32 *buf = (u32 *)_buf;
+ int i;
- io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa);
+ for (i = 0; i < samples; i++)
+ *(buf + i) = fsi_reg_read(fsi, DIDT);
+}
- /*
- * set interrupt generation factor
- * clear FIFO
- */
- if (is_play) {
- fsi_reg_write(fsi, DOFF_CTL, IRQ_HALF);
- fsi_reg_mask_set(fsi, DOFF_CTL, FIFO_CLR, FIFO_CLR);
- } else {
- fsi_reg_write(fsi, DIFF_CTL, IRQ_HALF);
- fsi_reg_mask_set(fsi, DIFF_CTL, FIFO_CLR, FIFO_CLR);
- }
+static u8 *fsi_pio_get_area(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ struct snd_pcm_runtime *runtime = io->substream->runtime;
+
+ return runtime->dma_area +
+ samples_to_bytes(runtime, io->buff_sample_pos);
}
-static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
+static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io,
+ void (*run16)(struct fsi_priv *fsi, u8 *buf, int samples),
+ void (*run32)(struct fsi_priv *fsi, u8 *buf, int samples),
+ int samples)
{
struct snd_pcm_runtime *runtime;
- struct snd_pcm_substream *substream = NULL;
- int is_play = fsi_stream_is_play(stream);
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
- int sample_residues;
- int sample_width;
- int samples;
- int samples_max;
+ struct snd_pcm_substream *substream;
+ u8 *buf;
int over_period;
- void (*fn)(struct fsi_priv *fsi, int size);
- if (!fsi ||
- !io->substream ||
- !io->substream->runtime)
+ if (!fsi_stream_is_working(fsi, io))
return -EINVAL;
over_period = 0;
@@ -780,60 +800,19 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
io->buff_sample_pos = 0;
}
- /* get 1 sample data width */
- sample_width = samples_to_bytes(runtime, 1);
-
- /* get number of residue samples */
- sample_residues = io->buff_sample_capa - io->buff_sample_pos;
+ buf = fsi_pio_get_area(fsi, io);
- if (is_play) {
- /*
- * for play-back
- *
- * samples_max : number of FSI fifo free samples space
- * samples : number of ALSA residue samples
- */
- samples_max = io->fifo_sample_capa;
- samples_max -= fsi_get_current_fifo_samples(fsi, is_play);
-
- samples = sample_residues;
-
- switch (sample_width) {
- case 2:
- fn = fsi_dma_soft_push16;
- break;
- case 4:
- fn = fsi_dma_soft_push32;
- break;
- default:
- return -EINVAL;
- }
- } else {
- /*
- * for capture
- *
- * samples_max : number of ALSA free samples space
- * samples : number of samples in FSI fifo
- */
- samples_max = sample_residues;
- samples = fsi_get_current_fifo_samples(fsi, is_play);
-
- switch (sample_width) {
- case 2:
- fn = fsi_dma_soft_pop16;
- break;
- case 4:
- fn = fsi_dma_soft_pop32;
- break;
- default:
- return -EINVAL;
- }
+ switch (io->sample_width) {
+ case 2:
+ run16(fsi, buf, samples);
+ break;
+ case 4:
+ run32(fsi, buf, samples);
+ break;
+ default:
+ return -EINVAL;
}
- samples = min(samples, samples_max);
-
- fn(fsi, samples);
-
/* update buff_sample_pos */
io->buff_sample_pos += samples;
@@ -843,16 +822,66 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
return 0;
}
-static int fsi_data_pop(struct fsi_priv *fsi)
+static int fsi_pio_pop(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ int sample_residues; /* samples in FSI fifo */
+ int sample_space; /* ALSA free samples space */
+ int samples;
+
+ sample_residues = fsi_get_current_fifo_samples(fsi, io);
+ sample_space = io->buff_sample_capa - io->buff_sample_pos;
+
+ samples = min(sample_residues, sample_space);
+
+ return fsi_pio_transfer(fsi, io,
+ fsi_pio_pop16,
+ fsi_pio_pop32,
+ samples);
+}
+
+static int fsi_pio_push(struct fsi_priv *fsi, struct fsi_stream *io)
{
- return fsi_fifo_data_ctrl(fsi, SNDRV_PCM_STREAM_CAPTURE);
+ int sample_residues; /* ALSA residue samples */
+ int sample_space; /* FSI fifo free samples space */
+ int samples;
+
+ sample_residues = io->buff_sample_capa - io->buff_sample_pos;
+ sample_space = io->fifo_sample_capa -
+ fsi_get_current_fifo_samples(fsi, io);
+
+ samples = min(sample_residues, sample_space);
+
+ return fsi_pio_transfer(fsi, io,
+ fsi_pio_push16,
+ fsi_pio_push32,
+ samples);
}
-static int fsi_data_push(struct fsi_priv *fsi)
+static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
+ int enable)
{
- return fsi_fifo_data_ctrl(fsi, SNDRV_PCM_STREAM_PLAYBACK);
+ struct fsi_master *master = fsi_get_master(fsi);
+ u32 clk = fsi_is_port_a(fsi) ? CRA : CRB;
+
+ if (enable)
+ fsi_irq_enable(fsi, io);
+ else
+ fsi_irq_disable(fsi, io);
+
+ if (fsi_is_clk_master(fsi))
+ fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
}
+static struct fsi_stream_handler fsi_pio_push_handler = {
+ .transfer = fsi_pio_push,
+ .start_stop = fsi_pio_start_stop,
+};
+
+static struct fsi_stream_handler fsi_pio_pop_handler = {
+ .transfer = fsi_pio_pop,
+ .start_stop = fsi_pio_start_stop,
+};
+
static irqreturn_t fsi_interrupt(int irq, void *data)
{
struct fsi_master *master = data;
@@ -863,13 +892,13 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
fsi_master_mask_set(master, SOFT_RST, IR, IR);
if (int_st & AB_IO(1, AO_SHIFT))
- fsi_data_push(&master->fsia);
+ fsi_stream_transfer(&master->fsia.playback);
if (int_st & AB_IO(1, BO_SHIFT))
- fsi_data_push(&master->fsib);
+ fsi_stream_transfer(&master->fsib.playback);
if (int_st & AB_IO(1, AI_SHIFT))
- fsi_data_pop(&master->fsia);
+ fsi_stream_transfer(&master->fsia.capture);
if (int_st & AB_IO(1, BI_SHIFT))
- fsi_data_pop(&master->fsib);
+ fsi_stream_transfer(&master->fsib.capture);
fsi_count_fifo_err(&master->fsia);
fsi_count_fifo_err(&master->fsib);
@@ -881,11 +910,271 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
}
/*
+ * dma data transfer handler
+ */
+static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ struct snd_pcm_runtime *runtime = io->substream->runtime;
+ struct snd_soc_dai *dai = fsi_get_dai(io->substream);
+ enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+ io->dma = dma_map_single(dai->dev, runtime->dma_area,
+ snd_pcm_lib_buffer_bytes(io->substream), dir);
+ return 0;
+}
+
+static int fsi_dma_quit(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ struct snd_soc_dai *dai = fsi_get_dai(io->substream);
+ enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+ dma_unmap_single(dai->dev, io->dma,
+ snd_pcm_lib_buffer_bytes(io->substream), dir);
+ return 0;
+}
+
+static void fsi_dma_complete(void *data)
+{
+ struct fsi_stream *io = (struct fsi_stream *)data;
+ struct fsi_priv *fsi = fsi_stream_to_priv(io);
+ struct snd_pcm_runtime *runtime = io->substream->runtime;
+ struct snd_soc_dai *dai = fsi_get_dai(io->substream);
+ enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+ dma_sync_single_for_cpu(dai->dev, io->dma,
+ samples_to_bytes(runtime, io->period_samples), dir);
+
+ io->buff_sample_pos += io->period_samples;
+ io->period_pos++;
+
+ if (io->period_pos >= runtime->periods) {
+ io->period_pos = 0;
+ io->buff_sample_pos = 0;
+ }
+
+ fsi_count_fifo_err(fsi);
+ fsi_stream_transfer(io);
+
+ snd_pcm_period_elapsed(io->substream);
+}
+
+static dma_addr_t fsi_dma_get_area(struct fsi_stream *io)
+{
+ struct snd_pcm_runtime *runtime = io->substream->runtime;
+
+ return io->dma + samples_to_bytes(runtime, io->buff_sample_pos);
+}
+
+static void fsi_dma_do_tasklet(unsigned long data)
+{
+ struct fsi_stream *io = (struct fsi_stream *)data;
+ struct fsi_priv *fsi = fsi_stream_to_priv(io);
+ struct dma_chan *chan;
+ struct snd_soc_dai *dai;
+ struct dma_async_tx_descriptor *desc;
+ struct scatterlist sg;
+ struct snd_pcm_runtime *runtime;
+ enum dma_data_direction dir;
+ dma_cookie_t cookie;
+ int is_play = fsi_stream_is_play(fsi, io);
+ int len;
+ dma_addr_t buf;
+
+ if (!fsi_stream_is_working(fsi, io))
+ return;
+
+ dai = fsi_get_dai(io->substream);
+ chan = io->chan;
+ runtime = io->substream->runtime;
+ dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ len = samples_to_bytes(runtime, io->period_samples);
+ buf = fsi_dma_get_area(io);
+
+ dma_sync_single_for_device(dai->dev, io->dma, len, dir);
+
+ sg_init_table(&sg, 1);
+ sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)),
+ len , offset_in_page(buf));
+ sg_dma_address(&sg) = buf;
+ sg_dma_len(&sg) = len;
+
+ desc = chan->device->device_prep_slave_sg(chan, &sg, 1, dir,
+ DMA_PREP_INTERRUPT |
+ DMA_CTRL_ACK);
+ if (!desc) {
+ dev_err(dai->dev, "device_prep_slave_sg() fail\n");
+ return;
+ }
+
+ desc->callback = fsi_dma_complete;
+ desc->callback_param = io;
+
+ cookie = desc->tx_submit(desc);
+ if (cookie < 0) {
+ dev_err(dai->dev, "tx_submit() fail\n");
+ return;
+ }
+
+ dma_async_issue_pending(chan);
+
+ /*
+ * FIXME
+ *
+ * In DMAEngine case, codec and FSI cannot be started simultaneously
+ * since FSI is using tasklet.
+ * Therefore, in capture case, probably FSI FIFO will have got
+ * overflow error in this point.
+ * in that case, DMA cannot start transfer until error was cleared.
+ */
+ if (!is_play) {
+ if (ERR_OVER & fsi_reg_read(fsi, DIFF_ST)) {
+ fsi_reg_mask_set(fsi, DIFF_CTL, FIFO_CLR, FIFO_CLR);
+ fsi_reg_write(fsi, DIFF_ST, 0);
+ }
+ }
+}
+
+static bool fsi_dma_filter(struct dma_chan *chan, void *param)
+{
+ struct sh_dmae_slave *slave = param;
+
+ chan->private = slave;
+
+ return true;
+}
+
+static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ tasklet_schedule(&io->tasklet);
+
+ return 0;
+}
+
+static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
+ int start)
+{
+ u32 bws;
+ u32 dma;
+
+ switch (io->sample_width * start) {
+ case 2:
+ bws = CR_BWS_16;
+ dma = VDMD_STREAM | DMA_ON;
+ break;
+ case 4:
+ bws = CR_BWS_24;
+ dma = VDMD_BACK | DMA_ON;
+ break;
+ default:
+ bws = 0;
+ dma = 0;
+ }
+
+ fsi_reg_mask_set(fsi, DO_FMT, CR_BWS_MASK, bws);
+ fsi_reg_write(fsi, OUT_DMAC, dma);
+}
+
+static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ dma_cap_mask_t mask;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave);
+ if (!io->chan)
+ return -EIO;
+
+ tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io);
+
+ return 0;
+}
+
+static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ tasklet_kill(&io->tasklet);
+
+ fsi_stream_stop(fsi, io);
+
+ if (io->chan)
+ dma_release_channel(io->chan);
+
+ io->chan = NULL;
+ return 0;
+}
+
+static struct fsi_stream_handler fsi_dma_push_handler = {
+ .init = fsi_dma_init,
+ .quit = fsi_dma_quit,
+ .probe = fsi_dma_probe,
+ .transfer = fsi_dma_transfer,
+ .remove = fsi_dma_remove,
+ .start_stop = fsi_dma_push_start_stop,
+};
+
+/*
* dai ops
*/
+static void fsi_fifo_init(struct fsi_priv *fsi,
+ struct fsi_stream *io,
+ struct device *dev)
+{
+ struct fsi_master *master = fsi_get_master(fsi);
+ int is_play = fsi_stream_is_play(fsi, io);
+ u32 shift, i;
+ int frame_capa;
+
+ /* get on-chip RAM capacity */
+ shift = fsi_master_read(master, FIFO_SZ);
+ shift >>= fsi_get_port_shift(fsi, io);
+ shift &= FIFO_SZ_MASK;
+ frame_capa = 256 << shift;
+ dev_dbg(dev, "fifo = %d words\n", frame_capa);
+
+ /*
+ * The maximum number of sample data varies depending
+ * on the number of channels selected for the format.
+ *
+ * FIFOs are used in 4-channel units in 3-channel mode
+ * and in 8-channel units in 5- to 7-channel mode
+ * meaning that more FIFOs than the required size of DPRAM
+ * are used.
+ *
+ * ex) if 256 words of DP-RAM is connected
+ * 1 channel: 256 (256 x 1 = 256)
+ * 2 channels: 128 (128 x 2 = 256)
+ * 3 channels: 64 ( 64 x 3 = 192)
+ * 4 channels: 64 ( 64 x 4 = 256)
+ * 5 channels: 32 ( 32 x 5 = 160)
+ * 6 channels: 32 ( 32 x 6 = 192)
+ * 7 channels: 32 ( 32 x 7 = 224)
+ * 8 channels: 32 ( 32 x 8 = 256)
+ */
+ for (i = 1; i < fsi->chan_num; i <<= 1)
+ frame_capa >>= 1;
+ dev_dbg(dev, "%d channel %d store\n",
+ fsi->chan_num, frame_capa);
+
+ io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa);
+
+ /*
+ * set interrupt generation factor
+ * clear FIFO
+ */
+ if (is_play) {
+ fsi_reg_write(fsi, DOFF_CTL, IRQ_HALF);
+ fsi_reg_mask_set(fsi, DOFF_CTL, FIFO_CLR, FIFO_CLR);
+ } else {
+ fsi_reg_write(fsi, DIFF_CTL, IRQ_HALF);
+ fsi_reg_mask_set(fsi, DIFF_CTL, FIFO_CLR, FIFO_CLR);
+ }
+}
static int fsi_hw_startup(struct fsi_priv *fsi,
- int is_play,
+ struct fsi_stream *io,
struct device *dev)
{
struct fsi_master *master = fsi_get_master(fsi);
@@ -934,17 +1223,16 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
}
/* irq clear */
- fsi_irq_disable(fsi, is_play);
+ fsi_irq_disable(fsi, io);
fsi_irq_clear_status(fsi);
/* fifo init */
- fsi_fifo_init(fsi, is_play, dev);
+ fsi_fifo_init(fsi, io, dev);
return 0;
}
static void fsi_hw_shutdown(struct fsi_priv *fsi,
- int is_play,
struct device *dev)
{
if (fsi_is_clk_master(fsi))
@@ -955,18 +1243,16 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct fsi_priv *fsi = fsi_get_priv(substream);
- int is_play = fsi_is_play(substream);
- return fsi_hw_startup(fsi, is_play, dai->dev);
+ return fsi_hw_startup(fsi, fsi_stream_get(fsi, substream), dai->dev);
}
static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct fsi_priv *fsi = fsi_get_priv(substream);
- int is_play = fsi_is_play(substream);
- fsi_hw_shutdown(fsi, is_play, dai->dev);
+ fsi_hw_shutdown(fsi, dai->dev);
fsi->rate = 0;
}
@@ -974,18 +1260,19 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
struct fsi_priv *fsi = fsi_get_priv(substream);
- int is_play = fsi_is_play(substream);
+ struct fsi_stream *io = fsi_stream_get(fsi, substream);
int ret = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- fsi_stream_push(fsi, is_play, substream);
- ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi);
- fsi_port_start(fsi, is_play);
+ fsi_stream_init(fsi, io, substream);
+ ret = fsi_stream_transfer(io);
+ if (0 == ret)
+ fsi_stream_start(fsi, io);
break;
case SNDRV_PCM_TRIGGER_STOP:
- fsi_port_stop(fsi, is_play);
- fsi_stream_pop(fsi, is_play);
+ fsi_stream_stop(fsi, io);
+ fsi_stream_quit(fsi, io);
break;
}
@@ -1036,8 +1323,7 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai);
- struct fsi_master *master = fsi_get_master(fsi);
- set_rate_func set_rate = fsi_get_info_set_rate(master);
+ set_rate_func set_rate = fsi_get_info_set_rate(fsi);
u32 flags = fsi_get_info_flags(fsi);
int ret;
@@ -1151,13 +1437,9 @@ static int fsi_hw_free(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
{
struct fsi_priv *fsi = fsi_get_priv(substream);
- struct fsi_stream *io = fsi_get_stream(fsi, fsi_is_play(substream));
- int samples_pos = io->buff_sample_pos - 1;
-
- if (samples_pos < 0)
- samples_pos = 0;
+ struct fsi_stream *io = fsi_stream_get(fsi, substream);
- return fsi_sample2frame(fsi, samples_pos);
+ return fsi_sample2frame(fsi, io->buff_sample_pos);
}
static struct snd_pcm_ops fsi_pcm_ops = {
@@ -1243,11 +1525,24 @@ static struct snd_soc_platform_driver fsi_soc_platform = {
/*
* platform function
*/
+static void fsi_handler_init(struct fsi_priv *fsi)
+{
+ fsi->playback.handler = &fsi_pio_push_handler; /* default PIO */
+ fsi->playback.priv = fsi;
+ fsi->capture.handler = &fsi_pio_pop_handler; /* default PIO */
+ fsi->capture.priv = fsi;
+
+ if (fsi->info->tx_id) {
+ fsi->playback.slave.slave_id = fsi->info->tx_id;
+ fsi->playback.handler = &fsi_dma_push_handler;
+ }
+}
static int fsi_probe(struct platform_device *pdev)
{
struct fsi_master *master;
const struct platform_device_id *id_entry;
+ struct sh_fsi_platform_info *info = pdev->dev.platform_data;
struct resource *res;
unsigned int irq;
int ret;
@@ -1282,17 +1577,30 @@ static int fsi_probe(struct platform_device *pdev)
/* master setting */
master->irq = irq;
- master->info = pdev->dev.platform_data;
master->core = (struct fsi_core *)id_entry->driver_data;
spin_lock_init(&master->lock);
/* FSI A setting */
master->fsia.base = master->base;
master->fsia.master = master;
+ master->fsia.info = &info->port_a;
+ fsi_handler_init(&master->fsia);
+ ret = fsi_stream_probe(&master->fsia);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "FSIA stream probe failed\n");
+ goto exit_iounmap;
+ }
/* FSI B setting */
master->fsib.base = master->base + 0x40;
master->fsib.master = master;
+ master->fsib.info = &info->port_b;
+ fsi_handler_init(&master->fsib);
+ ret = fsi_stream_probe(&master->fsib);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "FSIB stream probe failed\n");
+ goto exit_fsia;
+ }
pm_runtime_enable(&pdev->dev);
dev_set_drvdata(&pdev->dev, master);
@@ -1301,7 +1609,7 @@ static int fsi_probe(struct platform_device *pdev)
id_entry->name, master);
if (ret) {
dev_err(&pdev->dev, "irq request err\n");
- goto exit_iounmap;
+ goto exit_fsib;
}
ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform);
@@ -1323,6 +1631,10 @@ exit_snd_soc:
snd_soc_unregister_platform(&pdev->dev);
exit_free_irq:
free_irq(irq, master);
+exit_fsib:
+ fsi_stream_remove(&master->fsib);
+exit_fsia:
+ fsi_stream_remove(&master->fsia);
exit_iounmap:
iounmap(master->base);
pm_runtime_disable(&pdev->dev);
@@ -1345,6 +1657,9 @@ static int fsi_remove(struct platform_device *pdev)
snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
snd_soc_unregister_platform(&pdev->dev);
+ fsi_stream_remove(&master->fsia);
+ fsi_stream_remove(&master->fsib);
+
iounmap(master->base);
kfree(master);
@@ -1352,30 +1667,29 @@ static int fsi_remove(struct platform_device *pdev)
}
static void __fsi_suspend(struct fsi_priv *fsi,
- int is_play,
+ struct fsi_stream *io,
struct device *dev)
{
- if (!fsi_stream_is_working(fsi, is_play))
+ if (!fsi_stream_is_working(fsi, io))
return;
- fsi_port_stop(fsi, is_play);
- fsi_hw_shutdown(fsi, is_play, dev);
+ fsi_stream_stop(fsi, io);
+ fsi_hw_shutdown(fsi, dev);
}
static void __fsi_resume(struct fsi_priv *fsi,
- int is_play,
+ struct fsi_stream *io,
struct device *dev)
{
- if (!fsi_stream_is_working(fsi, is_play))
+ if (!fsi_stream_is_working(fsi, io))
return;
- fsi_hw_startup(fsi, is_play, dev);
+ fsi_hw_startup(fsi, io, dev);
if (fsi_is_clk_master(fsi) && fsi->rate)
fsi_set_master_clk(dev, fsi, fsi->rate, 1);
- fsi_port_start(fsi, is_play);
-
+ fsi_stream_start(fsi, io);
}
static int fsi_suspend(struct device *dev)
@@ -1384,11 +1698,11 @@ static int fsi_suspend(struct device *dev)
struct fsi_priv *fsia = &master->fsia;
struct fsi_priv *fsib = &master->fsib;
- __fsi_suspend(fsia, 1, dev);
- __fsi_suspend(fsia, 0, dev);
+ __fsi_suspend(fsia, &fsia->playback, dev);
+ __fsi_suspend(fsia, &fsia->capture, dev);
- __fsi_suspend(fsib, 1, dev);
- __fsi_suspend(fsib, 0, dev);
+ __fsi_suspend(fsib, &fsib->playback, dev);
+ __fsi_suspend(fsib, &fsib->capture, dev);
return 0;
}
@@ -1399,32 +1713,18 @@ static int fsi_resume(struct device *dev)
struct fsi_priv *fsia = &master->fsia;
struct fsi_priv *fsib = &master->fsib;
- __fsi_resume(fsia, 1, dev);
- __fsi_resume(fsia, 0, dev);
+ __fsi_resume(fsia, &fsia->playback, dev);
+ __fsi_resume(fsia, &fsia->capture, dev);
- __fsi_resume(fsib, 1, dev);
- __fsi_resume(fsib, 0, dev);
+ __fsi_resume(fsib, &fsib->playback, dev);
+ __fsi_resume(fsib, &fsib->capture, dev);
return 0;
}
-static int fsi_runtime_nop(struct device *dev)
-{
- /* Runtime PM callback shared between ->runtime_suspend()
- * and ->runtime_resume(). Simply returns success.
- *
- * This driver re-initializes all registers after
- * pm_runtime_get_sync() anyway so there is no need
- * to save and restore registers here.
- */
- return 0;
-}
-
static struct dev_pm_ops fsi_pm_ops = {
.suspend = fsi_suspend,
.resume = fsi_resume,
- .runtime_suspend = fsi_runtime_nop,
- .runtime_resume = fsi_runtime_nop,
};
static struct fsi_core fsi1_core = {
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 35a1e639d7f9..7978f6c01ef7 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -277,8 +277,7 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
codec->debugfs_codec_root = debugfs_create_dir(codec->name,
debugfs_card_root);
if (!codec->debugfs_codec_root) {
- printk(KERN_WARNING
- "ASoC: Failed to create codec debugfs directory\n");
+ dev_warn(codec->dev, "Failed to create codec debugfs directory\n");
return;
}
@@ -291,8 +290,7 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
codec->debugfs_codec_root,
codec, &codec_reg_fops);
if (!codec->debugfs_reg)
- printk(KERN_WARNING
- "ASoC: Failed to create codec register debugfs file\n");
+ dev_warn(codec->dev, "Failed to create codec register debugfs file\n");
snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root);
}
@@ -302,6 +300,27 @@ static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
debugfs_remove_recursive(codec->debugfs_codec_root);
}
+static void soc_init_platform_debugfs(struct snd_soc_platform *platform)
+{
+ struct dentry *debugfs_card_root = platform->card->debugfs_card_root;
+
+ platform->debugfs_platform_root = debugfs_create_dir(platform->name,
+ debugfs_card_root);
+ if (!platform->debugfs_platform_root) {
+ dev_warn(platform->dev,
+ "Failed to create platform debugfs directory\n");
+ return;
+ }
+
+ snd_soc_dapm_debugfs_init(&platform->dapm,
+ platform->debugfs_platform_root);
+}
+
+static void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform)
+{
+ debugfs_remove_recursive(platform->debugfs_platform_root);
+}
+
static ssize_t codec_list_read_file(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -435,6 +454,14 @@ static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
{
}
+static inline void soc_init_platform_debugfs(struct snd_soc_platform *platform)
+{
+}
+
+static inline void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform)
+{
+}
+
static inline void soc_init_card_debugfs(struct snd_soc_card *card)
{
}
@@ -546,18 +573,20 @@ int snd_soc_suspend(struct device *dev)
}
for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
+ struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
if (card->rtd[i].dai_link->ignore_suspend)
continue;
- if (driver->playback.stream_name != NULL)
- snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_SUSPEND);
+ snd_soc_dapm_stream_event(&card->rtd[i],
+ SNDRV_PCM_STREAM_PLAYBACK,
+ codec_dai,
+ SND_SOC_DAPM_STREAM_SUSPEND);
- if (driver->capture.stream_name != NULL)
- snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
- SND_SOC_DAPM_STREAM_SUSPEND);
+ snd_soc_dapm_stream_event(&card->rtd[i],
+ SNDRV_PCM_STREAM_CAPTURE,
+ codec_dai,
+ SND_SOC_DAPM_STREAM_SUSPEND);
}
/* suspend all CODECs */
@@ -567,6 +596,17 @@ int snd_soc_suspend(struct device *dev)
if (!codec->suspended && codec->driver->suspend) {
switch (codec->dapm.bias_level) {
case SND_SOC_BIAS_STANDBY:
+ /*
+ * If the CODEC is capable of idle
+ * bias off then being in STANDBY
+ * means it's doing something,
+ * otherwise fall through.
+ */
+ if (codec->dapm.idle_bias_off) {
+ dev_dbg(codec->dev,
+ "idle_bias_off CODEC on over suspend\n");
+ break;
+ }
case SND_SOC_BIAS_OFF:
codec->driver->suspend(codec);
codec->suspended = 1;
@@ -649,18 +689,18 @@ static void soc_resume_deferred(struct work_struct *work)
}
for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
+ struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
if (card->rtd[i].dai_link->ignore_suspend)
continue;
- if (driver->playback.stream_name != NULL)
- snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_RESUME);
+ snd_soc_dapm_stream_event(&card->rtd[i],
+ SNDRV_PCM_STREAM_PLAYBACK, codec_dai,
+ SND_SOC_DAPM_STREAM_RESUME);
- if (driver->capture.stream_name != NULL)
- snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
- SND_SOC_DAPM_STREAM_RESUME);
+ snd_soc_dapm_stream_event(&card->rtd[i],
+ SNDRV_PCM_STREAM_CAPTURE, codec_dai,
+ SND_SOC_DAPM_STREAM_RESUME);
}
/* unmute any active DACs */
@@ -893,7 +933,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
if (codec_dai->driver->remove) {
err = codec_dai->driver->remove(codec_dai);
if (err < 0)
- printk(KERN_ERR "asoc: failed to remove %s\n", codec_dai->name);
+ pr_err("asoc: failed to remove %s: %d\n",
+ codec_dai->name, err);
}
codec_dai->probed = 0;
list_del(&codec_dai->card_list);
@@ -905,12 +946,14 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
if (platform->driver->remove) {
err = platform->driver->remove(platform);
if (err < 0)
- printk(KERN_ERR "asoc: failed to remove %s\n", platform->name);
+ pr_err("asoc: failed to remove %s: %d\n",
+ platform->name, err);
}
/* Make sure all DAPM widgets are freed */
snd_soc_dapm_free(&platform->dapm);
+ soc_cleanup_platform_debugfs(platform);
platform->probed = 0;
list_del(&platform->card_list);
module_put(platform->dev->driver->owner);
@@ -927,7 +970,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
if (cpu_dai->driver->remove) {
err = cpu_dai->driver->remove(cpu_dai);
if (err < 0)
- printk(KERN_ERR "asoc: failed to remove %s\n", cpu_dai->name);
+ pr_err("asoc: failed to remove %s: %d\n",
+ cpu_dai->name, err);
}
cpu_dai->probed = 0;
list_del(&cpu_dai->card_list);
@@ -969,6 +1013,7 @@ static int soc_probe_codec(struct snd_soc_card *card,
{
int ret = 0;
const struct snd_soc_codec_driver *driver = codec->driver;
+ struct snd_soc_dai *dai;
codec->card = card;
codec->dapm.card = card;
@@ -983,6 +1028,14 @@ static int soc_probe_codec(struct snd_soc_card *card,
snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets,
driver->num_dapm_widgets);
+ /* Create DAPM widgets for each DAI stream */
+ list_for_each_entry(dai, &dai_list, list) {
+ if (dai->dev != codec->dev)
+ continue;
+
+ snd_soc_dapm_new_dai_widgets(&codec->dapm, dai);
+ }
+
codec->dapm.idle_bias_off = driver->idle_bias_off;
if (driver->probe) {
@@ -996,7 +1049,7 @@ static int soc_probe_codec(struct snd_soc_card *card,
}
if (driver->controls)
- snd_soc_add_controls(codec, driver->controls,
+ snd_soc_add_codec_controls(codec, driver->controls,
driver->num_controls);
if (driver->dapm_routes)
snd_soc_dapm_add_routes(&codec->dapm, driver->dapm_routes,
@@ -1028,6 +1081,8 @@ static int soc_probe_platform(struct snd_soc_card *card,
if (!try_module_get(platform->dev->driver->owner))
return -ENODEV;
+ soc_init_platform_debugfs(platform);
+
if (driver->dapm_widgets)
snd_soc_dapm_new_controls(&platform->dapm,
driver->dapm_widgets, driver->num_dapm_widgets);
@@ -1057,6 +1112,7 @@ static int soc_probe_platform(struct snd_soc_card *card,
return 0;
err_probe:
+ soc_cleanup_platform_debugfs(platform);
module_put(platform->dev->driver->owner);
return ret;
@@ -1172,8 +1228,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
if (cpu_dai->driver->probe) {
ret = cpu_dai->driver->probe(cpu_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: failed to probe CPU DAI %s\n",
- cpu_dai->name);
+ pr_err("asoc: failed to probe CPU DAI %s: %d\n",
+ cpu_dai->name, ret);
module_put(cpu_dai->dev->driver->owner);
return ret;
}
@@ -1204,8 +1260,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
if (codec_dai->driver->probe) {
ret = codec_dai->driver->probe(codec_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: failed to probe CODEC DAI %s\n",
- codec_dai->name);
+ pr_err("asoc: failed to probe CODEC DAI %s: %d\n",
+ codec_dai->name, ret);
return ret;
}
}
@@ -1225,12 +1281,13 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
ret = device_create_file(rtd->dev, &dev_attr_pmdown_time);
if (ret < 0)
- printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n");
+ pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret);
/* create the pcm */
ret = soc_new_pcm(rtd, num);
if (ret < 0) {
- printk(KERN_ERR "asoc: can't create pcm %s\n", dai_link->stream_name);
+ pr_err("asoc: can't create pcm %s :%d\n",
+ dai_link->stream_name, ret);
return ret;
}
@@ -1263,7 +1320,7 @@ static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
ret = soc_ac97_dev_register(rtd->codec);
if (ret < 0) {
- printk(KERN_ERR "asoc: AC97 device register failed\n");
+ pr_err("asoc: AC97 device register failed:%d\n", ret);
return ret;
}
@@ -1403,8 +1460,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
card->owner, 0, &card->snd_card);
if (ret < 0) {
- printk(KERN_ERR "asoc: can't create sound card for card %s\n",
- card->name);
+ pr_err("asoc: can't create sound card for card %s: %d\n",
+ card->name, ret);
mutex_unlock(&card->mutex);
return;
}
@@ -1457,13 +1514,10 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
}
}
- /* We should have a non-codec control add function but we don't */
+ snd_soc_dapm_link_dai_widgets(card);
+
if (card->controls)
- snd_soc_add_controls(list_first_entry(&card->codec_dev_list,
- struct snd_soc_codec,
- card_list),
- card->controls,
- card->num_controls);
+ snd_soc_add_card_controls(card, card->controls, card->num_controls);
if (card->dapm_routes)
snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes,
@@ -1527,7 +1581,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
ret = snd_card_register(card->snd_card);
if (ret < 0) {
- printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name);
+ pr_err("asoc: failed to register soundcard for %s: %d\n",
+ card->name, ret);
goto probe_aux_dev_err;
}
@@ -1536,7 +1591,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
for (i = 0; i < card->num_rtd; i++) {
ret = soc_register_ac97_dai_link(&card->rtd[i]);
if (ret < 0) {
- printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
+ pr_err("asoc: failed to register AC97 %s: %d\n",
+ card->name, ret);
while (--i >= 0)
soc_unregister_ac97_dai_link(card->rtd[i].codec);
goto probe_aux_dev_err;
@@ -1589,6 +1645,10 @@ static int soc_probe(struct platform_device *pdev)
if (!card)
return -EINVAL;
+ dev_warn(&pdev->dev,
+ "ASoC machine %s should use snd_soc_register_card()\n",
+ card->name);
+
/* Bodge while we unpick instantiation */
card->dev = &pdev->dev;
@@ -1665,7 +1725,10 @@ EXPORT_SYMBOL_GPL(snd_soc_poweroff);
const struct dev_pm_ops snd_soc_pm_ops = {
.suspend = snd_soc_suspend,
.resume = snd_soc_resume,
+ .freeze = snd_soc_suspend,
+ .thaw = snd_soc_resume,
.poweroff = snd_soc_poweroff,
+ .restore = snd_soc_resume,
};
EXPORT_SYMBOL_GPL(snd_soc_pm_ops);
@@ -1981,7 +2044,7 @@ EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
* Returns 0 for success, else error.
*/
struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
- void *data, char *long_name,
+ void *data, const char *long_name,
const char *prefix)
{
struct snd_kcontrol_new template;
@@ -2016,9 +2079,28 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
}
EXPORT_SYMBOL_GPL(snd_soc_cnew);
+static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
+ const struct snd_kcontrol_new *controls, int num_controls,
+ const char *prefix, void *data)
+{
+ int err, i;
+
+ for (i = 0; i < num_controls; i++) {
+ const struct snd_kcontrol_new *control = &controls[i];
+ err = snd_ctl_add(card, snd_soc_cnew(control, data,
+ control->name, prefix));
+ if (err < 0) {
+ dev_err(dev, "Failed to add %s: %d\n", control->name, err);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
/**
- * snd_soc_add_controls - add an array of controls to a codec.
- * Convienience function to add a list of controls. Many codecs were
+ * snd_soc_add_codec_controls - add an array of controls to a codec.
+ * Convenience function to add a list of controls. Many codecs were
* duplicating this code.
*
* @codec: codec to add controls to
@@ -2027,31 +2109,19 @@ EXPORT_SYMBOL_GPL(snd_soc_cnew);
*
* Return 0 for success, else error.
*/
-int snd_soc_add_controls(struct snd_soc_codec *codec,
+int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
const struct snd_kcontrol_new *controls, int num_controls)
{
struct snd_card *card = codec->card->snd_card;
- int err, i;
- for (i = 0; i < num_controls; i++) {
- const struct snd_kcontrol_new *control = &controls[i];
- err = snd_ctl_add(card, snd_soc_cnew(control, codec,
- control->name,
- codec->name_prefix));
- if (err < 0) {
- dev_err(codec->dev, "%s: Failed to add %s: %d\n",
- codec->name, control->name, err);
- return err;
- }
- }
-
- return 0;
+ return snd_soc_add_controls(card, codec->dev, controls, num_controls,
+ codec->name_prefix, codec);
}
-EXPORT_SYMBOL_GPL(snd_soc_add_controls);
+EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls);
/**
* snd_soc_add_platform_controls - add an array of controls to a platform.
- * Convienience function to add a list of controls.
+ * Convenience function to add a list of controls.
*
* @platform: platform to add controls to
* @controls: array of controls to add
@@ -2063,23 +2133,53 @@ int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
const struct snd_kcontrol_new *controls, int num_controls)
{
struct snd_card *card = platform->card->snd_card;
- int err, i;
- for (i = 0; i < num_controls; i++) {
- const struct snd_kcontrol_new *control = &controls[i];
- err = snd_ctl_add(card, snd_soc_cnew(control, platform,
- control->name, NULL));
- if (err < 0) {
- dev_err(platform->dev, "Failed to add %s %d\n",control->name, err);
- return err;
- }
- }
-
- return 0;
+ return snd_soc_add_controls(card, platform->dev, controls, num_controls,
+ NULL, platform);
}
EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls);
/**
+ * snd_soc_add_card_controls - add an array of controls to a SoC card.
+ * Convenience function to add a list of controls.
+ *
+ * @soc_card: SoC card to add controls to
+ * @controls: array of controls to add
+ * @num_controls: number of elements in the array
+ *
+ * Return 0 for success, else error.
+ */
+int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
+ const struct snd_kcontrol_new *controls, int num_controls)
+{
+ struct snd_card *card = soc_card->snd_card;
+
+ return snd_soc_add_controls(card, soc_card->dev, controls, num_controls,
+ NULL, soc_card);
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_card_controls);
+
+/**
+ * snd_soc_add_dai_controls - add an array of controls to a DAI.
+ * Convienience function to add a list of controls.
+ *
+ * @dai: DAI to add controls to
+ * @controls: array of controls to add
+ * @num_controls: number of elements in the array
+ *
+ * Return 0 for success, else error.
+ */
+int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
+ const struct snd_kcontrol_new *controls, int num_controls)
+{
+ struct snd_card *card = dai->card->snd_card;
+
+ return snd_soc_add_controls(card, dai->dev, controls, num_controls,
+ NULL, dai);
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls);
+
+/**
* snd_soc_info_enum_double - enumerated double mixer info callback
* @kcontrol: mixer control
* @uinfo: control element information
@@ -2645,6 +2745,115 @@ int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol,
}
EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r_sx);
+int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct soc_bytes *params = (void *)kcontrol->private_value;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+ uinfo->count = params->num_regs * codec->val_bytes;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_bytes_info);
+
+int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_bytes *params = (void *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int ret;
+
+ if (codec->using_regmap)
+ ret = regmap_raw_read(codec->control_data, params->base,
+ ucontrol->value.bytes.data,
+ params->num_regs * codec->val_bytes);
+ else
+ ret = -EINVAL;
+
+ /* Hide any masked bytes to ensure consistent data reporting */
+ if (ret == 0 && params->mask) {
+ switch (codec->val_bytes) {
+ case 1:
+ ucontrol->value.bytes.data[0] &= ~params->mask;
+ break;
+ case 2:
+ ((u16 *)(&ucontrol->value.bytes.data))[0]
+ &= ~params->mask;
+ break;
+ case 4:
+ ((u32 *)(&ucontrol->value.bytes.data))[0]
+ &= ~params->mask;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_bytes_get);
+
+int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_bytes *params = (void *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int ret, len;
+ unsigned int val;
+ void *data;
+
+ if (!codec->using_regmap)
+ return -EINVAL;
+
+ data = ucontrol->value.bytes.data;
+ len = params->num_regs * codec->val_bytes;
+
+ /*
+ * If we've got a mask then we need to preserve the register
+ * bits. We shouldn't modify the incoming data so take a
+ * copy.
+ */
+ if (params->mask) {
+ ret = regmap_read(codec->control_data, params->base, &val);
+ if (ret != 0)
+ return ret;
+
+ val &= params->mask;
+
+ data = kmemdup(data, len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ switch (codec->val_bytes) {
+ case 1:
+ ((u8 *)data)[0] &= ~params->mask;
+ ((u8 *)data)[0] |= val;
+ break;
+ case 2:
+ ((u16 *)data)[0] &= cpu_to_be16(~params->mask);
+ ((u16 *)data)[0] |= cpu_to_be16(val);
+ break;
+ case 4:
+ ((u32 *)data)[0] &= cpu_to_be32(~params->mask);
+ ((u32 *)data)[0] |= cpu_to_be32(val);
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ ret = regmap_raw_write(codec->control_data, params->base,
+ data, len);
+
+ if (params->mask)
+ kfree(data);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_bytes_put);
+
/**
* snd_soc_dai_set_sysclk - configure DAI system or master clock.
* @dai: DAI
@@ -2998,7 +3207,7 @@ static inline char *fmt_multiple_name(struct device *dev,
struct snd_soc_dai_driver *dai_drv)
{
if (dai_drv->name == NULL) {
- printk(KERN_ERR "asoc: error - multiple DAI %s registered with no name\n",
+ pr_err("asoc: error - multiple DAI %s registered with no name\n",
dev_name(dev));
return NULL;
}
@@ -3281,6 +3490,7 @@ int snd_soc_register_codec(struct device *dev,
codec->volatile_register = codec_drv->volatile_register;
codec->readable_register = codec_drv->readable_register;
codec->writable_register = codec_drv->writable_register;
+ codec->ignore_pmdown_time = codec_drv->ignore_pmdown_time;
codec->dapm.bias_level = SND_SOC_BIAS_OFF;
codec->dapm.dev = dev;
codec->dapm.codec = codec;
@@ -3469,8 +3679,7 @@ static int __init snd_soc_init(void)
#ifdef CONFIG_DEBUG_FS
snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL);
if (IS_ERR(snd_soc_debugfs_root) || !snd_soc_debugfs_root) {
- printk(KERN_WARNING
- "ASoC: Failed to create debugfs directory\n");
+ pr_warn("ASoC: Failed to create debugfs directory\n");
snd_soc_debugfs_root = NULL;
}
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 31a06b2b4442..c9b088dab1cf 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -14,19 +14,13 @@
* dynamic configuration of codec internal audio paths and active
* DACs/ADCs.
* o Platform power domain - can support external components i.e. amps and
- * mic/meadphone insertion events.
+ * mic/headphone insertion events.
* o Automatic Mic Bias support
* o Jack insertion power event initiation - e.g. hp insertion will enable
* sinks, dacs, etc
- * o Delayed powerdown of audio susbsystem to reduce pops between a quick
+ * o Delayed power down of audio subsystem to reduce pops between a quick
* device reopen.
*
- * Todo:
- * o DAPM power change sequencing - allow for configurable per
- * codec sequences.
- * o Support for analogue bias optimisation.
- * o Support for reduced codec oversampling rates.
- * o Support for reduced codec bias currents.
*/
#include <linux/module.h>
@@ -40,6 +34,7 @@
#include <linux/jiffies.h>
#include <linux/debugfs.h>
#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -55,7 +50,9 @@
static int dapm_up_seq[] = {
[snd_soc_dapm_pre] = 0,
[snd_soc_dapm_supply] = 1,
+ [snd_soc_dapm_regulator_supply] = 1,
[snd_soc_dapm_micbias] = 2,
+ [snd_soc_dapm_dai] = 3,
[snd_soc_dapm_aif_in] = 3,
[snd_soc_dapm_aif_out] = 3,
[snd_soc_dapm_mic] = 4,
@@ -90,6 +87,8 @@ static int dapm_down_seq[] = {
[snd_soc_dapm_value_mux] = 9,
[snd_soc_dapm_aif_in] = 10,
[snd_soc_dapm_aif_out] = 10,
+ [snd_soc_dapm_dai] = 10,
+ [snd_soc_dapm_regulator_supply] = 11,
[snd_soc_dapm_supply] = 11,
[snd_soc_dapm_post] = 12,
};
@@ -172,6 +171,19 @@ static inline struct snd_soc_card *dapm_get_soc_card(
return NULL;
}
+static void dapm_reset(struct snd_soc_card *card)
+{
+ struct snd_soc_dapm_widget *w;
+
+ memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
+
+ list_for_each_entry(w, &card->widgets, list) {
+ w->power_checked = false;
+ w->inputs = -1;
+ w->outputs = -1;
+ }
+}
+
static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg)
{
if (w->codec)
@@ -352,8 +364,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
case snd_soc_dapm_micbias:
case snd_soc_dapm_vmid:
case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
case snd_soc_dapm_aif_in:
case snd_soc_dapm_aif_out:
+ case snd_soc_dapm_dai:
case snd_soc_dapm_hp:
case snd_soc_dapm_mic:
case snd_soc_dapm_spk:
@@ -511,17 +525,17 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
* for widgets so cut the prefix off
* the front of the widget name.
*/
- snprintf(path->long_name, name_len, "%s %s",
- w->name + prefix_len,
+ snprintf((char *)path->long_name, name_len,
+ "%s %s", w->name + prefix_len,
w->kcontrol_news[i].name);
break;
case snd_soc_dapm_mixer_named_ctl:
- snprintf(path->long_name, name_len, "%s",
- w->kcontrol_news[i].name);
+ snprintf((char *)path->long_name, name_len,
+ "%s", w->kcontrol_news[i].name);
break;
}
- path->long_name[name_len - 1] = '\0';
+ ((char *)path->long_name)[name_len - 1] = '\0';
path->kcontrol = snd_soc_cnew(&w->kcontrol_news[i],
wlist, path->long_name,
@@ -555,7 +569,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
struct snd_soc_dapm_widget_list *wlist;
int shared, wlistentries;
size_t wlistsize;
- char *name;
+ const char *name;
if (w->num_kcontrols != 1) {
dev_err(dapm->dev,
@@ -680,12 +694,18 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
DAPM_UPDATE_STAT(widget, path_checks);
- if (widget->id == snd_soc_dapm_supply)
+ switch (widget->id) {
+ case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
return 0;
+ default:
+ break;
+ }
switch (widget->id) {
case snd_soc_dapm_adc:
case snd_soc_dapm_aif_out:
+ case snd_soc_dapm_dai:
if (widget->active) {
widget->outputs = snd_soc_dapm_suspend_check(widget);
return widget->outputs;
@@ -745,13 +765,19 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
DAPM_UPDATE_STAT(widget, path_checks);
- if (widget->id == snd_soc_dapm_supply)
+ switch (widget->id) {
+ case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
return 0;
+ default:
+ break;
+ }
/* active stream ? */
switch (widget->id) {
case snd_soc_dapm_dac:
case snd_soc_dapm_aif_in:
+ case snd_soc_dapm_dai:
if (widget->active) {
widget->inputs = snd_soc_dapm_suspend_check(widget);
return widget->inputs;
@@ -828,6 +854,19 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
}
EXPORT_SYMBOL_GPL(dapm_reg_event);
+/*
+ * Handler for regulator supply widget.
+ */
+int dapm_regulator_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ return regulator_enable(w->priv);
+ else
+ return regulator_disable_deferred(w->priv, w->shift);
+}
+EXPORT_SYMBOL_GPL(dapm_regulator_event);
+
static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
{
if (w->power_checked)
@@ -858,6 +897,13 @@ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
return out != 0 && in != 0;
}
+static int dapm_dai_check_power(struct snd_soc_dapm_widget *w)
+{
+ DAPM_UPDATE_STAT(w, power_checks);
+
+ return w->active;
+}
+
/* Check to see if an ADC has power */
static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
{
@@ -1258,7 +1304,7 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
dev_err(d->dev, "Failed to turn off bias: %d\n", ret);
if (d->dev)
- pm_runtime_put_sync(d->dev);
+ pm_runtime_put(d->dev);
}
/* If we just powered up then move to active bias */
@@ -1308,6 +1354,7 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
}
switch (w->id) {
case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
/* Supplies can't affect their outputs, only their inputs */
break;
default:
@@ -1380,13 +1427,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
}
}
- memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
-
- list_for_each_entry(w, &card->widgets, list) {
- w->power_checked = false;
- w->inputs = -1;
- w->outputs = -1;
- }
+ dapm_reset(card);
/* Check which widgets we need to power and store them in
* lists indicating if they should be powered up or down. We
@@ -1407,10 +1448,15 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
/* Supplies and micbiases only bring the
* context up to STANDBY as unless something
* else is active and passing audio they
- * generally don't require full power.
+ * generally don't require full power. Signal
+ * generators are virtual pins and have no
+ * power impact themselves.
*/
switch (w->id) {
+ case snd_soc_dapm_siggen:
+ break;
case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
case snd_soc_dapm_micbias:
if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
d->target_bias_level = SND_SOC_BIAS_STANDBY;
@@ -1482,6 +1528,12 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
&async_domain);
async_synchronize_full_domain(&async_domain);
+ /* do we need to notify any clients that DAPM event is complete */
+ list_for_each_entry(d, &card->dapm_list, list) {
+ if (d->stream_event)
+ d->stream_event(d, event);
+ }
+
pop_dbg(dapm->dev, card->pop_time,
"DAPM sequencing finished, waiting %dms\n", card->pop_time);
pop_wait(card->pop_time);
@@ -1666,9 +1718,8 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
#endif
/* test and update the power status of a mux widget */
-static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
- struct snd_kcontrol *kcontrol, int change,
- int mux, struct soc_enum *e)
+int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
+ struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
{
struct snd_soc_dapm_path *path;
int found = 0;
@@ -1678,9 +1729,6 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
widget->id != snd_soc_dapm_value_mux)
return -ENODEV;
- if (!change)
- return 0;
-
/* find dapm widget path assoc with kcontrol */
list_for_each_entry(path, &widget->dapm->card->paths, list) {
if (path->kcontrol != kcontrol)
@@ -1709,9 +1757,10 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
return 0;
}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
/* test and update the power status of a mixer or switch widget */
-static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
+int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
struct snd_kcontrol *kcontrol, int connect)
{
struct snd_soc_dapm_path *path;
@@ -1740,6 +1789,7 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
return 0;
}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
/* show dapm widget status in sys fs */
static ssize_t dapm_widget_show(struct device *dev,
@@ -1769,6 +1819,7 @@ static ssize_t dapm_widget_show(struct device *dev,
case snd_soc_dapm_mixer:
case snd_soc_dapm_mixer_named_ctl:
case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
if (w->name)
count += sprintf(buf + count, "%s: %s\n",
w->name, w->power ? "On":"Off");
@@ -1876,10 +1927,12 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
return -EINVAL;
}
+ if (w->connected != status)
+ dapm_mark_dirty(w, "pin configuration");
+
w->connected = status;
if (status == 0)
w->force = 0;
- dapm_mark_dirty(w, "pin configuration");
return 0;
}
@@ -2007,8 +2060,10 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
case snd_soc_dapm_pre:
case snd_soc_dapm_post:
case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
case snd_soc_dapm_aif_in:
case snd_soc_dapm_aif_out:
+ case snd_soc_dapm_dai:
list_add(&path->list, &dapm->card->paths);
list_add(&path->list_sink, &wsink->sources);
list_add(&path->list_source, &wsource->sinks);
@@ -2322,7 +2377,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- dapm_mixer_update_power(widget, kcontrol, connect);
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, connect);
widget->dapm->update = NULL;
}
@@ -2413,7 +2468,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- dapm_mux_update_power(widget, kcontrol, change, mux, e);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
widget->dapm->update = NULL;
}
@@ -2474,8 +2529,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
widget->value = ucontrol->value.enumerated.item[0];
- dapm_mux_update_power(widget, kcontrol, change,
- widget->value, e);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, widget->value, e);
}
}
@@ -2578,7 +2632,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- dapm_mux_update_power(widget, kcontrol, change, mux, e);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
widget->dapm->update = NULL;
}
@@ -2618,15 +2672,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch);
int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
const char *pin = (const char *)kcontrol->private_value;
- mutex_lock(&codec->mutex);
+ mutex_lock(&card->mutex);
ucontrol->value.integer.value[0] =
- snd_soc_dapm_get_pin_status(&codec->dapm, pin);
+ snd_soc_dapm_get_pin_status(&card->dapm, pin);
- mutex_unlock(&codec->mutex);
+ mutex_unlock(&card->mutex);
return 0;
}
@@ -2641,41 +2695,48 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch);
int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
const char *pin = (const char *)kcontrol->private_value;
- mutex_lock(&codec->mutex);
+ mutex_lock(&card->mutex);
if (ucontrol->value.integer.value[0])
- snd_soc_dapm_enable_pin(&codec->dapm, pin);
+ snd_soc_dapm_enable_pin(&card->dapm, pin);
else
- snd_soc_dapm_disable_pin(&codec->dapm, pin);
+ snd_soc_dapm_disable_pin(&card->dapm, pin);
- snd_soc_dapm_sync(&codec->dapm);
+ snd_soc_dapm_sync(&card->dapm);
- mutex_unlock(&codec->mutex);
+ mutex_unlock(&card->mutex);
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
-/**
- * snd_soc_dapm_new_control - create new dapm control
- * @dapm: DAPM context
- * @widget: widget template
- *
- * Creates a new dapm control based upon the template.
- *
- * Returns 0 for success else error.
- */
-int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
- const struct snd_soc_dapm_widget *widget)
+static struct snd_soc_dapm_widget *
+snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
+ const struct snd_soc_dapm_widget *widget)
{
struct snd_soc_dapm_widget *w;
size_t name_len;
+ int ret;
if ((w = dapm_cnew_widget(widget)) == NULL)
- return -ENOMEM;
+ return NULL;
+
+ switch (w->id) {
+ case snd_soc_dapm_regulator_supply:
+ w->priv = devm_regulator_get(dapm->dev, w->name);
+ if (IS_ERR(w->priv)) {
+ ret = PTR_ERR(w->priv);
+ dev_err(dapm->dev, "Failed to request %s: %d\n",
+ w->name, ret);
+ return NULL;
+ }
+ break;
+ default:
+ break;
+ }
name_len = strlen(widget->name) + 1;
if (dapm->codec && dapm->codec->name_prefix)
@@ -2683,13 +2744,13 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
w->name = kmalloc(name_len, GFP_KERNEL);
if (w->name == NULL) {
kfree(w);
- return -ENOMEM;
+ return NULL;
}
if (dapm->codec && dapm->codec->name_prefix)
- snprintf(w->name, name_len, "%s %s",
+ snprintf((char *)w->name, name_len, "%s %s",
dapm->codec->name_prefix, widget->name);
else
- snprintf(w->name, name_len, "%s", widget->name);
+ snprintf((char *)w->name, name_len, "%s", widget->name);
switch (w->id) {
case snd_soc_dapm_switch:
@@ -2722,8 +2783,12 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
w->power_check = dapm_generic_check_power;
break;
case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
w->power_check = dapm_supply_check_power;
break;
+ case snd_soc_dapm_dai:
+ w->power_check = dapm_dai_check_power;
+ break;
default:
w->power_check = dapm_always_on_check_power;
break;
@@ -2741,9 +2806,8 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
/* machine layer set ups unconnected pins and insertions */
w->connected = 1;
- return 0;
+ return w;
}
-EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
/**
* snd_soc_dapm_new_controls - create new dapm controls
@@ -2759,15 +2823,16 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_widget *widget,
int num)
{
- int i, ret;
+ struct snd_soc_dapm_widget *w;
+ int i;
for (i = 0; i < num; i++) {
- ret = snd_soc_dapm_new_control(dapm, widget);
- if (ret < 0) {
+ w = snd_soc_dapm_new_control(dapm, widget);
+ if (!w) {
dev_err(dapm->dev,
- "ASoC: Failed to create DAPM control %s: %d\n",
- widget->name, ret);
- return ret;
+ "ASoC: Failed to create DAPM control %s\n",
+ widget->name);
+ return -ENOMEM;
}
widget++;
}
@@ -2775,40 +2840,140 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
-static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
- const char *stream, int event)
+int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
+ struct snd_soc_dai *dai)
{
+ struct snd_soc_dapm_widget template;
struct snd_soc_dapm_widget *w;
- list_for_each_entry(w, &dapm->card->widgets, list)
- {
- if (!w->sname || w->dapm != dapm)
+ WARN_ON(dapm->dev != dai->dev);
+
+ memset(&template, 0, sizeof(template));
+ template.reg = SND_SOC_NOPM;
+
+ if (dai->driver->playback.stream_name) {
+ template.id = snd_soc_dapm_dai;
+ template.name = dai->driver->playback.stream_name;
+ template.sname = dai->driver->playback.stream_name;
+
+ dev_dbg(dai->dev, "adding %s widget\n",
+ template.name);
+
+ w = snd_soc_dapm_new_control(dapm, &template);
+ if (!w) {
+ dev_err(dapm->dev, "Failed to create %s widget\n",
+ dai->driver->playback.stream_name);
+ }
+
+ w->priv = dai;
+ dai->playback_widget = w;
+ }
+
+ if (dai->driver->capture.stream_name) {
+ template.id = snd_soc_dapm_dai;
+ template.name = dai->driver->capture.stream_name;
+ template.sname = dai->driver->capture.stream_name;
+
+ dev_dbg(dai->dev, "adding %s widget\n",
+ template.name);
+
+ w = snd_soc_dapm_new_control(dapm, &template);
+ if (!w) {
+ dev_err(dapm->dev, "Failed to create %s widget\n",
+ dai->driver->capture.stream_name);
+ }
+
+ w->priv = dai;
+ dai->capture_widget = w;
+ }
+
+ return 0;
+}
+
+int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
+{
+ struct snd_soc_dapm_widget *dai_w, *w;
+ struct snd_soc_dai *dai;
+ struct snd_soc_dapm_route r;
+
+ memset(&r, 0, sizeof(r));
+
+ /* For each DAI widget... */
+ list_for_each_entry(dai_w, &card->widgets, list) {
+ if (dai_w->id != snd_soc_dapm_dai)
continue;
- dev_vdbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n",
- w->name, w->sname, stream, event);
- if (strstr(w->sname, stream)) {
- dapm_mark_dirty(w, "stream event");
- switch(event) {
- case SND_SOC_DAPM_STREAM_START:
- w->active = 1;
- break;
- case SND_SOC_DAPM_STREAM_STOP:
- w->active = 0;
- break;
- case SND_SOC_DAPM_STREAM_SUSPEND:
- case SND_SOC_DAPM_STREAM_RESUME:
- case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
- case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
- break;
+
+ dai = dai_w->priv;
+
+ /* ...find all widgets with the same stream and link them */
+ list_for_each_entry(w, &card->widgets, list) {
+ if (w->dapm != dai_w->dapm)
+ continue;
+
+ if (w->id == snd_soc_dapm_dai)
+ continue;
+
+ if (!w->sname)
+ continue;
+
+ if (dai->driver->playback.stream_name &&
+ strstr(w->sname,
+ dai->driver->playback.stream_name)) {
+ r.source = dai->playback_widget->name;
+ r.sink = w->name;
+ dev_dbg(dai->dev, "%s -> %s\n",
+ r.source, r.sink);
+
+ snd_soc_dapm_add_route(w->dapm, &r);
+ }
+
+ if (dai->driver->capture.stream_name &&
+ strstr(w->sname,
+ dai->driver->capture.stream_name)) {
+ r.source = w->name;
+ r.sink = dai->capture_widget->name;
+ dev_dbg(dai->dev, "%s -> %s\n",
+ r.source, r.sink);
+
+ snd_soc_dapm_add_route(w->dapm, &r);
}
}
}
- dapm_power_widgets(dapm, event);
+ return 0;
+}
+
+static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
+ int stream, struct snd_soc_dai *dai,
+ int event)
+{
+ struct snd_soc_dapm_widget *w;
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ w = dai->playback_widget;
+ else
+ w = dai->capture_widget;
- /* do we need to notify any clients that DAPM stream is complete */
- if (dapm->stream_event)
- dapm->stream_event(dapm, event);
+ if (!w)
+ return;
+
+ dapm_mark_dirty(w, "stream event");
+
+ switch (event) {
+ case SND_SOC_DAPM_STREAM_START:
+ w->active = 1;
+ break;
+ case SND_SOC_DAPM_STREAM_STOP:
+ w->active = 0;
+ break;
+ case SND_SOC_DAPM_STREAM_SUSPEND:
+ case SND_SOC_DAPM_STREAM_RESUME:
+ case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
+ case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
+ break;
+ }
+
+ dapm_power_widgets(dapm, event);
}
/**
@@ -2822,16 +2987,13 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
*
* Returns 0 for success else error.
*/
-int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
- const char *stream, int event)
+int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
+ struct snd_soc_dai *dai, int event)
{
struct snd_soc_codec *codec = rtd->codec;
- if (stream == NULL)
- return 0;
-
mutex_lock(&codec->mutex);
- soc_dapm_stream_event(&codec->dapm, stream, event);
+ soc_dapm_stream_event(&codec->dapm, stream, dai, event);
mutex_unlock(&codec->mutex);
return 0;
}
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c
new file mode 100644
index 000000000000..0526cf82b54f
--- /dev/null
+++ b/sound/soc/soc-dmaengine-pcm.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2012, Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Based on:
+ * imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
+ * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc.
+ * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Copyright (C) 2006 Applied Data Systems
+ *
+ * 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.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/dmaengine.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <sound/dmaengine_pcm.h>
+
+struct dmaengine_pcm_runtime_data {
+ struct dma_chan *dma_chan;
+
+ unsigned int pos;
+
+ void *data;
+};
+
+static inline struct dmaengine_pcm_runtime_data *substream_to_prtd(
+ const struct snd_pcm_substream *substream)
+{
+ return substream->runtime->private_data;
+}
+
+/**
+ * snd_dmaengine_pcm_set_data - Set dmaengine substream private data
+ * @substream: PCM substream
+ * @data: Data to set
+ */
+void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+ prtd->data = data;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_data);
+
+/**
+ * snd_dmaengine_pcm_get_data - Get dmaeinge substream private data
+ * @substream: PCM substream
+ *
+ * Returns the data previously set with snd_dmaengine_pcm_set_data
+ */
+void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+ return prtd->data;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_data);
+
+struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+ return prtd->dma_chan;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_chan);
+
+/**
+ * snd_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config
+ * @substream: PCM substream
+ * @params: hw_params
+ * @slave_config: DMA slave config
+ *
+ * This function can be used to initialize a dma_slave_config from a substream
+ * and hw_params in a dmaengine based PCM driver implementation.
+ */
+int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
+ const struct snd_pcm_hw_params *params,
+ struct dma_slave_config *slave_config)
+{
+ enum dma_slave_buswidth buswidth;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ break;
+ case SNDRV_PCM_FORMAT_S18_3LE:
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ case SNDRV_PCM_FORMAT_S24_LE:
+ case SNDRV_PCM_FORMAT_S32_LE:
+ buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ slave_config->direction = DMA_MEM_TO_DEV;
+ slave_config->dst_addr_width = buswidth;
+ } else {
+ slave_config->direction = DMA_DEV_TO_MEM;
+ slave_config->src_addr_width = buswidth;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config);
+
+static void dmaengine_pcm_dma_complete(void *arg)
+{
+ struct snd_pcm_substream *substream = arg;
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+ prtd->pos += snd_pcm_lib_period_bytes(substream);
+ if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream))
+ prtd->pos = 0;
+
+ snd_pcm_period_elapsed(substream);
+}
+
+static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+ struct dma_chan *chan = prtd->dma_chan;
+ struct dma_async_tx_descriptor *desc;
+ enum dma_transfer_direction direction;
+
+ direction = snd_pcm_substream_to_dma_direction(substream);
+
+ desc = chan->device->device_prep_dma_cyclic(chan,
+ substream->runtime->dma_addr,
+ snd_pcm_lib_buffer_bytes(substream),
+ snd_pcm_lib_period_bytes(substream), direction);
+
+ if (!desc)
+ return -ENOMEM;
+
+ desc->callback = dmaengine_pcm_dma_complete;
+ desc->callback_param = substream;
+ dmaengine_submit(desc);
+
+ return 0;
+}
+
+/**
+ * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation
+ * @substream: PCM substream
+ * @cmd: Trigger command
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function can be used as the PCM trigger callback for dmaengine based PCM
+ * driver implementations.
+ */
+int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+ int ret;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ ret = dmaengine_pcm_prepare_and_submit(substream);
+ if (ret)
+ return ret;
+ dma_async_issue_pending(prtd->dma_chan);
+ break;
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ dmaengine_resume(prtd->dma_chan);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ dmaengine_pause(prtd->dma_chan);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ dmaengine_terminate_all(prtd->dma_chan);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger);
+
+/**
+ * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation
+ * @substream: PCM substream
+ *
+ * This function can be used as the PCM pointer callback for dmaengine based PCM
+ * driver implementations.
+ */
+snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+ return bytes_to_frames(substream->runtime, prtd->pos);
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer);
+
+static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd,
+ dma_filter_fn filter_fn, void *filter_data)
+{
+ dma_cap_mask_t mask;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_cap_set(DMA_CYCLIC, mask);
+ prtd->dma_chan = dma_request_channel(mask, filter_fn, filter_data);
+
+ if (!prtd->dma_chan)
+ return -ENXIO;
+
+ return 0;
+}
+
+/**
+ * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream
+ * @substream: PCM substream
+ * @filter_fn: Filter function used to request the DMA channel
+ * @filter_data: Data passed to the DMA filter function
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function will request a DMA channel using the passed filter function and
+ * data. The function should usually be called from the pcm open callback.
+ *
+ * Note that this function will use private_data field of the substream's
+ * runtime. So it is not availabe to your pcm driver implementation. If you need
+ * to keep additional data attached to a substream use
+ * snd_dmaeinge_pcm_{set,get}_data.
+ */
+int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
+ dma_filter_fn filter_fn, void *filter_data)
+{
+ struct dmaengine_pcm_runtime_data *prtd;
+ int ret;
+
+ ret = snd_pcm_hw_constraint_integer(substream->runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ return ret;
+
+ prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
+ if (!prtd)
+ return -ENOMEM;
+
+ ret = dmaengine_pcm_request_channel(prtd, filter_fn, filter_data);
+ if (ret < 0) {
+ kfree(prtd);
+ return ret;
+ }
+
+ substream->runtime->private_data = prtd;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open);
+
+/**
+ * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream
+ * @substream: PCM substream
+ */
+int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+ dma_release_channel(prtd->dma_chan);
+ kfree(prtd);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close);
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index 39ba5070ff92..4d8dc6a27d4d 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -114,6 +114,7 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
enum snd_soc_control_type control)
{
struct regmap_config config;
+ int ret;
memset(&config, 0, sizeof(config));
codec->write = hw_write;
@@ -141,6 +142,11 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
case SND_SOC_REGMAP:
/* Device has made its own regmap arrangements */
codec->using_regmap = true;
+
+ ret = regmap_get_val_bytes(codec->control_data);
+ /* Errors are legitimate for non-integer byte multiples */
+ if (ret > 0)
+ codec->val_bytes = ret;
break;
default:
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 326890148a26..0ad8dcacd2f3 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -68,7 +68,7 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
* like the DAC/ADC resolution to use but there isn't right now.
*/
static int sample_sizes[] = {
- 8, 16, 24, 32,
+ 24, 32,
};
static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
@@ -123,8 +123,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (cpu_dai->driver->ops->startup) {
ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: can't open interface %s\n",
- cpu_dai->name);
+ dev_err(cpu_dai->dev, "can't open interface %s: %d\n",
+ cpu_dai->name, ret);
goto out;
}
}
@@ -132,7 +132,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (platform->driver->ops && platform->driver->ops->open) {
ret = platform->driver->ops->open(substream);
if (ret < 0) {
- printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
+ dev_err(platform->dev, "can't open platform %s: %d\n",
+ platform->name, ret);
goto platform_err;
}
}
@@ -140,8 +141,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (codec_dai->driver->ops->startup) {
ret = codec_dai->driver->ops->startup(substream, codec_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: can't open codec %s\n",
- codec_dai->name);
+ dev_err(codec_dai->dev, "can't open codec %s: %d\n",
+ codec_dai->name, ret);
goto codec_dai_err;
}
}
@@ -149,7 +150,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
ret = rtd->dai_link->ops->startup(substream);
if (ret < 0) {
- printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name);
+ pr_err("asoc: %s startup failed: %d\n",
+ rtd->dai_link->name, ret);
goto machine_err;
}
}
@@ -305,9 +307,8 @@ static void close_delayed_work(struct work_struct *work)
/* are we waiting on this codec DAI stream */
if (codec_dai->pop_wait == 1) {
codec_dai->pop_wait = 0;
- snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_STOP);
+ snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
+ codec_dai, SND_SOC_DAPM_STREAM_STOP);
}
mutex_unlock(&rtd->pcm_mutex);
@@ -367,12 +368,13 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
cpu_dai->runtime = NULL;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- if (codec->ignore_pmdown_time ||
+ if (!rtd->pmdown_time || codec->ignore_pmdown_time ||
rtd->dai_link->ignore_pmdown_time) {
/* powered down playback stream now */
snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_STOP);
+ SNDRV_PCM_STREAM_PLAYBACK,
+ codec_dai,
+ SND_SOC_DAPM_STREAM_STOP);
} else {
/* start delayed pop wq here for playback streams */
codec_dai->pop_wait = 1;
@@ -381,9 +383,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
}
} else {
/* capture streams can be powered down now */
- snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->capture.stream_name,
- SND_SOC_DAPM_STREAM_STOP);
+ snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
+ codec_dai, SND_SOC_DAPM_STREAM_STOP);
}
mutex_unlock(&rtd->pcm_mutex);
@@ -413,7 +414,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
ret = rtd->dai_link->ops->prepare(substream);
if (ret < 0) {
- printk(KERN_ERR "asoc: machine prepare error\n");
+ pr_err("asoc: machine prepare error: %d\n", ret);
goto out;
}
}
@@ -421,7 +422,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
if (platform->driver->ops && platform->driver->ops->prepare) {
ret = platform->driver->ops->prepare(substream);
if (ret < 0) {
- printk(KERN_ERR "asoc: platform prepare error\n");
+ dev_err(platform->dev, "platform prepare error: %d\n",
+ ret);
goto out;
}
}
@@ -429,7 +431,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
if (codec_dai->driver->ops->prepare) {
ret = codec_dai->driver->ops->prepare(substream, codec_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: codec DAI prepare error\n");
+ dev_err(codec_dai->dev, "DAI prepare error: %d\n",
+ ret);
goto out;
}
}
@@ -437,7 +440,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
if (cpu_dai->driver->ops->prepare) {
ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: cpu DAI prepare error\n");
+ dev_err(cpu_dai->dev, "DAI prepare error: %d\n",
+ ret);
goto out;
}
}
@@ -449,14 +453,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
cancel_delayed_work(&rtd->delayed_work);
}
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_START);
- else
- snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->capture.stream_name,
- SND_SOC_DAPM_STREAM_START);
+ snd_soc_dapm_stream_event(rtd, substream->stream, codec_dai,
+ SND_SOC_DAPM_STREAM_START);
snd_soc_dai_digital_mute(codec_dai, 0);
@@ -484,7 +482,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
ret = rtd->dai_link->ops->hw_params(substream, params);
if (ret < 0) {
- printk(KERN_ERR "asoc: machine hw_params failed\n");
+ pr_err("asoc: machine hw_params failed: %d\n", ret);
goto out;
}
}
@@ -492,8 +490,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
if (codec_dai->driver->ops->hw_params) {
ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: can't set codec %s hw params\n",
- codec_dai->name);
+ dev_err(codec_dai->dev, "can't set %s hw params: %d\n",
+ codec_dai->name, ret);
goto codec_err;
}
}
@@ -501,8 +499,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
if (cpu_dai->driver->ops->hw_params) {
ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: interface %s hw params failed\n",
- cpu_dai->name);
+ dev_err(cpu_dai->dev, "%s hw params failed: %d\n",
+ cpu_dai->name, ret);
goto interface_err;
}
}
@@ -510,8 +508,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
if (platform->driver->ops && platform->driver->ops->hw_params) {
ret = platform->driver->ops->hw_params(substream, params);
if (ret < 0) {
- printk(KERN_ERR "asoc: platform %s hw params failed\n",
- platform->name);
+ dev_err(platform->dev, "%s hw params failed: %d\n",
+ platform->name, ret);
goto platform_err;
}
}
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
index 4a0e805c4edd..2a27725cc9b1 100644
--- a/sound/soc/tegra/tegra_alc5632.c
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -18,6 +18,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/gpio.h>
+#include <linux/of_gpio.h>
#include <sound/core.h>
#include <sound/jack.h>
@@ -34,8 +35,13 @@
#define DRV_NAME "tegra-alc5632"
+#define GPIO_HP_DET BIT(0)
+
struct tegra_alc5632 {
struct tegra_asoc_utils_data util_data;
+ struct platform_device *pcm_dev;
+ int gpio_requested;
+ int gpio_hp_det;
};
static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream,
@@ -85,24 +91,18 @@ static struct snd_soc_jack_pin tegra_alc5632_hs_jack_pins[] = {
},
};
+static struct snd_soc_jack_gpio tegra_alc5632_hp_jack_gpio = {
+ .name = "Headset detection",
+ .report = SND_JACK_HEADSET,
+ .debounce_time = 150,
+ .invert = 1,
+};
+
static const struct snd_soc_dapm_widget tegra_alc5632_dapm_widgets[] = {
SND_SOC_DAPM_SPK("Int Spk", NULL),
SND_SOC_DAPM_HP("Headset Stereophone", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
-};
-
-static const struct snd_soc_dapm_route tegra_alc5632_audio_map[] = {
- /* Internal Speaker */
- {"Int Spk", NULL, "SPKOUT"},
- {"Int Spk", NULL, "SPKOUTN"},
-
- /* Headset Mic */
- {"MIC1", NULL, "MICBIAS1"},
- {"MICBIAS1", NULL, "Headset Mic"},
-
- /* Headset Stereophone */
- {"Headset Stereophone", NULL, "HPR"},
- {"Headset Stereophone", NULL, "HPL"},
+ SND_SOC_DAPM_MIC("Digital Mic", NULL),
};
static const struct snd_kcontrol_new tegra_alc5632_controls[] = {
@@ -113,6 +113,9 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
+ struct device_node *np = codec->card->dev->of_node;
+ struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card);
+ int ret;
snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
&tegra_alc5632_hs_jack);
@@ -120,6 +123,16 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
ARRAY_SIZE(tegra_alc5632_hs_jack_pins),
tegra_alc5632_hs_jack_pins);
+ machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
+
+ if (gpio_is_valid(machine->gpio_hp_det)) {
+ tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det;
+ snd_soc_jack_add_gpios(&tegra_alc5632_hs_jack,
+ 1,
+ &tegra_alc5632_hp_jack_gpio);
+ machine->gpio_requested |= GPIO_HP_DET;
+ }
+
snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1");
return 0;
@@ -128,9 +141,7 @@ static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
static struct snd_soc_dai_link tegra_alc5632_dai = {
.name = "ALC5632",
.stream_name = "ALC5632 PCM",
- .codec_name = "alc5632.0-001e",
.platform_name = "tegra-pcm-audio",
- .cpu_dai_name = "tegra-i2s.0",
.codec_dai_name = "alc5632-hifi",
.init = tegra_alc5632_asoc_init,
.ops = &tegra_alc5632_asoc_ops,
@@ -148,8 +159,6 @@ static struct snd_soc_card snd_soc_tegra_alc5632 = {
.num_controls = ARRAY_SIZE(tegra_alc5632_controls),
.dapm_widgets = tegra_alc5632_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tegra_alc5632_dapm_widgets),
- .dapm_routes = tegra_alc5632_audio_map,
- .num_dapm_routes = ARRAY_SIZE(tegra_alc5632_audio_map),
.fully_routed = true,
};
@@ -163,45 +172,111 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
sizeof(struct tegra_alc5632), GFP_KERNEL);
if (!alc5632) {
dev_err(&pdev->dev, "Can't allocate tegra_alc5632\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err;
}
- ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev);
- if (ret)
- return ret;
-
card->dev = &pdev->dev;
platform_set_drvdata(pdev, card);
snd_soc_card_set_drvdata(card, alc5632);
+ alc5632->pcm_dev = ERR_PTR(-EINVAL);
+
+ if (!(pdev->dev.of_node)) {
+ dev_err(&pdev->dev, "Must be instantiated using device tree\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = snd_soc_of_parse_card_name(card, "nvidia,model");
+ if (ret)
+ goto err;
+
+ ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
+ if (ret)
+ goto err;
+
+ tegra_alc5632_dai.codec_of_node = of_parse_phandle(
+ pdev->dev.of_node, "nvidia,audio-codec", 0);
+
+ if (!tegra_alc5632_dai.codec_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,audio-codec' missing or invalid\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ tegra_alc5632_dai.cpu_dai_of_node = of_parse_phandle(
+ pdev->dev.of_node, "nvidia,i2s-controller", 0);
+ if (!tegra_alc5632_dai.cpu_dai_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,i2s-controller' missing or invalid\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ alc5632->pcm_dev = platform_device_register_simple(
+ "tegra-pcm-audio", -1, NULL, 0);
+ if (IS_ERR(alc5632->pcm_dev)) {
+ dev_err(&pdev->dev,
+ "Can't instantiate tegra-pcm-audio\n");
+ ret = PTR_ERR(alc5632->pcm_dev);
+ goto err;
+ }
+
+ ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev);
+ if (ret)
+ goto err_unregister;
+
ret = snd_soc_register_card(card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
ret);
- tegra_asoc_utils_fini(&alc5632->util_data);
- return ret;
+ goto err_fini_utils;
}
return 0;
+
+err_fini_utils:
+ tegra_asoc_utils_fini(&alc5632->util_data);
+err_unregister:
+ if (!IS_ERR(alc5632->pcm_dev))
+ platform_device_unregister(alc5632->pcm_dev);
+err:
+ return ret;
}
static int __devexit tegra_alc5632_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
- struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card);
+ struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card);
+
+ if (machine->gpio_requested & GPIO_HP_DET)
+ snd_soc_jack_free_gpios(&tegra_alc5632_hs_jack,
+ 1,
+ &tegra_alc5632_hp_jack_gpio);
+ machine->gpio_requested = 0;
snd_soc_unregister_card(card);
- tegra_asoc_utils_fini(&alc5632->util_data);
+ tegra_asoc_utils_fini(&machine->util_data);
+ if (!IS_ERR(machine->pcm_dev))
+ platform_device_unregister(machine->pcm_dev);
return 0;
}
+static const struct of_device_id tegra_alc5632_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra-audio-alc5632", },
+ {},
+};
+
static struct platform_driver tegra_alc5632_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
.pm = &snd_soc_pm_ops,
+ .of_match_table = tegra_alc5632_of_match,
},
.probe = tegra_alc5632_probe,
.remove = __devexit_p(tegra_alc5632_remove),
@@ -212,3 +287,4 @@ MODULE_AUTHOR("Leon Romanovsky <leon@leon.nu>");
MODULE_DESCRIPTION("Tegra+ALC5632 machine ASoC driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_alc5632_of_match);