aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/sound/alsa/HD-Audio-Models.txt1
-rw-r--r--sound/pci/hda/patch_analog.c139
-rw-r--r--sound/pci/hda/patch_realtek.c244
-rw-r--r--sound/pci/hda/patch_sigmatel.c20
4 files changed, 311 insertions, 93 deletions
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index f1708b79f963..75fddb40f416 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -209,6 +209,7 @@ AD1884A / AD1883 / AD1984A / AD1984B
209 laptop laptop with HP jack sensing 209 laptop laptop with HP jack sensing
210 mobile mobile devices with HP jack sensing 210 mobile mobile devices with HP jack sensing
211 thinkpad Lenovo Thinkpad X300 211 thinkpad Lenovo Thinkpad X300
212 touchsmart HP Touchsmart
212 213
213AD1884 214AD1884
214====== 215======
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 215e72a87113..2d603f6aba63 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -4032,6 +4032,127 @@ static int ad1984a_thinkpad_init(struct hda_codec *codec)
4032} 4032}
4033 4033
4034/* 4034/*
4035 * HP Touchsmart
4036 * port-A (0x11) - front hp-out
4037 * port-B (0x14) - unused
4038 * port-C (0x15) - unused
4039 * port-D (0x12) - rear line out
4040 * port-E (0x1c) - front mic-in
4041 * port-F (0x16) - Internal speakers
4042 * digital-mic (0x17) - Internal mic
4043 */
4044
4045static struct hda_verb ad1984a_touchsmart_verbs[] = {
4046 /* DACs; unmute as default */
4047 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4048 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
4049 /* Port-A (HP) mixer - route only from analog mixer */
4050 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4051 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4052 /* Port-A pin */
4053 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4054 /* Port-A (HP) pin - always unmuted */
4055 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4056 /* Port-E (int speaker) mixer - route only from analog mixer */
4057 {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03},
4058 /* Port-E pin */
4059 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4060 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4061 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4062 /* Port-F (int speaker) mixer - route only from analog mixer */
4063 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4064 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4065 /* Port-F pin */
4066 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4067 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4068 /* Analog mixer; mute as default */
4069 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4070 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4071 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4072 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4073 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4074 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
4075 /* Analog Mix output amp */
4076 {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4077 /* capture sources */
4078 /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */
4079 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4080 {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
4081 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4082 /* unsolicited event for pin-sense */
4083 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
4084 {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT},
4085 /* allow to touch GPIO1 (for mute control) */
4086 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
4087 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
4088 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */
4089 /* internal mic - dmic */
4090 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
4091 /* set magic COEFs for dmic */
4092 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
4093 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
4094 { } /* end */
4095};
4096
4097static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = {
4098 HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
4099/* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/
4100 {
4101 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4102 .name = "Master Playback Switch",
4103 .info = snd_hda_mixer_amp_switch_info,
4104 .get = snd_hda_mixer_amp_switch_get,
4105 .put = ad1884a_mobile_master_sw_put,
4106 .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
4107 },
4108 HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
4109 HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
4110 HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
4111 HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
4112 HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT),
4113 HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT),
4114 { } /* end */
4115};
4116
4117/* switch to external mic if plugged */
4118static void ad1984a_touchsmart_automic(struct hda_codec *codec)
4119{
4120 if (snd_hda_codec_read(codec, 0x1c, 0,
4121 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000) {
4122 snd_hda_codec_write(codec, 0x0c, 0,
4123 AC_VERB_SET_CONNECT_SEL, 0x4);
4124 } else {
4125 snd_hda_codec_write(codec, 0x0c, 0,
4126 AC_VERB_SET_CONNECT_SEL, 0x5);
4127 }
4128}
4129
4130
4131/* unsolicited event for HP jack sensing */
4132static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec,
4133 unsigned int res)
4134{
4135 switch (res >> 26) {
4136 case AD1884A_HP_EVENT:
4137 ad1884a_hp_automute(codec);
4138 break;
4139 case AD1884A_MIC_EVENT:
4140 ad1984a_touchsmart_automic(codec);
4141 break;
4142 }
4143}
4144
4145/* initialize jack-sensing, too */
4146static int ad1984a_touchsmart_init(struct hda_codec *codec)
4147{
4148 ad198x_init(codec);
4149 ad1884a_hp_automute(codec);
4150 ad1984a_touchsmart_automic(codec);
4151 return 0;
4152}
4153
4154
4155/*
4035 */ 4156 */
4036 4157
4037enum { 4158enum {
@@ -4039,6 +4160,7 @@ enum {
4039 AD1884A_LAPTOP, 4160 AD1884A_LAPTOP,
4040 AD1884A_MOBILE, 4161 AD1884A_MOBILE,
4041 AD1884A_THINKPAD, 4162 AD1884A_THINKPAD,
4163 AD1984A_TOUCHSMART,
4042 AD1884A_MODELS 4164 AD1884A_MODELS
4043}; 4165};
4044 4166
@@ -4047,6 +4169,7 @@ static const char *ad1884a_models[AD1884A_MODELS] = {
4047 [AD1884A_LAPTOP] = "laptop", 4169 [AD1884A_LAPTOP] = "laptop",
4048 [AD1884A_MOBILE] = "mobile", 4170 [AD1884A_MOBILE] = "mobile",
4049 [AD1884A_THINKPAD] = "thinkpad", 4171 [AD1884A_THINKPAD] = "thinkpad",
4172 [AD1984A_TOUCHSMART] = "touchsmart",
4050}; 4173};
4051 4174
4052static struct snd_pci_quirk ad1884a_cfg_tbl[] = { 4175static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
@@ -4059,6 +4182,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
4059 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP), 4182 SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP),
4060 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE), 4183 SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE),
4061 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), 4184 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
4185 SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART),
4062 {} 4186 {}
4063}; 4187};
4064 4188
@@ -4142,6 +4266,21 @@ static int patch_ad1884a(struct hda_codec *codec)
4142 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event; 4266 codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
4143 codec->patch_ops.init = ad1984a_thinkpad_init; 4267 codec->patch_ops.init = ad1984a_thinkpad_init;
4144 break; 4268 break;
4269 case AD1984A_TOUCHSMART:
4270 spec->mixers[0] = ad1984a_touchsmart_mixers;
4271 spec->init_verbs[0] = ad1984a_touchsmart_verbs;
4272 spec->multiout.dig_out_nid = 0;
4273 codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event;
4274 codec->patch_ops.init = ad1984a_touchsmart_init;
4275 /* set the upper-limit for mixer amp to 0dB for avoiding the
4276 * possible damage by overloading
4277 */
4278 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
4279 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
4280 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4281 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4282 (1 << AC_AMPCAP_MUTE_SHIFT));
4283 break;
4145 } 4284 }
4146 4285
4147 return 0; 4286 return 0;
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 129605819560..7810d3dcad83 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -12660,7 +12660,7 @@ static struct alc_config_preset alc268_presets[] = {
12660 .init_hook = alc268_toshiba_automute, 12660 .init_hook = alc268_toshiba_automute,
12661 }, 12661 },
12662 [ALC268_ACER] = { 12662 [ALC268_ACER] = {
12663 .mixers = { alc268_acer_mixer, alc268_capture_nosrc_mixer, 12663 .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
12664 alc268_beep_mixer }, 12664 alc268_beep_mixer },
12665 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, 12665 .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
12666 alc268_acer_verbs }, 12666 alc268_acer_verbs },
@@ -16852,6 +16852,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
16852 SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), 16852 SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
16853 SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K", 16853 SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K",
16854 ALC662_3ST_6ch_DIG), 16854 ALC662_3ST_6ch_DIG),
16855 SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB200", ALC663_ASUS_MODE4),
16855 SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10), 16856 SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
16856 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", 16857 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
16857 ALC662_3ST_6ch_DIG), 16858 ALC662_3ST_6ch_DIG),
@@ -17145,70 +17146,145 @@ static struct alc_config_preset alc662_presets[] = {
17145 * BIOS auto configuration 17146 * BIOS auto configuration
17146 */ 17147 */
17147 17148
17149/* convert from MIX nid to DAC */
17150static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid)
17151{
17152 if (nid == 0x0f)
17153 return 0x02;
17154 else if (nid >= 0x0c && nid <= 0x0e)
17155 return nid - 0x0c + 0x02;
17156 else
17157 return 0;
17158}
17159
17160/* get MIX nid connected to the given pin targeted to DAC */
17161static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
17162 hda_nid_t dac)
17163{
17164 hda_nid_t mix[4];
17165 int i, num;
17166
17167 num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
17168 for (i = 0; i < num; i++) {
17169 if (alc662_mix_to_dac(mix[i]) == dac)
17170 return mix[i];
17171 }
17172 return 0;
17173}
17174
17175/* look for an empty DAC slot */
17176static hda_nid_t alc662_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
17177{
17178 struct alc_spec *spec = codec->spec;
17179 hda_nid_t srcs[5];
17180 int i, j, num;
17181
17182 num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
17183 if (num < 0)
17184 return 0;
17185 for (i = 0; i < num; i++) {
17186 hda_nid_t nid = alc662_mix_to_dac(srcs[i]);
17187 if (!nid)
17188 continue;
17189 for (j = 0; j < spec->multiout.num_dacs; j++)
17190 if (spec->multiout.dac_nids[j] == nid)
17191 break;
17192 if (j >= spec->multiout.num_dacs)
17193 return nid;
17194 }
17195 return 0;
17196}
17197
17198/* fill in the dac_nids table from the parsed pin configuration */
17199static int alc662_auto_fill_dac_nids(struct hda_codec *codec,
17200 const struct auto_pin_cfg *cfg)
17201{
17202 struct alc_spec *spec = codec->spec;
17203 int i;
17204 hda_nid_t dac;
17205
17206 spec->multiout.dac_nids = spec->private_dac_nids;
17207 for (i = 0; i < cfg->line_outs; i++) {
17208 dac = alc662_look_for_dac(codec, cfg->line_out_pins[i]);
17209 if (!dac)
17210 continue;
17211 spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
17212 }
17213 return 0;
17214}
17215
17216static int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx,
17217 hda_nid_t nid, unsigned int chs)
17218{
17219 char name[32];
17220 sprintf(name, "%s Playback Volume", pfx);
17221 return add_control(spec, ALC_CTL_WIDGET_VOL, name,
17222 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
17223}
17224
17225static int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx,
17226 hda_nid_t nid, unsigned int chs)
17227{
17228 char name[32];
17229 sprintf(name, "%s Playback Switch", pfx);
17230 return add_control(spec, ALC_CTL_WIDGET_MUTE, name,
17231 HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT));
17232}
17233
17234#define alc662_add_stereo_vol(spec, pfx, nid) \
17235 alc662_add_vol_ctl(spec, pfx, nid, 3)
17236#define alc662_add_stereo_sw(spec, pfx, nid) \
17237 alc662_add_sw_ctl(spec, pfx, nid, 3)
17238
17148/* add playback controls from the parsed DAC table */ 17239/* add playback controls from the parsed DAC table */
17149static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, 17240static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
17150 const struct auto_pin_cfg *cfg) 17241 const struct auto_pin_cfg *cfg)
17151{ 17242{
17152 char name[32]; 17243 struct alc_spec *spec = codec->spec;
17153 static const char *chname[4] = { 17244 static const char *chname[4] = {
17154 "Front", "Surround", NULL /*CLFE*/, "Side" 17245 "Front", "Surround", NULL /*CLFE*/, "Side"
17155 }; 17246 };
17156 hda_nid_t nid; 17247 hda_nid_t nid, mix;
17157 int i, err; 17248 int i, err;
17158 17249
17159 for (i = 0; i < cfg->line_outs; i++) { 17250 for (i = 0; i < cfg->line_outs; i++) {
17160 if (!spec->multiout.dac_nids[i]) 17251 nid = spec->multiout.dac_nids[i];
17252 if (!nid)
17253 continue;
17254 mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid);
17255 if (!mix)
17161 continue; 17256 continue;
17162 nid = alc880_idx_to_dac(i);
17163 if (i == 2) { 17257 if (i == 2) {
17164 /* Center/LFE */ 17258 /* Center/LFE */
17165 err = add_control(spec, ALC_CTL_WIDGET_VOL, 17259 err = alc662_add_vol_ctl(spec, "Center", nid, 1);
17166 "Center Playback Volume",
17167 HDA_COMPOSE_AMP_VAL(nid, 1, 0,
17168 HDA_OUTPUT));
17169 if (err < 0) 17260 if (err < 0)
17170 return err; 17261 return err;
17171 err = add_control(spec, ALC_CTL_WIDGET_VOL, 17262 err = alc662_add_vol_ctl(spec, "LFE", nid, 2);
17172 "LFE Playback Volume",
17173 HDA_COMPOSE_AMP_VAL(nid, 2, 0,
17174 HDA_OUTPUT));
17175 if (err < 0) 17263 if (err < 0)
17176 return err; 17264 return err;
17177 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 17265 err = alc662_add_sw_ctl(spec, "Center", mix, 1);
17178 "Center Playback Switch",
17179 HDA_COMPOSE_AMP_VAL(0x0e, 1, 0,
17180 HDA_INPUT));
17181 if (err < 0) 17266 if (err < 0)
17182 return err; 17267 return err;
17183 err = add_control(spec, ALC_CTL_WIDGET_MUTE, 17268 err = alc662_add_sw_ctl(spec, "LFE", mix, 2);
17184 "LFE Playback Switch",
17185 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0,
17186 HDA_INPUT));
17187 if (err < 0) 17269 if (err < 0)
17188 return err; 17270 return err;
17189 } else { 17271 } else {
17190 const char *pfx; 17272 const char *pfx;
17191 if (cfg->line_outs == 1 && 17273 if (cfg->line_outs == 1 &&
17192 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { 17274 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
17193 if (!cfg->hp_pins) 17275 if (cfg->hp_outs)
17194 pfx = "Speaker"; 17276 pfx = "Speaker";
17195 else 17277 else
17196 pfx = "PCM"; 17278 pfx = "PCM";
17197 } else 17279 } else
17198 pfx = chname[i]; 17280 pfx = chname[i];
17199 sprintf(name, "%s Playback Volume", pfx); 17281 err = alc662_add_vol_ctl(spec, pfx, nid, 3);
17200 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
17201 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
17202 HDA_OUTPUT));
17203 if (err < 0) 17282 if (err < 0)
17204 return err; 17283 return err;
17205 if (cfg->line_outs == 1 && 17284 if (cfg->line_outs == 1 &&
17206 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) 17285 cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
17207 pfx = "Speaker"; 17286 pfx = "Speaker";
17208 sprintf(name, "%s Playback Switch", pfx); 17287 err = alc662_add_sw_ctl(spec, pfx, mix, 3);
17209 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
17210 HDA_COMPOSE_AMP_VAL(alc880_idx_to_mixer(i),
17211 3, 0, HDA_INPUT));
17212 if (err < 0) 17288 if (err < 0)
17213 return err; 17289 return err;
17214 } 17290 }
@@ -17217,54 +17293,38 @@ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec,
17217} 17293}
17218 17294
17219/* add playback controls for speaker and HP outputs */ 17295/* add playback controls for speaker and HP outputs */
17220static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, 17296/* return DAC nid if any new DAC is assigned */
17297static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
17221 const char *pfx) 17298 const char *pfx)
17222{ 17299{
17223 hda_nid_t nid; 17300 struct alc_spec *spec = codec->spec;
17301 hda_nid_t nid, mix;
17224 int err; 17302 int err;
17225 char name[32];
17226 17303
17227 if (!pin) 17304 if (!pin)
17228 return 0; 17305 return 0;
17229 17306 nid = alc662_look_for_dac(codec, pin);
17230 if (pin == 0x17) { 17307 if (!nid) {
17231 /* ALC663 has a mono output pin on 0x17 */ 17308 char name[32];
17309 /* the corresponding DAC is already occupied */
17310 if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
17311 return 0; /* no way */
17312 /* create a switch only */
17232 sprintf(name, "%s Playback Switch", pfx); 17313 sprintf(name, "%s Playback Switch", pfx);
17233 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 17314 return add_control(spec, ALC_CTL_WIDGET_MUTE, name,
17234 HDA_COMPOSE_AMP_VAL(pin, 2, 0, HDA_OUTPUT)); 17315 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
17235 return err;
17236 } 17316 }
17237 17317
17238 if (alc880_is_fixed_pin(pin)) { 17318 mix = alc662_dac_to_mix(codec, pin, nid);
17239 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 17319 if (!mix)
17240 /* printk(KERN_DEBUG "DAC nid=%x\n",nid); */ 17320 return 0;
17241 /* specify the DAC as the extra output */ 17321 err = alc662_add_vol_ctl(spec, pfx, nid, 3);
17242 if (!spec->multiout.hp_nid) 17322 if (err < 0)
17243 spec->multiout.hp_nid = nid; 17323 return err;
17244 else 17324 err = alc662_add_sw_ctl(spec, pfx, mix, 3);
17245 spec->multiout.extra_out_nid[0] = nid; 17325 if (err < 0)
17246 /* control HP volume/switch on the output mixer amp */ 17326 return err;
17247 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); 17327 return nid;
17248 sprintf(name, "%s Playback Volume", pfx);
17249 err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
17250 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
17251 if (err < 0)
17252 return err;
17253 sprintf(name, "%s Playback Switch", pfx);
17254 err = add_control(spec, ALC_CTL_BIND_MUTE, name,
17255 HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
17256 if (err < 0)
17257 return err;
17258 } else if (alc880_is_multi_pin(pin)) {
17259 /* set manual connection */
17260 /* we have only a switch on HP-out PIN */
17261 sprintf(name, "%s Playback Switch", pfx);
17262 err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
17263 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
17264 if (err < 0)
17265 return err;
17266 }
17267 return 0;
17268} 17328}
17269 17329
17270/* create playback/capture controls for input pins */ 17330/* create playback/capture controls for input pins */
@@ -17273,30 +17333,35 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
17273 17333
17274static void alc662_auto_set_output_and_unmute(struct hda_codec *codec, 17334static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
17275 hda_nid_t nid, int pin_type, 17335 hda_nid_t nid, int pin_type,
17276 int dac_idx) 17336 hda_nid_t dac)
17277{ 17337{
17338 int i, num;
17339 hda_nid_t srcs[4];
17340
17278 alc_set_pin_output(codec, nid, pin_type); 17341 alc_set_pin_output(codec, nid, pin_type);
17279 /* need the manual connection? */ 17342 /* need the manual connection? */
17280 if (alc880_is_multi_pin(nid)) { 17343 num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
17281 struct alc_spec *spec = codec->spec; 17344 if (num <= 1)
17282 int idx = alc880_multi_pin_idx(nid); 17345 return;
17283 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, 17346 for (i = 0; i < num; i++) {
17284 AC_VERB_SET_CONNECT_SEL, 17347 if (alc662_mix_to_dac(srcs[i]) != dac)
17285 alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); 17348 continue;
17349 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
17350 return;
17286 } 17351 }
17287} 17352}
17288 17353
17289static void alc662_auto_init_multi_out(struct hda_codec *codec) 17354static void alc662_auto_init_multi_out(struct hda_codec *codec)
17290{ 17355{
17291 struct alc_spec *spec = codec->spec; 17356 struct alc_spec *spec = codec->spec;
17357 int pin_type = get_pin_type(spec->autocfg.line_out_type);
17292 int i; 17358 int i;
17293 17359
17294 for (i = 0; i <= HDA_SIDE; i++) { 17360 for (i = 0; i <= HDA_SIDE; i++) {
17295 hda_nid_t nid = spec->autocfg.line_out_pins[i]; 17361 hda_nid_t nid = spec->autocfg.line_out_pins[i];
17296 int pin_type = get_pin_type(spec->autocfg.line_out_type);
17297 if (nid) 17362 if (nid)
17298 alc662_auto_set_output_and_unmute(codec, nid, pin_type, 17363 alc662_auto_set_output_and_unmute(codec, nid, pin_type,
17299 i); 17364 spec->multiout.dac_nids[i]);
17300 } 17365 }
17301} 17366}
17302 17367
@@ -17306,12 +17371,13 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec)
17306 hda_nid_t pin; 17371 hda_nid_t pin;
17307 17372
17308 pin = spec->autocfg.hp_pins[0]; 17373 pin = spec->autocfg.hp_pins[0];
17309 if (pin) /* connect to front */ 17374 if (pin)
17310 /* use dac 0 */ 17375 alc662_auto_set_output_and_unmute(codec, pin, PIN_HP,
17311 alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); 17376 spec->multiout.hp_nid);
17312 pin = spec->autocfg.speaker_pins[0]; 17377 pin = spec->autocfg.speaker_pins[0];
17313 if (pin) 17378 if (pin)
17314 alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); 17379 alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT,
17380 spec->multiout.extra_out_nid[0]);
17315} 17381}
17316 17382
17317#define ALC662_PIN_CD_NID ALC880_PIN_CD_NID 17383#define ALC662_PIN_CD_NID ALC880_PIN_CD_NID
@@ -17349,21 +17415,25 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
17349 if (!spec->autocfg.line_outs) 17415 if (!spec->autocfg.line_outs)
17350 return 0; /* can't find valid BIOS pin config */ 17416 return 0; /* can't find valid BIOS pin config */
17351 17417
17352 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); 17418 err = alc662_auto_fill_dac_nids(codec, &spec->autocfg);
17353 if (err < 0) 17419 if (err < 0)
17354 return err; 17420 return err;
17355 err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg); 17421 err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg);
17356 if (err < 0) 17422 if (err < 0)
17357 return err; 17423 return err;
17358 err = alc662_auto_create_extra_out(spec, 17424 err = alc662_auto_create_extra_out(codec,
17359 spec->autocfg.speaker_pins[0], 17425 spec->autocfg.speaker_pins[0],
17360 "Speaker"); 17426 "Speaker");
17361 if (err < 0) 17427 if (err < 0)
17362 return err; 17428 return err;
17363 err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], 17429 if (err)
17430 spec->multiout.extra_out_nid[0] = err;
17431 err = alc662_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
17364 "Headphone"); 17432 "Headphone");
17365 if (err < 0) 17433 if (err < 0)
17366 return err; 17434 return err;
17435 if (err)
17436 spec->multiout.hp_nid = err;
17367 err = alc662_auto_create_input_ctls(codec, &spec->autocfg); 17437 err = alc662_auto_create_input_ctls(codec, &spec->autocfg);
17368 if (err < 0) 17438 if (err < 0)
17369 return err; 17439 return err;
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 826137ec3002..a9b26828a651 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -182,8 +182,8 @@ struct sigmatel_jack {
182 182
183struct sigmatel_mic_route { 183struct sigmatel_mic_route {
184 hda_nid_t pin; 184 hda_nid_t pin;
185 unsigned char mux_idx; 185 signed char mux_idx;
186 unsigned char dmux_idx; 186 signed char dmux_idx;
187}; 187};
188 188
189struct sigmatel_spec { 189struct sigmatel_spec {
@@ -3469,18 +3469,26 @@ static int set_mic_route(struct hda_codec *codec,
3469 break; 3469 break;
3470 if (i <= AUTO_PIN_FRONT_MIC) { 3470 if (i <= AUTO_PIN_FRONT_MIC) {
3471 /* analog pin */ 3471 /* analog pin */
3472 mic->dmux_idx = 0;
3473 i = get_connection_index(codec, spec->mux_nids[0], pin); 3472 i = get_connection_index(codec, spec->mux_nids[0], pin);
3474 if (i < 0) 3473 if (i < 0)
3475 return -1; 3474 return -1;
3476 mic->mux_idx = i; 3475 mic->mux_idx = i;
3476 mic->dmux_idx = -1;
3477 if (spec->dmux_nids)
3478 mic->dmux_idx = get_connection_index(codec,
3479 spec->dmux_nids[0],
3480 spec->mux_nids[0]);
3477 } else if (spec->dmux_nids) { 3481 } else if (spec->dmux_nids) {
3478 /* digital pin */ 3482 /* digital pin */
3479 mic->mux_idx = 0;
3480 i = get_connection_index(codec, spec->dmux_nids[0], pin); 3483 i = get_connection_index(codec, spec->dmux_nids[0], pin);
3481 if (i < 0) 3484 if (i < 0)
3482 return -1; 3485 return -1;
3483 mic->dmux_idx = i; 3486 mic->dmux_idx = i;
3487 mic->mux_idx = -1;
3488 if (spec->mux_nids)
3489 mic->mux_idx = get_connection_index(codec,
3490 spec->mux_nids[0],
3491 spec->dmux_nids[0]);
3484 } 3492 }
3485 return 0; 3493 return 0;
3486} 3494}
@@ -4557,11 +4565,11 @@ static void stac92xx_mic_detect(struct hda_codec *codec)
4557 mic = &spec->ext_mic; 4565 mic = &spec->ext_mic;
4558 else 4566 else
4559 mic = &spec->int_mic; 4567 mic = &spec->int_mic;
4560 if (mic->dmux_idx) 4568 if (mic->dmux_idx >= 0)
4561 snd_hda_codec_write_cache(codec, spec->dmux_nids[0], 0, 4569 snd_hda_codec_write_cache(codec, spec->dmux_nids[0], 0,
4562 AC_VERB_SET_CONNECT_SEL, 4570 AC_VERB_SET_CONNECT_SEL,
4563 mic->dmux_idx); 4571 mic->dmux_idx);
4564 else 4572 if (mic->mux_idx >= 0)
4565 snd_hda_codec_write_cache(codec, spec->mux_nids[0], 0, 4573 snd_hda_codec_write_cache(codec, spec->mux_nids[0], 0,
4566 AC_VERB_SET_CONNECT_SEL, 4574 AC_VERB_SET_CONNECT_SEL,
4567 mic->mux_idx); 4575 mic->mux_idx);