aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-03-12 03:30:11 -0400
committerTakashi Iwai <tiwai@suse.de>2015-03-13 02:37:21 -0400
commitef403edb75580a3ec5d155f5de82155f0419c621 (patch)
tree619a1effc28507e067292989ca39ad94d7080b39 /sound
parent2ddee91abe9cc34ddb6294ee14702b46ae07d460 (diff)
ALSA: hda - Don't access stereo amps for mono channel widgets
The current HDA generic parser initializes / modifies the amp values always in stereo, but this seems causing the problem on ALC3229 codec that has a few mono channel widgets: namely, these mono widgets react to actions for both channels equally. In the driver code, we do care the mono channel and create a control only for the left channel (as defined in HD-audio spec) for such a node. When the control is updated, only the left channel value is changed. However, in the resume, the right channel value is also restored from the initial value we took as stereo, and this overwrites the left channel value. This ends up being the silent output as the right channel has been never touched and remains muted. This patch covers the places where unconditional stereo amp accesses are done and converts to the conditional accesses. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=94581 Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_generic.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index b680b4ec6331..fe18071bf93a 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -692,7 +692,23 @@ static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
692{ 692{
693 unsigned int caps = query_amp_caps(codec, nid, dir); 693 unsigned int caps = query_amp_caps(codec, nid, dir);
694 int val = get_amp_val_to_activate(codec, nid, dir, caps, false); 694 int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
695 snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val); 695
696 if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
697 snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
698 else
699 snd_hda_codec_amp_init(codec, nid, 0, dir, idx, 0xff, val);
700}
701
702/* update the amp, doing in stereo or mono depending on NID */
703static int update_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx,
704 unsigned int mask, unsigned int val)
705{
706 if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
707 return snd_hda_codec_amp_stereo(codec, nid, dir, idx,
708 mask, val);
709 else
710 return snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
711 mask, val);
696} 712}
697 713
698/* calculate amp value mask we can modify; 714/* calculate amp value mask we can modify;
@@ -732,7 +748,7 @@ static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
732 return; 748 return;
733 749
734 val &= mask; 750 val &= mask;
735 snd_hda_codec_amp_stereo(codec, nid, dir, idx, mask, val); 751 update_amp(codec, nid, dir, idx, mask, val);
736} 752}
737 753
738static void activate_amp_out(struct hda_codec *codec, struct nid_path *path, 754static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
@@ -4424,13 +4440,11 @@ static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
4424 has_amp = nid_has_mute(codec, mix, HDA_INPUT); 4440 has_amp = nid_has_mute(codec, mix, HDA_INPUT);
4425 for (i = 0; i < nums; i++) { 4441 for (i = 0; i < nums; i++) {
4426 if (has_amp) 4442 if (has_amp)
4427 snd_hda_codec_amp_stereo(codec, mix, 4443 update_amp(codec, mix, HDA_INPUT, i,
4428 HDA_INPUT, i, 4444 0xff, HDA_AMP_MUTE);
4429 0xff, HDA_AMP_MUTE);
4430 else if (nid_has_volume(codec, conn[i], HDA_OUTPUT)) 4445 else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
4431 snd_hda_codec_amp_stereo(codec, conn[i], 4446 update_amp(codec, conn[i], HDA_OUTPUT, 0,
4432 HDA_OUTPUT, 0, 4447 0xff, HDA_AMP_MUTE);
4433 0xff, HDA_AMP_MUTE);
4434 } 4448 }
4435} 4449}
4436 4450