aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/Kconfig1
-rw-r--r--sound/soc/Makefile2
-rw-r--r--sound/soc/atmel/atmel-pcm.c2
-rw-r--r--sound/soc/au1x/dbdma2.c2
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c2
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c2
-rw-r--r--sound/soc/codecs/Kconfig4
-rw-r--r--sound/soc/codecs/Makefile3
-rw-r--r--sound/soc/codecs/ac97.c2
-rw-r--r--sound/soc/codecs/ad1980.c21
-rw-r--r--sound/soc/codecs/ak4535.c18
-rw-r--r--sound/soc/codecs/ssm2602.c18
-rw-r--r--sound/soc/codecs/tlv320aic23.c21
-rw-r--r--sound/soc/codecs/tlv320aic3x.c19
-rw-r--r--sound/soc/codecs/twl4030.c22
-rw-r--r--sound/soc/codecs/uda134x.c50
-rw-r--r--sound/soc/codecs/uda1380.c18
-rw-r--r--sound/soc/codecs/wm8350.c134
-rw-r--r--sound/soc/codecs/wm8350.h8
-rw-r--r--sound/soc/codecs/wm8510.c19
-rw-r--r--sound/soc/codecs/wm8580.c21
-rw-r--r--sound/soc/codecs/wm8728.c22
-rw-r--r--sound/soc/codecs/wm8731.c19
-rw-r--r--sound/soc/codecs/wm8750.c18
-rw-r--r--sound/soc/codecs/wm8753.c22
-rw-r--r--sound/soc/codecs/wm8900.c19
-rw-r--r--sound/soc/codecs/wm8903.c18
-rw-r--r--sound/soc/codecs/wm8971.c18
-rw-r--r--sound/soc/codecs/wm8990.c22
-rw-r--r--sound/soc/codecs/wm9705.c410
-rw-r--r--sound/soc/codecs/wm9705.h14
-rw-r--r--sound/soc/codecs/wm9712.c22
-rw-r--r--sound/soc/codecs/wm9713.c32
-rw-r--r--sound/soc/davinci/davinci-pcm.c2
-rw-r--r--sound/soc/davinci/davinci-sffsdr.c20
-rw-r--r--sound/soc/fsl/Kconfig16
-rw-r--r--sound/soc/fsl/Makefile7
-rw-r--r--sound/soc/omap/omap-pcm.c2
-rw-r--r--sound/soc/pxa/Kconfig18
-rw-r--r--sound/soc/pxa/Makefile4
-rw-r--r--sound/soc/pxa/e740_wm9705.c213
-rw-r--r--sound/soc/pxa/e750_wm9705.c189
-rw-r--r--sound/soc/pxa/e800_wm9712.c116
-rw-r--r--sound/soc/pxa/zylonite.c101
-rw-r--r--sound/soc/soc-core.c31
-rw-r--r--sound/soc/soc-dapm.c57
-rw-r--r--sound/soc/soc-jack.c138
47 files changed, 1490 insertions, 449 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index ef025c66cc66..3d2bb6fc6dcc 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -6,6 +6,7 @@ menuconfig SND_SOC
6 tristate "ALSA for SoC audio support" 6 tristate "ALSA for SoC audio support"
7 select SND_PCM 7 select SND_PCM
8 select AC97_BUS if SND_SOC_AC97_BUS 8 select AC97_BUS if SND_SOC_AC97_BUS
9 select SND_JACK if INPUT=y || INPUT=SND
9 ---help--- 10 ---help---
10 11
11 If you want ASoC support, you should say Y here and also to the 12 If you want ASoC support, you should say Y here and also to the
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 86a9b1f5b0f3..0237879fd412 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,4 +1,4 @@
1snd-soc-core-objs := soc-core.o soc-dapm.o 1snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o
2 2
3obj-$(CONFIG_SND_SOC) += snd-soc-core.o 3obj-$(CONFIG_SND_SOC) += snd-soc-core.o
4obj-$(CONFIG_SND_SOC) += codecs/ 4obj-$(CONFIG_SND_SOC) += codecs/
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
index 3dcdc4e3cfa0..9ef6b96373f5 100644
--- a/sound/soc/atmel/atmel-pcm.c
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -347,7 +347,7 @@ static int atmel_pcm_mmap(struct snd_pcm_substream *substream,
347 vma->vm_end - vma->vm_start, vma->vm_page_prot); 347 vma->vm_end - vma->vm_start, vma->vm_page_prot);
348} 348}
349 349
350struct snd_pcm_ops atmel_pcm_ops = { 350static struct snd_pcm_ops atmel_pcm_ops = {
351 .open = atmel_pcm_open, 351 .open = atmel_pcm_open,
352 .close = atmel_pcm_close, 352 .close = atmel_pcm_close,
353 .ioctl = snd_pcm_lib_ioctl, 353 .ioctl = snd_pcm_lib_ioctl,
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index bc8d654576c0..30490a259148 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -305,7 +305,7 @@ static int au1xpsc_pcm_close(struct snd_pcm_substream *substream)
305 return 0; 305 return 0;
306} 306}
307 307
308struct snd_pcm_ops au1xpsc_pcm_ops = { 308static struct snd_pcm_ops au1xpsc_pcm_ops = {
309 .open = au1xpsc_pcm_open, 309 .open = au1xpsc_pcm_open,
310 .close = au1xpsc_pcm_close, 310 .close = au1xpsc_pcm_close,
311 .ioctl = snd_pcm_lib_ioctl, 311 .ioctl = snd_pcm_lib_ioctl,
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 8067cfafa3a7..8cfed1a5dcbe 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -297,7 +297,7 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
297} 297}
298#endif 298#endif
299 299
300struct snd_pcm_ops bf5xx_pcm_ac97_ops = { 300static struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
301 .open = bf5xx_pcm_open, 301 .open = bf5xx_pcm_open,
302 .ioctl = snd_pcm_lib_ioctl, 302 .ioctl = snd_pcm_lib_ioctl,
303 .hw_params = bf5xx_pcm_hw_params, 303 .hw_params = bf5xx_pcm_hw_params,
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index 53d290b3ea47..1318c4f627b7 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -184,7 +184,7 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
184 return 0 ; 184 return 0 ;
185} 185}
186 186
187struct snd_pcm_ops bf5xx_pcm_i2s_ops = { 187static struct snd_pcm_ops bf5xx_pcm_i2s_ops = {
188 .open = bf5xx_pcm_open, 188 .open = bf5xx_pcm_open,
189 .ioctl = snd_pcm_lib_ioctl, 189 .ioctl = snd_pcm_lib_ioctl,
190 .hw_params = bf5xx_pcm_hw_params, 190 .hw_params = bf5xx_pcm_hw_params,
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index d0e0d691ae51..cb5fcd605acc 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -34,6 +34,7 @@ config SND_SOC_ALL_CODECS
34 select SND_SOC_WM8903 if I2C 34 select SND_SOC_WM8903 if I2C
35 select SND_SOC_WM8971 if I2C 35 select SND_SOC_WM8971 if I2C
36 select SND_SOC_WM8990 if I2C 36 select SND_SOC_WM8990 if I2C
37 select SND_SOC_WM9705 if SND_SOC_AC97_BUS
37 select SND_SOC_WM9712 if SND_SOC_AC97_BUS 38 select SND_SOC_WM9712 if SND_SOC_AC97_BUS
38 select SND_SOC_WM9713 if SND_SOC_AC97_BUS 39 select SND_SOC_WM9713 if SND_SOC_AC97_BUS
39 help 40 help
@@ -144,6 +145,9 @@ config SND_SOC_WM8971
144config SND_SOC_WM8990 145config SND_SOC_WM8990
145 tristate 146 tristate
146 147
148config SND_SOC_WM9705
149 tristate
150
147config SND_SOC_WM9712 151config SND_SOC_WM9712
148 tristate 152 tristate
149 153
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index c4ddc9aa2bbd..3664cdc300b2 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -23,6 +23,7 @@ snd-soc-wm8900-objs := wm8900.o
23snd-soc-wm8903-objs := wm8903.o 23snd-soc-wm8903-objs := wm8903.o
24snd-soc-wm8971-objs := wm8971.o 24snd-soc-wm8971-objs := wm8971.o
25snd-soc-wm8990-objs := wm8990.o 25snd-soc-wm8990-objs := wm8990.o
26snd-soc-wm9705-objs := wm9705.o
26snd-soc-wm9712-objs := wm9712.o 27snd-soc-wm9712-objs := wm9712.o
27snd-soc-wm9713-objs := wm9713.o 28snd-soc-wm9713-objs := wm9713.o
28 29
@@ -51,5 +52,7 @@ obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o
51obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o 52obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o
52obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o 53obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o
53obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o 54obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
55obj-$(CONFIG_SND_SOC_WM8991) += snd-soc-wm8991.o
56obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
54obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o 57obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
55obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o 58obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index fb53e6511af2..89d41277616d 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -123,7 +123,6 @@ bus_err:
123 snd_soc_free_pcms(socdev); 123 snd_soc_free_pcms(socdev);
124 124
125err: 125err:
126 kfree(socdev->codec->reg_cache);
127 kfree(socdev->codec); 126 kfree(socdev->codec);
128 socdev->codec = NULL; 127 socdev->codec = NULL;
129 return ret; 128 return ret;
@@ -138,7 +137,6 @@ static int ac97_soc_remove(struct platform_device *pdev)
138 return 0; 137 return 0;
139 138
140 snd_soc_free_pcms(socdev); 139 snd_soc_free_pcms(socdev);
141 kfree(socdev->codec->reg_cache);
142 kfree(socdev->codec); 140 kfree(socdev->codec);
143 141
144 return 0; 142 return 0;
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 73fdbb4d4a3d..faf358758e13 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -93,20 +93,6 @@ SOC_ENUM("Capture Source", ad1980_cap_src),
93SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0), 93SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0),
94}; 94};
95 95
96/* add non dapm controls */
97static int ad1980_add_controls(struct snd_soc_codec *codec)
98{
99 int err, i;
100
101 for (i = 0; i < ARRAY_SIZE(ad1980_snd_ac97_controls); i++) {
102 err = snd_ctl_add(codec->card, snd_soc_cnew(
103 &ad1980_snd_ac97_controls[i], codec, NULL));
104 if (err < 0)
105 return err;
106 }
107 return 0;
108}
109
110static unsigned int ac97_read(struct snd_soc_codec *codec, 96static unsigned int ac97_read(struct snd_soc_codec *codec,
111 unsigned int reg) 97 unsigned int reg)
112{ 98{
@@ -123,7 +109,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec,
123 default: 109 default:
124 reg = reg >> 1; 110 reg = reg >> 1;
125 111
126 if (reg >= (ARRAY_SIZE(ad1980_reg))) 112 if (reg >= ARRAY_SIZE(ad1980_reg))
127 return -EINVAL; 113 return -EINVAL;
128 114
129 return cache[reg]; 115 return cache[reg];
@@ -137,7 +123,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
137 123
138 soc_ac97_ops.write(codec->ac97, reg, val); 124 soc_ac97_ops.write(codec->ac97, reg, val);
139 reg = reg >> 1; 125 reg = reg >> 1;
140 if (reg < (ARRAY_SIZE(ad1980_reg))) 126 if (reg < ARRAY_SIZE(ad1980_reg))
141 cache[reg] = val; 127 cache[reg] = val;
142 128
143 return 0; 129 return 0;
@@ -269,7 +255,8 @@ static int ad1980_soc_probe(struct platform_device *pdev)
269 ext_status = ac97_read(codec, AC97_EXTENDED_STATUS); 255 ext_status = ac97_read(codec, AC97_EXTENDED_STATUS);
270 ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800); 256 ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800);
271 257
272 ad1980_add_controls(codec); 258 snd_soc_add_controls(codec, ad1980_snd_ac97_controls,
259 ARRAY_SIZE(ad1980_snd_ac97_controls));
273 ret = snd_soc_init_card(socdev); 260 ret = snd_soc_init_card(socdev);
274 if (ret < 0) { 261 if (ret < 0) {
275 printk(KERN_ERR "ad1980: failed to register card\n"); 262 printk(KERN_ERR "ad1980: failed to register card\n");
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 81300d8d42ca..f17c363cb1db 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -155,21 +155,6 @@ static const struct snd_kcontrol_new ak4535_snd_controls[] = {
155 SOC_SINGLE("Mic Sidetone Volume", AK4535_VOL, 4, 7, 0), 155 SOC_SINGLE("Mic Sidetone Volume", AK4535_VOL, 4, 7, 0),
156}; 156};
157 157
158/* add non dapm controls */
159static int ak4535_add_controls(struct snd_soc_codec *codec)
160{
161 int err, i;
162
163 for (i = 0; i < ARRAY_SIZE(ak4535_snd_controls); i++) {
164 err = snd_ctl_add(codec->card,
165 snd_soc_cnew(&ak4535_snd_controls[i], codec, NULL));
166 if (err < 0)
167 return err;
168 }
169
170 return 0;
171}
172
173/* Mono 1 Mixer */ 158/* Mono 1 Mixer */
174static const struct snd_kcontrol_new ak4535_mono1_mixer_controls[] = { 159static const struct snd_kcontrol_new ak4535_mono1_mixer_controls[] = {
175 SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4535_SIG1, 4, 1, 0), 160 SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4535_SIG1, 4, 1, 0),
@@ -510,7 +495,8 @@ static int ak4535_init(struct snd_soc_device *socdev)
510 /* power on device */ 495 /* power on device */
511 ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 496 ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
512 497
513 ak4535_add_controls(codec); 498 snd_soc_add_controls(codec, ak4535_snd_controls,
499 ARRAY_SIZE(ak4535_snd_controls));
514 ak4535_add_widgets(codec); 500 ak4535_add_widgets(codec);
515 ret = snd_soc_init_card(socdev); 501 ret = snd_soc_init_card(socdev);
516 if (ret < 0) { 502 if (ret < 0) {
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index cac373616768..ec7fe3b7b0cb 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -151,21 +151,6 @@ SOC_ENUM("Capture Source", ssm2602_enum[0]),
151SOC_ENUM("Playback De-emphasis", ssm2602_enum[1]), 151SOC_ENUM("Playback De-emphasis", ssm2602_enum[1]),
152}; 152};
153 153
154/* add non dapm controls */
155static int ssm2602_add_controls(struct snd_soc_codec *codec)
156{
157 int err, i;
158
159 for (i = 0; i < ARRAY_SIZE(ssm2602_snd_controls); i++) {
160 err = snd_ctl_add(codec->card,
161 snd_soc_cnew(&ssm2602_snd_controls[i], codec, NULL));
162 if (err < 0)
163 return err;
164 }
165
166 return 0;
167}
168
169/* Output Mixer */ 154/* Output Mixer */
170static const struct snd_kcontrol_new ssm2602_output_mixer_controls[] = { 155static const struct snd_kcontrol_new ssm2602_output_mixer_controls[] = {
171SOC_DAPM_SINGLE("Line Bypass Switch", SSM2602_APANA, 3, 1, 0), 156SOC_DAPM_SINGLE("Line Bypass Switch", SSM2602_APANA, 3, 1, 0),
@@ -622,7 +607,8 @@ static int ssm2602_init(struct snd_soc_device *socdev)
622 APANA_ENABLE_MIC_BOOST); 607 APANA_ENABLE_MIC_BOOST);
623 ssm2602_write(codec, SSM2602_PWR, 0); 608 ssm2602_write(codec, SSM2602_PWR, 0);
624 609
625 ssm2602_add_controls(codec); 610 snd_soc_add_controls(codec, ssm2602_snd_controls,
611 ARRAY_SIZE(ssm2602_snd_controls));
626 ssm2602_add_widgets(codec); 612 ssm2602_add_widgets(codec);
627 ret = snd_soc_init_card(socdev); 613 ret = snd_soc_init_card(socdev);
628 if (ret < 0) { 614 if (ret < 0) {
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index cfdea007c4cb..a0e47c1dcd64 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -183,24 +183,6 @@ static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = {
183 SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph), 183 SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph),
184}; 184};
185 185
186/* add non dapm controls */
187static int tlv320aic23_add_controls(struct snd_soc_codec *codec)
188{
189
190 int err, i;
191
192 for (i = 0; i < ARRAY_SIZE(tlv320aic23_snd_controls); i++) {
193 err = snd_ctl_add(codec->card,
194 snd_soc_cnew(&tlv320aic23_snd_controls[i],
195 codec, NULL));
196 if (err < 0)
197 return err;
198 }
199
200 return 0;
201
202}
203
204/* PGA Mixer controls for Line and Mic switch */ 186/* PGA Mixer controls for Line and Mic switch */
205static const struct snd_kcontrol_new tlv320aic23_output_mixer_controls[] = { 187static const struct snd_kcontrol_new tlv320aic23_output_mixer_controls[] = {
206 SOC_DAPM_SINGLE("Line Bypass Switch", TLV320AIC23_ANLG, 3, 1, 0), 188 SOC_DAPM_SINGLE("Line Bypass Switch", TLV320AIC23_ANLG, 3, 1, 0),
@@ -718,7 +700,8 @@ static int tlv320aic23_init(struct snd_soc_device *socdev)
718 700
719 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1); 701 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1);
720 702
721 tlv320aic23_add_controls(codec); 703 snd_soc_add_controls(codec, tlv320aic23_snd_controls,
704 ARRAY_SIZE(tlv320aic23_snd_controls));
722 tlv320aic23_add_widgets(codec); 705 tlv320aic23_add_widgets(codec);
723 ret = snd_soc_init_card(socdev); 706 ret = snd_soc_init_card(socdev);
724 if (ret < 0) { 707 if (ret < 0) {
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index b47a749c5ea2..36ab0198ca3f 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -311,22 +311,6 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
311 SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]), 311 SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]),
312}; 312};
313 313
314/* add non dapm controls */
315static int aic3x_add_controls(struct snd_soc_codec *codec)
316{
317 int err, i;
318
319 for (i = 0; i < ARRAY_SIZE(aic3x_snd_controls); i++) {
320 err = snd_ctl_add(codec->card,
321 snd_soc_cnew(&aic3x_snd_controls[i],
322 codec, NULL));
323 if (err < 0)
324 return err;
325 }
326
327 return 0;
328}
329
330/* Left DAC Mux */ 314/* Left DAC Mux */
331static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = 315static const struct snd_kcontrol_new aic3x_left_dac_mux_controls =
332SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]); 316SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]);
@@ -1224,7 +1208,8 @@ static int aic3x_init(struct snd_soc_device *socdev)
1224 aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4); 1208 aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4);
1225 aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4); 1209 aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4);
1226 1210
1227 aic3x_add_controls(codec); 1211 snd_soc_add_controls(codec, aic3x_snd_controls,
1212 ARRAY_SIZE(aic3x_snd_controls));
1228 aic3x_add_widgets(codec); 1213 aic3x_add_widgets(codec);
1229 ret = snd_soc_init_card(socdev); 1214 ret = snd_soc_init_card(socdev);
1230 if (ret < 0) { 1215 if (ret < 0) {
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index ea370a4f86d5..f530c1e6d9e8 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -125,6 +125,9 @@ static inline unsigned int twl4030_read_reg_cache(struct snd_soc_codec *codec,
125{ 125{
126 u8 *cache = codec->reg_cache; 126 u8 *cache = codec->reg_cache;
127 127
128 if (reg >= TWL4030_CACHEREGNUM)
129 return -EIO;
130
128 return cache[reg]; 131 return cache[reg];
129} 132}
130 133
@@ -670,22 +673,6 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
670 0, 3, 5, 0, input_gain_tlv), 673 0, 3, 5, 0, input_gain_tlv),
671}; 674};
672 675
673/* add non dapm controls */
674static int twl4030_add_controls(struct snd_soc_codec *codec)
675{
676 int err, i;
677
678 for (i = 0; i < ARRAY_SIZE(twl4030_snd_controls); i++) {
679 err = snd_ctl_add(codec->card,
680 snd_soc_cnew(&twl4030_snd_controls[i],
681 codec, NULL));
682 if (err < 0)
683 return err;
684 }
685
686 return 0;
687}
688
689static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { 676static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
690 /* Left channel inputs */ 677 /* Left channel inputs */
691 SND_SOC_DAPM_INPUT("MAINMIC"), 678 SND_SOC_DAPM_INPUT("MAINMIC"),
@@ -1233,7 +1220,8 @@ static int twl4030_init(struct snd_soc_device *socdev)
1233 /* power on device */ 1220 /* power on device */
1234 twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1221 twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1235 1222
1236 twl4030_add_controls(codec); 1223 snd_soc_add_controls(codec, twl4030_snd_controls,
1224 ARRAY_SIZE(twl4030_snd_controls));
1237 twl4030_add_widgets(codec); 1225 twl4030_add_widgets(codec);
1238 1226
1239 ret = snd_soc_init_card(socdev); 1227 ret = snd_soc_init_card(socdev);
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index a2c5064a774b..277825d155a6 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -431,39 +431,6 @@ SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
431SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), 431SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
432}; 432};
433 433
434static int uda134x_add_controls(struct snd_soc_codec *codec)
435{
436 int err, i, n;
437 const struct snd_kcontrol_new *ctrls;
438 struct uda134x_platform_data *pd = codec->control_data;
439
440 switch (pd->model) {
441 case UDA134X_UDA1340:
442 case UDA134X_UDA1344:
443 n = ARRAY_SIZE(uda1340_snd_controls);
444 ctrls = uda1340_snd_controls;
445 break;
446 case UDA134X_UDA1341:
447 n = ARRAY_SIZE(uda1341_snd_controls);
448 ctrls = uda1341_snd_controls;
449 break;
450 default:
451 printk(KERN_ERR "%s unkown codec type: %d",
452 __func__, pd->model);
453 return -EINVAL;
454 }
455
456 for (i = 0; i < n; i++) {
457 err = snd_ctl_add(codec->card,
458 snd_soc_cnew(&ctrls[i],
459 codec, NULL));
460 if (err < 0)
461 return err;
462 }
463
464 return 0;
465}
466
467struct snd_soc_dai uda134x_dai = { 434struct snd_soc_dai uda134x_dai = {
468 .name = "UDA134X", 435 .name = "UDA134X",
469 /* playback capabilities */ 436 /* playback capabilities */
@@ -572,7 +539,22 @@ static int uda134x_soc_probe(struct platform_device *pdev)
572 goto pcm_err; 539 goto pcm_err;
573 } 540 }
574 541
575 ret = uda134x_add_controls(codec); 542 switch (pd->model) {
543 case UDA134X_UDA1340:
544 case UDA134X_UDA1344:
545 ret = snd_soc_add_controls(codec, uda1340_snd_controls,
546 ARRAY_SIZE(uda1340_snd_controls));
547 break;
548 case UDA134X_UDA1341:
549 ret = snd_soc_add_controls(codec, uda1341_snd_controls,
550 ARRAY_SIZE(uda1341_snd_controls));
551 break;
552 default:
553 printk(KERN_ERR "%s unkown codec type: %d",
554 __func__, pd->model);
555 return -EINVAL;
556 }
557
576 if (ret < 0) { 558 if (ret < 0) {
577 printk(KERN_ERR "UDA134X: failed to register controls\n"); 559 printk(KERN_ERR "UDA134X: failed to register controls\n");
578 goto pcm_err; 560 goto pcm_err;
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index e6bf0844fbf3..a957b4365b9d 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -271,21 +271,6 @@ static const struct snd_kcontrol_new uda1380_snd_controls[] = {
271 SOC_SINGLE("AGC Switch", UDA1380_AGC, 0, 1, 0), 271 SOC_SINGLE("AGC Switch", UDA1380_AGC, 0, 1, 0),
272}; 272};
273 273
274/* add non dapm controls */
275static int uda1380_add_controls(struct snd_soc_codec *codec)
276{
277 int err, i;
278
279 for (i = 0; i < ARRAY_SIZE(uda1380_snd_controls); i++) {
280 err = snd_ctl_add(codec->card,
281 snd_soc_cnew(&uda1380_snd_controls[i], codec, NULL));
282 if (err < 0)
283 return err;
284 }
285
286 return 0;
287}
288
289/* Input mux */ 274/* Input mux */
290static const struct snd_kcontrol_new uda1380_input_mux_control = 275static const struct snd_kcontrol_new uda1380_input_mux_control =
291 SOC_DAPM_ENUM("Route", uda1380_input_sel_enum); 276 SOC_DAPM_ENUM("Route", uda1380_input_sel_enum);
@@ -675,7 +660,8 @@ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk)
675 } 660 }
676 661
677 /* uda1380 init */ 662 /* uda1380 init */
678 uda1380_add_controls(codec); 663 snd_soc_add_controls(codec, uda1380_snd_controls,
664 ARRAY_SIZE(uda1380_snd_controls));
679 uda1380_add_widgets(codec); 665 uda1380_add_widgets(codec);
680 ret = snd_soc_init_card(socdev); 666 ret = snd_soc_init_card(socdev);
681 if (ret < 0) { 667 if (ret < 0) {
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index e3989d406f54..2e0db29b4998 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -51,10 +51,17 @@ struct wm8350_output {
51 u16 mute; 51 u16 mute;
52}; 52};
53 53
54struct wm8350_jack_data {
55 struct snd_soc_jack *jack;
56 int report;
57};
58
54struct wm8350_data { 59struct wm8350_data {
55 struct snd_soc_codec codec; 60 struct snd_soc_codec codec;
56 struct wm8350_output out1; 61 struct wm8350_output out1;
57 struct wm8350_output out2; 62 struct wm8350_output out2;
63 struct wm8350_jack_data hpl;
64 struct wm8350_jack_data hpr;
58 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; 65 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
59}; 66};
60 67
@@ -775,21 +782,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
775 {"Beep", NULL, "IN3R PGA"}, 782 {"Beep", NULL, "IN3R PGA"},
776}; 783};
777 784
778static int wm8350_add_controls(struct snd_soc_codec *codec)
779{
780 int err, i;
781
782 for (i = 0; i < ARRAY_SIZE(wm8350_snd_controls); i++) {
783 err = snd_ctl_add(codec->card,
784 snd_soc_cnew(&wm8350_snd_controls[i],
785 codec, NULL));
786 if (err < 0)
787 return err;
788 }
789
790 return 0;
791}
792
793static int wm8350_add_widgets(struct snd_soc_codec *codec) 785static int wm8350_add_widgets(struct snd_soc_codec *codec)
794{ 786{
795 int ret; 787 int ret;
@@ -1328,6 +1320,95 @@ static int wm8350_resume(struct platform_device *pdev)
1328 return 0; 1320 return 0;
1329} 1321}
1330 1322
1323static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data)
1324{
1325 struct wm8350_data *priv = data;
1326 u16 reg;
1327 int report;
1328 int mask;
1329 struct wm8350_jack_data *jack = NULL;
1330
1331 switch (irq) {
1332 case WM8350_IRQ_CODEC_JCK_DET_L:
1333 jack = &priv->hpl;
1334 mask = WM8350_JACK_L_LVL;
1335 break;
1336
1337 case WM8350_IRQ_CODEC_JCK_DET_R:
1338 jack = &priv->hpr;
1339 mask = WM8350_JACK_R_LVL;
1340 break;
1341
1342 default:
1343 BUG();
1344 }
1345
1346 if (!jack->jack) {
1347 dev_warn(wm8350->dev, "Jack interrupt called with no jack\n");
1348 return;
1349 }
1350
1351 /* Debounce */
1352 msleep(200);
1353
1354 reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS);
1355 if (reg & mask)
1356 report = jack->report;
1357 else
1358 report = 0;
1359
1360 snd_soc_jack_report(jack->jack, report, jack->report);
1361}
1362
1363/**
1364 * wm8350_hp_jack_detect - Enable headphone jack detection.
1365 *
1366 * @codec: WM8350 codec
1367 * @which: left or right jack detect signal
1368 * @jack: jack to report detection events on
1369 * @report: value to report
1370 *
1371 * Enables the headphone jack detection of the WM8350.
1372 */
1373int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
1374 struct snd_soc_jack *jack, int report)
1375{
1376 struct wm8350_data *priv = codec->private_data;
1377 struct wm8350 *wm8350 = codec->control_data;
1378 int irq;
1379 int ena;
1380
1381 switch (which) {
1382 case WM8350_JDL:
1383 priv->hpl.jack = jack;
1384 priv->hpl.report = report;
1385 irq = WM8350_IRQ_CODEC_JCK_DET_L;
1386 ena = WM8350_JDL_ENA;
1387 break;
1388
1389 case WM8350_JDR:
1390 priv->hpr.jack = jack;
1391 priv->hpr.report = report;
1392 irq = WM8350_IRQ_CODEC_JCK_DET_R;
1393 ena = WM8350_JDR_ENA;
1394 break;
1395
1396 default:
1397 return -EINVAL;
1398 }
1399
1400 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA);
1401 wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena);
1402
1403 /* Sync status */
1404 wm8350_hp_jack_handler(wm8350, irq, priv);
1405
1406 wm8350_unmask_irq(wm8350, irq);
1407
1408 return 0;
1409}
1410EXPORT_SYMBOL_GPL(wm8350_hp_jack_detect);
1411
1331static struct snd_soc_codec *wm8350_codec; 1412static struct snd_soc_codec *wm8350_codec;
1332 1413
1333static int wm8350_probe(struct platform_device *pdev) 1414static int wm8350_probe(struct platform_device *pdev)
@@ -1381,13 +1462,21 @@ static int wm8350_probe(struct platform_device *pdev)
1381 wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, 1462 wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME,
1382 WM8350_OUT2_VU | WM8350_OUT2R_MUTE); 1463 WM8350_OUT2_VU | WM8350_OUT2R_MUTE);
1383 1464
1465 wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L);
1466 wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R);
1467 wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L,
1468 wm8350_hp_jack_handler, priv);
1469 wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R,
1470 wm8350_hp_jack_handler, priv);
1471
1384 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 1472 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1385 if (ret < 0) { 1473 if (ret < 0) {
1386 dev_err(&pdev->dev, "failed to create pcms\n"); 1474 dev_err(&pdev->dev, "failed to create pcms\n");
1387 return ret; 1475 return ret;
1388 } 1476 }
1389 1477
1390 wm8350_add_controls(codec); 1478 snd_soc_add_controls(codec, wm8350_snd_controls,
1479 ARRAY_SIZE(wm8350_snd_controls));
1391 wm8350_add_widgets(codec); 1480 wm8350_add_widgets(codec);
1392 1481
1393 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1482 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1411,8 +1500,21 @@ static int wm8350_remove(struct platform_device *pdev)
1411 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1500 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1412 struct snd_soc_codec *codec = socdev->codec; 1501 struct snd_soc_codec *codec = socdev->codec;
1413 struct wm8350 *wm8350 = codec->control_data; 1502 struct wm8350 *wm8350 = codec->control_data;
1503 struct wm8350_data *priv = codec->private_data;
1414 int ret; 1504 int ret;
1415 1505
1506 wm8350_clear_bits(wm8350, WM8350_JACK_DETECT,
1507 WM8350_JDL_ENA | WM8350_JDR_ENA);
1508 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA);
1509
1510 wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L);
1511 wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R);
1512 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L);
1513 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R);
1514
1515 priv->hpl.jack = NULL;
1516 priv->hpr.jack = NULL;
1517
1416 /* cancel any work waiting to be queued. */ 1518 /* cancel any work waiting to be queued. */
1417 ret = cancel_delayed_work(&codec->delayed_work); 1519 ret = cancel_delayed_work(&codec->delayed_work);
1418 1520
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h
index cc2887aa6c38..d11bd9288cf9 100644
--- a/sound/soc/codecs/wm8350.h
+++ b/sound/soc/codecs/wm8350.h
@@ -17,4 +17,12 @@
17extern struct snd_soc_dai wm8350_dai; 17extern struct snd_soc_dai wm8350_dai;
18extern struct snd_soc_codec_device soc_codec_dev_wm8350; 18extern struct snd_soc_codec_device soc_codec_dev_wm8350;
19 19
20enum wm8350_jack {
21 WM8350_JDL = 1,
22 WM8350_JDR = 2,
23};
24
25int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
26 struct snd_soc_jack *jack, int report);
27
20#endif 28#endif
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 40f8238df717..abe7cce87714 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -171,22 +171,6 @@ SOC_SINGLE("Capture Boost(+20dB)", WM8510_ADCBOOST, 8, 1, 0),
171SOC_SINGLE("Mono Playback Switch", WM8510_MONOMIX, 6, 1, 1), 171SOC_SINGLE("Mono Playback Switch", WM8510_MONOMIX, 6, 1, 1),
172}; 172};
173 173
174/* add non dapm controls */
175static int wm8510_add_controls(struct snd_soc_codec *codec)
176{
177 int err, i;
178
179 for (i = 0; i < ARRAY_SIZE(wm8510_snd_controls); i++) {
180 err = snd_ctl_add(codec->card,
181 snd_soc_cnew(&wm8510_snd_controls[i], codec,
182 NULL));
183 if (err < 0)
184 return err;
185 }
186
187 return 0;
188}
189
190/* Speaker Output Mixer */ 174/* Speaker Output Mixer */
191static const struct snd_kcontrol_new wm8510_speaker_mixer_controls[] = { 175static const struct snd_kcontrol_new wm8510_speaker_mixer_controls[] = {
192SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_SPKMIX, 1, 1, 0), 176SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_SPKMIX, 1, 1, 0),
@@ -656,7 +640,8 @@ static int wm8510_init(struct snd_soc_device *socdev)
656 /* power on device */ 640 /* power on device */
657 codec->bias_level = SND_SOC_BIAS_OFF; 641 codec->bias_level = SND_SOC_BIAS_OFF;
658 wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 642 wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
659 wm8510_add_controls(codec); 643 snd_soc_add_controls(codec, wm8510_snd_controls,
644 ARRAY_SIZE(wm8510_snd_controls));
660 wm8510_add_widgets(codec); 645 wm8510_add_widgets(codec);
661 ret = snd_soc_init_card(socdev); 646 ret = snd_soc_init_card(socdev);
662 if (ret < 0) { 647 if (ret < 0) {
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index d004e5845298..3faf0e70ce10 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -200,7 +200,7 @@ static inline unsigned int wm8580_read_reg_cache(struct snd_soc_codec *codec,
200 unsigned int reg) 200 unsigned int reg)
201{ 201{
202 u16 *cache = codec->reg_cache; 202 u16 *cache = codec->reg_cache;
203 BUG_ON(reg > ARRAY_SIZE(wm8580_reg)); 203 BUG_ON(reg >= ARRAY_SIZE(wm8580_reg));
204 return cache[reg]; 204 return cache[reg];
205} 205}
206 206
@@ -223,7 +223,7 @@ static int wm8580_write(struct snd_soc_codec *codec, unsigned int reg,
223{ 223{
224 u8 data[2]; 224 u8 data[2];
225 225
226 BUG_ON(reg > ARRAY_SIZE(wm8580_reg)); 226 BUG_ON(reg >= ARRAY_SIZE(wm8580_reg));
227 227
228 /* Registers are 9 bits wide */ 228 /* Registers are 9 bits wide */
229 value &= 0x1ff; 229 value &= 0x1ff;
@@ -330,20 +330,6 @@ SOC_DOUBLE("ADC Mute Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0),
330SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), 330SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0),
331}; 331};
332 332
333/* Add non-DAPM controls */
334static int wm8580_add_controls(struct snd_soc_codec *codec)
335{
336 int err, i;
337
338 for (i = 0; i < ARRAY_SIZE(wm8580_snd_controls); i++) {
339 err = snd_ctl_add(codec->card,
340 snd_soc_cnew(&wm8580_snd_controls[i],
341 codec, NULL));
342 if (err < 0)
343 return err;
344 }
345 return 0;
346}
347static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = { 333static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = {
348SND_SOC_DAPM_DAC("DAC1", "Playback", WM8580_PWRDN1, 2, 1), 334SND_SOC_DAPM_DAC("DAC1", "Playback", WM8580_PWRDN1, 2, 1),
349SND_SOC_DAPM_DAC("DAC2", "Playback", WM8580_PWRDN1, 3, 1), 335SND_SOC_DAPM_DAC("DAC2", "Playback", WM8580_PWRDN1, 3, 1),
@@ -866,7 +852,8 @@ static int wm8580_init(struct snd_soc_device *socdev)
866 goto pcm_err; 852 goto pcm_err;
867 } 853 }
868 854
869 wm8580_add_controls(codec); 855 snd_soc_add_controls(codec, wm8580_snd_controls,
856 ARRAY_SIZE(wm8580_snd_controls));
870 wm8580_add_widgets(codec); 857 wm8580_add_widgets(codec);
871 858
872 ret = snd_soc_init_card(socdev); 859 ret = snd_soc_init_card(socdev);
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index 80b11983e137..f90dc52e975d 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -47,7 +47,7 @@ static inline unsigned int wm8728_read_reg_cache(struct snd_soc_codec *codec,
47 unsigned int reg) 47 unsigned int reg)
48{ 48{
49 u16 *cache = codec->reg_cache; 49 u16 *cache = codec->reg_cache;
50 BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults)); 50 BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults));
51 return cache[reg]; 51 return cache[reg];
52} 52}
53 53
@@ -55,7 +55,7 @@ static inline void wm8728_write_reg_cache(struct snd_soc_codec *codec,
55 u16 reg, unsigned int value) 55 u16 reg, unsigned int value)
56{ 56{
57 u16 *cache = codec->reg_cache; 57 u16 *cache = codec->reg_cache;
58 BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults)); 58 BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults));
59 cache[reg] = value; 59 cache[reg] = value;
60} 60}
61 61
@@ -92,21 +92,6 @@ SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8728_DACLVOL, WM8728_DACRVOL,
92SOC_SINGLE("Deemphasis", WM8728_DACCTL, 1, 1, 0), 92SOC_SINGLE("Deemphasis", WM8728_DACCTL, 1, 1, 0),
93}; 93};
94 94
95static int wm8728_add_controls(struct snd_soc_codec *codec)
96{
97 int err, i;
98
99 for (i = 0; i < ARRAY_SIZE(wm8728_snd_controls); i++) {
100 err = snd_ctl_add(codec->card,
101 snd_soc_cnew(&wm8728_snd_controls[i],
102 codec, NULL));
103 if (err < 0)
104 return err;
105 }
106
107 return 0;
108}
109
110/* 95/*
111 * DAPM controls. 96 * DAPM controls.
112 */ 97 */
@@ -330,7 +315,8 @@ static int wm8728_init(struct snd_soc_device *socdev)
330 /* power on device */ 315 /* power on device */
331 wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 316 wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
332 317
333 wm8728_add_controls(codec); 318 snd_soc_add_controls(codec, wm8728_snd_controls,
319 ARRAY_SIZE(wm8728_snd_controls));
334 wm8728_add_widgets(codec); 320 wm8728_add_widgets(codec);
335 ret = snd_soc_init_card(socdev); 321 ret = snd_soc_init_card(socdev);
336 if (ret < 0) { 322 if (ret < 0) {
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index c444b9f2701e..96d6e1aeaf43 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -129,22 +129,6 @@ SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0),
129SOC_ENUM("Playback De-emphasis", wm8731_enum[1]), 129SOC_ENUM("Playback De-emphasis", wm8731_enum[1]),
130}; 130};
131 131
132/* add non dapm controls */
133static int wm8731_add_controls(struct snd_soc_codec *codec)
134{
135 int err, i;
136
137 for (i = 0; i < ARRAY_SIZE(wm8731_snd_controls); i++) {
138 err = snd_ctl_add(codec->card,
139 snd_soc_cnew(&wm8731_snd_controls[i],
140 codec, NULL));
141 if (err < 0)
142 return err;
143 }
144
145 return 0;
146}
147
148/* Output Mixer */ 132/* Output Mixer */
149static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = { 133static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = {
150SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0), 134SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
@@ -543,7 +527,8 @@ static int wm8731_init(struct snd_soc_device *socdev)
543 reg = wm8731_read_reg_cache(codec, WM8731_RINVOL); 527 reg = wm8731_read_reg_cache(codec, WM8731_RINVOL);
544 wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100); 528 wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100);
545 529
546 wm8731_add_controls(codec); 530 snd_soc_add_controls(codec, wm8731_snd_controls,
531 ARRAY_SIZE(wm8731_snd_controls));
547 wm8731_add_widgets(codec); 532 wm8731_add_widgets(codec);
548 ret = snd_soc_init_card(socdev); 533 ret = snd_soc_init_card(socdev);
549 if (ret < 0) { 534 if (ret < 0) {
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 5997fa68e0d5..1578569793a2 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -231,21 +231,6 @@ SOC_SINGLE("Mono Playback Volume", WM8750_MOUTV, 0, 127, 0),
231 231
232}; 232};
233 233
234/* add non dapm controls */
235static int wm8750_add_controls(struct snd_soc_codec *codec)
236{
237 int err, i;
238
239 for (i = 0; i < ARRAY_SIZE(wm8750_snd_controls); i++) {
240 err = snd_ctl_add(codec->card,
241 snd_soc_cnew(&wm8750_snd_controls[i],
242 codec, NULL));
243 if (err < 0)
244 return err;
245 }
246 return 0;
247}
248
249/* 234/*
250 * DAPM Controls 235 * DAPM Controls
251 */ 236 */
@@ -816,7 +801,8 @@ static int wm8750_init(struct snd_soc_device *socdev)
816 reg = wm8750_read_reg_cache(codec, WM8750_RINVOL); 801 reg = wm8750_read_reg_cache(codec, WM8750_RINVOL);
817 wm8750_write(codec, WM8750_RINVOL, reg | 0x0100); 802 wm8750_write(codec, WM8750_RINVOL, reg | 0x0100);
818 803
819 wm8750_add_controls(codec); 804 snd_soc_add_controls(codec, wm8750_snd_controls,
805 ARRAY_SIZE(wm8750_snd_controls));
820 wm8750_add_widgets(codec); 806 wm8750_add_widgets(codec);
821 ret = snd_soc_init_card(socdev); 807 ret = snd_soc_init_card(socdev);
822 if (ret < 0) { 808 if (ret < 0) {
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 6c21b50c9375..5a1c1fca120f 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -97,7 +97,7 @@ static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec,
97 unsigned int reg) 97 unsigned int reg)
98{ 98{
99 u16 *cache = codec->reg_cache; 99 u16 *cache = codec->reg_cache;
100 if (reg < 1 || reg > (ARRAY_SIZE(wm8753_reg) + 1)) 100 if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1))
101 return -1; 101 return -1;
102 return cache[reg - 1]; 102 return cache[reg - 1];
103} 103}
@@ -109,7 +109,7 @@ static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec,
109 unsigned int reg, unsigned int value) 109 unsigned int reg, unsigned int value)
110{ 110{
111 u16 *cache = codec->reg_cache; 111 u16 *cache = codec->reg_cache;
112 if (reg < 1 || reg > 0x3f) 112 if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1))
113 return; 113 return;
114 cache[reg - 1] = value; 114 cache[reg - 1] = value;
115} 115}
@@ -339,21 +339,6 @@ SOC_ENUM("ADC Data Select", wm8753_enum[27]),
339SOC_ENUM("ROUT2 Phase", wm8753_enum[28]), 339SOC_ENUM("ROUT2 Phase", wm8753_enum[28]),
340}; 340};
341 341
342/* add non dapm controls */
343static int wm8753_add_controls(struct snd_soc_codec *codec)
344{
345 int err, i;
346
347 for (i = 0; i < ARRAY_SIZE(wm8753_snd_controls); i++) {
348 err = snd_ctl_add(codec->card,
349 snd_soc_cnew(&wm8753_snd_controls[i],
350 codec, NULL));
351 if (err < 0)
352 return err;
353 }
354 return 0;
355}
356
357/* 342/*
358 * _DAPM_ Controls 343 * _DAPM_ Controls
359 */ 344 */
@@ -1603,7 +1588,8 @@ static int wm8753_init(struct snd_soc_device *socdev)
1603 reg = wm8753_read_reg_cache(codec, WM8753_RINVOL); 1588 reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);
1604 wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); 1589 wm8753_write(codec, WM8753_RINVOL, reg | 0x0100);
1605 1590
1606 wm8753_add_controls(codec); 1591 snd_soc_add_controls(codec, wm8753_snd_controls,
1592 ARRAY_SIZE(wm8753_snd_controls));
1607 wm8753_add_widgets(codec); 1593 wm8753_add_widgets(codec);
1608 ret = snd_soc_init_card(socdev); 1594 ret = snd_soc_init_card(socdev);
1609 if (ret < 0) { 1595 if (ret < 0) {
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 6767de10ded0..1e08d4f065f2 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -517,22 +517,6 @@ SOC_SINGLE("LINEOUT2 LP -12dB", WM8900_REG_LOUTMIXCTL1,
517 517
518}; 518};
519 519
520/* add non dapm controls */
521static int wm8900_add_controls(struct snd_soc_codec *codec)
522{
523 int err, i;
524
525 for (i = 0; i < ARRAY_SIZE(wm8900_snd_controls); i++) {
526 err = snd_ctl_add(codec->card,
527 snd_soc_cnew(&wm8900_snd_controls[i],
528 codec, NULL));
529 if (err < 0)
530 return err;
531 }
532
533 return 0;
534}
535
536static const struct snd_kcontrol_new wm8900_dapm_loutput2_control = 520static const struct snd_kcontrol_new wm8900_dapm_loutput2_control =
537SOC_DAPM_SINGLE("LINEOUT2L Switch", WM8900_REG_POWER3, 6, 1, 0); 521SOC_DAPM_SINGLE("LINEOUT2L Switch", WM8900_REG_POWER3, 6, 1, 0);
538 522
@@ -1439,7 +1423,8 @@ static int wm8900_probe(struct platform_device *pdev)
1439 goto pcm_err; 1423 goto pcm_err;
1440 } 1424 }
1441 1425
1442 wm8900_add_controls(codec); 1426 snd_soc_add_controls(codec, wm8900_snd_controls,
1427 ARRAY_SIZE(wm8900_snd_controls));
1443 wm8900_add_widgets(codec); 1428 wm8900_add_widgets(codec);
1444 1429
1445 ret = snd_soc_init_card(socdev); 1430 ret = snd_soc_init_card(socdev);
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index bde74546db4a..6ff34b957dce 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -744,21 +744,6 @@ SOC_DOUBLE_R_TLV("Speaker Volume",
744 0, 63, 0, out_tlv), 744 0, 63, 0, out_tlv),
745}; 745};
746 746
747static int wm8903_add_controls(struct snd_soc_codec *codec)
748{
749 int err, i;
750
751 for (i = 0; i < ARRAY_SIZE(wm8903_snd_controls); i++) {
752 err = snd_ctl_add(codec->card,
753 snd_soc_cnew(&wm8903_snd_controls[i],
754 codec, NULL));
755 if (err < 0)
756 return err;
757 }
758
759 return 0;
760}
761
762static const struct snd_kcontrol_new linput_mode_mux = 747static const struct snd_kcontrol_new linput_mode_mux =
763 SOC_DAPM_ENUM("Left Input Mode Mux", linput_mode_enum); 748 SOC_DAPM_ENUM("Left Input Mode Mux", linput_mode_enum);
764 749
@@ -1737,7 +1722,8 @@ static int wm8903_probe(struct platform_device *pdev)
1737 goto err; 1722 goto err;
1738 } 1723 }
1739 1724
1740 wm8903_add_controls(socdev->codec); 1725 snd_soc_add_controls(socdev->codec, wm8903_snd_controls,
1726 ARRAY_SIZE(wm8903_snd_controls));
1741 wm8903_add_widgets(socdev->codec); 1727 wm8903_add_widgets(socdev->codec);
1742 1728
1743 ret = snd_soc_init_card(socdev); 1729 ret = snd_soc_init_card(socdev);
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 88ead7f8dd98..c8bd9b06f330 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -195,21 +195,6 @@ static const struct snd_kcontrol_new wm8971_snd_controls[] = {
195 SOC_DOUBLE_R("Mic Boost", WM8971_LADCIN, WM8971_RADCIN, 4, 3, 0), 195 SOC_DOUBLE_R("Mic Boost", WM8971_LADCIN, WM8971_RADCIN, 4, 3, 0),
196}; 196};
197 197
198/* add non-DAPM controls */
199static int wm8971_add_controls(struct snd_soc_codec *codec)
200{
201 int err, i;
202
203 for (i = 0; i < ARRAY_SIZE(wm8971_snd_controls); i++) {
204 err = snd_ctl_add(codec->card,
205 snd_soc_cnew(&wm8971_snd_controls[i],
206 codec, NULL));
207 if (err < 0)
208 return err;
209 }
210 return 0;
211}
212
213/* 198/*
214 * DAPM Controls 199 * DAPM Controls
215 */ 200 */
@@ -745,7 +730,8 @@ static int wm8971_init(struct snd_soc_device *socdev)
745 reg = wm8971_read_reg_cache(codec, WM8971_RINVOL); 730 reg = wm8971_read_reg_cache(codec, WM8971_RINVOL);
746 wm8971_write(codec, WM8971_RINVOL, reg | 0x0100); 731 wm8971_write(codec, WM8971_RINVOL, reg | 0x0100);
747 732
748 wm8971_add_controls(codec); 733 snd_soc_add_controls(codec, wm8971_snd_controls,
734 ARRAY_SIZE(wm8971_snd_controls));
749 wm8971_add_widgets(codec); 735 wm8971_add_widgets(codec);
750 ret = snd_soc_init_card(socdev); 736 ret = snd_soc_init_card(socdev);
751 if (ret < 0) { 737 if (ret < 0) {
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 5b5afc144478..f93c0955ed9d 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -116,7 +116,7 @@ static inline unsigned int wm8990_read_reg_cache(struct snd_soc_codec *codec,
116 unsigned int reg) 116 unsigned int reg)
117{ 117{
118 u16 *cache = codec->reg_cache; 118 u16 *cache = codec->reg_cache;
119 BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1); 119 BUG_ON(reg >= ARRAY_SIZE(wm8990_reg));
120 return cache[reg]; 120 return cache[reg];
121} 121}
122 122
@@ -129,7 +129,7 @@ static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec,
129 u16 *cache = codec->reg_cache; 129 u16 *cache = codec->reg_cache;
130 130
131 /* Reset register and reserved registers are uncached */ 131 /* Reset register and reserved registers are uncached */
132 if (reg == 0 || reg > ARRAY_SIZE(wm8990_reg) - 1) 132 if (reg == 0 || reg >= ARRAY_SIZE(wm8990_reg))
133 return; 133 return;
134 134
135 cache[reg] = value; 135 cache[reg] = value;
@@ -417,21 +417,6 @@ SOC_SINGLE("RIN34 Mute Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME,
417 417
418}; 418};
419 419
420/* add non dapm controls */
421static int wm8990_add_controls(struct snd_soc_codec *codec)
422{
423 int err, i;
424
425 for (i = 0; i < ARRAY_SIZE(wm8990_snd_controls); i++) {
426 err = snd_ctl_add(codec->card,
427 snd_soc_cnew(&wm8990_snd_controls[i], codec,
428 NULL));
429 if (err < 0)
430 return err;
431 }
432 return 0;
433}
434
435/* 420/*
436 * _DAPM_ Controls 421 * _DAPM_ Controls
437 */ 422 */
@@ -1460,7 +1445,8 @@ static int wm8990_init(struct snd_soc_device *socdev)
1460 wm8990_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); 1445 wm8990_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
1461 wm8990_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); 1446 wm8990_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
1462 1447
1463 wm8990_add_controls(codec); 1448 snd_soc_add_controls(codec, wm8990_snd_controls,
1449 ARRAY_SIZE(wm8990_snd_controls));
1464 wm8990_add_widgets(codec); 1450 wm8990_add_widgets(codec);
1465 ret = snd_soc_init_card(socdev); 1451 ret = snd_soc_init_card(socdev);
1466 if (ret < 0) { 1452 if (ret < 0) {
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
new file mode 100644
index 000000000000..5e1937ac0b5e
--- /dev/null
+++ b/sound/soc/codecs/wm9705.c
@@ -0,0 +1,410 @@
1/*
2 * wm9705.c -- ALSA Soc WM9705 codec support
3 *
4 * Copyright 2008 Ian Molton <spyro@f2s.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; Version 2 of the License only.
9 *
10 */
11
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/device.h>
16#include <sound/core.h>
17#include <sound/pcm.h>
18#include <sound/ac97_codec.h>
19#include <sound/initval.h>
20#include <sound/soc.h>
21#include <sound/soc-dapm.h>
22
23/*
24 * WM9705 register cache
25 */
26static const u16 wm9705_reg[] = {
27 0x6150, 0x8000, 0x8000, 0x8000, /* 0x0 */
28 0x0000, 0x8000, 0x8008, 0x8008, /* 0x8 */
29 0x8808, 0x8808, 0x8808, 0x8808, /* 0x10 */
30 0x8808, 0x0000, 0x8000, 0x0000, /* 0x18 */
31 0x0000, 0x0000, 0x0000, 0x000f, /* 0x20 */
32 0x0605, 0x0000, 0xbb80, 0x0000, /* 0x28 */
33 0x0000, 0xbb80, 0x0000, 0x0000, /* 0x30 */
34 0x0000, 0x2000, 0x0000, 0x0000, /* 0x38 */
35 0x0000, 0x0000, 0x0000, 0x0000, /* 0x40 */
36 0x0000, 0x0000, 0x0000, 0x0000, /* 0x48 */
37 0x0000, 0x0000, 0x0000, 0x0000, /* 0x50 */
38 0x0000, 0x0000, 0x0000, 0x0000, /* 0x58 */
39 0x0000, 0x0000, 0x0000, 0x0000, /* 0x60 */
40 0x0000, 0x0000, 0x0000, 0x0000, /* 0x68 */
41 0x0000, 0x0808, 0x0000, 0x0006, /* 0x70 */
42 0x0000, 0x0000, 0x574d, 0x4c05, /* 0x78 */
43};
44
45static const struct snd_kcontrol_new wm9705_snd_ac97_controls[] = {
46 SOC_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1),
47 SOC_SINGLE("Master Playback Switch", AC97_MASTER, 15, 1, 1),
48 SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1),
49 SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 1, 1),
50 SOC_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1),
51 SOC_SINGLE("PCM Playback Switch", AC97_PCM, 15, 1, 1),
52 SOC_SINGLE("Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1),
53 SOC_SINGLE("Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
54 SOC_SINGLE("PCBeep Playback Volume", AC97_PC_BEEP, 1, 15, 1),
55 SOC_SINGLE("Phone Playback Volume", AC97_PHONE, 0, 31, 1),
56 SOC_DOUBLE("Line Playback Volume", AC97_LINE, 8, 0, 31, 1),
57 SOC_DOUBLE("CD Playback Volume", AC97_CD, 8, 0, 31, 1),
58 SOC_SINGLE("Mic Playback Volume", AC97_MIC, 0, 31, 1),
59 SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 6, 1, 0),
60 SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0),
61 SOC_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1),
62};
63
64static const char *wm9705_mic[] = {"Mic 1", "Mic 2"};
65static const char *wm9705_rec_sel[] = {"Mic", "CD", "NC", "NC",
66 "Line", "Stereo Mix", "Mono Mix", "Phone"};
67
68static const struct soc_enum wm9705_enum_mic =
69 SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, wm9705_mic);
70static const struct soc_enum wm9705_enum_rec_l =
71 SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9705_rec_sel);
72static const struct soc_enum wm9705_enum_rec_r =
73 SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9705_rec_sel);
74
75/* Headphone Mixer */
76static const struct snd_kcontrol_new wm9705_hp_mixer_controls[] = {
77 SOC_DAPM_SINGLE("PCBeep Playback Switch", AC97_PC_BEEP, 15, 1, 1),
78 SOC_DAPM_SINGLE("CD Playback Switch", AC97_CD, 15, 1, 1),
79 SOC_DAPM_SINGLE("Mic Playback Switch", AC97_MIC, 15, 1, 1),
80 SOC_DAPM_SINGLE("Phone Playback Switch", AC97_PHONE, 15, 1, 1),
81 SOC_DAPM_SINGLE("Line Playback Switch", AC97_LINE, 15, 1, 1),
82};
83
84/* Mic source */
85static const struct snd_kcontrol_new wm9705_mic_src_controls =
86 SOC_DAPM_ENUM("Route", wm9705_enum_mic);
87
88/* Capture source */
89static const struct snd_kcontrol_new wm9705_capture_selectl_controls =
90 SOC_DAPM_ENUM("Route", wm9705_enum_rec_l);
91static const struct snd_kcontrol_new wm9705_capture_selectr_controls =
92 SOC_DAPM_ENUM("Route", wm9705_enum_rec_r);
93
94/* DAPM widgets */
95static const struct snd_soc_dapm_widget wm9705_dapm_widgets[] = {
96 SND_SOC_DAPM_MUX("Mic Source", SND_SOC_NOPM, 0, 0,
97 &wm9705_mic_src_controls),
98 SND_SOC_DAPM_MUX("Left Capture Source", SND_SOC_NOPM, 0, 0,
99 &wm9705_capture_selectl_controls),
100 SND_SOC_DAPM_MUX("Right Capture Source", SND_SOC_NOPM, 0, 0,
101 &wm9705_capture_selectr_controls),
102 SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback",
103 SND_SOC_NOPM, 0, 0),
104 SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback",
105 SND_SOC_NOPM, 0, 0),
106 SND_SOC_DAPM_MIXER_NAMED_CTL("HP Mixer", SND_SOC_NOPM, 0, 0,
107 &wm9705_hp_mixer_controls[0],
108 ARRAY_SIZE(wm9705_hp_mixer_controls)),
109 SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
110 SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", SND_SOC_NOPM, 0, 0),
111 SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", SND_SOC_NOPM, 0, 0),
112 SND_SOC_DAPM_PGA("Headphone PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
113 SND_SOC_DAPM_PGA("Speaker PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
114 SND_SOC_DAPM_PGA("Line PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
115 SND_SOC_DAPM_PGA("Line out PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
116 SND_SOC_DAPM_PGA("Mono PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
117 SND_SOC_DAPM_PGA("Phone PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
118 SND_SOC_DAPM_PGA("Mic PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
119 SND_SOC_DAPM_PGA("PCBEEP PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
120 SND_SOC_DAPM_PGA("CD PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
121 SND_SOC_DAPM_PGA("ADC PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
122 SND_SOC_DAPM_OUTPUT("HPOUTL"),
123 SND_SOC_DAPM_OUTPUT("HPOUTR"),
124 SND_SOC_DAPM_OUTPUT("LOUT"),
125 SND_SOC_DAPM_OUTPUT("ROUT"),
126 SND_SOC_DAPM_OUTPUT("MONOOUT"),
127 SND_SOC_DAPM_INPUT("PHONE"),
128 SND_SOC_DAPM_INPUT("LINEINL"),
129 SND_SOC_DAPM_INPUT("LINEINR"),
130 SND_SOC_DAPM_INPUT("CDINL"),
131 SND_SOC_DAPM_INPUT("CDINR"),
132 SND_SOC_DAPM_INPUT("PCBEEP"),
133 SND_SOC_DAPM_INPUT("MIC1"),
134 SND_SOC_DAPM_INPUT("MIC2"),
135};
136
137/* Audio map
138 * WM9705 has no switches to disable the route from the inputs to the HP mixer
139 * so in order to prevent active inputs from forcing the audio outputs to be
140 * constantly enabled, we use the mutes on those inputs to simulate such
141 * controls.
142 */
143static const struct snd_soc_dapm_route audio_map[] = {
144 /* HP mixer */
145 {"HP Mixer", "PCBeep Playback Switch", "PCBEEP PGA"},
146 {"HP Mixer", "CD Playback Switch", "CD PGA"},
147 {"HP Mixer", "Mic Playback Switch", "Mic PGA"},
148 {"HP Mixer", "Phone Playback Switch", "Phone PGA"},
149 {"HP Mixer", "Line Playback Switch", "Line PGA"},
150 {"HP Mixer", NULL, "Left DAC"},
151 {"HP Mixer", NULL, "Right DAC"},
152
153 /* mono mixer */
154 {"Mono Mixer", NULL, "HP Mixer"},
155
156 /* outputs */
157 {"Headphone PGA", NULL, "HP Mixer"},
158 {"HPOUTL", NULL, "Headphone PGA"},
159 {"HPOUTR", NULL, "Headphone PGA"},
160 {"Line out PGA", NULL, "HP Mixer"},
161 {"LOUT", NULL, "Line out PGA"},
162 {"ROUT", NULL, "Line out PGA"},
163 {"Mono PGA", NULL, "Mono Mixer"},
164 {"MONOOUT", NULL, "Mono PGA"},
165
166 /* inputs */
167 {"CD PGA", NULL, "CDINL"},
168 {"CD PGA", NULL, "CDINR"},
169 {"Line PGA", NULL, "LINEINL"},
170 {"Line PGA", NULL, "LINEINR"},
171 {"Phone PGA", NULL, "PHONE"},
172 {"Mic Source", "Mic 1", "MIC1"},
173 {"Mic Source", "Mic 2", "MIC2"},
174 {"Mic PGA", NULL, "Mic Source"},
175 {"PCBEEP PGA", NULL, "PCBEEP"},
176
177 /* Left capture selector */
178 {"Left Capture Source", "Mic", "Mic Source"},
179 {"Left Capture Source", "CD", "CDINL"},
180 {"Left Capture Source", "Line", "LINEINL"},
181 {"Left Capture Source", "Stereo Mix", "HP Mixer"},
182 {"Left Capture Source", "Mono Mix", "HP Mixer"},
183 {"Left Capture Source", "Phone", "PHONE"},
184
185 /* Right capture source */
186 {"Right Capture Source", "Mic", "Mic Source"},
187 {"Right Capture Source", "CD", "CDINR"},
188 {"Right Capture Source", "Line", "LINEINR"},
189 {"Right Capture Source", "Stereo Mix", "HP Mixer"},
190 {"Right Capture Source", "Mono Mix", "HP Mixer"},
191 {"Right Capture Source", "Phone", "PHONE"},
192
193 {"ADC PGA", NULL, "Left Capture Source"},
194 {"ADC PGA", NULL, "Right Capture Source"},
195
196 /* ADC's */
197 {"Left ADC", NULL, "ADC PGA"},
198 {"Right ADC", NULL, "ADC PGA"},
199};
200
201static int wm9705_add_widgets(struct snd_soc_codec *codec)
202{
203 snd_soc_dapm_new_controls(codec, wm9705_dapm_widgets,
204 ARRAY_SIZE(wm9705_dapm_widgets));
205 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
206 snd_soc_dapm_new_widgets(codec);
207
208 return 0;
209}
210
211/* We use a register cache to enhance read performance. */
212static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg)
213{
214 u16 *cache = codec->reg_cache;
215
216 switch (reg) {
217 case AC97_RESET:
218 case AC97_VENDOR_ID1:
219 case AC97_VENDOR_ID2:
220 return soc_ac97_ops.read(codec->ac97, reg);
221 default:
222 reg = reg >> 1;
223
224 if (reg >= (ARRAY_SIZE(wm9705_reg)))
225 return -EIO;
226
227 return cache[reg];
228 }
229}
230
231static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
232 unsigned int val)
233{
234 u16 *cache = codec->reg_cache;
235
236 soc_ac97_ops.write(codec->ac97, reg, val);
237 reg = reg >> 1;
238 if (reg < (ARRAY_SIZE(wm9705_reg)))
239 cache[reg] = val;
240
241 return 0;
242}
243
244static int ac97_prepare(struct snd_pcm_substream *substream,
245 struct snd_soc_dai *dai)
246{
247 struct snd_pcm_runtime *runtime = substream->runtime;
248 struct snd_soc_pcm_runtime *rtd = substream->private_data;
249 struct snd_soc_device *socdev = rtd->socdev;
250 struct snd_soc_codec *codec = socdev->codec;
251 int reg;
252 u16 vra;
253
254 vra = ac97_read(codec, AC97_EXTENDED_STATUS);
255 ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
256
257 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
258 reg = AC97_PCM_FRONT_DAC_RATE;
259 else
260 reg = AC97_PCM_LR_ADC_RATE;
261
262 return ac97_write(codec, reg, runtime->rate);
263}
264
265#define WM9705_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \
266 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
267 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
268 SNDRV_PCM_RATE_48000)
269
270struct snd_soc_dai wm9705_dai[] = {
271 {
272 .name = "AC97 HiFi",
273 .ac97_control = 1,
274 .playback = {
275 .stream_name = "HiFi Playback",
276 .channels_min = 1,
277 .channels_max = 2,
278 .rates = WM9705_AC97_RATES,
279 .formats = SNDRV_PCM_FMTBIT_S16_LE,
280 },
281 .capture = {
282 .stream_name = "HiFi Capture",
283 .channels_min = 1,
284 .channels_max = 2,
285 .rates = WM9705_AC97_RATES,
286 .formats = SNDRV_PCM_FMTBIT_S16_LE,
287 },
288 .ops = {
289 .prepare = ac97_prepare,
290 },
291 },
292 {
293 .name = "AC97 Aux",
294 .playback = {
295 .stream_name = "Aux Playback",
296 .channels_min = 1,
297 .channels_max = 1,
298 .rates = WM9705_AC97_RATES,
299 .formats = SNDRV_PCM_FMTBIT_S16_LE,
300 },
301 }
302};
303EXPORT_SYMBOL_GPL(wm9705_dai);
304
305static int wm9705_reset(struct snd_soc_codec *codec)
306{
307 if (soc_ac97_ops.reset) {
308 soc_ac97_ops.reset(codec->ac97);
309 if (ac97_read(codec, 0) == wm9705_reg[0])
310 return 0; /* Success */
311 }
312
313 return -EIO;
314}
315
316static int wm9705_soc_probe(struct platform_device *pdev)
317{
318 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
319 struct snd_soc_codec *codec;
320 int ret = 0;
321
322 printk(KERN_INFO "WM9705 SoC Audio Codec\n");
323
324 socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
325 if (socdev->codec == NULL)
326 return -ENOMEM;
327 codec = socdev->codec;
328 mutex_init(&codec->mutex);
329
330 codec->reg_cache = kmemdup(wm9705_reg, sizeof(wm9705_reg), GFP_KERNEL);
331 if (codec->reg_cache == NULL) {
332 ret = -ENOMEM;
333 goto cache_err;
334 }
335 codec->reg_cache_size = sizeof(wm9705_reg);
336 codec->reg_cache_step = 2;
337
338 codec->name = "WM9705";
339 codec->owner = THIS_MODULE;
340 codec->dai = wm9705_dai;
341 codec->num_dai = ARRAY_SIZE(wm9705_dai);
342 codec->write = ac97_write;
343 codec->read = ac97_read;
344 INIT_LIST_HEAD(&codec->dapm_widgets);
345 INIT_LIST_HEAD(&codec->dapm_paths);
346
347 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
348 if (ret < 0) {
349 printk(KERN_ERR "wm9705: failed to register AC97 codec\n");
350 goto codec_err;
351 }
352
353 /* register pcms */
354 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
355 if (ret < 0)
356 goto pcm_err;
357
358 ret = wm9705_reset(codec);
359 if (ret)
360 goto reset_err;
361
362 snd_soc_add_controls(codec, wm9705_snd_ac97_controls,
363 ARRAY_SIZE(wm9705_snd_ac97_controls));
364 wm9705_add_widgets(codec);
365
366 ret = snd_soc_init_card(socdev);
367 if (ret < 0) {
368 printk(KERN_ERR "wm9705: failed to register card\n");
369 goto pcm_err;
370 }
371
372 return 0;
373
374reset_err:
375 snd_soc_free_pcms(socdev);
376pcm_err:
377 snd_soc_free_ac97_codec(codec);
378codec_err:
379 kfree(codec->reg_cache);
380cache_err:
381 kfree(socdev->codec);
382 socdev->codec = NULL;
383 return ret;
384}
385
386static int wm9705_soc_remove(struct platform_device *pdev)
387{
388 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
389 struct snd_soc_codec *codec = socdev->codec;
390
391 if (codec == NULL)
392 return 0;
393
394 snd_soc_dapm_free(socdev);
395 snd_soc_free_pcms(socdev);
396 snd_soc_free_ac97_codec(codec);
397 kfree(codec->reg_cache);
398 kfree(codec);
399 return 0;
400}
401
402struct snd_soc_codec_device soc_codec_dev_wm9705 = {
403 .probe = wm9705_soc_probe,
404 .remove = wm9705_soc_remove,
405};
406EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705);
407
408MODULE_DESCRIPTION("ASoC WM9705 driver");
409MODULE_AUTHOR("Ian Molton");
410MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/wm9705.h b/sound/soc/codecs/wm9705.h
new file mode 100644
index 000000000000..d380f110f9e2
--- /dev/null
+++ b/sound/soc/codecs/wm9705.h
@@ -0,0 +1,14 @@
1/*
2 * wm9705.h -- WM9705 Soc Audio driver
3 */
4
5#ifndef _WM9705_H
6#define _WM9705_H
7
8#define WM9705_DAI_AC97_HIFI 0
9#define WM9705_DAI_AC97_AUX 1
10
11extern struct snd_soc_dai wm9705_dai[2];
12extern struct snd_soc_codec_device soc_codec_dev_wm9705;
13
14#endif
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index af83d629078a..4dc90d67530e 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -154,21 +154,6 @@ SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
154SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0), 154SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
155}; 155};
156 156
157/* add non dapm controls */
158static int wm9712_add_controls(struct snd_soc_codec *codec)
159{
160 int err, i;
161
162 for (i = 0; i < ARRAY_SIZE(wm9712_snd_ac97_controls); i++) {
163 err = snd_ctl_add(codec->card,
164 snd_soc_cnew(&wm9712_snd_ac97_controls[i],
165 codec, NULL));
166 if (err < 0)
167 return err;
168 }
169 return 0;
170}
171
172/* We have to create a fake left and right HP mixers because 157/* We have to create a fake left and right HP mixers because
173 * the codec only has a single control that is shared by both channels. 158 * the codec only has a single control that is shared by both channels.
174 * This makes it impossible to determine the audio path. 159 * This makes it impossible to determine the audio path.
@@ -467,7 +452,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec,
467 else { 452 else {
468 reg = reg >> 1; 453 reg = reg >> 1;
469 454
470 if (reg > (ARRAY_SIZE(wm9712_reg))) 455 if (reg >= (ARRAY_SIZE(wm9712_reg)))
471 return -EIO; 456 return -EIO;
472 457
473 return cache[reg]; 458 return cache[reg];
@@ -481,7 +466,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
481 466
482 soc_ac97_ops.write(codec->ac97, reg, val); 467 soc_ac97_ops.write(codec->ac97, reg, val);
483 reg = reg >> 1; 468 reg = reg >> 1;
484 if (reg <= (ARRAY_SIZE(wm9712_reg))) 469 if (reg < (ARRAY_SIZE(wm9712_reg)))
485 cache[reg] = val; 470 cache[reg] = val;
486 471
487 return 0; 472 return 0;
@@ -698,7 +683,8 @@ static int wm9712_soc_probe(struct platform_device *pdev)
698 ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000); 683 ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
699 684
700 wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 685 wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
701 wm9712_add_controls(codec); 686 snd_soc_add_controls(codec, wm9712_snd_ac97_controls,
687 ARRAY_SIZE(wm9712_snd_ac97_controls));
702 wm9712_add_widgets(codec); 688 wm9712_add_widgets(codec);
703 ret = snd_soc_init_card(socdev); 689 ret = snd_soc_init_card(socdev);
704 if (ret < 0) { 690 if (ret < 0) {
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index f3ca8aaf0139..0e60e16973d4 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -32,7 +32,6 @@
32 32
33struct wm9713_priv { 33struct wm9713_priv {
34 u32 pll_in; /* PLL input frequency */ 34 u32 pll_in; /* PLL input frequency */
35 u32 pll_out; /* PLL output frequency */
36}; 35};
37 36
38static unsigned int ac97_read(struct snd_soc_codec *codec, 37static unsigned int ac97_read(struct snd_soc_codec *codec,
@@ -190,21 +189,6 @@ SOC_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),
190SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1), 189SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
191}; 190};
192 191
193/* add non dapm controls */
194static int wm9713_add_controls(struct snd_soc_codec *codec)
195{
196 int err, i;
197
198 for (i = 0; i < ARRAY_SIZE(wm9713_snd_ac97_controls); i++) {
199 err = snd_ctl_add(codec->card,
200 snd_soc_cnew(&wm9713_snd_ac97_controls[i],
201 codec, NULL));
202 if (err < 0)
203 return err;
204 }
205 return 0;
206}
207
208/* We have to create a fake left and right HP mixers because 192/* We have to create a fake left and right HP mixers because
209 * the codec only has a single control that is shared by both channels. 193 * the codec only has a single control that is shared by both channels.
210 * This makes it impossible to determine the audio path using the current 194 * This makes it impossible to determine the audio path using the current
@@ -636,7 +620,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec,
636 else { 620 else {
637 reg = reg >> 1; 621 reg = reg >> 1;
638 622
639 if (reg > (ARRAY_SIZE(wm9713_reg))) 623 if (reg >= (ARRAY_SIZE(wm9713_reg)))
640 return -EIO; 624 return -EIO;
641 625
642 return cache[reg]; 626 return cache[reg];
@@ -650,7 +634,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
650 if (reg < 0x7c) 634 if (reg < 0x7c)
651 soc_ac97_ops.write(codec->ac97, reg, val); 635 soc_ac97_ops.write(codec->ac97, reg, val);
652 reg = reg >> 1; 636 reg = reg >> 1;
653 if (reg <= (ARRAY_SIZE(wm9713_reg))) 637 if (reg < (ARRAY_SIZE(wm9713_reg)))
654 cache[reg] = val; 638 cache[reg] = val;
655 639
656 return 0; 640 return 0;
@@ -738,13 +722,13 @@ static int wm9713_set_pll(struct snd_soc_codec *codec,
738 struct _pll_div pll_div; 722 struct _pll_div pll_div;
739 723
740 /* turn PLL off ? */ 724 /* turn PLL off ? */
741 if (freq_in == 0 || freq_out == 0) { 725 if (freq_in == 0) {
742 /* disable PLL power and select ext source */ 726 /* disable PLL power and select ext source */
743 reg = ac97_read(codec, AC97_HANDSET_RATE); 727 reg = ac97_read(codec, AC97_HANDSET_RATE);
744 ac97_write(codec, AC97_HANDSET_RATE, reg | 0x0080); 728 ac97_write(codec, AC97_HANDSET_RATE, reg | 0x0080);
745 reg = ac97_read(codec, AC97_EXTENDED_MID); 729 reg = ac97_read(codec, AC97_EXTENDED_MID);
746 ac97_write(codec, AC97_EXTENDED_MID, reg | 0x0200); 730 ac97_write(codec, AC97_EXTENDED_MID, reg | 0x0200);
747 wm9713->pll_out = 0; 731 wm9713->pll_in = 0;
748 return 0; 732 return 0;
749 } 733 }
750 734
@@ -788,7 +772,6 @@ static int wm9713_set_pll(struct snd_soc_codec *codec,
788 ac97_write(codec, AC97_EXTENDED_MID, reg & 0xfdff); 772 ac97_write(codec, AC97_EXTENDED_MID, reg & 0xfdff);
789 reg = ac97_read(codec, AC97_HANDSET_RATE); 773 reg = ac97_read(codec, AC97_HANDSET_RATE);
790 ac97_write(codec, AC97_HANDSET_RATE, reg & 0xff7f); 774 ac97_write(codec, AC97_HANDSET_RATE, reg & 0xff7f);
791 wm9713->pll_out = freq_out;
792 wm9713->pll_in = freq_in; 775 wm9713->pll_in = freq_in;
793 776
794 /* wait 10ms AC97 link frames for the link to stabilise */ 777 /* wait 10ms AC97 link frames for the link to stabilise */
@@ -1164,8 +1147,8 @@ static int wm9713_soc_resume(struct platform_device *pdev)
1164 wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1147 wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1165 1148
1166 /* do we need to re-start the PLL ? */ 1149 /* do we need to re-start the PLL ? */
1167 if (wm9713->pll_out) 1150 if (wm9713->pll_in)
1168 wm9713_set_pll(codec, 0, wm9713->pll_in, wm9713->pll_out); 1151 wm9713_set_pll(codec, 0, wm9713->pll_in, 0);
1169 1152
1170 /* only synchronise the codec if warm reset failed */ 1153 /* only synchronise the codec if warm reset failed */
1171 if (ret == 0) { 1154 if (ret == 0) {
@@ -1245,7 +1228,8 @@ static int wm9713_soc_probe(struct platform_device *pdev)
1245 reg = ac97_read(codec, AC97_CD) & 0x7fff; 1228 reg = ac97_read(codec, AC97_CD) & 0x7fff;
1246 ac97_write(codec, AC97_CD, reg); 1229 ac97_write(codec, AC97_CD, reg);
1247 1230
1248 wm9713_add_controls(codec); 1231 snd_soc_add_controls(codec, wm9713_snd_ac97_controls,
1232 ARRAY_SIZE(wm9713_snd_ac97_controls));
1249 wm9713_add_widgets(codec); 1233 wm9713_add_widgets(codec);
1250 ret = snd_soc_init_card(socdev); 1234 ret = snd_soc_init_card(socdev);
1251 if (ret < 0) 1235 if (ret < 0)
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index 366049d8578c..7af3b5b3a53d 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -286,7 +286,7 @@ static int davinci_pcm_mmap(struct snd_pcm_substream *substream,
286 runtime->dma_bytes); 286 runtime->dma_bytes);
287} 287}
288 288
289struct snd_pcm_ops davinci_pcm_ops = { 289static struct snd_pcm_ops davinci_pcm_ops = {
290 .open = davinci_pcm_open, 290 .open = davinci_pcm_open,
291 .close = davinci_pcm_close, 291 .close = davinci_pcm_close,
292 .ioctl = snd_pcm_lib_ioctl, 292 .ioctl = snd_pcm_lib_ioctl,
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c
index 4935d1bcbd8d..50baef1fe5b4 100644
--- a/sound/soc/davinci/davinci-sffsdr.c
+++ b/sound/soc/davinci/davinci-sffsdr.c
@@ -25,7 +25,9 @@
25 25
26#include <asm/dma.h> 26#include <asm/dma.h>
27#include <asm/mach-types.h> 27#include <asm/mach-types.h>
28#ifdef CONFIG_SFFSDR_FPGA
28#include <asm/plat-sffsdr/sffsdr-fpga.h> 29#include <asm/plat-sffsdr/sffsdr-fpga.h>
30#endif
29 31
30#include <mach/mcbsp.h> 32#include <mach/mcbsp.h>
31#include <mach/edma.h> 33#include <mach/edma.h>
@@ -43,6 +45,17 @@ static int sffsdr_hw_params(struct snd_pcm_substream *substream,
43 int fs; 45 int fs;
44 int ret = 0; 46 int ret = 0;
45 47
48 /* Fsref can be 32000, 44100 or 48000. */
49 fs = params_rate(params);
50
51#ifndef CONFIG_SFFSDR_FPGA
52 /* Without the FPGA module, the Fs is fixed at 44100 Hz */
53 if (fs != 44100) {
54 pr_debug("warning: only 44.1 kHz is supported without SFFSDR FPGA module\n");
55 return -EINVAL;
56 }
57#endif
58
46 /* Set cpu DAI configuration: 59 /* Set cpu DAI configuration:
47 * CLKX and CLKR are the inputs for the Sample Rate Generator. 60 * CLKX and CLKR are the inputs for the Sample Rate Generator.
48 * FSX and FSR are outputs, driven by the sample Rate Generator. */ 61 * FSX and FSR are outputs, driven by the sample Rate Generator. */
@@ -53,12 +66,13 @@ static int sffsdr_hw_params(struct snd_pcm_substream *substream,
53 if (ret < 0) 66 if (ret < 0)
54 return ret; 67 return ret;
55 68
56 /* Fsref can be 32000, 44100 or 48000. */
57 fs = params_rate(params);
58
59 pr_debug("sffsdr_hw_params: rate = %d Hz\n", fs); 69 pr_debug("sffsdr_hw_params: rate = %d Hz\n", fs);
60 70
71#ifndef CONFIG_SFFSDR_FPGA
72 return 0;
73#else
61 return sffsdr_fpga_set_codec_fs(fs); 74 return sffsdr_fpga_set_codec_fs(fs);
75#endif
62} 76}
63 77
64static struct snd_soc_ops sffsdr_ops = { 78static struct snd_soc_ops sffsdr_ops = {
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 95c12b26fe37..c7c78c39cfed 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -1,17 +1,17 @@
1config SND_SOC_OF_SIMPLE 1config SND_SOC_OF_SIMPLE
2 tristate 2 tristate
3 3
4# ASoC platform support for the Freescale MPC8610 SOC. This compiles drivers
5# for the SSI and the Elo DMA controller. You will still need to select
6# a platform driver and a codec driver.
4config SND_SOC_MPC8610 7config SND_SOC_MPC8610
5 bool "ALSA SoC support for the MPC8610 SOC" 8 tristate
6 depends on MPC8610_HPCD 9 depends on MPC8610
7 default y if MPC8610
8 help
9 Say Y if you want to add support for codecs attached to the SSI
10 device on an MPC8610.
11 10
12config SND_SOC_MPC8610_HPCD 11config SND_SOC_MPC8610_HPCD
13 bool "ALSA SoC support for the Freescale MPC8610 HPCD board" 12 tristate "ALSA SoC support for the Freescale MPC8610 HPCD board"
14 depends on SND_SOC_MPC8610 13 depends on MPC8610_HPCD
14 select SND_SOC_MPC8610
15 select SND_SOC_CS4270 15 select SND_SOC_CS4270
16 select SND_SOC_CS4270_VD33_ERRATA 16 select SND_SOC_CS4270_VD33_ERRATA
17 default y if MPC8610_HPCD 17 default y if MPC8610_HPCD
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 035da4afec34..f85134c86387 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -2,10 +2,13 @@
2obj-$(CONFIG_SND_SOC_OF_SIMPLE) += soc-of-simple.o 2obj-$(CONFIG_SND_SOC_OF_SIMPLE) += soc-of-simple.o
3 3
4# MPC8610 HPCD Machine Support 4# MPC8610 HPCD Machine Support
5obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += mpc8610_hpcd.o 5snd-soc-mpc8610-hpcd-objs := mpc8610_hpcd.o
6obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o
6 7
7# MPC8610 Platform Support 8# MPC8610 Platform Support
8obj-$(CONFIG_SND_SOC_MPC8610) += fsl_ssi.o fsl_dma.o 9snd-soc-fsl-ssi-objs := fsl_ssi.o
10snd-soc-fsl-dma-objs := fsl_dma.o
11obj-$(CONFIG_SND_SOC_MPC8610) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o
9 12
10obj-$(CONFIG_SND_SOC_MPC5200_I2S) += mpc5200_psc_i2s.o 13obj-$(CONFIG_SND_SOC_MPC5200_I2S) += mpc5200_psc_i2s.o
11 14
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index b0362dfd5b71..607a38c7ae48 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -264,7 +264,7 @@ static int omap_pcm_mmap(struct snd_pcm_substream *substream,
264 runtime->dma_bytes); 264 runtime->dma_bytes);
265} 265}
266 266
267struct snd_pcm_ops omap_pcm_ops = { 267static struct snd_pcm_ops omap_pcm_ops = {
268 .open = omap_pcm_open, 268 .open = omap_pcm_open,
269 .close = omap_pcm_close, 269 .close = omap_pcm_close,
270 .ioctl = snd_pcm_lib_ioctl, 270 .ioctl = snd_pcm_lib_ioctl,
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index f82e10699471..958ac3fe15d1 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -61,6 +61,24 @@ config SND_PXA2XX_SOC_TOSA
61 Say Y if you want to add support for SoC audio on Sharp 61 Say Y if you want to add support for SoC audio on Sharp
62 Zaurus SL-C6000x models (Tosa). 62 Zaurus SL-C6000x models (Tosa).
63 63
64config SND_PXA2XX_SOC_E740
65 tristate "SoC AC97 Audio support for e740"
66 depends on SND_PXA2XX_SOC && MACH_E740
67 select SND_SOC_WM9705
68 select SND_PXA2XX_SOC_AC97
69 help
70 Say Y if you want to add support for SoC audio on the
71 toshiba e740 PDA
72
73config SND_PXA2XX_SOC_E750
74 tristate "SoC AC97 Audio support for e750"
75 depends on SND_PXA2XX_SOC && MACH_E750
76 select SND_SOC_WM9705
77 select SND_PXA2XX_SOC_AC97
78 help
79 Say Y if you want to add support for SoC audio on the
80 toshiba e750 PDA
81
64config SND_PXA2XX_SOC_E800 82config SND_PXA2XX_SOC_E800
65 tristate "SoC AC97 Audio support for e800" 83 tristate "SoC AC97 Audio support for e800"
66 depends on SND_PXA2XX_SOC && MACH_E800 84 depends on SND_PXA2XX_SOC && MACH_E800
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index 08a9f2797729..97a51a8c936c 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -13,6 +13,8 @@ obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o
13snd-soc-corgi-objs := corgi.o 13snd-soc-corgi-objs := corgi.o
14snd-soc-poodle-objs := poodle.o 14snd-soc-poodle-objs := poodle.o
15snd-soc-tosa-objs := tosa.o 15snd-soc-tosa-objs := tosa.o
16snd-soc-e740-objs := e740_wm9705.o
17snd-soc-e750-objs := e750_wm9705.o
16snd-soc-e800-objs := e800_wm9712.o 18snd-soc-e800-objs := e800_wm9712.o
17snd-soc-spitz-objs := spitz.o 19snd-soc-spitz-objs := spitz.o
18snd-soc-em-x270-objs := em-x270.o 20snd-soc-em-x270-objs := em-x270.o
@@ -22,6 +24,8 @@ snd-soc-zylonite-objs := zylonite.o
22obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o 24obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
23obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o 25obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
24obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o 26obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o
27obj-$(CONFIG_SND_PXA2XX_SOC_E740) += snd-soc-e740.o
28obj-$(CONFIG_SND_PXA2XX_SOC_E750) += snd-soc-e750.o
25obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o 29obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o
26obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o 30obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o
27obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o 31obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o
diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c
new file mode 100644
index 000000000000..ac3617651734
--- /dev/null
+++ b/sound/soc/pxa/e740_wm9705.c
@@ -0,0 +1,213 @@
1/*
2 * e740-wm9705.c -- SoC audio for e740
3 *
4 * Copyright 2007 (c) Ian Molton <spyro@f2s.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; version 2 ONLY.
9 *
10 */
11
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/gpio.h>
15
16#include <sound/core.h>
17#include <sound/pcm.h>
18#include <sound/soc.h>
19#include <sound/soc-dapm.h>
20
21#include <mach/pxa-regs.h>
22#include <mach/hardware.h>
23#include <mach/audio.h>
24#include <mach/eseries-gpio.h>
25
26#include <asm/mach-types.h>
27
28#include "../codecs/wm9705.h"
29#include "pxa2xx-pcm.h"
30#include "pxa2xx-ac97.h"
31
32
33#define E740_AUDIO_OUT 1
34#define E740_AUDIO_IN 2
35
36static int e740_audio_power;
37
38static void e740_sync_audio_power(int status)
39{
40 gpio_set_value(GPIO_E740_WM9705_nAVDD2, !status);
41 gpio_set_value(GPIO_E740_AMP_ON, (status & E740_AUDIO_OUT) ? 1 : 0);
42 gpio_set_value(GPIO_E740_MIC_ON, (status & E740_AUDIO_IN) ? 1 : 0);
43}
44
45static int e740_mic_amp_event(struct snd_soc_dapm_widget *w,
46 struct snd_kcontrol *kcontrol, int event)
47{
48 if (event & SND_SOC_DAPM_PRE_PMU)
49 e740_audio_power |= E740_AUDIO_IN;
50 else if (event & SND_SOC_DAPM_POST_PMD)
51 e740_audio_power &= ~E740_AUDIO_IN;
52
53 e740_sync_audio_power(e740_audio_power);
54
55 return 0;
56}
57
58static int e740_output_amp_event(struct snd_soc_dapm_widget *w,
59 struct snd_kcontrol *kcontrol, int event)
60{
61 if (event & SND_SOC_DAPM_PRE_PMU)
62 e740_audio_power |= E740_AUDIO_OUT;
63 else if (event & SND_SOC_DAPM_POST_PMD)
64 e740_audio_power &= ~E740_AUDIO_OUT;
65
66 e740_sync_audio_power(e740_audio_power);
67
68 return 0;
69}
70
71static const struct snd_soc_dapm_widget e740_dapm_widgets[] = {
72 SND_SOC_DAPM_HP("Headphone Jack", NULL),
73 SND_SOC_DAPM_SPK("Speaker", NULL),
74 SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
75 SND_SOC_DAPM_PGA_E("Output Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
76 e740_output_amp_event, SND_SOC_DAPM_PRE_PMU |
77 SND_SOC_DAPM_POST_PMD),
78 SND_SOC_DAPM_PGA_E("Mic Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
79 e740_mic_amp_event, SND_SOC_DAPM_PRE_PMU |
80 SND_SOC_DAPM_POST_PMD),
81};
82
83static const struct snd_soc_dapm_route audio_map[] = {
84 {"Output Amp", NULL, "LOUT"},
85 {"Output Amp", NULL, "ROUT"},
86 {"Output Amp", NULL, "MONOOUT"},
87
88 {"Speaker", NULL, "Output Amp"},
89 {"Headphone Jack", NULL, "Output Amp"},
90
91 {"MIC1", NULL, "Mic Amp"},
92 {"Mic Amp", NULL, "Mic (Internal)"},
93};
94
95static int e740_ac97_init(struct snd_soc_codec *codec)
96{
97 snd_soc_dapm_nc_pin(codec, "HPOUTL");
98 snd_soc_dapm_nc_pin(codec, "HPOUTR");
99 snd_soc_dapm_nc_pin(codec, "PHONE");
100 snd_soc_dapm_nc_pin(codec, "LINEINL");
101 snd_soc_dapm_nc_pin(codec, "LINEINR");
102 snd_soc_dapm_nc_pin(codec, "CDINL");
103 snd_soc_dapm_nc_pin(codec, "CDINR");
104 snd_soc_dapm_nc_pin(codec, "PCBEEP");
105 snd_soc_dapm_nc_pin(codec, "MIC2");
106
107 snd_soc_dapm_new_controls(codec, e740_dapm_widgets,
108 ARRAY_SIZE(e740_dapm_widgets));
109
110 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
111
112 snd_soc_dapm_sync(codec);
113
114 return 0;
115}
116
117static struct snd_soc_dai_link e740_dai[] = {
118 {
119 .name = "AC97",
120 .stream_name = "AC97 HiFi",
121 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
122 .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI],
123 .init = e740_ac97_init,
124 },
125 {
126 .name = "AC97 Aux",
127 .stream_name = "AC97 Aux",
128 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
129 .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX],
130 },
131};
132
133static struct snd_soc_card e740 = {
134 .name = "Toshiba e740",
135 .platform = &pxa2xx_soc_platform,
136 .dai_link = e740_dai,
137 .num_links = ARRAY_SIZE(e740_dai),
138};
139
140static struct snd_soc_device e740_snd_devdata = {
141 .card = &e740,
142 .codec_dev = &soc_codec_dev_wm9705,
143};
144
145static struct platform_device *e740_snd_device;
146
147static int __init e740_init(void)
148{
149 int ret;
150
151 if (!machine_is_e740())
152 return -ENODEV;
153
154 ret = gpio_request(GPIO_E740_MIC_ON, "Mic amp");
155 if (ret)
156 return ret;
157
158 ret = gpio_request(GPIO_E740_AMP_ON, "Output amp");
159 if (ret)
160 goto free_mic_amp_gpio;
161
162 ret = gpio_request(GPIO_E740_WM9705_nAVDD2, "Audio power");
163 if (ret)
164 goto free_op_amp_gpio;
165
166 /* Disable audio */
167 ret = gpio_direction_output(GPIO_E740_MIC_ON, 0);
168 if (ret)
169 goto free_apwr_gpio;
170 ret = gpio_direction_output(GPIO_E740_AMP_ON, 0);
171 if (ret)
172 goto free_apwr_gpio;
173 ret = gpio_direction_output(GPIO_E740_WM9705_nAVDD2, 1);
174 if (ret)
175 goto free_apwr_gpio;
176
177 e740_snd_device = platform_device_alloc("soc-audio", -1);
178 if (!e740_snd_device) {
179 ret = -ENOMEM;
180 goto free_apwr_gpio;
181 }
182
183 platform_set_drvdata(e740_snd_device, &e740_snd_devdata);
184 e740_snd_devdata.dev = &e740_snd_device->dev;
185 ret = platform_device_add(e740_snd_device);
186
187 if (!ret)
188 return 0;
189
190/* Fail gracefully */
191 platform_device_put(e740_snd_device);
192free_apwr_gpio:
193 gpio_free(GPIO_E740_WM9705_nAVDD2);
194free_op_amp_gpio:
195 gpio_free(GPIO_E740_AMP_ON);
196free_mic_amp_gpio:
197 gpio_free(GPIO_E740_MIC_ON);
198
199 return ret;
200}
201
202static void __exit e740_exit(void)
203{
204 platform_device_unregister(e740_snd_device);
205}
206
207module_init(e740_init);
208module_exit(e740_exit);
209
210/* Module information */
211MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
212MODULE_DESCRIPTION("ALSA SoC driver for e740");
213MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c
new file mode 100644
index 000000000000..20fbdcfa9f78
--- /dev/null
+++ b/sound/soc/pxa/e750_wm9705.c
@@ -0,0 +1,189 @@
1/*
2 * e750-wm9705.c -- SoC audio for e750
3 *
4 * Copyright 2007 (c) Ian Molton <spyro@f2s.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; version 2 ONLY.
9 *
10 */
11
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/gpio.h>
15
16#include <sound/core.h>
17#include <sound/pcm.h>
18#include <sound/soc.h>
19#include <sound/soc-dapm.h>
20
21#include <mach/pxa-regs.h>
22#include <mach/hardware.h>
23#include <mach/audio.h>
24#include <mach/eseries-gpio.h>
25
26#include <asm/mach-types.h>
27
28#include "../codecs/wm9705.h"
29#include "pxa2xx-pcm.h"
30#include "pxa2xx-ac97.h"
31
32static int e750_spk_amp_event(struct snd_soc_dapm_widget *w,
33 struct snd_kcontrol *kcontrol, int event)
34{
35 if (event & SND_SOC_DAPM_PRE_PMU)
36 gpio_set_value(GPIO_E750_SPK_AMP_OFF, 0);
37 else if (event & SND_SOC_DAPM_POST_PMD)
38 gpio_set_value(GPIO_E750_SPK_AMP_OFF, 1);
39
40 return 0;
41}
42
43static int e750_hp_amp_event(struct snd_soc_dapm_widget *w,
44 struct snd_kcontrol *kcontrol, int event)
45{
46 if (event & SND_SOC_DAPM_PRE_PMU)
47 gpio_set_value(GPIO_E750_HP_AMP_OFF, 0);
48 else if (event & SND_SOC_DAPM_POST_PMD)
49 gpio_set_value(GPIO_E750_HP_AMP_OFF, 1);
50
51 return 0;
52}
53
54static const struct snd_soc_dapm_widget e750_dapm_widgets[] = {
55 SND_SOC_DAPM_HP("Headphone Jack", NULL),
56 SND_SOC_DAPM_SPK("Speaker", NULL),
57 SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
58 SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
59 e750_hp_amp_event, SND_SOC_DAPM_PRE_PMU |
60 SND_SOC_DAPM_POST_PMD),
61 SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
62 e750_spk_amp_event, SND_SOC_DAPM_PRE_PMU |
63 SND_SOC_DAPM_POST_PMD),
64};
65
66static const struct snd_soc_dapm_route audio_map[] = {
67 {"Headphone Amp", NULL, "HPOUTL"},
68 {"Headphone Amp", NULL, "HPOUTR"},
69 {"Headphone Jack", NULL, "Headphone Amp"},
70
71 {"Speaker Amp", NULL, "MONOOUT"},
72 {"Speaker", NULL, "Speaker Amp"},
73
74 {"MIC1", NULL, "Mic (Internal)"},
75};
76
77static int e750_ac97_init(struct snd_soc_codec *codec)
78{
79 snd_soc_dapm_nc_pin(codec, "LOUT");
80 snd_soc_dapm_nc_pin(codec, "ROUT");
81 snd_soc_dapm_nc_pin(codec, "PHONE");
82 snd_soc_dapm_nc_pin(codec, "LINEINL");
83 snd_soc_dapm_nc_pin(codec, "LINEINR");
84 snd_soc_dapm_nc_pin(codec, "CDINL");
85 snd_soc_dapm_nc_pin(codec, "CDINR");
86 snd_soc_dapm_nc_pin(codec, "PCBEEP");
87 snd_soc_dapm_nc_pin(codec, "MIC2");
88
89 snd_soc_dapm_new_controls(codec, e750_dapm_widgets,
90 ARRAY_SIZE(e750_dapm_widgets));
91
92 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
93
94 snd_soc_dapm_sync(codec);
95
96 return 0;
97}
98
99static struct snd_soc_dai_link e750_dai[] = {
100 {
101 .name = "AC97",
102 .stream_name = "AC97 HiFi",
103 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
104 .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI],
105 .init = e750_ac97_init,
106 /* use ops to check startup state */
107 },
108 {
109 .name = "AC97 Aux",
110 .stream_name = "AC97 Aux",
111 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
112 .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX],
113 },
114};
115
116static struct snd_soc_card e750 = {
117 .name = "Toshiba e750",
118 .platform = &pxa2xx_soc_platform,
119 .dai_link = e750_dai,
120 .num_links = ARRAY_SIZE(e750_dai),
121};
122
123static struct snd_soc_device e750_snd_devdata = {
124 .card = &e750,
125 .codec_dev = &soc_codec_dev_wm9705,
126};
127
128static struct platform_device *e750_snd_device;
129
130static int __init e750_init(void)
131{
132 int ret;
133
134 if (!machine_is_e750())
135 return -ENODEV;
136
137 ret = gpio_request(GPIO_E750_HP_AMP_OFF, "Headphone amp");
138 if (ret)
139 return ret;
140
141 ret = gpio_request(GPIO_E750_SPK_AMP_OFF, "Speaker amp");
142 if (ret)
143 goto free_hp_amp_gpio;
144
145 ret = gpio_direction_output(GPIO_E750_HP_AMP_OFF, 1);
146 if (ret)
147 goto free_spk_amp_gpio;
148
149 ret = gpio_direction_output(GPIO_E750_SPK_AMP_OFF, 1);
150 if (ret)
151 goto free_spk_amp_gpio;
152
153 e750_snd_device = platform_device_alloc("soc-audio", -1);
154 if (!e750_snd_device) {
155 ret = -ENOMEM;
156 goto free_spk_amp_gpio;
157 }
158
159 platform_set_drvdata(e750_snd_device, &e750_snd_devdata);
160 e750_snd_devdata.dev = &e750_snd_device->dev;
161 ret = platform_device_add(e750_snd_device);
162
163 if (!ret)
164 return 0;
165
166/* Fail gracefully */
167 platform_device_put(e750_snd_device);
168free_spk_amp_gpio:
169 gpio_free(GPIO_E750_SPK_AMP_OFF);
170free_hp_amp_gpio:
171 gpio_free(GPIO_E750_HP_AMP_OFF);
172
173 return ret;
174}
175
176static void __exit e750_exit(void)
177{
178 platform_device_unregister(e750_snd_device);
179 gpio_free(GPIO_E750_SPK_AMP_OFF);
180 gpio_free(GPIO_E750_HP_AMP_OFF);
181}
182
183module_init(e750_init);
184module_exit(e750_exit);
185
186/* Module information */
187MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
188MODULE_DESCRIPTION("ALSA SoC driver for e750");
189MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c
index 2e3386dfa0f0..78a1770b986c 100644
--- a/sound/soc/pxa/e800_wm9712.c
+++ b/sound/soc/pxa/e800_wm9712.c
@@ -1,8 +1,6 @@
1/* 1/*
2 * e800-wm9712.c -- SoC audio for e800 2 * e800-wm9712.c -- SoC audio for e800
3 * 3 *
4 * Based on tosa.c
5 *
6 * Copyright 2007 (c) Ian Molton <spyro@f2s.com> 4 * Copyright 2007 (c) Ian Molton <spyro@f2s.com>
7 * 5 *
8 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
@@ -13,31 +11,96 @@
13 11
14#include <linux/module.h> 12#include <linux/module.h>
15#include <linux/moduleparam.h> 13#include <linux/moduleparam.h>
16#include <linux/device.h> 14#include <linux/gpio.h>
17 15
18#include <sound/core.h> 16#include <sound/core.h>
19#include <sound/pcm.h> 17#include <sound/pcm.h>
20#include <sound/soc.h> 18#include <sound/soc.h>
21#include <sound/soc-dapm.h> 19#include <sound/soc-dapm.h>
22 20
23#include <asm/mach-types.h>
24#include <mach/pxa-regs.h> 21#include <mach/pxa-regs.h>
25#include <mach/hardware.h> 22#include <mach/hardware.h>
26#include <mach/audio.h> 23#include <mach/audio.h>
24#include <mach/eseries-gpio.h>
25
26#include <asm/mach-types.h>
27 27
28#include "../codecs/wm9712.h" 28#include "../codecs/wm9712.h"
29#include "pxa2xx-pcm.h" 29#include "pxa2xx-pcm.h"
30#include "pxa2xx-ac97.h" 30#include "pxa2xx-ac97.h"
31 31
32static struct snd_soc_card e800; 32static int e800_spk_amp_event(struct snd_soc_dapm_widget *w,
33 struct snd_kcontrol *kcontrol, int event)
34{
35 if (event & SND_SOC_DAPM_PRE_PMU)
36 gpio_set_value(GPIO_E800_SPK_AMP_ON, 1);
37 else if (event & SND_SOC_DAPM_POST_PMD)
38 gpio_set_value(GPIO_E800_SPK_AMP_ON, 0);
33 39
34static struct snd_soc_dai_link e800_dai[] = { 40 return 0;
41}
42
43static int e800_hp_amp_event(struct snd_soc_dapm_widget *w,
44 struct snd_kcontrol *kcontrol, int event)
35{ 45{
36 .name = "AC97 Aux", 46 if (event & SND_SOC_DAPM_PRE_PMU)
37 .stream_name = "AC97 Aux", 47 gpio_set_value(GPIO_E800_HP_AMP_OFF, 0);
38 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], 48 else if (event & SND_SOC_DAPM_POST_PMD)
39 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], 49 gpio_set_value(GPIO_E800_HP_AMP_OFF, 1);
40}, 50
51 return 0;
52}
53
54static const struct snd_soc_dapm_widget e800_dapm_widgets[] = {
55 SND_SOC_DAPM_HP("Headphone Jack", NULL),
56 SND_SOC_DAPM_MIC("Mic (Internal1)", NULL),
57 SND_SOC_DAPM_MIC("Mic (Internal2)", NULL),
58 SND_SOC_DAPM_SPK("Speaker", NULL),
59 SND_SOC_DAPM_PGA_E("Headphone Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
60 e800_hp_amp_event, SND_SOC_DAPM_PRE_PMU |
61 SND_SOC_DAPM_POST_PMD),
62 SND_SOC_DAPM_PGA_E("Speaker Amp", SND_SOC_NOPM, 0, 0, NULL, 0,
63 e800_spk_amp_event, SND_SOC_DAPM_PRE_PMU |
64 SND_SOC_DAPM_POST_PMD),
65};
66
67static const struct snd_soc_dapm_route audio_map[] = {
68 {"Headphone Jack", NULL, "HPOUTL"},
69 {"Headphone Jack", NULL, "HPOUTR"},
70 {"Headphone Jack", NULL, "Headphone Amp"},
71
72 {"Speaker Amp", NULL, "MONOOUT"},
73 {"Speaker", NULL, "Speaker Amp"},
74
75 {"MIC1", NULL, "Mic (Internal1)"},
76 {"MIC2", NULL, "Mic (Internal2)"},
77};
78
79static int e800_ac97_init(struct snd_soc_codec *codec)
80{
81 snd_soc_dapm_new_controls(codec, e800_dapm_widgets,
82 ARRAY_SIZE(e800_dapm_widgets));
83
84 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
85 snd_soc_dapm_sync(codec);
86
87 return 0;
88}
89
90static struct snd_soc_dai_link e800_dai[] = {
91 {
92 .name = "AC97",
93 .stream_name = "AC97 HiFi",
94 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
95 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
96 .init = e800_ac97_init,
97 },
98 {
99 .name = "AC97 Aux",
100 .stream_name = "AC97 Aux",
101 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
102 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
103 },
41}; 104};
42 105
43static struct snd_soc_card e800 = { 106static struct snd_soc_card e800 = {
@@ -61,6 +124,22 @@ static int __init e800_init(void)
61 if (!machine_is_e800()) 124 if (!machine_is_e800())
62 return -ENODEV; 125 return -ENODEV;
63 126
127 ret = gpio_request(GPIO_E800_HP_AMP_OFF, "Headphone amp");
128 if (ret)
129 return ret;
130
131 ret = gpio_request(GPIO_E800_SPK_AMP_ON, "Speaker amp");
132 if (ret)
133 goto free_hp_amp_gpio;
134
135 ret = gpio_direction_output(GPIO_E800_HP_AMP_OFF, 1);
136 if (ret)
137 goto free_spk_amp_gpio;
138
139 ret = gpio_direction_output(GPIO_E800_SPK_AMP_ON, 1);
140 if (ret)
141 goto free_spk_amp_gpio;
142
64 e800_snd_device = platform_device_alloc("soc-audio", -1); 143 e800_snd_device = platform_device_alloc("soc-audio", -1);
65 if (!e800_snd_device) 144 if (!e800_snd_device)
66 return -ENOMEM; 145 return -ENOMEM;
@@ -69,8 +148,15 @@ static int __init e800_init(void)
69 e800_snd_devdata.dev = &e800_snd_device->dev; 148 e800_snd_devdata.dev = &e800_snd_device->dev;
70 ret = platform_device_add(e800_snd_device); 149 ret = platform_device_add(e800_snd_device);
71 150
72 if (ret) 151 if (!ret)
73 platform_device_put(e800_snd_device); 152 return 0;
153
154/* Fail gracefully */
155 platform_device_put(e800_snd_device);
156free_spk_amp_gpio:
157 gpio_free(GPIO_E800_SPK_AMP_ON);
158free_hp_amp_gpio:
159 gpio_free(GPIO_E800_HP_AMP_OFF);
74 160
75 return ret; 161 return ret;
76} 162}
@@ -78,6 +164,8 @@ static int __init e800_init(void)
78static void __exit e800_exit(void) 164static void __exit e800_exit(void)
79{ 165{
80 platform_device_unregister(e800_snd_device); 166 platform_device_unregister(e800_snd_device);
167 gpio_free(GPIO_E800_SPK_AMP_ON);
168 gpio_free(GPIO_E800_HP_AMP_OFF);
81} 169}
82 170
83module_init(e800_init); 171module_init(e800_init);
@@ -86,4 +174,4 @@ module_exit(e800_exit);
86/* Module information */ 174/* Module information */
87MODULE_AUTHOR("Ian Molton <spyro@f2s.com>"); 175MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
88MODULE_DESCRIPTION("ALSA SoC driver for e800"); 176MODULE_DESCRIPTION("ALSA SoC driver for e800");
89MODULE_LICENSE("GPL"); 177MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c
index f8e9ecd589d3..8541b679f6eb 100644
--- a/sound/soc/pxa/zylonite.c
+++ b/sound/soc/pxa/zylonite.c
@@ -14,6 +14,7 @@
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/moduleparam.h> 15#include <linux/moduleparam.h>
16#include <linux/device.h> 16#include <linux/device.h>
17#include <linux/clk.h>
17#include <linux/i2c.h> 18#include <linux/i2c.h>
18#include <sound/core.h> 19#include <sound/core.h>
19#include <sound/pcm.h> 20#include <sound/pcm.h>
@@ -26,6 +27,17 @@
26#include "pxa2xx-ac97.h" 27#include "pxa2xx-ac97.h"
27#include "pxa-ssp.h" 28#include "pxa-ssp.h"
28 29
30/*
31 * There is a physical switch SW15 on the board which changes the MCLK
32 * for the WM9713 between the standard AC97 master clock and the
33 * output of the CLK_POUT signal from the PXA.
34 */
35static int clk_pout;
36module_param(clk_pout, int, 0);
37MODULE_PARM_DESC(clk_pout, "Use CLK_POUT as WM9713 MCLK (SW15 on board).");
38
39static struct clk *pout;
40
29static struct snd_soc_card zylonite; 41static struct snd_soc_card zylonite;
30 42
31static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = { 43static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = {
@@ -61,10 +73,8 @@ static const struct snd_soc_dapm_route audio_map[] = {
61 73
62static int zylonite_wm9713_init(struct snd_soc_codec *codec) 74static int zylonite_wm9713_init(struct snd_soc_codec *codec)
63{ 75{
64 /* Currently we only support use of the AC97 clock here. If 76 if (clk_pout)
65 * CLK_POUT is selected by SW15 then the clock API will need 77 snd_soc_dai_set_pll(&codec->dai[0], 0, clk_get_rate(pout), 0);
66 * to be used to request and enable it here.
67 */
68 78
69 snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, 79 snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets,
70 ARRAY_SIZE(zylonite_dapm_widgets)); 80 ARRAY_SIZE(zylonite_dapm_widgets));
@@ -85,7 +95,6 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream,
85 struct snd_soc_pcm_runtime *rtd = substream->private_data; 95 struct snd_soc_pcm_runtime *rtd = substream->private_data;
86 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 96 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
87 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 97 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
88 unsigned int pll_out = 0;
89 unsigned int acds = 0; 98 unsigned int acds = 0;
90 unsigned int wm9713_div = 0; 99 unsigned int wm9713_div = 0;
91 int ret = 0; 100 int ret = 0;
@@ -93,16 +102,13 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream,
93 switch (params_rate(params)) { 102 switch (params_rate(params)) {
94 case 8000: 103 case 8000:
95 wm9713_div = 12; 104 wm9713_div = 12;
96 pll_out = 2048000;
97 break; 105 break;
98 case 16000: 106 case 16000:
99 wm9713_div = 6; 107 wm9713_div = 6;
100 pll_out = 4096000;
101 break; 108 break;
102 case 48000: 109 case 48000:
103 default: 110 default:
104 wm9713_div = 2; 111 wm9713_div = 2;
105 pll_out = 12288000;
106 acds = 1; 112 acds = 1;
107 break; 113 break;
108 } 114 }
@@ -123,10 +129,6 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream,
123 if (ret < 0) 129 if (ret < 0)
124 return ret; 130 return ret;
125 131
126 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, pll_out);
127 if (ret < 0)
128 return ret;
129
130 ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds); 132 ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds);
131 if (ret < 0) 133 if (ret < 0)
132 return ret; 134 return ret;
@@ -135,11 +137,12 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream,
135 if (ret < 0) 137 if (ret < 0)
136 return ret; 138 return ret;
137 139
138 /* Note that if the PLL is in use the WM9713_PCMCLK_PLL_DIV needs 140 if (clk_pout)
139 * to be set instead. 141 ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_PLL_DIV,
140 */ 142 WM9713_PCMDIV(wm9713_div));
141 ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV, 143 else
142 WM9713_PCMDIV(wm9713_div)); 144 ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV,
145 WM9713_PCMDIV(wm9713_div));
143 if (ret < 0) 146 if (ret < 0)
144 return ret; 147 return ret;
145 148
@@ -173,8 +176,72 @@ static struct snd_soc_dai_link zylonite_dai[] = {
173}, 176},
174}; 177};
175 178
179static int zylonite_probe(struct platform_device *pdev)
180{
181 int ret;
182
183 if (clk_pout) {
184 pout = clk_get(NULL, "CLK_POUT");
185 if (IS_ERR(pout)) {
186 dev_err(&pdev->dev, "Unable to obtain CLK_POUT: %ld\n",
187 PTR_ERR(pout));
188 return PTR_ERR(pout);
189 }
190
191 ret = clk_enable(pout);
192 if (ret != 0) {
193 dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n",
194 ret);
195 clk_put(pout);
196 return ret;
197 }
198
199 dev_dbg(&pdev->dev, "MCLK enabled at %luHz\n",
200 clk_get_rate(pout));
201 }
202
203 return 0;
204}
205
206static int zylonite_remove(struct platform_device *pdev)
207{
208 if (clk_pout) {
209 clk_disable(pout);
210 clk_put(pout);
211 }
212
213 return 0;
214}
215
216static int zylonite_suspend_post(struct platform_device *pdev,
217 pm_message_t state)
218{
219 if (clk_pout)
220 clk_disable(pout);
221
222 return 0;
223}
224
225static int zylonite_resume_pre(struct platform_device *pdev)
226{
227 int ret = 0;
228
229 if (clk_pout) {
230 ret = clk_enable(pout);
231 if (ret != 0)
232 dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n",
233 ret);
234 }
235
236 return ret;
237}
238
176static struct snd_soc_card zylonite = { 239static struct snd_soc_card zylonite = {
177 .name = "Zylonite", 240 .name = "Zylonite",
241 .probe = &zylonite_probe,
242 .remove = &zylonite_remove,
243 .suspend_post = &zylonite_suspend_post,
244 .resume_pre = &zylonite_resume_pre,
178 .platform = &pxa2xx_soc_platform, 245 .platform = &pxa2xx_soc_platform,
179 .dai_link = zylonite_dai, 246 .dai_link = zylonite_dai,
180 .num_links = ARRAY_SIZE(zylonite_dai), 247 .num_links = ARRAY_SIZE(zylonite_dai),
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 55fdb4abb179..8313d52a6e8c 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1495,6 +1495,37 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
1495EXPORT_SYMBOL_GPL(snd_soc_cnew); 1495EXPORT_SYMBOL_GPL(snd_soc_cnew);
1496 1496
1497/** 1497/**
1498 * snd_soc_add_controls - add an array of controls to a codec.
1499 * Convienience function to add a list of controls. Many codecs were
1500 * duplicating this code.
1501 *
1502 * @codec: codec to add controls to
1503 * @controls: array of controls to add
1504 * @num_controls: number of elements in the array
1505 *
1506 * Return 0 for success, else error.
1507 */
1508int snd_soc_add_controls(struct snd_soc_codec *codec,
1509 const struct snd_kcontrol_new *controls, int num_controls)
1510{
1511 struct snd_card *card = codec->card;
1512 int err, i;
1513
1514 for (i = 0; i < num_controls; i++) {
1515 const struct snd_kcontrol_new *control = &controls[i];
1516 err = snd_ctl_add(card, snd_soc_cnew(control, codec, NULL));
1517 if (err < 0) {
1518 dev_err(codec->dev, "%s: Failed to add %s\n",
1519 codec->name, control->name);
1520 return err;
1521 }
1522 }
1523
1524 return 0;
1525}
1526EXPORT_SYMBOL_GPL(snd_soc_add_controls);
1527
1528/**
1498 * snd_soc_info_enum_double - enumerated double mixer info callback 1529 * snd_soc_info_enum_double - enumerated double mixer info callback
1499 * @kcontrol: mixer control 1530 * @kcontrol: mixer control
1500 * @uinfo: control element information 1531 * @uinfo: control element information
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index a2f1da8b4646..54b4564b82b4 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -54,14 +54,15 @@
54static int dapm_up_seq[] = { 54static int dapm_up_seq[] = {
55 snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic, 55 snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic,
56 snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac, 56 snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac,
57 snd_soc_dapm_mixer, snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, 57 snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_pga,
58 snd_soc_dapm_spk, snd_soc_dapm_post 58 snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post
59}; 59};
60
60static int dapm_down_seq[] = { 61static int dapm_down_seq[] = {
61 snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, 62 snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
62 snd_soc_dapm_pga, snd_soc_dapm_mixer, snd_soc_dapm_dac, snd_soc_dapm_mic, 63 snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer,
63 snd_soc_dapm_micbias, snd_soc_dapm_mux, snd_soc_dapm_value_mux, 64 snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias,
64 snd_soc_dapm_post 65 snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_post
65}; 66};
66 67
67static int dapm_status = 1; 68static int dapm_status = 1;
@@ -101,7 +102,8 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
101{ 102{
102 switch (w->id) { 103 switch (w->id) {
103 case snd_soc_dapm_switch: 104 case snd_soc_dapm_switch:
104 case snd_soc_dapm_mixer: { 105 case snd_soc_dapm_mixer:
106 case snd_soc_dapm_mixer_named_ctl: {
105 int val; 107 int val;
106 struct soc_mixer_control *mc = (struct soc_mixer_control *) 108 struct soc_mixer_control *mc = (struct soc_mixer_control *)
107 w->kcontrols[i].private_value; 109 w->kcontrols[i].private_value;
@@ -323,15 +325,33 @@ static int dapm_new_mixer(struct snd_soc_codec *codec,
323 if (path->name != (char*)w->kcontrols[i].name) 325 if (path->name != (char*)w->kcontrols[i].name)
324 continue; 326 continue;
325 327
326 /* add dapm control with long name */ 328 /* add dapm control with long name.
327 name_len = 2 + strlen(w->name) 329 * for dapm_mixer this is the concatenation of the
328 + strlen(w->kcontrols[i].name); 330 * mixer and kcontrol name.
331 * for dapm_mixer_named_ctl this is simply the
332 * kcontrol name.
333 */
334 name_len = strlen(w->kcontrols[i].name) + 1;
335 if (w->id == snd_soc_dapm_mixer)
336 name_len += 1 + strlen(w->name);
337
329 path->long_name = kmalloc(name_len, GFP_KERNEL); 338 path->long_name = kmalloc(name_len, GFP_KERNEL);
339
330 if (path->long_name == NULL) 340 if (path->long_name == NULL)
331 return -ENOMEM; 341 return -ENOMEM;
332 342
333 snprintf(path->long_name, name_len, "%s %s", 343 switch (w->id) {
334 w->name, w->kcontrols[i].name); 344 case snd_soc_dapm_mixer:
345 default:
346 snprintf(path->long_name, name_len, "%s %s",
347 w->name, w->kcontrols[i].name);
348 break;
349 case snd_soc_dapm_mixer_named_ctl:
350 snprintf(path->long_name, name_len, "%s",
351 w->kcontrols[i].name);
352 break;
353 }
354
335 path->long_name[name_len - 1] = '\0'; 355 path->long_name[name_len - 1] = '\0';
336 356
337 path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, 357 path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
@@ -687,6 +707,7 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
687 case snd_soc_dapm_adc: 707 case snd_soc_dapm_adc:
688 case snd_soc_dapm_pga: 708 case snd_soc_dapm_pga:
689 case snd_soc_dapm_mixer: 709 case snd_soc_dapm_mixer:
710 case snd_soc_dapm_mixer_named_ctl:
690 if (w->name) { 711 if (w->name) {
691 in = is_connected_input_ep(w); 712 in = is_connected_input_ep(w);
692 dapm_clear_walk(w->codec); 713 dapm_clear_walk(w->codec);
@@ -760,6 +781,7 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
760 int found = 0; 781 int found = 0;
761 782
762 if (widget->id != snd_soc_dapm_mixer && 783 if (widget->id != snd_soc_dapm_mixer &&
784 widget->id != snd_soc_dapm_mixer_named_ctl &&
763 widget->id != snd_soc_dapm_switch) 785 widget->id != snd_soc_dapm_switch)
764 return -ENODEV; 786 return -ENODEV;
765 787
@@ -813,6 +835,7 @@ static ssize_t dapm_widget_show(struct device *dev,
813 case snd_soc_dapm_adc: 835 case snd_soc_dapm_adc:
814 case snd_soc_dapm_pga: 836 case snd_soc_dapm_pga:
815 case snd_soc_dapm_mixer: 837 case snd_soc_dapm_mixer:
838 case snd_soc_dapm_mixer_named_ctl:
816 if (w->name) 839 if (w->name)
817 count += sprintf(buf + count, "%s: %s\n", 840 count += sprintf(buf + count, "%s: %s\n",
818 w->name, w->power ? "On":"Off"); 841 w->name, w->power ? "On":"Off");
@@ -876,7 +899,7 @@ static void dapm_free_widgets(struct snd_soc_codec *codec)
876} 899}
877 900
878static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec, 901static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec,
879 char *pin, int status) 902 const char *pin, int status)
880{ 903{
881 struct snd_soc_dapm_widget *w; 904 struct snd_soc_dapm_widget *w;
882 905
@@ -991,6 +1014,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
991 break; 1014 break;
992 case snd_soc_dapm_switch: 1015 case snd_soc_dapm_switch:
993 case snd_soc_dapm_mixer: 1016 case snd_soc_dapm_mixer:
1017 case snd_soc_dapm_mixer_named_ctl:
994 ret = dapm_connect_mixer(codec, wsource, wsink, path, control); 1018 ret = dapm_connect_mixer(codec, wsource, wsink, path, control);
995 if (ret != 0) 1019 if (ret != 0)
996 goto err; 1020 goto err;
@@ -1068,6 +1092,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
1068 switch(w->id) { 1092 switch(w->id) {
1069 case snd_soc_dapm_switch: 1093 case snd_soc_dapm_switch:
1070 case snd_soc_dapm_mixer: 1094 case snd_soc_dapm_mixer:
1095 case snd_soc_dapm_mixer_named_ctl:
1071 dapm_new_mixer(codec, w); 1096 dapm_new_mixer(codec, w);
1072 break; 1097 break;
1073 case snd_soc_dapm_mux: 1098 case snd_soc_dapm_mux:
@@ -1549,7 +1574,7 @@ int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
1549 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to 1574 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1550 * do any widget power switching. 1575 * do any widget power switching.
1551 */ 1576 */
1552int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin) 1577int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin)
1553{ 1578{
1554 return snd_soc_dapm_set_pin(codec, pin, 1); 1579 return snd_soc_dapm_set_pin(codec, pin, 1);
1555} 1580}
@@ -1564,7 +1589,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
1564 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to 1589 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1565 * do any widget power switching. 1590 * do any widget power switching.
1566 */ 1591 */
1567int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin) 1592int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin)
1568{ 1593{
1569 return snd_soc_dapm_set_pin(codec, pin, 0); 1594 return snd_soc_dapm_set_pin(codec, pin, 0);
1570} 1595}
@@ -1584,7 +1609,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
1584 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to 1609 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1585 * do any widget power switching. 1610 * do any widget power switching.
1586 */ 1611 */
1587int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin) 1612int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin)
1588{ 1613{
1589 return snd_soc_dapm_set_pin(codec, pin, 0); 1614 return snd_soc_dapm_set_pin(codec, pin, 0);
1590} 1615}
@@ -1599,7 +1624,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
1599 * 1624 *
1600 * Returns 1 for connected otherwise 0. 1625 * Returns 1 for connected otherwise 0.
1601 */ 1626 */
1602int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin) 1627int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin)
1603{ 1628{
1604 struct snd_soc_dapm_widget *w; 1629 struct snd_soc_dapm_widget *w;
1605 1630
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
new file mode 100644
index 000000000000..8cc00c3cdf34
--- /dev/null
+++ b/sound/soc/soc-jack.c
@@ -0,0 +1,138 @@
1/*
2 * soc-jack.c -- ALSA SoC jack handling
3 *
4 * Copyright 2008 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <sound/jack.h>
15#include <sound/soc.h>
16#include <sound/soc-dapm.h>
17
18/**
19 * snd_soc_jack_new - Create a new jack
20 * @card: ASoC card
21 * @id: an identifying string for this jack
22 * @type: a bitmask of enum snd_jack_type values that can be detected by
23 * this jack
24 * @jack: structure to use for the jack
25 *
26 * Creates a new jack object.
27 *
28 * Returns zero if successful, or a negative error code on failure.
29 * On success jack will be initialised.
30 */
31int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type,
32 struct snd_soc_jack *jack)
33{
34 jack->card = card;
35 INIT_LIST_HEAD(&jack->pins);
36
37 return snd_jack_new(card->socdev->codec->card, id, type, &jack->jack);
38}
39EXPORT_SYMBOL_GPL(snd_soc_jack_new);
40
41/**
42 * snd_soc_jack_report - Report the current status for a jack
43 *
44 * @jack: the jack
45 * @status: a bitmask of enum snd_jack_type values that are currently detected.
46 * @mask: a bitmask of enum snd_jack_type values that being reported.
47 *
48 * If configured using snd_soc_jack_add_pins() then the associated
49 * DAPM pins will be enabled or disabled as appropriate and DAPM
50 * synchronised.
51 *
52 * Note: This function uses mutexes and should be called from a
53 * context which can sleep (such as a workqueue).
54 */
55void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
56{
57 struct snd_soc_codec *codec = jack->card->socdev->codec;
58 struct snd_soc_jack_pin *pin;
59 int enable;
60 int oldstatus;
61
62 if (!jack) {
63 WARN_ON_ONCE(!jack);
64 return;
65 }
66
67 mutex_lock(&codec->mutex);
68
69 oldstatus = jack->status;
70
71 jack->status &= ~mask;
72 jack->status |= status;
73
74 /* The DAPM sync is expensive enough to be worth skipping */
75 if (jack->status == oldstatus)
76 goto out;
77
78 list_for_each_entry(pin, &jack->pins, list) {
79 enable = pin->mask & status;
80
81 if (pin->invert)
82 enable = !enable;
83
84 if (enable)
85 snd_soc_dapm_enable_pin(codec, pin->pin);
86 else
87 snd_soc_dapm_disable_pin(codec, pin->pin);
88 }
89
90 snd_soc_dapm_sync(codec);
91
92 snd_jack_report(jack->jack, status);
93
94out:
95 mutex_unlock(&codec->mutex);
96}
97EXPORT_SYMBOL_GPL(snd_soc_jack_report);
98
99/**
100 * snd_soc_jack_add_pins - Associate DAPM pins with an ASoC jack
101 *
102 * @jack: ASoC jack
103 * @count: Number of pins
104 * @pins: Array of pins
105 *
106 * After this function has been called the DAPM pins specified in the
107 * pins array will have their status updated to reflect the current
108 * state of the jack whenever the jack status is updated.
109 */
110int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
111 struct snd_soc_jack_pin *pins)
112{
113 int i;
114
115 for (i = 0; i < count; i++) {
116 if (!pins[i].pin) {
117 printk(KERN_ERR "No name for pin %d\n", i);
118 return -EINVAL;
119 }
120 if (!pins[i].mask) {
121 printk(KERN_ERR "No mask for pin %d (%s)\n", i,
122 pins[i].pin);
123 return -EINVAL;
124 }
125
126 INIT_LIST_HEAD(&pins[i].list);
127 list_add(&(pins[i].list), &jack->pins);
128 }
129
130 /* Update to reflect the last reported status; canned jack
131 * implementations are likely to set their state before the
132 * card has an opportunity to associate pins.
133 */
134 snd_soc_jack_report(jack, 0, 0);
135
136 return 0;
137}
138EXPORT_SYMBOL_GPL(snd_soc_jack_add_pins);