summaryrefslogtreecommitdiff
path: root/drivers
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 /drivers
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 'drivers')
-rw-r--r--drivers/video/tegra/dc/hdmi.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/video/tegra/dc/hdmi.c b/drivers/video/tegra/dc/hdmi.c
index adea17677283..c4a1ed28ec88 100644
--- a/drivers/video/tegra/dc/hdmi.c
+++ b/drivers/video/tegra/dc/hdmi.c
@@ -77,6 +77,9 @@ struct tegra_dc_hdmi_data {
struct clk *disp1_clk;
struct clk *disp2_clk;
+ struct clk *hda_clk;
+ struct clk *hda2codec_clk;
+ struct clk *hda2hdmicodec_clk;
struct switch_dev hpd_switch;
@@ -867,6 +870,29 @@ static int tegra_dc_hdmi_init(struct tegra_dc *dc)
goto err_put_clock;
}
+#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
+ hdmi->hda_clk = clk_get_sys("hda", NULL);
+ if (IS_ERR_OR_NULL(hdmi->hda_clk)) {
+ dev_err(&dc->ndev->dev, "hdmi: can't get hda clock\n");
+ err = -ENOENT;
+ goto err_put_clock;
+ }
+
+ hdmi->hda2codec_clk = clk_get_sys("hda2codec_2x", NULL);
+ if (IS_ERR_OR_NULL(hdmi->hda2codec_clk)) {
+ dev_err(&dc->ndev->dev, "hdmi: can't get hda2codec clock\n");
+ err = -ENOENT;
+ goto err_put_clock;
+ }
+
+ hdmi->hda2hdmicodec_clk = clk_get_sys("hda2hdmi", NULL);
+ if (IS_ERR_OR_NULL(hdmi->hda2hdmicodec_clk)) {
+ dev_err(&dc->ndev->dev, "hdmi: can't get hda2hdmi clock\n");
+ err = -ENOENT;
+ goto err_put_clock;
+ }
+#endif
+
/* TODO: support non-hotplug */
if (request_irq(gpio_to_irq(dc->out->hotplug_gpio), tegra_dc_hdmi_irq,
IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
@@ -934,6 +960,14 @@ err_edid_destroy:
err_free_irq:
free_irq(gpio_to_irq(dc->out->hotplug_gpio), dc);
err_put_clock:
+#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
+ if (!IS_ERR_OR_NULL(hdmi->hda2hdmicodec_clk))
+ clk_put(hdmi->hda2hdmicodec_clk);
+ if (!IS_ERR_OR_NULL(hdmi->hda2codec_clk))
+ clk_put(hdmi->hda2codec_clk);
+ if (!IS_ERR_OR_NULL(hdmi->hda_clk))
+ clk_put(hdmi->hda_clk);
+#endif
if (!IS_ERR_OR_NULL(disp2_clk))
clk_put(disp2_clk);
if (!IS_ERR_OR_NULL(disp1_clk))
@@ -958,6 +992,11 @@ static void tegra_dc_hdmi_destroy(struct tegra_dc *dc)
switch_dev_unregister(&hdmi->hpd_switch);
iounmap(hdmi->base);
release_resource(hdmi->base_res);
+#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
+ clk_put(hdmi->hda2hdmicodec_clk);
+ clk_put(hdmi->hda2codec_clk);
+ clk_put(hdmi->hda_clk);
+#endif
clk_put(hdmi->clk);
clk_put(hdmi->disp1_clk);
clk_put(hdmi->disp2_clk);
@@ -1397,6 +1436,13 @@ static void tegra_dc_hdmi_enable(struct tegra_dc *dc)
clk_enable(hdmi->disp1_clk);
clk_enable(hdmi->disp2_clk);
+#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
+ /* Enabling HDA clocks before asserting HDA PD and ELDV bits */
+ clk_enable(hdmi->hda_clk);
+ clk_enable(hdmi->hda2codec_clk);
+ clk_enable(hdmi->hda2hdmicodec_clk);
+#endif
+
/* back off multiplier before attaching to parent at new rate. */
oldrate = clk_get_rate(hdmi->clk);
clk_set_rate(hdmi->clk, oldrate / 2);
@@ -1592,6 +1638,11 @@ static void tegra_dc_hdmi_disable(struct tegra_dc *dc)
#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE_0);
+ // sleep 1ms before disabling clocks to ensure HDA gets the interrupt
+ msleep(1);
+ clk_disable(hdmi->hda2hdmicodec_clk);
+ clk_disable(hdmi->hda2codec_clk);
+ clk_disable(hdmi->hda_clk);
#endif
hdmi->eld_retrieved = false;
tegra_periph_reset_assert(hdmi->clk);