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