diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-02-01 10:33:23 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-13 11:16:51 -0800 |
commit | cb935a3a4ffa533491976365aa430ad9d586718f (patch) | |
tree | 0e5f8c6b1230a47420b12e29b81787fa407e38c2 /sound | |
parent | d0f03303d8a9c7c82856c50e6c7ea137c8ca7c83 (diff) |
ALSA: hda - Allow analog low-current mode when dynamic power-control is on
commit e9d010c2e8f03952e67a6fd8aed0f0dc92084ccc upstream.
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
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/patch_via.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 06845420f16..d2a477d54c0 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -198,6 +198,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]; @@ -748,6 +751,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; } @@ -1035,13 +1039,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) { @@ -1073,6 +1083,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 */ @@ -1498,10 +1513,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 */ return 0; } @@ -2771,6 +2782,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); |