diff options
author | Min-wuk Lee <mlee@nvidia.com> | 2013-09-06 17:43:06 +0900 |
---|---|---|
committer | Gabby Lee <galee@nvidia.com> | 2013-09-10 19:02:19 -0700 |
commit | 8a2f117c4472919ec22263c858fbac1a91ee5e72 (patch) | |
tree | 5b3c24ad96831464848e70d253e59238cf17d58c | |
parent | edf22c31968ec0658e1315f9c6d468f3961c9e1e (diff) |
tegra: video: hdmi: WAR: ensure hdcp register access with clk enabled
There is a race condition between hdcp upstream and hdmi disable
during suspend/resume stress with hdmi plugged-in. WAR by making
host1x/hdmi clk enabled and hdmi clk out of reset.
Bug 1349507
Change-Id: I6870066358900d6f6798b3e20bc59bf5645f25b8
Original-author: Roger Hsieh <rhsieh@nvidia.com>
Signed-off-by: Roger Hsieh <rhsieh@nvidia.com>
Signed-off-by: Min-wuk Lee <mlee@nvidia.com>
Reviewed-on: http://git-master/r/271389
GVS: Gerrit_Virtual_Submit
Reviewed-by: Gabby Lee <galee@nvidia.com>
Tested-by: Gabby Lee <galee@nvidia.com>
-rw-r--r-- | drivers/video/tegra/dc/hdmi.c | 38 | ||||
-rw-r--r-- | security/tf_driver/tf_device.c | 5 |
2 files changed, 39 insertions, 4 deletions
diff --git a/drivers/video/tegra/dc/hdmi.c b/drivers/video/tegra/dc/hdmi.c index ccce7c707f35..0f98cd75acaa 100644 --- a/drivers/video/tegra/dc/hdmi.c +++ b/drivers/video/tegra/dc/hdmi.c @@ -109,6 +109,7 @@ struct tegra_dc_hdmi_data { }; struct tegra_dc_hdmi_data *dc_hdmi; +atomic_t __maybe_unused tf_hdmi_enable = ATOMIC_INIT(0); #if defined(CONFIG_ARCH_TEGRA_3x_SOC) const struct tmds_config tmds_config[] = { @@ -470,6 +471,34 @@ static inline void tegra_hdmi_hotplug_enable(struct tegra_dc_hdmi_data *hdmi) enable_irq(gpio_to_irq(dc->out->hotplug_gpio)); } +void tegra_hdmi_enable_clk(void) +{ + struct tegra_dc_hdmi_data *hdmi = dc_hdmi; + struct tegra_dc *dc = hdmi->dc; + + mutex_lock(&dc->lock); + clk_prepare_enable(hdmi->disp1_clk); + clk_prepare_enable(hdmi->disp2_clk); + clk_prepare_enable(hdmi->clk); + mutex_unlock(&dc->lock); + atomic_set(&tf_hdmi_enable, 1); +} +EXPORT_SYMBOL(tegra_hdmi_enable_clk); + +void tegra_hdmi_disable_clk(void) +{ + struct tegra_dc_hdmi_data *hdmi = dc_hdmi; + struct tegra_dc *dc = hdmi->dc; + + atomic_set(&tf_hdmi_enable, 0); + mutex_lock(&dc->lock); + clk_disable_unprepare(hdmi->clk); + clk_disable_unprepare(hdmi->disp1_clk); + clk_disable_unprepare(hdmi->disp2_clk); + mutex_unlock(&dc->lock); + +} +EXPORT_SYMBOL(tegra_hdmi_disable_clk); #ifdef CONFIG_DEBUG_FS static int dbg_hdmi_show(struct seq_file *m, void *unused) @@ -1840,9 +1869,11 @@ static void tegra_dc_hdmi_enable(struct tegra_dc *dc) clk_set_rate(hdmi->clk, dc->mode.pclk); clk_prepare_enable(hdmi->clk); - tegra_periph_reset_assert(hdmi->clk); - mdelay(1); - tegra_periph_reset_deassert(hdmi->clk); + if (!atomic_read(&tf_hdmi_enable)) { + tegra_periph_reset_assert(hdmi->clk); + mdelay(1); + tegra_periph_reset_deassert(hdmi->clk); + } /* TODO: copy HDCP keys from KFUSE to HDMI */ @@ -2059,7 +2090,6 @@ static void tegra_dc_hdmi_disable(struct tegra_dc *dc) clk_disable_unprepare(hdmi->hda2codec_clk); clk_disable_unprepare(hdmi->hda_clk); #endif - tegra_periph_reset_assert(hdmi->clk); hdmi->clk_enabled = false; clk_disable_unprepare(hdmi->clk); tegra_dvfs_set_rate(hdmi->clk, 0); diff --git a/security/tf_driver/tf_device.c b/security/tf_driver/tf_device.c index 70d6a70a6244..3a10acf93b1f 100644 --- a/security/tf_driver/tf_device.c +++ b/security/tf_driver/tf_device.c @@ -55,6 +55,9 @@ * Forward Declarations *----------------------------------------------------------------------------*/ +extern void tegra_hdmi_enable_clk(void); +extern void tegra_hdmi_disable_clk(void); + /* * Creates and registers the device to be managed by the specified driver. * @@ -743,10 +746,12 @@ static long tf_device_ioctl(struct file *file, unsigned int ioctl_num, break; case TF_MESSAGE_TYPE_INVOKE_CLIENT_COMMAND: + tegra_hdmi_enable_clk(); trace_invoke_client_command(NVSEC_INVOKE_CMD_START); result = tf_invoke_client_command(connection, &command, &answer); trace_invoke_client_command(NVSEC_INVOKE_CMD_DONE); + tegra_hdmi_disable_clk(); break; case TF_MESSAGE_TYPE_CANCEL_CLIENT_COMMAND: |