diff options
author | kevinh <kevinh@nvidia.com> | 2011-03-18 00:12:40 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-04-26 15:54:32 -0700 |
commit | 9ea9dce375e0b842048897a16d3cd01601b66279 (patch) | |
tree | a0c0ac90ad6ddb7c32bb83eb45563771dbbcc82f | |
parent | 19856b7af82659462c8f0292c1a283ec7edc0f55 (diff) |
video: tegra: dsi: Stop dc stream at the frame end
Fixed tegra_dsi_stop_dc_stream() to flush register immediately.
Added tegra_dsi_stop_dc_stream_at_frame_end().
Original-Change-Id: Ie4fe1f6d59e6bf0dab40251f33a0c2f8d816fdd8
Reviewed-on: http://git-master/r/23488
Reviewed-by: Kevin Huang <kevinh@nvidia.com>
Tested-by: Kevin Huang <kevinh@nvidia.com>
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Change-Id: I398cb977146656936c5768c2bc3ec83f7bdc7c66
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 4 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc_priv.h | 4 | ||||
-rwxr-xr-x | drivers/video/tegra/dc/dsi.c | 37 |
3 files changed, 41 insertions, 4 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index 5a7062e10c79..8b0c2e66f993 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -1166,6 +1166,9 @@ static irqreturn_t tegra_dc_irq(int irq, void *ptr) status = tegra_dc_readl(dc, DC_CMD_INT_STATUS); tegra_dc_writel(dc, status, DC_CMD_INT_STATUS); + if (status & V_BLANK_INT) + complete(&dc->v_blank_complete); + if (status & FRAME_END_INT) { int completed = 0; int dirty = 0; @@ -1639,6 +1642,7 @@ static int tegra_dc_probe(struct nvhost_device *ndev) dc->enabled = true; mutex_init(&dc->lock); + init_completion(&dc->v_blank_complete); init_waitqueue_head(&dc->wq); INIT_WORK(&dc->reset_work, tegra_dc_reset_worker); diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h index d31c4436dcba..9049e07c8ba2 100644 --- a/drivers/video/tegra/dc/dc_priv.h +++ b/drivers/video/tegra/dc/dc_priv.h @@ -23,6 +23,8 @@ #include <linux/mutex.h> #include <linux/wait.h> #include <linux/switch.h> +#include <linux/completion.h> + #include "../host/dev.h" struct tegra_dc; @@ -93,6 +95,8 @@ struct tegra_dc { struct work_struct reset_work; struct switch_dev modeset_switch; + + struct completion v_blank_complete; }; static inline void tegra_dc_io_start(struct tegra_dc *dc) diff --git a/drivers/video/tegra/dc/dsi.c b/drivers/video/tegra/dc/dsi.c index e7474b76400d..288580fc5d13 100755 --- a/drivers/video/tegra/dc/dsi.c +++ b/drivers/video/tegra/dc/dsi.c @@ -40,6 +40,7 @@ #define DSI_USE_SYNC_POINTS 0 +#define DSI_STOP_DC_DURATION_MSEC 1000 #define DSI_MODULE_NOT_INIT 0x0 #define DSI_MODULE_INIT 0x1 @@ -699,11 +700,39 @@ static void tegra_dsi_set_pkt_seq(struct tegra_dc *dc, static void tegra_dsi_stop_dc_stream(struct tegra_dc *dc, struct tegra_dc_dsi_data *dsi) { - /* - * TODO: It is possible that we are in the middle of video stream, - * Add code to wait for vsync and then stop DC from sending data to dsi - */ tegra_dc_writel(dc, 0, DC_DISP_DISP_WIN_OPTIONS); + tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); + tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); +} + +void tegra_dsi_stop_dc_stream_at_frame_end(struct tegra_dc *dc, struct tegra_dc_dsi_data *dsi) +{ + int val; + long timeout; + + /* stop dc */ + tegra_dsi_stop_dc_stream(dc, dsi); + + /* enable vblank interrupt */ + 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); + + /* wait for vblank completion */ + timeout = wait_for_completion_interruptible_timeout( + &dc->v_blank_complete, DSI_STOP_DC_DURATION_MSEC); + + /* disable vblank interrupt */ + val = tegra_dc_readl(dc, DC_CMD_INT_ENABLE); + val &= ~V_BLANK_INT; + tegra_dc_writel(dc, val, DC_CMD_INT_ENABLE); + + if(timeout == 0) + printk("Warning: dc dosen't stop at the end of the frame.\n"); } static void tegra_dsi_start_dc_stream(struct tegra_dc *dc, |