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