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