diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-02-01 04:33:23 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-02-02 04:18:09 -0500 |
commit | e9d010c2e8f03952e67a6fd8aed0f0dc92084ccc (patch) | |
tree | ef54a3c768f43e761577dd67d682cc680865981a /sound/pci/hda/patch_via.c | |
parent | 924339239fd5ba3e505f9420d41f0939196f3530 (diff) |
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>
Diffstat (limited to 'sound/pci/hda/patch_via.c')
-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 de43cd92b0a5..79166fb8b074 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -199,6 +199,9 @@ struct via_spec { | |||
199 | unsigned int no_pin_power_ctl; | 199 | unsigned int no_pin_power_ctl; |
200 | enum VIA_HDA_CODEC codec_type; | 200 | enum VIA_HDA_CODEC codec_type; |
201 | 201 | ||
202 | /* analog low-power control */ | ||
203 | bool alc_mode; | ||
204 | |||
202 | /* smart51 setup */ | 205 | /* smart51 setup */ |
203 | unsigned int smart51_nums; | 206 | unsigned int smart51_nums; |
204 | hda_nid_t smart51_pins[2]; | 207 | hda_nid_t smart51_pins[2]; |
@@ -758,6 +761,7 @@ static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol, | |||
758 | return 0; | 761 | return 0; |
759 | spec->no_pin_power_ctl = val; | 762 | spec->no_pin_power_ctl = val; |
760 | set_widgets_power_state(codec); | 763 | set_widgets_power_state(codec); |
764 | analog_low_current_mode(codec); | ||
761 | return 1; | 765 | return 1; |
762 | } | 766 | } |
763 | 767 | ||
@@ -1045,13 +1049,19 @@ static bool is_aa_path_mute(struct hda_codec *codec) | |||
1045 | } | 1049 | } |
1046 | 1050 | ||
1047 | /* enter/exit analog low-current mode */ | 1051 | /* enter/exit analog low-current mode */ |
1048 | static void analog_low_current_mode(struct hda_codec *codec) | 1052 | static void __analog_low_current_mode(struct hda_codec *codec, bool force) |
1049 | { | 1053 | { |
1050 | struct via_spec *spec = codec->spec; | 1054 | struct via_spec *spec = codec->spec; |
1051 | bool enable; | 1055 | bool enable; |
1052 | unsigned int verb, parm; | 1056 | unsigned int verb, parm; |
1053 | 1057 | ||
1054 | enable = is_aa_path_mute(codec) && !spec->opened_streams; | 1058 | if (spec->no_pin_power_ctl) |
1059 | enable = false; | ||
1060 | else | ||
1061 | enable = is_aa_path_mute(codec) && !spec->opened_streams; | ||
1062 | if (enable == spec->alc_mode && !force) | ||
1063 | return; | ||
1064 | spec->alc_mode = enable; | ||
1055 | 1065 | ||
1056 | /* decide low current mode's verb & parameter */ | 1066 | /* decide low current mode's verb & parameter */ |
1057 | switch (spec->codec_type) { | 1067 | switch (spec->codec_type) { |
@@ -1083,6 +1093,11 @@ static void analog_low_current_mode(struct hda_codec *codec) | |||
1083 | snd_hda_codec_write(codec, codec->afg, 0, verb, parm); | 1093 | snd_hda_codec_write(codec, codec->afg, 0, verb, parm); |
1084 | } | 1094 | } |
1085 | 1095 | ||
1096 | static void analog_low_current_mode(struct hda_codec *codec) | ||
1097 | { | ||
1098 | return __analog_low_current_mode(codec, false); | ||
1099 | } | ||
1100 | |||
1086 | /* | 1101 | /* |
1087 | * generic initialization of ADC, input mixers and output mixers | 1102 | * generic initialization of ADC, input mixers and output mixers |
1088 | */ | 1103 | */ |
@@ -1508,10 +1523,6 @@ static int via_build_controls(struct hda_codec *codec) | |||
1508 | return err; | 1523 | return err; |
1509 | } | 1524 | } |
1510 | 1525 | ||
1511 | /* init power states */ | ||
1512 | set_widgets_power_state(codec); | ||
1513 | analog_low_current_mode(codec); | ||
1514 | |||
1515 | via_free_kctls(codec); /* no longer needed */ | 1526 | via_free_kctls(codec); /* no longer needed */ |
1516 | 1527 | ||
1517 | err = snd_hda_jack_add_kctls(codec, &spec->autocfg); | 1528 | err = snd_hda_jack_add_kctls(codec, &spec->autocfg); |
@@ -2782,6 +2793,10 @@ static int via_init(struct hda_codec *codec) | |||
2782 | for (i = 0; i < spec->num_iverbs; i++) | 2793 | for (i = 0; i < spec->num_iverbs; i++) |
2783 | snd_hda_sequence_write(codec, spec->init_verbs[i]); | 2794 | snd_hda_sequence_write(codec, spec->init_verbs[i]); |
2784 | 2795 | ||
2796 | /* init power states */ | ||
2797 | set_widgets_power_state(codec); | ||
2798 | __analog_low_current_mode(codec, true); | ||
2799 | |||
2785 | via_auto_init_multi_out(codec); | 2800 | via_auto_init_multi_out(codec); |
2786 | via_auto_init_hp_out(codec); | 2801 | via_auto_init_hp_out(codec); |
2787 | via_auto_init_speaker_out(codec); | 2802 | via_auto_init_speaker_out(codec); |