summaryrefslogtreecommitdiff
path: root/sound/pci
diff options
context:
space:
mode:
authorMengdong Lin <mengdong.lin@intel.com>2013-06-24 10:18:54 -0400
committerTakashi Iwai <tiwai@suse.de>2013-06-24 10:06:04 +0200
commit3af3f356e16041c3353210214da601782e2cd8b4 (patch)
treedc9df197dc781f332c0e27a1df3e46e8530ba6b7 /sound/pci
parenta91c3fb2f84204dcf024ca6a032f12cdb84f2196 (diff)
ALSA: hda - reset hda link during system/runtime suspend
If all the codecs report ClkStopOK (OK to stop bus clock) after being put to D3, this patch will reset the HDA link before the controller is put to D3. So the link will be in reset during system or runtime suspend, the bus clock stops and the codecs are in D3(ClkStop) state. This may help to reduce power consumption by dozens of mW on some peripheral hda codecs. Signed-off-by: Mengdong Lin <mengdong.lin@intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/hda_intel.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index f089fa0aa03d..9f110c7ba092 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1120,6 +1120,20 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus,
struct snd_dma_buffer *dmab);
#endif
+/* enter link reset */
+static void azx_reset_link(struct azx *chip)
+{
+ unsigned long timeout;
+
+ /* reset controller */
+ azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET);
+
+ timeout = jiffies + msecs_to_jiffies(100);
+ while ((azx_readb(chip, GCTL) & ICH6_GCTL_RESET) &&
+ time_before(jiffies, timeout))
+ usleep_range(500, 1000);
+}
+
/* reset codec link */
static int azx_reset(struct azx *chip, int full_reset)
{
@@ -2894,6 +2908,7 @@ static int azx_suspend(struct device *dev)
if (chip->initialized)
snd_hda_suspend(chip->bus);
azx_stop_chip(chip);
+ azx_reset_link(chip);
if (chip->irq >= 0) {
free_irq(chip->irq, chip);
chip->irq = -1;
@@ -2946,6 +2961,7 @@ static int azx_runtime_suspend(struct device *dev)
struct azx *chip = card->private_data;
azx_stop_chip(chip);
+ azx_reset_link(chip);
azx_clear_irq_pending(chip);
return 0;
}