diff options
author | Sumit Bhattacharya <sumitb@nvidia.com> | 2011-06-14 20:16:13 +0530 |
---|---|---|
committer | Niket Sirsi <nsirsi@nvidia.com> | 2011-06-15 21:30:46 -0700 |
commit | c242bcd738fa47f833822f618eff4dbff092bde7 (patch) | |
tree | 14f38883041a61227973efe24b4a1a9c8bef42c8 /sound/arm | |
parent | e38ad73bcc26cd1352443bbadc18e39e613ecea6 (diff) |
arm: tegra: disable HDA clocks while not in use
Disable HDA related clocks when device is not connected
to HDMI. HDA clocks will be enabled from HDMI driver when
HDMI device is hot plugged.
Bug 820213
Change-Id: I4e6839aab0dc5277b11c415cbb495766f72442b8
Reviewed-on: http://git-master/r/36517
Tested-by: Sumit Bhattacharya <sumitb@nvidia.com>
Reviewed-by: Niranjan Wartikar <nwartikar@nvidia.com>
Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
Reviewed-by: Scott Peterson <speterson@nvidia.com>
Diffstat (limited to 'sound/arm')
-rw-r--r-- | sound/arm/tegra/hda_tegra.c | 71 |
1 files changed, 41 insertions, 30 deletions
diff --git a/sound/arm/tegra/hda_tegra.c b/sound/arm/tegra/hda_tegra.c index af1c26c25fca..e43765323ef4 100644 --- a/sound/arm/tegra/hda_tegra.c +++ b/sound/arm/tegra/hda_tegra.c @@ -53,6 +53,7 @@ static int enable_msi; /* Module clock info */ static struct clk *clk_hda, *clk_hda2codec , *clk_hda2hdmicodec; +static bool is_hda_clk_on = false; #ifdef CONFIG_SND_HDA_PATCH_LOADER static char *patch[SNDRV_CARDS]; @@ -448,6 +449,21 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, return 0; } +static void nv_tegra_enable_hda_clks(bool on) +{ + if (on && !is_hda_clk_on) { + clk_enable(clk_hda); + clk_enable(clk_hda2codec); + clk_enable(clk_hda2hdmicodec); + } + else if (!on && is_hda_clk_on) { + clk_disable(clk_hda2hdmicodec); + clk_disable(clk_hda2codec); + clk_disable(clk_hda); + } + is_hda_clk_on = on; +} + #ifdef CONFIG_SND_HDA_POWER_SAVE /* power-up/down the controller */ void azx_power_notify(struct hda_bus *bus) @@ -462,11 +478,18 @@ void azx_power_notify(struct hda_bus *bus) break; } } - if (power_on) + + if (power_on) { + nv_tegra_enable_hda_clks(true); azx_init_chip(chip, 1); - else if (chip->running && power_save_controller && - !bus->power_keep_link_on) - azx_stop_chip(chip); + } + else { + if (chip->running && power_save_controller && + !bus->power_keep_link_on) + azx_stop_chip(chip); + + nv_tegra_enable_hda_clks(false); + } } #endif /* CONFIG_SND_HDA_POWER_SAVE */ @@ -475,15 +498,6 @@ void azx_power_notify(struct hda_bus *bus) /* * power management */ -static int nv_tegra_hda_controller_suspend(struct platform_device *pdev) -{ - clk_disable(clk_hda2hdmicodec); - clk_disable(clk_hda2codec); - clk_disable(clk_hda); - - return 0; -} - static int nv_tegra_azx_suspend(struct platform_device *pdev, pm_message_t state) { @@ -491,26 +505,23 @@ static int nv_tegra_azx_suspend(struct platform_device *pdev, struct azx *chip = card->private_data; int i; + nv_tegra_enable_hda_clks(true); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); azx_clear_irq_pending(chip); for (i = 0; i < HDA_MAX_PCMS; i++) snd_pcm_suspend_all(chip->pcm[i]); if (chip->initialized) snd_hda_suspend(chip->bus); - azx_stop_chip(chip); + + if (!chip->bus->power_keep_link_on) + azx_stop_chip(chip); + if (chip->irq >= 0) { free_irq(chip->irq, chip); chip->irq = -1; } - return nv_tegra_hda_controller_suspend(pdev); -} - -static int nv_tegra_hda_controller_resume(struct platform_device *pdev) -{ - clk_enable(clk_hda); - clk_enable(clk_hda2codec); - clk_enable(clk_hda2hdmicodec); + nv_tegra_enable_hda_clks(false); return 0; } @@ -519,21 +530,22 @@ static int nv_tegra_azx_resume(struct platform_device *pdev) { struct snd_card *card = dev_get_drvdata(&pdev->dev); struct azx *chip = card->private_data; - int rc; - rc = nv_tegra_hda_controller_resume(pdev); - if (rc) - return rc; + nv_tegra_enable_hda_clks(true); chip->msi = 0; if (azx_acquire_irq(chip, 1) < 0) return -EIO; - if (snd_hda_codecs_inuse(chip->bus)) + if (snd_hda_codecs_inuse(chip->bus) || chip->bus->power_keep_link_on) azx_init_chip(chip, 1); snd_hda_resume(chip->bus); snd_power_change_state(card, SNDRV_CTL_POWER_D0); + + if (!snd_hda_codecs_inuse(chip->bus)) + nv_tegra_enable_hda_clks(false); + return 0; } @@ -783,9 +795,8 @@ static int nv_tegra_hda_controller_init(struct platform_device *pdev) snd_printk(KERN_ERR T30SFX "%s: can't get hda clock\n", __func__); return -1; } - clk_enable(clk_hda); - clk_enable(clk_hda2codec); - clk_enable(clk_hda2hdmicodec); + nv_tegra_enable_hda_clks(true); + /*Enable the PCI access */ temp = readl(hda_reg + IPFS_HDA_CONFIGURATION_0); temp |= IPFS_EN_FPCI; |