video: tegra: delay HDMI hotplug detection until after resume

Change-Id: I87c35dc3e1287fc1d936e554013deb2f92cbd6f4
Signed-off-by: Erik Gilling <konkers@android.com>
This commit is contained in:
Erik Gilling
2010-11-10 15:32:58 -08:00
parent 1da2bd65cf
commit fd0e00d6ae
3 changed files with 60 additions and 4 deletions

View File

@@ -1102,6 +1102,10 @@ static int tegra_dc_suspend(struct nvhost_device *ndev, pm_message_t state)
dev_info(&ndev->dev, "suspend\n");
mutex_lock(&dc->lock);
if (dc->out_ops && dc->out_ops->suspend)
dc->out_ops->suspend(dc);
if (dc->enabled) {
tegra_fb_suspend(dc->fb);
_tegra_dc_disable(dc);
@@ -1120,6 +1124,9 @@ static int tegra_dc_resume(struct nvhost_device *ndev)
mutex_lock(&dc->lock);
if (dc->enabled)
_tegra_dc_enable(dc);
if (dc->out_ops && dc->out_ops->resume)
dc->out_ops->resume(dc);
mutex_unlock(&dc->lock);
return 0;

View File

@@ -42,6 +42,11 @@ struct tegra_dc_out_ops {
void (*enable)(struct tegra_dc *dc);
/* disable output. dc clocks are on at this point */
void (*disable)(struct tegra_dc *dc);
/* suspend output. dc clocks are on at this point */
void (*suspend)(struct tegra_dc *dc);
/* resume output. dc clocks are on at this point */
void (*resume)(struct tegra_dc *dc);
};
struct tegra_dc {

View File

@@ -23,6 +23,7 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <mach/clk.h>
@@ -52,6 +53,10 @@ struct tegra_dc_hdmi_data {
struct clk *disp1_clk;
struct clk *disp2_clk;
spinlock_t suspend_lock;
bool suspended;
bool hpd_pending;
};
const struct fb_videomode tegra_dc_hdmi_supported_modes[] = {
@@ -470,15 +475,49 @@ static irqreturn_t tegra_dc_hdmi_irq(int irq, void *ptr)
{
struct tegra_dc *dc = ptr;
struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
unsigned long flags;
if (tegra_dc_hdmi_hpd(dc))
schedule_delayed_work(&hdmi->work, msecs_to_jiffies(100));
else
schedule_delayed_work(&hdmi->work, msecs_to_jiffies(0));
spin_lock_irqsave(&hdmi->suspend_lock, flags);
if (hdmi->suspended) {
hdmi->hpd_pending = true;
} else {
if (tegra_dc_hdmi_hpd(dc))
schedule_delayed_work(&hdmi->work, msecs_to_jiffies(100));
else
schedule_delayed_work(&hdmi->work, msecs_to_jiffies(0));
}
spin_unlock_irqrestore(&hdmi->suspend_lock, flags);
return IRQ_HANDLED;
}
static void tegra_dc_hdmi_suspend(struct tegra_dc *dc)
{
struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
unsigned long flags;
spin_lock_irqsave(&hdmi->suspend_lock, flags);
hdmi->suspended = true;
spin_unlock_irqrestore(&hdmi->suspend_lock, flags);
}
static void tegra_dc_hdmi_resume(struct tegra_dc *dc)
{
struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
unsigned long flags;
spin_lock_irqsave(&hdmi->suspend_lock, flags);
hdmi->suspended = false;
if (hdmi->hpd_pending) {
if (tegra_dc_hdmi_hpd(dc))
schedule_delayed_work(&hdmi->work, msecs_to_jiffies(100));
else
schedule_delayed_work(&hdmi->work, msecs_to_jiffies(0));
hdmi->hpd_pending = false;
}
spin_unlock_irqrestore(&hdmi->suspend_lock, flags);
}
static int tegra_dc_hdmi_init(struct tegra_dc *dc)
{
struct tegra_dc_hdmi_data *hdmi;
@@ -561,6 +600,9 @@ static int tegra_dc_hdmi_init(struct tegra_dc *dc)
hdmi->clk = clk;
hdmi->disp1_clk = disp1_clk;
hdmi->disp2_clk = disp2_clk;
hdmi->suspended = false;
hdmi->hpd_pending = false;
spin_lock_init(&hdmi->suspend_lock);
dc->out->depth = 24;
@@ -1054,5 +1096,7 @@ struct tegra_dc_out_ops tegra_dc_hdmi_ops = {
.enable = tegra_dc_hdmi_enable,
.disable = tegra_dc_hdmi_disable,
.detect = tegra_dc_hdmi_detect,
.suspend = tegra_dc_hdmi_suspend,
.resume = tegra_dc_hdmi_resume,
};