struct omap_overlay_manager_info info;
 
-       bool manual_update;
-       bool do_manual_update;
-
        /* If true, GO bit is up and shadow registers cannot be written.
         * Never true for manual update displays */
        bool busy;
 /* lock for blocking functions */
 static DEFINE_MUTEX(apply_lock);
 
+static void dss_register_vsync_isr(void);
+
 static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl)
 {
        return &dss_data.ovl_priv_data_array[ovl->id];
        return mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
 }
 
+static bool need_isr(void)
+{
+       const int num_mgrs = dss_feat_get_num_mgrs();
+       int i;
+
+       for (i = 0; i < num_mgrs; ++i) {
+               struct omap_overlay_manager *mgr;
+               struct mgr_priv_data *mp;
+               struct omap_overlay *ovl;
+
+               mgr = omap_dss_get_overlay_manager(i);
+               mp = get_mgr_priv(mgr);
+
+               if (!mp->enabled)
+                       continue;
+
+               if (mgr_manual_update(mgr))
+                       continue;
+
+               /* to catch GO bit going down */
+               if (mp->busy)
+                       return true;
+
+               /* to write new values to registers */
+               if (mp->dirty)
+                       return true;
+
+               list_for_each_entry(ovl, &mgr->overlays, list) {
+                       struct ovl_priv_data *op;
+
+                       op = get_ovl_priv(ovl);
+
+                       if (!op->enabled)
+                               continue;
+
+                       /* to write new values to registers */
+                       if (op->dirty || op->extra_info_dirty)
+                               return true;
+               }
+       }
+
+       return false;
+}
+
+static bool need_go(struct omap_overlay_manager *mgr)
+{
+       struct omap_overlay *ovl;
+       struct mgr_priv_data *mp;
+       struct ovl_priv_data *op;
+
+       mp = get_mgr_priv(mgr);
+
+       if (mp->shadow_dirty)
+               return true;
+
+       list_for_each_entry(ovl, &mgr->overlays, list) {
+               op = get_ovl_priv(ovl);
+               if (op->shadow_dirty || op->shadow_extra_info_dirty)
+                       return true;
+       }
+
+       return false;
+}
+
 int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
 {
        unsigned long timeout = msecs_to_jiffies(500);
        return r;
 }
 
-static int dss_ovl_write_regs(struct omap_overlay *ovl)
+static void dss_ovl_write_regs(struct omap_overlay *ovl)
 {
-       struct ovl_priv_data *op;
+       struct ovl_priv_data *op = get_ovl_priv(ovl);
        struct omap_overlay_info *oi;
        bool ilace, replication;
        int r;
 
        DSSDBGF("%d", ovl->id);
 
-       op = get_ovl_priv(ovl);
-       oi = &op->info;
+       if (!op->enabled || !op->dirty)
+               return;
 
-       if (!op->enabled)
-               return 0;
+       oi = &op->info;
 
        replication = dss_use_replication(ovl->manager->device, oi->color_mode);
 
 
        r = dispc_ovl_setup(ovl->id, oi, ilace, replication);
        if (r) {
-               /* this shouldn't happen */
+               /*
+                * We can't do much here, as this function can be called from
+                * vsync interrupt.
+                */
                DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id);
-               dispc_ovl_enable(ovl->id, 0);
-               return r;
+
+               /* This will leave fifo configurations in a nonoptimal state */
+               op->enabled = false;
+               dispc_ovl_enable(ovl->id, false);
+               return;
        }
 
        dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
 
-       return 0;
+       op->dirty = false;
+       op->shadow_dirty = true;
 }
 
 static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
 
        DSSDBGF("%d", ovl->id);
 
+       if (!op->extra_info_dirty)
+               return;
+
        /* note: write also when op->enabled == false, so that the ovl gets
         * disabled */
 
        dispc_ovl_enable(ovl->id, op->enabled);
