diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-01-10 09:45:23 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-01-10 09:45:23 -0500 |
commit | bcb2f0f517ebae7350526bbde8912ad187147e2d (patch) | |
tree | 03a7e8884e4c120c3f11b25bd14f8f5f58b0f9aa /sound/pci | |
parent | b2d0576055bd1cafcd91a23cf85064815f1396cd (diff) |
ALSA: hda - Add support for multiple headphone/speaker controls for Realtek
So far, Realtek auto-parser assumed that the multiple pins are only for
line-outs, and assigned the channel names like Front, Surround, etc for
the multiple outputs. But, there are devices that have multiple
headphones, and these can be better controlled with the corresponding
control-name like "Headphone" with indicies.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 137 |
1 files changed, 68 insertions, 69 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b4f78952381a..0ecd75e2d28f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -5068,6 +5068,25 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec, | |||
5068 | return 0; | 5068 | return 0; |
5069 | } | 5069 | } |
5070 | 5070 | ||
5071 | static const char *alc_get_line_out_pfx(const struct auto_pin_cfg *cfg, | ||
5072 | bool can_be_master) | ||
5073 | { | ||
5074 | if (!cfg->hp_outs && !cfg->speaker_outs && can_be_master) | ||
5075 | return "Master"; | ||
5076 | |||
5077 | switch (cfg->line_out_type) { | ||
5078 | case AUTO_PIN_SPEAKER_OUT: | ||
5079 | return "Speaker"; | ||
5080 | case AUTO_PIN_HP_OUT: | ||
5081 | return "Headphone"; | ||
5082 | default: | ||
5083 | if (cfg->line_outs == 1) | ||
5084 | return "PCM"; | ||
5085 | break; | ||
5086 | } | ||
5087 | return NULL; | ||
5088 | } | ||
5089 | |||
5071 | /* add playback controls from the parsed DAC table */ | 5090 | /* add playback controls from the parsed DAC table */ |
5072 | static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, | 5091 | static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, |
5073 | const struct auto_pin_cfg *cfg) | 5092 | const struct auto_pin_cfg *cfg) |
@@ -5075,6 +5094,7 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
5075 | static const char *chname[4] = { | 5094 | static const char *chname[4] = { |
5076 | "Front", "Surround", NULL /*CLFE*/, "Side" | 5095 | "Front", "Surround", NULL /*CLFE*/, "Side" |
5077 | }; | 5096 | }; |
5097 | const char *pfx = alc_get_line_out_pfx(cfg, false); | ||
5078 | hda_nid_t nid; | 5098 | hda_nid_t nid; |
5079 | int i, err; | 5099 | int i, err; |
5080 | 5100 | ||
@@ -5082,7 +5102,7 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
5082 | if (!spec->multiout.dac_nids[i]) | 5102 | if (!spec->multiout.dac_nids[i]) |
5083 | continue; | 5103 | continue; |
5084 | nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i])); | 5104 | nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i])); |
5085 | if (i == 2) { | 5105 | if (!pfx && i == 2) { |
5086 | /* Center/LFE */ | 5106 | /* Center/LFE */ |
5087 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, | 5107 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, |
5088 | "Center", | 5108 | "Center", |
@@ -5109,18 +5129,17 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
5109 | if (err < 0) | 5129 | if (err < 0) |
5110 | return err; | 5130 | return err; |
5111 | } else { | 5131 | } else { |
5112 | const char *pfx; | 5132 | const char *name = pfx; |
5113 | if (cfg->line_outs == 1 && | 5133 | if (!name) |
5114 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | 5134 | name = chname[i]; |
5115 | pfx = "Speaker"; | 5135 | err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, |
5116 | else | 5136 | name, i, |
5117 | pfx = chname[i]; | ||
5118 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, | ||
5119 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, | 5137 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, |
5120 | HDA_OUTPUT)); | 5138 | HDA_OUTPUT)); |
5121 | if (err < 0) | 5139 | if (err < 0) |
5122 | return err; | 5140 | return err; |
5123 | err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx, | 5141 | err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, |
5142 | name, i, | ||
5124 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, | 5143 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, |
5125 | HDA_INPUT)); | 5144 | HDA_INPUT)); |
5126 | if (err < 0) | 5145 | if (err < 0) |
@@ -12085,13 +12104,8 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
12085 | spec->multiout.dac_nids = spec->private_dac_nids; | 12104 | spec->multiout.dac_nids = spec->private_dac_nids; |
12086 | spec->multiout.dac_nids[0] = 2; | 12105 | spec->multiout.dac_nids[0] = 2; |
12087 | 12106 | ||
12088 | if (!cfg->speaker_pins[0] && !cfg->hp_pins[0]) | 12107 | pfx = alc_get_line_out_pfx(cfg, true); |
12089 | pfx = "Master"; | 12108 | if (!pfx) |
12090 | else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | ||
12091 | pfx = "Speaker"; | ||
12092 | else if (cfg->line_out_type == AUTO_PIN_HP_OUT) | ||
12093 | pfx = "Headphone"; | ||
12094 | else | ||
12095 | pfx = "Front"; | 12109 | pfx = "Front"; |
12096 | for (i = 0; i < 2; i++) { | 12110 | for (i = 0; i < 2; i++) { |
12097 | err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[i], pfx, i); | 12111 | err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[i], pfx, i); |
@@ -15885,13 +15899,16 @@ static int alc861_auto_fill_dac_nids(struct hda_codec *codec, | |||
15885 | return 0; | 15899 | return 0; |
15886 | } | 15900 | } |
15887 | 15901 | ||
15888 | static int alc861_create_out_sw(struct hda_codec *codec, const char *pfx, | 15902 | static int __alc861_create_out_sw(struct hda_codec *codec, const char *pfx, |
15889 | hda_nid_t nid, unsigned int chs) | 15903 | hda_nid_t nid, int idx, unsigned int chs) |
15890 | { | 15904 | { |
15891 | return add_pb_sw_ctrl(codec->spec, ALC_CTL_WIDGET_MUTE, pfx, | 15905 | return __add_pb_sw_ctrl(codec->spec, ALC_CTL_WIDGET_MUTE, pfx, idx, |
15892 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | 15906 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); |
15893 | } | 15907 | } |
15894 | 15908 | ||
15909 | #define alc861_create_out_sw(codec, pfx, nid, chs) \ | ||
15910 | __alc861_create_out_sw(codec, pfx, nid, 0, chs) | ||
15911 | |||
15895 | /* add playback controls from the parsed DAC table */ | 15912 | /* add playback controls from the parsed DAC table */ |
15896 | static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec, | 15913 | static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec, |
15897 | const struct auto_pin_cfg *cfg) | 15914 | const struct auto_pin_cfg *cfg) |
@@ -15900,26 +15917,15 @@ static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
15900 | static const char *chname[4] = { | 15917 | static const char *chname[4] = { |
15901 | "Front", "Surround", NULL /*CLFE*/, "Side" | 15918 | "Front", "Surround", NULL /*CLFE*/, "Side" |
15902 | }; | 15919 | }; |
15920 | const char *pfx = alc_get_line_out_pfx(cfg, true); | ||
15903 | hda_nid_t nid; | 15921 | hda_nid_t nid; |
15904 | int i, err; | 15922 | int i, err; |
15905 | 15923 | ||
15906 | if (cfg->line_outs == 1) { | ||
15907 | const char *pfx = NULL; | ||
15908 | if (!cfg->hp_outs) | ||
15909 | pfx = "Master"; | ||
15910 | else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | ||
15911 | pfx = "Speaker"; | ||
15912 | if (pfx) { | ||
15913 | nid = spec->multiout.dac_nids[0]; | ||
15914 | return alc861_create_out_sw(codec, pfx, nid, 3); | ||
15915 | } | ||
15916 | } | ||
15917 | |||
15918 | for (i = 0; i < cfg->line_outs; i++) { | 15924 | for (i = 0; i < cfg->line_outs; i++) { |
15919 | nid = spec->multiout.dac_nids[i]; | 15925 | nid = spec->multiout.dac_nids[i]; |
15920 | if (!nid) | 15926 | if (!nid) |
15921 | continue; | 15927 | continue; |
15922 | if (i == 2) { | 15928 | if (!pfx && i == 2) { |
15923 | /* Center/LFE */ | 15929 | /* Center/LFE */ |
15924 | err = alc861_create_out_sw(codec, "Center", nid, 1); | 15930 | err = alc861_create_out_sw(codec, "Center", nid, 1); |
15925 | if (err < 0) | 15931 | if (err < 0) |
@@ -15928,7 +15934,10 @@ static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
15928 | if (err < 0) | 15934 | if (err < 0) |
15929 | return err; | 15935 | return err; |
15930 | } else { | 15936 | } else { |
15931 | err = alc861_create_out_sw(codec, chname[i], nid, 3); | 15937 | const char *name = pfx; |
15938 | if (!name) | ||
15939 | name = chname[i]; | ||
15940 | err = __alc861_create_out_sw(codec, name, nid, i, 3); | ||
15932 | if (err < 0) | 15941 | if (err < 0) |
15933 | return err; | 15942 | return err; |
15934 | } | 15943 | } |
@@ -17033,6 +17042,7 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
17033 | const struct auto_pin_cfg *cfg) | 17042 | const struct auto_pin_cfg *cfg) |
17034 | { | 17043 | { |
17035 | static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"}; | 17044 | static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"}; |
17045 | const char *pfx = alc_get_line_out_pfx(cfg, true); | ||
17036 | hda_nid_t nid_v, nid_s; | 17046 | hda_nid_t nid_v, nid_s; |
17037 | int i, err; | 17047 | int i, err; |
17038 | 17048 | ||
@@ -17046,7 +17056,7 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
17046 | alc880_dac_to_idx( | 17056 | alc880_dac_to_idx( |
17047 | spec->multiout.dac_nids[i])); | 17057 | spec->multiout.dac_nids[i])); |
17048 | 17058 | ||
17049 | if (i == 2) { | 17059 | if (!pfx && i == 2) { |
17050 | /* Center/LFE */ | 17060 | /* Center/LFE */ |
17051 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, | 17061 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, |
17052 | "Center", | 17062 | "Center", |
@@ -17073,24 +17083,17 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
17073 | if (err < 0) | 17083 | if (err < 0) |
17074 | return err; | 17084 | return err; |
17075 | } else { | 17085 | } else { |
17076 | const char *pfx; | 17086 | const char *name = pfx; |
17077 | if (cfg->line_outs == 1 && | 17087 | if (!name) |
17078 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { | 17088 | name = chname[i]; |
17079 | if (!cfg->hp_pins) | 17089 | err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, |
17080 | pfx = "Speaker"; | 17090 | name, i, |
17081 | else | ||
17082 | pfx = "PCM"; | ||
17083 | } else | ||
17084 | pfx = chname[i]; | ||
17085 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, | ||
17086 | HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, | 17091 | HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, |
17087 | HDA_OUTPUT)); | 17092 | HDA_OUTPUT)); |
17088 | if (err < 0) | 17093 | if (err < 0) |
17089 | return err; | 17094 | return err; |
17090 | if (cfg->line_outs == 1 && | 17095 | err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, |
17091 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | 17096 | name, i, |
17092 | pfx = "Speaker"; | ||
17093 | err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx, | ||
17094 | HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, | 17097 | HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, |
17095 | HDA_INPUT)); | 17098 | HDA_INPUT)); |
17096 | if (err < 0) | 17099 | if (err < 0) |
@@ -19078,20 +19081,24 @@ static int alc662_auto_fill_dac_nids(struct hda_codec *codec, | |||
19078 | return 0; | 19081 | return 0; |
19079 | } | 19082 | } |
19080 | 19083 | ||
19081 | static inline int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx, | 19084 | static inline int __alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx, |
19082 | hda_nid_t nid, unsigned int chs) | 19085 | hda_nid_t nid, int idx, unsigned int chs) |
19083 | { | 19086 | { |
19084 | return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, | 19087 | return __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, idx, |
19085 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | 19088 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); |
19086 | } | 19089 | } |
19087 | 19090 | ||
19088 | static inline int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx, | 19091 | static inline int __alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx, |
19089 | hda_nid_t nid, unsigned int chs) | 19092 | hda_nid_t nid, int idx, unsigned int chs) |
19090 | { | 19093 | { |
19091 | return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, | 19094 | return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, idx, |
19092 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT)); | 19095 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_INPUT)); |
19093 | } | 19096 | } |
19094 | 19097 | ||
19098 | #define alc662_add_vol_ctl(spec, pfx, nid, chs) \ | ||
19099 | __alc662_add_vol_ctl(spec, pfx, nid, 0, chs) | ||
19100 | #define alc662_add_sw_ctl(spec, pfx, nid, chs) \ | ||
19101 | __alc662_add_sw_ctl(spec, pfx, nid, 0, chs) | ||
19095 | #define alc662_add_stereo_vol(spec, pfx, nid) \ | 19102 | #define alc662_add_stereo_vol(spec, pfx, nid) \ |
19096 | alc662_add_vol_ctl(spec, pfx, nid, 3) | 19103 | alc662_add_vol_ctl(spec, pfx, nid, 3) |
19097 | #define alc662_add_stereo_sw(spec, pfx, nid) \ | 19104 | #define alc662_add_stereo_sw(spec, pfx, nid) \ |
@@ -19105,6 +19112,7 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
19105 | static const char *chname[4] = { | 19112 | static const char *chname[4] = { |
19106 | "Front", "Surround", NULL /*CLFE*/, "Side" | 19113 | "Front", "Surround", NULL /*CLFE*/, "Side" |
19107 | }; | 19114 | }; |
19115 | const char *pfx = alc_get_line_out_pfx(cfg, true); | ||
19108 | hda_nid_t nid, mix; | 19116 | hda_nid_t nid, mix; |
19109 | int i, err; | 19117 | int i, err; |
19110 | 19118 | ||
@@ -19115,7 +19123,7 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
19115 | mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid); | 19123 | mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid); |
19116 | if (!mix) | 19124 | if (!mix) |
19117 | continue; | 19125 | continue; |
19118 | if (i == 2) { | 19126 | if (!pfx && i == 2) { |
19119 | /* Center/LFE */ | 19127 | /* Center/LFE */ |
19120 | err = alc662_add_vol_ctl(spec, "Center", nid, 1); | 19128 | err = alc662_add_vol_ctl(spec, "Center", nid, 1); |
19121 | if (err < 0) | 19129 | if (err < 0) |
@@ -19130,22 +19138,13 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
19130 | if (err < 0) | 19138 | if (err < 0) |
19131 | return err; | 19139 | return err; |
19132 | } else { | 19140 | } else { |
19133 | const char *pfx; | 19141 | const char *name = pfx; |
19134 | if (cfg->line_outs == 1 && | 19142 | if (!name) |
19135 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) { | 19143 | name = chname[i]; |
19136 | if (cfg->hp_outs) | 19144 | err = __alc662_add_vol_ctl(spec, name, nid, i, 3); |
19137 | pfx = "Speaker"; | ||
19138 | else | ||
19139 | pfx = "PCM"; | ||
19140 | } else | ||
19141 | pfx = chname[i]; | ||
19142 | err = alc662_add_vol_ctl(spec, pfx, nid, 3); | ||
19143 | if (err < 0) | 19145 | if (err < 0) |
19144 | return err; | 19146 | return err; |
19145 | if (cfg->line_outs == 1 && | 19147 | err = __alc662_add_sw_ctl(spec, name, mix, i, 3); |
19146 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | ||
19147 | pfx = "Speaker"; | ||
19148 | err = alc662_add_sw_ctl(spec, pfx, mix, 3); | ||
19149 | if (err < 0) | 19148 | if (err < 0) |
19150 | return err; | 19149 | return err; |
19151 | } | 19150 | } |