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