]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/video/omap2/dss/apply.c
OMAPDSS: APPLY: Remove omap_dss_device references from dss_ovl_enable/disable
[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_device(struct omap_overlay_manager *mgr,
1114                 struct omap_dss_device *dssdev)
1115 {
1116         int r;
1117
1118         mutex_lock(&apply_lock);
1119
1120         if (dssdev->manager) {
1121                 DSSERR("display '%s' already has a manager '%s'\n",
1122                                dssdev->name, dssdev->manager->name);
1123                 r = -EINVAL;
1124                 goto err;
1125         }
1126
1127         if ((mgr->supported_displays & dssdev->type) == 0) {
1128                 DSSERR("display '%s' does not support manager '%s'\n",
1129                                dssdev->name, mgr->name);
1130                 r = -EINVAL;
1131                 goto err;
1132         }
1133
1134         dssdev->manager = mgr;
1135         mgr->device = dssdev;
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_device(struct omap_overlay_manager *mgr)
1146 {
1147         int r;
1148
1149         mutex_lock(&apply_lock);
1150
1151         if (!mgr->device) {
1152                 DSSERR("failed to unset display, display not set.\n");
1153                 r = -EINVAL;
1154                 goto err;
1155         }
1156
1157         /*
1158          * Don't allow currently enabled displays to have the overlay manager
1159          * pulled out from underneath them
1160          */
1161         if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) {
1162                 r = -EINVAL;
1163                 goto err;
1164         }
1165
1166         mgr->device->manager = NULL;
1167         mgr->device = NULL;
1168
1169         mutex_unlock(&apply_lock);
1170
1171         return 0;
1172 err:
1173         mutex_unlock(&apply_lock);
1174         return r;
1175 }
1176
1177 int dss_mgr_set_output(struct omap_overlay_manager *mgr,
1178                 struct omap_dss_output *output)
1179 {
1180         int r;
1181
1182         mutex_lock(&apply_lock);
1183
1184         if (mgr->output) {
1185                 DSSERR("manager %s is already connected to an output\n",
1186                         mgr->name);
1187                 r = -EINVAL;
1188                 goto err;
1189         }
1190
1191         if ((mgr->supported_outputs & output->id) == 0) {
1192                 DSSERR("output does not support manager %s\n",
1193                         mgr->name);
1194                 r = -EINVAL;
1195                 goto err;
1196         }
1197
1198         output->manager = mgr;
1199         mgr->output = output;
1200
1201         mutex_unlock(&apply_lock);
1202
1203         return 0;
1204 err:
1205         mutex_unlock(&apply_lock);
1206         return r;
1207 }
1208
1209 int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
1210 {
1211         int r;
1212         struct mgr_priv_data *mp = get_mgr_priv(mgr);
1213         unsigned long flags;
1214
1215         mutex_lock(&apply_lock);
1216
1217         if (!mgr->output) {
1218                 DSSERR("failed to unset output, output not set\n");
1219                 r = -EINVAL;
1220                 goto err;
1221         }
1222
1223         spin_lock_irqsave(&data_lock, flags);
1224
1225         if (mp->enabled) {
1226                 DSSERR("output can't be unset when manager is enabled\n");
1227                 r = -EINVAL;
1228                 goto err1;
1229         }
1230
1231         spin_unlock_irqrestore(&data_lock, flags);
1232
1233         mgr->output->manager = NULL;
1234         mgr->output = NULL;
1235
1236         mutex_unlock(&apply_lock);
1237
1238         return 0;
1239 err1:
1240         spin_unlock_irqrestore(&data_lock, flags);
1241 err:
1242         mutex_unlock(&apply_lock);
1243
1244         return r;
1245 }
1246
1247 static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
1248                 const struct omap_video_timings *timings)
1249 {
1250         struct mgr_priv_data *mp = get_mgr_priv(mgr);
1251
1252         mp->timings = *timings;
1253         mp->extra_info_dirty = true;
1254 }
1255
1256 void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
1257                 const struct omap_video_timings *timings)
1258 {
1259         unsigned long flags;
1260         struct mgr_priv_data *mp = get_mgr_priv(mgr);
1261
1262         spin_lock_irqsave(&data_lock, flags);
1263
1264         if (mp->updating) {
1265                 DSSERR("cannot set timings for %s: manager needs to be disabled\n",
1266                         mgr->name);
1267                 goto out;
1268         }
1269
1270         dss_apply_mgr_timings(mgr, timings);
1271 out:
1272         spin_unlock_irqrestore(&data_lock, flags);
1273 }
1274
1275 static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
1276                 const struct dss_lcd_mgr_config *config)
1277 {
1278         struct mgr_priv_data *mp = get_mgr_priv(mgr);
1279
1280         mp->lcd_config = *config;
1281         mp->extra_info_dirty = true;
1282 }
1283
1284 void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
1285                 const struct dss_lcd_mgr_config *config)
1286 {
1287         unsigned long flags;
1288         struct mgr_priv_data *mp = get_mgr_priv(mgr);
1289
1290         spin_lock_irqsave(&data_lock, flags);
1291
1292         if (mp->enabled) {
1293                 DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
1294                         mgr->name);
1295                 goto out;
1296         }
1297
1298         dss_apply_mgr_lcd_config(mgr, config);
1299 out:
1300         spin_unlock_irqrestore(&data_lock, flags);
1301 }
1302
1303 int dss_ovl_set_info(struct omap_overlay *ovl,
1304                 struct omap_overlay_info *info)
1305 {
1306         struct ovl_priv_data *op = get_ovl_priv(ovl);
1307         unsigned long flags;
1308         int r;
1309
1310         r = dss_ovl_simple_check(ovl, info);
1311         if (r)
1312                 return r;
1313
1314         spin_lock_irqsave(&data_lock, flags);
1315
1316         op->user_info = *info;
1317         op->user_info_dirty = true;
1318
1319         spin_unlock_irqrestore(&data_lock, flags);
1320
1321         return 0;
1322 }
1323
1324 void dss_ovl_get_info(struct omap_overlay *ovl,
1325                 struct omap_overlay_info *info)
1326 {
1327         struct ovl_priv_data *op = get_ovl_priv(ovl);
1328         unsigned long flags;
1329
1330         spin_lock_irqsave(&data_lock, flags);
1331
1332         *info = op->user_info;
1333
1334         spin_unlock_irqrestore(&data_lock, flags);
1335 }
1336
1337 int dss_ovl_set_manager(struct omap_overlay *ovl,
1338                 struct omap_overlay_manager *mgr)
1339 {
1340         struct ovl_priv_data *op = get_ovl_priv(ovl);
1341         unsigned long flags;
1342         int r;
1343
1344         if (!mgr)
1345                 return -EINVAL;
1346
1347         mutex_lock(&apply_lock);
1348
1349         if (ovl->manager) {
1350                 DSSERR("overlay '%s' already has a manager '%s'\n",
1351                                 ovl->name, ovl->manager->name);
1352                 r = -EINVAL;
1353                 goto err;
1354         }
1355
1356         spin_lock_irqsave(&data_lock, flags);
1357
1358         if (op->enabled) {
1359                 spin_unlock_irqrestore(&data_lock, flags);
1360                 DSSERR("overlay has to be disabled to change the manager\n");
1361                 r = -EINVAL;
1362                 goto err;
1363         }
1364
1365         op->channel = mgr->id;
1366         op->extra_info_dirty = true;
1367
1368         ovl->manager = mgr;
1369         list_add_tail(&ovl->list, &mgr->overlays);
1370
1371         spin_unlock_irqrestore(&data_lock, flags);
1372
1373         /* XXX: When there is an overlay on a DSI manual update display, and
1374          * the overlay is first disabled, then moved to tv, and enabled, we
1375          * seem to get SYNC_LOST_DIGIT error.
1376          *
1377          * Waiting doesn't seem to help, but updating the manual update display
1378          * after disabling the overlay seems to fix this. This hints that the
1379          * overlay is perhaps somehow tied to the LCD output until the output
1380          * is updated.
1381          *
1382          * Userspace workaround for this is to update the LCD after disabling
1383          * the overlay, but before moving the overlay to TV.
1384          */
1385
1386         mutex_unlock(&apply_lock);
1387
1388         return 0;
1389 err:
1390         mutex_unlock(&apply_lock);
1391         return r;
1392 }
1393
1394 int dss_ovl_unset_manager(struct omap_overlay *ovl)
1395 {
1396         struct ovl_priv_data *op = get_ovl_priv(ovl);
1397         unsigned long flags;
1398         int r;
1399
1400         mutex_lock(&apply_lock);
1401
1402         if (!ovl->manager) {
1403                 DSSERR("failed to detach overlay: manager not set\n");
1404                 r = -EINVAL;
1405                 goto err;
1406         }
1407
1408         spin_lock_irqsave(&data_lock, flags);
1409
1410         if (op->enabled) {
1411                 spin_unlock_irqrestore(&data_lock, flags);
1412                 DSSERR("overlay has to be disabled to unset the manager\n");
1413                 r = -EINVAL;
1414                 goto err;
1415         }
1416
1417         spin_unlock_irqrestore(&data_lock, flags);
1418
1419         /* wait for pending extra_info updates to ensure the ovl is disabled */
1420         wait_pending_extra_info_updates();
1421
1422         spin_lock_irqsave(&data_lock, flags);
1423
1424         op->channel = -1;
1425
1426         ovl->manager = NULL;
1427         list_del(&ovl->list);
1428
1429         spin_unlock_irqrestore(&data_lock, flags);
1430
1431         mutex_unlock(&apply_lock);
1432
1433         return 0;
1434 err:
1435         mutex_unlock(&apply_lock);
1436         return r;
1437 }
1438
1439 bool dss_ovl_is_enabled(struct omap_overlay *ovl)
1440 {
1441         struct ovl_priv_data *op = get_ovl_priv(ovl);
1442         unsigned long flags;
1443         bool e;
1444
1445         spin_lock_irqsave(&data_lock, flags);
1446
1447         e = op->enabled;
1448
1449         spin_unlock_irqrestore(&data_lock, flags);
1450
1451         return e;
1452 }
1453
1454 int dss_ovl_enable(struct omap_overlay *ovl)
1455 {
1456         struct ovl_priv_data *op = get_ovl_priv(ovl);
1457         unsigned long flags;
1458         int r;
1459
1460         mutex_lock(&apply_lock);
1461
1462         if (op->enabled) {
1463                 r = 0;
1464                 goto err1;
1465         }
1466
1467         if (ovl->manager == NULL || ovl->manager->output == NULL) {
1468                 r = -EINVAL;
1469                 goto err1;
1470         }
1471
1472         spin_lock_irqsave(&data_lock, flags);
1473
1474         op->enabling = true;
1475
1476         r = dss_check_settings(ovl->manager);
1477         if (r) {
1478                 DSSERR("failed to enable overlay %d: check_settings failed\n",
1479                                 ovl->id);
1480                 goto err2;
1481         }
1482
1483         dss_setup_fifos();
1484
1485         op->enabling = false;
1486         dss_apply_ovl_enable(ovl, true);
1487
1488         dss_write_regs();
1489         dss_set_go_bits();
1490
1491         spin_unlock_irqrestore(&data_lock, flags);
1492
1493         mutex_unlock(&apply_lock);
1494
1495         return 0;
1496 err2:
1497         op->enabling = false;
1498         spin_unlock_irqrestore(&data_lock, flags);
1499 err1:
1500         mutex_unlock(&apply_lock);
1501         return r;
1502 }
1503
1504 int dss_ovl_disable(struct omap_overlay *ovl)
1505 {
1506         struct ovl_priv_data *op = get_ovl_priv(ovl);
1507         unsigned long flags;
1508         int r;
1509
1510         mutex_lock(&apply_lock);
1511
1512         if (!op->enabled) {
1513                 r = 0;
1514                 goto err;
1515         }
1516
1517         if (ovl->manager == NULL || ovl->manager->output == NULL) {
1518                 r = -EINVAL;
1519                 goto err;
1520         }
1521
1522         spin_lock_irqsave(&data_lock, flags);
1523
1524         dss_apply_ovl_enable(ovl, false);
1525         dss_write_regs();
1526         dss_set_go_bits();
1527
1528         spin_unlock_irqrestore(&data_lock, flags);
1529
1530         mutex_unlock(&apply_lock);
1531
1532         return 0;
1533
1534 err:
1535         mutex_unlock(&apply_lock);
1536         return r;
1537 }
1538