]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
video: tegra: dc: Fix and refactor FRAME_END_INT
authorDaniel Solomon <daniels@nvidia.com>
Tue, 5 Aug 2014 21:48:42 +0000 (14:48 -0700)
committerMitch Luban <mluban@nvidia.com>
Tue, 14 Oct 2014 19:42:29 +0000 (12:42 -0700)
- 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
Bug 200036846

Change-Id: I40e26ada2f0494782979e32c1a22906361b214b5
Signed-off-by: Daniel Solomon <daniels@nvidia.com>
Reviewed-on: http://git-master/r/451186
(cherry picked from commit 24a39c49f63eea704003ee27296f1f70d46bcbd0)
Signed-off-by: Gaurav Singh <gauravsingh@nvidia.com>
Reviewed-on: http://git-master/r/556483
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Animesh Kishore <ankishore@nvidia.com>
Reviewed-by: Mitch Luban <mluban@nvidia.com>
drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/dc_priv.h
drivers/video/tegra/dc/dsi.c
drivers/video/tegra/dc/window.c

index 1c7c9e44567656114363c814c9bfd08855c38a45..99ab067c56fe982b7b8ac33bb0e3190ee003e7d7 100644 (file)
@@ -1641,6 +1641,30 @@ out:
        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 */
@@ -1863,6 +1887,30 @@ static void tegra_dc_process_vblank(struct tegra_dc *dc, ktime_t timestamp)
                tegra_dc_ext_process_vblank(dc->ndev->id, timestamp);
 }
 
+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)
 {
index f488dcdc497d52db1a5fdbd18299beef1a94a5fe..41317c3541efc56b819645cd9a81d60c2b1e3004 100644 (file)
@@ -395,6 +395,13 @@ void tegra_dc_put(struct tegra_dc *dc);
 void tegra_dc_hold_dc_out(struct tegra_dc *dc);
 void tegra_dc_release_dc_out(struct tegra_dc *dc);
 
+/* 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);
index 07b31aec426743d29bf8d0cb06e83d4e6ff72f64..18aaf7073df355d730995168b4ef83a4acd56336 100644 (file)
@@ -1695,7 +1695,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;
@@ -1708,26 +1707,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;
 }
 
index 4f5aec0cd4b8748b5dddb4ccddd121c8a9074108..e61f587a150de3c20f240295cb7bb3b29f3eeea3 100644 (file)
@@ -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;