aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/sound/alsa/soc/dapm.txt3
-rw-r--r--include/linux/mfd/wm8350/audio.h1
-rw-r--r--include/sound/soc-dapm.h19
-rw-r--r--include/sound/soc.h34
-rw-r--r--sound/soc/Kconfig1
-rw-r--r--sound/soc/Makefile2
-rw-r--r--sound/soc/codecs/ad1980.c17
-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.c19
-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.c17
-rw-r--r--sound/soc/codecs/wm8728.c18
-rw-r--r--sound/soc/codecs/wm8731.c19
-rw-r--r--sound/soc/codecs/wm8750.c18
-rw-r--r--sound/soc/codecs/wm8753.c18
-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.c18
-rw-r--r--sound/soc/codecs/wm9712.c18
-rw-r--r--sound/soc/codecs/wm9713.c18
-rw-r--r--sound/soc/soc-core.c31
-rw-r--r--sound/soc/soc-dapm.c57
-rw-r--r--sound/soc/soc-jack.c138
31 files changed, 445 insertions, 381 deletions
diff --git a/Documentation/sound/alsa/soc/dapm.txt b/Documentation/sound/alsa/soc/dapm.txt
index 46f9684d0b29..9e6763264a2e 100644
--- a/Documentation/sound/alsa/soc/dapm.txt
+++ b/Documentation/sound/alsa/soc/dapm.txt
@@ -116,6 +116,9 @@ SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
116SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls, 116SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
117 ARRAY_SIZE(wm8731_output_mixer_controls)), 117 ARRAY_SIZE(wm8731_output_mixer_controls)),
118 118
119If you dont want the mixer elements prefixed with the name of the mixer widget,
120you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same
121as for SND_SOC_DAPM_MIXER.
119 122
1202.3 Platform/Machine domain Widgets 1232.3 Platform/Machine domain Widgets
121----------------------------------- 124-----------------------------------
diff --git a/include/linux/mfd/wm8350/audio.h b/include/linux/mfd/wm8350/audio.h
index af95a1d2f3a1..d899dc0223ba 100644
--- a/include/linux/mfd/wm8350/audio.h
+++ b/include/linux/mfd/wm8350/audio.h
@@ -490,6 +490,7 @@
490/* 490/*
491 * R231 (0xE7) - Jack Status 491 * R231 (0xE7) - Jack Status
492 */ 492 */
493#define WM8350_JACK_L_LVL 0x0800
493#define WM8350_JACK_R_LVL 0x0400 494#define WM8350_JACK_R_LVL 0x0400
494 495
495/* 496/*
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 93a4edb148b5..0accdba211f9 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -76,6 +76,11 @@
76 wcontrols, wncontrols)\ 76 wcontrols, wncontrols)\
77{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ 77{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
78 .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols} 78 .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols}
79#define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \
80 wcontrols, wncontrols)\
81{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, .reg = wreg, \
82 .shift = wshift, .invert = winvert, .kcontrols = wcontrols, \
83 .num_kcontrols = wncontrols}
79#define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \ 84#define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \
80{ .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \ 85{ .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
81 .invert = winvert, .kcontrols = NULL, .num_kcontrols = 0} 86 .invert = winvert, .kcontrols = NULL, .num_kcontrols = 0}
@@ -101,6 +106,11 @@
101{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \ 106{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
102 .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols, \ 107 .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols, \
103 .event = wevent, .event_flags = wflags} 108 .event = wevent, .event_flags = wflags}
109#define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \
110 wcontrols, wncontrols, wevent, wflags) \
111{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
112 .invert = winvert, .kcontrols = wcontrols, \
113 .num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags}
104#define SND_SOC_DAPM_MICBIAS_E(wname, wreg, wshift, winvert, wevent, wflags) \ 114#define SND_SOC_DAPM_MICBIAS_E(wname, wreg, wshift, winvert, wevent, wflags) \
105{ .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \ 115{ .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
106 .invert = winvert, .kcontrols = NULL, .num_kcontrols = 0, \ 116 .invert = winvert, .kcontrols = NULL, .num_kcontrols = 0, \
@@ -250,10 +260,10 @@ int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
250int snd_soc_dapm_sys_add(struct device *dev); 260int snd_soc_dapm_sys_add(struct device *dev);
251 261
252/* dapm audio pin control and status */ 262/* dapm audio pin control and status */
253int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin); 263int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin);
254int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin); 264int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin);
255int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin); 265int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin);
256int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin); 266int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin);
257int snd_soc_dapm_sync(struct snd_soc_codec *codec); 267int snd_soc_dapm_sync(struct snd_soc_codec *codec);
258 268
259/* dapm widget types */ 269/* dapm widget types */
@@ -263,6 +273,7 @@ enum snd_soc_dapm_type {
263 snd_soc_dapm_mux, /* selects 1 analog signal from many inputs */ 273 snd_soc_dapm_mux, /* selects 1 analog signal from many inputs */
264 snd_soc_dapm_value_mux, /* selects 1 analog signal from many inputs */ 274 snd_soc_dapm_value_mux, /* selects 1 analog signal from many inputs */
265 snd_soc_dapm_mixer, /* mixes several analog signals together */ 275 snd_soc_dapm_mixer, /* mixes several analog signals together */
276 snd_soc_dapm_mixer_named_ctl, /* mixer with named controls */
266 snd_soc_dapm_pga, /* programmable gain/attenuation (volume) */ 277 snd_soc_dapm_pga, /* programmable gain/attenuation (volume) */
267 snd_soc_dapm_adc, /* analog to digital converter */ 278 snd_soc_dapm_adc, /* analog to digital converter */
268 snd_soc_dapm_dac, /* digital to analog converter */ 279 snd_soc_dapm_dac, /* digital to analog converter */
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 24593ac3ea19..7039343e8a78 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -154,6 +154,8 @@ enum snd_soc_bias_level {
154 SND_SOC_BIAS_OFF, 154 SND_SOC_BIAS_OFF,
155}; 155};
156 156
157struct snd_jack;
158struct snd_soc_card;
157struct snd_soc_device; 159struct snd_soc_device;
158struct snd_soc_pcm_stream; 160struct snd_soc_pcm_stream;
159struct snd_soc_ops; 161struct snd_soc_ops;
@@ -164,6 +166,8 @@ struct snd_soc_platform;
164struct snd_soc_codec; 166struct snd_soc_codec;
165struct soc_enum; 167struct soc_enum;
166struct snd_soc_ac97_ops; 168struct snd_soc_ac97_ops;
169struct snd_soc_jack;
170struct snd_soc_jack_pin;
167 171
168typedef int (*hw_write_t)(void *,const char* ,int); 172typedef int (*hw_write_t)(void *,const char* ,int);
169typedef int (*hw_read_t)(void *,char* ,int); 173typedef int (*hw_read_t)(void *,char* ,int);
@@ -184,6 +188,13 @@ int snd_soc_init_card(struct snd_soc_device *socdev);
184int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, 188int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
185 const struct snd_pcm_hardware *hw); 189 const struct snd_pcm_hardware *hw);
186 190
191/* Jack reporting */
192int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type,
193 struct snd_soc_jack *jack);
194void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask);
195int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
196 struct snd_soc_jack_pin *pins);
197
187/* codec IO */ 198/* codec IO */
188#define snd_soc_read(codec, reg) codec->read(codec, reg) 199#define snd_soc_read(codec, reg) codec->read(codec, reg)
189#define snd_soc_write(codec, reg, value) codec->write(codec, reg, value) 200#define snd_soc_write(codec, reg, value) codec->write(codec, reg, value)
@@ -203,6 +214,8 @@ void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
203 */ 214 */
204struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, 215struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
205 void *data, char *long_name); 216 void *data, char *long_name);
217int snd_soc_add_controls(struct snd_soc_codec *codec,
218 const struct snd_kcontrol_new *controls, int num_controls);
206int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, 219int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
207 struct snd_ctl_elem_info *uinfo); 220 struct snd_ctl_elem_info *uinfo);
208int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol, 221int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
@@ -237,6 +250,27 @@ int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
237int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, 250int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
238 struct snd_ctl_elem_value *ucontrol); 251 struct snd_ctl_elem_value *ucontrol);
239 252
253/**
254 * struct snd_soc_jack_pin - Describes a pin to update based on jack detection
255 *
256 * @pin: name of the pin to update
257 * @mask: bits to check for in reported jack status
258 * @invert: if non-zero then pin is enabled when status is not reported
259 */
260struct snd_soc_jack_pin {
261 struct list_head list;
262 const char *pin;
263 int mask;
264 bool invert;
265};
266
267struct snd_soc_jack {
268 struct snd_jack *jack;
269 struct snd_soc_card *card;
270 struct list_head pins;
271 int status;
272};
273
240/* SoC PCM stream information */ 274/* SoC PCM stream information */
241struct snd_soc_pcm_stream { 275struct snd_soc_pcm_stream {
242 char *stream_name; 276 char *stream_name;
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/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 73fdbb4d4a3d..c3c5d0eee37a 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{
@@ -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..ddc9f37d863f 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -670,22 +670,6 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
670 0, 3, 5, 0, input_gain_tlv), 670 0, 3, 5, 0, input_gain_tlv),
671}; 671};
672 672
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[] = { 673static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
690 /* Left channel inputs */ 674 /* Left channel inputs */
691 SND_SOC_DAPM_INPUT("MAINMIC"), 675 SND_SOC_DAPM_INPUT("MAINMIC"),
@@ -1233,7 +1217,8 @@ static int twl4030_init(struct snd_soc_device *socdev)
1233 /* power on device */ 1217 /* power on device */
1234 twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1218 twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1235 1219
1236 twl4030_add_controls(codec); 1220 snd_soc_add_controls(codec, twl4030_snd_controls,
1221 ARRAY_SIZE(twl4030_snd_controls));
1237 twl4030_add_widgets(codec); 1222 twl4030_add_widgets(codec);
1238 1223
1239 ret = snd_soc_init_card(socdev); 1224 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..9b75a377453e 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -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..defa310bc7d9 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -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..7283178e0eb5 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -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..6b2778632d5e 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -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/wm9712.c b/sound/soc/codecs/wm9712.c
index af83d629078a..1b0ace0f4dca 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.
@@ -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..a45622620db7 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -190,21 +190,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), 190SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),
191}; 191};
192 192
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 193/* 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. 194 * 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 195 * This makes it impossible to determine the audio path using the current
@@ -1245,7 +1230,8 @@ static int wm9713_soc_probe(struct platform_device *pdev)
1245 reg = ac97_read(codec, AC97_CD) & 0x7fff; 1230 reg = ac97_read(codec, AC97_CD) & 0x7fff;
1246 ac97_write(codec, AC97_CD, reg); 1231 ac97_write(codec, AC97_CD, reg);
1247 1232
1248 wm9713_add_controls(codec); 1233 snd_soc_add_controls(codec, wm9713_snd_ac97_controls,
1234 ARRAY_SIZE(wm9713_snd_ac97_controls));
1249 wm9713_add_widgets(codec); 1235 wm9713_add_widgets(codec);
1250 ret = snd_soc_init_card(socdev); 1236 ret = snd_soc_init_card(socdev);
1251 if (ret < 0) 1237 if (ret < 0)
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);