diff options
Diffstat (limited to 'drivers/video/tegra')
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 48 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc_priv.h | 7 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dsi.c | 19 | ||||
-rw-r--r-- | drivers/video/tegra/dc/window.c | 15 |
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; |