Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Wang Xingchao and committed by
Takashi Iwai
7d4f606c 18e60627

+24
+24
sound/pci/hda/hda_intel.c
··· 2971 2971 struct snd_card *card = dev_get_drvdata(dev); 2972 2972 struct azx *chip = card->private_data; 2973 2973 2974 + /* enable controller wake up event */ 2975 + azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) | 2976 + STATESTS_INT_MASK); 2977 + 2974 2978 azx_stop_chip(chip); 2975 2979 azx_enter_link_reset(chip); 2976 2980 azx_clear_irq_pending(chip); ··· 2987 2983 { 2988 2984 struct snd_card *card = dev_get_drvdata(dev); 2989 2985 struct azx *chip = card->private_data; 2986 + struct hda_bus *bus; 2987 + struct hda_codec *codec; 2988 + int status; 2990 2989 2991 2990 if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) 2992 2991 hda_display_power(true); 2992 + 2993 + /* Read STATESTS before controller reset */ 2994 + status = azx_readw(chip, STATESTS); 2995 + 2993 2996 azx_init_pci(chip); 2994 2997 azx_init_chip(chip, 1); 2998 + 2999 + bus = chip->bus; 3000 + if (status && bus) { 3001 + list_for_each_entry(codec, &bus->codec_list, list) 3002 + if (status & (1 << codec->addr)) 3003 + queue_delayed_work(codec->bus->workq, 3004 + &codec->jackpoll_work, codec->jackpoll_interval); 3005 + } 3006 + 3007 + /* disable controller Wake Up event*/ 3008 + azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) & 3009 + ~STATESTS_INT_MASK); 3010 + 2995 3011 return 0; 2996 3012 } 2997 3013