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