root/drivers/video/fbdev/omap2/omapfb/dss/apply.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_ovl_priv
  2. get_mgr_priv
  3. apply_init_priv
  4. ovl_manual_update
  5. mgr_manual_update
  6. dss_check_settings_low
  7. dss_check_settings
  8. dss_check_settings_apply
  9. need_isr
  10. need_go
  11. extra_info_update_ongoing
  12. wait_pending_extra_info_updates
  13. dss_mgr_get_device
  14. dss_ovl_get_device
  15. dss_mgr_wait_for_vsync
  16. dss_mgr_wait_for_go
  17. dss_mgr_wait_for_go_ovl
  18. dss_ovl_write_regs
  19. dss_ovl_write_regs_extra
  20. dss_mgr_write_regs
  21. dss_mgr_write_regs_extra
  22. dss_write_regs
  23. dss_set_go_bits
  24. mgr_clear_shadow_dirty
  25. dss_mgr_connect_compat
  26. dss_mgr_disconnect_compat
  27. dss_mgr_start_update_compat
  28. dss_register_vsync_isr
  29. dss_unregister_vsync_isr
  30. dss_apply_irq_handler
  31. omap_dss_mgr_apply_ovl
  32. omap_dss_mgr_apply_mgr
  33. omap_dss_mgr_apply
  34. dss_apply_ovl_enable
  35. dss_apply_ovl_fifo_thresholds
  36. dss_ovl_setup_fifo
  37. dss_mgr_setup_fifos
  38. dss_setup_fifos
  39. dss_mgr_enable_compat
  40. dss_mgr_disable_compat
  41. dss_mgr_set_info
  42. dss_mgr_get_info
  43. dss_mgr_set_output
  44. dss_mgr_unset_output
  45. dss_apply_mgr_timings
  46. dss_mgr_set_timings_compat
  47. dss_apply_mgr_lcd_config
  48. dss_mgr_set_lcd_config_compat
  49. dss_ovl_set_info
  50. dss_ovl_get_info
  51. dss_ovl_set_manager
  52. dss_ovl_unset_manager
  53. dss_ovl_is_enabled
  54. dss_ovl_enable
  55. dss_ovl_disable
  56. dss_mgr_register_framedone_handler_compat
  57. dss_mgr_unregister_framedone_handler_compat
  58. omapdss_compat_init
  59. omapdss_compat_uninit

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

/* [<][>][^][v][top][bottom][index][help] */