summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorSumit Bhattacharya <sumitb@nvidia.com>2011-06-14 20:16:13 +0530
committerNiket Sirsi <nsirsi@nvidia.com>2011-06-15 21:30:46 -0700
commitc242bcd738fa47f833822f618eff4dbff092bde7 (patch)
tree14f38883041a61227973efe24b4a1a9c8bef42c8 /sound
parente38ad73bcc26cd1352443bbadc18e39e613ecea6 (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')
-rw-r--r--sound/arm/tegra/hda_tegra.c71
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;