summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Mayo <jmayo@nvidia.com>2013-06-04 13:50:12 -0700
committerMatthew Pedro <mapedro@nvidia.com>2013-07-11 12:27:50 -0700
commit4d7ee9988ffaf7addd462285544dd4ef78bc0c7c (patch)
tree5fa8cc6f8744cec240902a7dea6b612018214b7d
parentf730ab83fd4797d30a0414d1cd7762591cf031df (diff)
video: tegra: dc: hdmi: defer resume regulator enable
On suspend/resume, defer the blocking regulator enable. Place this slow path in the dedicated hotplug thread. bug 1299936 bug 1294872 Change-Id: I61a835c2c37dcae47697482e0023b68684ff19dc Signed-off-by: Jon Mayo <jmayo@nvidia.com> Reviewed-on: http://git-master/r/239058 (cherry picked from commit 6e789c76d47a6e144868d1e33f9d79b7fc58405d) Reviewed-on: http://git-master/r/247365 Tested-by: Jong Kim <jongk@nvidia.com> Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Matthew Pedro <mapedro@nvidia.com> Tested-by: Matthew Pedro <mapedro@nvidia.com>
-rw-r--r--drivers/video/tegra/dc/dc.c14
-rw-r--r--drivers/video/tegra/dc/dc_priv.h9
-rw-r--r--drivers/video/tegra/dc/hdmi.c51
3 files changed, 46 insertions, 28 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index 7b5d01d034b6..7145fcf2edb1 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -2477,8 +2477,7 @@ static int tegra_dc_probe(struct platform_device *ndev)
if (dc->out && dc->out->n_modes)
tegra_dc_add_modes(dc);
- if (dc->out && dc->out->hotplug_init)
- dc->out->hotplug_init(&ndev->dev);
+ tegra_dc_hotplug_init(dc);
if (dc->out_ops && dc->out_ops->detect)
dc->out_ops->detect(dc);
@@ -2587,14 +2586,8 @@ static int tegra_dc_suspend(struct platform_device *ndev, pm_message_t state)
dc->suspended = true;
}
- if (dc->out && dc->out->postsuspend) {
+ if (dc->out && dc->out->postsuspend)
dc->out->postsuspend();
- if (dc->out->type && dc->out->type == TEGRA_DC_OUT_HDMI)
- /*
- * avoid resume event due to voltage falling
- */
- msleep(100);
- }
tegra_dc_io_end(dc);
mutex_unlock(&dc->lock);
@@ -2622,9 +2615,6 @@ static int tegra_dc_resume(struct platform_device *ndev)
dc->enabled = _tegra_dc_enable(dc);
}
- if (dc->out && dc->out->hotplug_init)
- dc->out->hotplug_init(&ndev->dev);
-
if (dc->out_ops && dc->out_ops->resume)
dc->out_ops->resume(dc);
mutex_unlock(&dc->lock);
diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h
index 294ce55590e7..b8d72344515b 100644
--- a/drivers/video/tegra/dc/dc_priv.h
+++ b/drivers/video/tegra/dc/dc_priv.h
@@ -4,7 +4,7 @@
* Copyright (C) 2010 Google, Inc.
* Author: Erik Gilling <konkers@android.com>
*
- * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION, All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -250,6 +250,13 @@ static inline bool tegra_dc_is_powered(struct tegra_dc *dc)
}
#endif
+
+static inline void tegra_dc_hotplug_init(struct tegra_dc *dc)
+{
+ if (dc->out && dc->out->hotplug_init)
+ dc->out->hotplug_init(&dc->ndev->dev);
+}
+
extern struct tegra_dc_out_ops tegra_dc_rgb_ops;
extern struct tegra_dc_out_ops tegra_dc_hdmi_ops;
extern struct tegra_dc_out_ops tegra_dc_dsi_ops;
diff --git a/drivers/video/tegra/dc/hdmi.c b/drivers/video/tegra/dc/hdmi.c
index 6fdac23cbcef..14eca2f7afcc 100644
--- a/drivers/video/tegra/dc/hdmi.c
+++ b/drivers/video/tegra/dc/hdmi.c
@@ -440,6 +440,29 @@ static inline void tegra_hdmi_clrsetbits(struct tegra_dc_hdmi_data *hdmi,
tegra_hdmi_writel(hdmi, val, reg);
}
+static inline void tegra_hdmi_hotplug_signal(struct tegra_dc_hdmi_data *hdmi)
+{
+ queue_delayed_work(system_nrt_wq, &hdmi->work,
+ msecs_to_jiffies(100));
+}
+
+/* disables hotplug IRQ - this must be balanced */
+static inline void tegra_hdmi_hotplug_disable(struct tegra_dc_hdmi_data *hdmi)
+{
+ struct tegra_dc *dc = hdmi->dc;
+
+ disable_irq(gpio_to_irq(dc->out->hotplug_gpio));
+}
+
+/* enables hotplug IRQ - this must be balanced */
+static inline void tegra_hdmi_hotplug_enable(struct tegra_dc_hdmi_data *hdmi)
+{
+ struct tegra_dc *dc = hdmi->dc;
+
+ enable_irq(gpio_to_irq(dc->out->hotplug_gpio));
+}
+
+
#ifdef CONFIG_DEBUG_FS
static int dbg_hdmi_show(struct seq_file *m, void *unused)
{
@@ -666,8 +689,7 @@ static int dbg_hotplug_write(struct file *file, const char __user *addr,
dc->out->hotplug_state = new_state;
- queue_delayed_work(system_nrt_wq, &hdmi->work,
- msecs_to_jiffies(100));
+ tegra_hdmi_hotplug_signal(hdmi);
return len;
}
@@ -928,10 +950,13 @@ fail:
static void tegra_dc_hdmi_detect_worker(struct work_struct *work)
{
- struct tegra_dc_hdmi_data *hdmi =
- container_of(to_delayed_work(work), struct tegra_dc_hdmi_data, work);
+ struct tegra_dc_hdmi_data *hdmi = container_of(to_delayed_work(work),
+ struct tegra_dc_hdmi_data, work);
struct tegra_dc *dc = hdmi->dc;
+ /* board files are expected to allow multiple calls to hotplug_init() */
+ tegra_dc_hotplug_init(dc);
+
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
/* Set default videomode on dc before enabling it*/
tegra_dc_set_default_videomode(dc);
@@ -956,12 +981,7 @@ static irqreturn_t tegra_dc_hdmi_irq(int irq, void *ptr)
spin_lock_irqsave(&hdmi->suspend_lock, flags);
if (!hdmi->suspended) {
__cancel_delayed_work(&hdmi->work);
- if (tegra_dc_hdmi_hpd(dc))
- queue_delayed_work(system_nrt_wq, &hdmi->work,
- msecs_to_jiffies(100));
- else
- queue_delayed_work(system_nrt_wq, &hdmi->work,
- msecs_to_jiffies(30));
+ tegra_hdmi_hotplug_signal(hdmi);
}
spin_unlock_irqrestore(&hdmi->suspend_lock, flags);
@@ -973,6 +993,8 @@ static void tegra_dc_hdmi_suspend(struct tegra_dc *dc)
struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
unsigned long flags;
+ /* turn off hotplug detection to avoid resume event when +5V falls */
+ tegra_hdmi_hotplug_disable(hdmi);
tegra_nvhdcp_suspend(hdmi->nvhdcp);
spin_lock_irqsave(&hdmi->suspend_lock, flags);
hdmi->suspended = true;
@@ -982,17 +1004,16 @@ static void tegra_dc_hdmi_suspend(struct tegra_dc *dc)
static void tegra_dc_hdmi_resume(struct tegra_dc *dc)
{
struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
- bool hpd = tegra_dc_hdmi_hpd(dc);
unsigned long flags;
spin_lock_irqsave(&hdmi->suspend_lock, flags);
hdmi->suspended = false;
-
- queue_delayed_work(system_nrt_wq, &hdmi->work,
- msecs_to_jiffies(hpd ? 100 : 30));
-
spin_unlock_irqrestore(&hdmi->suspend_lock, flags);
+
tegra_nvhdcp_resume(hdmi->nvhdcp);
+ /* restore hotplug detection */
+ tegra_hdmi_hotplug_enable(hdmi);
+ tegra_hdmi_hotplug_signal(hdmi);
}
#ifdef CONFIG_SWITCH