From c3fc1f502a1f1a751c891d3b757a24dc76943539 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 25 Aug 2009 16:08:47 +0200 Subject: [PATCH] ALSA: hda - Improve auto-cfg mixer name for ALC262 Similar improvements for ALC262 codec like previous two commits: assign a better name, either Master or Speaker, for the primary output controls. However, in the case of ALC262 codec, the necessary changes are larger than others because we need to check the possibility of different mixer amps depending on the pins. The pin 0x16 is mono, and bound with the dedicated mixer 0x0e while other pins are bound with 0x0c. Thus, there are two possible volumes. When only one of them is used, we can name it as "Master". OTOH, when both are used at the same time, they have to be named uniquely. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 152 ++++++++++++++++++++-------------- 1 file changed, 89 insertions(+), 63 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 00ed1268f274..407475941fd3 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -10790,80 +10790,106 @@ static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = { { } /* end */ }; +/* We use two mixers depending on the output pin; 0x16 is a mono output + * and thus it's bound with a different mixer. + * This function returns which mixer amp should be used. + */ +static int alc262_check_volbit(hda_nid_t nid) +{ + if (!nid) + return 0; + else if (nid == 0x16) + return 2; + else + return 1; +} + +static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid, + const char *pfx, int *vbits) +{ + char name[32]; + unsigned long val; + int vbit; + + vbit = alc262_check_volbit(nid); + if (!vbit) + return 0; + if (*vbits & vbit) /* a volume control for this mixer already there */ + return 0; + *vbits |= vbit; + snprintf(name, sizeof(name), "%s Playback Volume", pfx); + if (vbit == 2) + val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT); + else + val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT); + return add_control(spec, ALC_CTL_WIDGET_VOL, name, val); +} + +static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid, + const char *pfx) +{ + char name[32]; + unsigned long val; + + if (!nid) + return 0; + snprintf(name, sizeof(name), "%s Playback Switch", pfx); + if (nid == 0x16) + val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT); + else + val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); + return add_control(spec, ALC_CTL_WIDGET_MUTE, name, val); +} + /* add playback controls from the parsed DAC table */ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) { - hda_nid_t nid; + const char *pfx; + int vbits; int err; spec->multiout.num_dacs = 1; /* only use one dac */ spec->multiout.dac_nids = spec->private_dac_nids; spec->multiout.dac_nids[0] = 2; - nid = cfg->line_out_pins[0]; - if (nid) { - err = add_control(spec, ALC_CTL_WIDGET_VOL, - "Front Playback Volume", - HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT)); - if (err < 0) - return err; - err = add_control(spec, ALC_CTL_WIDGET_MUTE, - "Front Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); - if (err < 0) - return err; - } + if (!cfg->speaker_pins[0] && !cfg->hp_pins[0]) + pfx = "Master"; + else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) + pfx = "Speaker"; + else + pfx = "Front"; + err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[0], pfx); + if (err < 0) + return err; + err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[0], "Speaker"); + if (err < 0) + return err; + err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[0], "Headphone"); + if (err < 0) + return err; - nid = cfg->speaker_pins[0]; - if (nid) { - if (nid == 0x16) { - err = add_control(spec, ALC_CTL_WIDGET_VOL, - "Speaker Playback Volume", - HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, - HDA_OUTPUT)); - if (err < 0) - return err; - err = add_control(spec, ALC_CTL_WIDGET_MUTE, - "Speaker Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 2, 0, - HDA_OUTPUT)); - if (err < 0) - return err; - } else { - err = add_control(spec, ALC_CTL_WIDGET_MUTE, - "Speaker Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 3, 0, - HDA_OUTPUT)); - if (err < 0) - return err; - } - } - nid = cfg->hp_pins[0]; - if (nid) { - /* spec->multiout.hp_nid = 2; */ - if (nid == 0x16) { - err = add_control(spec, ALC_CTL_WIDGET_VOL, - "Headphone Playback Volume", - HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, - HDA_OUTPUT)); - if (err < 0) - return err; - err = add_control(spec, ALC_CTL_WIDGET_MUTE, - "Headphone Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 2, 0, - HDA_OUTPUT)); - if (err < 0) - return err; - } else { - err = add_control(spec, ALC_CTL_WIDGET_MUTE, - "Headphone Playback Switch", - HDA_COMPOSE_AMP_VAL(nid, 3, 0, - HDA_OUTPUT)); - if (err < 0) - return err; - } - } + vbits = alc262_check_volbit(cfg->line_out_pins[0]) | + alc262_check_volbit(cfg->speaker_pins[0]) | + alc262_check_volbit(cfg->hp_pins[0]); + if (vbits == 1 || vbits == 2) + pfx = "Master"; /* only one mixer is used */ + else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) + pfx = "Speaker"; + else + pfx = "Front"; + vbits = 0; + err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[0], pfx, &vbits); + if (err < 0) + return err; + err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[0], "Speaker", + &vbits); + if (err < 0) + return err; + err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[0], "Headphone", + &vbits); + if (err < 0) + return err; return 0; } -- 2.20.1