aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2006-09-20 11:10:27 -0400
committerJaroslav Kysela <perex@suse.cz>2006-09-23 04:47:38 -0400
commiteb06ed8f4c2440558ebf465e8baeac6367d90201 (patch)
tree60501d5c4e918f96d26033b95373f4368ca929e2
parent33ef765131bcf82bc5fca3f25d8313fa4df93ce0 (diff)
[ALSA] hda-codec - Support multiple headphone pins
Some machines have multiple headpohne pins (usually on the lpatop and on the docking station) while the current hda-codec driver assumes a single headphone pin. Now it supports multiple hp pins (at least for detection). The sigmatel 92xx code supports this new multiple hp pins. It detects all hp pins for auto-muting, too. Also, the driver checks speaker pins in addition. In some cases, all line-out, speaker and hp-pins coexist. Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
-rw-r--r--sound/pci/hda/hda_codec.c23
-rw-r--r--sound/pci/hda/hda_local.h3
-rw-r--r--sound/pci/hda/patch_analog.c4
-rw-r--r--sound/pci/hda/patch_realtek.c18
-rw-r--r--sound/pci/hda/patch_sigmatel.c202
5 files changed, 164 insertions, 86 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 8b2c080c85ae..07360996caaa 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -2012,7 +2012,7 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
2012 * in the order of front, rear, CLFE, side, ... 2012 * in the order of front, rear, CLFE, side, ...
2013 * 2013 *
2014 * If more extra outputs (speaker and headphone) are found, the pins are 2014 * If more extra outputs (speaker and headphone) are found, the pins are
2015 * assisnged to hp_pin and speaker_pins[], respectively. If no line-out jack 2015 * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack
2016 * is detected, one of speaker of HP pins is assigned as the primary 2016 * is detected, one of speaker of HP pins is assigned as the primary
2017 * output, i.e. to line_out_pins[0]. So, line_outs is always positive 2017 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
2018 * if any analog output exists. 2018 * if any analog output exists.
@@ -2074,7 +2074,10 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c
2074 cfg->speaker_outs++; 2074 cfg->speaker_outs++;
2075 break; 2075 break;
2076 case AC_JACK_HP_OUT: 2076 case AC_JACK_HP_OUT:
2077 cfg->hp_pin = nid; 2077 if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins))
2078 continue;
2079 cfg->hp_pins[cfg->hp_outs] = nid;
2080 cfg->hp_outs++;
2078 break; 2081 break;
2079 case AC_JACK_MIC_IN: 2082 case AC_JACK_MIC_IN:
2080 if (loc == AC_JACK_LOC_FRONT) 2083 if (loc == AC_JACK_LOC_FRONT)
@@ -2147,8 +2150,10 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c
2147 cfg->speaker_outs, cfg->speaker_pins[0], 2150 cfg->speaker_outs, cfg->speaker_pins[0],
2148 cfg->speaker_pins[1], cfg->speaker_pins[2], 2151 cfg->speaker_pins[1], cfg->speaker_pins[2],
2149 cfg->speaker_pins[3], cfg->speaker_pins[4]); 2152 cfg->speaker_pins[3], cfg->speaker_pins[4]);
2150 snd_printd(" hp=0x%x, dig_out=0x%x, din_in=0x%x\n", 2153 snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
2151 cfg->hp_pin, cfg->dig_out_pin, cfg->dig_in_pin); 2154 cfg->hp_outs, cfg->hp_pins[0],
2155 cfg->hp_pins[1], cfg->hp_pins[2],
2156 cfg->hp_pins[3], cfg->hp_pins[4]);
2152 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," 2157 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
2153 " cd=0x%x, aux=0x%x\n", 2158 " cd=0x%x, aux=0x%x\n",
2154 cfg->input_pins[AUTO_PIN_MIC], 2159 cfg->input_pins[AUTO_PIN_MIC],
@@ -2169,10 +2174,12 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c
2169 sizeof(cfg->speaker_pins)); 2174 sizeof(cfg->speaker_pins));
2170 cfg->speaker_outs = 0; 2175 cfg->speaker_outs = 0;
2171 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); 2176 memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
2172 } else if (cfg->hp_pin) { 2177 } else if (cfg->hp_outs) {
2173 cfg->line_outs = 1; 2178 cfg->line_outs = cfg->hp_outs;
2174 cfg->line_out_pins[0] = cfg->hp_pin; 2179 memcpy(cfg->line_out_pins, cfg->hp_pins,
2175 cfg->hp_pin = 0; 2180 sizeof(cfg->hp_pins));
2181 cfg->hp_outs = 0;
2182 memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
2176 } 2183 }
2177 } 2184 }
2178 2185
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index ff24266fe353..f9416c36396e 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -229,7 +229,8 @@ struct auto_pin_cfg {
229 hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */ 229 hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */
230 int speaker_outs; 230 int speaker_outs;
231 hda_nid_t speaker_pins[5]; 231 hda_nid_t speaker_pins[5];
232 hda_nid_t hp_pin; 232 int hp_outs;
233 hda_nid_t hp_pins[5];
233 hda_nid_t input_pins[AUTO_PIN_LAST]; 234 hda_nid_t input_pins[AUTO_PIN_LAST];
234 hda_nid_t dig_out_pin; 235 hda_nid_t dig_out_pin;
235 hda_nid_t dig_in_pin; 236 hda_nid_t dig_in_pin;
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 71abc2aa61a6..511df07fa2a3 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -2471,7 +2471,7 @@ static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2471 pin = spec->autocfg.speaker_pins[0]; 2471 pin = spec->autocfg.speaker_pins[0];
2472 if (pin) /* connect to front */ 2472 if (pin) /* connect to front */
2473 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); 2473 ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2474 pin = spec->autocfg.hp_pin; 2474 pin = spec->autocfg.hp_pins[0];
2475 if (pin) /* connect to front */ 2475 if (pin) /* connect to front */
2476 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 2476 ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2477} 2477}
@@ -2523,7 +2523,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
2523 (err = ad1988_auto_create_extra_out(codec, 2523 (err = ad1988_auto_create_extra_out(codec,
2524 spec->autocfg.speaker_pins[0], 2524 spec->autocfg.speaker_pins[0],
2525 "Speaker")) < 0 || 2525 "Speaker")) < 0 ||
2526 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pin, 2526 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
2527 "Headphone")) < 0 || 2527 "Headphone")) < 0 ||
2528 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) 2528 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2529 return err; 2529 return err;
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index ba9e050e2012..d08d2e399c8f 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2753,7 +2753,7 @@ static void alc880_auto_init_extra_out(struct hda_codec *codec)
2753 pin = spec->autocfg.speaker_pins[0]; 2753 pin = spec->autocfg.speaker_pins[0];
2754 if (pin) /* connect to front */ 2754 if (pin) /* connect to front */
2755 alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); 2755 alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
2756 pin = spec->autocfg.hp_pin; 2756 pin = spec->autocfg.hp_pins[0];
2757 if (pin) /* connect to front */ 2757 if (pin) /* connect to front */
2758 alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 2758 alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
2759} 2759}
@@ -2794,7 +2794,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
2794 (err = alc880_auto_create_extra_out(spec, 2794 (err = alc880_auto_create_extra_out(spec,
2795 spec->autocfg.speaker_pins[0], 2795 spec->autocfg.speaker_pins[0],
2796 "Speaker")) < 0 || 2796 "Speaker")) < 0 ||
2797 (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pin, 2797 (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
2798 "Headphone")) < 0 || 2798 "Headphone")) < 0 ||
2799 (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) 2799 (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2800 return err; 2800 return err;
@@ -3736,7 +3736,7 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
3736 return err; 3736 return err;
3737 } 3737 }
3738 3738
3739 nid = cfg->hp_pin; 3739 nid = cfg->hp_pins[0];
3740 if (nid) { 3740 if (nid) {
3741 err = alc260_add_playback_controls(spec, nid, "Headphone"); 3741 err = alc260_add_playback_controls(spec, nid, "Headphone");
3742 if (err < 0) 3742 if (err < 0)
@@ -3806,7 +3806,7 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec)
3806 if (nid) 3806 if (nid)
3807 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); 3807 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
3808 3808
3809 nid = spec->autocfg.hp_pin; 3809 nid = spec->autocfg.hp_pins[0];
3810 if (nid) 3810 if (nid)
3811 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); 3811 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
3812} 3812}
@@ -4526,7 +4526,7 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec)
4526 struct alc_spec *spec = codec->spec; 4526 struct alc_spec *spec = codec->spec;
4527 hda_nid_t pin; 4527 hda_nid_t pin;
4528 4528
4529 pin = spec->autocfg.hp_pin; 4529 pin = spec->autocfg.hp_pins[0];
4530 if (pin) /* connect to front */ 4530 if (pin) /* connect to front */
4531 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */ 4531 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */
4532} 4532}
@@ -5207,7 +5207,7 @@ static void alc883_auto_init_hp_out(struct hda_codec *codec)
5207 struct alc_spec *spec = codec->spec; 5207 struct alc_spec *spec = codec->spec;
5208 hda_nid_t pin; 5208 hda_nid_t pin;
5209 5209
5210 pin = spec->autocfg.hp_pin; 5210 pin = spec->autocfg.hp_pins[0];
5211 if (pin) /* connect to front */ 5211 if (pin) /* connect to front */
5212 /* use dac 0 */ 5212 /* use dac 0 */
5213 alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 5213 alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
@@ -5630,7 +5630,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct
5630 return err; 5630 return err;
5631 } 5631 }
5632 } 5632 }
5633 nid = cfg->hp_pin; 5633 nid = cfg->hp_pins[0];
5634 if (nid) { 5634 if (nid) {
5635 /* spec->multiout.hp_nid = 2; */ 5635 /* spec->multiout.hp_nid = 2; */
5636 if (nid == 0x16) { 5636 if (nid == 0x16) {
@@ -6630,7 +6630,7 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec)
6630 struct alc_spec *spec = codec->spec; 6630 struct alc_spec *spec = codec->spec;
6631 hda_nid_t pin; 6631 hda_nid_t pin;
6632 6632
6633 pin = spec->autocfg.hp_pin; 6633 pin = spec->autocfg.hp_pins[0];
6634 if (pin) /* connect to front */ 6634 if (pin) /* connect to front */
6635 alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]); 6635 alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]);
6636} 6636}
@@ -6665,7 +6665,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
6665 6665
6666 if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || 6666 if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
6667 (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || 6667 (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
6668 (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 || 6668 (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0])) < 0 ||
6669 (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) 6669 (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
6670 return err; 6670 return err;
6671 6671
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index bcbbe111ab95..7cc064265204 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -1011,11 +1011,29 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec,
1011 return 0; 1011 return 0;
1012} 1012}
1013 1013
1014/* create volume control/switch for the given prefx type */
1015static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs)
1016{
1017 char name[32];
1018 int err;
1019
1020 sprintf(name, "%s Playback Volume", pfx);
1021 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name,
1022 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
1023 if (err < 0)
1024 return err;
1025 sprintf(name, "%s Playback Switch", pfx);
1026 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name,
1027 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
1028 if (err < 0)
1029 return err;
1030 return 0;
1031}
1032
1014/* add playback controls from the parsed DAC table */ 1033/* add playback controls from the parsed DAC table */
1015static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, 1034static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec,
1016 const struct auto_pin_cfg *cfg) 1035 const struct auto_pin_cfg *cfg)
1017{ 1036{
1018 char name[32];
1019 static const char *chname[4] = { 1037 static const char *chname[4] = {
1020 "Front", "Surround", NULL /*CLFE*/, "Side" 1038 "Front", "Surround", NULL /*CLFE*/, "Side"
1021 }; 1039 };
@@ -1030,26 +1048,15 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec,
1030 1048
1031 if (i == 2) { 1049 if (i == 2) {
1032 /* Center/LFE */ 1050 /* Center/LFE */
1033 if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "Center Playback Volume", 1051 err = create_controls(spec, "Center", nid, 1);
1034 HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) 1052 if (err < 0)
1035 return err; 1053 return err;
1036 if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "LFE Playback Volume", 1054 err = create_controls(spec, "LFE", nid, 2);
1037 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) 1055 if (err < 0)
1038 return err;
1039 if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "Center Playback Switch",
1040 HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
1041 return err;
1042 if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "LFE Playback Switch",
1043 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
1044 return err; 1056 return err;
1045 } else { 1057 } else {
1046 sprintf(name, "%s Playback Volume", chname[i]); 1058 err = create_controls(spec, chname[i], nid, 3);
1047 if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, 1059 if (err < 0)
1048 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
1049 return err;
1050 sprintf(name, "%s Playback Switch", chname[i]);
1051 if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name,
1052 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
1053 return err; 1060 return err;
1054 } 1061 }
1055 } 1062 }
@@ -1065,39 +1072,85 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec,
1065 return 0; 1072 return 0;
1066} 1073}
1067 1074
1068/* add playback controls for HP output */ 1075static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
1069static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin_cfg *cfg)
1070{ 1076{
1071 struct sigmatel_spec *spec = codec->spec; 1077 int i;
1072 hda_nid_t pin = cfg->hp_pin;
1073 hda_nid_t nid;
1074 int i, err;
1075 unsigned int wid_caps;
1076 1078
1077 if (! pin) 1079 for (i = 0; i < spec->multiout.num_dacs; i++) {
1078 return 0; 1080 if (spec->multiout.dac_nids[i] == nid)
1081 return 1;
1082 }
1083 if (spec->multiout.hp_nid == nid)
1084 return 1;
1085 return 0;
1086}
1079 1087
1080 wid_caps = get_wcaps(codec, pin); 1088static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid)
1081 if (wid_caps & AC_WCAP_UNSOL_CAP) 1089{
1082 spec->hp_detect = 1; 1090 if (!spec->multiout.hp_nid)
1091 spec->multiout.hp_nid = nid;
1092 else if (spec->multiout.num_dacs > 4) {
1093 printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid);
1094 return 1;
1095 } else {
1096 spec->multiout.dac_nids[spec->multiout.num_dacs] = nid;
1097 spec->multiout.num_dacs++;
1098 }
1099 return 0;
1100}
1083 1101
1084 nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; 1102/* add playback controls for Speaker and HP outputs */
1085 for (i = 0; i < cfg->line_outs; i++) { 1103static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
1086 if (! spec->multiout.dac_nids[i]) 1104 struct auto_pin_cfg *cfg)
1105{
1106 struct sigmatel_spec *spec = codec->spec;
1107 hda_nid_t nid;
1108 int i, old_num_dacs, err;
1109
1110 old_num_dacs = spec->multiout.num_dacs;
1111 for (i = 0; i < cfg->hp_outs; i++) {
1112 unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]);
1113 if (wid_caps & AC_WCAP_UNSOL_CAP)
1114 spec->hp_detect = 1;
1115 nid = snd_hda_codec_read(codec, cfg->hp_pins[i], 0,
1116 AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
1117 if (check_in_dac_nids(spec, nid))
1118 nid = 0;
1119 if (! nid)
1087 continue; 1120 continue;
1088 if (spec->multiout.dac_nids[i] == nid) 1121 add_spec_dacs(spec, nid);
1089 return 0; 1122 }
1123 for (i = 0; i < cfg->speaker_outs; i++) {
1124 nid = snd_hda_codec_read(codec, cfg->speaker_pins[0], 0,
1125 AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
1126 if (check_in_dac_nids(spec, nid))
1127 nid = 0;
1128 if (check_in_dac_nids(spec, nid))
1129 nid = 0;
1130 if (! nid)
1131 continue;
1132 add_spec_dacs(spec, nid);
1090 } 1133 }
1091 1134
1092 spec->multiout.hp_nid = nid; 1135 for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) {
1093 1136 static const char *pfxs[] = {
1094 /* control HP volume/switch on the output mixer amp */ 1137 "Speaker", "External Speaker", "Speaker2",
1095 if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "Headphone Playback Volume", 1138 };
1096 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) 1139 err = create_controls(spec, pfxs[i - old_num_dacs],
1097 return err; 1140 spec->multiout.dac_nids[i], 3);
1098 if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "Headphone Playback Switch", 1141 if (err < 0)
1099 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) 1142 return err;
1100 return err; 1143 }
1144 if (spec->multiout.hp_nid) {
1145 const char *pfx;
1146 if (old_num_dacs == spec->multiout.num_dacs)
1147 pfx = "Master";
1148 else
1149 pfx = "Headphone";
1150 err = create_controls(spec, pfx, spec->multiout.hp_nid, 3);
1151 if (err < 0)
1152 return err;
1153 }
1101 1154
1102 return 0; 1155 return 0;
1103} 1156}
@@ -1160,11 +1213,20 @@ static void stac92xx_auto_init_multi_out(struct hda_codec *codec)
1160static void stac92xx_auto_init_hp_out(struct hda_codec *codec) 1213static void stac92xx_auto_init_hp_out(struct hda_codec *codec)
1161{ 1214{
1162 struct sigmatel_spec *spec = codec->spec; 1215 struct sigmatel_spec *spec = codec->spec;
1163 hda_nid_t pin; 1216 int i;
1164 1217
1165 pin = spec->autocfg.hp_pin; 1218 for (i = 0; i < spec->autocfg.hp_outs; i++) {
1166 if (pin) /* connect to front */ 1219 hda_nid_t pin;
1167 stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); 1220 pin = spec->autocfg.hp_pins[i];
1221 if (pin) /* connect to front */
1222 stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
1223 }
1224 for (i = 0; i < spec->autocfg.speaker_outs; i++) {
1225 hda_nid_t pin;
1226 pin = spec->autocfg.speaker_pins[i];
1227 if (pin) /* connect to front */
1228 stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN);
1229 }
1168} 1230}
1169 1231
1170static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) 1232static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in)
@@ -1210,7 +1272,7 @@ static int stac9200_auto_create_hp_ctls(struct hda_codec *codec,
1210 struct auto_pin_cfg *cfg) 1272 struct auto_pin_cfg *cfg)
1211{ 1273{
1212 struct sigmatel_spec *spec = codec->spec; 1274 struct sigmatel_spec *spec = codec->spec;
1213 hda_nid_t pin = cfg->hp_pin; 1275 hda_nid_t pin = cfg->hp_pins[0];
1214 unsigned int wid_caps; 1276 unsigned int wid_caps;
1215 1277
1216 if (! pin) 1278 if (! pin)
@@ -1266,16 +1328,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec,
1266 } 1328 }
1267 1329
1268 if (lfe_pin) { 1330 if (lfe_pin) {
1269 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, 1331 err = create_controls(spec, "LFE", lfe_pin, 1);
1270 "LFE Playback Volume",
1271 HDA_COMPOSE_AMP_VAL(lfe_pin, 1, 0,
1272 HDA_OUTPUT));
1273 if (err < 0)
1274 return err;
1275 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE,
1276 "LFE Playback Switch",
1277 HDA_COMPOSE_AMP_VAL(lfe_pin, 1, 0,
1278 HDA_OUTPUT));
1279 if (err < 0) 1332 if (err < 0)
1280 return err; 1333 return err;
1281 } 1334 }
@@ -1363,9 +1416,11 @@ static int stac92xx_init(struct hda_codec *codec)
1363 /* set up pins */ 1416 /* set up pins */
1364 if (spec->hp_detect) { 1417 if (spec->hp_detect) {
1365 /* Enable unsolicited responses on the HP widget */ 1418 /* Enable unsolicited responses on the HP widget */
1366 snd_hda_codec_write(codec, cfg->hp_pin, 0, 1419 for (i = 0; i < cfg->hp_outs; i++)
1367 AC_VERB_SET_UNSOLICITED_ENABLE, 1420 if (get_wcaps(codec, cfg->hp_pins[i]) & AC_WCAP_UNSOL_CAP)
1368 STAC_UNSOL_ENABLE); 1421 snd_hda_codec_write(codec, cfg->hp_pins[i], 0,
1422 AC_VERB_SET_UNSOLICITED_ENABLE,
1423 STAC_UNSOL_ENABLE);
1369 /* fake event to set up pins */ 1424 /* fake event to set up pins */
1370 codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); 1425 codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
1371 /* enable the headphones by default. If/when unsol_event detection works, this will be ignored */ 1426 /* enable the headphones by default. If/when unsol_event detection works, this will be ignored */
@@ -1447,21 +1502,36 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
1447 if ((res >> 26) != STAC_HP_EVENT) 1502 if ((res >> 26) != STAC_HP_EVENT)
1448 return; 1503 return;
1449 1504
1450 presence = snd_hda_codec_read(codec, cfg->hp_pin, 0, 1505 presence = 0;
1451 AC_VERB_GET_PIN_SENSE, 0x00) >> 31; 1506 for (i = 0; i < cfg->hp_outs; i++) {
1507 int p = snd_hda_codec_read(codec, cfg->hp_pins[i], 0,
1508 AC_VERB_GET_PIN_SENSE, 0x00);
1509 if (p & (1 << 31))
1510 presence++;
1511 }
1452 1512
1453 if (presence) { 1513 if (presence) {
1454 /* disable lineouts, enable hp */ 1514 /* disable lineouts, enable hp */
1455 for (i = 0; i < cfg->line_outs; i++) 1515 for (i = 0; i < cfg->line_outs; i++)
1456 stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], 1516 stac92xx_reset_pinctl(codec, cfg->line_out_pins[i],
1457 AC_PINCTL_OUT_EN); 1517 AC_PINCTL_OUT_EN);
1458 stac92xx_set_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); 1518 for (i = 0; i < cfg->speaker_outs; i++)
1519 stac92xx_reset_pinctl(codec, cfg->speaker_pins[i],
1520 AC_PINCTL_OUT_EN);
1521 for (i = 0; i < cfg->hp_outs; i++)
1522 stac92xx_set_pinctl(codec, cfg->hp_pins[i],
1523 AC_PINCTL_OUT_EN);
1459 } else { 1524 } else {
1460 /* enable lineouts, disable hp */ 1525 /* enable lineouts, disable hp */
1461 for (i = 0; i < cfg->line_outs; i++) 1526 for (i = 0; i < cfg->line_outs; i++)
1462 stac92xx_set_pinctl(codec, cfg->line_out_pins[i], 1527 stac92xx_set_pinctl(codec, cfg->line_out_pins[i],
1463 AC_PINCTL_OUT_EN); 1528 AC_PINCTL_OUT_EN);
1464 stac92xx_reset_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); 1529 for (i = 0; i < cfg->speaker_outs; i++)
1530 stac92xx_set_pinctl(codec, cfg->speaker_pins[i],
1531 AC_PINCTL_OUT_EN);
1532 for (i = 0; i < cfg->hp_outs; i++)
1533 stac92xx_reset_pinctl(codec, cfg->hp_pins[i],
1534 AC_PINCTL_OUT_EN);
1465 } 1535 }
1466} 1536}
1467 1537