diff options
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 27d13bd9ed10..443f31e74a75 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c | |||
@@ -106,6 +106,7 @@ static struct { | |||
106 | static spinlock_t data_lock; | 106 | static spinlock_t data_lock; |
107 | /* lock for blocking functions */ | 107 | /* lock for blocking functions */ |
108 | static DEFINE_MUTEX(apply_lock); | 108 | static DEFINE_MUTEX(apply_lock); |
109 | static DECLARE_COMPLETION(extra_updated_completion); | ||
109 | 110 | ||
110 | static void dss_register_vsync_isr(void); | 111 | static void dss_register_vsync_isr(void); |
111 | 112 | ||
@@ -232,6 +233,70 @@ static bool need_go(struct omap_overlay_manager *mgr) | |||
232 | return false; | 233 | return false; |
233 | } | 234 | } |
234 | 235 | ||
236 | /* returns true if an extra_info field is currently being updated */ | ||
237 | static bool extra_info_update_ongoing(void) | ||
238 | { | ||
239 | const int num_ovls = omap_dss_get_num_overlays(); | ||
240 | struct ovl_priv_data *op; | ||
241 | struct omap_overlay *ovl; | ||
242 | struct mgr_priv_data *mp; | ||
243 | int i; | ||
244 | bool eid; | ||
245 | |||
246 | for (i = 0; i < num_ovls; ++i) { | ||
247 | ovl = omap_dss_get_overlay(i); | ||
248 | op = get_ovl_priv(ovl); | ||
249 | |||
250 | if (!op->enabled) | ||
251 | continue; | ||
252 | |||
253 | mp = get_mgr_priv(ovl->manager); | ||
254 | |||
255 | if (!mp->enabled) | ||
256 | continue; | ||
257 | |||
258 | eid = op->extra_info_dirty || op->shadow_extra_info_dirty; | ||
259 | |||
260 | if (!eid) | ||
261 | continue; | ||
262 | |||
263 | if (ovl_manual_update(ovl) && !mp->updating) | ||
264 | continue; | ||
265 | |||
266 | return true; | ||
267 | } | ||
268 | |||
269 | return false; | ||
270 | } | ||
271 | |||
272 | /* wait until no extra_info updates are pending */ | ||
273 | static void wait_pending_extra_info_updates(void) | ||
274 | { | ||
275 | bool updating; | ||
276 | unsigned long flags; | ||
277 | unsigned long t; | ||
278 | |||
279 | spin_lock_irqsave(&data_lock, flags); | ||
280 | |||
281 | updating = extra_info_update_ongoing(); | ||
282 | |||
283 | if (!updating) { | ||
284 | spin_unlock_irqrestore(&data_lock, flags); | ||
285 | return; | ||
286 | } | ||
287 | |||
288 | init_completion(&extra_updated_completion); | ||
289 | |||
290 | spin_unlock_irqrestore(&data_lock, flags); | ||
291 | |||
292 | t = msecs_to_jiffies(500); | ||
293 | wait_for_completion_timeout(&extra_updated_completion, t); | ||
294 | |||
295 | updating = extra_info_update_ongoing(); | ||
296 | |||
297 | WARN_ON(updating); | ||
298 | } | ||
299 | |||
235 | int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) | 300 | int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) |
236 | { | 301 | { |
237 | unsigned long timeout = msecs_to_jiffies(500); | 302 | unsigned long timeout = msecs_to_jiffies(500); |
@@ -553,6 +618,7 @@ static void dss_apply_irq_handler(void *data, u32 mask) | |||
553 | { | 618 | { |
554 | const int num_mgrs = dss_feat_get_num_mgrs(); | 619 | const int num_mgrs = dss_feat_get_num_mgrs(); |
555 | int i; | 620 | int i; |
621 | bool extra_updating; | ||
556 | 622 | ||
557 | spin_lock(&data_lock); | 623 | spin_lock(&data_lock); |
558 | 624 | ||
@@ -582,6 +648,10 @@ static void dss_apply_irq_handler(void *data, u32 mask) | |||
582 | 648 | ||
583 | dss_write_regs(); | 649 | dss_write_regs(); |
584 | 650 | ||
651 | extra_updating = extra_info_update_ongoing(); | ||
652 | if (!extra_updating) | ||
653 | complete_all(&extra_updated_completion); | ||
654 | |||
585 | if (!need_isr()) | 655 | if (!need_isr()) |
586 | dss_unregister_vsync_isr(); | 656 | dss_unregister_vsync_isr(); |
587 | 657 | ||