diff --git a/sound/pci/hda/alc662_asus_nx5_quirks.c b/sound/pci/hda/alc662_asus_nx5_quirks.c new file mode 100644 index 0000000..02adac8 --- /dev/null +++ b/sound/pci/hda/alc662_asus_nx5_quirks.c @@ -0,0 +1,106 @@ + +static const struct hda_verb alc662_asus_nx5_ch2_init[] = { + { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, + { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, + { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x21, AC_VERB_SET_CONNECT_SEL, 0x00 }, /* HP as HP */ + { 0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP }, + { } /* end */ +}; + +static const struct hda_verb alc662_asus_nx5_ch3_init[] = { + { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x21, AC_VERB_SET_CONNECT_SEL, 0x00 }, /* HP as HP */ + { 0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP }, + { } /* end */ +}; + +static const struct hda_verb alc662_asus_nx5_ch5_init[] = { + { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, + { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 }, + { 0x21, AC_VERB_SET_CONNECT_SEL, 0x01 }, /* HP as line-out for rear */ + { 0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + { } /* end */ +}; + +static const struct hda_channel_mode alc662_nx5modes[] = { + { 2, alc662_asus_nx5_ch2_init }, + { 3, alc662_asus_nx5_ch3_init }, + /* We have 5 real channels, but 5 makes alsa go nuts */ + { 6, alc662_asus_nx5_ch5_init } +}; + + +static const struct snd_kcontrol_new nx5_base_mixer[] = { + /* output mixer control */ + HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), + + /*Input mixer control */ + HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT), + HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT), + { } /* end */ +}; + + +static const struct snd_kcontrol_new nx5_mixer_extra[] = { + ALC_PIN_MODE("HP jack mode", 0x21, ALC_PIN_DIR_INOUT), + ALC_PIN_MODE("Mic jack mode", 0x18, ALC_PIN_DIR_IN), + /* FIXME: Not sure if this is OK. Is there any other better way + to add automute control? */ + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Auto-Mute Mode", + .info = alc_automute_mode_info, + .get = alc_automute_mode_get, + .put = alc_automute_mode_put, + }, + { } /* end */ +}; + +static const struct hda_verb alc663_nx5_init_verbs[] = { + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0 }, /* Subwoofer initially off */ + /* This should theoreticall enabled sensing, but it does not */ + /* TODO: Figure out how subwoofer is sensed */ + {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_FRONT_EVENT }, + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, + {} +}; + + +static void alc663_mode_asus_nx5_setup(struct hda_codec *codec) +{ + + struct alc_spec *spec = codec->spec; + spec->autocfg.hp_pins[0] = 0x21; + spec->autocfg.speaker_pins[0] = 0x14; + spec->autocfg.speaker_pins[1] = 0x16; + spec->autocfg.line_out_pins[1]=0x21; + spec->automute = 1; + spec->automute_mode = ALC_AUTOMUTE_PIN; + spec->ext_mic_pin = 0x18; + spec->int_mic_pin = 0x19; + spec->auto_mic = 1; + /* TODO: Enable subwoofer autosensing to switch 2ch<-->3ch */ + /* Regular sensing doesn't work for it */ + /* TODO: Things that need testing: */ + /* Automic, spdif, line-in, hp as mic-in*/ + /* TODO: Remove this before sending upstream, after cleaning things */ + printk("alc663: N75SF Advanced ALSA preset by Necromant (beta)\n"); +} + diff --git a/sound/pci/hda/alc662_quirks.c b/sound/pci/hda/alc662_quirks.c index e69a6ea..93fa802 100644 --- a/sound/pci/hda/alc662_quirks.c +++ b/sound/pci/hda/alc662_quirks.c @@ -26,6 +26,7 @@ enum { ALC663_ASUS_MODE6, ALC663_ASUS_MODE7, ALC663_ASUS_MODE8, + ALC663_ASUS_NX5, ALC272_DELL, ALC272_DELL_ZM1, ALC272_SAMSUNG_NC10, @@ -172,6 +173,9 @@ static const struct hda_channel_mode alc662_5stack_modes[2] = { { 6, alc662_sixstack_ch8_init }, }; + +#include "alc662_asus_nx5_quirks.c" + /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b */ @@ -984,6 +988,7 @@ static const char * const alc662_models[ALC662_MODEL_LAST] = { [ALC663_ASUS_MODE6] = "asus-mode6", [ALC663_ASUS_MODE7] = "asus-mode7", [ALC663_ASUS_MODE8] = "asus-mode8", + [ALC663_ASUS_NX5] = "asus-nx5sf", [ALC272_DELL] = "dell", [ALC272_DELL_ZM1] = "dell-zm1", [ALC272_SAMSUNG_NC10] = "samsung-nc10", @@ -1053,6 +1058,8 @@ static const struct snd_pci_quirk alc662_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG), SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701), SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20), + SND_PCI_QUIRK(0x1043, 0x1b93, "ASUS N75SF", ALC663_ASUS_NX5), + SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC663_ASUS_NX5), SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K", ALC662_3ST_6ch_DIG), @@ -1355,6 +1362,26 @@ static const struct alc_config_preset alc662_presets[] = { .setup = alc663_mode8_setup, .init_hook = alc_inithook, }, + [ALC663_ASUS_NX5] = { + .mixers = { nx5_base_mixer, alc662_chmode_mixer, nx5_mixer_extra }, + .cap_mixer = alc662_auto_capture_mixer, + .init_verbs = { alc662_init_verbs, + alc662_eapd_init_verbs, + alc663_g50v_init_verbs, + alc663_nx5_init_verbs, + alc662_asus_nx5_ch2_init }, /* default to 2ch mode */ + .num_dacs = ARRAY_SIZE(alc662_dac_nids), + .hp_nid = 0x21, + .dac_nids = alc662_dac_nids, + .dig_out_nid = ALC662_DIGOUT_NID, + .num_channel_mode = ARRAY_SIZE(alc662_nx5modes), + .channel_mode = alc662_nx5modes, + .const_channel_count = 6, + .input_mux = &alc663_capture_source, + .unsol_event = alc_sku_unsol_event, + .setup = alc663_mode_asus_nx5_setup, + .init_hook = alc_inithook, + }, [ALC272_DELL] = { .mixers = { alc663_m51va_mixer }, .cap_mixer = alc272_auto_capture_mixer,