Loading Documentation/sound/alsa/HD-Audio-Models.txt +1 −0 Original line number Diff line number Diff line Loading @@ -209,6 +209,7 @@ AD1884A / AD1883 / AD1984A / AD1984B laptop laptop with HP jack sensing mobile mobile devices with HP jack sensing thinkpad Lenovo Thinkpad X300 touchsmart HP Touchsmart AD1884 ====== Loading sound/pci/hda/hda_intel.c +1 −0 Original line number Diff line number Diff line Loading @@ -2303,6 +2303,7 @@ static void __devinit check_probe_mask(struct azx *chip, int dev) * white-list for enable_msi */ static struct snd_pci_quirk msi_white_list[] __devinitdata = { SND_PCI_QUIRK(0x103c, 0x30f7, "HP Pavilion dv4t-1300", 1), SND_PCI_QUIRK(0x103c, 0x3607, "HP Compa CQ40", 1), {} }; Loading sound/pci/hda/patch_analog.c +139 −0 Original line number Diff line number Diff line Loading @@ -4031,6 +4031,127 @@ static int ad1984a_thinkpad_init(struct hda_codec *codec) return 0; } /* * HP Touchsmart * port-A (0x11) - front hp-out * port-B (0x14) - unused * port-C (0x15) - unused * port-D (0x12) - rear line out * port-E (0x1c) - front mic-in * port-F (0x16) - Internal speakers * digital-mic (0x17) - Internal mic */ static struct hda_verb ad1984a_touchsmart_verbs[] = { /* DACs; unmute as default */ {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ /* Port-A (HP) mixer - route only from analog mixer */ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, /* Port-A pin */ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, /* Port-A (HP) pin - always unmuted */ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Port-E (int speaker) mixer - route only from analog mixer */ {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03}, /* Port-E pin */ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port-F (int speaker) mixer - route only from analog mixer */ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, /* Port-F pin */ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Analog mixer; mute as default */ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Analog Mix output amp */ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* capture sources */ /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* unsolicited event for pin-sense */ {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, /* allow to touch GPIO1 (for mute control) */ {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ /* internal mic - dmic */ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* set magic COEFs for dmic */ {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7}, {0x01, AC_VERB_SET_PROC_COEF, 0x08}, { } /* end */ }; static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = { HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Switch", .info = snd_hda_mixer_amp_switch_info, .get = snd_hda_mixer_amp_switch_get, .put = ad1884a_mobile_master_sw_put, .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), }, HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT), { } /* end */ }; /* switch to external mic if plugged */ static void ad1984a_touchsmart_automic(struct hda_codec *codec) { if (snd_hda_codec_read(codec, 0x1c, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000) { snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, 0x4); } else { snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, 0x5); } } /* unsolicited event for HP jack sensing */ static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec, unsigned int res) { switch (res >> 26) { case AD1884A_HP_EVENT: ad1884a_hp_automute(codec); break; case AD1884A_MIC_EVENT: ad1984a_touchsmart_automic(codec); break; } } /* initialize jack-sensing, too */ static int ad1984a_touchsmart_init(struct hda_codec *codec) { ad198x_init(codec); ad1884a_hp_automute(codec); ad1984a_touchsmart_automic(codec); return 0; } /* */ Loading @@ -4039,6 +4160,7 @@ enum { AD1884A_LAPTOP, AD1884A_MOBILE, AD1884A_THINKPAD, AD1984A_TOUCHSMART, AD1884A_MODELS }; Loading @@ -4047,6 +4169,7 @@ static const char *ad1884a_models[AD1884A_MODELS] = { [AD1884A_LAPTOP] = "laptop", [AD1884A_MOBILE] = "mobile", [AD1884A_THINKPAD] = "thinkpad", [AD1984A_TOUCHSMART] = "touchsmart", }; static struct snd_pci_quirk ad1884a_cfg_tbl[] = { Loading @@ -4059,6 +4182,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = { SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP), SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE), SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART), {} }; Loading Loading @@ -4142,6 +4266,21 @@ static int patch_ad1884a(struct hda_codec *codec) codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event; codec->patch_ops.init = ad1984a_thinkpad_init; break; case AD1984A_TOUCHSMART: spec->mixers[0] = ad1984a_touchsmart_mixers; spec->init_verbs[0] = ad1984a_touchsmart_verbs; spec->multiout.dig_out_nid = 0; codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event; codec->patch_ops.init = ad1984a_touchsmart_init; /* set the upper-limit for mixer amp to 0dB for avoiding the * possible damage by overloading */ snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, (0x17 << AC_AMPCAP_OFFSET_SHIFT) | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | (1 << AC_AMPCAP_MUTE_SHIFT)); break; } return 0; Loading sound/pci/hda/patch_conexant.c +11 −1 Original line number Diff line number Diff line Loading @@ -682,11 +682,13 @@ static struct hda_input_mux cxt5045_capture_source = { }; static struct hda_input_mux cxt5045_capture_source_benq = { .num_items = 3, .num_items = 5, .items = { { "IntMic", 0x1 }, { "ExtMic", 0x2 }, { "LineIn", 0x3 }, { "CD", 0x4 }, { "Mixer", 0x0 }, } }; Loading Loading @@ -811,11 +813,19 @@ static struct snd_kcontrol_new cxt5045_mixers[] = { }; static struct snd_kcontrol_new cxt5045_benq_mixers[] = { HDA_CODEC_VOLUME("CD Capture Volume", 0x1a, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Capture Switch", 0x1a, 0x04, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x4, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x4, HDA_INPUT), HDA_CODEC_VOLUME("Line In Capture Volume", 0x1a, 0x03, HDA_INPUT), HDA_CODEC_MUTE("Line In Capture Switch", 0x1a, 0x03, HDA_INPUT), HDA_CODEC_VOLUME("Line In Playback Volume", 0x17, 0x3, HDA_INPUT), HDA_CODEC_MUTE("Line In Playback Switch", 0x17, 0x3, HDA_INPUT), HDA_CODEC_VOLUME("Mixer Capture Volume", 0x1a, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Mixer Capture Switch", 0x1a, 0x0, HDA_INPUT), {} }; Loading sound/pci/hda/patch_realtek.c +157 −87 Original line number Diff line number Diff line Loading @@ -12660,7 +12660,7 @@ static struct alc_config_preset alc268_presets[] = { .init_hook = alc268_toshiba_automute, }, [ALC268_ACER] = { .mixers = { alc268_acer_mixer, alc268_capture_nosrc_mixer, .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer, alc268_beep_mixer }, .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, alc268_acer_verbs }, Loading Loading @@ -16852,6 +16852,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K", ALC662_3ST_6ch_DIG), SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB200", ALC663_ASUS_MODE4), SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10), SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", ALC662_3ST_6ch_DIG), Loading Loading @@ -17145,70 +17146,145 @@ static struct alc_config_preset alc662_presets[] = { * BIOS auto configuration */ /* add playback controls from the parsed DAC table */ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, /* convert from MIX nid to DAC */ static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid) { if (nid == 0x0f) return 0x02; else if (nid >= 0x0c && nid <= 0x0e) return nid - 0x0c + 0x02; else return 0; } /* get MIX nid connected to the given pin targeted to DAC */ static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac) { hda_nid_t mix[4]; int i, num; num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix)); for (i = 0; i < num; i++) { if (alc662_mix_to_dac(mix[i]) == dac) return mix[i]; } return 0; } /* look for an empty DAC slot */ static hda_nid_t alc662_look_for_dac(struct hda_codec *codec, hda_nid_t pin) { struct alc_spec *spec = codec->spec; hda_nid_t srcs[5]; int i, j, num; num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs)); if (num < 0) return 0; for (i = 0; i < num; i++) { hda_nid_t nid = alc662_mix_to_dac(srcs[i]); if (!nid) continue; for (j = 0; j < spec->multiout.num_dacs; j++) if (spec->multiout.dac_nids[j] == nid) break; if (j >= spec->multiout.num_dacs) return nid; } return 0; } /* fill in the dac_nids table from the parsed pin configuration */ static int alc662_auto_fill_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { struct alc_spec *spec = codec->spec; int i; hda_nid_t dac; spec->multiout.dac_nids = spec->private_dac_nids; for (i = 0; i < cfg->line_outs; i++) { dac = alc662_look_for_dac(codec, cfg->line_out_pins[i]); if (!dac) continue; spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac; } return 0; } static int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx, hda_nid_t nid, unsigned int chs) { char name[32]; sprintf(name, "%s Playback Volume", pfx); return add_control(spec, ALC_CTL_WIDGET_VOL, name, HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); } static int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx, hda_nid_t nid, unsigned int chs) { char name[32]; sprintf(name, "%s Playback Switch", pfx); return add_control(spec, ALC_CTL_WIDGET_MUTE, name, HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT)); } #define alc662_add_stereo_vol(spec, pfx, nid) \ alc662_add_vol_ctl(spec, pfx, nid, 3) #define alc662_add_stereo_sw(spec, pfx, nid) \ alc662_add_sw_ctl(spec, pfx, nid, 3) /* add playback controls from the parsed DAC table */ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { struct alc_spec *spec = codec->spec; static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; hda_nid_t nid; hda_nid_t nid, mix; int i, err; for (i = 0; i < cfg->line_outs; i++) { if (!spec->multiout.dac_nids[i]) nid = spec->multiout.dac_nids[i]; if (!nid) continue; mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid); if (!mix) continue; nid = alc880_idx_to_dac(i); if (i == 2) { /* Center/LFE */ err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume", HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT)); err = alc662_add_vol_ctl(spec, "Center", nid, 1); if (err < 0) return err; err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume", HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT)); err = alc662_add_vol_ctl(spec, "LFE", nid, 2); if (err < 0) return err; err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Center Playback Switch", HDA_COMPOSE_AMP_VAL(0x0e, 1, 0, HDA_INPUT)); err = alc662_add_sw_ctl(spec, "Center", mix, 1); if (err < 0) return err; err = add_control(spec, ALC_CTL_WIDGET_MUTE, "LFE Playback Switch", HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_INPUT)); err = alc662_add_sw_ctl(spec, "LFE", mix, 2); if (err < 0) return err; } else { const char *pfx; if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { if (!cfg->hp_pins) if (cfg->hp_outs) pfx = "Speaker"; else pfx = "PCM"; } else pfx = chname[i]; sprintf(name, "%s Playback Volume", pfx); err = add_control(spec, ALC_CTL_WIDGET_VOL, name, HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); err = alc662_add_vol_ctl(spec, pfx, nid, 3); if (err < 0) return err; if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) pfx = "Speaker"; sprintf(name, "%s Playback Switch", pfx); err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, HDA_COMPOSE_AMP_VAL(alc880_idx_to_mixer(i), 3, 0, HDA_INPUT)); err = alc662_add_sw_ctl(spec, pfx, mix, 3); if (err < 0) return err; } Loading @@ -17217,54 +17293,38 @@ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, } /* add playback controls for speaker and HP outputs */ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, /* return DAC nid if any new DAC is assigned */ static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, const char *pfx) { hda_nid_t nid; struct alc_spec *spec = codec->spec; hda_nid_t nid, mix; int err; char name[32]; if (!pin) return 0; if (pin == 0x17) { /* ALC663 has a mono output pin on 0x17 */ nid = alc662_look_for_dac(codec, pin); if (!nid) { char name[32]; /* the corresponding DAC is already occupied */ if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)) return 0; /* no way */ /* create a switch only */ sprintf(name, "%s Playback Switch", pfx); err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, HDA_COMPOSE_AMP_VAL(pin, 2, 0, HDA_OUTPUT)); return err; return add_control(spec, ALC_CTL_WIDGET_MUTE, name, HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); } if (alc880_is_fixed_pin(pin)) { nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); /* printk(KERN_DEBUG "DAC nid=%x\n",nid); */ /* specify the DAC as the extra output */ if (!spec->multiout.hp_nid) spec->multiout.hp_nid = nid; else spec->multiout.extra_out_nid[0] = nid; /* control HP volume/switch on the output mixer amp */ nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); sprintf(name, "%s Playback Volume", pfx); err = add_control(spec, ALC_CTL_WIDGET_VOL, name, HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); if (err < 0) return err; sprintf(name, "%s Playback Switch", pfx); err = add_control(spec, ALC_CTL_BIND_MUTE, name, HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); mix = alc662_dac_to_mix(codec, pin, nid); if (!mix) return 0; err = alc662_add_vol_ctl(spec, pfx, nid, 3); if (err < 0) return err; } else if (alc880_is_multi_pin(pin)) { /* set manual connection */ /* we have only a switch on HP-out PIN */ sprintf(name, "%s Playback Switch", pfx); err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); err = alc662_add_sw_ctl(spec, pfx, mix, 3); if (err < 0) return err; } return 0; return nid; } /* create playback/capture controls for input pins */ Loading @@ -17273,30 +17333,35 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, static void alc662_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type, int dac_idx) hda_nid_t dac) { int i, num; hda_nid_t srcs[4]; alc_set_pin_output(codec, nid, pin_type); /* need the manual connection? */ if (alc880_is_multi_pin(nid)) { struct alc_spec *spec = codec->spec; int idx = alc880_multi_pin_idx(nid); snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, AC_VERB_SET_CONNECT_SEL, alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs)); if (num <= 1) return; for (i = 0; i < num; i++) { if (alc662_mix_to_dac(srcs[i]) != dac) continue; snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i); return; } } static void alc662_auto_init_multi_out(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; int pin_type = get_pin_type(spec->autocfg.line_out_type); int i; for (i = 0; i <= HDA_SIDE; i++) { hda_nid_t nid = spec->autocfg.line_out_pins[i]; int pin_type = get_pin_type(spec->autocfg.line_out_type); if (nid) alc662_auto_set_output_and_unmute(codec, nid, pin_type, i); spec->multiout.dac_nids[i]); } } Loading @@ -17306,12 +17371,13 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec) hda_nid_t pin; pin = spec->autocfg.hp_pins[0]; if (pin) /* connect to front */ /* use dac 0 */ alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); if (pin) alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.hp_nid); pin = spec->autocfg.speaker_pins[0]; if (pin) alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, spec->multiout.extra_out_nid[0]); } #define ALC662_PIN_CD_NID ALC880_PIN_CD_NID Loading Loading @@ -17349,21 +17415,25 @@ static int alc662_parse_auto_config(struct hda_codec *codec) if (!spec->autocfg.line_outs) return 0; /* can't find valid BIOS pin config */ err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); err = alc662_auto_fill_dac_nids(codec, &spec->autocfg); if (err < 0) return err; err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg); err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg); if (err < 0) return err; err = alc662_auto_create_extra_out(spec, err = alc662_auto_create_extra_out(codec, spec->autocfg.speaker_pins[0], "Speaker"); if (err < 0) return err; err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], if (err) spec->multiout.extra_out_nid[0] = err; err = alc662_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], "Headphone"); if (err < 0) return err; if (err) spec->multiout.hp_nid = err; err = alc662_auto_create_input_ctls(codec, &spec->autocfg); if (err < 0) return err; Loading
Documentation/sound/alsa/HD-Audio-Models.txt +1 −0 Original line number Diff line number Diff line Loading @@ -209,6 +209,7 @@ AD1884A / AD1883 / AD1984A / AD1984B laptop laptop with HP jack sensing mobile mobile devices with HP jack sensing thinkpad Lenovo Thinkpad X300 touchsmart HP Touchsmart AD1884 ====== Loading
sound/pci/hda/hda_intel.c +1 −0 Original line number Diff line number Diff line Loading @@ -2303,6 +2303,7 @@ static void __devinit check_probe_mask(struct azx *chip, int dev) * white-list for enable_msi */ static struct snd_pci_quirk msi_white_list[] __devinitdata = { SND_PCI_QUIRK(0x103c, 0x30f7, "HP Pavilion dv4t-1300", 1), SND_PCI_QUIRK(0x103c, 0x3607, "HP Compa CQ40", 1), {} }; Loading
sound/pci/hda/patch_analog.c +139 −0 Original line number Diff line number Diff line Loading @@ -4031,6 +4031,127 @@ static int ad1984a_thinkpad_init(struct hda_codec *codec) return 0; } /* * HP Touchsmart * port-A (0x11) - front hp-out * port-B (0x14) - unused * port-C (0x15) - unused * port-D (0x12) - rear line out * port-E (0x1c) - front mic-in * port-F (0x16) - Internal speakers * digital-mic (0x17) - Internal mic */ static struct hda_verb ad1984a_touchsmart_verbs[] = { /* DACs; unmute as default */ {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ /* Port-A (HP) mixer - route only from analog mixer */ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, /* Port-A pin */ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, /* Port-A (HP) pin - always unmuted */ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Port-E (int speaker) mixer - route only from analog mixer */ {0x25, AC_VERB_SET_AMP_GAIN_MUTE, 0x03}, /* Port-E pin */ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port-F (int speaker) mixer - route only from analog mixer */ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, /* Port-F pin */ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Analog mixer; mute as default */ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Analog Mix output amp */ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* capture sources */ /* {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, */ /* set via unsol */ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* unsolicited event for pin-sense */ {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_MIC_EVENT}, /* allow to touch GPIO1 (for mute control) */ {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, /* first muted */ /* internal mic - dmic */ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* set magic COEFs for dmic */ {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7}, {0x01, AC_VERB_SET_PROC_COEF, 0x08}, { } /* end */ }; static struct snd_kcontrol_new ad1984a_touchsmart_mixers[] = { HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), /* HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),*/ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Switch", .info = snd_hda_mixer_amp_switch_info, .get = snd_hda_mixer_amp_switch_get, .put = ad1884a_mobile_master_sw_put, .private_value = HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), }, HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT), { } /* end */ }; /* switch to external mic if plugged */ static void ad1984a_touchsmart_automic(struct hda_codec *codec) { if (snd_hda_codec_read(codec, 0x1c, 0, AC_VERB_GET_PIN_SENSE, 0) & 0x80000000) { snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, 0x4); } else { snd_hda_codec_write(codec, 0x0c, 0, AC_VERB_SET_CONNECT_SEL, 0x5); } } /* unsolicited event for HP jack sensing */ static void ad1984a_touchsmart_unsol_event(struct hda_codec *codec, unsigned int res) { switch (res >> 26) { case AD1884A_HP_EVENT: ad1884a_hp_automute(codec); break; case AD1884A_MIC_EVENT: ad1984a_touchsmart_automic(codec); break; } } /* initialize jack-sensing, too */ static int ad1984a_touchsmart_init(struct hda_codec *codec) { ad198x_init(codec); ad1884a_hp_automute(codec); ad1984a_touchsmart_automic(codec); return 0; } /* */ Loading @@ -4039,6 +4160,7 @@ enum { AD1884A_LAPTOP, AD1884A_MOBILE, AD1884A_THINKPAD, AD1984A_TOUCHSMART, AD1884A_MODELS }; Loading @@ -4047,6 +4169,7 @@ static const char *ad1884a_models[AD1884A_MODELS] = { [AD1884A_LAPTOP] = "laptop", [AD1884A_MOBILE] = "mobile", [AD1884A_THINKPAD] = "thinkpad", [AD1984A_TOUCHSMART] = "touchsmart", }; static struct snd_pci_quirk ad1884a_cfg_tbl[] = { Loading @@ -4059,6 +4182,7 @@ static struct snd_pci_quirk ad1884a_cfg_tbl[] = { SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3600, "HP laptop", AD1884A_LAPTOP), SND_PCI_QUIRK_MASK(0x103c, 0xfff0, 0x7010, "HP laptop", AD1884A_MOBILE), SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), SND_PCI_QUIRK(0x103c, 0x2a82, "Touchsmart", AD1984A_TOUCHSMART), {} }; Loading Loading @@ -4142,6 +4266,21 @@ static int patch_ad1884a(struct hda_codec *codec) codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event; codec->patch_ops.init = ad1984a_thinkpad_init; break; case AD1984A_TOUCHSMART: spec->mixers[0] = ad1984a_touchsmart_mixers; spec->init_verbs[0] = ad1984a_touchsmart_verbs; spec->multiout.dig_out_nid = 0; codec->patch_ops.unsol_event = ad1984a_touchsmart_unsol_event; codec->patch_ops.init = ad1984a_touchsmart_init; /* set the upper-limit for mixer amp to 0dB for avoiding the * possible damage by overloading */ snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT, (0x17 << AC_AMPCAP_OFFSET_SHIFT) | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | (1 << AC_AMPCAP_MUTE_SHIFT)); break; } return 0; Loading
sound/pci/hda/patch_conexant.c +11 −1 Original line number Diff line number Diff line Loading @@ -682,11 +682,13 @@ static struct hda_input_mux cxt5045_capture_source = { }; static struct hda_input_mux cxt5045_capture_source_benq = { .num_items = 3, .num_items = 5, .items = { { "IntMic", 0x1 }, { "ExtMic", 0x2 }, { "LineIn", 0x3 }, { "CD", 0x4 }, { "Mixer", 0x0 }, } }; Loading Loading @@ -811,11 +813,19 @@ static struct snd_kcontrol_new cxt5045_mixers[] = { }; static struct snd_kcontrol_new cxt5045_benq_mixers[] = { HDA_CODEC_VOLUME("CD Capture Volume", 0x1a, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Capture Switch", 0x1a, 0x04, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x4, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x4, HDA_INPUT), HDA_CODEC_VOLUME("Line In Capture Volume", 0x1a, 0x03, HDA_INPUT), HDA_CODEC_MUTE("Line In Capture Switch", 0x1a, 0x03, HDA_INPUT), HDA_CODEC_VOLUME("Line In Playback Volume", 0x17, 0x3, HDA_INPUT), HDA_CODEC_MUTE("Line In Playback Switch", 0x17, 0x3, HDA_INPUT), HDA_CODEC_VOLUME("Mixer Capture Volume", 0x1a, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Mixer Capture Switch", 0x1a, 0x0, HDA_INPUT), {} }; Loading
sound/pci/hda/patch_realtek.c +157 −87 Original line number Diff line number Diff line Loading @@ -12660,7 +12660,7 @@ static struct alc_config_preset alc268_presets[] = { .init_hook = alc268_toshiba_automute, }, [ALC268_ACER] = { .mixers = { alc268_acer_mixer, alc268_capture_nosrc_mixer, .mixers = { alc268_acer_mixer, alc268_capture_alt_mixer, alc268_beep_mixer }, .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, alc268_acer_verbs }, Loading Loading @@ -16852,6 +16852,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K", ALC662_3ST_6ch_DIG), SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB200", ALC663_ASUS_MODE4), SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10), SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", ALC662_3ST_6ch_DIG), Loading Loading @@ -17145,70 +17146,145 @@ static struct alc_config_preset alc662_presets[] = { * BIOS auto configuration */ /* add playback controls from the parsed DAC table */ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, /* convert from MIX nid to DAC */ static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid) { if (nid == 0x0f) return 0x02; else if (nid >= 0x0c && nid <= 0x0e) return nid - 0x0c + 0x02; else return 0; } /* get MIX nid connected to the given pin targeted to DAC */ static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac) { hda_nid_t mix[4]; int i, num; num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix)); for (i = 0; i < num; i++) { if (alc662_mix_to_dac(mix[i]) == dac) return mix[i]; } return 0; } /* look for an empty DAC slot */ static hda_nid_t alc662_look_for_dac(struct hda_codec *codec, hda_nid_t pin) { struct alc_spec *spec = codec->spec; hda_nid_t srcs[5]; int i, j, num; num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs)); if (num < 0) return 0; for (i = 0; i < num; i++) { hda_nid_t nid = alc662_mix_to_dac(srcs[i]); if (!nid) continue; for (j = 0; j < spec->multiout.num_dacs; j++) if (spec->multiout.dac_nids[j] == nid) break; if (j >= spec->multiout.num_dacs) return nid; } return 0; } /* fill in the dac_nids table from the parsed pin configuration */ static int alc662_auto_fill_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { struct alc_spec *spec = codec->spec; int i; hda_nid_t dac; spec->multiout.dac_nids = spec->private_dac_nids; for (i = 0; i < cfg->line_outs; i++) { dac = alc662_look_for_dac(codec, cfg->line_out_pins[i]); if (!dac) continue; spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac; } return 0; } static int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx, hda_nid_t nid, unsigned int chs) { char name[32]; sprintf(name, "%s Playback Volume", pfx); return add_control(spec, ALC_CTL_WIDGET_VOL, name, HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); } static int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx, hda_nid_t nid, unsigned int chs) { char name[32]; sprintf(name, "%s Playback Switch", pfx); return add_control(spec, ALC_CTL_WIDGET_MUTE, name, HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT)); } #define alc662_add_stereo_vol(spec, pfx, nid) \ alc662_add_vol_ctl(spec, pfx, nid, 3) #define alc662_add_stereo_sw(spec, pfx, nid) \ alc662_add_sw_ctl(spec, pfx, nid, 3) /* add playback controls from the parsed DAC table */ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { struct alc_spec *spec = codec->spec; static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; hda_nid_t nid; hda_nid_t nid, mix; int i, err; for (i = 0; i < cfg->line_outs; i++) { if (!spec->multiout.dac_nids[i]) nid = spec->multiout.dac_nids[i]; if (!nid) continue; mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid); if (!mix) continue; nid = alc880_idx_to_dac(i); if (i == 2) { /* Center/LFE */ err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume", HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT)); err = alc662_add_vol_ctl(spec, "Center", nid, 1); if (err < 0) return err; err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume", HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT)); err = alc662_add_vol_ctl(spec, "LFE", nid, 2); if (err < 0) return err; err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Center Playback Switch", HDA_COMPOSE_AMP_VAL(0x0e, 1, 0, HDA_INPUT)); err = alc662_add_sw_ctl(spec, "Center", mix, 1); if (err < 0) return err; err = add_control(spec, ALC_CTL_WIDGET_MUTE, "LFE Playback Switch", HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_INPUT)); err = alc662_add_sw_ctl(spec, "LFE", mix, 2); if (err < 0) return err; } else { const char *pfx; if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { if (!cfg->hp_pins) if (cfg->hp_outs) pfx = "Speaker"; else pfx = "PCM"; } else pfx = chname[i]; sprintf(name, "%s Playback Volume", pfx); err = add_control(spec, ALC_CTL_WIDGET_VOL, name, HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); err = alc662_add_vol_ctl(spec, pfx, nid, 3); if (err < 0) return err; if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) pfx = "Speaker"; sprintf(name, "%s Playback Switch", pfx); err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, HDA_COMPOSE_AMP_VAL(alc880_idx_to_mixer(i), 3, 0, HDA_INPUT)); err = alc662_add_sw_ctl(spec, pfx, mix, 3); if (err < 0) return err; } Loading @@ -17217,54 +17293,38 @@ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, } /* add playback controls for speaker and HP outputs */ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, /* return DAC nid if any new DAC is assigned */ static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, const char *pfx) { hda_nid_t nid; struct alc_spec *spec = codec->spec; hda_nid_t nid, mix; int err; char name[32]; if (!pin) return 0; if (pin == 0x17) { /* ALC663 has a mono output pin on 0x17 */ nid = alc662_look_for_dac(codec, pin); if (!nid) { char name[32]; /* the corresponding DAC is already occupied */ if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)) return 0; /* no way */ /* create a switch only */ sprintf(name, "%s Playback Switch", pfx); err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, HDA_COMPOSE_AMP_VAL(pin, 2, 0, HDA_OUTPUT)); return err; return add_control(spec, ALC_CTL_WIDGET_MUTE, name, HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); } if (alc880_is_fixed_pin(pin)) { nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); /* printk(KERN_DEBUG "DAC nid=%x\n",nid); */ /* specify the DAC as the extra output */ if (!spec->multiout.hp_nid) spec->multiout.hp_nid = nid; else spec->multiout.extra_out_nid[0] = nid; /* control HP volume/switch on the output mixer amp */ nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); sprintf(name, "%s Playback Volume", pfx); err = add_control(spec, ALC_CTL_WIDGET_VOL, name, HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); if (err < 0) return err; sprintf(name, "%s Playback Switch", pfx); err = add_control(spec, ALC_CTL_BIND_MUTE, name, HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT)); mix = alc662_dac_to_mix(codec, pin, nid); if (!mix) return 0; err = alc662_add_vol_ctl(spec, pfx, nid, 3); if (err < 0) return err; } else if (alc880_is_multi_pin(pin)) { /* set manual connection */ /* we have only a switch on HP-out PIN */ sprintf(name, "%s Playback Switch", pfx); err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT)); err = alc662_add_sw_ctl(spec, pfx, mix, 3); if (err < 0) return err; } return 0; return nid; } /* create playback/capture controls for input pins */ Loading @@ -17273,30 +17333,35 @@ static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, static void alc662_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type, int dac_idx) hda_nid_t dac) { int i, num; hda_nid_t srcs[4]; alc_set_pin_output(codec, nid, pin_type); /* need the manual connection? */ if (alc880_is_multi_pin(nid)) { struct alc_spec *spec = codec->spec; int idx = alc880_multi_pin_idx(nid); snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, AC_VERB_SET_CONNECT_SEL, alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs)); if (num <= 1) return; for (i = 0; i < num; i++) { if (alc662_mix_to_dac(srcs[i]) != dac) continue; snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i); return; } } static void alc662_auto_init_multi_out(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; int pin_type = get_pin_type(spec->autocfg.line_out_type); int i; for (i = 0; i <= HDA_SIDE; i++) { hda_nid_t nid = spec->autocfg.line_out_pins[i]; int pin_type = get_pin_type(spec->autocfg.line_out_type); if (nid) alc662_auto_set_output_and_unmute(codec, nid, pin_type, i); spec->multiout.dac_nids[i]); } } Loading @@ -17306,12 +17371,13 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec) hda_nid_t pin; pin = spec->autocfg.hp_pins[0]; if (pin) /* connect to front */ /* use dac 0 */ alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); if (pin) alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.hp_nid); pin = spec->autocfg.speaker_pins[0]; if (pin) alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); alc662_auto_set_output_and_unmute(codec, pin, PIN_OUT, spec->multiout.extra_out_nid[0]); } #define ALC662_PIN_CD_NID ALC880_PIN_CD_NID Loading Loading @@ -17349,21 +17415,25 @@ static int alc662_parse_auto_config(struct hda_codec *codec) if (!spec->autocfg.line_outs) return 0; /* can't find valid BIOS pin config */ err = alc880_auto_fill_dac_nids(spec, &spec->autocfg); err = alc662_auto_fill_dac_nids(codec, &spec->autocfg); if (err < 0) return err; err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg); err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg); if (err < 0) return err; err = alc662_auto_create_extra_out(spec, err = alc662_auto_create_extra_out(codec, spec->autocfg.speaker_pins[0], "Speaker"); if (err < 0) return err; err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], if (err) spec->multiout.extra_out_nid[0] = err; err = alc662_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], "Headphone"); if (err < 0) return err; if (err) spec->multiout.hp_nid = err; err = alc662_auto_create_input_ctls(codec, &spec->autocfg); if (err < 0) return err;