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