root/drivers/video/fbdev/omap2/omapfb/dss/dispc-compat.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dispc_dump_irqs
  2. _omap_dispc_set_irqs
  3. omap_dispc_register_isr
  4. omap_dispc_unregister_isr
  5. print_irq_status
  6. omap_dispc_irq_handler
  7. dispc_error_worker
  8. dss_dispc_initialize_irq
  9. dss_dispc_uninitialize_irq
  10. dispc_mgr_disable_isr
  11. dispc_mgr_enable_lcd_out
  12. dispc_mgr_disable_lcd_out
  13. dispc_digit_out_enable_isr
  14. dispc_mgr_enable_digit_out
  15. dispc_mgr_disable_digit_out
  16. dispc_mgr_enable_sync
  17. dispc_mgr_disable_sync
  18. dispc_irq_wait_handler
  19. omap_dispc_wait_for_irq_interruptible_timeout

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

/* [<][>][^][v][top][bottom][index][help] */