video: tegra: dc: power optimize DC and host1x clk
[linux-2.6.git] / drivers / video / tegra / dc / window.c
index 0b4350d..48fef11 100644 (file)
@@ -31,11 +31,16 @@ static bool tegra_dc_windows_are_clean(struct tegra_dc_win *windows[],
                                             int n)
 {
        int i;
+       struct tegra_dc *dc = windows[0]->dc;
 
+       mutex_lock(&dc->lock);
        for (i = 0; i < n; i++) {
-               if (windows[i]->dirty)
+               if (windows[i]->dirty) {
+                       mutex_unlock(&dc->lock);
                        return false;
+               }
        }
+       mutex_unlock(&dc->lock);
 
        return true;
 }
@@ -100,6 +105,7 @@ static void tegra_dc_set_blending(struct tegra_dc *dc,
 {
        unsigned long mask = BIT(DC_N_WINDOWS) - 1;
 
+       tegra_dc_io_start(dc);
        while (mask) {
                int idx = get_topmost_window(blend->z, &mask);
 
@@ -116,6 +122,7 @@ static void tegra_dc_set_blending(struct tegra_dc *dc,
                tegra_dc_writel(dc, blend_3win(idx, mask, blend->flags),
                                DC_WIN_BLEND_3WIN_XY);
        }
+       tegra_dc_io_end(dc);
 }
 
 /* does not support syncing windows on multiple dcs in one call */
@@ -141,6 +148,8 @@ int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n)
        trace_printk("%s:After wait_event_interruptible_timeout\n",
                windows[0]->dc->ndev->name);
 #endif
+       /* tegra_dc_io_start() done in update_windows */
+       tegra_dc_io_end(windows[0]->dc);
        return ret;
 }
 EXPORT_SYMBOL(tegra_dc_sync_windows);
@@ -192,7 +201,8 @@ static inline u32 compute_initial_dda(fixed20_12 in)
        return dfixed_frac(in);
 }
 
-/* does not support updating windows on multiple dcs in one call */
+/* Does not support updating windows on multiple dcs in one call.
+ * Requires a matching sync_windows to avoid leaking ref-count on clocks. */
 int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
 {
        struct tegra_dc *dc;
@@ -219,6 +229,7 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
                return -EFAULT;
        }
 
+       tegra_dc_io_start(dc);
        tegra_dc_hold_dc_out(dc);
 
        if (no_vsync)
@@ -424,6 +435,7 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
        trace_printk("%s:update_mask=%#lx\n", dc->ndev->name, update_mask);
 
        tegra_dc_release_dc_out(dc);
+       /* tegra_dc_io_end() is called in tegra_dc_sync_windows() */
        mutex_unlock(&dc->lock);
        if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
                mutex_unlock(&dc->one_shot_lock);