aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_realtek.c
diff options
context:
space:
mode:
authorKailang Yang <kailang@realtek.com>2010-09-14 17:22:00 -0400
committerTakashi Iwai <tiwai@suse.de>2010-09-14 17:22:00 -0400
commit9ad0e496519d99eb2c34f01e41500a775122c744 (patch)
tree736ab4a2b4e4645187998e43896546e52c3f34df /sound/pci/hda/patch_realtek.c
parent4a4d4a6985dd37a3c96534027f054be796bf95f6 (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.c98
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
286struct 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
287struct alc_customize_define { 294struct 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
1004static 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
1011static 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
1037static 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
1058static 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
1078static inline void alc_report_jack(struct hda_codec *codec, hda_nid_t nid)
1079{
1080}
1081
1082static inline int alc_init_jacks(struct hda_codec *codec)
1083{
1084 return 0;
1085}
1086#endif
1087
993static void alc_automute_speaker(struct hda_codec *codec, int pinctl) 1088static 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}