diff options
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/omap2/dss/apply.c | 79 |
1 files changed, 51 insertions, 28 deletions
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index 931c7776e901..3bb5149b3a28 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -92,6 +92,9 @@ struct mgr_priv_data { * Never true for manual update displays */ bool busy; + /* If true, dispc output is enabled */ + bool updating; + /* If true, a display is enabled using this manager */ bool enabled; }; @@ -151,28 +154,31 @@ static bool need_isr(void) if (!mp->enabled) continue; - if (mgr_manual_update(mgr)) - continue; - - /* to catch GO bit going down */ - if (mp->busy) - return true; + if (mgr_manual_update(mgr)) { + /* to catch FRAMEDONE */ + if (mp->updating) + return true; + } else { + /* to catch GO bit going down */ + if (mp->busy) + return true; - /* to write new values to registers */ - if (mp->dirty) - 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; + list_for_each_entry(ovl, &mgr->overlays, list) { + struct ovl_priv_data *op; - op = get_ovl_priv(ovl); + op = get_ovl_priv(ovl); - if (!op->enabled) - continue; + if (!op->enabled) + continue; - /* to write new values to registers */ - if (op->dirty || op->extra_info_dirty) - return true; + /* to write new values to registers */ + if (op->dirty || op->extra_info_dirty) + return true; + } } } @@ -325,6 +331,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl) struct ovl_priv_data *op = get_ovl_priv(ovl); struct omap_overlay_info *oi; bool ilace, replication; + struct mgr_priv_data *mp; int r; DSSDBGF("%d", ovl->id); @@ -356,13 +363,17 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl) dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high); + mp = get_mgr_priv(ovl->manager); + op->dirty = false; - op->shadow_dirty = true; + if (mp->updating) + op->shadow_dirty = true; } static void dss_ovl_write_regs_extra(struct omap_overlay *ovl) { struct ovl_priv_data *op = get_ovl_priv(ovl); + struct mgr_priv_data *mp; DSSDBGF("%d", ovl->id); @@ -374,8 +385,11 @@ static void dss_ovl_write_regs_extra(struct omap_overlay *ovl) dispc_ovl_enable(ovl->id, op->enabled); + mp = get_mgr_priv(ovl->manager); + op->extra_info_dirty = false; - op->shadow_extra_info_dirty = true; + if (mp->updating) + op->shadow_extra_info_dirty = true; } static void dss_mgr_write_regs(struct omap_overlay_manager *mgr) @@ -400,7 +414,8 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr) dispc_mgr_setup(mgr->id, &mp->info); mp->dirty = false; - mp->shadow_dirty = true; + if (mp->updating) + mp->shadow_dirty = true; } } @@ -435,21 +450,18 @@ static void dss_write_regs(void) void dss_mgr_start_update(struct omap_overlay_manager *mgr) { struct mgr_priv_data *mp = get_mgr_priv(mgr); - struct ovl_priv_data *op; - struct omap_overlay *ovl; unsigned long flags; spin_lock_irqsave(&data_lock, flags); + WARN_ON(mp->updating); + dss_mgr_write_regs(mgr); - list_for_each_entry(ovl, &mgr->overlays, list) { - op = get_ovl_priv(ovl); - op->shadow_dirty = false; - op->shadow_extra_info_dirty = false; - } + mp->updating = true; - mp->shadow_dirty = false; + if (!dss_data.irq_enabled && need_isr()) + dss_register_vsync_isr(); dispc_mgr_enable(mgr->id, true); @@ -468,6 +480,9 @@ static void dss_register_vsync_isr(void) for (i = 0; i < num_mgrs; ++i) mask |= dispc_mgr_get_vsync_irq(i); + for (i = 0; i < num_mgrs; ++i) + mask |= dispc_mgr_get_framedone_irq(i); + r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask); WARN_ON(r); @@ -484,6 +499,9 @@ static void dss_unregister_vsync_isr(void) for (i = 0; i < num_mgrs; ++i) mask |= dispc_mgr_get_vsync_irq(i); + for (i = 0; i < num_mgrs; ++i) + mask |= dispc_mgr_get_framedone_irq(i); + r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask); WARN_ON(r); @@ -507,6 +525,7 @@ static void dss_apply_irq_handler(void *data, u32 mask) mp = get_mgr_priv(mgr); mp->busy = dispc_mgr_go_busy(i); + mp->updating = dispc_mgr_is_enabled(i); } for (i = 0; i < num_ovls; ++i) { @@ -663,6 +682,9 @@ void dss_mgr_enable(struct omap_overlay_manager *mgr) dss_write_regs(); + if (!mgr_manual_update(mgr)) + mp->updating = true; + spin_unlock_irqrestore(&data_lock, flags); if (!mgr_manual_update(mgr)) @@ -683,6 +705,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr) spin_lock_irqsave(&data_lock, flags); + mp->updating = false; mp->enabled = false; spin_unlock_irqrestore(&data_lock, flags); |