aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorWang Xingchao <xingchao.wang@linux.intel.com>2013-07-25 23:34:46 -0400
committerTakashi Iwai <tiwai@suse.de>2013-07-29 14:33:20 +0200
commit7d4f606c50ffaaa3ac60b7faf770dc6e84af3207 (patch)
treeb833c9ec23b4496a61e96d7887469c3bf47722af /sound/pci
parentALSA: hda - jack poll once if jackpoll_interval==0 (diff)
downloadlinux-dev-7d4f606c50ffaaa3ac60b7faf770dc6e84af3207.tar.xz
linux-dev-7d4f606c50ffaaa3ac60b7faf770dc6e84af3207.zip
ALSA: hda - WAKEEN feature enabling for runtime pm
With runtime power save feature enabled, Headphone hotplug event will not be detected while controller/codec in D3. HDA has feature WAKEEN to let codec wake up system if controller is in D3 or system in S3.(HDA Spec 4.5.9.2/3). Codec can send out INT or wake up controller depending on whether CIE or GIE enabled.(Figure 4, Interupt structure). The controller must be in RESET mode after enter runtime-suspend, otherwise it will not be waken up even if codec send out wake-up event. And STATESTS will be cleared after controller brought out of RESET mode. This patch only enable WAKEEN for runtime-suspend(Controller D3) mode, not for system S3 mode. with tool "evtest", Headphone hotplug events could be cought and reported successfully. [fixed an unused variable warning by tiwai] Signed-off-by: Wang Xingchao <xingchao.wang@linux.intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/hda_intel.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 3f16c4bafc1a..7f9e4062a8d7 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -2971,6 +2971,10 @@ static int azx_runtime_suspend(struct device *dev)
struct snd_card *card = dev_get_drvdata(dev);
struct azx *chip = card->private_data;
+ /* enable controller wake up event */
+ azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) |
+ STATESTS_INT_MASK);
+
azx_stop_chip(chip);
azx_enter_link_reset(chip);
azx_clear_irq_pending(chip);
@@ -2983,11 +2987,31 @@ static int azx_runtime_resume(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
struct azx *chip = card->private_data;
+ struct hda_bus *bus;
+ struct hda_codec *codec;
+ int status;
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
hda_display_power(true);
+
+ /* Read STATESTS before controller reset */
+ status = azx_readw(chip, STATESTS);
+
azx_init_pci(chip);
azx_init_chip(chip, 1);
+
+ bus = chip->bus;
+ if (status && bus) {
+ list_for_each_entry(codec, &bus->codec_list, list)
+ if (status & (1 << codec->addr))
+ queue_delayed_work(codec->bus->workq,
+ &codec->jackpoll_work, codec->jackpoll_interval);
+ }
+
+ /* disable controller Wake Up event*/
+ azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) &
+ ~STATESTS_INT_MASK);
+
return 0;
}