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