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