File Index
Files and directories
Sign in
FILE

apply.c

File preview with syntax highlighting.

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