diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-12-01 11:41:36 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-12-01 11:47:54 -0500 |
commit | 31ef22579302ac42054bebecb528710f46580925 (patch) | |
tree | 8f521b4920f0a1ebbb1e6f9105948a5f38f24404 /sound/pci/hda/hda_jack.c | |
parent | 358b6e62b86f6313d114e0f6b7d8f8adaf85ed9c (diff) |
ALSA: hda - Integrate input-jack stuff into kctl-jack
Instead of managing input-jack stuff separately, call all stuff inside
the kctl-jack creation, deletion and report. The caller no longer needs
to care about input-jack.
The better integration between input-jack and kctl-jack should be done
in the upper layer in near future, but for now, it's implemented locally
for more tests.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_jack.c')
-rw-r--r-- | sound/pci/hda/hda_jack.c | 159 |
1 files changed, 60 insertions, 99 deletions
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 394901515d9..d8a35da0803 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c | |||
@@ -90,15 +90,19 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid) | |||
90 | } | 90 | } |
91 | EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_new); | 91 | EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_new); |
92 | 92 | ||
93 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
94 | static void snd_hda_input_jack_free(struct hda_codec *codec); | ||
95 | #else | ||
96 | #define snd_hda_input_jack_free(codec) | ||
97 | #endif | ||
98 | |||
99 | void snd_hda_jack_tbl_clear(struct hda_codec *codec) | 93 | void snd_hda_jack_tbl_clear(struct hda_codec *codec) |
100 | { | 94 | { |
101 | snd_hda_input_jack_free(codec); | 95 | #ifdef CONFIG_SND_HDA_INPUT_JACK |
96 | /* free jack instances manually when clearing/reconfiguring */ | ||
97 | if (!codec->bus->shutdown && codec->jacktbl.list) { | ||
98 | struct hda_jack_tbl *jack = codec->jacktbl.list; | ||
99 | int i; | ||
100 | for (i = 0; i < codec->jacktbl.used; i++, jack++) { | ||
101 | if (jack->jack) | ||
102 | snd_device_free(codec->bus->card, jack->jack); | ||
103 | } | ||
104 | } | ||
105 | #endif | ||
102 | snd_array_free(&codec->jacktbl); | 106 | snd_array_free(&codec->jacktbl); |
103 | } | 107 | } |
104 | 108 | ||
@@ -199,10 +203,44 @@ void snd_hda_jack_report_sync(struct hda_codec *codec) | |||
199 | continue; | 203 | continue; |
200 | state = get_jack_plug_state(jack->pin_sense); | 204 | state = get_jack_plug_state(jack->pin_sense); |
201 | snd_kctl_jack_report(codec->bus->card, jack->kctl, state); | 205 | snd_kctl_jack_report(codec->bus->card, jack->kctl, state); |
206 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
207 | if (jack->jack) | ||
208 | snd_jack_report(jack->jack, | ||
209 | state ? jack->type : 0); | ||
210 | #endif | ||
202 | } | 211 | } |
203 | } | 212 | } |
204 | EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync); | 213 | EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync); |
205 | 214 | ||
215 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
216 | /* guess the jack type from the pin-config */ | ||
217 | static int get_input_jack_type(struct hda_codec *codec, hda_nid_t nid) | ||
218 | { | ||
219 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); | ||
220 | switch (get_defcfg_device(def_conf)) { | ||
221 | case AC_JACK_LINE_OUT: | ||
222 | case AC_JACK_SPEAKER: | ||
223 | return SND_JACK_LINEOUT; | ||
224 | case AC_JACK_HP_OUT: | ||
225 | return SND_JACK_HEADPHONE; | ||
226 | case AC_JACK_SPDIF_OUT: | ||
227 | case AC_JACK_DIG_OTHER_OUT: | ||
228 | return SND_JACK_AVOUT; | ||
229 | case AC_JACK_MIC_IN: | ||
230 | return SND_JACK_MICROPHONE; | ||
231 | default: | ||
232 | return SND_JACK_LINEIN; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | static void hda_free_jack_priv(struct snd_jack *jack) | ||
237 | { | ||
238 | struct hda_jack_tbl *jacks = jack->private_data; | ||
239 | jacks->nid = 0; | ||
240 | jacks->jack = NULL; | ||
241 | } | ||
242 | #endif | ||
243 | |||
206 | /** | 244 | /** |
207 | * snd_hda_jack_add_kctl - Add a kctl for the given pin | 245 | * snd_hda_jack_add_kctl - Add a kctl for the given pin |
208 | * | 246 | * |
@@ -214,6 +252,7 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | |||
214 | { | 252 | { |
215 | struct hda_jack_tbl *jack; | 253 | struct hda_jack_tbl *jack; |
216 | struct snd_kcontrol *kctl; | 254 | struct snd_kcontrol *kctl; |
255 | int err, state; | ||
217 | 256 | ||
218 | jack = snd_hda_jack_tbl_new(codec, nid); | 257 | jack = snd_hda_jack_tbl_new(codec, nid); |
219 | if (!jack) | 258 | if (!jack) |
@@ -223,11 +262,21 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, | |||
223 | kctl = snd_kctl_jack_new(name, idx, codec); | 262 | kctl = snd_kctl_jack_new(name, idx, codec); |
224 | if (!kctl) | 263 | if (!kctl) |
225 | return -ENOMEM; | 264 | return -ENOMEM; |
226 | if (snd_hda_ctl_add(codec, nid, kctl) < 0) | 265 | err = snd_hda_ctl_add(codec, nid, kctl); |
227 | return -ENOMEM; | 266 | if (err < 0) |
267 | return err; | ||
228 | jack->kctl = kctl; | 268 | jack->kctl = kctl; |
229 | snd_kctl_jack_report(codec->bus->card, kctl, | 269 | state = snd_hda_jack_detect(codec, nid); |
230 | snd_hda_jack_detect(codec, nid)); | 270 | snd_kctl_jack_report(codec->bus->card, kctl, state); |
271 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
272 | jack->type = get_input_jack_type(codec, nid); | ||
273 | err = snd_jack_new(codec->bus->card, name, jack->type, &jack->jack); | ||
274 | if (err < 0) | ||
275 | return err; | ||
276 | jack->jack->private_data = jack; | ||
277 | jack->jack->private_free = hda_free_jack_priv; | ||
278 | snd_jack_report(jack->jack, state ? jack->type : 0); | ||
279 | #endif | ||
231 | return 0; | 280 | return 0; |
232 | } | 281 | } |
233 | EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); | 282 | EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl); |
@@ -302,91 +351,3 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec, | |||
302 | return 0; | 351 | return 0; |
303 | } | 352 | } |
304 | EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls); | 353 | EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls); |
305 | |||
306 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
307 | /* | ||
308 | * Input-jack notification support | ||
309 | */ | ||
310 | static const char *get_jack_default_name(struct hda_codec *codec, hda_nid_t nid, | ||
311 | int type) | ||
312 | { | ||
313 | switch (type) { | ||
314 | case SND_JACK_HEADPHONE: | ||
315 | return "Headphone"; | ||
316 | case SND_JACK_MICROPHONE: | ||
317 | return "Mic"; | ||
318 | case SND_JACK_LINEOUT: | ||
319 | return "Line-out"; | ||
320 | case SND_JACK_LINEIN: | ||
321 | return "Line-in"; | ||
322 | case SND_JACK_HEADSET: | ||
323 | return "Headset"; | ||
324 | case SND_JACK_VIDEOOUT: | ||
325 | return "HDMI/DP"; | ||
326 | default: | ||
327 | return "Misc"; | ||
328 | } | ||
329 | } | ||
330 | |||
331 | static void hda_free_jack_priv(struct snd_jack *jack) | ||
332 | { | ||
333 | struct hda_jack_tbl *jacks = jack->private_data; | ||
334 | jacks->nid = 0; | ||
335 | jacks->jack = NULL; | ||
336 | } | ||
337 | |||
338 | int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type, | ||
339 | const char *name) | ||
340 | { | ||
341 | struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); | ||
342 | int err; | ||
343 | |||
344 | if (!jack) | ||
345 | return -ENOMEM; | ||
346 | if (!name) | ||
347 | name = get_jack_default_name(codec, nid, type); | ||
348 | err = snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
349 | if (err < 0) | ||
350 | return err; | ||
351 | jack->type = type; | ||
352 | jack->jack->private_data = jack; | ||
353 | jack->jack->private_free = hda_free_jack_priv; | ||
354 | return 0; | ||
355 | } | ||
356 | EXPORT_SYMBOL_HDA(snd_hda_input_jack_add); | ||
357 | |||
358 | void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid) | ||
359 | { | ||
360 | struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); | ||
361 | unsigned int pin_ctl; | ||
362 | unsigned int present; | ||
363 | int type; | ||
364 | |||
365 | if (!jack || !jack->jack) | ||
366 | return; | ||
367 | |||
368 | present = snd_hda_jack_detect(codec, nid); | ||
369 | type = jack->type; | ||
370 | if (type == (SND_JACK_HEADPHONE | SND_JACK_LINEOUT)) { | ||
371 | pin_ctl = snd_hda_codec_read(codec, nid, 0, | ||
372 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
373 | type = (pin_ctl & AC_PINCTL_HP_EN) ? | ||
374 | SND_JACK_HEADPHONE : SND_JACK_LINEOUT; | ||
375 | } | ||
376 | snd_jack_report(jack->jack, present ? type : 0); | ||
377 | } | ||
378 | EXPORT_SYMBOL_HDA(snd_hda_input_jack_report); | ||
379 | |||
380 | /* free jack instances manually when clearing/reconfiguring */ | ||
381 | static void snd_hda_input_jack_free(struct hda_codec *codec) | ||
382 | { | ||
383 | if (!codec->bus->shutdown && codec->jacktbl.list) { | ||
384 | struct hda_jack_tbl *jack = codec->jacktbl.list; | ||
385 | int i; | ||
386 | for (i = 0; i < codec->jacktbl.used; i++, jack++) { | ||
387 | if (jack->jack) | ||
388 | snd_device_free(codec->bus->card, jack->jack); | ||
389 | } | ||
390 | } | ||
391 | } | ||
392 | #endif /* CONFIG_SND_HDA_INPUT_JACK */ | ||