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:49:24 -0800
commita48e69c07ea71a84f87dd59b32cf514786f8d904 (patch)
tree05dbb3507880909c957a69b4495b709870485b26 /drivers/video/tegra/dc/hdmi.c
parent17b18864c4bef606799a907c5371191b7835f4ee (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> Rebase-Id: R35c55b5c492c15bb79c1b17e29fd6293f1764d3f
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 708d989b473d..8152aed3b82b 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 *hda2hdmicodec_clk;
spinlock_t suspend_lock;
bool suspended;
@@ -904,6 +907,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,
@@ -967,6 +993,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))
@@ -990,6 +1024,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->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);
@@ -1432,6 +1471,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);
@@ -1627,6 +1673,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;