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
50struct 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
73struct 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
103static 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 */
111static DEFINE_SPINLOCK(data_lock);
112/* lock for blocking functions */
113static DEFINE_MUTEX(apply_lock);
114static DECLARE_COMPLETION(extra_updated_completion);
115
116static void dss_register_vsync_isr(void);
117
118static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl)
119{
120	return &dss_data.ovl_priv_data_array[ovl->id];
121}
122
123static 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
128static 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 */
181static 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
188static 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
195static 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 */
235static 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 */
244static int dss_check_settings_apply(struct omap_overlay_manager *mgr)
245{
246	return dss_check_settings_low(mgr, true);
247}
248
249static 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
332static 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 */
353static 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 */
387static 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
413static 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
430static 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
435static 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
467static 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
537static 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
614static 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
652static 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
675static 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
702static 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
722static 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
750static 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
778static 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
795static 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
801static void dss_mgr_disconnect_compat(struct omap_overlay_manager *mgr,
802		struct omap_dss_device *dst)
803{
804	mgr->unset_output(mgr);
805}
806
807static 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
837static void dss_apply_irq_handler(void *data, u32 mask);
838
839static 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
858static 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
877static 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
935static 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
949static 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
963static 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
995static 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
1008static 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
1021static 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
1036static 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
1050static 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
1062static 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
1100out:
1101	mutex_unlock(&apply_lock);
1102
1103	return 0;
1104
1105err:
1106	mp->enabled = false;
1107	spin_unlock_irqrestore(&data_lock, flags);
1108	mutex_unlock(&apply_lock);
1109	return r;
1110}
1111
1112static 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
1134out:
1135	mutex_unlock(&apply_lock);
1136}
1137
1138static 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
1159static 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
1172static 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;
1199err:
1200	mutex_unlock(&apply_lock);
1201	return r;
1202}
1203
1204static 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;
1234err1:
1235	spin_unlock_irqrestore(&data_lock, flags);
1236err:
1237	mutex_unlock(&apply_lock);
1238
1239	return r;
1240}
1241
1242static 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
1251static 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);
1266out:
1267	spin_unlock_irqrestore(&data_lock, flags);
1268}
1269
1270static 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
1279static 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);
1294out:
1295	spin_unlock_irqrestore(&data_lock, flags);
1296}
1297
1298static 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
1319static 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
1332static 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
1377err1:
1378	dispc_runtime_put();
1379err:
1380	mutex_unlock(&apply_lock);
1381	return r;
1382}
1383
1384static 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;
1439err:
1440	mutex_unlock(&apply_lock);
1441	return r;
1442}
1443
1444static 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
1459static 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;
1501err2:
1502	op->enabling = false;
1503	spin_unlock_irqrestore(&data_lock, flags);
1504err1:
1505	mutex_unlock(&apply_lock);
1506	return r;
1507}
1508
1509static 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
1539err:
1540	mutex_unlock(&apply_lock);
1541	return r;
1542}
1543
1544static 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
1558static 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
1570static 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
1582static int compat_refcnt;
1583static DEFINE_MUTEX(compat_init_lock);
1584
1585int 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
1645out:
1646	mutex_unlock(&compat_init_lock);
1647
1648	return 0;
1649
1650err_init_irq:
1651	dispc_runtime_put();
1652	display_uninit_sysfs(pdev);
1653
1654err_disp_sysfs:
1655	dss_uninstall_mgr_ops();
1656
1657err_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}
1667EXPORT_SYMBOL(omapdss_compat_init);
1668
1669void 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);
1686out:
1687	mutex_unlock(&compat_init_lock);
1688}
1689EXPORT_SYMBOL(omapdss_compat_uninit);
1690