aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/patch_realtek.c169
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
13776static 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 */
13777static int alc861_auto_fill_dac_nids(struct alc_spec *spec, 13803static 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
13821static 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 */
13797static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec, 13831static 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
13841static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) 13874static 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 */
13862static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, 13896static 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
13906static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, 13941static 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
13916static void alc861_auto_init_multi_out(struct hda_codec *codec) 13968static 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
13944static void alc861_auto_init_analog_input(struct hda_codec *codec) 13997static 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