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