+
+       op->extra_info_dirty = false;
+       op->shadow_extra_info_dirty = true;
 }
 
 static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
 {
-       struct mgr_priv_data *mp;
-       struct omap_overlay_manager_info *mi;
+       struct mgr_priv_data *mp = get_mgr_priv(mgr);
+       struct omap_overlay *ovl;
 
        DSSDBGF("%d", mgr->id);
 
-       mp = get_mgr_priv(mgr);
-       mi = &mp->info;
-
-       dispc_mgr_setup(mgr->id, mi);
-}
-
-/* dss_write_regs() tries to write values from cache to shadow registers.
- * It writes only to those managers/overlays that are not busy.
- * returns 0 if everything could be written to shadow registers.
- * returns 1 if not everything could be written to shadow registers. */
-static int dss_write_regs(void)
-{
-       struct omap_overlay *ovl;
-       struct omap_overlay_manager *mgr;
-       struct ovl_priv_data *op;
-       struct mgr_priv_data *mp;
-       const int num_ovls = dss_feat_get_num_ovls();
-       const int num_mgrs = dss_feat_get_num_mgrs();
-       int i;
-       int r;
-       bool mgr_go[MAX_DSS_MANAGERS] = { false };
-       bool busy;
+       if (!mp->enabled)
+               return;
 
-       r = 0;
-       busy = false;
+       WARN_ON(mp->busy);
 
        /* Commit overlay settings */
-       for (i = 0; i < num_ovls; ++i) {
-               ovl = omap_dss_get_overlay(i);
-               op = get_ovl_priv(ovl);
-
-               if (!op->dirty)
-                       continue;
-
-               mp = get_mgr_priv(ovl->manager);
-
-               if (mp->manual_update && !mp->do_manual_update)
-                       continue;
-
-               if (mp->busy) {
-                       busy = true;
-                       continue;
-               }
-
-               r = dss_ovl_write_regs(ovl);
-               if (r)
-                       DSSERR("dss_ovl_write_regs %d failed\n", i);
-
-               op->dirty = false;
-               op->shadow_dirty = true;
-               mgr_go[op->channel] = true;
-       }
-
-       for (i = 0; i < num_ovls; ++i) {
-               ovl = omap_dss_get_overlay(i);
-               op = get_ovl_priv(ovl);
-
-               if (!op->extra_info_dirty)
-                       continue;
-
-               mp = get_mgr_priv(ovl->manager);
-
-               if (mp->manual_update && !mp->do_manual_update)
-                       continue;
-
-               if (mp->busy) {
-                       busy = true;
-                       continue;
-               }
-
+       list_for_each_entry(ovl, &mgr->overlays, list) {
+               dss_ovl_write_regs(ovl);
                dss_ovl_write_regs_extra(ovl);
-
-               op->extra_info_dirty = false;
-               op->shadow_extra_info_dirty = true;
-               mgr_go[op->channel] = true;
        }
 
-       /* Commit manager settings */
-       for (i = 0; i < num_mgrs; ++i) {
-               mgr = omap_dss_get_overlay_manager(i);
-               mp = get_mgr_priv(mgr);
-
-               if (!mp->dirty)
-                       continue;
-
-               if (mp->manual_update && !mp->do_manual_update)
-                       continue;
-
-               if (mp->busy) {
-                       busy = true;
-                       continue;
-               }
+       if (mp->dirty) {
+               dispc_mgr_setup(mgr->id, &mp->info);
 
-               dss_mgr_write_regs(mgr);
                mp->dirty = false;
                mp->shadow_dirty = true;
-               mgr_go[i] = true;
        }
+}
+
+static void dss_write_regs(void)
+{
+       const int num_mgrs = omap_dss_get_num_overlay_managers();
+       int i;
 
-       /* set GO */
        for (i = 0; i < num_mgrs; ++i) {
+               struct omap_overlay_manager *mgr;
+               struct mgr_priv_data *mp;
+
                mgr = omap_dss_get_overlay_manager(i);
                mp = get_mgr_priv(mgr);
 
-               if (!mgr_go[i])
+               if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
                        continue;
 
-               /* We don't need GO with manual update display. LCD iface will
-                * always be turned off after frame, and new settings will be
-                * taken in to use at next update */
-               if (!mp->manual_update) {
+               dss_mgr_write_regs(mgr);
+
+               if (need_go(mgr)) {
                        mp->busy = true;
-                       dispc_mgr_go(i);
-               }
-       }
 
-       if (busy)
-               r = 1;
-       else
-               r = 0;
+                       if (!dss_data.irq_enabled && need_isr())
+                               dss_register_vsync_isr();
 
-       return r;
+                       dispc_mgr_go(mgr->id);
+               }
+       }
 }
 
 void dss_mgr_start_update(struct omap_overlay_manager *mgr)
 
        spin_lock_irqsave(&data_lock, flags);
 
-       mp->do_manual_update = true;
-       dss_write_regs();
-       mp->do_manual_update = false;
+       dss_mgr_write_regs(mgr);
 
        list_for_each_entry(ovl, &mgr->overlays, list) {
                op = get_ovl_priv(ovl);
        struct ovl_priv_data *op;
        const int num_ovls = dss_feat_get_num_ovls();
        const int num_mgrs = dss_feat_get_num_mgrs();
-       int i, r;
+       int i;
 
        spin_lock(&data_lock);
 
                        mp->shadow_dirty = false;
        }
 
-       r = dss_write_regs();
-       if (r == 1)
-               goto end;
-
-       /* re-read busy flags */
-       for (i = 0; i < num_mgrs; i++) {
-               mgr = omap_dss_get_overlay_manager(i);
-               mp = get_mgr_priv(mgr);
-
-               mp->busy = dispc_mgr_go_busy(i);
-       }
-
-       /* keep running as long as there are busy managers, so that
-        * we can collect overlay-applied information */
-       for (i = 0; i < num_mgrs; ++i) {
-               mgr = omap_dss_get_overlay_manager(i);
-               mp = get_mgr_priv(mgr);
-
-               if (mp->busy)
-                       goto end;
-       }
+       dss_write_regs();
 
-       dss_unregister_vsync_isr();
+       if (!need_isr())
+               dss_unregister_vsync_isr();
 
-end:
        spin_unlock(&data_lock);
 }
 
        if (!mgr->info_dirty)
                return;
 
