ALSA: hda - Treat stereo-to-mono mix properly
The commit [ef403edb75
: ALSA: hda - Don't access stereo amps for
mono channel widgets] fixed the handling of mono widgets in general,
but it still misses an exceptional case: namely, a mono mixer widget
taking a single stereo input. In this case, it has stereo volumes
although it's a mono widget, and thus we have to take care of both
left and right input channels, as stated in HD-audio spec ("7.1.3
Widget Interconnection Rules").
This patch covers this missing piece by adding proper checks of stereo
amps in both the generic parser and the proc output codes.
Reported-by: Raymond Yau <superquad.vortex2@gmail.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
@@ -687,13 +687,30 @@ static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
|
||||
return val;
|
||||
}
|
||||
|
||||
/* is this a stereo widget or a stereo-to-mono mix? */
|
||||
static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, int dir)
|
||||
{
|
||||
unsigned int wcaps = get_wcaps(codec, nid);
|
||||
hda_nid_t conn;
|
||||
|
||||
if (wcaps & AC_WCAP_STEREO)
|
||||
return true;
|
||||
if (dir != HDA_INPUT || get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
|
||||
return false;
|
||||
if (snd_hda_get_num_conns(codec, nid) != 1)
|
||||
return false;
|
||||
if (snd_hda_get_connections(codec, nid, &conn, 1) < 0)
|
||||
return false;
|
||||
return !!(get_wcaps(codec, conn) & AC_WCAP_STEREO);
|
||||
}
|
||||
|
||||
/* initialize the amp value (only at the first time) */
|
||||
static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
|
||||
{
|
||||
unsigned int caps = query_amp_caps(codec, nid, dir);
|
||||
int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
|
||||
|
||||
if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
|
||||
if (is_stereo_amps(codec, nid, dir))
|
||||
snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
|
||||
else
|
||||
snd_hda_codec_amp_init(codec, nid, 0, dir, idx, 0xff, val);
|
||||
@@ -703,7 +720,7 @@ static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
|
||||
static int update_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx,
|
||||
unsigned int mask, unsigned int val)
|
||||
{
|
||||
if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
|
||||
if (is_stereo_amps(codec, nid, dir))
|
||||
return snd_hda_codec_amp_stereo(codec, nid, dir, idx,
|
||||
mask, val);
|
||||
else
|
||||
|
Reference in New Issue
Block a user