summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorSumit Bhattacharya <sumitb@nvidia.com>2011-11-28 13:41:25 +0530
committerVarun Wadekar <vwadekar@nvidia.com>2011-12-08 17:06:50 +0530
commit3dbacbbe26b577f88294e33af10caa8e5f526dec (patch)
tree898990915b0da24b1f20a69a43c18568d348374a /sound
parentf60feca208e5ed75b9eafb52856212e88a454c54 (diff)
ALSA: hda: Disable platform clocks when not required
Add support for disabling of platform driver clocks when HDA is idle to reduce HDA power consumption. Take care of enabling of HDA clocks before accessing any hardware register. Bug 904530 Change-Id: I51be7990e900cef3dac376d9635c48cd1ffbfa99 Signed-off-by: Sumit Bhattacharya <sumitb@nvidia.com> Reviewed-on: http://git-master/r/66886 Reviewed-by: Scott Peterson <speterson@nvidia.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_intel.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 7b7fc90b1f0c..cc32d89e8b03 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -441,6 +441,7 @@ struct azx {
/* platform driver clocks */
struct clk **platform_clks;
int platform_clk_count;
+ int platform_clk_enable;
#endif
/* locks */
@@ -1276,14 +1277,21 @@ static void azx_platform_enable_clocks(struct azx *chip)
for (i = 0; i < chip->platform_clk_count; i++)
clk_enable(chip->platform_clks[i]);
+
+ chip->platform_clk_enable++;
}
static void azx_platform_disable_clocks(struct azx *chip)
{
int i;
+ if (!chip->platform_clk_enable)
+ return;
+
for (i = 0; i < chip->platform_clk_count; i++)
clk_disable(chip->platform_clks[i]);
+
+ chip->platform_clk_enable--;
}
#endif /* CONFIG_SND_HDA_PLATFORM_DRIVER */
@@ -2374,11 +2382,19 @@ static void azx_power_notify(struct hda_bus *bus)
break;
}
}
- if (power_on)
+ if (power_on) {
+#ifdef CONFIG_SND_HDA_PLATFORM_DRIVER
+ azx_platform_enable_clocks(chip);
+#endif
azx_init_chip(chip, 1);
+ }
else if (chip->running && power_save_controller &&
- !bus->power_keep_link_on)
+ !bus->power_keep_link_on) {
azx_stop_chip(chip);
+#ifdef CONFIG_SND_HDA_PLATFORM_DRIVER
+ azx_platform_disable_clocks(chip);
+#endif
+ }
}
#endif /* CONFIG_SND_HDA_POWER_SAVE */
@@ -2403,6 +2419,12 @@ static int azx_suspend(struct azx *chip, pm_message_t state)
struct snd_card *card = chip->card;
int i;
+#if defined(CONFIG_SND_HDA_PLATFORM_DRIVER) && \
+ defined(CONFIG_SND_HDA_POWER_SAVE)
+ if (!chip->platform_clk_enable)
+ azx_platform_enable_clocks(chip);
+#endif
+
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
azx_clear_irq_pending(chip);
for (i = 0; i < HDA_MAX_PCMS; i++)
@@ -2472,6 +2494,13 @@ static int azx_resume(struct azx *chip)
snd_hda_resume(chip->bus);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+
+#if defined(CONFIG_SND_HDA_PLATFORM_DRIVER) && \
+ defined(CONFIG_SND_HDA_POWER_SAVE)
+ if (chip->pdev)
+ azx_platform_disable_clocks(chip);
+#endif
+
return 0;
}
@@ -2518,8 +2547,22 @@ static int azx_resume_platform(struct platform_device *pdev)
static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf)
{
struct azx *chip = container_of(nb, struct azx, reboot_notifier);
+
+#if defined(CONFIG_SND_HDA_PLATFORM_DRIVER) && \
+ defined(CONFIG_SND_HDA_POWER_SAVE)
+ if (chip->pdev)
+ azx_platform_enable_clocks(chip);
+#endif
+
snd_hda_bus_reboot_notify(chip->bus);
azx_stop_chip(chip);
+
+#if defined(CONFIG_SND_HDA_PLATFORM_DRIVER) && \
+ defined(CONFIG_SND_HDA_POWER_SAVE)
+ if (chip->pdev)
+ azx_platform_disable_clocks(chip);
+#endif
+
return NOTIFY_OK;
}