Skip to content

Commit ef403ed

Browse files
committed
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>
1 parent 2ddee91 commit ef403ed

File tree

1 file changed

+22
-8
lines changed

1 file changed

+22
-8
lines changed

sound/pci/hda/hda_generic.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -692,7 +692,23 @@ static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
692692
{
693693
unsigned int caps = query_amp_caps(codec, nid, dir);
694694
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 */
703+
static 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);
696712
}
697713

698714
/* 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,
732748
return;
733749

734750
val &= mask;
735-
snd_hda_codec_amp_stereo(codec, nid, dir, idx, mask, val);
751+
update_amp(codec, nid, dir, idx, mask, val);
736752
}
737753

738754
static 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)
44244440
has_amp = nid_has_mute(codec, mix, HDA_INPUT);
44254441
for (i = 0; i < nums; i++) {
44264442
if (has_amp)
4427-
snd_hda_codec_amp_stereo(codec, mix,
4428-
HDA_INPUT, i,
4429-
0xff, HDA_AMP_MUTE);
4443+
update_amp(codec, mix, HDA_INPUT, i,
4444+
0xff, HDA_AMP_MUTE);
44304445
else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
4431-
snd_hda_codec_amp_stereo(codec, conn[i],
4432-
HDA_OUTPUT, 0,
4433-
0xff, HDA_AMP_MUTE);
4446+
update_amp(codec, conn[i], HDA_OUTPUT, 0,
4447+
0xff, HDA_AMP_MUTE);
44344448
}
44354449
}
44364450

0 commit comments

Comments
 (0)