From 3dbacbbe26b577f88294e33af10caa8e5f526dec Mon Sep 17 00:00:00 2001 From: Sumit Bhattacharya Date: Mon, 28 Nov 2011 13:41:25 +0530 Subject: 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 Reviewed-on: http://git-master/r/66886 Reviewed-by: Scott Peterson --- sound/pci/hda/hda_intel.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) (limited to 'sound/pci/hda') 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; } -- cgit v1.2.3