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