1 /*
2  * Copyright (C) 2011 Texas Instruments
3  * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published by
7  * the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #define DSS_SUBSYS_NAME "APPLY"
19 
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 #include <linux/slab.h>
23 #include <linux/spinlock.h>
24 #include <linux/jiffies.h>
25 
26 #include <video/omapdss.h>
27 
28 #include "dss.h"
29 #include "dss_features.h"
30 #include "dispc-compat.h"
31 
32 /*
33  * We have 4 levels of cache for the dispc settings. First two are in SW and
34  * the latter two in HW.
35  *
36  *       set_info()
37  *          v
38  * +--------------------+
39  * |     user_info      |
40  * +--------------------+
41  *          v
42  *        apply()
43  *          v
44  * +--------------------+
45  * |       info         |
46  * +--------------------+
47  *          v
48  *      write_regs()
49  *          v
50  * +--------------------+
51  * |  shadow registers  |
52  * +--------------------+
53  *          v
54  * VFP or lcd/digit_enable
55  *          v
56  * +--------------------+
57  * |      registers     |
58  * +--------------------+
59  */
60 
61 struct ovl_priv_data {
62 
63 	bool user_info_dirty;
64 	struct omap_overlay_info user_info;
65 
66 	bool info_dirty;
67 	struct omap_overlay_info info;
68 
69 	bool shadow_info_dirty;
70 
71 	bool extra_info_dirty;
72 	bool shadow_extra_info_dirty;
73 
74 	bool enabled;
75 	u32 fifo_low, fifo_high;
76 
77 	/*
78 	 * True if overlay is to be enabled. Used to check and calculate configs
79 	 * for the overlay before it is enabled in the HW.
80 	 */
81 	bool enabling;
82 };
83 
84 struct mgr_priv_data {
85 
86 	bool user_info_dirty;
87 	struct omap_overlay_manager_info user_info;
88 
89 	bool info_dirty;
90 	struct omap_overlay_manager_info info;
91 
92 	bool shadow_info_dirty;
93 
94 	/* If true, GO bit is up and shadow registers cannot be written.
95 	 * Never true for manual update displays */
96 	bool busy;
97 
98 	/* If true, dispc output is enabled */
99 	bool updating;
100 
101 	/* If true, a display is enabled using this manager */
102 	bool enabled;
103 
104 	bool extra_info_dirty;
105 	bool shadow_extra_info_dirty;
106 
107 	struct omap_video_timings timings;
108 	struct dss_lcd_mgr_config lcd_config;
109 
110 	void (*framedone_handler)(void *);
111 	void *framedone_handler_data;
112 };
113 
114 static struct {
115 	struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
116 	struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
117 
118 	bool irq_enabled;
119 } dss_data;
120 
121 /* protects dss_data */
122 static spinlock_t data_lock;
123 /* lock for blocking functions */
124 static DEFINE_MUTEX(apply_lock);
125 static DECLARE_COMPLETION(extra_updated_completion);
126 
127 static void dss_register_vsync_isr(void);
128 
129 static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl)
130 {
131 	return &dss_data.ovl_priv_data_array[ovl->id];
132 }
133 
134 static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
135 {
136 	return &dss_data.mgr_priv_data_array[mgr->id];
137 }
138 
139 static void apply_init_priv(void)
140 {
141 	const int num_ovls = dss_feat_get_num_ovls();
142 	struct mgr_priv_data *mp;
143 	int i;
144 
145 	spin_lock_init(&data_lock);
146 
147 	for (i = 0; i < num_ovls; ++i) {
148 		struct ovl_priv_data *op;
149 
150 		op = &dss_data.ovl_priv_data_array[i];
151 
152 		op->info.color_mode = OMAP_DSS_COLOR_RGB16;
153 		op->info.rotation_type = OMAP_DSS_ROT_DMA;
154 
155 		op->info.global_alpha = 255;
156 
157 		switch (i) {
158 		case 0:
159 			op->info.zorder = 0;
160 			break;
161 		case 1:
162 			op->info.zorder =
163 				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
164 			break;
165 		case 2:
166 			op->info.zorder =
167 				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
168 			break;
169 		case 3:
170 			op->info.zorder =
171 				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
172 			break;
173 		}
174 
175 		op->user_info = op->info;
176 	}
177 
178 	/*
179 	 * Initialize some of the lcd_config fields for TV manager, this lets
180 	 * us prevent checking if the manager is LCD or TV at some places
181 	 */
182 	mp = &dss_data.mgr_priv_data_array[OMAP_DSS_CHANNEL_DIGIT];
183 
184 	mp->lcd_config.video_port_width = 24;
185 	mp->lcd_config.clock_info.lck_div = 1;
186 	mp->lcd_config.clock_info.pck_div = 1;
187 }
188 
189 /*
190  * A LCD manager's stallmode decides whether it is in manual or auto update. TV
191  * manager is always auto update, stallmode field for TV manager is false by
192  * default
193  */
194 static bool ovl_manual_update(struct omap_overlay *ovl)
195 {
196 	struct mgr_priv_data *mp = get_mgr_priv(ovl->manager);
197 
198 	return mp->lcd_config.stallmode;
199 }
200 
201 static bool mgr_manual_update(struct omap_overlay_manager *mgr)
202 {
203 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
204 
205 	return mp->lcd_config.stallmode;
206 }
207 
208 static int dss_check_settings_low(struct omap_overlay_manager *mgr,
209 		bool applying)
210 {
211 	struct omap_overlay_info *oi;
212 	struct omap_overlay_manager_info *mi;
213 	struct omap_overlay *ovl;
214 	struct omap_overlay_info *ois[MAX_DSS_OVERLAYS];
215 	struct ovl_priv_data *op;
216 	struct mgr_priv_data *mp;
217 
218 	mp = get_mgr_priv(mgr);
219 
220 	if (!mp->enabled)
221 		return 0;
222 
223 	if (applying && mp->user_info_dirty)
224 		mi = &mp->user_info;
225 	else
226 		mi = &mp->info;
227 
228 	/* collect the infos to be tested into the array */
229 	list_for_each_entry(ovl, &mgr->overlays, list) {
230 		op = get_ovl_priv(ovl);
231 
232 		if (!op->enabled && !op->enabling)
233 			oi = NULL;
234 		else if (applying && op->user_info_dirty)
235 			oi = &op->user_info;
236 		else
237 			oi = &op->info;
238 
239 		ois[ovl->id] = oi;
240 	}
241 
242 	return dss_mgr_check(mgr, mi, &mp->timings, &mp->lcd_config, ois);
243 }
244 
245 /*
246  * check manager and overlay settings using overlay_info from data->info
247  */
248 static int dss_check_settings(struct omap_overlay_manager *mgr)
249 {
250 	return dss_check_settings_low(mgr, false);
251 }
252 
253 /*
254  * check manager and overlay settings using overlay_info from ovl->info if
255  * dirty and from data->info otherwise
256  */
257 static int dss_check_settings_apply(struct omap_overlay_manager *mgr)
258 {
259 	return dss_check_settings_low(mgr, true);
260 }
261 
262 static bool need_isr(void)
263 {
264 	const int num_mgrs = dss_feat_get_num_mgrs();
265 	int i;
266 
267 	for (i = 0; i < num_mgrs; ++i) {
268 		struct omap_overlay_manager *mgr;
269 		struct mgr_priv_data *mp;
270 		struct omap_overlay *ovl;
271 
272 		mgr = omap_dss_get_overlay_manager(i);
273 		mp = get_mgr_priv(mgr);
274 
275 		if (!mp->enabled)
276 			continue;
277 
278 		if (mgr_manual_update(mgr)) {
279 			/* to catch FRAMEDONE */
280 			if (mp->updating)
281 				return true;
282 		} else {
283 			/* to catch GO bit going down */
284 			if (mp->busy)
285 				return true;
286 
287 			/* to write new values to registers */
288 			if (mp->info_dirty)
289 				return true;
290 
291 			/* to set GO bit */
292 			if (mp->shadow_info_dirty)
293 				return true;
294 
295 			/*
296 			 * NOTE: we don't check extra_info flags for disabled
297 			 * managers, once the manager is enabled, the extra_info
298 			 * related manager changes will be taken in by HW.
299 			 */
300 
301 			/* to write new values to registers */
302 			if (mp->extra_info_dirty)
303 				return true;
304 
305 			/* to set GO bit */
306 			if (mp->shadow_extra_info_dirty)
307 				return true;
308 
309 			list_for_each_entry(ovl, &mgr->overlays, list) {
310 				struct ovl_priv_data *op;
311 
312 				op = get_ovl_priv(ovl);
313 
314 				/*
315 				 * NOTE: we check extra_info flags even for
316 				 * disabled overlays, as extra_infos need to be
317 				 * always written.
318 				 */
319 
320 				/* to write new values to registers */
321 				if (op->extra_info_dirty)
322 					return true;
323 
324 				/* to set GO bit */
325 				if (op->shadow_extra_info_dirty)
326 					return true;
327 
328 				if (!op->enabled)
329 					continue;
330 
331 				/* to write new values to registers */
332 				if (op->info_dirty)
333 					return true;
334 
335 				/* to set GO bit */
336 				if (op->shadow_info_dirty)
337 					return true;
338 			}
339 		}
340 	}
341 
342 	return false;
343 }
344 
345 static bool need_go(struct omap_overlay_manager *mgr)
346 {
347 	struct omap_overlay *ovl;
348 	struct mgr_priv_data *mp;
349 	struct ovl_priv_data *op;
350 
351 	mp = get_mgr_priv(mgr);
352 
353 	if (mp->shadow_info_dirty || mp->shadow_extra_info_dirty)
354 		return true;
355 
356 	list_for_each_entry(ovl, &mgr->overlays, list) {
357 		op = get_ovl_priv(ovl);
358 		if (op->shadow_info_dirty || op->shadow_extra_info_dirty)
359 			return true;
360 	}
361 
362 	return false;
363 }
364 
365 /* returns true if an extra_info field is currently being updated */
366 static bool extra_info_update_ongoing(void)
367 {
368 	const int num_mgrs = dss_feat_get_num_mgrs();
369 	int i;
370 
371 	for (i = 0; i < num_mgrs; ++i) {
372 		struct omap_overlay_manager *mgr;
373 		struct omap_overlay *ovl;
374 		struct mgr_priv_data *mp;
375 
376 		mgr = omap_dss_get_overlay_manager(i);
377 		mp = get_mgr_priv(mgr);
378 
379 		if (!mp->enabled)
380 			continue;
381 
382 		if (!mp->updating)
383 			continue;
384 
385 		if (mp->extra_info_dirty || mp->shadow_extra_info_dirty)
386 			return true;
387 
388 		list_for_each_entry(ovl, &mgr->overlays, list) {
389 			struct ovl_priv_data *op = get_ovl_priv(ovl);
390 
391 			if (op->extra_info_dirty || op->shadow_extra_info_dirty)
392 				return true;
393 		}
394 	}
395 
396 	return false;
397 }
398 
399 /* wait until no extra_info updates are pending */
400 static void wait_pending_extra_info_updates(void)
401 {
402 	bool updating;
403 	unsigned long flags;
404 	unsigned long t;
405 	int r;
406 
407 	spin_lock_irqsave(&data_lock, flags);
408 
409 	updating = extra_info_update_ongoing();
410 
411 	if (!updating) {
412 		spin_unlock_irqrestore(&data_lock, flags);
413 		return;
414 	}
415 
416 	init_completion(&extra_updated_completion);
417 
418 	spin_unlock_irqrestore(&data_lock, flags);
419 
420 	t = msecs_to_jiffies(500);
421 	r = wait_for_completion_timeout(&extra_updated_completion, t);
422 	if (r == 0)
423 		DSSWARN("timeout in wait_pending_extra_info_updates\n");
424 }
425 
426 static struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
427 {
428 	struct omap_dss_device *dssdev;
429 
430 	dssdev = mgr->output;
431 	if (dssdev == NULL)
432 		return NULL;
433 
434 	while (dssdev->dst)
435 		dssdev = dssdev->dst;
436 
437 	if (dssdev->driver)
438 		return dssdev;
439 	else
440 		return NULL;
441 }
442 
443 static struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
444 {
445 	return ovl->manager ? dss_mgr_get_device(ovl->manager) : NULL;
446 }
447 
448 static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
449 {
450 	unsigned long timeout = msecs_to_jiffies(500);
451 	u32 irq;
452 	int r;
453 
454 	if (mgr->output == NULL)
455 		return -ENODEV;
456 
457 	r = dispc_runtime_get();
458 	if (r)
459 		return r;
460 
461 	switch (mgr->output->id) {
462 	case OMAP_DSS_OUTPUT_VENC:
463 		irq = DISPC_IRQ_EVSYNC_ODD;
464 		break;
465 	case OMAP_DSS_OUTPUT_HDMI:
466 		irq = DISPC_IRQ_EVSYNC_EVEN;
467 		break;
468 	default:
469 		irq = dispc_mgr_get_vsync_irq(mgr->id);
470 		break;
471 	}
472 
473 	r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
474 
475 	dispc_runtime_put();
476 
477 	return r;
478 }
479 
480 static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
481 {
482 	unsigned long timeout = msecs_to_jiffies(500);
483 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
484 	u32 irq;
485 	unsigned long flags;
486 	int r;
487 	int i;
488 
489 	spin_lock_irqsave(&data_lock, flags);
490 
491 	if (mgr_manual_update(mgr)) {
492 		spin_unlock_irqrestore(&data_lock, flags);
493 		return 0;
494 	}
495 
496 	if (!mp->enabled) {
497 		spin_unlock_irqrestore(&data_lock, flags);
498 		return 0;
499 	}
500 
501 	spin_unlock_irqrestore(&data_lock, flags);
502 
503 	r = dispc_runtime_get();
504 	if (r)
505 		return r;
506 
507 	irq = dispc_mgr_get_vsync_irq(mgr->id);
508 
509 	i = 0;
510 	while (1) {
511 		bool shadow_dirty, dirty;
512 
513 		spin_lock_irqsave(&data_lock, flags);
514 		dirty = mp->info_dirty;
515 		shadow_dirty = mp->shadow_info_dirty;
516 		spin_unlock_irqrestore(&data_lock, flags);
517 
518 		if (!dirty && !shadow_dirty) {
519 			r = 0;
520 			break;
521 		}
522 
523 		/* 4 iterations is the worst case:
524 		 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
525 		 * 2 - first VSYNC, dirty = true
526 		 * 3 - dirty = false, shadow_dirty = true
527 		 * 4 - shadow_dirty = false */
528 		if (i++ == 3) {
529 			DSSERR("mgr(%d)->wait_for_go() not finishing\n",
530 					mgr->id);
531 			r = 0;
532 			break;
533 		}
534 
535 		r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
536 		if (r == -ERESTARTSYS)
537 			break;
538 
539 		if (r) {
540 			DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
541 			break;
542 		}
543 	}
544 
545 	dispc_runtime_put();
546 
547 	return r;
548 }
549 
550 static int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
551 {
552 	unsigned long timeout = msecs_to_jiffies(500);
553 	struct ovl_priv_data *op;
554 	struct mgr_priv_data *mp;
555 	u32 irq;
556 	unsigned long flags;
557 	int r;
558 	int i;
559 
560 	if (!ovl->manager)
561 		return 0;
562 
563 	mp = get_mgr_priv(ovl->manager);
564 
565 	spin_lock_irqsave(&data_lock, flags);
566 
567 	if (ovl_manual_update(ovl)) {
568 		spin_unlock_irqrestore(&data_lock, flags);
569 		return 0;
570 	}
571 
572 	if (!mp->enabled) {
573 		spin_unlock_irqrestore(&data_lock, flags);
574 		return 0;
575 	}
576 
577 	spin_unlock_irqrestore(&data_lock, flags);
578 
579 	r = dispc_runtime_get();
580 	if (r)
581 		return r;
582 
583 	irq = dispc_mgr_get_vsync_irq(ovl->manager->id);
584 
585 	op = get_ovl_priv(ovl);
586 	i = 0;
587 	while (1) {
588 		bool shadow_dirty, dirty;
589 
590 		spin_lock_irqsave(&data_lock, flags);
591 		dirty = op->info_dirty;
592 		shadow_dirty = op->shadow_info_dirty;
593 		spin_unlock_irqrestore(&data_lock, flags);
594 
595 		if (!dirty && !shadow_dirty) {
596 			r = 0;
597 			break;
598 		}
599 
600 		/* 4 iterations is the worst case:
601 		 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
602 		 * 2 - first VSYNC, dirty = true
603 		 * 3 - dirty = false, shadow_dirty = true
604 		 * 4 - shadow_dirty = false */
605 		if (i++ == 3) {
606 			DSSERR("ovl(%d)->wait_for_go() not finishing\n",
607 					ovl->id);
608 			r = 0;
609 			break;
610 		}
611 
612 		r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
613 		if (r == -ERESTARTSYS)
614 			break;
615 
616 		if (r) {
617 			DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
618 			break;
619 		}
620 	}
621 
622 	dispc_runtime_put();
623 
624 	return r;
625 }
626 
627 static void dss_ovl_write_regs(struct omap_overlay *ovl)
628 {
629 	struct ovl_priv_data *op = get_ovl_priv(ovl);
630 	struct omap_overlay_info *oi;
631 	bool replication;
632 	struct mgr_priv_data *mp;
633 	int r;
634 
635 	DSSDBG("writing ovl %d regs\n", ovl->id);
636 
637 	if (!op->enabled || !op->info_dirty)
638 		return;
639 
640 	oi = &op->info;
641 
642 	mp = get_mgr_priv(ovl->manager);
643 
644 	replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
645 
646 	r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);
647 	if (r) {
648 		/*
649 		 * We can't do much here, as this function can be called from
650 		 * vsync interrupt.
651 		 */
652 		DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id);
653 
654 		/* This will leave fifo configurations in a nonoptimal state */
655 		op->enabled = false;
656 		dispc_ovl_enable(ovl->id, false);
657 		return;
658 	}
659 
660 	op->info_dirty = false;
661 	if (mp->updating)
662 		op->shadow_info_dirty = true;
663 }
664 
665 static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
666 {
667 	struct ovl_priv_data *op = get_ovl_priv(ovl);
668 	struct mgr_priv_data *mp;
669 
670 	DSSDBG("writing ovl %d regs extra\n", ovl->id);
671 
672 	if (!op->extra_info_dirty)
673 		return;
674 
675 	/* note: write also when op->enabled == false, so that the ovl gets
676 	 * disabled */
677 
678 	dispc_ovl_enable(ovl->id, op->enabled);
679 	dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
680 
681 	mp = get_mgr_priv(ovl->manager);
682 
683 	op->extra_info_dirty = false;
684 	if (mp->updating)
685 		op->shadow_extra_info_dirty = true;
686 }
687 
688 static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
689 {
690 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
691 	struct omap_overlay *ovl;
692 
693 	DSSDBG("writing mgr %d regs\n", mgr->id);
694 
695 	if (!mp->enabled)
696 		return;
697 
698 	WARN_ON(mp->busy);
699 
700 	/* Commit overlay settings */
701 	list_for_each_entry(ovl, &mgr->overlays, list) {
702 		dss_ovl_write_regs(ovl);
703 		dss_ovl_write_regs_extra(ovl);
704 	}
705 
706 	if (mp->info_dirty) {
707 		dispc_mgr_setup(mgr->id, &mp->info);
708 
709 		mp->info_dirty = false;
710 		if (mp->updating)
711 			mp->shadow_info_dirty = true;
712 	}
713 }
714 
715 static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
716 {
717 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
718 
719 	DSSDBG("writing mgr %d regs extra\n", mgr->id);
720 
721 	if (!mp->extra_info_dirty)
722 		return;
723 
724 	dispc_mgr_set_timings(mgr->id, &mp->timings);
725 
726 	/* lcd_config parameters */
727 	if (dss_mgr_is_lcd(mgr->id))
728 		dispc_mgr_set_lcd_config(mgr->id, &mp->lcd_config);
729 
730 	mp->extra_info_dirty = false;
731 	if (mp->updating)
732 		mp->shadow_extra_info_dirty = true;
733 }
734 
735 static void dss_write_regs(void)
736 {
737 	const int num_mgrs = omap_dss_get_num_overlay_managers();
738 	int i;
739 
740 	for (i = 0; i < num_mgrs; ++i) {
741 		struct omap_overlay_manager *mgr;
742 		struct mgr_priv_data *mp;
743 		int r;
744 
745 		mgr = omap_dss_get_overlay_manager(i);
746 		mp = get_mgr_priv(mgr);
747 
748 		if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
749 			continue;
750 
751 		r = dss_check_settings(mgr);
752 		if (r) {
753 			DSSERR("cannot write registers for manager %s: "
754 					"illegal configuration\n", mgr->name);
755 			continue;
756 		}
757 
758 		dss_mgr_write_regs(mgr);
759 		dss_mgr_write_regs_extra(mgr);
760 	}
761 }
762 
763 static void dss_set_go_bits(void)
764 {
765 	const int num_mgrs = omap_dss_get_num_overlay_managers();
766 	int i;
767 
768 	for (i = 0; i < num_mgrs; ++i) {
769 		struct omap_overlay_manager *mgr;
770 		struct mgr_priv_data *mp;
771 
772 		mgr = omap_dss_get_overlay_manager(i);
773 		mp = get_mgr_priv(mgr);
774 
775 		if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
776 			continue;
777 
778 		if (!need_go(mgr))
779 			continue;
780 
781 		mp->busy = true;
782 
783 		if (!dss_data.irq_enabled && need_isr())
784 			dss_register_vsync_isr();
785 
786 		dispc_mgr_go(mgr->id);
787 	}
788 
789 }
790 
791 static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
792 {
793 	struct omap_overlay *ovl;
794 	struct mgr_priv_data *mp;
795 	struct ovl_priv_data *op;
796 
797 	mp = get_mgr_priv(mgr);
798 	mp->shadow_info_dirty = false;
799 	mp->shadow_extra_info_dirty = false;
800 
801 	list_for_each_entry(ovl, &mgr->overlays, list) {
802 		op = get_ovl_priv(ovl);
803 		op->shadow_info_dirty = false;
804 		op->shadow_extra_info_dirty = false;
805 	}
806 }
807 
808 static int dss_mgr_connect_compat(struct omap_overlay_manager *mgr,
809 		struct omap_dss_device *dst)
810 {
811 	return mgr->set_output(mgr, dst);
812 }
813 
814 static void dss_mgr_disconnect_compat(struct omap_overlay_manager *mgr,
815 		struct omap_dss_device *dst)
816 {
817 	mgr->unset_output(mgr);
818 }
819 
820 static void dss_mgr_start_update_compat(struct omap_overlay_manager *mgr)
821 {
822 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
823 	unsigned long flags;
824 	int r;
825 
826 	spin_lock_irqsave(&data_lock, flags);
827 
828 	WARN_ON(mp->updating);
829 
830 	r = dss_check_settings(mgr);
831 	if (r) {
832 		DSSERR("cannot start manual update: illegal configuration\n");
833 		spin_unlock_irqrestore(&data_lock, flags);
834 		return;
835 	}
836 
837 	dss_mgr_write_regs(mgr);
838 	dss_mgr_write_regs_extra(mgr);
839 
840 	mp->updating = true;
841 
842 	if (!dss_data.irq_enabled && need_isr())
843 		dss_register_vsync_isr();
844 
845 	dispc_mgr_enable_sync(mgr->id);
846 
847 	spin_unlock_irqrestore(&data_lock, flags);
848 }
849 
850 static void dss_apply_irq_handler(void *data, u32 mask);
851 
852 static void dss_register_vsync_isr(void)
853 {
854 	const int num_mgrs = dss_feat_get_num_mgrs();
855 	u32 mask;
856 	int r, i;
857 
858 	mask = 0;
859 	for (i = 0; i < num_mgrs; ++i)
860 		mask |= dispc_mgr_get_vsync_irq(i);
861 
862 	for (i = 0; i < num_mgrs; ++i)
863 		mask |= dispc_mgr_get_framedone_irq(i);
864 
865 	r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
866 	WARN_ON(r);
867 
868 	dss_data.irq_enabled = true;
869 }
870 
871 static void dss_unregister_vsync_isr(void)
872 {
873 	const int num_mgrs = dss_feat_get_num_mgrs();
874 	u32 mask;
875 	int r, i;
876 
877 	mask = 0;
878 	for (i = 0; i < num_mgrs; ++i)
879 		mask |= dispc_mgr_get_vsync_irq(i);
880 
881 	for (i = 0; i < num_mgrs; ++i)
882 		mask |= dispc_mgr_get_framedone_irq(i);
883 
884 	r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask);
885 	WARN_ON(r);
886 
887 	dss_data.irq_enabled = false;
888 }
889 
890 static void dss_apply_irq_handler(void *data, u32 mask)
891 {
892 	const int num_mgrs = dss_feat_get_num_mgrs();
893 	int i;
894 	bool extra_updating;
895 
896 	spin_lock(&data_lock);
897 
898 	/* clear busy, updating flags, shadow_dirty flags */
899 	for (i = 0; i < num_mgrs; i++) {
900 		struct omap_overlay_manager *mgr;
901 		struct mgr_priv_data *mp;
902 
903 		mgr = omap_dss_get_overlay_manager(i);
904 		mp = get_mgr_priv(mgr);
905 
906 		if (!mp->enabled)
907 			continue;
908 
909 		mp->updating = dispc_mgr_is_enabled(i);
910 
911 		if (!mgr_manual_update(mgr)) {
912 			bool was_busy = mp->busy;
913 			mp->busy = dispc_mgr_go_busy(i);
914 
915 			if (was_busy && !mp->busy)
916 				mgr_clear_shadow_dirty(mgr);
917 		}
918 	}
919 
920 	dss_write_regs();
921 	dss_set_go_bits();
922 
923 	extra_updating = extra_info_update_ongoing();
924 	if (!extra_updating)
925 		complete_all(&extra_updated_completion);
926 
927 	/* call framedone handlers for manual update displays */
928 	for (i = 0; i < num_mgrs; i++) {
929 		struct omap_overlay_manager *mgr;
930 		struct mgr_priv_data *mp;
931 
932 		mgr = omap_dss_get_overlay_manager(i);
933 		mp = get_mgr_priv(mgr);
934 
935 		if (!mgr_manual_update(mgr) || !mp->framedone_handler)
936 			continue;
937 
938 		if (mask & dispc_mgr_get_framedone_irq(i))
939 			mp->framedone_handler(mp->framedone_handler_data);
940 	}
941 
942 	if (!need_isr())
943 		dss_unregister_vsync_isr();
944 
945 	spin_unlock(&data_lock);
946 }
947 
948 static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl)
949 {
950 	struct ovl_priv_data *op;
951 
952 	op = get_ovl_priv(ovl);
953 
954 	if (!op->user_info_dirty)
955 		return;
956 
957 	op->user_info_dirty = false;
958 	op->info_dirty = true;
959 	op->info = op->user_info;
960 }
961 
962 static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
963 {
964 	struct mgr_priv_data *mp;
965 
966 	mp = get_mgr_priv(mgr);
967 
968 	if (!mp->user_info_dirty)
969 		return;
970 
971 	mp->user_info_dirty = false;
972 	mp->info_dirty = true;
973 	mp->info = mp->user_info;
974 }
975 
976 static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
977 {
978 	unsigned long flags;
979 	struct omap_overlay *ovl;
980 	int r;
981 
982 	DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
983 
984 	spin_lock_irqsave(&data_lock, flags);
985 
986 	r = dss_check_settings_apply(mgr);
987 	if (r) {
988 		spin_unlock_irqrestore(&data_lock, flags);
989 		DSSERR("failed to apply settings: illegal configuration.\n");
990 		return r;
991 	}
992 
993 	/* Configure overlays */
994 	list_for_each_entry(ovl, &mgr->overlays, list)
995 		omap_dss_mgr_apply_ovl(ovl);
996 
997 	/* Configure manager */
998 	omap_dss_mgr_apply_mgr(mgr);
999 
1000 	dss_write_regs();
1001 	dss_set_go_bits();
1002 
1003 	spin_unlock_irqrestore(&data_lock, flags);
1004 
1005 	return 0;
1006 }
1007 
1008 static void dss_apply_ovl_enable(struct omap_overlay *ovl, bool enable)
1009 {
1010 	struct ovl_priv_data *op;
1011 
1012 	op = get_ovl_priv(ovl);
1013 
1014 	if (op->enabled == enable)
1015 		return;
1016 
1017 	op->enabled = enable;
1018 	op->extra_info_dirty = true;
1019 }
1020 
1021 static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
1022 		u32 fifo_low, u32 fifo_high)
1023 {
1024 	struct ovl_priv_data *op = get_ovl_priv(ovl);
1025 
1026 	if (op->fifo_low == fifo_low && op->fifo_high == fifo_high)
1027 		return;
1028 
1029 	op->fifo_low = fifo_low;
1030 	op->fifo_high = fifo_high;
1031 	op->extra_info_dirty = true;
1032 }
1033 
1034 static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
1035 {
1036 	struct ovl_priv_data *op = get_ovl_priv(ovl);
1037 	u32 fifo_low, fifo_high;
1038 	bool use_fifo_merge = false;
1039 
1040 	if (!op->enabled && !op->enabling)
1041 		return;
1042 
1043 	dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high,
1044 			use_fifo_merge, ovl_manual_update(ovl));
1045 
1046 	dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
1047 }
1048 
1049 static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
1050 {
1051 	struct omap_overlay *ovl;
1052 	struct mgr_priv_data *mp;
1053 
1054 	mp = get_mgr_priv(mgr);
1055 
1056 	if (!mp->enabled)
1057 		return;
1058 
1059 	list_for_each_entry(ovl, &mgr->overlays, list)
1060 		dss_ovl_setup_fifo(ovl);
1061 }
1062 
1063 static void dss_setup_fifos(void)
1064 {
1065 	const int num_mgrs = omap_dss_get_num_overlay_managers();
1066 	struct omap_overlay_manager *mgr;
1067 	int i;
1068 
1069 	for (i = 0; i < num_mgrs; ++i) {
1070 		mgr = omap_dss_get_overlay_manager(i);
1071 		dss_mgr_setup_fifos(mgr);
1072 	}
1073 }
1074 
1075 static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
1076 {
1077 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
1078 	unsigned long flags;
1079 	int r;
1080 
1081 	mutex_lock(&apply_lock);
1082 
1083 	if (mp->enabled)
1084 		goto out;
1085 
1086 	spin_lock_irqsave(&data_lock, flags);
1087 
1088 	mp->enabled = true;
1089 
1090 	r = dss_check_settings(mgr);
1091 	if (r) {
1092 		DSSERR("failed to enable manager %d: check_settings failed\n",
1093 				mgr->id);
1094 		goto err;
1095 	}
1096 
1097 	dss_setup_fifos();
1098 
1099 	dss_write_regs();
1100 	dss_set_go_bits();
1101 
1102 	if (!mgr_manual_update(mgr))
1103 		mp->updating = true;
1104 
1105 	if (!dss_data.irq_enabled && need_isr())
1106 		dss_register_vsync_isr();
1107 
1108 	spin_unlock_irqrestore(&data_lock, flags);
1109 
1110 	if (!mgr_manual_update(mgr))
1111 		dispc_mgr_enable_sync(mgr->id);
1112 
1113 out:
1114 	mutex_unlock(&apply_lock);
1115 
1116 	return 0;
1117 
1118 err:
1119 	mp->enabled = false;
1120 	spin_unlock_irqrestore(&data_lock, flags);
1121 	mutex_unlock(&apply_lock);
1122 	return r;
1123 }
1124 
1125 static void dss_mgr_disable_compat(struct omap_overlay_manager *mgr)
1126 {
1127 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
1128 	unsigned long flags;
1129 
1130 	mutex_lock(&apply_lock);
1131 
1132 	if (!mp->enabled)
1133 		goto out;
1134 
1135 	wait_pending_extra_info_updates();
1136 
1137 	if (!mgr_manual_update(mgr))
1138 		dispc_mgr_disable_sync(mgr->id);
1139 
1140 	spin_lock_irqsave(&data_lock, flags);
1141 
1142 	mp->updating = false;
1143 	mp->enabled = false;
1144 
1145 	spin_unlock_irqrestore(&data_lock, flags);
1146 
1147 out:
1148 	mutex_unlock(&apply_lock);
1149 }
1150 
1151 static int dss_mgr_set_info(struct omap_overlay_manager *mgr,
1152 		struct omap_overlay_manager_info *info)
1153 {
1154 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
1155 	unsigned long flags;
1156 	int r;
1157 
1158 	r = dss_mgr_simple_check(mgr, info);
1159 	if (r)
1160 		return r;
1161 
1162 	spin_lock_irqsave(&data_lock, flags);
1163 
1164 	mp->user_info = *info;
1165 	mp->user_info_dirty = true;
1166 
1167 	spin_unlock_irqrestore(&data_lock, flags);
1168 
1169 	return 0;
1170 }
1171 
1172 static void dss_mgr_get_info(struct omap_overlay_manager *mgr,
1173 		struct omap_overlay_manager_info *info)
1174 {
1175 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
1176 	unsigned long flags;
1177 
1178 	spin_lock_irqsave(&data_lock, flags);
1179 
1180 	*info = mp->user_info;
1181 
1182 	spin_unlock_irqrestore(&data_lock, flags);
1183 }
1184 
1185 static int dss_mgr_set_output(struct omap_overlay_manager *mgr,
1186 		struct omap_dss_device *output)
1187 {
1188 	int r;
1189 
1190 	mutex_lock(&apply_lock);
1191 
1192 	if (mgr->output) {
1193 		DSSERR("manager %s is already connected to an output\n",
1194 			mgr->name);
1195 		r = -EINVAL;
1196 		goto err;
1197 	}
1198 
1199 	if ((mgr->supported_outputs & output->id) == 0) {
1200 		DSSERR("output does not support manager %s\n",
1201 			mgr->name);
1202 		r = -EINVAL;
1203 		goto err;
1204 	}
1205 
1206 	output->manager = mgr;
1207 	mgr->output = output;
1208 
1209 	mutex_unlock(&apply_lock);
1210 
1211 	return 0;
1212 err:
1213 	mutex_unlock(&apply_lock);
1214 	return r;
1215 }
1216 
1217 static int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
1218 {
1219 	int r;
1220 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
1221 	unsigned long flags;
1222 
1223 	mutex_lock(&apply_lock);
1224 
1225 	if (!mgr->output) {
1226 		DSSERR("failed to unset output, output not set\n");
1227 		r = -EINVAL;
1228 		goto err;
1229 	}
1230 
1231 	spin_lock_irqsave(&data_lock, flags);
1232 
1233 	if (mp->enabled) {
1234 		DSSERR("output can't be unset when manager is enabled\n");
1235 		r = -EINVAL;
1236 		goto err1;
1237 	}
1238 
1239 	spin_unlock_irqrestore(&data_lock, flags);
1240 
1241 	mgr->output->manager = NULL;
1242 	mgr->output = NULL;
1243 
1244 	mutex_unlock(&apply_lock);
1245 
1246 	return 0;
1247 err1:
1248 	spin_unlock_irqrestore(&data_lock, flags);
1249 err:
1250 	mutex_unlock(&apply_lock);
1251 
1252 	return r;
1253 }
1254 
1255 static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
1256 		const struct omap_video_timings *timings)
1257 {
1258 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
1259 
1260 	mp->timings = *timings;
1261 	mp->extra_info_dirty = true;
1262 }
1263 
1264 static void dss_mgr_set_timings_compat(struct omap_overlay_manager *mgr,
1265 		const struct omap_video_timings *timings)
1266 {
1267 	unsigned long flags;
1268 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
1269 
1270 	spin_lock_irqsave(&data_lock, flags);
1271 
1272 	if (mp->updating) {
1273 		DSSERR("cannot set timings for %s: manager needs to be disabled\n",
1274 			mgr->name);
1275 		goto out;
1276 	}
1277 
1278 	dss_apply_mgr_timings(mgr, timings);
1279 out:
1280 	spin_unlock_irqrestore(&data_lock, flags);
1281 }
1282 
1283 static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
1284 		const struct dss_lcd_mgr_config *config)
1285 {
1286 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
1287 
1288 	mp->lcd_config = *config;
1289 	mp->extra_info_dirty = true;
1290 }
1291 
1292 static void dss_mgr_set_lcd_config_compat(struct omap_overlay_manager *mgr,
1293 		const struct dss_lcd_mgr_config *config)
1294 {
1295 	unsigned long flags;
1296 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
1297 
1298 	spin_lock_irqsave(&data_lock, flags);
1299 
1300 	if (mp->enabled) {
1301 		DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
1302 			mgr->name);
1303 		goto out;
1304 	}
1305 
1306 	dss_apply_mgr_lcd_config(mgr, config);
1307 out:
1308 	spin_unlock_irqrestore(&data_lock, flags);
1309 }
1310 
1311 static int dss_ovl_set_info(struct omap_overlay *ovl,
1312 		struct omap_overlay_info *info)
1313 {
1314 	struct ovl_priv_data *op = get_ovl_priv(ovl);
1315 	unsigned long flags;
1316 	int r;
1317 
1318 	r = dss_ovl_simple_check(ovl, info);
1319 	if (r)
1320 		return r;
1321 
1322 	spin_lock_irqsave(&data_lock, flags);
1323 
1324 	op->user_info = *info;
1325 	op->user_info_dirty = true;
1326 
1327 	spin_unlock_irqrestore(&data_lock, flags);
1328 
1329 	return 0;
1330 }
1331 
1332 static void dss_ovl_get_info(struct omap_overlay *ovl,
1333 		struct omap_overlay_info *info)
1334 {
1335 	struct ovl_priv_data *op = get_ovl_priv(ovl);
1336 	unsigned long flags;
1337 
1338 	spin_lock_irqsave(&data_lock, flags);
1339 
1340 	*info = op->user_info;
1341 
1342 	spin_unlock_irqrestore(&data_lock, flags);
1343 }
1344 
1345 static int dss_ovl_set_manager(struct omap_overlay *ovl,
1346 		struct omap_overlay_manager *mgr)
1347 {
1348 	struct ovl_priv_data *op = get_ovl_priv(ovl);
1349 	unsigned long flags;
1350 	int r;
1351 
1352 	if (!mgr)
1353 		return -EINVAL;
1354 
1355 	mutex_lock(&apply_lock);
1356 
1357 	if (ovl->manager) {
1358 		DSSERR("overlay '%s' already has a manager '%s'\n",
1359 				ovl->name, ovl->manager->name);
1360 		r = -EINVAL;
1361 		goto err;
1362 	}
1363 
1364 	r = dispc_runtime_get();
1365 	if (r)
1366 		goto err;
1367 
1368 	spin_lock_irqsave(&data_lock, flags);
1369 
1370 	if (op->enabled) {
1371 		spin_unlock_irqrestore(&data_lock, flags);
1372 		DSSERR("overlay has to be disabled to change the manager\n");
1373 		r = -EINVAL;
1374 		goto err1;
1375 	}
1376 
1377 	dispc_ovl_set_channel_out(ovl->id, mgr->id);
1378 
1379 	ovl->manager = mgr;
1380 	list_add_tail(&ovl->list, &mgr->overlays);
1381 
1382 	spin_unlock_irqrestore(&data_lock, flags);
1383 
1384 	dispc_runtime_put();
1385 
1386 	mutex_unlock(&apply_lock);
1387 
1388 	return 0;
1389 
1390 err1:
1391 	dispc_runtime_put();
1392 err:
1393 	mutex_unlock(&apply_lock);
1394 	return r;
1395 }
1396 
1397 static int dss_ovl_unset_manager(struct omap_overlay *ovl)
1398 {
1399 	struct ovl_priv_data *op = get_ovl_priv(ovl);
1400 	unsigned long flags;
1401 	int r;
1402 
1403 	mutex_lock(&apply_lock);
1404 
1405 	if (!ovl->manager) {
1406 		DSSERR("failed to detach overlay: manager not set\n");
1407 		r = -EINVAL;
1408 		goto err;
1409 	}
1410 
1411 	spin_lock_irqsave(&data_lock, flags);
1412 
1413 	if (op->enabled) {
1414 		spin_unlock_irqrestore(&data_lock, flags);
1415 		DSSERR("overlay has to be disabled to unset the manager\n");
1416 		r = -EINVAL;
1417 		goto err;
1418 	}
1419 
1420 	spin_unlock_irqrestore(&data_lock, flags);
1421 
1422 	/* wait for pending extra_info updates to ensure the ovl is disabled */
1423 	wait_pending_extra_info_updates();
1424 
1425 	/*
1426 	 * For a manual update display, there is no guarantee that the overlay
1427 	 * is really disabled in HW, we may need an extra update from this
1428 	 * manager before the configurations can go in. Return an error if the
1429 	 * overlay needed an update from the manager.
1430 	 *
1431 	 * TODO: Instead of returning an error, try to do a dummy manager update
1432 	 * here to disable the overlay in hardware. Use the *GATED fields in
1433 	 * the DISPC_CONFIG registers to do a dummy update.
1434 	 */
1435 	spin_lock_irqsave(&data_lock, flags);
1436 
1437 	if (ovl_manual_update(ovl) && op->extra_info_dirty) {
1438 		spin_unlock_irqrestore(&data_lock, flags);
1439 		DSSERR("need an update to change the manager\n");
1440 		r = -EINVAL;
1441 		goto err;
1442 	}
1443 
1444 	ovl->manager = NULL;
1445 	list_del(&ovl->list);
1446 
1447 	spin_unlock_irqrestore(&data_lock, flags);
1448 
1449 	mutex_unlock(&apply_lock);
1450 
1451 	return 0;
1452 err:
1453 	mutex_unlock(&apply_lock);
1454 	return r;
1455 }
1456 
1457 static bool dss_ovl_is_enabled(struct omap_overlay *ovl)
1458 {
1459 	struct ovl_priv_data *op = get_ovl_priv(ovl);
1460 	unsigned long flags;
1461 	bool e;
1462 
1463 	spin_lock_irqsave(&data_lock, flags);
1464 
1465 	e = op->enabled;
1466 
1467 	spin_unlock_irqrestore(&data_lock, flags);
1468 
1469 	return e;
1470 }
1471 
1472 static int dss_ovl_enable(struct omap_overlay *ovl)
1473 {
1474 	struct ovl_priv_data *op = get_ovl_priv(ovl);
1475 	unsigned long flags;
1476 	int r;
1477 
1478 	mutex_lock(&apply_lock);
1479 
1480 	if (op->enabled) {
1481 		r = 0;
1482 		goto err1;
1483 	}
1484 
1485 	if (ovl->manager == NULL || ovl->manager->output == NULL) {
1486 		r = -EINVAL;
1487 		goto err1;
1488 	}
1489 
1490 	spin_lock_irqsave(&data_lock, flags);
1491 
1492 	op->enabling = true;
1493 
1494 	r = dss_check_settings(ovl->manager);
1495 	if (r) {
1496 		DSSERR("failed to enable overlay %d: check_settings failed\n",
1497 				ovl->id);
1498 		goto err2;
1499 	}
1500 
1501 	dss_setup_fifos();
1502 
1503 	op->enabling = false;
1504 	dss_apply_ovl_enable(ovl, true);
1505 
1506 	dss_write_regs();
1507 	dss_set_go_bits();
1508 
1509 	spin_unlock_irqrestore(&data_lock, flags);
1510 
1511 	mutex_unlock(&apply_lock);
1512 
1513 	return 0;
1514 err2:
1515 	op->enabling = false;
1516 	spin_unlock_irqrestore(&data_lock, flags);
1517 err1:
1518 	mutex_unlock(&apply_lock);
1519 	return r;
1520 }
1521 
1522 static int dss_ovl_disable(struct omap_overlay *ovl)
1523 {
1524 	struct ovl_priv_data *op = get_ovl_priv(ovl);
1525 	unsigned long flags;
1526 	int r;
1527 
1528 	mutex_lock(&apply_lock);
1529 
1530 	if (!op->enabled) {
1531 		r = 0;
1532 		goto err;
1533 	}
1534 
1535 	if (ovl->manager == NULL || ovl->manager->output == NULL) {
1536 		r = -EINVAL;
1537 		goto err;
1538 	}
1539 
1540 	spin_lock_irqsave(&data_lock, flags);
1541 
1542 	dss_apply_ovl_enable(ovl, false);
1543 	dss_write_regs();
1544 	dss_set_go_bits();
1545 
1546 	spin_unlock_irqrestore(&data_lock, flags);
1547 
1548 	mutex_unlock(&apply_lock);
1549 
1550 	return 0;
1551 
1552 err:
1553 	mutex_unlock(&apply_lock);
1554 	return r;
1555 }
1556 
1557 static int dss_mgr_register_framedone_handler_compat(struct omap_overlay_manager *mgr,
1558 		void (*handler)(void *), void *data)
1559 {
1560 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
1561 
1562 	if (mp->framedone_handler)
1563 		return -EBUSY;
1564 
1565 	mp->framedone_handler = handler;
1566 	mp->framedone_handler_data = data;
1567 
1568 	return 0;
1569 }
1570 
1571 static void dss_mgr_unregister_framedone_handler_compat(struct omap_overlay_manager *mgr,
1572 		void (*handler)(void *), void *data)
1573 {
1574 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
1575 
1576 	WARN_ON(mp->framedone_handler != handler ||
1577 			mp->framedone_handler_data != data);
1578 
1579 	mp->framedone_handler = NULL;
1580 	mp->framedone_handler_data = NULL;
1581 }
1582 
1583 static const struct dss_mgr_ops apply_mgr_ops = {
1584 	.connect = dss_mgr_connect_compat,
1585 	.disconnect = dss_mgr_disconnect_compat,
1586 	.start_update = dss_mgr_start_update_compat,
1587 	.enable = dss_mgr_enable_compat,
1588 	.disable = dss_mgr_disable_compat,
1589 	.set_timings = dss_mgr_set_timings_compat,
1590 	.set_lcd_config = dss_mgr_set_lcd_config_compat,
1591 	.register_framedone_handler = dss_mgr_register_framedone_handler_compat,
1592 	.unregister_framedone_handler = dss_mgr_unregister_framedone_handler_compat,
1593 };
1594 
1595 static int compat_refcnt;
1596 static DEFINE_MUTEX(compat_init_lock);
1597 
1598 int omapdss_compat_init(void)
1599 {
1600 	struct platform_device *pdev = dss_get_core_pdev();
1601 	int i, r;
1602 
1603 	mutex_lock(&compat_init_lock);
1604 
1605 	if (compat_refcnt++ > 0)
1606 		goto out;
1607 
1608 	apply_init_priv();
1609 
1610 	dss_init_overlay_managers_sysfs(pdev);
1611 	dss_init_overlays(pdev);
1612 
1613 	for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
1614 		struct omap_overlay_manager *mgr;
1615 
1616 		mgr = omap_dss_get_overlay_manager(i);
1617 
1618 		mgr->set_output = &dss_mgr_set_output;
1619 		mgr->unset_output = &dss_mgr_unset_output;
1620 		mgr->apply = &omap_dss_mgr_apply;
1621 		mgr->set_manager_info = &dss_mgr_set_info;
1622 		mgr->get_manager_info = &dss_mgr_get_info;
1623 		mgr->wait_for_go = &dss_mgr_wait_for_go;
1624 		mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
1625 		mgr->get_device = &dss_mgr_get_device;
1626 	}
1627 
1628 	for (i = 0; i < omap_dss_get_num_overlays(); i++) {
1629 		struct omap_overlay *ovl = omap_dss_get_overlay(i);
1630 
1631 		ovl->is_enabled = &dss_ovl_is_enabled;
1632 		ovl->enable = &dss_ovl_enable;
1633 		ovl->disable = &dss_ovl_disable;
1634 		ovl->set_manager = &dss_ovl_set_manager;
1635 		ovl->unset_manager = &dss_ovl_unset_manager;
1636 		ovl->set_overlay_info = &dss_ovl_set_info;
1637 		ovl->get_overlay_info = &dss_ovl_get_info;
1638 		ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
1639 		ovl->get_device = &dss_ovl_get_device;
1640 	}
1641 
1642 	r = dss_install_mgr_ops(&apply_mgr_ops);
1643 	if (r)
1644 		goto err_mgr_ops;
1645 
1646 	r = display_init_sysfs(pdev);
1647 	if (r)
1648 		goto err_disp_sysfs;
1649 
1650 	dispc_runtime_get();
1651 
1652 	r = dss_dispc_initialize_irq();
1653 	if (r)
1654 		goto err_init_irq;
1655 
1656 	dispc_runtime_put();
1657 
1658 out:
1659 	mutex_unlock(&compat_init_lock);
1660 
1661 	return 0;
1662 
1663 err_init_irq:
1664 	dispc_runtime_put();
1665 	display_uninit_sysfs(pdev);
1666 
1667 err_disp_sysfs:
1668 	dss_uninstall_mgr_ops();
1669 
1670 err_mgr_ops:
1671 	dss_uninit_overlay_managers_sysfs(pdev);
1672 	dss_uninit_overlays(pdev);
1673 
1674 	compat_refcnt--;
1675 
1676 	mutex_unlock(&compat_init_lock);
1677 
1678 	return r;
1679 }
1680 EXPORT_SYMBOL(omapdss_compat_init);
1681 
1682 void omapdss_compat_uninit(void)
1683 {
1684 	struct platform_device *pdev = dss_get_core_pdev();
1685 
1686 	mutex_lock(&compat_init_lock);
1687 
1688 	if (--compat_refcnt > 0)
1689 		goto out;
1690 
1691 	dss_dispc_uninitialize_irq();
1692 
1693 	display_uninit_sysfs(pdev);
1694 
1695 	dss_uninstall_mgr_ops();
1696 
1697 	dss_uninit_overlay_managers_sysfs(pdev);
1698 	dss_uninit_overlays(pdev);
1699 out:
1700 	mutex_unlock(&compat_init_lock);
1701 }
1702 EXPORT_SYMBOL(omapdss_compat_uninit);
1703