diff options
author | Jon Mayo <jmayo@nvidia.com> | 2013-06-04 13:50:12 -0700 |
---|---|---|
committer | Matthew Pedro <mapedro@nvidia.com> | 2013-07-11 12:27:50 -0700 |
commit | 4d7ee9988ffaf7addd462285544dd4ef78bc0c7c (patch) | |
tree | 5fa8cc6f8744cec240902a7dea6b612018214b7d | |
parent | f730ab83fd4797d30a0414d1cd7762591cf031df (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.c | 14 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc_priv.h | 9 | ||||
-rw-r--r-- | drivers/video/tegra/dc/hdmi.c | 51 |
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 |