aboutsummaryrefslogtreecommitdiffstats
path: root/sound
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
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')
-rw-r--r--sound/pci/hda/hda_codec.c27
-rw-r--r--sound/pci/hda/hda_codec.h5
2 files changed, 31 insertions, 1 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);
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 49e939e7e5cd..5991d14e1ec0 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -821,6 +821,7 @@ struct hda_codec {
821 unsigned int pin_amp_workaround:1; /* pin out-amp takes index 821 unsigned int pin_amp_workaround:1; /* pin out-amp takes index
822 * (e.g. Conexant codecs) 822 * (e.g. Conexant codecs)
823 */ 823 */
824 unsigned int pins_shutup:1; /* pins are shut up */
824 unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ 825 unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
825#ifdef CONFIG_SND_HDA_POWER_SAVE 826#ifdef CONFIG_SND_HDA_POWER_SAVE
826 unsigned int power_on :1; /* current (global) power-state */ 827 unsigned int power_on :1; /* current (global) power-state */
@@ -897,7 +898,9 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec);
897/* the struct for codec->pin_configs */ 898/* the struct for codec->pin_configs */
898struct hda_pincfg { 899struct hda_pincfg {
899 hda_nid_t nid; 900 hda_nid_t nid;
900 unsigned int cfg; 901 unsigned char ctrl; /* current pin control value */
902 unsigned char pad; /* reserved */
903 unsigned int cfg; /* default configuration */
901}; 904};
902 905
903unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid); 906unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid);