aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-01-10 09:45:23 -0500
committerTakashi Iwai <tiwai@suse.de>2011-01-10 09:45:23 -0500
commitbcb2f0f517ebae7350526bbde8912ad187147e2d (patch)
tree03a7e8884e4c120c3f11b25bd14f8f5f58b0f9aa /sound/pci
parentb2d0576055bd1cafcd91a23cf85064815f1396cd (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.c137
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
5071static 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 */
5072static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, 5091static 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
15888static int alc861_create_out_sw(struct hda_codec *codec, const char *pfx, 15902static 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 */
15896static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec, 15913static 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
19081static inline int alc662_add_vol_ctl(struct alc_spec *spec, const char *pfx, 19084static 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
19088static inline int alc662_add_sw_ctl(struct alc_spec *spec, const char *pfx, 19091static 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 }