diff options
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 169 |
1 files changed, 111 insertions, 58 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 454df58e983f..b2ea43206f18 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -13685,23 +13685,23 @@ static struct hda_verb alc861_auto_init_verbs[] = { | |||
13685 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 13685 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
13686 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, | 13686 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, |
13687 | 13687 | ||
13688 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 13688 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
13689 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 13689 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
13690 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 13690 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
13691 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 13691 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
13692 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 13692 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
13693 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 13693 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
13694 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 13694 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
13695 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 13695 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
13696 | 13696 | ||
13697 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 13697 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
13698 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 13698 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
13699 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 13699 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
13700 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 13700 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
13701 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 13701 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
13702 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 13702 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
13703 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, | 13703 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
13704 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, | 13704 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
13705 | 13705 | ||
13706 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, /* set Mic 1 */ | 13706 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, /* set Mic 1 */ |
13707 | 13707 | ||
@@ -13773,64 +13773,97 @@ static struct hda_input_mux alc861_capture_source = { | |||
13773 | }, | 13773 | }, |
13774 | }; | 13774 | }; |
13775 | 13775 | ||
13776 | static hda_nid_t alc861_look_for_dac(struct hda_codec *codec, hda_nid_t pin) | ||
13777 | { | ||
13778 | struct alc_spec *spec = codec->spec; | ||
13779 | hda_nid_t mix, srcs[5]; | ||
13780 | int i, j, num; | ||
13781 | |||
13782 | if (snd_hda_get_connections(codec, pin, &mix, 1) != 1) | ||
13783 | return 0; | ||
13784 | num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs)); | ||
13785 | if (num < 0) | ||
13786 | return 0; | ||
13787 | for (i = 0; i < num; i++) { | ||
13788 | unsigned int type; | ||
13789 | type = (get_wcaps(codec, srcs[i]) & AC_WCAP_TYPE) | ||
13790 | >> AC_WCAP_TYPE_SHIFT; | ||
13791 | if (type != AC_WID_AUD_OUT) | ||
13792 | continue; | ||
13793 | for (j = 0; j < spec->multiout.num_dacs; j++) | ||
13794 | if (spec->multiout.dac_nids[j] == srcs[i]) | ||
13795 | break; | ||
13796 | if (j >= spec->multiout.num_dacs) | ||
13797 | return srcs[i]; | ||
13798 | } | ||
13799 | return 0; | ||
13800 | } | ||
13801 | |||
13776 | /* fill in the dac_nids table from the parsed pin configuration */ | 13802 | /* fill in the dac_nids table from the parsed pin configuration */ |
13777 | static int alc861_auto_fill_dac_nids(struct alc_spec *spec, | 13803 | static int alc861_auto_fill_dac_nids(struct hda_codec *codec, |
13778 | const struct auto_pin_cfg *cfg) | 13804 | const struct auto_pin_cfg *cfg) |
13779 | { | 13805 | { |
13806 | struct alc_spec *spec = codec->spec; | ||
13780 | int i; | 13807 | int i; |
13781 | hda_nid_t nid; | 13808 | hda_nid_t nid, dac; |
13782 | 13809 | ||
13783 | spec->multiout.dac_nids = spec->private_dac_nids; | 13810 | spec->multiout.dac_nids = spec->private_dac_nids; |
13784 | for (i = 0; i < cfg->line_outs; i++) { | 13811 | for (i = 0; i < cfg->line_outs; i++) { |
13785 | nid = cfg->line_out_pins[i]; | 13812 | nid = cfg->line_out_pins[i]; |
13786 | if (nid) { | 13813 | dac = alc861_look_for_dac(codec, nid); |
13787 | if (i >= ARRAY_SIZE(alc861_dac_nids)) | 13814 | if (!dac) |
13788 | continue; | 13815 | continue; |
13789 | spec->multiout.dac_nids[i] = alc861_dac_nids[i]; | 13816 | spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac; |
13790 | } | ||
13791 | } | 13817 | } |
13792 | spec->multiout.num_dacs = cfg->line_outs; | ||
13793 | return 0; | 13818 | return 0; |
13794 | } | 13819 | } |
13795 | 13820 | ||
13821 | static int alc861_create_out_sw(struct hda_codec *codec, const char *pfx, | ||
13822 | hda_nid_t nid, unsigned int chs) | ||
13823 | { | ||
13824 | char name[32]; | ||
13825 | snprintf(name, sizeof(name), "%s Playback Switch", pfx); | ||
13826 | return add_control(codec->spec, ALC_CTL_WIDGET_MUTE, name, | ||
13827 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | ||
13828 | } | ||
13829 | |||
13796 | /* add playback controls from the parsed DAC table */ | 13830 | /* add playback controls from the parsed DAC table */ |
13797 | static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec, | 13831 | static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec, |
13798 | const struct auto_pin_cfg *cfg) | 13832 | const struct auto_pin_cfg *cfg) |
13799 | { | 13833 | { |
13800 | char name[32]; | 13834 | struct alc_spec *spec = codec->spec; |
13801 | static const char *chname[4] = { | 13835 | static const char *chname[4] = { |
13802 | "Front", "Surround", NULL /*CLFE*/, "Side" | 13836 | "Front", "Surround", NULL /*CLFE*/, "Side" |
13803 | }; | 13837 | }; |
13804 | hda_nid_t nid; | 13838 | hda_nid_t nid; |
13805 | int i, idx, err; | 13839 | int i, err; |
13840 | |||
13841 | if (cfg->line_outs == 1) { | ||
13842 | const char *pfx = NULL; | ||
13843 | if (!cfg->hp_outs) | ||
13844 | pfx = "Master"; | ||
13845 | else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | ||
13846 | pfx = "Speaker"; | ||
13847 | if (pfx) { | ||
13848 | nid = spec->multiout.dac_nids[0]; | ||
13849 | return alc861_create_out_sw(codec, pfx, nid, 3); | ||
13850 | } | ||
13851 | } | ||
13806 | 13852 | ||
13807 | for (i = 0; i < cfg->line_outs; i++) { | 13853 | for (i = 0; i < cfg->line_outs; i++) { |
13808 | nid = spec->multiout.dac_nids[i]; | 13854 | nid = spec->multiout.dac_nids[i]; |
13809 | if (!nid) | 13855 | if (!nid) |
13810 | continue; | 13856 | continue; |
13811 | if (nid == 0x05) { | 13857 | if (i == 2) { |
13812 | /* Center/LFE */ | 13858 | /* Center/LFE */ |
13813 | err = add_control(spec, ALC_CTL_BIND_MUTE, | 13859 | err = alc861_create_out_sw(codec, "Center", nid, 1); |
13814 | "Center Playback Switch", | ||
13815 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, | ||
13816 | HDA_OUTPUT)); | ||
13817 | if (err < 0) | 13860 | if (err < 0) |
13818 | return err; | 13861 | return err; |
13819 | err = add_control(spec, ALC_CTL_BIND_MUTE, | 13862 | err = alc861_create_out_sw(codec, "LFE", nid, 2); |
13820 | "LFE Playback Switch", | ||
13821 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, | ||
13822 | HDA_OUTPUT)); | ||
13823 | if (err < 0) | 13863 | if (err < 0) |
13824 | return err; | 13864 | return err; |
13825 | } else { | 13865 | } else { |
13826 | for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1; | 13866 | err = alc861_create_out_sw(codec, chname[i], nid, 3); |
13827 | idx++) | ||
13828 | if (nid == alc861_dac_nids[idx]) | ||
13829 | break; | ||
13830 | sprintf(name, "%s Playback Switch", chname[idx]); | ||
13831 | err = add_control(spec, ALC_CTL_BIND_MUTE, name, | ||
13832 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, | ||
13833 | HDA_OUTPUT)); | ||
13834 | if (err < 0) | 13867 | if (err < 0) |
13835 | return err; | 13868 | return err; |
13836 | } | 13869 | } |
@@ -13838,8 +13871,9 @@ static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
13838 | return 0; | 13871 | return 0; |
13839 | } | 13872 | } |
13840 | 13873 | ||
13841 | static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) | 13874 | static int alc861_auto_create_hp_ctls(struct hda_codec *codec, hda_nid_t pin) |
13842 | { | 13875 | { |
13876 | struct alc_spec *spec = codec->spec; | ||
13843 | int err; | 13877 | int err; |
13844 | hda_nid_t nid; | 13878 | hda_nid_t nid; |
13845 | 13879 | ||
@@ -13847,21 +13881,22 @@ static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) | |||
13847 | return 0; | 13881 | return 0; |
13848 | 13882 | ||
13849 | if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) { | 13883 | if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) { |
13850 | nid = 0x03; | 13884 | nid = alc861_look_for_dac(codec, pin); |
13851 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, | 13885 | if (nid) { |
13852 | "Headphone Playback Switch", | 13886 | err = alc861_create_out_sw(codec, "Headphone", nid, 3); |
13853 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); | 13887 | if (err < 0) |
13854 | if (err < 0) | 13888 | return err; |
13855 | return err; | 13889 | spec->multiout.hp_nid = nid; |
13856 | spec->multiout.hp_nid = nid; | 13890 | } |
13857 | } | 13891 | } |
13858 | return 0; | 13892 | return 0; |
13859 | } | 13893 | } |
13860 | 13894 | ||
13861 | /* create playback/capture controls for input pins */ | 13895 | /* create playback/capture controls for input pins */ |
13862 | static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, | 13896 | static int alc861_auto_create_analog_input_ctls(struct hda_codec *codec, |
13863 | const struct auto_pin_cfg *cfg) | 13897 | const struct auto_pin_cfg *cfg) |
13864 | { | 13898 | { |
13899 | struct alc_spec *spec = codec->spec; | ||
13865 | struct hda_input_mux *imux = &spec->private_imux[0]; | 13900 | struct hda_input_mux *imux = &spec->private_imux[0]; |
13866 | int i, err, idx, idx1; | 13901 | int i, err, idx, idx1; |
13867 | 13902 | ||
@@ -13905,12 +13940,29 @@ static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, | |||
13905 | 13940 | ||
13906 | static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, | 13941 | static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, |
13907 | hda_nid_t nid, | 13942 | hda_nid_t nid, |
13908 | int pin_type, int dac_idx) | 13943 | int pin_type, hda_nid_t dac) |
13909 | { | 13944 | { |
13945 | hda_nid_t mix, srcs[5]; | ||
13946 | int i, num; | ||
13947 | |||
13910 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 13948 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, |
13911 | pin_type); | 13949 | pin_type); |
13912 | snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 13950 | snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE, |
13913 | AMP_OUT_UNMUTE); | 13951 | AMP_OUT_UNMUTE); |
13952 | if (snd_hda_get_connections(codec, nid, &mix, 1) != 1) | ||
13953 | return; | ||
13954 | num = snd_hda_get_connections(codec, mix, srcs, ARRAY_SIZE(srcs)); | ||
13955 | if (num < 0) | ||
13956 | return; | ||
13957 | for (i = 0; i < num; i++) { | ||
13958 | unsigned int mute; | ||
13959 | if (srcs[i] == dac || srcs[i] == 0x15) | ||
13960 | mute = AMP_IN_UNMUTE(i); | ||
13961 | else | ||
13962 | mute = AMP_IN_MUTE(i); | ||
13963 | snd_hda_codec_write(codec, mix, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
13964 | mute); | ||
13965 | } | ||
13914 | } | 13966 | } |
13915 | 13967 | ||
13916 | static void alc861_auto_init_multi_out(struct hda_codec *codec) | 13968 | static void alc861_auto_init_multi_out(struct hda_codec *codec) |
@@ -13933,12 +13985,13 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec) | |||
13933 | hda_nid_t pin; | 13985 | hda_nid_t pin; |
13934 | 13986 | ||
13935 | pin = spec->autocfg.hp_pins[0]; | 13987 | pin = spec->autocfg.hp_pins[0]; |
13936 | if (pin) /* connect to front */ | 13988 | if (pin) |
13937 | alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, | 13989 | alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, |
13938 | spec->multiout.dac_nids[0]); | 13990 | spec->multiout.hp_nid); |
13939 | pin = spec->autocfg.speaker_pins[0]; | 13991 | pin = spec->autocfg.speaker_pins[0]; |
13940 | if (pin) | 13992 | if (pin) |
13941 | alc861_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); | 13993 | alc861_auto_set_output_and_unmute(codec, pin, PIN_OUT, |
13994 | spec->multiout.dac_nids[0]); | ||
13942 | } | 13995 | } |
13943 | 13996 | ||
13944 | static void alc861_auto_init_analog_input(struct hda_codec *codec) | 13997 | static void alc861_auto_init_analog_input(struct hda_codec *codec) |
@@ -13970,16 +14023,16 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
13970 | if (!spec->autocfg.line_outs) | 14023 | if (!spec->autocfg.line_outs) |
13971 | return 0; /* can't find valid BIOS pin config */ | 14024 | return 0; /* can't find valid BIOS pin config */ |
13972 | 14025 | ||
13973 | err = alc861_auto_fill_dac_nids(spec, &spec->autocfg); | 14026 | err = alc861_auto_fill_dac_nids(codec, &spec->autocfg); |
13974 | if (err < 0) | 14027 | if (err < 0) |
13975 | return err; | 14028 | return err; |
13976 | err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg); | 14029 | err = alc861_auto_create_multi_out_ctls(codec, &spec->autocfg); |
13977 | if (err < 0) | 14030 | if (err < 0) |
13978 | return err; | 14031 | return err; |
13979 | err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 14032 | err = alc861_auto_create_hp_ctls(codec, spec->autocfg.hp_pins[0]); |
13980 | if (err < 0) | 14033 | if (err < 0) |
13981 | return err; | 14034 | return err; |
13982 | err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg); | 14035 | err = alc861_auto_create_analog_input_ctls(codec, &spec->autocfg); |
13983 | if (err < 0) | 14036 | if (err < 0) |
13984 | return err; | 14037 | return err; |
13985 | 14038 | ||