diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2011-11-16 14:37:48 +0200 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2011-12-02 08:54:51 +0200 |
commit | f1577ce18004337ec2f6f48109ca14cac10a0a4f (patch) | |
tree | 0776380d725dc91580b9b67b15961e8cee00c1a8 /drivers/video/omap2 | |
parent | e4f7ad702ef271d2b0c03e9904b05f9bcbf0808b (diff) |
OMAPDSS: APPLY: add wait_pending_extra_info_updates()
Add wait_pending_extra_info_updates() function which can be used to wait
until any extra_info changes have been taken into use by the hardware.
This can be only called when holding the apply mutex, so that other
threads cannot insert new extra_info changes.
This will be used to handle fifo-configurations.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video/omap2')
-rw-r--r-- | drivers/video/omap2/dss/apply.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index 27d13bd9ed1..443f31e74a7 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -106,6 +106,7 @@ static struct { static spinlock_t data_lock; /* lock for blocking functions */ static DEFINE_MUTEX(apply_lock); +static DECLARE_COMPLETION(extra_updated_completion); static void dss_register_vsync_isr(void); @@ -232,6 +233,70 @@ static bool need_go(struct omap_overlay_manager *mgr) return false; } +/* returns true if an extra_info field is currently being updated */ +static bool extra_info_update_ongoing(void) +{ + const int num_ovls = omap_dss_get_num_overlays(); + struct ovl_priv_data *op; + struct omap_overlay *ovl; + struct mgr_priv_data *mp; + int i; + bool eid; + + for (i = 0; i < num_ovls; ++i) { + ovl = omap_dss_get_overlay(i); + op = get_ovl_priv(ovl); + + if (!op->enabled) + continue; + + mp = get_mgr_priv(ovl->manager); + + if (!mp->enabled) + continue; + + eid = op->extra_info_dirty || op->shadow_extra_info_dirty; + + if (!eid) + continue; + + if (ovl_manual_update(ovl) && !mp->updating) + continue; + + return true; + } + + return false; +} + +/* wait until no extra_info updates are pending */ +static void wait_pending_extra_info_updates(void) +{ + bool updating; + unsigned long flags; + unsigned long t; + + spin_lock_irqsave(&data_lock, flags); + + updating = extra_info_update_ongoing(); + + if (!updating) { + spin_unlock_irqrestore(&data_lock, flags); + return; + } + + init_completion(&extra_updated_completion); + + spin_unlock_irqrestore(&data_lock, flags); + + t = msecs_to_jiffies(500); + wait_for_completion_timeout(&extra_updated_completion, t); + + updating = extra_info_update_ongoing(); + + WARN_ON(updating); +} + int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) { unsigned long timeout = msecs_to_jiffies(500); @@ -553,6 +618,7 @@ static void dss_apply_irq_handler(void *data, u32 mask) { const int num_mgrs = dss_feat_get_num_mgrs(); int i; + bool extra_updating; spin_lock(&data_lock); @@ -582,6 +648,10 @@ static void dss_apply_irq_handler(void *data, u32 mask) dss_write_regs(); + extra_updating = extra_info_update_ongoing(); + if (!extra_updating) + complete_all(&extra_updated_completion); + if (!need_isr()) dss_unregister_vsync_isr(); |