From fd0e00d6ae856a2c9644325d2f7f57ae233bb851 Mon Sep 17 00:00:00 2001 From: Erik Gilling Date: Wed, 10 Nov 2010 15:32:58 -0800 Subject: [PATCH] video: tegra: delay HDMI hotplug detection until after resume Change-Id: I87c35dc3e1287fc1d936e554013deb2f92cbd6f4 Signed-off-by: Erik Gilling --- drivers/video/tegra/dc/dc.c | 7 +++++ drivers/video/tegra/dc/dc_priv.h | 5 +++ drivers/video/tegra/dc/hdmi.c | 52 +++++++++++++++++++++++++++++--- 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index d802535b913b..f10f3c441e01 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -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; diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h index 39a03e8fb9c0..7d0e340a6ee2 100644 --- a/drivers/video/tegra/dc/dc_priv.h +++ b/drivers/video/tegra/dc/dc_priv.h @@ -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 { diff --git a/drivers/video/tegra/dc/hdmi.c b/drivers/video/tegra/dc/hdmi.c index f2179c3a7857..6ad63ba791a4 100644 --- a/drivers/video/tegra/dc/hdmi.c +++ b/drivers/video/tegra/dc/hdmi.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -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, }; -- 2.34.1