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