1 /*
2  * drivers/gpu/drm/omapdrm/omap_crtc.c
3  *
4  * Copyright (C) 2011 Texas Instruments
5  * Author: Rob Clark <rob@ti.com>
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License version 2 as published by
9  * the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "omap_drv.h"
21 
22 #include <drm/drm_mode.h>
23 #include <drm/drm_plane_helper.h>
24 #include "drm_crtc.h"
25 #include "drm_crtc_helper.h"
26 
27 #define to_omap_crtc(x) container_of(x, struct omap_crtc, base)
28 
29 struct omap_crtc {
30 	struct drm_crtc base;
31 	struct drm_plane *plane;
32 
33 	const char *name;
34 	int pipe;
35 	enum omap_channel channel;
36 	struct omap_overlay_manager_info info;
37 	struct drm_encoder *current_encoder;
38 
39 	/*
40 	 * Temporary: eventually this will go away, but it is needed
41 	 * for now to keep the output's happy.  (They only need
42 	 * mgr->id.)  Eventually this will be replaced w/ something
43 	 * more common-panel-framework-y
44 	 */
45 	struct omap_overlay_manager *mgr;
46 
47 	struct omap_video_timings timings;
48 	bool enabled;
49 	bool full_update;
50 
51 	struct omap_drm_apply apply;
52 
53 	struct omap_drm_irq apply_irq;
54 	struct omap_drm_irq error_irq;
55 
56 	/* list of in-progress apply's: */
57 	struct list_head pending_applies;
58 
59 	/* list of queued apply's: */
60 	struct list_head queued_applies;
61 
62 	/* for handling queued and in-progress applies: */
63 	struct work_struct apply_work;
64 
65 	/* if there is a pending flip, these will be non-null: */
66 	struct drm_pending_vblank_event *event;
67 	struct drm_framebuffer *old_fb;
68 
69 	/* for handling page flips without caring about what
70 	 * the callback is called from.  Possibly we should just
71 	 * make omap_gem always call the cb from the worker so
72 	 * we don't have to care about this..
73 	 *
74 	 * XXX maybe fold into apply_work??
75 	 */
76 	struct work_struct page_flip_work;
77 };
78 
79 uint32_t pipe2vbl(struct drm_crtc *crtc)
80 {
81 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
82 
83 	return dispc_mgr_get_vsync_irq(omap_crtc->channel);
84 }
85 
86 /*
87  * Manager-ops, callbacks from output when they need to configure
88  * the upstream part of the video pipe.
89  *
90  * Most of these we can ignore until we add support for command-mode
91  * panels.. for video-mode the crtc-helpers already do an adequate
92  * job of sequencing the setup of the video pipe in the proper order
93  */
94 
95 /* ovl-mgr-id -> crtc */
96 static struct omap_crtc *omap_crtcs[8];
97 
98 /* we can probably ignore these until we support command-mode panels: */
99 static int omap_crtc_connect(struct omap_overlay_manager *mgr,
100 		struct omap_dss_device *dst)
101 {
102 	if (mgr->output)
103 		return -EINVAL;
104 
105 	if ((mgr->supported_outputs & dst->id) == 0)
106 		return -EINVAL;
107 
108 	dst->manager = mgr;
109 	mgr->output = dst;
110 
111 	return 0;
112 }
113 
114 static void omap_crtc_disconnect(struct omap_overlay_manager *mgr,
115 		struct omap_dss_device *dst)
116 {
117 	mgr->output->manager = NULL;
118 	mgr->output = NULL;
119 }
120 
121 static void omap_crtc_start_update(struct omap_overlay_manager *mgr)
122 {
123 }
124 
125 static void set_enabled(struct drm_crtc *crtc, bool enable);
126 
127 static int omap_crtc_enable(struct omap_overlay_manager *mgr)
128 {
129 	struct omap_crtc *omap_crtc = omap_crtcs[mgr->id];
130 
131 	dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info);
132 	dispc_mgr_set_timings(omap_crtc->channel,
133 			&omap_crtc->timings);
134 	set_enabled(&omap_crtc->base, true);
135 
136 	return 0;
137 }
138 
139 static void omap_crtc_disable(struct omap_overlay_manager *mgr)
140 {
141 	struct omap_crtc *omap_crtc = omap_crtcs[mgr->id];
142 
143 	set_enabled(&omap_crtc->base, false);
144 }
145 
146 static void omap_crtc_set_timings(struct omap_overlay_manager *mgr,
147 		const struct omap_video_timings *timings)
148 {
149 	struct omap_crtc *omap_crtc = omap_crtcs[mgr->id];
150 	DBG("%s", omap_crtc->name);
151 	omap_crtc->timings = *timings;
152 	omap_crtc->full_update = true;
153 }
154 
155 static void omap_crtc_set_lcd_config(struct omap_overlay_manager *mgr,
156 		const struct dss_lcd_mgr_config *config)
157 {
158 	struct omap_crtc *omap_crtc = omap_crtcs[mgr->id];
159 	DBG("%s", omap_crtc->name);
160 	dispc_mgr_set_lcd_config(omap_crtc->channel, config);
161 }
162 
163 static int omap_crtc_register_framedone_handler(
164 		struct omap_overlay_manager *mgr,
165 		void (*handler)(void *), void *data)
166 {
167 	return 0;
168 }
169 
170 static void omap_crtc_unregister_framedone_handler(
171 		struct omap_overlay_manager *mgr,
172 		void (*handler)(void *), void *data)
173 {
174 }
175 
176 static const struct dss_mgr_ops mgr_ops = {
177 		.connect = omap_crtc_connect,
178 		.disconnect = omap_crtc_disconnect,
179 		.start_update = omap_crtc_start_update,
180 		.enable = omap_crtc_enable,
181 		.disable = omap_crtc_disable,
182 		.set_timings = omap_crtc_set_timings,
183 		.set_lcd_config = omap_crtc_set_lcd_config,
184 		.register_framedone_handler = omap_crtc_register_framedone_handler,
185 		.unregister_framedone_handler = omap_crtc_unregister_framedone_handler,
186 };
187 
188 /*
189  * CRTC funcs:
190  */
191 
192 static void omap_crtc_destroy(struct drm_crtc *crtc)
193 {
194 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
195 
196 	DBG("%s", omap_crtc->name);
197 
198 	WARN_ON(omap_crtc->apply_irq.registered);
199 	omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
200 
201 	drm_crtc_cleanup(crtc);
202 
203 	kfree(omap_crtc);
204 }
205 
206 static void omap_crtc_dpms(struct drm_crtc *crtc, int mode)
207 {
208 	struct omap_drm_private *priv = crtc->dev->dev_private;
209 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
210 	bool enabled = (mode == DRM_MODE_DPMS_ON);
211 	int i;
212 
213 	DBG("%s: %d", omap_crtc->name, mode);
214 
215 	if (enabled != omap_crtc->enabled) {
216 		omap_crtc->enabled = enabled;
217 		omap_crtc->full_update = true;
218 		omap_crtc_apply(crtc, &omap_crtc->apply);
219 
220 		/* also enable our private plane: */
221 		WARN_ON(omap_plane_dpms(omap_crtc->plane, mode));
222 
223 		/* and any attached overlay planes: */
224 		for (i = 0; i < priv->num_planes; i++) {
225 			struct drm_plane *plane = priv->planes[i];
226 			if (plane->crtc == crtc)
227 				WARN_ON(omap_plane_dpms(plane, mode));
228 		}
229 	}
230 }
231 
232 static bool omap_crtc_mode_fixup(struct drm_crtc *crtc,
233 		const struct drm_display_mode *mode,
234 		struct drm_display_mode *adjusted_mode)
235 {
236 	return true;
237 }
238 
239 static int omap_crtc_mode_set(struct drm_crtc *crtc,
240 		struct drm_display_mode *mode,
241 		struct drm_display_mode *adjusted_mode,
242 		int x, int y,
243 		struct drm_framebuffer *old_fb)
244 {
245 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
246 
247 	mode = adjusted_mode;
248 
249 	DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
250 			omap_crtc->name, mode->base.id, mode->name,
251 			mode->vrefresh, mode->clock,
252 			mode->hdisplay, mode->hsync_start,
253 			mode->hsync_end, mode->htotal,
254 			mode->vdisplay, mode->vsync_start,
255 			mode->vsync_end, mode->vtotal,
256 			mode->type, mode->flags);
257 
258 	copy_timings_drm_to_omap(&omap_crtc->timings, mode);
259 	omap_crtc->full_update = true;
260 
261 	return omap_plane_mode_set(omap_crtc->plane, crtc, crtc->primary->fb,
262 			0, 0, mode->hdisplay, mode->vdisplay,
263 			x << 16, y << 16,
264 			mode->hdisplay << 16, mode->vdisplay << 16,
265 			NULL, NULL);
266 }
267 
268 static void omap_crtc_prepare(struct drm_crtc *crtc)
269 {
270 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
271 	DBG("%s", omap_crtc->name);
272 	omap_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
273 }
274 
275 static void omap_crtc_commit(struct drm_crtc *crtc)
276 {
277 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
278 	DBG("%s", omap_crtc->name);
279 	omap_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
280 }
281 
282 static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
283 		struct drm_framebuffer *old_fb)
284 {
285 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
286 	struct drm_plane *plane = omap_crtc->plane;
287 	struct drm_display_mode *mode = &crtc->mode;
288 
289 	return omap_plane_mode_set(plane, crtc, crtc->primary->fb,
290 			0, 0, mode->hdisplay, mode->vdisplay,
291 			x << 16, y << 16,
292 			mode->hdisplay << 16, mode->vdisplay << 16,
293 			NULL, NULL);
294 }
295 
296 static void vblank_cb(void *arg)
297 {
298 	struct drm_crtc *crtc = arg;
299 	struct drm_device *dev = crtc->dev;
300 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
301 	unsigned long flags;
302 
303 	spin_lock_irqsave(&dev->event_lock, flags);
304 
305 	/* wakeup userspace */
306 	if (omap_crtc->event)
307 		drm_send_vblank_event(dev, omap_crtc->pipe, omap_crtc->event);
308 
309 	omap_crtc->event = NULL;
310 	omap_crtc->old_fb = NULL;
311 
312 	spin_unlock_irqrestore(&dev->event_lock, flags);
313 }
314 
315 static void page_flip_worker(struct work_struct *work)
316 {
317 	struct omap_crtc *omap_crtc =
318 			container_of(work, struct omap_crtc, page_flip_work);
319 	struct drm_crtc *crtc = &omap_crtc->base;
320 	struct drm_display_mode *mode = &crtc->mode;
321 	struct drm_gem_object *bo;
322 
323 	drm_modeset_lock(&crtc->mutex, NULL);
324 	omap_plane_mode_set(omap_crtc->plane, crtc, crtc->primary->fb,
325 			0, 0, mode->hdisplay, mode->vdisplay,
326 			crtc->x << 16, crtc->y << 16,
327 			mode->hdisplay << 16, mode->vdisplay << 16,
328 			vblank_cb, crtc);
329 	drm_modeset_unlock(&crtc->mutex);
330 
331 	bo = omap_framebuffer_bo(crtc->primary->fb, 0);
332 	drm_gem_object_unreference_unlocked(bo);
333 }
334 
335 static void page_flip_cb(void *arg)
336 {
337 	struct drm_crtc *crtc = arg;
338 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
339 	struct omap_drm_private *priv = crtc->dev->dev_private;
340 
341 	/* avoid assumptions about what ctxt we are called from: */
342 	queue_work(priv->wq, &omap_crtc->page_flip_work);
343 }
344 
345 static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
346 		 struct drm_framebuffer *fb,
347 		 struct drm_pending_vblank_event *event,
348 		 uint32_t page_flip_flags)
349 {
350 	struct drm_device *dev = crtc->dev;
351 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
352 	struct drm_plane *primary = crtc->primary;
353 	struct drm_gem_object *bo;
354 	unsigned long flags;
355 
356 	DBG("%d -> %d (event=%p)", primary->fb ? primary->fb->base.id : -1,
357 			fb->base.id, event);
358 
359 	spin_lock_irqsave(&dev->event_lock, flags);
360 
361 	if (omap_crtc->old_fb) {
362 		spin_unlock_irqrestore(&dev->event_lock, flags);
363 		dev_err(dev->dev, "already a pending flip\n");
364 		return -EINVAL;
365 	}
366 
367 	omap_crtc->event = event;
368 	omap_crtc->old_fb = primary->fb = fb;
369 
370 	spin_unlock_irqrestore(&dev->event_lock, flags);
371 
372 	/*
373 	 * Hold a reference temporarily until the crtc is updated
374 	 * and takes the reference to the bo.  This avoids it
375 	 * getting freed from under us:
376 	 */
377 	bo = omap_framebuffer_bo(fb, 0);
378 	drm_gem_object_reference(bo);
379 
380 	omap_gem_op_async(bo, OMAP_GEM_READ, page_flip_cb, crtc);
381 
382 	return 0;
383 }
384 
385 static int omap_crtc_set_property(struct drm_crtc *crtc,
386 		struct drm_property *property, uint64_t val)
387 {
388 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
389 	struct omap_drm_private *priv = crtc->dev->dev_private;
390 
391 	if (property == priv->rotation_prop) {
392 		crtc->invert_dimensions =
393 				!!(val & ((1LL << DRM_ROTATE_90) | (1LL << DRM_ROTATE_270)));
394 	}
395 
396 	return omap_plane_set_property(omap_crtc->plane, property, val);
397 }
398 
399 static const struct drm_crtc_funcs omap_crtc_funcs = {
400 	.set_config = drm_crtc_helper_set_config,
401 	.destroy = omap_crtc_destroy,
402 	.page_flip = omap_crtc_page_flip_locked,
403 	.set_property = omap_crtc_set_property,
404 };
405 
406 static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {
407 	.dpms = omap_crtc_dpms,
408 	.mode_fixup = omap_crtc_mode_fixup,
409 	.mode_set = omap_crtc_mode_set,
410 	.prepare = omap_crtc_prepare,
411 	.commit = omap_crtc_commit,
412 	.mode_set_base = omap_crtc_mode_set_base,
413 };
414 
415 const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc)
416 {
417 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
418 	return &omap_crtc->timings;
419 }
420 
421 enum omap_channel omap_crtc_channel(struct drm_crtc *crtc)
422 {
423 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
424 	return omap_crtc->channel;
425 }
426 
427 static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
428 {
429 	struct omap_crtc *omap_crtc =
430 			container_of(irq, struct omap_crtc, error_irq);
431 	struct drm_crtc *crtc = &omap_crtc->base;
432 	DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus);
433 	/* avoid getting in a flood, unregister the irq until next vblank */
434 	__omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
435 }
436 
437 static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
438 {
439 	struct omap_crtc *omap_crtc =
440 			container_of(irq, struct omap_crtc, apply_irq);
441 	struct drm_crtc *crtc = &omap_crtc->base;
442 
443 	if (!omap_crtc->error_irq.registered)
444 		__omap_irq_register(crtc->dev, &omap_crtc->error_irq);
445 
446 	if (!dispc_mgr_go_busy(omap_crtc->channel)) {
447 		struct omap_drm_private *priv =
448 				crtc->dev->dev_private;
449 		DBG("%s: apply done", omap_crtc->name);
450 		__omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq);
451 		queue_work(priv->wq, &omap_crtc->apply_work);
452 	}
453 }
454 
455 static void apply_worker(struct work_struct *work)
456 {
457 	struct omap_crtc *omap_crtc =
458 			container_of(work, struct omap_crtc, apply_work);
459 	struct drm_crtc *crtc = &omap_crtc->base;
460 	struct drm_device *dev = crtc->dev;
461 	struct omap_drm_apply *apply, *n;
462 	bool need_apply;
463 
464 	/*
465 	 * Synchronize everything on mode_config.mutex, to keep
466 	 * the callbacks and list modification all serialized
467 	 * with respect to modesetting ioctls from userspace.
468 	 */
469 	drm_modeset_lock(&crtc->mutex, NULL);
470 	dispc_runtime_get();
471 
472 	/*
473 	 * If we are still pending a previous update, wait.. when the
474 	 * pending update completes, we get kicked again.
475 	 */
476 	if (omap_crtc->apply_irq.registered)
477 		goto out;
478 
479 	/* finish up previous apply's: */
480 	list_for_each_entry_safe(apply, n,
481 			&omap_crtc->pending_applies, pending_node) {
482 		apply->post_apply(apply);
483 		list_del(&apply->pending_node);
484 	}
485 
486 	need_apply = !list_empty(&omap_crtc->queued_applies);
487 
488 	/* then handle the next round of of queued apply's: */
489 	list_for_each_entry_safe(apply, n,
490 			&omap_crtc->queued_applies, queued_node) {
491 		apply->pre_apply(apply);
492 		list_del(&apply->queued_node);
493 		apply->queued = false;
494 		list_add_tail(&apply->pending_node,
495 				&omap_crtc->pending_applies);
496 	}
497 
498 	if (need_apply) {
499 		enum omap_channel channel = omap_crtc->channel;
500 
501 		DBG("%s: GO", omap_crtc->name);
502 
503 		if (dispc_mgr_is_enabled(channel)) {
504 			omap_irq_register(dev, &omap_crtc->apply_irq);
505 			dispc_mgr_go(channel);
506 		} else {
507 			struct omap_drm_private *priv = dev->dev_private;
508 			queue_work(priv->wq, &omap_crtc->apply_work);
509 		}
510 	}
511 
512 out:
513 	dispc_runtime_put();
514 	drm_modeset_unlock(&crtc->mutex);
515 }
516 
517 int omap_crtc_apply(struct drm_crtc *crtc,
518 		struct omap_drm_apply *apply)
519 {
520 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
521 
522 	WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
523 
524 	/* no need to queue it again if it is already queued: */
525 	if (apply->queued)
526 		return 0;
527 
528 	apply->queued = true;
529 	list_add_tail(&apply->queued_node, &omap_crtc->queued_applies);
530 
531 	/*
532 	 * If there are no currently pending updates, then go ahead and
533 	 * kick the worker immediately, otherwise it will run again when
534 	 * the current update finishes.
535 	 */
536 	if (list_empty(&omap_crtc->pending_applies)) {
537 		struct omap_drm_private *priv = crtc->dev->dev_private;
538 		queue_work(priv->wq, &omap_crtc->apply_work);
539 	}
540 
541 	return 0;
542 }
543 
544 /* called only from apply */
545 static void set_enabled(struct drm_crtc *crtc, bool enable)
546 {
547 	struct drm_device *dev = crtc->dev;
548 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
549 	enum omap_channel channel = omap_crtc->channel;
550 	struct omap_irq_wait *wait;
551 	u32 framedone_irq, vsync_irq;
552 	int ret;
553 
554 	if (dispc_mgr_is_enabled(channel) == enable)
555 		return;
556 
557 	/*
558 	 * Digit output produces some sync lost interrupts during the first
559 	 * frame when enabling, so we need to ignore those.
560 	 */
561 	omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
562 
563 	framedone_irq = dispc_mgr_get_framedone_irq(channel);
564 	vsync_irq = dispc_mgr_get_vsync_irq(channel);
565 
566 	if (enable) {
567 		wait = omap_irq_wait_init(dev, vsync_irq, 1);
568 	} else {
569 		/*
570 		 * When we disable the digit output, we need to wait for
571 		 * FRAMEDONE to know that DISPC has finished with the output.
572 		 *
573 		 * OMAP2/3 does not have FRAMEDONE irq for digit output, and in
574 		 * that case we need to use vsync interrupt, and wait for both
575 		 * even and odd frames.
576 		 */
577 
578 		if (framedone_irq)
579 			wait = omap_irq_wait_init(dev, framedone_irq, 1);
580 		else
581 			wait = omap_irq_wait_init(dev, vsync_irq, 2);
582 	}
583 
584 	dispc_mgr_enable(channel, enable);
585 
586 	ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100));
587 	if (ret) {
588 		dev_err(dev->dev, "%s: timeout waiting for %s\n",
589 				omap_crtc->name, enable ? "enable" : "disable");
590 	}
591 
592 	omap_irq_register(crtc->dev, &omap_crtc->error_irq);
593 }
594 
595 static void omap_crtc_pre_apply(struct omap_drm_apply *apply)
596 {
597 	struct omap_crtc *omap_crtc =
598 			container_of(apply, struct omap_crtc, apply);
599 	struct drm_crtc *crtc = &omap_crtc->base;
600 	struct drm_encoder *encoder = NULL;
601 
602 	DBG("%s: enabled=%d, full=%d", omap_crtc->name,
603 			omap_crtc->enabled, omap_crtc->full_update);
604 
605 	if (omap_crtc->full_update) {
606 		struct omap_drm_private *priv = crtc->dev->dev_private;
607 		int i;
608 		for (i = 0; i < priv->num_encoders; i++) {
609 			if (priv->encoders[i]->crtc == crtc) {
610 				encoder = priv->encoders[i];
611 				break;
612 			}
613 		}
614 	}
615 
616 	if (omap_crtc->current_encoder && encoder != omap_crtc->current_encoder)
617 		omap_encoder_set_enabled(omap_crtc->current_encoder, false);
618 
619 	omap_crtc->current_encoder = encoder;
620 
621 	if (!omap_crtc->enabled) {
622 		if (encoder)
623 			omap_encoder_set_enabled(encoder, false);
624 	} else {
625 		if (encoder) {
626 			omap_encoder_set_enabled(encoder, false);
627 			omap_encoder_update(encoder, omap_crtc->mgr,
628 					&omap_crtc->timings);
629 			omap_encoder_set_enabled(encoder, true);
630 		}
631 	}
632 
633 	omap_crtc->full_update = false;
634 }
635 
636 static void omap_crtc_post_apply(struct omap_drm_apply *apply)
637 {
638 	/* nothing needed for post-apply */
639 }
640 
641 void omap_crtc_flush(struct drm_crtc *crtc)
642 {
643 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
644 	int loops = 0;
645 
646 	while (!list_empty(&omap_crtc->pending_applies) ||
647 		!list_empty(&omap_crtc->queued_applies) ||
648 		omap_crtc->event || omap_crtc->old_fb) {
649 
650 		if (++loops > 10) {
651 			dev_err(crtc->dev->dev,
652 				"omap_crtc_flush() timeout\n");
653 			break;
654 		}
655 
656 		schedule_timeout_uninterruptible(msecs_to_jiffies(20));
657 	}
658 }
659 
660 static const char *channel_names[] = {
661 		[OMAP_DSS_CHANNEL_LCD] = "lcd",
662 		[OMAP_DSS_CHANNEL_DIGIT] = "tv",
663 		[OMAP_DSS_CHANNEL_LCD2] = "lcd2",
664 		[OMAP_DSS_CHANNEL_LCD3] = "lcd3",
665 };
666 
667 void omap_crtc_pre_init(void)
668 {
669 	dss_install_mgr_ops(&mgr_ops);
670 }
671 
672 void omap_crtc_pre_uninit(void)
673 {
674 	dss_uninstall_mgr_ops();
675 }
676 
677 /* initialize crtc */
678 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
679 		struct drm_plane *plane, enum omap_channel channel, int id)
680 {
681 	struct drm_crtc *crtc = NULL;
682 	struct omap_crtc *omap_crtc;
683 	struct omap_overlay_manager_info *info;
684 
685 	DBG("%s", channel_names[channel]);
686 
687 	omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL);
688 	if (!omap_crtc)
689 		goto fail;
690 
691 	crtc = &omap_crtc->base;
692 
693 	INIT_WORK(&omap_crtc->page_flip_work, page_flip_worker);
694 	INIT_WORK(&omap_crtc->apply_work, apply_worker);
695 
696 	INIT_LIST_HEAD(&omap_crtc->pending_applies);
697 	INIT_LIST_HEAD(&omap_crtc->queued_applies);
698 
699 	omap_crtc->apply.pre_apply  = omap_crtc_pre_apply;
700 	omap_crtc->apply.post_apply = omap_crtc_post_apply;
701 
702 	omap_crtc->channel = channel;
703 	omap_crtc->plane = plane;
704 	omap_crtc->plane->crtc = crtc;
705 	omap_crtc->name = channel_names[channel];
706 	omap_crtc->pipe = id;
707 
708 	omap_crtc->apply_irq.irqmask = pipe2vbl(crtc);
709 	omap_crtc->apply_irq.irq = omap_crtc_apply_irq;
710 
711 	omap_crtc->error_irq.irqmask =
712 			dispc_mgr_get_sync_lost_irq(channel);
713 	omap_crtc->error_irq.irq = omap_crtc_error_irq;
714 	omap_irq_register(dev, &omap_crtc->error_irq);
715 
716 	/* temporary: */
717 	omap_crtc->mgr = omap_dss_get_overlay_manager(channel);
718 
719 	/* TODO: fix hard-coded setup.. add properties! */
720 	info = &omap_crtc->info;
721 	info->default_color = 0x00000000;
722 	info->trans_key = 0x00000000;
723 	info->trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
724 	info->trans_enabled = false;
725 
726 	drm_crtc_init(dev, crtc, &omap_crtc_funcs);
727 	drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs);
728 
729 	omap_plane_install_properties(omap_crtc->plane, &crtc->base);
730 
731 	omap_crtcs[channel] = omap_crtc;
732 
733 	return crtc;
734 
735 fail:
736 	if (crtc)
737 		omap_crtc_destroy(crtc);
738 
739 	return NULL;
740 }
741