From 05d46c545304fd7b023123d64c0043c65d3c842a Mon Sep 17 00:00:00 2001 From: Kevin Huang Date: Wed, 27 Jul 2011 00:53:35 -0700 Subject: 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 Tested-by: Karan Jhavar Reviewed-by: Ryan Wong Tested-by: Ryan Wong --- drivers/video/tegra/dc/dc.c | 159 +++++++++++++++++++++++++-------------- 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 <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 <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 <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); } -- cgit v1.2.3