diff options
author | Sumit Bhattacharya <sumitb@nvidia.com> | 2011-10-13 16:12:38 +0530 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-10-13 18:44:04 -0700 |
commit | ec6673c1d2021df64e3920cc9c6a06e52e9ffbcb (patch) | |
tree | e964005e6322c3044779facbf6252b77346c237d | |
parent | 0ff8d8639ea85f86bc1c356d1c5b1cbe1a90aab3 (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.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 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; |