]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blobdiff - drivers/video/tegra/dc/dc.c
video: tegra: dc: Fix and refactor FRAME_END_INT
[sojka/nv-tegra/linux-3.10.git] / drivers / video / tegra / dc / dc.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)
 {