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