diff options
author | Sumit Bhattacharya <sumitb@nvidia.com> | 2011-11-28 13:41:25 +0530 |
---|---|---|
committer | Varun Wadekar <vwadekar@nvidia.com> | 2011-12-08 17:06:50 +0530 |
commit | 3dbacbbe26b577f88294e33af10caa8e5f526dec (patch) | |
tree | 898990915b0da24b1f20a69a43c18568d348374a /sound | |
parent | f60feca208e5ed75b9eafb52856212e88a454c54 (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.c | 47 |
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; } |