summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSumit Bhattacharya <sumitb@nvidia.com>2011-10-13 16:12:38 +0530
committerVarun Colbert <vcolbert@nvidia.com>2011-10-13 18:44:04 -0700
commitec6673c1d2021df64e3920cc9c6a06e52e9ffbcb (patch)
treee964005e6322c3044779facbf6252b77346c237d
parent0ff8d8639ea85f86bc1c356d1c5b1cbe1a90aab3 (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: I975daa1621098eea2175244ce5774312bc396649 Signed-off-by: Sumit Bhattacharya <sumitb@nvidia.com> Reviewed-on: http://git-master/r/57846 Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Tested-by: Varun Colbert <vcolbert@nvidia.com>
-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 ab76f3ee6792..abac83b8f021 100644
--- a/drivers/video/tegra/dc/hdmi.c
+++ b/drivers/video/tegra/dc/hdmi.c
@@ -79,6 +79,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;
#ifdef CONFIG_SWITCH
struct switch_dev hpd_switch;
@@ -918,6 +921,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,
@@ -986,6 +1012,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))
@@ -1012,6 +1046,11 @@ static void tegra_dc_hdmi_destroy(struct tegra_dc *dc)
#endif
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);
@@ -1454,6 +1493,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);
@@ -1649,6 +1695,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
tegra_periph_reset_assert(hdmi->clk);
hdmi->clk_enabled = false;