aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_codec.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-07-05 10:50:13 -0400
committerTakashi Iwai <tiwai@suse.de>2010-07-09 02:42:29 -0400
commitac0547dc62e67a3e0b0c1628b6e49efba8f517db (patch)
treedafd1c8283cc09c3eda5d8fc2a1d06ffeb0141c8 /sound/pci/hda/hda_codec.c
parentf189efcd1cc06b75fe18642c9751d26aa5ed2b54 (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.c27
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)
912void snd_hda_shutup_pins(struct hda_codec *codec) 915void 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}
922EXPORT_SYMBOL_HDA(snd_hda_shutup_pins); 931EXPORT_SYMBOL_HDA(snd_hda_shutup_pins);
923 932
933/* Restore the pin controls cleared previously via snd_hda_shutup_pins() */
934static 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
924static void init_hda_cache(struct hda_cache_rec *cache, 950static void init_hda_cache(struct hda_cache_rec *cache,
925 unsigned int record_size); 951 unsigned int record_size);
926static void free_hda_cache(struct hda_cache_rec *cache); 952static 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);