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