diff options
author | Kailang Yang <kailang@realtek.com> | 2010-09-14 17:22:00 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-09-14 17:22:00 -0400 |
commit | 9ad0e496519d99eb2c34f01e41500a775122c744 (patch) | |
tree | 736ab4a2b4e4645187998e43896546e52c3f34df /sound/pci/hda/patch_realtek.c | |
parent | 4a4d4a6985dd37a3c96534027f054be796bf95f6 (diff) |
ALSA: hda - Add input jack layer support to Realtek codec
Signed-off-by: Kailang Yang <kailang@realtek.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 9c2c19c8b059..3b040870365d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
30 | #include <sound/core.h> | 30 | #include <sound/core.h> |
31 | #include <sound/jack.h> | ||
31 | #include "hda_codec.h" | 32 | #include "hda_codec.h" |
32 | #include "hda_local.h" | 33 | #include "hda_local.h" |
33 | #include "hda_beep.h" | 34 | #include "hda_beep.h" |
@@ -282,6 +283,12 @@ struct alc_mic_route { | |||
282 | unsigned char amix_idx; | 283 | unsigned char amix_idx; |
283 | }; | 284 | }; |
284 | 285 | ||
286 | struct alc_jack { | ||
287 | hda_nid_t nid; | ||
288 | int type; | ||
289 | struct snd_jack *jack; | ||
290 | }; | ||
291 | |||
285 | #define MUX_IDX_UNDEF ((unsigned char)-1) | 292 | #define MUX_IDX_UNDEF ((unsigned char)-1) |
286 | 293 | ||
287 | struct alc_customize_define { | 294 | struct alc_customize_define { |
@@ -357,6 +364,9 @@ struct alc_spec { | |||
357 | /* PCM information */ | 364 | /* PCM information */ |
358 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ | 365 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ |
359 | 366 | ||
367 | /* jack detection */ | ||
368 | struct snd_array jacks; | ||
369 | |||
360 | /* dynamic controls, init_verbs and input_mux */ | 370 | /* dynamic controls, init_verbs and input_mux */ |
361 | struct auto_pin_cfg autocfg; | 371 | struct auto_pin_cfg autocfg; |
362 | struct alc_customize_define cdefine; | 372 | struct alc_customize_define cdefine; |
@@ -990,6 +1000,91 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid, | |||
990 | alc_fix_pll(codec); | 1000 | alc_fix_pll(codec); |
991 | } | 1001 | } |
992 | 1002 | ||
1003 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
1004 | static void alc_free_jack_priv(struct snd_jack *jack) | ||
1005 | { | ||
1006 | struct alc_jack *jacks = jack->private_data; | ||
1007 | jacks->nid = 0; | ||
1008 | jacks->jack = NULL; | ||
1009 | } | ||
1010 | |||
1011 | static int alc_add_jack(struct hda_codec *codec, | ||
1012 | hda_nid_t nid, int type) | ||
1013 | { | ||
1014 | struct alc_spec *spec; | ||
1015 | struct alc_jack *jack; | ||
1016 | const char *name; | ||
1017 | int err; | ||
1018 | |||
1019 | spec = codec->spec; | ||
1020 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | ||
1021 | jack = snd_array_new(&spec->jacks); | ||
1022 | if (!jack) | ||
1023 | return -ENOMEM; | ||
1024 | |||
1025 | jack->nid = nid; | ||
1026 | jack->type = type; | ||
1027 | name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ; | ||
1028 | |||
1029 | err = snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
1030 | if (err < 0) | ||
1031 | return err; | ||
1032 | jack->jack->private_data = jack; | ||
1033 | jack->jack->private_free = alc_free_jack_priv; | ||
1034 | return 0; | ||
1035 | } | ||
1036 | |||
1037 | static void alc_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
1038 | { | ||
1039 | struct alc_spec *spec = codec->spec; | ||
1040 | struct alc_jack *jacks = spec->jacks.list; | ||
1041 | |||
1042 | if (jacks) { | ||
1043 | int i; | ||
1044 | for (i = 0; i < spec->jacks.used; i++) { | ||
1045 | if (jacks->nid == nid) { | ||
1046 | unsigned int present; | ||
1047 | present = snd_hda_jack_detect(codec, nid); | ||
1048 | |||
1049 | present = (present) ? jacks->type : 0; | ||
1050 | |||
1051 | snd_jack_report(jacks->jack, present); | ||
1052 | } | ||
1053 | jacks++; | ||
1054 | } | ||
1055 | } | ||
1056 | } | ||
1057 | |||
1058 | static int alc_init_jacks(struct hda_codec *codec) | ||
1059 | { | ||
1060 | struct alc_spec *spec = codec->spec; | ||
1061 | int err; | ||
1062 | unsigned int hp_nid = spec->autocfg.hp_pins[0]; | ||
1063 | unsigned int mic_nid = spec->ext_mic.pin; | ||
1064 | |||
1065 | err = alc_add_jack(codec, hp_nid, SND_JACK_HEADPHONE); | ||
1066 | if (err < 0) | ||
1067 | return err; | ||
1068 | alc_report_jack(codec, hp_nid); | ||
1069 | |||
1070 | err = alc_add_jack(codec, mic_nid, SND_JACK_MICROPHONE); | ||
1071 | if (err < 0) | ||
1072 | return err; | ||
1073 | alc_report_jack(codec, mic_nid); | ||
1074 | |||
1075 | return 0; | ||
1076 | } | ||
1077 | #else | ||
1078 | static inline void alc_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
1079 | { | ||
1080 | } | ||
1081 | |||
1082 | static inline int alc_init_jacks(struct hda_codec *codec) | ||
1083 | { | ||
1084 | return 0; | ||
1085 | } | ||
1086 | #endif | ||
1087 | |||
993 | static void alc_automute_speaker(struct hda_codec *codec, int pinctl) | 1088 | static void alc_automute_speaker(struct hda_codec *codec, int pinctl) |
994 | { | 1089 | { |
995 | struct alc_spec *spec = codec->spec; | 1090 | struct alc_spec *spec = codec->spec; |
@@ -1006,6 +1101,7 @@ static void alc_automute_speaker(struct hda_codec *codec, int pinctl) | |||
1006 | spec->jack_present = 1; | 1101 | spec->jack_present = 1; |
1007 | break; | 1102 | break; |
1008 | } | 1103 | } |
1104 | alc_report_jack(codec, spec->autocfg.hp_pins[i]); | ||
1009 | } | 1105 | } |
1010 | 1106 | ||
1011 | mute = spec->jack_present ? HDA_AMP_MUTE : 0; | 1107 | mute = spec->jack_present ? HDA_AMP_MUTE : 0; |
@@ -1111,6 +1207,7 @@ static void alc_mic_automute(struct hda_codec *codec) | |||
1111 | AC_VERB_SET_CONNECT_SEL, | 1207 | AC_VERB_SET_CONNECT_SEL, |
1112 | alive->mux_idx); | 1208 | alive->mux_idx); |
1113 | } | 1209 | } |
1210 | alc_report_jack(codec, spec->ext_mic.pin); | ||
1114 | 1211 | ||
1115 | /* FIXME: analog mixer */ | 1212 | /* FIXME: analog mixer */ |
1116 | } | 1213 | } |
@@ -14496,6 +14593,7 @@ static void alc269_auto_init(struct hda_codec *codec) | |||
14496 | alc269_auto_init_hp_out(codec); | 14593 | alc269_auto_init_hp_out(codec); |
14497 | alc269_auto_init_analog_input(codec); | 14594 | alc269_auto_init_analog_input(codec); |
14498 | alc_auto_init_digital(codec); | 14595 | alc_auto_init_digital(codec); |
14596 | alc_init_jacks(codec); | ||
14499 | if (spec->unsol_event) | 14597 | if (spec->unsol_event) |
14500 | alc_inithook(codec); | 14598 | alc_inithook(codec); |
14501 | } | 14599 | } |