summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/dc/hdmi.c
diff options
context:
space:
mode:
authorSumit Bhattacharya <sumitb@nvidia.com>2011-10-13 16:12:38 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:50:26 -0800
commit1dfa9d43eb95b274b6fe5330fbba03155d494767 (patch)
tree498872a25b977592cb7a18bd5960aa4b4b54ffb2 /drivers/video/tegra/dc/hdmi.c
parentf40bbfd0bd35f1f52d9c97e22791f860d0f304cd (diff)
video: tegra: Add HDA clock management
Add code to manage HDA related clocks from HDMI driver. When no HDMI device is connected to device HDA clocks are disabled to save power. Whenever HDMI hot plug in happend HDMI driver needs to enable these clocks before setting HDA presense bit so that HDA controller recieves the interrupt. Bug 862023 Change-Id: If62113ad2c71657419056000f5dfe363762bd697 Signed-off-by: Sumit Bhattacharya <sumitb@nvidia.com> Reviewed-on: http://git-master/r/66091 Reviewed-by: Scott Peterson <speterson@nvidia.com> Reviewed-by: Jon Mayo <jmayo@nvidia.com> Rebase-Id: R7367eac67b14907effdee571cd71a04b81b6945e
Diffstat (limited to 'drivers/video/tegra/dc/hdmi.c')
-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 39b5d0272624..720755c8a01e 100644
--- a/drivers/video/tegra/dc/hdmi.c
+++ b/drivers/video/tegra/dc/hdmi.c
@@ -76,6 +76,9 @@ struct tegra_dc_hdmi_data {
struct clk *disp1_clk;
struct clk *disp2_clk;
+ struct clk *hda_clk;
+ struct clk *hda2codec_clk;
+ struct clk *hda2hdmi_clk;
spinlock_t suspend_lock;
bool suspended;
@@ -949,6 +952,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("tegra30-hda", "hda");
+ 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("tegra30-hda", "hda2codec");
+ 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->hda2hdmi_clk = clk_get_sys("tegra30-hda", "hda2hdmi");
+ if (IS_ERR_OR_NULL(hdmi->hda2hdmi_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,
@@ -1012,6 +1038,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->hda2hdmi_clk))
+ clk_put(hdmi->hda2hdmi_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))
@@ -1035,6 +1069,11 @@ static void tegra_dc_hdmi_destroy(struct tegra_dc *dc)
cancel_delayed_work_sync(&hdmi->work);
iounmap(hdmi->base);
release_resource(hdmi->base_res);
+#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
+ clk_put(hdmi->hda2hdmi_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);
@@ -1477,6 +1516,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->hda2hdmi_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);
@@ -1672,6 +1718,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->hda2hdmi_clk);
+ clk_disable(hdmi->hda2codec_clk);
+ clk_disable(hdmi->hda_clk);
#endif
tegra_periph_reset_assert(hdmi->clk);
hdmi->clk_enabled = false;