aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_realtek.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-07-22 09:17:45 -0400
committerTakashi Iwai <tiwai@suse.de>2009-07-22 09:36:25 -0400
commit1c20930a41c623a2281e754f9321cd0feb01ceb9 (patch)
tree7484d66f36b73b599095c37e454a87b0f8e04897 /sound/pci/hda/patch_realtek.c
parent05ff7e11b78f18ff6819d2c260b7bcc7da0c8f46 (diff)
ALSA: hda - Fix ALC861 auto-mode parser
Fix the logic of ALC861 auto-mode parser for the outputs. Instead of assuming the fixed DAC list, parse the conection and assign the DAC dynamically. Also, unmute the unused output connections to avoid noises on inputs. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-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