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