diff options
author | Takashi Iwai <tiwai@suse.de> | 2010-07-05 10:50:13 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-07-09 02:42:29 -0400 |
commit | ac0547dc62e67a3e0b0c1628b6e49efba8f517db (patch) | |
tree | dafd1c8283cc09c3eda5d8fc2a1d06ffeb0141c8 /sound/pci/hda/hda_codec.c | |
parent | f189efcd1cc06b75fe18642c9751d26aa5ed2b54 (diff) |
ALSA: hda - Restore cleared pin controls on resume
Many codecs now clear the pin controls at suspend via snd_hda_shutup_pins()
for reducing the click noise at power-off. But this leaves some pins
uninitialized, and they'll be never recovered after resume.
This patch adds the proper recovery of cleared pin controls on resume.
Also it adds a check of bus->shutdown so that pins won't be cleared at
module unloading.
Reference: Kernel bug 16339
http://bugzilla.kernel.org/show_bug.cgi?id=16339
Cc: <stable@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index a3d638c8c1fd..ba2098d20ccc 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -784,6 +784,9 @@ static int read_pin_defaults(struct hda_codec *codec) | |||
784 | pin->nid = nid; | 784 | pin->nid = nid; |
785 | pin->cfg = snd_hda_codec_read(codec, nid, 0, | 785 | pin->cfg = snd_hda_codec_read(codec, nid, 0, |
786 | AC_VERB_GET_CONFIG_DEFAULT, 0); | 786 | AC_VERB_GET_CONFIG_DEFAULT, 0); |
787 | pin->ctrl = snd_hda_codec_read(codec, nid, 0, | ||
788 | AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
789 | 0); | ||
787 | } | 790 | } |
788 | return 0; | 791 | return 0; |
789 | } | 792 | } |
@@ -912,15 +915,38 @@ static void restore_pincfgs(struct hda_codec *codec) | |||
912 | void snd_hda_shutup_pins(struct hda_codec *codec) | 915 | void snd_hda_shutup_pins(struct hda_codec *codec) |
913 | { | 916 | { |
914 | int i; | 917 | int i; |
918 | /* don't shut up pins when unloading the driver; otherwise it breaks | ||
919 | * the default pin setup at the next load of the driver | ||
920 | */ | ||
921 | if (codec->bus->shutdown) | ||
922 | return; | ||
915 | for (i = 0; i < codec->init_pins.used; i++) { | 923 | for (i = 0; i < codec->init_pins.used; i++) { |
916 | struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); | 924 | struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); |
917 | /* use read here for syncing after issuing each verb */ | 925 | /* use read here for syncing after issuing each verb */ |
918 | snd_hda_codec_read(codec, pin->nid, 0, | 926 | snd_hda_codec_read(codec, pin->nid, 0, |
919 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0); | 927 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0); |
920 | } | 928 | } |
929 | codec->pins_shutup = 1; | ||
921 | } | 930 | } |
922 | EXPORT_SYMBOL_HDA(snd_hda_shutup_pins); | 931 | EXPORT_SYMBOL_HDA(snd_hda_shutup_pins); |
923 | 932 | ||
933 | /* Restore the pin controls cleared previously via snd_hda_shutup_pins() */ | ||
934 | static void restore_shutup_pins(struct hda_codec *codec) | ||
935 | { | ||
936 | int i; | ||
937 | if (!codec->pins_shutup) | ||
938 | return; | ||
939 | if (codec->bus->shutdown) | ||
940 | return; | ||
941 | for (i = 0; i < codec->init_pins.used; i++) { | ||
942 | struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); | ||
943 | snd_hda_codec_write(codec, pin->nid, 0, | ||
944 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
945 | pin->ctrl); | ||
946 | } | ||
947 | codec->pins_shutup = 0; | ||
948 | } | ||
949 | |||
924 | static void init_hda_cache(struct hda_cache_rec *cache, | 950 | static void init_hda_cache(struct hda_cache_rec *cache, |
925 | unsigned int record_size); | 951 | unsigned int record_size); |
926 | static void free_hda_cache(struct hda_cache_rec *cache); | 952 | static void free_hda_cache(struct hda_cache_rec *cache); |
@@ -2907,6 +2933,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) | |||
2907 | codec->afg ? codec->afg : codec->mfg, | 2933 | codec->afg ? codec->afg : codec->mfg, |
2908 | AC_PWRST_D0); | 2934 | AC_PWRST_D0); |
2909 | restore_pincfgs(codec); /* restore all current pin configs */ | 2935 | restore_pincfgs(codec); /* restore all current pin configs */ |
2936 | restore_shutup_pins(codec); | ||
2910 | hda_exec_init_verbs(codec); | 2937 | hda_exec_init_verbs(codec); |
2911 | if (codec->patch_ops.resume) | 2938 | if (codec->patch_ops.resume) |
2912 | codec->patch_ops.resume(codec); | 2939 | codec->patch_ops.resume(codec); |