Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / video / fbdev / omap2 / dss / dispc-compat.c
1 /*
2  * Copyright (C) 2012 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/module.h>
22 #include <linux/slab.h>
23 #include <linux/spinlock.h>
24 #include <linux/jiffies.h>
25 #include <linux/delay.h>
26 #include <linux/interrupt.h>
27 #include <linux/seq_file.h>
28
29 #include <video/omapdss.h>
30
31 #include "dss.h"
32 #include "dss_features.h"
33 #include "dispc-compat.h"
34
35 #define DISPC_IRQ_MASK_ERROR            (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
36                                          DISPC_IRQ_OCP_ERR | \
37                                          DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
38                                          DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
39                                          DISPC_IRQ_SYNC_LOST | \
40                                          DISPC_IRQ_SYNC_LOST_DIGIT)
41
42 #define DISPC_MAX_NR_ISRS               8
43
44 struct omap_dispc_isr_data {
45         omap_dispc_isr_t        isr;
46         void                    *arg;
47         u32                     mask;
48 };
49
50 struct dispc_irq_stats {
51         unsigned long last_reset;
52         unsigned irq_count;
53         unsigned irqs[32];
54 };
55
56 static struct {
57         spinlock_t irq_lock;
58         u32 irq_error_mask;
59         struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
60         u32 error_irqs;
61         struct work_struct error_work;
62
63 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
64         spinlock_t irq_stats_lock;
65         struct dispc_irq_stats irq_stats;
66 #endif
67 } dispc_compat;
68
69
70 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
71 static void dispc_dump_irqs(struct seq_file *s)
72 {
73         unsigned long flags;
74         struct dispc_irq_stats stats;
75
76         spin_lock_irqsave(&dispc_compat.irq_stats_lock, flags);
77
78         stats = dispc_compat.irq_stats;
79         memset(&dispc_compat.irq_stats, 0, sizeof(dispc_compat.irq_stats));
80         dispc_compat.irq_stats.last_reset = jiffies;
81
82         spin_unlock_irqrestore(&dispc_compat.irq_stats_lock, flags);
83
84         seq_printf(s, "period %u ms\n",
85                         jiffies_to_msecs(jiffies - stats.last_reset));
86
87         seq_printf(s, "irqs %d\n", stats.irq_count);
88 #define PIS(x) \
89         seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
90
91         PIS(FRAMEDONE);
92         PIS(VSYNC);
93         PIS(EVSYNC_EVEN);
94         PIS(EVSYNC_ODD);
95         PIS(ACBIAS_COUNT_STAT);
96         PIS(PROG_LINE_NUM);
97         PIS(GFX_FIFO_UNDERFLOW);
98         PIS(GFX_END_WIN);
99         PIS(PAL_GAMMA_MASK);
100         PIS(OCP_ERR);
101         PIS(VID1_FIFO_UNDERFLOW);
102         PIS(VID1_END_WIN);
103         PIS(VID2_FIFO_UNDERFLOW);
104         PIS(VID2_END_WIN);
105         if (dss_feat_get_num_ovls() > 3) {
106                 PIS(VID3_FIFO_UNDERFLOW);
107                 PIS(VID3_END_WIN);
108         }
109         PIS(SYNC_LOST);
110         PIS(SYNC_LOST_DIGIT);
111         PIS(WAKEUP);
112         if (dss_has_feature(FEAT_MGR_LCD2)) {
113                 PIS(FRAMEDONE2);
114                 PIS(VSYNC2);
115                 PIS(ACBIAS_COUNT_STAT2);
116                 PIS(SYNC_LOST2);
117         }
118         if (dss_has_feature(FEAT_MGR_LCD3)) {
119                 PIS(FRAMEDONE3);
120                 PIS(VSYNC3);
121                 PIS(ACBIAS_COUNT_STAT3);
122                 PIS(SYNC_LOST3);
123         }
124 #undef PIS
125 }
126 #endif
127
128 /* dispc.irq_lock has to be locked by the caller */
129 static void _omap_dispc_set_irqs(void)
130 {
131         u32 mask;
132         int i;
133         struct omap_dispc_isr_data *isr_data;
134
135         mask = dispc_compat.irq_error_mask;
136
137         for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
138                 isr_data = &dispc_compat.registered_isr[i];
139
140                 if (isr_data->isr == NULL)
141                         continue;
142
143                 mask |= isr_data->mask;
144         }
145
146         dispc_write_irqenable(mask);
147 }
148
149 int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
150 {
151         int i;
152         int ret;
153         unsigned long flags;
154         struct omap_dispc_isr_data *isr_data;
155
156         if (isr == NULL)
157                 return -EINVAL;
158
159         spin_lock_irqsave(&dispc_compat.irq_lock, flags);
160
161         /* check for duplicate entry */
162         for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
163                 isr_data = &dispc_compat.registered_isr[i];
164                 if (isr_data->isr == isr && isr_data->arg == arg &&
165                                 isr_data->mask == mask) {
166                         ret = -EINVAL;
167                         goto err;
168                 }
169         }
170
171         isr_data = NULL;
172         ret = -EBUSY;
173
174         for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
175                 isr_data = &dispc_compat.registered_isr[i];
176
177                 if (isr_data->isr != NULL)
178                         continue;
179
180                 isr_data->isr = isr;
181                 isr_data->arg = arg;
182                 isr_data->mask = mask;
183                 ret = 0;
184
185                 break;
186         }
187
188         if (ret)
189                 goto err;
190
191         _omap_dispc_set_irqs();
192
193         spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
194
195         return 0;
196 err:
197         spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
198
199         return ret;
200 }
201 EXPORT_SYMBOL(omap_dispc_register_isr);
202
203 int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
204 {
205         int i;
206         unsigned long flags;
207         int ret = -EINVAL;
208         struct omap_dispc_isr_data *isr_data;
209
210         spin_lock_irqsave(&dispc_compat.irq_lock, flags);
211
212         for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
213                 isr_data = &dispc_compat.registered_isr[i];
214                 if (isr_data->isr != isr || isr_data->arg != arg ||
215                                 isr_data->mask != mask)
216                         continue;
217
218                 /* found the correct isr */
219
220                 isr_data->isr = NULL;
221                 isr_data->arg = NULL;
222                 isr_data->mask = 0;
223
224                 ret = 0;
225                 break;
226         }
227
228         if (ret == 0)
229                 _omap_dispc_set_irqs();
230
231         spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
232
233         return ret;
234 }
235 EXPORT_SYMBOL(omap_dispc_unregister_isr);
236
237 static void print_irq_status(u32 status)
238 {
239         if ((status & dispc_compat.irq_error_mask) == 0)
240                 return;
241
242 #define PIS(x) (status & DISPC_IRQ_##x) ? (#x " ") : ""
243
244         pr_debug("DISPC IRQ: 0x%x: %s%s%s%s%s%s%s%s%s\n",
245                 status,
246                 PIS(OCP_ERR),
247                 PIS(GFX_FIFO_UNDERFLOW),
248                 PIS(VID1_FIFO_UNDERFLOW),
249                 PIS(VID2_FIFO_UNDERFLOW),
250                 dss_feat_get_num_ovls() > 3 ? PIS(VID3_FIFO_UNDERFLOW) : "",
251                 PIS(SYNC_LOST),
252                 PIS(SYNC_LOST_DIGIT),
253                 dss_has_feature(FEAT_MGR_LCD2) ? PIS(SYNC_LOST2) : "",
254                 dss_has_feature(FEAT_MGR_LCD3) ? PIS(SYNC_LOST3) : "");
255 #undef PIS
256 }
257
258 /* Called from dss.c. Note that we don't touch clocks here,
259  * but we presume they are on because we got an IRQ. However,
260  * an irq handler may turn the clocks off, so we may not have
261  * clock later in the function. */
262 static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
263 {
264         int i;
265         u32 irqstatus, irqenable;
266         u32 handledirqs = 0;
267         u32 unhandled_errors;
268         struct omap_dispc_isr_data *isr_data;
269         struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
270
271         spin_lock(&dispc_compat.irq_lock);
272
273         irqstatus = dispc_read_irqstatus();
274         irqenable = dispc_read_irqenable();
275
276         /* IRQ is not for us */
277         if (!(irqstatus & irqenable)) {
278                 spin_unlock(&dispc_compat.irq_lock);
279                 return IRQ_NONE;
280         }
281
282 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
283         spin_lock(&dispc_compat.irq_stats_lock);
284         dispc_compat.irq_stats.irq_count++;
285         dss_collect_irq_stats(irqstatus, dispc_compat.irq_stats.irqs);
286         spin_unlock(&dispc_compat.irq_stats_lock);
287 #endif
288
289         print_irq_status(irqstatus);
290
291         /* Ack the interrupt. Do it here before clocks are possibly turned
292          * off */
293         dispc_clear_irqstatus(irqstatus);
294         /* flush posted write */
295         dispc_read_irqstatus();
296
297         /* make a copy and unlock, so that isrs can unregister
298          * themselves */
299         memcpy(registered_isr, dispc_compat.registered_isr,
300                         sizeof(registered_isr));
301
302         spin_unlock(&dispc_compat.irq_lock);
303
304         for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
305                 isr_data = &registered_isr[i];
306
307                 if (!isr_data->isr)
308                         continue;
309
310                 if (isr_data->mask & irqstatus) {
311                         isr_data->isr(isr_data->arg, irqstatus);
312                         handledirqs |= isr_data->mask;
313                 }
314         }
315
316         spin_lock(&dispc_compat.irq_lock);
317
318         unhandled_errors = irqstatus & ~handledirqs & dispc_compat.irq_error_mask;
319
320         if (unhandled_errors) {
321                 dispc_compat.error_irqs |= unhandled_errors;
322
323                 dispc_compat.irq_error_mask &= ~unhandled_errors;
324                 _omap_dispc_set_irqs();
325
326                 schedule_work(&dispc_compat.error_work);
327         }
328
329         spin_unlock(&dispc_compat.irq_lock);
330
331         return IRQ_HANDLED;
332 }
333
334 static void dispc_error_worker(struct work_struct *work)
335 {
336         int i;
337         u32 errors;
338         unsigned long flags;
339         static const unsigned fifo_underflow_bits[] = {
340                 DISPC_IRQ_GFX_FIFO_UNDERFLOW,
341                 DISPC_IRQ_VID1_FIFO_UNDERFLOW,
342                 DISPC_IRQ_VID2_FIFO_UNDERFLOW,
343                 DISPC_IRQ_VID3_FIFO_UNDERFLOW,
344         };
345
346         spin_lock_irqsave(&dispc_compat.irq_lock, flags);
347         errors = dispc_compat.error_irqs;
348         dispc_compat.error_irqs = 0;
349         spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
350
351         dispc_runtime_get();
352
353         for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
354                 struct omap_overlay *ovl;
355                 unsigned bit;
356
357                 ovl = omap_dss_get_overlay(i);
358                 bit = fifo_underflow_bits[i];
359
360                 if (bit & errors) {
361                         DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
362                                         ovl->name);
363                         ovl->disable(ovl);
364                         msleep(50);
365                 }
366         }
367
368         for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
369                 struct omap_overlay_manager *mgr;
370                 unsigned bit;
371
372                 mgr = omap_dss_get_overlay_manager(i);
373                 bit = dispc_mgr_get_sync_lost_irq(i);
374
375                 if (bit & errors) {
376                         int j;
377
378                         DSSERR("SYNC_LOST on channel %s, restarting the output "
379                                         "with video overlays disabled\n",
380                                         mgr->name);
381
382                         dss_mgr_disable(mgr);
383
384                         for (j = 0; j < omap_dss_get_num_overlays(); ++j) {
385                                 struct omap_overlay *ovl;
386                                 ovl = omap_dss_get_overlay(j);
387
388                                 if (ovl->id != OMAP_DSS_GFX &&
389                                                 ovl->manager == mgr)
390                                         ovl->disable(ovl);
391                         }
392
393                         dss_mgr_enable(mgr);
394                 }
395         }
396
397         if (errors & DISPC_IRQ_OCP_ERR) {
398                 DSSERR("OCP_ERR\n");
399                 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
400                         struct omap_overlay_manager *mgr;
401
402                         mgr = omap_dss_get_overlay_manager(i);
403                         dss_mgr_disable(mgr);
404                 }
405         }
406
407         spin_lock_irqsave(&dispc_compat.irq_lock, flags);
408         dispc_compat.irq_error_mask |= errors;
409         _omap_dispc_set_irqs();
410         spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
411
412         dispc_runtime_put();
413 }
414
415 int dss_dispc_initialize_irq(void)
416 {
417         int r;
418
419 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
420         spin_lock_init(&dispc_compat.irq_stats_lock);
421         dispc_compat.irq_stats.last_reset = jiffies;
422         dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
423 #endif
424
425         spin_lock_init(&dispc_compat.irq_lock);
426
427         memset(dispc_compat.registered_isr, 0,
428                         sizeof(dispc_compat.registered_isr));
429
430         dispc_compat.irq_error_mask = DISPC_IRQ_MASK_ERROR;
431         if (dss_has_feature(FEAT_MGR_LCD2))
432                 dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
433         if (dss_has_feature(FEAT_MGR_LCD3))
434                 dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
435         if (dss_feat_get_num_ovls() > 3)
436                 dispc_compat.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
437
438         /*
439          * there's SYNC_LOST_DIGIT waiting after enabling the DSS,
440          * so clear it
441          */
442         dispc_clear_irqstatus(dispc_read_irqstatus());
443
444         INIT_WORK(&dispc_compat.error_work, dispc_error_worker);
445
446         _omap_dispc_set_irqs();
447
448         r = dispc_request_irq(omap_dispc_irq_handler, &dispc_compat);
449         if (r) {
450                 DSSERR("dispc_request_irq failed\n");
451                 return r;
452         }
453
454         return 0;
455 }
456
457 void dss_dispc_uninitialize_irq(void)
458 {
459         dispc_free_irq(&dispc_compat);
460 }
461
462 static void dispc_mgr_disable_isr(void *data, u32 mask)
463 {
464         struct completion *compl = data;
465         complete(compl);
466 }
467
468 static void dispc_mgr_enable_lcd_out(enum omap_channel channel)
469 {
470         dispc_mgr_enable(channel, true);
471 }
472
473 static void dispc_mgr_disable_lcd_out(enum omap_channel channel)
474 {
475         DECLARE_COMPLETION_ONSTACK(framedone_compl);
476         int r;
477         u32 irq;
478
479         if (dispc_mgr_is_enabled(channel) == false)
480                 return;
481
482         /*
483          * When we disable LCD output, we need to wait for FRAMEDONE to know
484          * that DISPC has finished with the LCD output.
485          */
486
487         irq = dispc_mgr_get_framedone_irq(channel);
488
489         r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
490                         irq);
491         if (r)
492                 DSSERR("failed to register FRAMEDONE isr\n");
493
494         dispc_mgr_enable(channel, false);
495
496         /* if we couldn't register for framedone, just sleep and exit */
497         if (r) {
498                 msleep(100);
499                 return;
500         }
501
502         if (!wait_for_completion_timeout(&framedone_compl,
503                                 msecs_to_jiffies(100)))
504                 DSSERR("timeout waiting for FRAME DONE\n");
505
506         r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
507                         irq);
508         if (r)
509                 DSSERR("failed to unregister FRAMEDONE isr\n");
510 }
511
512 static void dispc_digit_out_enable_isr(void *data, u32 mask)
513 {
514         struct completion *compl = data;
515
516         /* ignore any sync lost interrupts */
517         if (mask & (DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD))
518                 complete(compl);
519 }
520
521 static void dispc_mgr_enable_digit_out(void)
522 {
523         DECLARE_COMPLETION_ONSTACK(vsync_compl);
524         int r;
525         u32 irq_mask;
526
527         if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == true)
528                 return;
529
530         /*
531          * Digit output produces some sync lost interrupts during the first
532          * frame when enabling. Those need to be ignored, so we register for the
533          * sync lost irq to prevent the error handler from triggering.
534          */
535
536         irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT) |
537                 dispc_mgr_get_sync_lost_irq(OMAP_DSS_CHANNEL_DIGIT);
538
539         r = omap_dispc_register_isr(dispc_digit_out_enable_isr, &vsync_compl,
540                         irq_mask);
541         if (r) {
542                 DSSERR("failed to register %x isr\n", irq_mask);
543                 return;
544         }
545
546         dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, true);
547
548         /* wait for the first evsync */
549         if (!wait_for_completion_timeout(&vsync_compl, msecs_to_jiffies(100)))
550                 DSSERR("timeout waiting for digit out to start\n");
551
552         r = omap_dispc_unregister_isr(dispc_digit_out_enable_isr, &vsync_compl,
553                         irq_mask);
554         if (r)
555                 DSSERR("failed to unregister %x isr\n", irq_mask);
556 }
557
558 static void dispc_mgr_disable_digit_out(void)
559 {
560         DECLARE_COMPLETION_ONSTACK(framedone_compl);
561         int r, i;
562         u32 irq_mask;
563         int num_irqs;
564
565         if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == false)
566                 return;
567
568         /*
569          * When we disable the digit output, we need to wait for FRAMEDONE to
570          * know that DISPC has finished with the output.
571          */
572
573         irq_mask = dispc_mgr_get_framedone_irq(OMAP_DSS_CHANNEL_DIGIT);
574         num_irqs = 1;
575
576         if (!irq_mask) {
577                 /*
578                  * omap 2/3 don't have framedone irq for TV, so we need to use
579                  * vsyncs for this.
580                  */
581
582                 irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT);
583                 /*
584                  * We need to wait for both even and odd vsyncs. Note that this
585                  * is not totally reliable, as we could get a vsync interrupt
586                  * before we disable the output, which leads to timeout in the
587                  * wait_for_completion.
588                  */
589                 num_irqs = 2;
590         }
591
592         r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
593                         irq_mask);
594         if (r)
595                 DSSERR("failed to register %x isr\n", irq_mask);
596
597         dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, false);
598
599         /* if we couldn't register the irq, just sleep and exit */
600         if (r) {
601                 msleep(100);
602                 return;
603         }
604
605         for (i = 0; i < num_irqs; ++i) {
606                 if (!wait_for_completion_timeout(&framedone_compl,
607                                         msecs_to_jiffies(100)))
608                         DSSERR("timeout waiting for digit out to stop\n");
609         }
610
611         r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
612                         irq_mask);
613         if (r)
614                 DSSERR("failed to unregister %x isr\n", irq_mask);
615 }
616
617 void dispc_mgr_enable_sync(enum omap_channel channel)
618 {
619         if (dss_mgr_is_lcd(channel))
620                 dispc_mgr_enable_lcd_out(channel);
621         else if (channel == OMAP_DSS_CHANNEL_DIGIT)
622                 dispc_mgr_enable_digit_out();
623         else
624                 WARN_ON(1);
625 }
626
627 void dispc_mgr_disable_sync(enum omap_channel channel)
628 {
629         if (dss_mgr_is_lcd(channel))
630                 dispc_mgr_disable_lcd_out(channel);
631         else if (channel == OMAP_DSS_CHANNEL_DIGIT)
632                 dispc_mgr_disable_digit_out();
633         else
634                 WARN_ON(1);
635 }
636
637 static inline void dispc_irq_wait_handler(void *data, u32 mask)
638 {
639         complete((struct completion *)data);
640 }
641
642 int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
643                 unsigned long timeout)
644 {
645
646         int r;
647         DECLARE_COMPLETION_ONSTACK(completion);
648
649         r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
650                         irqmask);
651
652         if (r)
653                 return r;
654
655         timeout = wait_for_completion_interruptible_timeout(&completion,
656                         timeout);
657
658         omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
659
660         if (timeout == 0)
661                 return -ETIMEDOUT;
662
663         if (timeout == -ERESTARTSYS)
664                 return -ERESTARTSYS;
665
666         return 0;
667 }