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