diff options
author | Kevin Huang <kevinh@nvidia.com> | 2011-07-27 00:53:35 -0700 |
---|---|---|
committer | Ryan Wong <ryanw@nvidia.com> | 2011-08-10 18:37:32 -0700 |
commit | 05d46c545304fd7b023123d64c0043c65d3c842a (patch) | |
tree | c02dc695f12445c84d3f4f2a1baef93d94d6317a | |
parent | 0a7255bd9124cedf7522abda04b9381cb5dfcfbb (diff) |
video: tegra: overlay: Modified overlay flipping for DSI one-shot mode.
Change-Id: I547458d0c20d0197c1134e689d0ee98776ab28e8
Reviewed-on: http://git-master/r/46501
Reviewed-by: Karan Jhavar <kjhavar@nvidia.com>
Tested-by: Karan Jhavar <kjhavar@nvidia.com>
Reviewed-by: Ryan Wong <ryanw@nvidia.com>
Tested-by: Ryan Wong <ryanw@nvidia.com>
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 159 | ||||
-rw-r--r-- | drivers/video/tegra/dc/overlay.c | 3 |
2 files changed, 106 insertions, 56 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index 7505eef9da90..8a63e49067e3 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -1762,80 +1762,129 @@ static irqreturn_t tegra_dc_irq(int irq, void *ptr) if (status & WIN_C_UF_INT) dc->stats.underflows_c++; } + if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) { + int completed = 0; + int dirty = 0; + if (status & V_BLANK_INT) { + /* Schedule any additional bottom-half vblank actvities. */ + schedule_work(&dc->vblank_work); + + /* Mark the vblank as complete. */ + complete(&dc->vblank_complete); + + val = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL); + for (i = 0; i < DC_N_WINDOWS; i++) { + if (!(val & (WIN_A_UPDATE << i))) { + dc->windows[i].dirty = 0; + completed = 1; + } else { + dirty = 1; + } + } + wake_up(&dc->wq); + } - if (status & V_BLANK_INT) { - int i; - - /* Check for any underflow reset conditions */ - for (i = 0; i< DC_N_WINDOWS; i++) { - if (dc->underflow_mask & (WIN_A_UF_INT <<i)) { - dc->windows[i].underflows++; + if (status & FRAME_END_INT) { + int i; + /* Check for any underflow reset conditions */ + for (i = 0; i< DC_N_WINDOWS; i++) { + if (dc->underflow_mask & (WIN_A_UF_INT <<i)) { + dc->windows[i].underflows++; + + #ifdef CONFIG_ARCH_TEGRA_2x_SOC + if (dc->windows[i].underflows > 4) + schedule_work(&dc->reset_work); + #endif + } else { + dc->windows[i].underflows = 0; + } + } -#ifdef CONFIG_ARCH_TEGRA_2x_SOC - if (dc->windows[i].underflows > 4) - schedule_work(&dc->reset_work); -#endif - } else { - dc->windows[i].underflows = 0; + if (!dc->underflow_mask) { + /* If we have no underflow to check, go ahead + and disable the interrupt */ + val = tegra_dc_readl(dc, DC_CMD_INT_ENABLE); + val &= ~FRAME_END_INT; + tegra_dc_writel(dc, val, DC_CMD_INT_ENABLE); } - } - if (!dc->underflow_mask) { - /* If we have no underflow to check, go ahead - and disable the interrupt */ - val = tegra_dc_readl(dc, DC_CMD_INT_ENABLE); - val &= ~V_BLANK_INT; - tegra_dc_writel(dc, val, DC_CMD_INT_ENABLE); + /* Clear the underflow mask now that we've checked it. */ + dc->underflow_mask = 0; } + } else { + if (status & V_BLANK_INT) { + int i; + + /* Check for any underflow reset conditions */ + for (i = 0; i< DC_N_WINDOWS; i++) { + if (dc->underflow_mask & (WIN_A_UF_INT <<i)) { + dc->windows[i].underflows++; + + #ifdef CONFIG_ARCH_TEGRA_2x_SOC + if (dc->windows[i].underflows > 4) + schedule_work(&dc->reset_work); + #endif + } else { + dc->windows[i].underflows = 0; + } + } - /* Clear the underflow mask now that we've checked it. */ - dc->underflow_mask = 0; - - /* Schedule any additional bottom-half vblank actvities. */ - schedule_work(&dc->vblank_work); + if (!dc->underflow_mask) { + /* If we have no underflow to check, go ahead + and disable the interrupt */ + val = tegra_dc_readl(dc, DC_CMD_INT_ENABLE); + val &= ~V_BLANK_INT; + tegra_dc_writel(dc, val, DC_CMD_INT_ENABLE); + } - /* Mark the vblank as complete. */ - complete(&dc->vblank_complete); - } + /* Clear the underflow mask now that we've checked it. */ + dc->underflow_mask = 0; - if (status & FRAME_END_INT) { - int completed = 0; - int dirty = 0; + /* Schedule any additional bottom-half vblank actvities. */ + schedule_work(&dc->vblank_work); - val = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL); - for (i = 0; i < DC_N_WINDOWS; i++) { - if (!(val & (WIN_A_UPDATE << i))) { - dc->windows[i].dirty = 0; - completed = 1; - } else { - dirty = 1; - } + /* Mark the vblank as complete. */ + complete(&dc->vblank_complete); } - if (!dirty) { - val = tegra_dc_readl(dc, DC_CMD_INT_ENABLE); - val &= ~FRAME_END_INT; - tegra_dc_writel(dc, val, DC_CMD_INT_ENABLE); - } + if (status & FRAME_END_INT) { + int completed = 0; + int dirty = 0; + + val = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL); + for (i = 0; i < DC_N_WINDOWS; i++) { + if (!(val & (WIN_A_UPDATE << i))) { + dc->windows[i].dirty = 0; + completed = 1; + } else { + dirty = 1; + } + } - if (completed) { if (!dirty) { - /* With the last completed window, go ahead - and enable the vblank interrupt for nvsd. */ val = tegra_dc_readl(dc, DC_CMD_INT_ENABLE); - val |= V_BLANK_INT; + val &= ~FRAME_END_INT; tegra_dc_writel(dc, val, DC_CMD_INT_ENABLE); - - val = tegra_dc_readl(dc, DC_CMD_INT_MASK); - val |= V_BLANK_INT; - tegra_dc_writel(dc, val, DC_CMD_INT_MASK); } - /* Wake up the workqueue regardless. */ - wake_up(&dc->wq); + if (completed) { + if (!dirty) { + /* With the last completed window, go ahead + and enable the vblank interrupt for nvsd. */ + val = tegra_dc_readl(dc, DC_CMD_INT_ENABLE); + val |= V_BLANK_INT; + tegra_dc_writel(dc, val, DC_CMD_INT_ENABLE); + + val = tegra_dc_readl(dc, DC_CMD_INT_MASK); + val |= V_BLANK_INT; + tegra_dc_writel(dc, val, DC_CMD_INT_MASK); + } + + /* Wake up the workqueue regardless. */ + wake_up(&dc->wq); + } } } - return IRQ_HANDLED; #else /* CONFIG_TEGRA_SILICON_PLATFORM */ return IRQ_NONE; diff --git a/drivers/video/tegra/dc/overlay.c b/drivers/video/tegra/dc/overlay.c index 7879100be8e1..83191a40b8af 100644 --- a/drivers/video/tegra/dc/overlay.c +++ b/drivers/video/tegra/dc/overlay.c @@ -318,7 +318,7 @@ static void tegra_overlay_flip_worker(struct work_struct *work) tegra_dc_sync_windows(wins, nr_win); } - tegra_dc_incr_syncpt_min(overlay->dc, data->syncpt_max); + tegra_dc_incr_syncpt_min(overlay->dc, data->syncpt_max); /* unpin and deref previous front buffers */ for (i = 0; i < nr_unpin; i++) { @@ -779,5 +779,6 @@ void tegra_overlay_disable(struct tegra_overlay_info *overlay_info) { mutex_lock(&tegra_flip_lock); flush_workqueue(overlay_info->flip_wq); + mutex_unlock(&tegra_flip_lock); } |