]> 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)
committerJon Mayo <jmayo@nvidia.com>
Tue, 12 Aug 2014 16:19:20 +0000 (09:19 -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

Change-Id: I40e26ada2f0494782979e32c1a22906361b214b5
Signed-off-by: Daniel Solomon <daniels@nvidia.com>
Reviewed-on: http://git-master/r/451186
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Jon Mayo <jmayo@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 7d9959c643b055c6929cead3a741b3c8f7336f06..6e37f49f62f32b6e4a0a6550aff2253cd914c193 100644 (file)
@@ -2051,6 +2051,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 */
@@ -2276,6 +2300,30 @@ static void tegra_dc_process_vblank(struct tegra_dc *dc, ktime_t timestamp)
 #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)
 {
index c4cdffe136cd29979d7763f67b91cbe38f05d682..daf1c3268812f725e2c904248dd0c86b20a0793c 100644 (file)
@@ -485,6 +485,13 @@ u32 timeout_ms);
 /* defined in dc.c, used by ext/dev.c */
 extern int no_vsync;
 
+/* 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 e104a9dd92cc24c87893716a5ab5dbeb88aeb3ed..8fd4539b01427203fe47a080e539224e68984fd0 100644 (file)
@@ -1728,7 +1728,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;
@@ -1741,26 +1740,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 88f1acc910b36c87e91c154679b233b245853de4..535308b02fb1e050d9717a429c216549133523cd 100644 (file)
@@ -50,21 +50,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;