]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/video/omap2/dss/apply.c
2b1fa851a8b9f877c99362ff00159acdfc68d7f5
[karo-tx-linux.git] / drivers / video / omap2 / dss / apply.c
1 /*
2  * Copyright (C) 2011 Texas Instruments
3  * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published by
7  * the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #define DSS_SUBSYS_NAME "APPLY"
19
20 #include <linux/kernel.h>
21 #include <linux/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 = get_mgr_priv(mgr);
425         u32 irq;
426         unsigned long flags;
427         int r;
428         int i;
429
430         spin_lock_irqsave(&data_lock, flags);
431
432         if (mgr_manual_update(mgr)) {
433                 spin_unlock_irqrestore(&data_lock, flags);
434                 return 0;
435         }
436
437         if (!mp->enabled) {
438                 spin_unlock_irqrestore(&data_lock, flags);
439                 return 0;
440         }
441
442         spin_unlock_irqrestore(&data_lock, flags);
443
444         r = dispc_runtime_get();
445         if (r)
446                 return r;
447
448         irq = dispc_mgr_get_vsync_irq(mgr->id);
449
450         i = 0;
451         while (1) {
452                 bool shadow_dirty, dirty;
453
454                 spin_lock_irqsave(&data_lock, flags);
455                 dirty = mp->info_dirty;
456                 shadow_dirty = mp->shadow_info_dirty;
457                 spin_unlock_irqrestore(&data_lock, flags);
458
459                 if (!dirty && !shadow_dirty) {
460                         r = 0;
461                         break;
462                 }
463
464                 /* 4 iterations is the worst case:
465                  * 1 - initial iteration, dirty = true (between VFP and VSYNC)
466                  * 2 - first VSYNC, dirty = true
467                  * 3 - dirty = false, shadow_dirty = true
468                  * 4 - shadow_dirty = false */
469                 if (i++ == 3) {
470                         DSSERR("mgr(%d)->wait_for_go() not finishing\n",
471                                         mgr->id);
472                         r = 0;
473                         break;
474                 }
475
476                 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
477                 if (r == -ERESTARTSYS)
478                         break;
479
480                 if (r) {
481                         DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
482                         break;
483                 }
484         }
485
486         dispc_runtime_put();
487
488         return r;
489 }
490
491 int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
492 {
493         unsigned long timeout = msecs_to_jiffies(500);
494         struct ovl_priv_data *op;
495         struct mgr_priv_data *mp;
496         u32 irq;
497         unsigned long flags;
498         int r;
499         int i;
500
501         if (!ovl->manager)
502                 return 0;
503
504         mp = get_mgr_priv(ovl->manager);
505
506         spin_lock_irqsave(&data_lock, flags);
507
508         if (ovl_manual_update(ovl)) {
509                 spin_unlock_irqrestore(&data_lock, flags);
510                 return 0;
511         }
512
513         if (!mp->enabled) {
514                 spin_unlock_irqrestore(&data_lock, flags);
515                 return 0;
516         }
517
518         spin_unlock_irqrestore(&data_lock, flags);
519
520         r = dispc_runtime_get();
521         if (r)
522                 return r;
523
524         irq = dispc_mgr_get_vsync_irq(ovl->manager->id);
525
526         op = get_ovl_priv(ovl);
527         i = 0;
528         while (1) {
529                 bool shadow_dirty, dirty;
530
531                 spin_lock_irqsave(&data_lock, flags);
532                 dirty = op->info_dirty;
533                 shadow_dirty = op->shadow_info_dirty;
534                 spin_unlock_irqrestore(&data_lock, flags);
535
536                 if (!dirty && !shadow_dirty) {
537                         r = 0;
538                         break;
539                 }
540
541                 /* 4 iterations is the worst case:
542                  * 1 - initial iteration, dirty = true (between VFP and VSYNC)
543                  * 2 - first VSYNC, dirty = true
544                  * 3 - dirty = false, shadow_dirty = true
545                  * 4 - shadow_dirty = false */
546                 if (i++ == 3) {
547                         DSSERR("ovl(%d)->wait_for_go() not finishing\n",
548                                         ovl->id);
549                         r = 0;
550                         break;
551                 }
552
553                 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
554                 if (r == -ERESTARTSYS)
555                         break;
556
557                 if (r) {
558                         DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
559                         break;
560                 }
561         }
562
563         dispc_runtime_put();
564
565         return r;
566 }
567
568 static void dss_ovl_write_regs(struct omap_overlay *ovl)
569 {
570         struct ovl_priv_data *op = get_ovl_priv(ovl);
571         struct omap_overlay_info *oi;
572         bool replication;
573         struct mgr_priv_data *mp;
574         int r;
575
576         DSSDBGF("%d", ovl->id);
577
578         if (!op->enabled || !op->info_dirty)
579                 return;
580
581         oi = &op->info;
582
583         mp = get_mgr_priv(ovl->manager);
584
585         replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
586
587         r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings);
588         if (r) {
589                 /*
590                  * We can't do much here, as this function can be called from
591                  * vsync interrupt.
592                  */
593                 DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id);
594
595                 /* This will leave fifo configurations in a nonoptimal state */
596                 op->enabled = false;
597                 dispc_ovl_enable(ovl->id, false);
598                 return;
599         }
600
601         op->info_dirty = false;
602         if (mp->updating)
603                 op->shadow_info_dirty = true;
604 }
605
606 static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
607 {
608         struct ovl_priv_data *op = get_ovl_priv(ovl);
609         struct mgr_priv_data *mp;
610
611         DSSDBGF("%d", ovl->id);
612
613         if (!op->extra_info_dirty)
614                 return;
615
616         /* note: write also when op->enabled == false, so that the ovl gets
617          * disabled */
618
619         dispc_ovl_enable(ovl->id, op->enabled);
620         dispc_ovl_set_channel_out(ovl->id, op->channel);
621         dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
622
623         mp = get_mgr_priv(ovl->manager);
624
625         op->extra_info_dirty = false;
626         if (mp->updating)
627                 op->shadow_extra_info_dirty = true;
628 }
629
630 static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
631 {
632         struct mgr_priv_data *mp = get_mgr_priv(mgr);
633         struct omap_overlay *ovl;
634
635         DSSDBGF("%d", mgr->id);
636
637         if (!mp->enabled)
638                 return;
639
640         WARN_ON(mp->busy);
641
642         /* Commit overlay settings */
643         list_for_each_entry(ovl, &mgr->overlays, list) {
644                 dss_ovl_write_regs(ovl);
645                 dss_ovl_write_regs_extra(ovl);
646         }
647
648         if (mp->info_dirty) {
649                 dispc_mgr_setup(mgr->id, &mp->info);
650
651                 mp->info_dirty = false;
652                 if (mp->updating)
653                         mp->shadow_info_dirty = true;
654         }
655 }
656
657 static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
658 {
659         struct mgr_priv_data *mp = get_mgr_priv(mgr);
660
661         DSSDBGF("%d", mgr->id);
662
663         if (!mp->extra_info_dirty)
664                 return;
665
666         dispc_mgr_set_timings(mgr->id, &mp->timings);
667
668         /* lcd_config parameters */
669         if (dss_mgr_is_lcd(mgr->id)) {
670                 dispc_mgr_set_io_pad_mode(mp->lcd_config.io_pad_mode);
671
672                 dispc_mgr_enable_stallmode(mgr->id, mp->lcd_config.stallmode);
673                 dispc_mgr_enable_fifohandcheck(mgr->id,
674                         mp->lcd_config.fifohandcheck);
675
676                 dispc_mgr_set_clock_div(mgr->id, &mp->lcd_config.clock_info);
677
678                 dispc_mgr_set_tft_data_lines(mgr->id,
679                         mp->lcd_config.video_port_width);
680
681                 dispc_lcd_enable_signal_polarity(mp->lcd_config.lcden_sig_polarity);
682
683                 dispc_mgr_set_lcd_type_tft(mgr->id);
684         }
685
686         mp->extra_info_dirty = false;
687         if (mp->updating)
688                 mp->shadow_extra_info_dirty = true;
689 }
690
691 static void dss_write_regs(void)
692 {
693         const int num_mgrs = omap_dss_get_num_overlay_managers();
694         int i;
695
696         for (i = 0; i < num_mgrs; ++i) {
697                 struct omap_overlay_manager *mgr;
698                 struct mgr_priv_data *mp;
699                 int r;
700
701                 mgr = omap_dss_get_overlay_manager(i);
702                 mp = get_mgr_priv(mgr);
703
704                 if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
705                         continue;
706
707                 r = dss_check_settings(mgr);
708                 if (r) {
709                         DSSERR("cannot write registers for manager %s: "
710                                         "illegal configuration\n", mgr->name);
711                         continue;
712                 }
713
714                 dss_mgr_write_regs(mgr);
715                 dss_mgr_write_regs_extra(mgr);
716         }
717 }
718
719 static void dss_set_go_bits(void)
720 {
721         const int num_mgrs = omap_dss_get_num_overlay_managers();
722         int i;
723
724         for (i = 0; i < num_mgrs; ++i) {
725                 struct omap_overlay_manager *mgr;
726                 struct mgr_priv_data *mp;
727
728                 mgr = omap_dss_get_overlay_manager(i);
729                 mp = get_mgr_priv(mgr);
730
731                 if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
732                         continue;
733
734                 if (!need_go(mgr))
735                         continue;
736
737                 mp->busy = true;
738
739                 if (!dss_data.irq_enabled && need_isr())
740                         dss_register_vsync_isr();
741
742                 dispc_mgr_go(mgr->id);
743         }
744
745 }
746
747 static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
748 {
749         struct omap_overlay *ovl;
750         struct mgr_priv_data *mp;
751         struct ovl_priv_data *op;
752
753         mp = get_mgr_priv(mgr);
754         mp->shadow_info_dirty = false;
755         mp->shadow_extra_info_dirty = false;
756
757         list_for_each_entry(ovl, &mgr->overlays, list) {
758                 op = get_ovl_priv(ovl);
759                 op->shadow_info_dirty = false;
760                 op->shadow_extra_info_dirty = false;
761         }
762 }
763
764 void dss_mgr_start_update(struct omap_overlay_manager *mgr)
765 {
766         struct mgr_priv_data *mp = get_mgr_priv(mgr);
767         unsigned long flags;
768         int r;
769
770         spin_lock_irqsave(&data_lock, flags);
771
772         WARN_ON(mp->updating);
773
774         r = dss_check_settings(mgr);
775         if (r) {
776                 DSSERR("cannot start manual update: illegal configuration\n");
777                 spin_unlock_irqrestore(&data_lock, flags);
778                 return;
779         }
780
781         dss_mgr_write_regs(mgr);
782         dss_mgr_write_regs_extra(mgr);
783
784         mp->updating = true;
785
786         if (!dss_data.irq_enabled && need_isr())
787                 dss_register_vsync_isr();
788
789         dispc_mgr_enable(mgr->id, true);
790
791         mgr_clear_shadow_dirty(mgr);
792
793         spin_unlock_irqrestore(&data_lock, flags);
794 }
795
796 static void dss_apply_irq_handler(void *data, u32 mask);
797
798 static void dss_register_vsync_isr(void)
799 {
800         const int num_mgrs = dss_feat_get_num_mgrs();
801         u32 mask;
802         int r, i;
803
804         mask = 0;
805         for (i = 0; i < num_mgrs; ++i)
806                 mask |= dispc_mgr_get_vsync_irq(i);
807
808         for (i = 0; i < num_mgrs; ++i)
809                 mask |= dispc_mgr_get_framedone_irq(i);
810
811         r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
812         WARN_ON(r);
813
814         dss_data.irq_enabled = true;
815 }
816
817 static void dss_unregister_vsync_isr(void)
818 {
819         const int num_mgrs = dss_feat_get_num_mgrs();
820         u32 mask;
821         int r, i;
822
823         mask = 0;
824         for (i = 0; i < num_mgrs; ++i)
825                 mask |= dispc_mgr_get_vsync_irq(i);
826
827         for (i = 0; i < num_mgrs; ++i)
828                 mask |= dispc_mgr_get_framedone_irq(i);
829
830         r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask);
831         WARN_ON(r);
832
833         dss_data.irq_enabled = false;
834 }
835
836 static void dss_apply_irq_handler(void *data, u32 mask)
837 {
838         const int num_mgrs = dss_feat_get_num_mgrs();
839         int i;
840         bool extra_updating;
841
842         spin_lock(&data_lock);
843
844         /* clear busy, updating flags, shadow_dirty flags */
845         for (i = 0; i < num_mgrs; i++) {
846                 struct omap_overlay_manager *mgr;
847                 struct mgr_priv_data *mp;
848                 bool was_updating;
849
850                 mgr = omap_dss_get_overlay_manager(i);
851                 mp = get_mgr_priv(mgr);
852
853                 if (!mp->enabled)
854                         continue;
855
856                 was_updating = mp->updating;
857                 mp->updating = dispc_mgr_is_enabled(i);
858
859                 if (!mgr_manual_update(mgr)) {
860                         bool was_busy = mp->busy;
861                         mp->busy = dispc_mgr_go_busy(i);
862
863                         if (was_busy && !mp->busy)
864                                 mgr_clear_shadow_dirty(mgr);
865                 }
866         }
867
868         dss_write_regs();
869         dss_set_go_bits();
870
871         extra_updating = extra_info_update_ongoing();
872         if (!extra_updating)
873                 complete_all(&extra_updated_completion);
874
875         if (!need_isr())
876                 dss_unregister_vsync_isr();
877
878         spin_unlock(&data_lock);
879 }
880
881 static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl)
882 {
883         struct ovl_priv_data *op;
884
885         op = get_ovl_priv(ovl);
886
887         if (!op->user_info_dirty)
888                 return;
889
890         op->user_info_dirty = false;
891         op->info_dirty = true;
892         op->info = op->user_info;
893 }
894
895 static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
896 {
897         struct mgr_priv_data *mp;
898
899         mp = get_mgr_priv(mgr);
900
901         if (!mp->user_info_dirty)
902                 return;
903
904         mp->user_info_dirty = false;
905         mp->info_dirty = true;
906         mp->info = mp->user_info;
907 }
908
909 int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
910 {
911         unsigned long flags;
912         struct omap_overlay *ovl;
913         int r;
914
915         DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
916
917         spin_lock_irqsave(&data_lock, flags);
918
919         r = dss_check_settings_apply(mgr);
920         if (r) {
921                 spin_unlock_irqrestore(&data_lock, flags);
922                 DSSERR("failed to apply settings: illegal configuration.\n");
923                 return r;
924         }
925
926         /* Configure overlays */
927         list_for_each_entry(ovl, &mgr->overlays, list)
928                 omap_dss_mgr_apply_ovl(ovl);
929
930         /* Configure manager */
931         omap_dss_mgr_apply_mgr(mgr);
932
933         dss_write_regs();
934         dss_set_go_bits();
935
936         spin_unlock_irqrestore(&data_lock, flags);
937
938         return 0;
939 }
940
941 static void dss_apply_ovl_enable(struct omap_overlay *ovl, bool enable)
942 {
943         struct ovl_priv_data *op;
944
945         op = get_ovl_priv(ovl);
946
947         if (op->enabled == enable)
948                 return;
949
950         op->enabled = enable;
951         op->extra_info_dirty = true;
952 }
953
954 static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
955                 u32 fifo_low, u32 fifo_high)
956 {
957         struct ovl_priv_data *op = get_ovl_priv(ovl);
958
959         if (op->fifo_low == fifo_low && op->fifo_high == fifo_high)
960                 return;
961
962         op->fifo_low = fifo_low;
963         op->fifo_high = fifo_high;
964         op->extra_info_dirty = true;
965 }
966
967 static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
968 {
969         struct ovl_priv_data *op = get_ovl_priv(ovl);
970         u32 fifo_low, fifo_high;
971         bool use_fifo_merge = false;
972
973         if (!op->enabled && !op->enabling)
974                 return;
975
976         dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high,
977                         use_fifo_merge, ovl_manual_update(ovl));
978
979         dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
980 }
981
982 static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
983 {
984         struct omap_overlay *ovl;
985         struct mgr_priv_data *mp;
986
987         mp = get_mgr_priv(mgr);
988
989         if (!mp->enabled)
990                 return;
991
992         list_for_each_entry(ovl, &mgr->overlays, list)
993                 dss_ovl_setup_fifo(ovl);
994 }
995
996 static void dss_setup_fifos(void)
997 {
998         const int num_mgrs = omap_dss_get_num_overlay_managers();
999         struct omap_overlay_manager *mgr;
1000         int i;
1001
1002         for (i = 0; i < num_mgrs; ++i) {
1003                 mgr = omap_dss_get_overlay_manager(i);
1004                 dss_mgr_setup_fifos(mgr);
1005         }
1006 }
1007
1008 int dss_mgr_enable(struct omap_overlay_manager *mgr)
1009 {
1010         struct mgr_priv_data *mp = get_mgr_priv(mgr);
1011         unsigned long flags;
1012         int r;
1013
1014         mutex_lock(&apply_lock);
1015
1016         if (mp->enabled)
1017                 goto out;
1018
1019         spin_lock_irqsave(&data_lock, flags);
1020
1021         mp->enabled = true;
1022
1023         r = dss_check_settings(mgr);
1024         if (r) {
1025                 DSSERR("failed to enable manager %d: check_settings failed\n",
1026                                 mgr->id);
1027                 goto err;
1028         }
1029
1030         dss_setup_fifos();
1031
1032         dss_write_regs();
1033         dss_set_go_bits();
1034
1035         if (!mgr_manual_update(mgr))
1036                 mp->updating = true;
1037
1038         spin_unlock_irqrestore(&data_lock, flags);
1039
1040         if (!mgr_manual_update(mgr))
1041                 dispc_mgr_enable(mgr->id, true);
1042
1043 out:
1044         mutex_unlock(&apply_lock);
1045
1046         return 0;
1047
1048 err:
1049         mp->enabled = false;
1050         spin_unlock_irqrestore(&data_lock, flags);
1051         mutex_unlock(&apply_lock);
1052         return r;
1053 }
1054
1055 void dss_mgr_disable(struct omap_overlay_manager *mgr)
1056 {
1057         struct mgr_priv_data *mp = get_mgr_priv(mgr);
1058         unsigned long flags;
1059
1060         mutex_lock(&apply_lock);
1061
1062         if (!mp->enabled)
1063                 goto out;
1064
1065         if (!mgr_manual_update(mgr))
1066                 dispc_mgr_enable(mgr->id, false);
1067
1068         spin_lock_irqsave(&data_lock, flags);
1069
1070         mp->updating = false;
1071         mp->enabled = false;
1072
1073         spin_unlock_irqrestore(&data_lock, flags);
1074
1075 out:
1076         mutex_unlock(&apply_lock);
1077 }
1078
1079 int dss_mgr_set_info(struct omap_overlay_manager *mgr,
1080                 struct omap_overlay_manager_info *info)
1081 {
1082         struct mgr_priv_data *mp = get_mgr_priv(mgr);
1083         unsigned long flags;
1084         int r;
1085
1086         r = dss_mgr_simple_check(mgr, info);
1087         if (r)
1088                 return r;
1089
1090         spin_lock_irqsave(&data_lock, flags);
1091
1092         mp->user_info = *info;
1093         mp->user_info_dirty = true;
1094
1095         spin_unlock_irqrestore(&data_lock, flags);
1096
1097         return 0;
1098 }
1099
1100 void dss_mgr_get_info(struct omap_overlay_manager *mgr,
1101                 struct omap_overlay_manager_info *info)
1102 {
1103         struct mgr_priv_data *mp = get_mgr_priv(mgr);
1104         unsigned long flags;
1105
1106         spin_lock_irqsave(&data_lock, flags);
1107
1108         *info = mp->user_info;
1109
1110         spin_unlock_irqrestore(&data_lock, flags);
1111 }
1112
1113 int dss_mgr_set_output(struct omap_overlay_manager *mgr,
1114                 struct omap_dss_output *output)
1115 {
1116         int r;
1117
1118         mutex_lock(&apply_lock);
1119
1120         if (mgr->output) {
1121                 DSSERR("manager %s is already connected to an output\n",
1122                         mgr->name);
1123                 r = -EINVAL;
1124                 goto err;
1125         }
1126
1127         if ((mgr->supported_outputs & output->id) == 0) {
1128                 DSSERR("output does not support manager %s\n",
1129                         mgr->name);
1130                 r = -EINVAL;
1131                 goto err;
1132         }
1133
1134         output->manager = mgr;
1135         mgr->output = output;
1136
1137         mutex_unlock(&apply_lock);
1138
1139         return 0;
1140 err:
1141         mutex_unlock(&apply_lock);
1142         return r;
1143 }
1144
1145 int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
1146 {
1147         int r;
1148         struct mgr_priv_data *mp = get_mgr_priv(mgr);
1149         unsigned long flags;
1150
1151         mutex_lock(&apply_lock);
1152
1153         if (!mgr->output) {
1154                 DSSERR("failed to unset output, output not set\n");
1155                 r = -EINVAL;
1156                 goto err;
1157         }
1158
1159         spin_lock_irqsave(&data_lock, flags);
1160
1161         if (mp->enabled) {
1162                 DSSERR("output can't be unset when manager is enabled\n");
1163                 r = -EINVAL;
1164                 goto err1;
1165         }
1166
1167         spin_unlock_irqrestore(&data_lock, flags);
1168
1169         mgr->output->manager = NULL;
1170         mgr->output = NULL;
1171
1172         mutex_unlock(&apply_lock);
1173
1174         return 0;
1175 err1:
1176         spin_unlock_irqrestore(&data_lock, flags);
1177 err:
1178         mutex_unlock(&apply_lock);
1179
1180         return r;
1181 }
1182
1183 static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
1184                 const struct omap_video_timings *timings)
1185 {
1186         struct mgr_priv_data *mp = get_mgr_priv(mgr);
1187
1188         mp->timings = *timings;
1189         mp->extra_info_dirty = true;
1190 }
1191
1192 void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
1193                 const struct omap_video_timings *timings)
1194 {
1195         unsigned long flags;
1196         struct mgr_priv_data *mp = get_mgr_priv(mgr);
1197
1198         spin_lock_irqsave(&data_lock, flags);
1199
1200         if (mp->updating) {
1201                 DSSERR("cannot set timings for %s: manager needs to be disabled\n",
1202                         mgr->name);
1203                 goto out;
1204         }
1205
1206         dss_apply_mgr_timings(mgr, timings);
1207 out:
1208         spin_unlock_irqrestore(&data_lock, flags);
1209 }
1210
1211 static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
1212                 const struct dss_lcd_mgr_config *config)
1213 {
1214         struct mgr_priv_data *mp = get_mgr_priv(mgr);
1215
1216         mp->lcd_config = *config;
1217         mp->extra_info_dirty = true;
1218 }
1219
1220 void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
1221                 const struct dss_lcd_mgr_config *config)
1222 {
1223         unsigned long flags;
1224         struct mgr_priv_data *mp = get_mgr_priv(mgr);
1225
1226         spin_lock_irqsave(&data_lock, flags);
1227
1228         if (mp->enabled) {
1229                 DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
1230                         mgr->name);
1231                 goto out;
1232         }
1233
1234         dss_apply_mgr_lcd_config(mgr, config);
1235 out:
1236         spin_unlock_irqrestore(&data_lock, flags);
1237 }
1238
1239 int dss_ovl_set_info(struct omap_overlay *ovl,
1240                 struct omap_overlay_info *info)
1241 {
1242         struct ovl_priv_data *op = get_ovl_priv(ovl);
1243         unsigned long flags;
1244         int r;
1245
1246         r = dss_ovl_simple_check(ovl, info);
1247         if (r)
1248                 return r;
1249
1250         spin_lock_irqsave(&data_lock, flags);
1251
1252         op->user_info = *info;
1253         op->user_info_dirty = true;
1254
1255         spin_unlock_irqrestore(&data_lock, flags);
1256
1257         return 0;
1258 }
1259
1260 void dss_ovl_get_info(struct omap_overlay *ovl,
1261                 struct omap_overlay_info *info)
1262 {
1263         struct ovl_priv_data *op = get_ovl_priv(ovl);
1264         unsigned long flags;
1265
1266         spin_lock_irqsave(&data_lock, flags);
1267
1268         *info = op->user_info;
1269
1270         spin_unlock_irqrestore(&data_lock, flags);
1271 }
1272
1273 int dss_ovl_set_manager(struct omap_overlay *ovl,
1274                 struct omap_overlay_manager *mgr)
1275 {
1276         struct ovl_priv_data *op = get_ovl_priv(ovl);
1277         unsigned long flags;
1278         int r;
1279
1280         if (!mgr)
1281                 return -EINVAL;
1282
1283         mutex_lock(&apply_lock);
1284
1285         if (ovl->manager) {
1286                 DSSERR("overlay '%s' already has a manager '%s'\n",
1287                                 ovl->name, ovl->manager->name);
1288                 r = -EINVAL;
1289                 goto err;
1290         }
1291
1292         spin_lock_irqsave(&data_lock, flags);
1293
1294         if (op->enabled) {
1295                 spin_unlock_irqrestore(&data_lock, flags);
1296                 DSSERR("overlay has to be disabled to change the manager\n");
1297                 r = -EINVAL;
1298                 goto err;
1299         }
1300
1301         op->channel = mgr->id;
1302         op->extra_info_dirty = true;
1303
1304         ovl->manager = mgr;
1305         list_add_tail(&ovl->list, &mgr->overlays);
1306
1307         spin_unlock_irqrestore(&data_lock, flags);
1308
1309         /* XXX: When there is an overlay on a DSI manual update display, and
1310          * the overlay is first disabled, then moved to tv, and enabled, we
1311          * seem to get SYNC_LOST_DIGIT error.
1312          *
1313          * Waiting doesn't seem to help, but updating the manual update display
1314          * after disabling the overlay seems to fix this. This hints that the
1315          * overlay is perhaps somehow tied to the LCD output until the output
1316          * is updated.
1317          *
1318          * Userspace workaround for this is to update the LCD after disabling
1319          * the overlay, but before moving the overlay to TV.
1320          */
1321
1322         mutex_unlock(&apply_lock);
1323
1324         return 0;
1325 err:
1326         mutex_unlock(&apply_lock);
1327         return r;
1328 }
1329
1330 int dss_ovl_unset_manager(struct omap_overlay *ovl)
1331 {
1332         struct ovl_priv_data *op = get_ovl_priv(ovl);
1333         unsigned long flags;
1334         int r;
1335
1336         mutex_lock(&apply_lock);
1337
1338         if (!ovl->manager) {
1339                 DSSERR("failed to detach overlay: manager not set\n");
1340                 r = -EINVAL;
1341                 goto err;
1342         }
1343
1344         spin_lock_irqsave(&data_lock, flags);
1345
1346         if (op->enabled) {
1347                 spin_unlock_irqrestore(&data_lock, flags);
1348                 DSSERR("overlay has to be disabled to unset the manager\n");
1349                 r = -EINVAL;
1350                 goto err;
1351         }
1352
1353         spin_unlock_irqrestore(&data_lock, flags);
1354
1355         /* wait for pending extra_info updates to ensure the ovl is disabled */
1356         wait_pending_extra_info_updates();
1357
1358         spin_lock_irqsave(&data_lock, flags);
1359
1360         op->channel = -1;
1361
1362         ovl->manager = NULL;
1363         list_del(&ovl->list);
1364
1365         spin_unlock_irqrestore(&data_lock, flags);
1366
1367         mutex_unlock(&apply_lock);
1368
1369         return 0;
1370 err:
1371         mutex_unlock(&apply_lock);
1372         return r;
1373 }
1374
1375 bool dss_ovl_is_enabled(struct omap_overlay *ovl)
1376 {
1377         struct ovl_priv_data *op = get_ovl_priv(ovl);
1378         unsigned long flags;
1379         bool e;
1380
1381         spin_lock_irqsave(&data_lock, flags);
1382
1383         e = op->enabled;
1384
1385         spin_unlock_irqrestore(&data_lock, flags);
1386
1387         return e;
1388 }
1389
1390 int dss_ovl_enable(struct omap_overlay *ovl)
1391 {
1392         struct ovl_priv_data *op = get_ovl_priv(ovl);
1393         unsigned long flags;
1394         int r;
1395
1396         mutex_lock(&apply_lock);
1397
1398         if (op->enabled) {
1399                 r = 0;
1400                 goto err1;
1401         }
1402
1403         if (ovl->manager == NULL || ovl->manager->output == NULL) {
1404                 r = -EINVAL;
1405                 goto err1;
1406         }
1407
1408         spin_lock_irqsave(&data_lock, flags);
1409
1410         op->enabling = true;
1411
1412         r = dss_check_settings(ovl->manager);
1413         if (r) {
1414                 DSSERR("failed to enable overlay %d: check_settings failed\n",
1415                                 ovl->id);
1416                 goto err2;
1417         }
1418
1419         dss_setup_fifos();
1420
1421         op->enabling = false;
1422         dss_apply_ovl_enable(ovl, true);
1423
1424         dss_write_regs();
1425         dss_set_go_bits();
1426
1427         spin_unlock_irqrestore(&data_lock, flags);
1428
1429         mutex_unlock(&apply_lock);
1430
1431         return 0;
1432 err2:
1433         op->enabling = false;
1434         spin_unlock_irqrestore(&data_lock, flags);
1435 err1:
1436         mutex_unlock(&apply_lock);
1437         return r;
1438 }
1439
1440 int dss_ovl_disable(struct omap_overlay *ovl)
1441 {
1442         struct ovl_priv_data *op = get_ovl_priv(ovl);
1443         unsigned long flags;
1444         int r;
1445
1446         mutex_lock(&apply_lock);
1447
1448         if (!op->enabled) {
1449                 r = 0;
1450                 goto err;
1451         }
1452
1453         if (ovl->manager == NULL || ovl->manager->output == NULL) {
1454                 r = -EINVAL;
1455                 goto err;
1456         }
1457
1458         spin_lock_irqsave(&data_lock, flags);
1459
1460         dss_apply_ovl_enable(ovl, false);
1461         dss_write_regs();
1462         dss_set_go_bits();
1463
1464         spin_unlock_irqrestore(&data_lock, flags);
1465
1466         mutex_unlock(&apply_lock);
1467
1468         return 0;
1469
1470 err:
1471         mutex_unlock(&apply_lock);
1472         return r;
1473 }
1474