-       if (!mgr->device)
-               return;
-
        mgr->info_dirty = false;
        mp->dirty = true;
        mp->info = mgr->info;
-
-       mp->manual_update = mgr_manual_update(mgr);
 }
 
 static void omap_dss_mgr_apply_ovl_fifos(struct omap_overlay *ovl)
        int r;
        unsigned long flags;
        struct omap_overlay *ovl;
-       struct mgr_priv_data *mp = get_mgr_priv(mgr);
 
        DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
 
        list_for_each_entry(ovl, &mgr->overlays, list)
                omap_dss_mgr_apply_ovl_fifos(ovl);
 
-       r = 0;
-       if (mp->enabled && !mgr_manual_update(mgr)) {
-               if (!dss_data.irq_enabled)
-                       dss_register_vsync_isr();
-
-               dss_write_regs();
-       }
+       dss_write_regs();
 
        spin_unlock_irqrestore(&data_lock, flags);
 
 
        mutex_lock(&apply_lock);
 
-       if (!mgr_manual_update(mgr))
-               dispc_mgr_enable(mgr->id, true);
-
        spin_lock_irqsave(&data_lock, flags);
 
        mp->enabled = true;
 
+       dss_write_regs();
+
        spin_unlock_irqrestore(&data_lock, flags);
 
+       if (!mgr_manual_update(mgr))
+               dispc_mgr_enable(mgr->id, true);
+
        mutex_unlock(&apply_lock);
 }
 
        op->enabled = true;
        op->extra_info_dirty = true;
 
+       dss_write_regs();
+
        spin_unlock_irqrestore(&data_lock, flags);
 
        mutex_unlock(&apply_lock);
        op->enabled = false;
        op->extra_info_dirty = true;
 
+       dss_write_regs();
+
        spin_unlock_irqrestore(&data_lock, flags);
 
        mutex_unlock(&apply_lock);