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