diff options
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), | |||
116 | SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls, | 116 | SND_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 | ||
119 | If you dont want the mixer elements prefixed with the name of the mixer widget, | ||
120 | you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same | ||
121 | as for SND_SOC_DAPM_MIXER. | ||
119 | 122 | ||
120 | 2.3 Platform/Machine domain Widgets | 123 | 2.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, | |||
250 | int snd_soc_dapm_sys_add(struct device *dev); | 260 | int snd_soc_dapm_sys_add(struct device *dev); |
251 | 261 | ||
252 | /* dapm audio pin control and status */ | 262 | /* dapm audio pin control and status */ |
253 | int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin); | 263 | int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin); |
254 | int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin); | 264 | int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin); |
255 | int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin); | 265 | int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin); |
256 | int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin); | 266 | int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin); |
257 | int snd_soc_dapm_sync(struct snd_soc_codec *codec); | 267 | int 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 | ||
157 | struct snd_jack; | ||
158 | struct snd_soc_card; | ||
157 | struct snd_soc_device; | 159 | struct snd_soc_device; |
158 | struct snd_soc_pcm_stream; | 160 | struct snd_soc_pcm_stream; |
159 | struct snd_soc_ops; | 161 | struct snd_soc_ops; |
@@ -164,6 +166,8 @@ struct snd_soc_platform; | |||
164 | struct snd_soc_codec; | 166 | struct snd_soc_codec; |
165 | struct soc_enum; | 167 | struct soc_enum; |
166 | struct snd_soc_ac97_ops; | 168 | struct snd_soc_ac97_ops; |
169 | struct snd_soc_jack; | ||
170 | struct snd_soc_jack_pin; | ||
167 | 171 | ||
168 | typedef int (*hw_write_t)(void *,const char* ,int); | 172 | typedef int (*hw_write_t)(void *,const char* ,int); |
169 | typedef int (*hw_read_t)(void *,char* ,int); | 173 | typedef int (*hw_read_t)(void *,char* ,int); |
@@ -184,6 +188,13 @@ int snd_soc_init_card(struct snd_soc_device *socdev); | |||
184 | int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, | 188 | int 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 */ | ||
192 | int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, | ||
193 | struct snd_soc_jack *jack); | ||
194 | void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); | ||
195 | int 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 | */ |
204 | struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, | 215 | struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, |
205 | void *data, char *long_name); | 216 | void *data, char *long_name); |
217 | int snd_soc_add_controls(struct snd_soc_codec *codec, | ||
218 | const struct snd_kcontrol_new *controls, int num_controls); | ||
206 | int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, | 219 | int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, |
207 | struct snd_ctl_elem_info *uinfo); | 220 | struct snd_ctl_elem_info *uinfo); |
208 | int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol, | 221 | int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol, |
@@ -237,6 +250,27 @@ int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, | |||
237 | int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, | 250 | int 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 | */ | ||
260 | struct snd_soc_jack_pin { | ||
261 | struct list_head list; | ||
262 | const char *pin; | ||
263 | int mask; | ||
264 | bool invert; | ||
265 | }; | ||
266 | |||
267 | struct 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 */ |
241 | struct snd_soc_pcm_stream { | 275 | struct 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 @@ | |||
1 | snd-soc-core-objs := soc-core.o soc-dapm.o | 1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o |
2 | 2 | ||
3 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o | 3 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o |
4 | obj-$(CONFIG_SND_SOC) += codecs/ | 4 | obj-$(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), | |||
93 | SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0), | 93 | SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0), |
94 | }; | 94 | }; |
95 | 95 | ||
96 | /* add non dapm controls */ | ||
97 | static 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 | |||
110 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 96 | static 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 */ | ||
159 | static 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 */ |
174 | static const struct snd_kcontrol_new ak4535_mono1_mixer_controls[] = { | 159 | static 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]), | |||
151 | SOC_ENUM("Playback De-emphasis", ssm2602_enum[1]), | 151 | SOC_ENUM("Playback De-emphasis", ssm2602_enum[1]), |
152 | }; | 152 | }; |
153 | 153 | ||
154 | /* add non dapm controls */ | ||
155 | static 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 */ |
170 | static const struct snd_kcontrol_new ssm2602_output_mixer_controls[] = { | 155 | static const struct snd_kcontrol_new ssm2602_output_mixer_controls[] = { |
171 | SOC_DAPM_SINGLE("Line Bypass Switch", SSM2602_APANA, 3, 1, 0), | 156 | SOC_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 */ | ||
187 | static 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 */ |
205 | static const struct snd_kcontrol_new tlv320aic23_output_mixer_controls[] = { | 187 | static 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 */ | ||
315 | static 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 */ |
331 | static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = | 315 | static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = |
332 | SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]); | 316 | SOC_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 */ | ||
674 | static 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 | |||
689 | static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | 673 | static 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]), | |||
431 | SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), | 431 | SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), |
432 | }; | 432 | }; |
433 | 433 | ||
434 | static 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 | |||
467 | struct snd_soc_dai uda134x_dai = { | 434 | struct 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 */ | ||
275 | static 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 */ |
290 | static const struct snd_kcontrol_new uda1380_input_mux_control = | 275 | static 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 | ||
54 | struct wm8350_jack_data { | ||
55 | struct snd_soc_jack *jack; | ||
56 | int report; | ||
57 | }; | ||
58 | |||
54 | struct wm8350_data { | 59 | struct 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 | ||
778 | static 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 | |||
793 | static int wm8350_add_widgets(struct snd_soc_codec *codec) | 785 | static 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 | ||
1323 | static 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 | */ | ||
1373 | int 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 | } | ||
1410 | EXPORT_SYMBOL_GPL(wm8350_hp_jack_detect); | ||
1411 | |||
1331 | static struct snd_soc_codec *wm8350_codec; | 1412 | static struct snd_soc_codec *wm8350_codec; |
1332 | 1413 | ||
1333 | static int wm8350_probe(struct platform_device *pdev) | 1414 | static 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 @@ | |||
17 | extern struct snd_soc_dai wm8350_dai; | 17 | extern struct snd_soc_dai wm8350_dai; |
18 | extern struct snd_soc_codec_device soc_codec_dev_wm8350; | 18 | extern struct snd_soc_codec_device soc_codec_dev_wm8350; |
19 | 19 | ||
20 | enum wm8350_jack { | ||
21 | WM8350_JDL = 1, | ||
22 | WM8350_JDR = 2, | ||
23 | }; | ||
24 | |||
25 | int 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), | |||
171 | SOC_SINGLE("Mono Playback Switch", WM8510_MONOMIX, 6, 1, 1), | 171 | SOC_SINGLE("Mono Playback Switch", WM8510_MONOMIX, 6, 1, 1), |
172 | }; | 172 | }; |
173 | 173 | ||
174 | /* add non dapm controls */ | ||
175 | static 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 */ |
191 | static const struct snd_kcontrol_new wm8510_speaker_mixer_controls[] = { | 175 | static const struct snd_kcontrol_new wm8510_speaker_mixer_controls[] = { |
192 | SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_SPKMIX, 1, 1, 0), | 176 | SOC_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), | |||
330 | SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), | 330 | SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), |
331 | }; | 331 | }; |
332 | 332 | ||
333 | /* Add non-DAPM controls */ | ||
334 | static 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 | } | ||
347 | static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = { | 333 | static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = { |
348 | SND_SOC_DAPM_DAC("DAC1", "Playback", WM8580_PWRDN1, 2, 1), | 334 | SND_SOC_DAPM_DAC("DAC1", "Playback", WM8580_PWRDN1, 2, 1), |
349 | SND_SOC_DAPM_DAC("DAC2", "Playback", WM8580_PWRDN1, 3, 1), | 335 | SND_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, | |||
92 | SOC_SINGLE("Deemphasis", WM8728_DACCTL, 1, 1, 0), | 92 | SOC_SINGLE("Deemphasis", WM8728_DACCTL, 1, 1, 0), |
93 | }; | 93 | }; |
94 | 94 | ||
95 | static 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), | |||
129 | SOC_ENUM("Playback De-emphasis", wm8731_enum[1]), | 129 | SOC_ENUM("Playback De-emphasis", wm8731_enum[1]), |
130 | }; | 130 | }; |
131 | 131 | ||
132 | /* add non dapm controls */ | ||
133 | static 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 */ |
149 | static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = { | 133 | static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = { |
150 | SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0), | 134 | SOC_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 */ | ||
235 | static 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]), | |||
339 | SOC_ENUM("ROUT2 Phase", wm8753_enum[28]), | 339 | SOC_ENUM("ROUT2 Phase", wm8753_enum[28]), |
340 | }; | 340 | }; |
341 | 341 | ||
342 | /* add non dapm controls */ | ||
343 | static 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 */ | ||
521 | static 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 | |||
536 | static const struct snd_kcontrol_new wm8900_dapm_loutput2_control = | 520 | static const struct snd_kcontrol_new wm8900_dapm_loutput2_control = |
537 | SOC_DAPM_SINGLE("LINEOUT2L Switch", WM8900_REG_POWER3, 6, 1, 0); | 521 | SOC_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 | ||
747 | static 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 | |||
762 | static const struct snd_kcontrol_new linput_mode_mux = | 747 | static 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 */ | ||
199 | static 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 */ | ||
421 | static 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), | |||
154 | SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0), | 154 | SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0), |
155 | }; | 155 | }; |
156 | 156 | ||
157 | /* add non dapm controls */ | ||
158 | static 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), | |||
190 | SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1), | 190 | SOC_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1), |
191 | }; | 191 | }; |
192 | 192 | ||
193 | /* add non dapm controls */ | ||
194 | static 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, | |||
1495 | EXPORT_SYMBOL_GPL(snd_soc_cnew); | 1495 | EXPORT_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 | */ | ||
1508 | int 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 | } | ||
1526 | EXPORT_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 @@ | |||
54 | static int dapm_up_seq[] = { | 54 | static 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 | |||
60 | static int dapm_down_seq[] = { | 61 | static 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 | ||
67 | static int dapm_status = 1; | 68 | static 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 | ||
878 | static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec, | 901 | static 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 | */ |
1552 | int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin) | 1577 | int 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 | */ |
1567 | int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin) | 1592 | int 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 | */ |
1587 | int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin) | 1612 | int 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 | */ |
1602 | int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin) | 1627 | int 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 | */ | ||
31 | int 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 | } | ||
39 | EXPORT_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 | */ | ||
55 | void 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 | |||
94 | out: | ||
95 | mutex_unlock(&codec->mutex); | ||
96 | } | ||
97 | EXPORT_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 | */ | ||
110 | int 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 | } | ||
138 | EXPORT_SYMBOL_GPL(snd_soc_jack_add_pins); | ||