diff options
author | Sumit Bhattacharya <sumitb@nvidia.com> | 2011-06-14 20:16:13 +0530 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-07-12 19:00:37 -0700 |
commit | 6d4ce7d3005e652d5f90f729908969a5443d4603 (patch) | |
tree | 974a83e5dea948448edfe2362c2058107b428252 /drivers | |
parent | 83bbb54352fd7ab1a7d1689a0347d2a39d3eab2f (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.c | 51 |
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); |