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