diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-03-03 08:40:14 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-03-03 08:40:14 -0500 |
commit | cd372fb3befde3bceef3fdcbc550dde50c894e36 (patch) | |
tree | 300fec172522d11408ccd8086f7789cdcd2a8509 /sound | |
parent | d207df2df064c19a2cf4eac8f887351fe5ce526e (diff) |
ALSA: hda - Make common input-jack helper functions
Since multiple codec drivers already use the input-jack stuff, let's
make common helper functions to reduce the duplicated codes.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 105 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 5 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 24 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 124 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 94 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 85 |
6 files changed, 165 insertions, 272 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index ae5c5d5e4b7c..2c79e96d0324 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <sound/asoundef.h> | 29 | #include <sound/asoundef.h> |
30 | #include <sound/tlv.h> | 30 | #include <sound/tlv.h> |
31 | #include <sound/initval.h> | 31 | #include <sound/initval.h> |
32 | #include <sound/jack.h> | ||
32 | #include "hda_local.h" | 33 | #include "hda_local.h" |
33 | #include "hda_beep.h" | 34 | #include "hda_beep.h" |
34 | #include <sound/hda_hwdep.h> | 35 | #include <sound/hda_hwdep.h> |
@@ -4959,5 +4960,109 @@ void snd_print_pcm_bits(int pcm, char *buf, int buflen) | |||
4959 | } | 4960 | } |
4960 | EXPORT_SYMBOL_HDA(snd_print_pcm_bits); | 4961 | EXPORT_SYMBOL_HDA(snd_print_pcm_bits); |
4961 | 4962 | ||
4963 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
4964 | /* | ||
4965 | * Input-jack notification support | ||
4966 | */ | ||
4967 | struct hda_jack_item { | ||
4968 | hda_nid_t nid; | ||
4969 | int type; | ||
4970 | struct snd_jack *jack; | ||
4971 | }; | ||
4972 | |||
4973 | static const char *get_jack_default_name(struct hda_codec *codec, hda_nid_t nid, | ||
4974 | int type) | ||
4975 | { | ||
4976 | switch (type) { | ||
4977 | case SND_JACK_HEADPHONE: | ||
4978 | return "Headphone"; | ||
4979 | case SND_JACK_MICROPHONE: | ||
4980 | return "Mic"; | ||
4981 | case SND_JACK_LINEOUT: | ||
4982 | return "Line-out"; | ||
4983 | case SND_JACK_HEADSET: | ||
4984 | return "Headset"; | ||
4985 | default: | ||
4986 | return "Misc"; | ||
4987 | } | ||
4988 | } | ||
4989 | |||
4990 | static void hda_free_jack_priv(struct snd_jack *jack) | ||
4991 | { | ||
4992 | struct hda_jack_item *jacks = jack->private_data; | ||
4993 | jacks->nid = 0; | ||
4994 | jacks->jack = NULL; | ||
4995 | } | ||
4996 | |||
4997 | int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type, | ||
4998 | const char *name) | ||
4999 | { | ||
5000 | struct hda_jack_item *jack; | ||
5001 | int err; | ||
5002 | |||
5003 | snd_array_init(&codec->jacks, sizeof(*jack), 32); | ||
5004 | jack = snd_array_new(&codec->jacks); | ||
5005 | if (!jack) | ||
5006 | return -ENOMEM; | ||
5007 | |||
5008 | jack->nid = nid; | ||
5009 | jack->type = type; | ||
5010 | if (!name) | ||
5011 | name = get_jack_default_name(codec, nid, type); | ||
5012 | err = snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
5013 | if (err < 0) { | ||
5014 | jack->nid = 0; | ||
5015 | return err; | ||
5016 | } | ||
5017 | jack->jack->private_data = jack; | ||
5018 | jack->jack->private_free = hda_free_jack_priv; | ||
5019 | return 0; | ||
5020 | } | ||
5021 | EXPORT_SYMBOL_HDA(snd_hda_input_jack_add); | ||
5022 | |||
5023 | void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid) | ||
5024 | { | ||
5025 | struct hda_jack_item *jacks = codec->jacks.list; | ||
5026 | int i; | ||
5027 | |||
5028 | if (!jacks) | ||
5029 | return; | ||
5030 | |||
5031 | for (i = 0; i < codec->jacks.used; i++, jacks++) { | ||
5032 | unsigned int pin_ctl; | ||
5033 | unsigned int present; | ||
5034 | int type; | ||
5035 | |||
5036 | if (jacks->nid != nid) | ||
5037 | continue; | ||
5038 | present = snd_hda_jack_detect(codec, nid); | ||
5039 | type = jacks->type; | ||
5040 | if (type == (SND_JACK_HEADPHONE | SND_JACK_LINEOUT)) { | ||
5041 | pin_ctl = snd_hda_codec_read(codec, nid, 0, | ||
5042 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
5043 | type = (pin_ctl & AC_PINCTL_HP_EN) ? | ||
5044 | SND_JACK_HEADPHONE : SND_JACK_LINEOUT; | ||
5045 | } | ||
5046 | snd_jack_report(jacks->jack, present ? type : 0); | ||
5047 | } | ||
5048 | } | ||
5049 | EXPORT_SYMBOL_HDA(snd_hda_input_jack_report); | ||
5050 | |||
5051 | /* free jack instances manually when clearing/reconfiguring */ | ||
5052 | void snd_hda_input_jack_free(struct hda_codec *codec) | ||
5053 | { | ||
5054 | if (!codec->bus->shutdown && codec->jacks.list) { | ||
5055 | struct hda_jack_item *jacks = codec->jacks.list; | ||
5056 | int i; | ||
5057 | for (i = 0; i < codec->jacks.used; i++, jacks++) { | ||
5058 | if (jacks->jack) | ||
5059 | snd_device_free(codec->bus->card, jacks->jack); | ||
5060 | } | ||
5061 | } | ||
5062 | snd_array_free(&codec->jacks); | ||
5063 | } | ||
5064 | EXPORT_SYMBOL_HDA(snd_hda_input_jack_free); | ||
5065 | #endif /* CONFIG_SND_HDA_INPUT_JACK */ | ||
5066 | |||
4962 | MODULE_DESCRIPTION("HDA codec core"); | 5067 | MODULE_DESCRIPTION("HDA codec core"); |
4963 | MODULE_LICENSE("GPL"); | 5068 | MODULE_LICENSE("GPL"); |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index fdf8d44f8b6b..e46d5420a9f2 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -866,6 +866,11 @@ struct hda_codec { | |||
866 | /* codec-specific additional proc output */ | 866 | /* codec-specific additional proc output */ |
867 | void (*proc_widget_hook)(struct snd_info_buffer *buffer, | 867 | void (*proc_widget_hook)(struct snd_info_buffer *buffer, |
868 | struct hda_codec *codec, hda_nid_t nid); | 868 | struct hda_codec *codec, hda_nid_t nid); |
869 | |||
870 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
871 | /* jack detection */ | ||
872 | struct snd_array jacks; | ||
873 | #endif | ||
869 | }; | 874 | }; |
870 | 875 | ||
871 | /* direction */ | 876 | /* direction */ |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 3ab5e7a303db..ff5e2ac2239a 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -656,4 +656,28 @@ static inline void snd_hda_eld_proc_free(struct hda_codec *codec, | |||
656 | #define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80 | 656 | #define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80 |
657 | void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen); | 657 | void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen); |
658 | 658 | ||
659 | /* | ||
660 | * Input-jack notification support | ||
661 | */ | ||
662 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
663 | int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type, | ||
664 | const char *name); | ||
665 | void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid); | ||
666 | void snd_hda_input_jack_free(struct hda_codec *codec); | ||
667 | #else /* CONFIG_SND_HDA_INPUT_JACK */ | ||
668 | static inline int snd_hda_input_jack_add(struct hda_codec *codec, | ||
669 | hda_nid_t nid, int type, | ||
670 | const char *name) | ||
671 | { | ||
672 | return 0; | ||
673 | } | ||
674 | static inline void snd_hda_input_jack_report(struct hda_codec *codec, | ||
675 | hda_nid_t nid) | ||
676 | { | ||
677 | } | ||
678 | static inline void snd_hda_input_jack_free(struct hda_codec *codec) | ||
679 | { | ||
680 | } | ||
681 | #endif /* CONFIG_SND_HDA_INPUT_JACK */ | ||
682 | |||
659 | #endif /* __SOUND_HDA_LOCAL_H */ | 683 | #endif /* __SOUND_HDA_LOCAL_H */ |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 4d5004e693f0..d08cf31596f3 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -49,14 +49,6 @@ | |||
49 | #define AUTO_MIC_PORTB (1 << 1) | 49 | #define AUTO_MIC_PORTB (1 << 1) |
50 | #define AUTO_MIC_PORTC (1 << 2) | 50 | #define AUTO_MIC_PORTC (1 << 2) |
51 | 51 | ||
52 | struct conexant_jack { | ||
53 | |||
54 | hda_nid_t nid; | ||
55 | int type; | ||
56 | struct snd_jack *jack; | ||
57 | |||
58 | }; | ||
59 | |||
60 | struct pin_dac_pair { | 52 | struct pin_dac_pair { |
61 | hda_nid_t pin; | 53 | hda_nid_t pin; |
62 | hda_nid_t dac; | 54 | hda_nid_t dac; |
@@ -111,9 +103,6 @@ struct conexant_spec { | |||
111 | 103 | ||
112 | unsigned int spdif_route; | 104 | unsigned int spdif_route; |
113 | 105 | ||
114 | /* jack detection */ | ||
115 | struct snd_array jacks; | ||
116 | |||
117 | /* dynamic controls, init_verbs and input_mux */ | 106 | /* dynamic controls, init_verbs and input_mux */ |
118 | struct auto_pin_cfg autocfg; | 107 | struct auto_pin_cfg autocfg; |
119 | struct hda_input_mux private_imux; | 108 | struct hda_input_mux private_imux; |
@@ -393,71 +382,9 @@ static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
393 | &spec->cur_mux[adc_idx]); | 382 | &spec->cur_mux[adc_idx]); |
394 | } | 383 | } |
395 | 384 | ||
396 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
397 | static void conexant_free_jack_priv(struct snd_jack *jack) | ||
398 | { | ||
399 | struct conexant_jack *jacks = jack->private_data; | ||
400 | jacks->nid = 0; | ||
401 | jacks->jack = NULL; | ||
402 | } | ||
403 | |||
404 | static int conexant_add_jack(struct hda_codec *codec, | ||
405 | hda_nid_t nid, int type) | ||
406 | { | ||
407 | struct conexant_spec *spec; | ||
408 | struct conexant_jack *jack; | ||
409 | const char *name; | ||
410 | int i, err; | ||
411 | |||
412 | spec = codec->spec; | ||
413 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | ||
414 | |||
415 | jack = spec->jacks.list; | ||
416 | for (i = 0; i < spec->jacks.used; i++, jack++) | ||
417 | if (jack->nid == nid) | ||
418 | return 0 ; /* already present */ | ||
419 | |||
420 | jack = snd_array_new(&spec->jacks); | ||
421 | name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ; | ||
422 | |||
423 | if (!jack) | ||
424 | return -ENOMEM; | ||
425 | |||
426 | jack->nid = nid; | ||
427 | jack->type = type; | ||
428 | |||
429 | err = snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
430 | if (err < 0) | ||
431 | return err; | ||
432 | jack->jack->private_data = jack; | ||
433 | jack->jack->private_free = conexant_free_jack_priv; | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
438 | { | ||
439 | struct conexant_spec *spec = codec->spec; | ||
440 | struct conexant_jack *jacks = spec->jacks.list; | ||
441 | |||
442 | if (jacks) { | ||
443 | int i; | ||
444 | for (i = 0; i < spec->jacks.used; i++) { | ||
445 | if (jacks->nid == nid) { | ||
446 | unsigned int present; | ||
447 | present = snd_hda_jack_detect(codec, nid); | ||
448 | |||
449 | present = (present) ? jacks->type : 0 ; | ||
450 | |||
451 | snd_jack_report(jacks->jack, | ||
452 | present); | ||
453 | } | ||
454 | jacks++; | ||
455 | } | ||
456 | } | ||
457 | } | ||
458 | |||
459 | static int conexant_init_jacks(struct hda_codec *codec) | 385 | static int conexant_init_jacks(struct hda_codec *codec) |
460 | { | 386 | { |
387 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
461 | struct conexant_spec *spec = codec->spec; | 388 | struct conexant_spec *spec = codec->spec; |
462 | int i; | 389 | int i; |
463 | 390 | ||
@@ -469,15 +396,15 @@ static int conexant_init_jacks(struct hda_codec *codec) | |||
469 | int err = 0; | 396 | int err = 0; |
470 | switch (hv->param ^ AC_USRSP_EN) { | 397 | switch (hv->param ^ AC_USRSP_EN) { |
471 | case CONEXANT_HP_EVENT: | 398 | case CONEXANT_HP_EVENT: |
472 | err = conexant_add_jack(codec, hv->nid, | 399 | err = snd_hda_input_jack_add(codec, hv->nid, |
473 | SND_JACK_HEADPHONE); | 400 | SND_JACK_HEADPHONE, NULL); |
474 | conexant_report_jack(codec, hv->nid); | 401 | snd_hda_input_jack_report(codec, hv->nid); |
475 | break; | 402 | break; |
476 | case CXT5051_PORTC_EVENT: | 403 | case CXT5051_PORTC_EVENT: |
477 | case CONEXANT_MIC_EVENT: | 404 | case CONEXANT_MIC_EVENT: |
478 | err = conexant_add_jack(codec, hv->nid, | 405 | err = snd_hda_input_jack_add(codec, hv->nid, |
479 | SND_JACK_MICROPHONE); | 406 | SND_JACK_MICROPHONE, NULL); |
480 | conexant_report_jack(codec, hv->nid); | 407 | snd_hda_input_jack_report(codec, hv->nid); |
481 | break; | 408 | break; |
482 | } | 409 | } |
483 | if (err < 0) | 410 | if (err < 0) |
@@ -485,19 +412,9 @@ static int conexant_init_jacks(struct hda_codec *codec) | |||
485 | ++hv; | 412 | ++hv; |
486 | } | 413 | } |
487 | } | 414 | } |
488 | return 0; | 415 | #endif /* CONFIG_SND_HDA_INPUT_JACK */ |
489 | |||
490 | } | ||
491 | #else | ||
492 | static inline void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
493 | { | ||
494 | } | ||
495 | |||
496 | static inline int conexant_init_jacks(struct hda_codec *codec) | ||
497 | { | ||
498 | return 0; | 416 | return 0; |
499 | } | 417 | } |
500 | #endif | ||
501 | 418 | ||
502 | static int conexant_init(struct hda_codec *codec) | 419 | static int conexant_init(struct hda_codec *codec) |
503 | { | 420 | { |
@@ -511,18 +428,7 @@ static int conexant_init(struct hda_codec *codec) | |||
511 | 428 | ||
512 | static void conexant_free(struct hda_codec *codec) | 429 | static void conexant_free(struct hda_codec *codec) |
513 | { | 430 | { |
514 | #ifdef CONFIG_SND_HDA_INPUT_JACK | 431 | snd_hda_input_jack_free(codec); |
515 | struct conexant_spec *spec = codec->spec; | ||
516 | if (spec->jacks.list) { | ||
517 | struct conexant_jack *jacks = spec->jacks.list; | ||
518 | int i; | ||
519 | for (i = 0; i < spec->jacks.used; i++, jacks++) { | ||
520 | if (jacks->jack) | ||
521 | snd_device_free(codec->bus->card, jacks->jack); | ||
522 | } | ||
523 | snd_array_free(&spec->jacks); | ||
524 | } | ||
525 | #endif | ||
526 | snd_hda_detach_beep_device(codec); | 432 | snd_hda_detach_beep_device(codec); |
527 | kfree(codec->spec); | 433 | kfree(codec->spec); |
528 | } | 434 | } |
@@ -1787,7 +1693,7 @@ static void cxt5051_hp_unsol_event(struct hda_codec *codec, | |||
1787 | cxt5051_portc_automic(codec); | 1693 | cxt5051_portc_automic(codec); |
1788 | break; | 1694 | break; |
1789 | } | 1695 | } |
1790 | conexant_report_jack(codec, nid); | 1696 | snd_hda_input_jack_report(codec, nid); |
1791 | } | 1697 | } |
1792 | 1698 | ||
1793 | static struct snd_kcontrol_new cxt5051_playback_mixers[] = { | 1699 | static struct snd_kcontrol_new cxt5051_playback_mixers[] = { |
@@ -1959,10 +1865,8 @@ static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid, | |||
1959 | snd_hda_codec_write(codec, nid, 0, | 1865 | snd_hda_codec_write(codec, nid, 0, |
1960 | AC_VERB_SET_UNSOLICITED_ENABLE, | 1866 | AC_VERB_SET_UNSOLICITED_ENABLE, |
1961 | AC_USRSP_EN | event); | 1867 | AC_USRSP_EN | event); |
1962 | #ifdef CONFIG_SND_HDA_INPUT_JACK | 1868 | snd_hda_input_jack_add(codec, nid, SND_JACK_MICROPHONE, NULL); |
1963 | conexant_add_jack(codec, nid, SND_JACK_MICROPHONE); | 1869 | snd_hda_input_jack_report(codec, nid); |
1964 | conexant_report_jack(codec, nid); | ||
1965 | #endif | ||
1966 | } | 1870 | } |
1967 | 1871 | ||
1968 | static struct hda_verb cxt5051_ideapad_init_verbs[] = { | 1872 | static struct hda_verb cxt5051_ideapad_init_verbs[] = { |
@@ -3477,11 +3381,11 @@ static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res) | |||
3477 | switch (res >> 26) { | 3381 | switch (res >> 26) { |
3478 | case CONEXANT_HP_EVENT: | 3382 | case CONEXANT_HP_EVENT: |
3479 | cx_auto_hp_automute(codec); | 3383 | cx_auto_hp_automute(codec); |
3480 | conexant_report_jack(codec, nid); | 3384 | snd_hda_input_jack_report(codec, nid); |
3481 | break; | 3385 | break; |
3482 | case CONEXANT_MIC_EVENT: | 3386 | case CONEXANT_MIC_EVENT: |
3483 | cx_auto_automic(codec); | 3387 | cx_auto_automic(codec); |
3484 | conexant_report_jack(codec, nid); | 3388 | snd_hda_input_jack_report(codec, nid); |
3485 | break; | 3389 | break; |
3486 | } | 3390 | } |
3487 | } | 3391 | } |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 96cb442dc1d1..f6c344126b83 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -282,12 +282,6 @@ struct alc_mic_route { | |||
282 | unsigned char amix_idx; | 282 | unsigned char amix_idx; |
283 | }; | 283 | }; |
284 | 284 | ||
285 | struct alc_jack { | ||
286 | hda_nid_t nid; | ||
287 | int type; | ||
288 | struct snd_jack *jack; | ||
289 | }; | ||
290 | |||
291 | #define MUX_IDX_UNDEF ((unsigned char)-1) | 285 | #define MUX_IDX_UNDEF ((unsigned char)-1) |
292 | 286 | ||
293 | struct alc_customize_define { | 287 | struct alc_customize_define { |
@@ -366,9 +360,6 @@ struct alc_spec { | |||
366 | /* PCM information */ | 360 | /* PCM information */ |
367 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ | 361 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ |
368 | 362 | ||
369 | /* jack detection */ | ||
370 | struct snd_array jacks; | ||
371 | |||
372 | /* dynamic controls, init_verbs and input_mux */ | 363 | /* dynamic controls, init_verbs and input_mux */ |
373 | struct auto_pin_cfg autocfg; | 364 | struct auto_pin_cfg autocfg; |
374 | struct alc_customize_define cdefine; | 365 | struct alc_customize_define cdefine; |
@@ -1032,94 +1023,32 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid, | |||
1032 | alc_fix_pll(codec); | 1023 | alc_fix_pll(codec); |
1033 | } | 1024 | } |
1034 | 1025 | ||
1035 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
1036 | static void alc_free_jack_priv(struct snd_jack *jack) | ||
1037 | { | ||
1038 | struct alc_jack *jacks = jack->private_data; | ||
1039 | jacks->nid = 0; | ||
1040 | jacks->jack = NULL; | ||
1041 | } | ||
1042 | |||
1043 | static int alc_add_jack(struct hda_codec *codec, | ||
1044 | hda_nid_t nid, int type) | ||
1045 | { | ||
1046 | struct alc_spec *spec; | ||
1047 | struct alc_jack *jack; | ||
1048 | const char *name; | ||
1049 | int err; | ||
1050 | |||
1051 | spec = codec->spec; | ||
1052 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | ||
1053 | jack = snd_array_new(&spec->jacks); | ||
1054 | if (!jack) | ||
1055 | return -ENOMEM; | ||
1056 | |||
1057 | jack->nid = nid; | ||
1058 | jack->type = type; | ||
1059 | name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ; | ||
1060 | |||
1061 | err = snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
1062 | if (err < 0) | ||
1063 | return err; | ||
1064 | jack->jack->private_data = jack; | ||
1065 | jack->jack->private_free = alc_free_jack_priv; | ||
1066 | return 0; | ||
1067 | } | ||
1068 | |||
1069 | static void alc_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
1070 | { | ||
1071 | struct alc_spec *spec = codec->spec; | ||
1072 | struct alc_jack *jacks = spec->jacks.list; | ||
1073 | |||
1074 | if (jacks) { | ||
1075 | int i; | ||
1076 | for (i = 0; i < spec->jacks.used; i++) { | ||
1077 | if (jacks->nid == nid) { | ||
1078 | unsigned int present; | ||
1079 | present = snd_hda_jack_detect(codec, nid); | ||
1080 | |||
1081 | present = (present) ? jacks->type : 0; | ||
1082 | |||
1083 | snd_jack_report(jacks->jack, present); | ||
1084 | } | ||
1085 | jacks++; | ||
1086 | } | ||
1087 | } | ||
1088 | } | ||
1089 | |||
1090 | static int alc_init_jacks(struct hda_codec *codec) | 1026 | static int alc_init_jacks(struct hda_codec *codec) |
1091 | { | 1027 | { |
1028 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
1092 | struct alc_spec *spec = codec->spec; | 1029 | struct alc_spec *spec = codec->spec; |
1093 | int err; | 1030 | int err; |
1094 | unsigned int hp_nid = spec->autocfg.hp_pins[0]; | 1031 | unsigned int hp_nid = spec->autocfg.hp_pins[0]; |
1095 | unsigned int mic_nid = spec->ext_mic.pin; | 1032 | unsigned int mic_nid = spec->ext_mic.pin; |
1096 | 1033 | ||
1097 | if (hp_nid) { | 1034 | if (hp_nid) { |
1098 | err = alc_add_jack(codec, hp_nid, SND_JACK_HEADPHONE); | 1035 | err = snd_hda_input_jack_add(codec, hp_nid, |
1036 | SND_JACK_HEADPHONE, NULL); | ||
1099 | if (err < 0) | 1037 | if (err < 0) |
1100 | return err; | 1038 | return err; |
1101 | alc_report_jack(codec, hp_nid); | 1039 | snd_hda_input_jack_report(codec, hp_nid); |
1102 | } | 1040 | } |
1103 | 1041 | ||
1104 | if (mic_nid) { | 1042 | if (mic_nid) { |
1105 | err = alc_add_jack(codec, mic_nid, SND_JACK_MICROPHONE); | 1043 | err = snd_hda_input_jack_add(codec, mic_nid, |
1044 | SND_JACK_MICROPHONE, NULL); | ||
1106 | if (err < 0) | 1045 | if (err < 0) |
1107 | return err; | 1046 | return err; |
1108 | alc_report_jack(codec, mic_nid); | 1047 | snd_hda_input_jack_report(codec, mic_nid); |
1109 | } | 1048 | } |
1110 | 1049 | #endif /* CONFIG_SND_HDA_INPUT_JACK */ | |
1111 | return 0; | ||
1112 | } | ||
1113 | #else | ||
1114 | static inline void alc_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
1115 | { | ||
1116 | } | ||
1117 | |||
1118 | static inline int alc_init_jacks(struct hda_codec *codec) | ||
1119 | { | ||
1120 | return 0; | 1050 | return 0; |
1121 | } | 1051 | } |
1122 | #endif | ||
1123 | 1052 | ||
1124 | static void alc_automute_speaker(struct hda_codec *codec, int pinctl) | 1053 | static void alc_automute_speaker(struct hda_codec *codec, int pinctl) |
1125 | { | 1054 | { |
@@ -1133,7 +1062,7 @@ static void alc_automute_speaker(struct hda_codec *codec, int pinctl) | |||
1133 | nid = spec->autocfg.hp_pins[i]; | 1062 | nid = spec->autocfg.hp_pins[i]; |
1134 | if (!nid) | 1063 | if (!nid) |
1135 | break; | 1064 | break; |
1136 | alc_report_jack(codec, nid); | 1065 | snd_hda_input_jack_report(codec, nid); |
1137 | spec->jack_present |= snd_hda_jack_detect(codec, nid); | 1066 | spec->jack_present |= snd_hda_jack_detect(codec, nid); |
1138 | } | 1067 | } |
1139 | 1068 | ||
@@ -1240,7 +1169,7 @@ static void alc_mic_automute(struct hda_codec *codec) | |||
1240 | AC_VERB_SET_CONNECT_SEL, | 1169 | AC_VERB_SET_CONNECT_SEL, |
1241 | alive->mux_idx); | 1170 | alive->mux_idx); |
1242 | } | 1171 | } |
1243 | alc_report_jack(codec, spec->ext_mic.pin); | 1172 | snd_hda_input_jack_report(codec, spec->ext_mic.pin); |
1244 | 1173 | ||
1245 | /* FIXME: analog mixer */ | 1174 | /* FIXME: analog mixer */ |
1246 | } | 1175 | } |
@@ -4283,6 +4212,7 @@ static void alc_free(struct hda_codec *codec) | |||
4283 | return; | 4212 | return; |
4284 | 4213 | ||
4285 | alc_shutup(codec); | 4214 | alc_shutup(codec); |
4215 | snd_hda_input_jack_free(codec); | ||
4286 | alc_free_kctls(codec); | 4216 | alc_free_kctls(codec); |
4287 | kfree(spec); | 4217 | kfree(spec); |
4288 | snd_hda_detach_beep_device(codec); | 4218 | snd_hda_detach_beep_device(codec); |
@@ -14494,7 +14424,7 @@ static void alc269_speaker_automute(struct hda_codec *codec) | |||
14494 | HDA_AMP_MUTE, bits); | 14424 | HDA_AMP_MUTE, bits); |
14495 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, | 14425 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, |
14496 | HDA_AMP_MUTE, bits); | 14426 | HDA_AMP_MUTE, bits); |
14497 | alc_report_jack(codec, nid); | 14427 | snd_hda_input_jack_report(codec, nid); |
14498 | } | 14428 | } |
14499 | 14429 | ||
14500 | /* unsolicited event for HP jack sensing */ | 14430 | /* unsolicited event for HP jack sensing */ |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index bd7b123f6440..8fe5608c5f29 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -180,12 +180,6 @@ struct sigmatel_event { | |||
180 | int data; | 180 | int data; |
181 | }; | 181 | }; |
182 | 182 | ||
183 | struct sigmatel_jack { | ||
184 | hda_nid_t nid; | ||
185 | int type; | ||
186 | struct snd_jack *jack; | ||
187 | }; | ||
188 | |||
189 | struct sigmatel_mic_route { | 183 | struct sigmatel_mic_route { |
190 | hda_nid_t pin; | 184 | hda_nid_t pin; |
191 | signed char mux_idx; | 185 | signed char mux_idx; |
@@ -229,9 +223,6 @@ struct sigmatel_spec { | |||
229 | hda_nid_t *pwr_nids; | 223 | hda_nid_t *pwr_nids; |
230 | hda_nid_t *dac_list; | 224 | hda_nid_t *dac_list; |
231 | 225 | ||
232 | /* jack detection */ | ||
233 | struct snd_array jacks; | ||
234 | |||
235 | /* events */ | 226 | /* events */ |
236 | struct snd_array events; | 227 | struct snd_array events; |
237 | 228 | ||
@@ -4054,21 +4045,10 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, | |||
4054 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ | 4045 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ |
4055 | } | 4046 | } |
4056 | 4047 | ||
4057 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
4058 | static void stac92xx_free_jack_priv(struct snd_jack *jack) | ||
4059 | { | ||
4060 | struct sigmatel_jack *jacks = jack->private_data; | ||
4061 | jacks->nid = 0; | ||
4062 | jacks->jack = NULL; | ||
4063 | } | ||
4064 | #endif | ||
4065 | |||
4066 | static int stac92xx_add_jack(struct hda_codec *codec, | 4048 | static int stac92xx_add_jack(struct hda_codec *codec, |
4067 | hda_nid_t nid, int type) | 4049 | hda_nid_t nid, int type) |
4068 | { | 4050 | { |
4069 | #ifdef CONFIG_SND_HDA_INPUT_JACK | 4051 | #ifdef CONFIG_SND_HDA_INPUT_JACK |
4070 | struct sigmatel_spec *spec = codec->spec; | ||
4071 | struct sigmatel_jack *jack; | ||
4072 | int def_conf = snd_hda_codec_get_pincfg(codec, nid); | 4052 | int def_conf = snd_hda_codec_get_pincfg(codec, nid); |
4073 | int connectivity = get_defcfg_connect(def_conf); | 4053 | int connectivity = get_defcfg_connect(def_conf); |
4074 | char name[32]; | 4054 | char name[32]; |
@@ -4077,26 +4057,15 @@ static int stac92xx_add_jack(struct hda_codec *codec, | |||
4077 | if (connectivity && connectivity != AC_JACK_PORT_FIXED) | 4057 | if (connectivity && connectivity != AC_JACK_PORT_FIXED) |
4078 | return 0; | 4058 | return 0; |
4079 | 4059 | ||
4080 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | ||
4081 | jack = snd_array_new(&spec->jacks); | ||
4082 | if (!jack) | ||
4083 | return -ENOMEM; | ||
4084 | jack->nid = nid; | ||
4085 | jack->type = type; | ||
4086 | |||
4087 | snprintf(name, sizeof(name), "%s at %s %s Jack", | 4060 | snprintf(name, sizeof(name), "%s at %s %s Jack", |
4088 | snd_hda_get_jack_type(def_conf), | 4061 | snd_hda_get_jack_type(def_conf), |
4089 | snd_hda_get_jack_connectivity(def_conf), | 4062 | snd_hda_get_jack_connectivity(def_conf), |
4090 | snd_hda_get_jack_location(def_conf)); | 4063 | snd_hda_get_jack_location(def_conf)); |
4091 | 4064 | ||
4092 | err = snd_jack_new(codec->bus->card, name, type, &jack->jack); | 4065 | err = snd_hda_input_jack_add(codec, nid, type, name); |
4093 | if (err < 0) { | 4066 | if (err < 0) |
4094 | jack->nid = 0; | ||
4095 | return err; | 4067 | return err; |
4096 | } | 4068 | #endif /* CONFIG_SND_HDA_INPUT_JACK */ |
4097 | jack->jack->private_data = jack; | ||
4098 | jack->jack->private_free = stac92xx_free_jack_priv; | ||
4099 | #endif | ||
4100 | return 0; | 4069 | return 0; |
4101 | } | 4070 | } |
4102 | 4071 | ||
@@ -4399,23 +4368,6 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4399 | return 0; | 4368 | return 0; |
4400 | } | 4369 | } |
4401 | 4370 | ||
4402 | static void stac92xx_free_jacks(struct hda_codec *codec) | ||
4403 | { | ||
4404 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
4405 | /* free jack instances manually when clearing/reconfiguring */ | ||
4406 | struct sigmatel_spec *spec = codec->spec; | ||
4407 | if (!codec->bus->shutdown && spec->jacks.list) { | ||
4408 | struct sigmatel_jack *jacks = spec->jacks.list; | ||
4409 | int i; | ||
4410 | for (i = 0; i < spec->jacks.used; i++, jacks++) { | ||
4411 | if (jacks->jack) | ||
4412 | snd_device_free(codec->bus->card, jacks->jack); | ||
4413 | } | ||
4414 | } | ||
4415 | snd_array_free(&spec->jacks); | ||
4416 | #endif | ||
4417 | } | ||
4418 | |||
4419 | static void stac92xx_free_kctls(struct hda_codec *codec) | 4371 | static void stac92xx_free_kctls(struct hda_codec *codec) |
4420 | { | 4372 | { |
4421 | struct sigmatel_spec *spec = codec->spec; | 4373 | struct sigmatel_spec *spec = codec->spec; |
@@ -4449,7 +4401,7 @@ static void stac92xx_free(struct hda_codec *codec) | |||
4449 | return; | 4401 | return; |
4450 | 4402 | ||
4451 | stac92xx_shutup(codec); | 4403 | stac92xx_shutup(codec); |
4452 | stac92xx_free_jacks(codec); | 4404 | snd_hda_input_jack_free(codec); |
4453 | snd_array_free(&spec->events); | 4405 | snd_array_free(&spec->events); |
4454 | 4406 | ||
4455 | kfree(spec); | 4407 | kfree(spec); |
@@ -4667,33 +4619,6 @@ static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid) | |||
4667 | stac_toggle_power_map(codec, nid, get_pin_presence(codec, nid)); | 4619 | stac_toggle_power_map(codec, nid, get_pin_presence(codec, nid)); |
4668 | } | 4620 | } |
4669 | 4621 | ||
4670 | static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
4671 | { | ||
4672 | struct sigmatel_spec *spec = codec->spec; | ||
4673 | struct sigmatel_jack *jacks = spec->jacks.list; | ||
4674 | |||
4675 | if (jacks) { | ||
4676 | int i; | ||
4677 | for (i = 0; i < spec->jacks.used; i++) { | ||
4678 | if (jacks->nid == nid) { | ||
4679 | unsigned int pin_ctl = | ||
4680 | snd_hda_codec_read(codec, nid, | ||
4681 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
4682 | 0x00); | ||
4683 | int type = jacks->type; | ||
4684 | if (type == (SND_JACK_LINEOUT | ||
4685 | | SND_JACK_HEADPHONE)) | ||
4686 | type = (pin_ctl & AC_PINCTL_HP_EN) | ||
4687 | ? SND_JACK_HEADPHONE : SND_JACK_LINEOUT; | ||
4688 | snd_jack_report(jacks->jack, | ||
4689 | get_pin_presence(codec, nid) | ||
4690 | ? type : 0); | ||
4691 | } | ||
4692 | jacks++; | ||
4693 | } | ||
4694 | } | ||
4695 | } | ||
4696 | |||
4697 | /* get the pin connection (fixed, none, etc) */ | 4622 | /* get the pin connection (fixed, none, etc) */ |
4698 | static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx) | 4623 | static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx) |
4699 | { | 4624 | { |
@@ -4782,7 +4707,7 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | |||
4782 | case STAC_PWR_EVENT: | 4707 | case STAC_PWR_EVENT: |
4783 | if (spec->num_pwrs > 0) | 4708 | if (spec->num_pwrs > 0) |
4784 | stac92xx_pin_sense(codec, event->nid); | 4709 | stac92xx_pin_sense(codec, event->nid); |
4785 | stac92xx_report_jack(codec, event->nid); | 4710 | snd_hda_input_jack_report(codec, event->nid); |
4786 | 4711 | ||
4787 | switch (codec->subsystem_id) { | 4712 | switch (codec->subsystem_id) { |
4788 | case 0x103c308f: | 4713 | case 0x103c308f: |