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