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