cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

apply.c (34776B)


      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);