1076bc0a7f788a0578f34e28001d4854b989ba68
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / omapdrm / omap_crtc.c
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 <linux/completion.h>
21
22 #include "omap_drv.h"
23
24 #include <drm/drm_mode.h>
25 #include <drm/drm_plane_helper.h>
26 #include "drm_crtc.h"
27 #include "drm_crtc_helper.h"
28
29 #define to_omap_crtc(x) container_of(x, struct omap_crtc, base)
30
31 enum omap_page_flip_state {
32         OMAP_PAGE_FLIP_IDLE,
33         OMAP_PAGE_FLIP_WAIT,
34         OMAP_PAGE_FLIP_QUEUED,
35         OMAP_PAGE_FLIP_CANCELLED,
36 };
37
38 struct omap_crtc {
39         struct drm_crtc base;
40
41         const char *name;
42         int pipe;
43         enum omap_channel channel;
44         struct omap_overlay_manager_info info;
45         struct drm_encoder *current_encoder;
46
47         /*
48          * Temporary: eventually this will go away, but it is needed
49          * for now to keep the output's happy.  (They only need
50          * mgr->id.)  Eventually this will be replaced w/ something
51          * more common-panel-framework-y
52          */
53         struct omap_overlay_manager *mgr;
54
55         struct omap_video_timings timings;
56         bool enabled;
57
58         struct omap_drm_irq vblank_irq;
59         struct omap_drm_irq error_irq;
60
61         /* list of framebuffers to unpin */
62         struct list_head pending_unpins;
63
64         /*
65          * flip_state flag indicates the current page flap state: IDLE if no
66          * page queue has been submitted, WAIT when waiting for GEM async
67          * completion, QUEUED when the page flip has been queued to the hardware
68          * or CANCELLED when the CRTC is turned off before the flip gets queued
69          * to the hardware. The flip event, if any, is stored in flip_event. The
70          * flip_wait wait queue is used to wait for page flip completion.
71          *
72          * The flip_work work queue handles page flip requests without caring
73          * about what context the GEM async callback is called from. Possibly we
74          * should just make omap_gem always call the cb from the worker so we
75          * don't have to care about this.
76          */
77         enum omap_page_flip_state flip_state;
78         struct drm_pending_vblank_event *flip_event;
79         wait_queue_head_t flip_wait;
80         struct work_struct flip_work;
81
82         struct completion completion;
83
84         bool ignore_digit_sync_lost;
85 };
86
87 struct omap_framebuffer_unpin {
88         struct list_head list;
89         struct drm_framebuffer *fb;
90 };
91
92 /* -----------------------------------------------------------------------------
93  * Helper Functions
94  */
95
96 uint32_t pipe2vbl(struct drm_crtc *crtc)
97 {
98         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
99
100         return dispc_mgr_get_vsync_irq(omap_crtc->channel);
101 }
102
103 const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc)
104 {
105         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
106         return &omap_crtc->timings;
107 }
108
109 enum omap_channel omap_crtc_channel(struct drm_crtc *crtc)
110 {
111         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
112         return omap_crtc->channel;
113 }
114
115 /* -----------------------------------------------------------------------------
116  * DSS Manager Functions
117  */
118
119 /*
120  * Manager-ops, callbacks from output when they need to configure
121  * the upstream part of the video pipe.
122  *
123  * Most of these we can ignore until we add support for command-mode
124  * panels.. for video-mode the crtc-helpers already do an adequate
125  * job of sequencing the setup of the video pipe in the proper order
126  */
127
128 /* ovl-mgr-id -> crtc */
129 static struct omap_crtc *omap_crtcs[8];
130
131 /* we can probably ignore these until we support command-mode panels: */
132 static int omap_crtc_connect(struct omap_overlay_manager *mgr,
133                 struct omap_dss_device *dst)
134 {
135         if (mgr->output)
136                 return -EINVAL;
137
138         if ((mgr->supported_outputs & dst->id) == 0)
139                 return -EINVAL;
140
141         dst->manager = mgr;
142         mgr->output = dst;
143
144         return 0;
145 }
146
147 static void omap_crtc_disconnect(struct omap_overlay_manager *mgr,
148                 struct omap_dss_device *dst)
149 {
150         mgr->output->manager = NULL;
151         mgr->output = NULL;
152 }
153
154 static void omap_crtc_start_update(struct omap_overlay_manager *mgr)
155 {
156 }
157
158 /* Called only from omap_crtc_setup and suspend/resume handlers. */
159 static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
160 {
161         struct drm_device *dev = crtc->dev;
162         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
163         enum omap_channel channel = omap_crtc->channel;
164         struct omap_irq_wait *wait;
165         u32 framedone_irq, vsync_irq;
166         int ret;
167
168         if (dispc_mgr_is_enabled(channel) == enable)
169                 return;
170
171         if (omap_crtc->channel == OMAP_DSS_CHANNEL_DIGIT) {
172                 /*
173                  * Digit output produces some sync lost interrupts during the
174                  * first frame when enabling, so we need to ignore those.
175                  */
176                 omap_crtc->ignore_digit_sync_lost = true;
177         }
178
179         framedone_irq = dispc_mgr_get_framedone_irq(channel);
180         vsync_irq = dispc_mgr_get_vsync_irq(channel);
181
182         if (enable) {
183                 wait = omap_irq_wait_init(dev, vsync_irq, 1);
184         } else {
185                 /*
186                  * When we disable the digit output, we need to wait for
187                  * FRAMEDONE to know that DISPC has finished with the output.
188                  *
189                  * OMAP2/3 does not have FRAMEDONE irq for digit output, and in
190                  * that case we need to use vsync interrupt, and wait for both
191                  * even and odd frames.
192                  */
193
194                 if (framedone_irq)
195                         wait = omap_irq_wait_init(dev, framedone_irq, 1);
196                 else
197                         wait = omap_irq_wait_init(dev, vsync_irq, 2);
198         }
199
200         dispc_mgr_enable(channel, enable);
201
202         ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100));
203         if (ret) {
204                 dev_err(dev->dev, "%s: timeout waiting for %s\n",
205                                 omap_crtc->name, enable ? "enable" : "disable");
206         }
207
208         if (omap_crtc->channel == OMAP_DSS_CHANNEL_DIGIT) {
209                 omap_crtc->ignore_digit_sync_lost = false;
210                 /* make sure the irq handler sees the value above */
211                 mb();
212         }
213 }
214
215
216 static int omap_crtc_enable(struct omap_overlay_manager *mgr)
217 {
218         struct omap_crtc *omap_crtc = omap_crtcs[mgr->id];
219
220         dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info);
221         dispc_mgr_set_timings(omap_crtc->channel,
222                         &omap_crtc->timings);
223         omap_crtc_set_enabled(&omap_crtc->base, true);
224
225         return 0;
226 }
227
228 static void omap_crtc_disable(struct omap_overlay_manager *mgr)
229 {
230         struct omap_crtc *omap_crtc = omap_crtcs[mgr->id];
231
232         omap_crtc_set_enabled(&omap_crtc->base, false);
233 }
234
235 static void omap_crtc_set_timings(struct omap_overlay_manager *mgr,
236                 const struct omap_video_timings *timings)
237 {
238         struct omap_crtc *omap_crtc = omap_crtcs[mgr->id];
239         DBG("%s", omap_crtc->name);
240         omap_crtc->timings = *timings;
241 }
242
243 static void omap_crtc_set_lcd_config(struct omap_overlay_manager *mgr,
244                 const struct dss_lcd_mgr_config *config)
245 {
246         struct omap_crtc *omap_crtc = omap_crtcs[mgr->id];
247         DBG("%s", omap_crtc->name);
248         dispc_mgr_set_lcd_config(omap_crtc->channel, config);
249 }
250
251 static int omap_crtc_register_framedone_handler(
252                 struct omap_overlay_manager *mgr,
253                 void (*handler)(void *), void *data)
254 {
255         return 0;
256 }
257
258 static void omap_crtc_unregister_framedone_handler(
259                 struct omap_overlay_manager *mgr,
260                 void (*handler)(void *), void *data)
261 {
262 }
263
264 static const struct dss_mgr_ops mgr_ops = {
265         .connect = omap_crtc_connect,
266         .disconnect = omap_crtc_disconnect,
267         .start_update = omap_crtc_start_update,
268         .enable = omap_crtc_enable,
269         .disable = omap_crtc_disable,
270         .set_timings = omap_crtc_set_timings,
271         .set_lcd_config = omap_crtc_set_lcd_config,
272         .register_framedone_handler = omap_crtc_register_framedone_handler,
273         .unregister_framedone_handler = omap_crtc_unregister_framedone_handler,
274 };
275
276 /* -----------------------------------------------------------------------------
277  * Setup, Flush and Page Flip
278  */
279
280 void omap_crtc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
281 {
282         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
283         struct drm_device *dev = crtc->dev;
284         unsigned long flags;
285
286         spin_lock_irqsave(&dev->event_lock, flags);
287
288         /* Only complete events queued for our file handle. */
289         if (omap_crtc->flip_event &&
290             file == omap_crtc->flip_event->base.file_priv) {
291                 drm_send_vblank_event(dev, omap_crtc->pipe,
292                                       omap_crtc->flip_event);
293                 omap_crtc->flip_event = NULL;
294         }
295
296         spin_unlock_irqrestore(&dev->event_lock, flags);
297 }
298
299 /* Must be called with dev->event_lock locked. */
300 static void omap_crtc_complete_page_flip(struct drm_crtc *crtc,
301                                          enum omap_page_flip_state state)
302 {
303         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
304         struct drm_device *dev = crtc->dev;
305
306         if (omap_crtc->flip_event) {
307                 drm_send_vblank_event(dev, omap_crtc->pipe,
308                                       omap_crtc->flip_event);
309                 omap_crtc->flip_event = NULL;
310         }
311
312         omap_crtc->flip_state = state;
313
314         if (state == OMAP_PAGE_FLIP_IDLE)
315                 wake_up(&omap_crtc->flip_wait);
316 }
317
318 static bool omap_crtc_page_flip_pending(struct drm_crtc *crtc)
319 {
320         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
321         struct drm_device *dev = crtc->dev;
322         unsigned long flags;
323         bool pending;
324
325         spin_lock_irqsave(&dev->event_lock, flags);
326         pending = omap_crtc->flip_state != OMAP_PAGE_FLIP_IDLE;
327         spin_unlock_irqrestore(&dev->event_lock, flags);
328
329         return pending;
330 }
331
332 static void omap_crtc_wait_page_flip(struct drm_crtc *crtc)
333 {
334         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
335         struct drm_device *dev = crtc->dev;
336         bool cancelled = false;
337         unsigned long flags;
338
339         /*
340          * If we're still waiting for the GEM async operation to complete just
341          * cancel the page flip, as we're holding the CRTC mutex preventing the
342          * page flip work handler from queueing the page flip.
343          *
344          * We can't release the reference to the frame buffer here as the async
345          * operation doesn't keep its own reference to the buffer. We'll just
346          * let the page flip work queue handle that.
347          */
348         spin_lock_irqsave(&dev->event_lock, flags);
349         if (omap_crtc->flip_state == OMAP_PAGE_FLIP_WAIT) {
350                 omap_crtc_complete_page_flip(crtc, OMAP_PAGE_FLIP_CANCELLED);
351                 cancelled = true;
352         }
353         spin_unlock_irqrestore(&dev->event_lock, flags);
354
355         if (cancelled)
356                 return;
357
358         if (wait_event_timeout(omap_crtc->flip_wait,
359                                !omap_crtc_page_flip_pending(crtc),
360                                msecs_to_jiffies(50)))
361                 return;
362
363         dev_warn(crtc->dev->dev, "page flip timeout!\n");
364
365         spin_lock_irqsave(&dev->event_lock, flags);
366         omap_crtc_complete_page_flip(crtc, OMAP_PAGE_FLIP_IDLE);
367         spin_unlock_irqrestore(&dev->event_lock, flags);
368 }
369
370 static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
371 {
372         struct omap_crtc *omap_crtc =
373                         container_of(irq, struct omap_crtc, error_irq);
374
375         if (omap_crtc->ignore_digit_sync_lost) {
376                 irqstatus &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
377                 if (!irqstatus)
378                         return;
379         }
380
381         DRM_ERROR_RATELIMITED("%s: errors: %08x\n", omap_crtc->name, irqstatus);
382 }
383
384 static void omap_crtc_vblank_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
385 {
386         struct omap_crtc *omap_crtc =
387                         container_of(irq, struct omap_crtc, vblank_irq);
388         struct drm_device *dev = omap_crtc->base.dev;
389         unsigned long flags;
390
391         if (dispc_mgr_go_busy(omap_crtc->channel))
392                 return;
393
394         DBG("%s: apply done", omap_crtc->name);
395         __omap_irq_unregister(dev, &omap_crtc->vblank_irq);
396
397         /* wakeup userspace */
398         spin_lock_irqsave(&dev->event_lock, flags);
399         omap_crtc_complete_page_flip(&omap_crtc->base, OMAP_PAGE_FLIP_IDLE);
400         spin_unlock_irqrestore(&dev->event_lock, flags);
401
402         complete(&omap_crtc->completion);
403 }
404
405 int omap_crtc_flush(struct drm_crtc *crtc)
406 {
407         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
408         struct omap_framebuffer_unpin *fb, *next;
409
410         DBG("%s: GO", omap_crtc->name);
411
412         WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
413         WARN_ON(omap_crtc->vblank_irq.registered);
414
415         dispc_runtime_get();
416
417         if (dispc_mgr_is_enabled(omap_crtc->channel)) {
418                 dispc_mgr_go(omap_crtc->channel);
419                 omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
420
421                 WARN_ON(!wait_for_completion_timeout(&omap_crtc->completion,
422                                                      msecs_to_jiffies(100)));
423                 reinit_completion(&omap_crtc->completion);
424         }
425
426         dispc_runtime_put();
427
428         /* Unpin and unreference pending framebuffers. */
429         list_for_each_entry_safe(fb, next, &omap_crtc->pending_unpins, list) {
430                 omap_framebuffer_unpin(fb->fb);
431                 drm_framebuffer_unreference(fb->fb);
432                 list_del(&fb->list);
433                 kfree(fb);
434         }
435
436         return 0;
437 }
438
439 int omap_crtc_queue_unpin(struct drm_crtc *crtc, struct drm_framebuffer *fb)
440 {
441         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
442         struct omap_framebuffer_unpin *unpin;
443
444         unpin = kzalloc(sizeof(*unpin), GFP_KERNEL);
445         if (!unpin)
446                 return -ENOMEM;
447
448         unpin->fb = fb;
449         list_add_tail(&unpin->list, &omap_crtc->pending_unpins);
450
451         return 0;
452 }
453
454 static void omap_crtc_setup(struct drm_crtc *crtc)
455 {
456         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
457         struct omap_drm_private *priv = crtc->dev->dev_private;
458         struct drm_encoder *encoder = NULL;
459         unsigned int i;
460
461         DBG("%s: enabled=%d", omap_crtc->name, omap_crtc->enabled);
462
463         dispc_runtime_get();
464
465         for (i = 0; i < priv->num_encoders; i++) {
466                 if (priv->encoders[i]->crtc == crtc) {
467                         encoder = priv->encoders[i];
468                         break;
469                 }
470         }
471
472         if (omap_crtc->current_encoder && encoder != omap_crtc->current_encoder)
473                 omap_encoder_set_enabled(omap_crtc->current_encoder, false);
474
475         omap_crtc->current_encoder = encoder;
476
477         if (!omap_crtc->enabled) {
478                 if (encoder)
479                         omap_encoder_set_enabled(encoder, false);
480         } else {
481                 if (encoder) {
482                         omap_encoder_set_enabled(encoder, false);
483                         omap_encoder_update(encoder, omap_crtc->mgr,
484                                         &omap_crtc->timings);
485                         omap_encoder_set_enabled(encoder, true);
486                 }
487         }
488
489         dispc_runtime_put();
490 }
491
492 /* -----------------------------------------------------------------------------
493  * CRTC Functions
494  */
495
496 static void omap_crtc_destroy(struct drm_crtc *crtc)
497 {
498         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
499
500         DBG("%s", omap_crtc->name);
501
502         WARN_ON(omap_crtc->vblank_irq.registered);
503         omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
504
505         drm_crtc_cleanup(crtc);
506
507         kfree(omap_crtc);
508 }
509
510 static void omap_crtc_dpms(struct drm_crtc *crtc, int mode)
511 {
512         struct omap_drm_private *priv = crtc->dev->dev_private;
513         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
514         bool enable = (mode == DRM_MODE_DPMS_ON);
515         int i;
516
517         DBG("%s: %d", omap_crtc->name, mode);
518
519         if (enable == omap_crtc->enabled)
520                 return;
521
522         if (!enable) {
523                 omap_crtc_wait_page_flip(crtc);
524                 dispc_runtime_get();
525                 drm_crtc_vblank_off(crtc);
526                 dispc_runtime_put();
527         }
528
529         /* Enable/disable all planes associated with the CRTC. */
530         for (i = 0; i < priv->num_planes; i++) {
531                 struct drm_plane *plane = priv->planes[i];
532
533                 if (plane->crtc == crtc)
534                         WARN_ON(omap_plane_set_enable(plane, enable));
535         }
536
537         omap_crtc->enabled = enable;
538
539         omap_crtc_setup(crtc);
540         omap_crtc_flush(crtc);
541
542         if (enable) {
543                 dispc_runtime_get();
544                 drm_crtc_vblank_on(crtc);
545                 dispc_runtime_put();
546         }
547 }
548
549 static bool omap_crtc_mode_fixup(struct drm_crtc *crtc,
550                 const struct drm_display_mode *mode,
551                 struct drm_display_mode *adjusted_mode)
552 {
553         return true;
554 }
555
556 static int omap_crtc_mode_set(struct drm_crtc *crtc,
557                 struct drm_display_mode *mode,
558                 struct drm_display_mode *adjusted_mode,
559                 int x, int y,
560                 struct drm_framebuffer *old_fb)
561 {
562         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
563
564         mode = adjusted_mode;
565
566         DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
567                         omap_crtc->name, mode->base.id, mode->name,
568                         mode->vrefresh, mode->clock,
569                         mode->hdisplay, mode->hsync_start,
570                         mode->hsync_end, mode->htotal,
571                         mode->vdisplay, mode->vsync_start,
572                         mode->vsync_end, mode->vtotal,
573                         mode->type, mode->flags);
574
575         copy_timings_drm_to_omap(&omap_crtc->timings, mode);
576
577         /*
578          * The primary plane CRTC can be reset if the plane is disabled directly
579          * through the universal plane API. Set it again here.
580          */
581         crtc->primary->crtc = crtc;
582
583         return omap_plane_mode_set(crtc->primary, crtc, crtc->primary->fb,
584                                    0, 0, mode->hdisplay, mode->vdisplay,
585                                    x, y, mode->hdisplay, mode->vdisplay);
586 }
587
588 static void omap_crtc_prepare(struct drm_crtc *crtc)
589 {
590         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
591         DBG("%s", omap_crtc->name);
592         omap_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
593 }
594
595 static void omap_crtc_commit(struct drm_crtc *crtc)
596 {
597         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
598         DBG("%s", omap_crtc->name);
599         omap_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
600 }
601
602 static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
603                 struct drm_framebuffer *old_fb)
604 {
605         struct drm_plane *plane = crtc->primary;
606         struct drm_display_mode *mode = &crtc->mode;
607         int ret;
608
609         ret = omap_plane_mode_set(plane, crtc, crtc->primary->fb,
610                                   0, 0, mode->hdisplay, mode->vdisplay,
611                                   x, y, mode->hdisplay, mode->vdisplay);
612         if (ret < 0)
613                 return ret;
614
615         return omap_crtc_flush(crtc);
616 }
617
618 static void page_flip_worker(struct work_struct *work)
619 {
620         struct omap_crtc *omap_crtc =
621                         container_of(work, struct omap_crtc, flip_work);
622         struct drm_crtc *crtc = &omap_crtc->base;
623         struct drm_display_mode *mode = &crtc->mode;
624         struct drm_device *dev = crtc->dev;
625         struct drm_framebuffer *fb;
626         struct drm_gem_object *bo;
627         unsigned long flags;
628         bool queue_flip;
629
630         drm_modeset_lock(&crtc->mutex, NULL);
631
632         spin_lock_irqsave(&dev->event_lock, flags);
633         /*
634          * The page flip could have been cancelled while waiting for the GEM
635          * async operation to complete. Don't queue the flip in that case.
636          */
637         if (omap_crtc->flip_state == OMAP_PAGE_FLIP_WAIT) {
638                 omap_crtc->flip_state = OMAP_PAGE_FLIP_QUEUED;
639                 queue_flip = true;
640         } else {
641                 omap_crtc->flip_state = OMAP_PAGE_FLIP_IDLE;
642                 queue_flip = false;
643         }
644         spin_unlock_irqrestore(&dev->event_lock, flags);
645
646         fb = crtc->primary->fb;
647
648         if (queue_flip) {
649                 omap_plane_mode_set(crtc->primary, crtc, fb,
650                                     0, 0, mode->hdisplay, mode->vdisplay,
651                                     crtc->x, crtc->y, mode->hdisplay,
652                                     mode->vdisplay);
653                 omap_crtc_flush(crtc);
654         }
655
656         drm_modeset_unlock(&crtc->mutex);
657
658         bo = omap_framebuffer_bo(fb, 0);
659         drm_gem_object_unreference_unlocked(bo);
660         drm_framebuffer_unreference(crtc->primary->fb);
661 }
662
663 static void page_flip_cb(void *arg)
664 {
665         struct drm_crtc *crtc = arg;
666         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
667         struct omap_drm_private *priv = crtc->dev->dev_private;
668
669         /* avoid assumptions about what ctxt we are called from: */
670         queue_work(priv->wq, &omap_crtc->flip_work);
671 }
672
673 static int omap_crtc_page_flip(struct drm_crtc *crtc,
674                                struct drm_framebuffer *fb,
675                                struct drm_pending_vblank_event *event,
676                                uint32_t page_flip_flags)
677 {
678         struct drm_device *dev = crtc->dev;
679         struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
680         struct drm_plane *primary = crtc->primary;
681         struct drm_gem_object *bo;
682         unsigned long flags;
683
684         DBG("%d -> %d (event=%p)", primary->fb ? primary->fb->base.id : -1,
685                         fb->base.id, event);
686
687         spin_lock_irqsave(&dev->event_lock, flags);
688
689         if (omap_crtc->flip_state != OMAP_PAGE_FLIP_IDLE) {
690                 spin_unlock_irqrestore(&dev->event_lock, flags);
691                 dev_err(dev->dev, "already a pending flip\n");
692                 return -EBUSY;
693         }
694
695         omap_crtc->flip_event = event;
696         omap_crtc->flip_state = OMAP_PAGE_FLIP_WAIT;
697         primary->fb = fb;
698         drm_framebuffer_reference(fb);
699
700         spin_unlock_irqrestore(&dev->event_lock, flags);
701
702         /*
703          * Hold a reference temporarily until the crtc is updated
704          * and takes the reference to the bo.  This avoids it
705          * getting freed from under us:
706          */
707         bo = omap_framebuffer_bo(fb, 0);
708         drm_gem_object_reference(bo);
709
710         omap_gem_op_async(bo, OMAP_GEM_READ, page_flip_cb, crtc);
711
712         return 0;
713 }
714
715 static int omap_crtc_set_property(struct drm_crtc *crtc,
716                 struct drm_property *property, uint64_t val)
717 {
718         if (property == crtc->dev->mode_config.rotation_property) {
719                 crtc->invert_dimensions =
720                                 !!(val & ((1LL << DRM_ROTATE_90) | (1LL << DRM_ROTATE_270)));
721         }
722
723         return omap_plane_set_property(crtc->primary, property, val);
724 }
725
726 static const struct drm_crtc_funcs omap_crtc_funcs = {
727         .set_config = drm_crtc_helper_set_config,
728         .destroy = omap_crtc_destroy,
729         .page_flip = omap_crtc_page_flip,
730         .set_property = omap_crtc_set_property,
731 };
732
733 static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {
734         .dpms = omap_crtc_dpms,
735         .mode_fixup = omap_crtc_mode_fixup,
736         .mode_set = omap_crtc_mode_set,
737         .prepare = omap_crtc_prepare,
738         .commit = omap_crtc_commit,
739         .mode_set_base = omap_crtc_mode_set_base,
740 };
741
742 /* -----------------------------------------------------------------------------
743  * Init and Cleanup
744  */
745
746 static const char *channel_names[] = {
747         [OMAP_DSS_CHANNEL_LCD] = "lcd",
748         [OMAP_DSS_CHANNEL_DIGIT] = "tv",
749         [OMAP_DSS_CHANNEL_LCD2] = "lcd2",
750         [OMAP_DSS_CHANNEL_LCD3] = "lcd3",
751 };
752
753 void omap_crtc_pre_init(void)
754 {
755         dss_install_mgr_ops(&mgr_ops);
756 }
757
758 void omap_crtc_pre_uninit(void)
759 {
760         dss_uninstall_mgr_ops();
761 }
762
763 /* initialize crtc */
764 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
765                 struct drm_plane *plane, enum omap_channel channel, int id)
766 {
767         struct drm_crtc *crtc = NULL;
768         struct omap_crtc *omap_crtc;
769         struct omap_overlay_manager_info *info;
770         int ret;
771
772         DBG("%s", channel_names[channel]);
773
774         omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL);
775         if (!omap_crtc)
776                 return NULL;
777
778         crtc = &omap_crtc->base;
779
780         INIT_WORK(&omap_crtc->flip_work, page_flip_worker);
781         init_waitqueue_head(&omap_crtc->flip_wait);
782
783         INIT_LIST_HEAD(&omap_crtc->pending_unpins);
784
785         init_completion(&omap_crtc->completion);
786
787         omap_crtc->channel = channel;
788         omap_crtc->name = channel_names[channel];
789         omap_crtc->pipe = id;
790
791         omap_crtc->vblank_irq.irqmask = pipe2vbl(crtc);
792         omap_crtc->vblank_irq.irq = omap_crtc_vblank_irq;
793
794         omap_crtc->error_irq.irqmask =
795                         dispc_mgr_get_sync_lost_irq(channel);
796         omap_crtc->error_irq.irq = omap_crtc_error_irq;
797         omap_irq_register(dev, &omap_crtc->error_irq);
798
799         /* temporary: */
800         omap_crtc->mgr = omap_dss_get_overlay_manager(channel);
801
802         /* TODO: fix hard-coded setup.. add properties! */
803         info = &omap_crtc->info;
804         info->default_color = 0x00000000;
805         info->trans_key = 0x00000000;
806         info->trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
807         info->trans_enabled = false;
808
809         ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
810                                         &omap_crtc_funcs);
811         if (ret < 0) {
812                 kfree(omap_crtc);
813                 return NULL;
814         }
815
816         drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs);
817
818         omap_plane_install_properties(crtc->primary, &crtc->base);
819
820         omap_crtcs[channel] = omap_crtc;
821
822         return crtc;
823 }