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