summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkevinh <kevinh@nvidia.com>2011-03-18 00:12:40 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-04-26 15:54:32 -0700
commit9ea9dce375e0b842048897a16d3cd01601b66279 (patch)
treea0c0ac90ad6ddb7c32bb83eb45563771dbbcc82f
parent19856b7af82659462c8f0292c1a283ec7edc0f55 (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.c4
-rw-r--r--drivers/video/tegra/dc/dc_priv.h4
-rwxr-xr-xdrivers/video/tegra/dc/dsi.c37
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,