ALSA: hda - Allow analog low-current mode when dynamic power-control is on
VIA codecs have several different power-saving features, and one of them is the analog low-current mode. But it turned out that the ALC mode causes pop-noises at each on/off time on some machines. As a quick workaround, disable the ALC when another power-saving feature, the dynamic pin power-control, is turned off, too, since the dynamic power-control is already exposed as a mixer enum element so that user can turn it on/off freely. Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=741128 Cc: <stable@kernel.org> [v3.1+] Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
924339239f
commit
e9d010c2e8
@ -199,6 +199,9 @@ struct via_spec {
|
||||
unsigned int no_pin_power_ctl;
|
||||
enum VIA_HDA_CODEC codec_type;
|
||||
|
||||
/* analog low-power control */
|
||||
bool alc_mode;
|
||||
|
||||
/* smart51 setup */
|
||||
unsigned int smart51_nums;
|
||||
hda_nid_t smart51_pins[2];
|
||||
@ -758,6 +761,7 @@ static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol,
|
||||
return 0;
|
||||
spec->no_pin_power_ctl = val;
|
||||
set_widgets_power_state(codec);
|
||||
analog_low_current_mode(codec);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1045,13 +1049,19 @@ static bool is_aa_path_mute(struct hda_codec *codec)
|
||||
}
|
||||
|
||||
/* enter/exit analog low-current mode */
|
||||
static void analog_low_current_mode(struct hda_codec *codec)
|
||||
static void __analog_low_current_mode(struct hda_codec *codec, bool force)
|
||||
{
|
||||
struct via_spec *spec = codec->spec;
|
||||
bool enable;
|
||||
unsigned int verb, parm;
|
||||
|
||||
enable = is_aa_path_mute(codec) && !spec->opened_streams;
|
||||
if (spec->no_pin_power_ctl)
|
||||
enable = false;
|
||||
else
|
||||
enable = is_aa_path_mute(codec) && !spec->opened_streams;
|
||||
if (enable == spec->alc_mode && !force)
|
||||
return;
|
||||
spec->alc_mode = enable;
|
||||
|
||||
/* decide low current mode's verb & parameter */
|
||||
switch (spec->codec_type) {
|
||||
@ -1083,6 +1093,11 @@ static void analog_low_current_mode(struct hda_codec *codec)
|
||||
snd_hda_codec_write(codec, codec->afg, 0, verb, parm);
|
||||
}
|
||||
|
||||
static void analog_low_current_mode(struct hda_codec *codec)
|
||||
{
|
||||
return __analog_low_current_mode(codec, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* generic initialization of ADC, input mixers and output mixers
|
||||
*/
|
||||
@ -1508,10 +1523,6 @@ static int via_build_controls(struct hda_codec *codec)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* init power states */
|
||||
set_widgets_power_state(codec);
|
||||
analog_low_current_mode(codec);
|
||||
|
||||
via_free_kctls(codec); /* no longer needed */
|
||||
|
||||
err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
|
||||
@ -2782,6 +2793,10 @@ static int via_init(struct hda_codec *codec)
|
||||
for (i = 0; i < spec->num_iverbs; i++)
|
||||
snd_hda_sequence_write(codec, spec->init_verbs[i]);
|
||||
|
||||
/* init power states */
|
||||
set_widgets_power_state(codec);
|
||||
__analog_low_current_mode(codec, true);
|
||||
|
||||
via_auto_init_multi_out(codec);
|
||||
via_auto_init_hp_out(codec);
|
||||
via_auto_init_speaker_out(codec);
|
||||
|
Loading…
Reference in New Issue
Block a user