summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorSumit Bhattacharya <sumitb@nvidia.com>2011-06-14 20:16:13 +0530
committerVarun Colbert <vcolbert@nvidia.com>2011-07-12 19:00:37 -0700
commit6d4ce7d3005e652d5f90f729908969a5443d4603 (patch)
tree974a83e5dea948448edfe2362c2058107b428252 /sound
parent83bbb54352fd7ab1a7d1689a0347d2a39d3eab2f (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. Also register a reboot notifier so that HDA clocks can be enabled during device reboot since HDA driver needs to stop the azx chip during reboot. Bug 820213 Change-Id: Ib962ac418edf25c5681f108b9a80577dc55c42af Reviewed-on: http://git-master/r/40543 Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Tested-by: Varun Colbert <vcolbert@nvidia.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/arm/tegra/hda_tegra.c73
-rw-r--r--sound/pci/hda/hda_codec.c2
-rw-r--r--sound/pci/hda/patch_nvhdmi.c10
3 files changed, 54 insertions, 31 deletions
diff --git a/sound/arm/tegra/hda_tegra.c b/sound/arm/tegra/hda_tegra.c
index af1c26c25fca..63d207fd2980 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,23 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
return 0;
}
+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);
+ msleep(1);
+ }
+ else if (!on && is_hda_clk_on) {
+ msleep(1);
+ 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 +480,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 +500,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 +507,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 +532,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 +797,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;
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index c23e30237ce8..a9be0c0bfd30 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -4137,7 +4137,7 @@ void snd_hda_bus_reboot_notify(struct hda_bus *bus)
return;
list_for_each_entry(codec, &bus->codec_list, list) {
#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!codec->power_on)
+ if (!codec->power_on && !bus->power_keep_link_on)
continue;
#endif
if (codec->patch_ops.reboot_notify)
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
index fafd054955cb..ac4bff538c44 100644
--- a/sound/pci/hda/patch_nvhdmi.c
+++ b/sound/pci/hda/patch_nvhdmi.c
@@ -37,6 +37,8 @@
#include "patch_hdmi.c"
+extern void nv_tegra_enable_hda_clks(bool on);
+
static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = {
"NVIDIA HDMI",
};
@@ -159,6 +161,11 @@ static void nvhdmi_free(struct hda_codec *codec)
kfree(spec);
}
+static void nvhdmi_shutup(struct hda_codec *codec)
+{
+ nv_tegra_enable_hda_clks(true);
+}
+
/*
* Digital out
*/
@@ -457,6 +464,7 @@ static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = {
.init = nvhdmi_init,
.free = nvhdmi_free,
.unsol_event = hdmi_unsol_event,
+ .reboot_notify = nvhdmi_shutup,
};
static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
@@ -464,6 +472,7 @@ static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
.build_pcms = nvhdmi_build_pcms_8ch_7x,
.init = nvhdmi_init,
.free = nvhdmi_free,
+ .reboot_notify = nvhdmi_shutup,
};
static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
@@ -471,6 +480,7 @@ static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
.build_pcms = nvhdmi_build_pcms_2ch,
.init = nvhdmi_init,
.free = nvhdmi_free,
+ .reboot_notify = nvhdmi_shutup,
};
static int patch_nvhdmi_8ch_89(struct hda_codec *codec)