summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Solomon <daniels@nvidia.com>2014-08-05 14:48:42 -0700
committerWinnie Hsu <whsu@nvidia.com>2014-09-18 11:13:40 -0700
commit7ea8e5317c76e8618e011af1c951b00ab7ac5403 (patch)
tree9543cb2826926d1c3c019a9358d7e9a6d36d7b32
parent9210331cfbae36fc1064408a1571f3b1e07a100e (diff)
video: tegra: dc: Fix and refactor FRAME_END_INT
- Fix a conflict with other DC interrupt masks when the DSI driver waits on FRAME_END_INT - Move generic FRAME_END_INT mask/unmask and wait-for functions to dc.c Bug 1534724 Change-Id: I40e26ada2f0494782979e32c1a22906361b214b5 Signed-off-by: Daniel Solomon <daniels@nvidia.com> Reviewed-on: http://git-master/r/451186 (cherry picked from commit 24a39c49f63eea704003ee27296f1f70d46bcbd0) Reviewed-on: http://git-master/r/496580 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Jong Kim <jongk@nvidia.com> Reviewed-by: Bibek Basu <bbasu@nvidia.com> Tested-by: Bibek Basu <bbasu@nvidia.com> Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>
-rw-r--r--drivers/video/tegra/dc/dc.c48
-rw-r--r--drivers/video/tegra/dc/dc_priv.h7
-rw-r--r--drivers/video/tegra/dc/dsi.c19
-rw-r--r--drivers/video/tegra/dc/window.c15
4 files changed, 57 insertions, 32 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index 2809eef48ea3..541e6f00820f 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -1641,6 +1641,30 @@ int tegra_dc_wait_for_vsync(struct tegra_dc *dc)
return ret;
}
+int tegra_dc_wait_for_frame_end(struct tegra_dc *dc,
+ u32 timeout_ms)
+{
+ int ret;
+
+ INIT_COMPLETION(dc->frame_end_complete);
+
+ tegra_dc_get(dc);
+
+ tegra_dc_flush_interrupt(dc, FRAME_END_INT);
+ /* unmask frame end interrupt */
+ tegra_dc_config_frame_end_intr(dc, true);
+
+ ret = wait_for_completion_interruptible_timeout(
+ &dc->frame_end_complete,
+ msecs_to_jiffies(timeout_ms));
+
+ tegra_dc_config_frame_end_intr(dc, false);
+
+ tegra_dc_put(dc);
+
+ return ret;
+}
+
static void tegra_dc_prism_update_backlight(struct tegra_dc *dc)
{
/* Do the actual brightness update outside of the mutex dc->lock */
@@ -1870,6 +1894,30 @@ static void tegra_dc_vpulse2(struct work_struct *work)
}
#endif
+int tegra_dc_config_frame_end_intr(struct tegra_dc *dc, bool enable)
+{
+ bool locked_by_caller;
+
+ /* This function is called in situations where dc->lock
+ * is either free or already acquired - avoid a deadlock. */
+ locked_by_caller = mutex_is_locked(&dc->lock);
+ if (!locked_by_caller)
+ mutex_lock(&dc->lock);
+
+ tegra_dc_io_start(dc);
+ if (enable) {
+ atomic_inc(&dc->frame_end_ref);
+ tegra_dc_unmask_interrupt(dc, FRAME_END_INT);
+ } else if (!atomic_dec_return(&dc->frame_end_ref))
+ tegra_dc_mask_interrupt(dc, FRAME_END_INT);
+ tegra_dc_io_end(dc);
+
+ if (!locked_by_caller)
+ mutex_unlock(&dc->lock);
+
+ return 0;
+}
+
static void tegra_dc_one_shot_irq(struct tegra_dc *dc, unsigned long status,
ktime_t timestamp)
{
diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h
index bf54bfffa7b8..1c5d53b92035 100644
--- a/drivers/video/tegra/dc/dc_priv.h
+++ b/drivers/video/tegra/dc/dc_priv.h
@@ -403,6 +403,13 @@ unsigned long tegra_dc_poll_register(struct tegra_dc *dc,
u32 reg, u32 mask, u32 exp_val, u32 poll_interval_us,
u32 timeout_ms);
+/* defined in dc.c, used in ext/dev.c */
+int tegra_dc_config_frame_end_intr(struct tegra_dc *dc, bool enable);
+
+/* defined in dc.c, used in dsi.c */
+int tegra_dc_wait_for_frame_end(struct tegra_dc *dc,
+ u32 timeout_ms);
+
/* defined in bandwidth.c, used in dc.c */
void tegra_dc_clear_bandwidth(struct tegra_dc *dc);
void tegra_dc_program_bandwidth(struct tegra_dc *dc, bool use_new);
diff --git a/drivers/video/tegra/dc/dsi.c b/drivers/video/tegra/dc/dsi.c
index 681a63ce4bc6..df76712a5975 100644
--- a/drivers/video/tegra/dc/dsi.c
+++ b/drivers/video/tegra/dc/dsi.c
@@ -1694,7 +1694,6 @@ static int tegra_dsi_wait_frame_end(struct tegra_dc *dc,
struct tegra_dc_dsi_data *dsi,
u32 timeout_n_frames)
{
- int val;
long timeout;
u32 frame_period = DIV_ROUND_UP(S_TO_MS(1), dsi->info.refresh_rate);
struct tegra_dc_mode mode = dc->mode;
@@ -1707,26 +1706,12 @@ static int tegra_dsi_wait_frame_end(struct tegra_dc *dc,
dev_WARN(&dc->ndev->dev,
"dsi: to stop at next frame give at least 2 frame delay\n");
- INIT_COMPLETION(dc->frame_end_complete);
-
- tegra_dc_get(dc);
-
- tegra_dc_flush_interrupt(dc, FRAME_END_INT);
- /* unmask frame end interrupt */
- val = tegra_dc_unmask_interrupt(dc, FRAME_END_INT);
-
- timeout = wait_for_completion_interruptible_timeout(
- &dc->frame_end_complete,
- msecs_to_jiffies(timeout_n_frames * frame_period));
-
- /* reinstate interrupt mask */
- tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
+ timeout = tegra_dc_wait_for_frame_end(dc, timeout_n_frames *
+ frame_period);
/* wait for v_ref_to_sync no. of lines after frame end interrupt */
udelay(mode.v_ref_to_sync * line_period);
- tegra_dc_put(dc);
-
return timeout;
}
diff --git a/drivers/video/tegra/dc/window.c b/drivers/video/tegra/dc/window.c
index ef8dd918a937..c7b44b182e67 100644
--- a/drivers/video/tegra/dc/window.c
+++ b/drivers/video/tegra/dc/window.c
@@ -49,21 +49,6 @@ static bool tegra_dc_windows_are_clean(struct tegra_dc_win *windows[],
return true;
}
-int tegra_dc_config_frame_end_intr(struct tegra_dc *dc, bool enable)
-{
-
- mutex_lock(&dc->lock);
- tegra_dc_io_start(dc);
- if (enable) {
- atomic_inc(&dc->frame_end_ref);
- tegra_dc_unmask_interrupt(dc, FRAME_END_INT);
- } else if (!atomic_dec_return(&dc->frame_end_ref))
- tegra_dc_mask_interrupt(dc, FRAME_END_INT);
- tegra_dc_io_end(dc);
- mutex_unlock(&dc->lock);
- return 0;
-}
-
static int get_topmost_window(u32 *depths, unsigned long *wins, int win_num)
{
int idx, best = -1;