diff options
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 331 |
1 files changed, 330 insertions, 1 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f1ce7d7f5aa3..630e66743e8e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -18612,7 +18612,7 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
18612 | 18612 | ||
18613 | add_verb(spec, alc662_init_verbs); | 18613 | add_verb(spec, alc662_init_verbs); |
18614 | if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 || | 18614 | if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 || |
18615 | codec->vendor_id == 0x10ec0665) | 18615 | codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670) |
18616 | add_verb(spec, alc663_init_verbs); | 18616 | add_verb(spec, alc663_init_verbs); |
18617 | 18617 | ||
18618 | if (codec->vendor_id == 0x10ec0272) | 18618 | if (codec->vendor_id == 0x10ec0272) |
@@ -18756,6 +18756,334 @@ static int patch_alc888(struct hda_codec *codec) | |||
18756 | } | 18756 | } |
18757 | 18757 | ||
18758 | /* | 18758 | /* |
18759 | * ALC680 support | ||
18760 | */ | ||
18761 | #define ALC680_DIGOUT_NID ALC880_DIGOUT_NID | ||
18762 | #define alc680_modes alc260_modes | ||
18763 | |||
18764 | static hda_nid_t alc680_dac_nids[3] = { | ||
18765 | /* Lout1, Lout2, hp */ | ||
18766 | 0x02, 0x03, 0x04 | ||
18767 | }; | ||
18768 | |||
18769 | static hda_nid_t alc680_adc_nids[3] = { | ||
18770 | /* ADC0-2 */ | ||
18771 | /* DMIC, MIC, Line-in*/ | ||
18772 | 0x07, 0x08, 0x09 | ||
18773 | }; | ||
18774 | |||
18775 | static struct snd_kcontrol_new alc680_base_mixer[] = { | ||
18776 | /* output mixer control */ | ||
18777 | HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), | ||
18778 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
18779 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT), | ||
18780 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT), | ||
18781 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
18782 | { } | ||
18783 | }; | ||
18784 | |||
18785 | static struct snd_kcontrol_new alc680_capture_mixer[] = { | ||
18786 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | ||
18787 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | ||
18788 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | ||
18789 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | ||
18790 | HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), | ||
18791 | HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), | ||
18792 | { } /* end */ | ||
18793 | }; | ||
18794 | |||
18795 | /* | ||
18796 | * generic initialization of ADC, input mixers and output mixers | ||
18797 | */ | ||
18798 | static struct hda_verb alc680_init_verbs[] = { | ||
18799 | /* Unmute DAC0-1 and set vol = 0 */ | ||
18800 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
18801 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
18802 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
18803 | |||
18804 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
18805 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
18806 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, | ||
18807 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
18808 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
18809 | |||
18810 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
18811 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
18812 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
18813 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
18814 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
18815 | { } | ||
18816 | }; | ||
18817 | |||
18818 | /* create input playback/capture controls for the given pin */ | ||
18819 | static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid, | ||
18820 | const char *ctlname, int idx) | ||
18821 | { | ||
18822 | hda_nid_t dac; | ||
18823 | int err; | ||
18824 | |||
18825 | switch (nid) { | ||
18826 | case 0x14: | ||
18827 | dac = 0x02; | ||
18828 | break; | ||
18829 | case 0x15: | ||
18830 | dac = 0x03; | ||
18831 | break; | ||
18832 | case 0x16: | ||
18833 | dac = 0x04; | ||
18834 | break; | ||
18835 | default: | ||
18836 | return 0; | ||
18837 | } | ||
18838 | if (spec->multiout.dac_nids[0] != dac && | ||
18839 | spec->multiout.dac_nids[1] != dac) { | ||
18840 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, | ||
18841 | HDA_COMPOSE_AMP_VAL(dac, 3, idx, | ||
18842 | HDA_OUTPUT)); | ||
18843 | if (err < 0) | ||
18844 | return err; | ||
18845 | |||
18846 | err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, | ||
18847 | HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT)); | ||
18848 | |||
18849 | if (err < 0) | ||
18850 | return err; | ||
18851 | spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac; | ||
18852 | } | ||
18853 | |||
18854 | return 0; | ||
18855 | } | ||
18856 | |||
18857 | /* add playback controls from the parsed DAC table */ | ||
18858 | static int alc680_auto_create_multi_out_ctls(struct alc_spec *spec, | ||
18859 | const struct auto_pin_cfg *cfg) | ||
18860 | { | ||
18861 | hda_nid_t nid; | ||
18862 | int err; | ||
18863 | |||
18864 | spec->multiout.dac_nids = spec->private_dac_nids; | ||
18865 | |||
18866 | nid = cfg->line_out_pins[0]; | ||
18867 | if (nid) { | ||
18868 | const char *name; | ||
18869 | if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | ||
18870 | name = "Speaker"; | ||
18871 | else | ||
18872 | name = "Front"; | ||
18873 | err = alc680_new_analog_output(spec, nid, name, 0); | ||
18874 | if (err < 0) | ||
18875 | return err; | ||
18876 | } | ||
18877 | |||
18878 | nid = cfg->speaker_pins[0]; | ||
18879 | if (nid) { | ||
18880 | err = alc680_new_analog_output(spec, nid, "Speaker", 0); | ||
18881 | if (err < 0) | ||
18882 | return err; | ||
18883 | } | ||
18884 | nid = cfg->hp_pins[0]; | ||
18885 | if (nid) { | ||
18886 | err = alc680_new_analog_output(spec, nid, "Headphone", 0); | ||
18887 | if (err < 0) | ||
18888 | return err; | ||
18889 | } | ||
18890 | |||
18891 | return 0; | ||
18892 | } | ||
18893 | |||
18894 | static void alc680_auto_set_output_and_unmute(struct hda_codec *codec, | ||
18895 | hda_nid_t nid, int pin_type) | ||
18896 | { | ||
18897 | alc_set_pin_output(codec, nid, pin_type); | ||
18898 | } | ||
18899 | |||
18900 | static void alc680_auto_init_multi_out(struct hda_codec *codec) | ||
18901 | { | ||
18902 | struct alc_spec *spec = codec->spec; | ||
18903 | hda_nid_t nid = spec->autocfg.line_out_pins[0]; | ||
18904 | if (nid) { | ||
18905 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | ||
18906 | alc680_auto_set_output_and_unmute(codec, nid, pin_type); | ||
18907 | } | ||
18908 | } | ||
18909 | |||
18910 | static void alc680_auto_init_hp_out(struct hda_codec *codec) | ||
18911 | { | ||
18912 | struct alc_spec *spec = codec->spec; | ||
18913 | hda_nid_t pin; | ||
18914 | |||
18915 | pin = spec->autocfg.hp_pins[0]; | ||
18916 | if (pin) | ||
18917 | alc680_auto_set_output_and_unmute(codec, pin, PIN_HP); | ||
18918 | pin = spec->autocfg.speaker_pins[0]; | ||
18919 | if (pin) | ||
18920 | alc680_auto_set_output_and_unmute(codec, pin, PIN_OUT); | ||
18921 | } | ||
18922 | |||
18923 | /* pcm configuration: identical with ALC880 */ | ||
18924 | #define alc680_pcm_analog_playback alc880_pcm_analog_playback | ||
18925 | #define alc680_pcm_analog_capture alc880_pcm_analog_capture | ||
18926 | #define alc680_pcm_analog_alt_capture alc880_pcm_analog_alt_capture | ||
18927 | #define alc680_pcm_digital_playback alc880_pcm_digital_playback | ||
18928 | |||
18929 | static struct hda_input_mux alc680_capture_source = { | ||
18930 | .num_items = 1, | ||
18931 | .items = { | ||
18932 | { "Mic", 0x0 }, | ||
18933 | }, | ||
18934 | }; | ||
18935 | |||
18936 | /* | ||
18937 | * BIOS auto configuration | ||
18938 | */ | ||
18939 | static int alc680_parse_auto_config(struct hda_codec *codec) | ||
18940 | { | ||
18941 | struct alc_spec *spec = codec->spec; | ||
18942 | int err; | ||
18943 | static hda_nid_t alc680_ignore[] = { 0 }; | ||
18944 | |||
18945 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | ||
18946 | alc680_ignore); | ||
18947 | if (err < 0) | ||
18948 | return err; | ||
18949 | if (!spec->autocfg.line_outs) { | ||
18950 | if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) { | ||
18951 | spec->multiout.max_channels = 2; | ||
18952 | spec->no_analog = 1; | ||
18953 | goto dig_only; | ||
18954 | } | ||
18955 | return 0; /* can't find valid BIOS pin config */ | ||
18956 | } | ||
18957 | err = alc680_auto_create_multi_out_ctls(spec, &spec->autocfg); | ||
18958 | if (err < 0) | ||
18959 | return err; | ||
18960 | |||
18961 | spec->multiout.max_channels = 2; | ||
18962 | |||
18963 | dig_only: | ||
18964 | /* digital only support output */ | ||
18965 | if (spec->autocfg.dig_outs) { | ||
18966 | spec->multiout.dig_out_nid = ALC680_DIGOUT_NID; | ||
18967 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; | ||
18968 | } | ||
18969 | if (spec->kctls.list) | ||
18970 | add_mixer(spec, spec->kctls.list); | ||
18971 | |||
18972 | add_verb(spec, alc680_init_verbs); | ||
18973 | spec->num_mux_defs = 1; | ||
18974 | spec->input_mux = &alc680_capture_source; | ||
18975 | |||
18976 | err = alc_auto_add_mic_boost(codec); | ||
18977 | if (err < 0) | ||
18978 | return err; | ||
18979 | |||
18980 | return 1; | ||
18981 | } | ||
18982 | |||
18983 | #define alc680_auto_init_analog_input alc882_auto_init_analog_input | ||
18984 | |||
18985 | /* init callback for auto-configuration model -- overriding the default init */ | ||
18986 | static void alc680_auto_init(struct hda_codec *codec) | ||
18987 | { | ||
18988 | struct alc_spec *spec = codec->spec; | ||
18989 | alc680_auto_init_multi_out(codec); | ||
18990 | alc680_auto_init_hp_out(codec); | ||
18991 | alc680_auto_init_analog_input(codec); | ||
18992 | if (spec->unsol_event) | ||
18993 | alc_inithook(codec); | ||
18994 | } | ||
18995 | |||
18996 | /* | ||
18997 | * configuration and preset | ||
18998 | */ | ||
18999 | static const char *alc680_models[ALC680_MODEL_LAST] = { | ||
19000 | [ALC680_BASE] = "alc680_base", | ||
19001 | }; | ||
19002 | |||
19003 | static struct snd_pci_quirk alc680_cfg_tbl[] = { | ||
19004 | SND_PCI_QUIRK(0x1043, 0x12f3, "ASUS NX90", ALC680_BASE), | ||
19005 | {} | ||
19006 | }; | ||
19007 | |||
19008 | static struct alc_config_preset alc680_presets[] = { | ||
19009 | [ALC680_BASE] = { | ||
19010 | .mixers = { alc680_base_mixer }, | ||
19011 | .cap_mixer = alc680_capture_mixer, | ||
19012 | .init_verbs = { alc680_init_verbs }, | ||
19013 | .num_dacs = ARRAY_SIZE(alc680_dac_nids), | ||
19014 | .dac_nids = alc680_dac_nids, | ||
19015 | .num_adc_nids = ARRAY_SIZE(alc680_adc_nids), | ||
19016 | .adc_nids = alc680_adc_nids, | ||
19017 | .hp_nid = 0x04, | ||
19018 | .dig_out_nid = ALC680_DIGOUT_NID, | ||
19019 | .num_channel_mode = ARRAY_SIZE(alc680_modes), | ||
19020 | .channel_mode = alc680_modes, | ||
19021 | .input_mux = &alc680_capture_source, | ||
19022 | }, | ||
19023 | }; | ||
19024 | |||
19025 | static int patch_alc680(struct hda_codec *codec) | ||
19026 | { | ||
19027 | struct alc_spec *spec; | ||
19028 | int board_config; | ||
19029 | int err; | ||
19030 | |||
19031 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
19032 | if (spec == NULL) | ||
19033 | return -ENOMEM; | ||
19034 | |||
19035 | codec->spec = spec; | ||
19036 | |||
19037 | board_config = snd_hda_check_board_config(codec, ALC680_MODEL_LAST, | ||
19038 | alc680_models, | ||
19039 | alc680_cfg_tbl); | ||
19040 | |||
19041 | if (board_config < 0 || board_config >= ALC680_MODEL_LAST) { | ||
19042 | printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", | ||
19043 | codec->chip_name); | ||
19044 | board_config = ALC680_AUTO; | ||
19045 | } | ||
19046 | |||
19047 | if (board_config == ALC680_AUTO) { | ||
19048 | /* automatic parse from the BIOS config */ | ||
19049 | err = alc680_parse_auto_config(codec); | ||
19050 | if (err < 0) { | ||
19051 | alc_free(codec); | ||
19052 | return err; | ||
19053 | } else if (!err) { | ||
19054 | printk(KERN_INFO | ||
19055 | "hda_codec: Cannot set up configuration " | ||
19056 | "from BIOS. Using base mode...\n"); | ||
19057 | board_config = ALC680_BASE; | ||
19058 | } | ||
19059 | } | ||
19060 | |||
19061 | if (board_config != ALC680_AUTO) | ||
19062 | setup_preset(codec, &alc680_presets[board_config]); | ||
19063 | |||
19064 | spec->stream_analog_playback = &alc680_pcm_analog_playback; | ||
19065 | spec->stream_analog_capture = &alc680_pcm_analog_capture; | ||
19066 | spec->stream_analog_alt_capture = &alc680_pcm_analog_alt_capture; | ||
19067 | spec->stream_digital_playback = &alc680_pcm_digital_playback; | ||
19068 | |||
19069 | if (!spec->adc_nids) { | ||
19070 | spec->adc_nids = alc680_adc_nids; | ||
19071 | spec->num_adc_nids = ARRAY_SIZE(alc680_adc_nids); | ||
19072 | } | ||
19073 | |||
19074 | if (!spec->cap_mixer) | ||
19075 | set_capture_mixer(codec); | ||
19076 | |||
19077 | spec->vmaster_nid = 0x02; | ||
19078 | |||
19079 | codec->patch_ops = alc_patch_ops; | ||
19080 | if (board_config == ALC680_AUTO) | ||
19081 | spec->init_hook = alc680_auto_init; | ||
19082 | |||
19083 | return 0; | ||
19084 | } | ||
19085 | |||
19086 | /* | ||
18759 | * patch entries | 19087 | * patch entries |
18760 | */ | 19088 | */ |
18761 | static struct hda_codec_preset snd_hda_preset_realtek[] = { | 19089 | static struct hda_codec_preset snd_hda_preset_realtek[] = { |
@@ -18779,6 +19107,7 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = { | |||
18779 | { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, | 19107 | { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, |
18780 | { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, | 19108 | { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, |
18781 | { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, | 19109 | { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, |
19110 | { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 }, | ||
18782 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, | 19111 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, |
18783 | { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, | 19112 | { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, |
18784 | { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, | 19113 | { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, |