ALSA: hda - Fix aamix activation with loopback control on VIA codecs

When we have a loopback mixer control, this should manage the state
whether the output paths include the aamix or not.  But the current
code blindly initializes the output paths with aamix = true, thus the
aamix is enabled unless the loopback mixer control is changed.

Also, update_aamix_paths() called by the loopback mixer control put
callback invokes snd_hda_activate_path() with aamix = true even for
disabling the mixing.  This leaves the aamix path even though the
loopback control is turned off.

This patch fixes these issues:
- Introduced aamix_default() helper to indicate whether with_aamix is
  true or false as default
- Fix the argument in update_aamix_paths() for disabling loopback

Reported-by: Lydia Wang <LydiaWang@viatech.com.cn>
Cc: <stable@vger.kernel.org> [v3.9+]
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2013-04-16 12:31:05 +02:00
parent ae03bbb8f9
commit 65033cc8d5
1 changed files with 16 additions and 6 deletions

View File

@ -2082,6 +2082,14 @@ get_multiio_path(struct hda_codec *codec, int idx)
static void update_automute_all(struct hda_codec *codec); static void update_automute_all(struct hda_codec *codec);
/* Default value to be passed as aamix argument for snd_hda_activate_path();
* used for output paths
*/
static bool aamix_default(struct hda_gen_spec *spec)
{
return !spec->have_aamix_ctl || spec->aamix_mode;
}
static int set_multi_io(struct hda_codec *codec, int idx, bool output) static int set_multi_io(struct hda_codec *codec, int idx, bool output)
{ {
struct hda_gen_spec *spec = codec->spec; struct hda_gen_spec *spec = codec->spec;
@ -2097,11 +2105,11 @@ static int set_multi_io(struct hda_codec *codec, int idx, bool output)
if (output) { if (output) {
set_pin_target(codec, nid, PIN_OUT, true); set_pin_target(codec, nid, PIN_OUT, true);
snd_hda_activate_path(codec, path, true, true); snd_hda_activate_path(codec, path, true, aamix_default(spec));
set_pin_eapd(codec, nid, true); set_pin_eapd(codec, nid, true);
} else { } else {
set_pin_eapd(codec, nid, false); set_pin_eapd(codec, nid, false);
snd_hda_activate_path(codec, path, false, true); snd_hda_activate_path(codec, path, false, aamix_default(spec));
set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true); set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
path_power_down_sync(codec, path); path_power_down_sync(codec, path);
} }
@ -2192,8 +2200,8 @@ static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
snd_hda_activate_path(codec, mix_path, true, true); snd_hda_activate_path(codec, mix_path, true, true);
path_power_down_sync(codec, nomix_path); path_power_down_sync(codec, nomix_path);
} else { } else {
snd_hda_activate_path(codec, mix_path, false, true); snd_hda_activate_path(codec, mix_path, false, false);
snd_hda_activate_path(codec, nomix_path, true, true); snd_hda_activate_path(codec, nomix_path, true, false);
path_power_down_sync(codec, mix_path); path_power_down_sync(codec, mix_path);
} }
} }
@ -4923,7 +4931,8 @@ static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
return; return;
pin = path->path[path->depth - 1]; pin = path->path[path->depth - 1];
restore_pin_ctl(codec, pin); restore_pin_ctl(codec, pin);
snd_hda_activate_path(codec, path, path->active, true); snd_hda_activate_path(codec, path, path->active,
aamix_default(codec->spec));
set_pin_eapd(codec, pin, path->active); set_pin_eapd(codec, pin, path->active);
} }
@ -4973,7 +4982,8 @@ static void init_multi_io(struct hda_codec *codec)
if (!spec->multi_io[i].ctl_in) if (!spec->multi_io[i].ctl_in)
spec->multi_io[i].ctl_in = spec->multi_io[i].ctl_in =
snd_hda_codec_get_pin_target(codec, pin); snd_hda_codec_get_pin_target(codec, pin);
snd_hda_activate_path(codec, path, path->active, true); snd_hda_activate_path(codec, path, path->active,
aamix_default(spec));
} }
} }