diff options
author | Rob Clark <rob@ti.com> | 2012-03-11 22:11:21 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-03-13 18:44:44 -0400 |
commit | 72d0c3363e88d1816b0fef3687ff58e6553a7889 (patch) | |
tree | 37df0421313dc94b41f9217032d784c3c6288c66 /drivers/staging | |
parent | b66848eb85c2a646c852ea4644f43e1a86517245 (diff) |
staging: drm/omap: send page-flip event after endwin
The endwin irq indicates that DSS has finished scanning out a buffer.
Use this to trigger page-flip event to userspace, so this happens
only *after* the previous buffer is finished.
Signed-off-by: Rob Clark <rob@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/omapdrm/omap_crtc.c | 27 | ||||
-rw-r--r-- | drivers/staging/omapdrm/omap_drv.h | 2 | ||||
-rw-r--r-- | drivers/staging/omapdrm/omap_plane.c | 56 |
3 files changed, 67 insertions, 18 deletions
diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c index 17ca163e5896..13e3c7f7d2b9 100644 --- a/drivers/staging/omapdrm/omap_crtc.c +++ b/drivers/staging/omapdrm/omap_crtc.c | |||
@@ -118,25 +118,21 @@ static void omap_crtc_load_lut(struct drm_crtc *crtc) | |||
118 | { | 118 | { |
119 | } | 119 | } |
120 | 120 | ||
121 | static void page_flip_cb(void *arg) | 121 | static void vblank_cb(void *arg) |
122 | { | 122 | { |
123 | static uint32_t sequence = 0; | ||
123 | struct drm_crtc *crtc = arg; | 124 | struct drm_crtc *crtc = arg; |
124 | struct drm_device *dev = crtc->dev; | 125 | struct drm_device *dev = crtc->dev; |
125 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 126 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
126 | struct drm_pending_vblank_event *event = omap_crtc->event; | 127 | struct drm_pending_vblank_event *event = omap_crtc->event; |
127 | struct drm_framebuffer *old_fb = omap_crtc->old_fb; | ||
128 | struct timeval now; | ||
129 | unsigned long flags; | 128 | unsigned long flags; |
129 | struct timeval now; | ||
130 | 130 | ||
131 | WARN_ON(!event); | 131 | WARN_ON(!event); |
132 | 132 | ||
133 | omap_crtc->event = NULL; | 133 | omap_crtc->event = NULL; |
134 | omap_crtc->old_fb = NULL; | ||
135 | |||
136 | omap_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb); | ||
137 | 134 | ||
138 | /* wakeup userspace */ | 135 | /* wakeup userspace */ |
139 | /* TODO: this should happen *after* flip in vsync IRQ handler */ | ||
140 | if (event) { | 136 | if (event) { |
141 | spin_lock_irqsave(&dev->event_lock, flags); | 137 | spin_lock_irqsave(&dev->event_lock, flags); |
142 | event->event.sequence = drm_vblank_count_and_time( | 138 | event->event.sequence = drm_vblank_count_and_time( |
@@ -150,6 +146,23 @@ static void page_flip_cb(void *arg) | |||
150 | } | 146 | } |
151 | } | 147 | } |
152 | 148 | ||
149 | static void page_flip_cb(void *arg) | ||
150 | { | ||
151 | struct drm_crtc *crtc = arg; | ||
152 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | ||
153 | struct drm_framebuffer *old_fb = omap_crtc->old_fb; | ||
154 | |||
155 | omap_crtc->old_fb = NULL; | ||
156 | |||
157 | omap_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb); | ||
158 | |||
159 | /* really we'd like to setup the callback atomically w/ setting the | ||
160 | * new scanout buffer to avoid getting stuck waiting an extra vblank | ||
161 | * cycle.. for now go for correctness and later figure out speed.. | ||
162 | */ | ||
163 | omap_plane_on_endwin(omap_crtc->plane, vblank_cb, crtc); | ||
164 | } | ||
165 | |||
153 | static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, | 166 | static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, |
154 | struct drm_framebuffer *fb, | 167 | struct drm_framebuffer *fb, |
155 | struct drm_pending_vblank_event *event) | 168 | struct drm_pending_vblank_event *event) |
diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h index 21e48cf430f4..b7e0f0773003 100644 --- a/drivers/staging/omapdrm/omap_drv.h +++ b/drivers/staging/omapdrm/omap_drv.h | |||
@@ -85,6 +85,8 @@ int omap_plane_mode_set(struct drm_plane *plane, | |||
85 | unsigned int crtc_w, unsigned int crtc_h, | 85 | unsigned int crtc_w, unsigned int crtc_h, |
86 | uint32_t src_x, uint32_t src_y, | 86 | uint32_t src_x, uint32_t src_y, |
87 | uint32_t src_w, uint32_t src_h); | 87 | uint32_t src_w, uint32_t src_h); |
88 | void omap_plane_on_endwin(struct drm_plane *plane, | ||
89 | void (*fxn)(void *), void *arg); | ||
88 | 90 | ||
89 | struct drm_encoder *omap_encoder_init(struct drm_device *dev, | 91 | struct drm_encoder *omap_encoder_init(struct drm_device *dev, |
90 | struct omap_overlay_manager *mgr); | 92 | struct omap_overlay_manager *mgr); |
diff --git a/drivers/staging/omapdrm/omap_plane.c b/drivers/staging/omapdrm/omap_plane.c index 9b3bfa02a91c..7997be74010d 100644 --- a/drivers/staging/omapdrm/omap_plane.c +++ b/drivers/staging/omapdrm/omap_plane.c | |||
@@ -31,6 +31,11 @@ | |||
31 | * plane funcs | 31 | * plane funcs |
32 | */ | 32 | */ |
33 | 33 | ||
34 | struct callback { | ||
35 | void (*fxn)(void *); | ||
36 | void *arg; | ||
37 | }; | ||
38 | |||
34 | #define to_omap_plane(x) container_of(x, struct omap_plane, base) | 39 | #define to_omap_plane(x) container_of(x, struct omap_plane, base) |
35 | 40 | ||
36 | struct omap_plane { | 41 | struct omap_plane { |
@@ -58,6 +63,9 @@ struct omap_plane { | |||
58 | 63 | ||
59 | /* for deferred unpin when we need to wait for scanout complete irq */ | 64 | /* for deferred unpin when we need to wait for scanout complete irq */ |
60 | struct work_struct work; | 65 | struct work_struct work; |
66 | |||
67 | /* callback on next endwin irq */ | ||
68 | struct callback endwin; | ||
61 | }; | 69 | }; |
62 | 70 | ||
63 | /* map from ovl->id to the irq we are interested in for scanout-done */ | 71 | /* map from ovl->id to the irq we are interested in for scanout-done */ |
@@ -84,6 +92,7 @@ static void unpin_worker(struct work_struct *work) | |||
84 | { | 92 | { |
85 | struct omap_plane *omap_plane = | 93 | struct omap_plane *omap_plane = |
86 | container_of(work, struct omap_plane, work); | 94 | container_of(work, struct omap_plane, work); |
95 | struct callback endwin; | ||
87 | 96 | ||
88 | mutex_lock(&omap_plane->unpin_mutex); | 97 | mutex_lock(&omap_plane->unpin_mutex); |
89 | DBG("unpinning %d of %d", omap_plane->num_unpins, | 98 | DBG("unpinning %d of %d", omap_plane->num_unpins, |
@@ -96,7 +105,28 @@ static void unpin_worker(struct work_struct *work) | |||
96 | drm_gem_object_unreference_unlocked(bo); | 105 | drm_gem_object_unreference_unlocked(bo); |
97 | omap_plane->num_unpins--; | 106 | omap_plane->num_unpins--; |
98 | } | 107 | } |
108 | endwin = omap_plane->endwin; | ||
109 | omap_plane->endwin.fxn = NULL; | ||
99 | mutex_unlock(&omap_plane->unpin_mutex); | 110 | mutex_unlock(&omap_plane->unpin_mutex); |
111 | |||
112 | if (endwin.fxn) | ||
113 | endwin.fxn(endwin.arg); | ||
114 | } | ||
115 | |||
116 | static void install_irq(struct drm_plane *plane) | ||
117 | { | ||
118 | struct omap_plane *omap_plane = to_omap_plane(plane); | ||
119 | struct omap_overlay *ovl = omap_plane->ovl; | ||
120 | int ret; | ||
121 | |||
122 | ret = omap_dispc_register_isr(dispc_isr, plane, id2irq[ovl->id]); | ||
123 | |||
124 | /* | ||
125 | * omapdss has upper limit on # of registered irq handlers, | ||
126 | * which we shouldn't hit.. but if we do the limit should | ||
127 | * be raised or bad things happen: | ||
128 | */ | ||
129 | WARN_ON(ret == -EBUSY); | ||
100 | } | 130 | } |
101 | 131 | ||
102 | /* push changes down to dss2 */ | 132 | /* push changes down to dss2 */ |
@@ -146,17 +176,8 @@ static int commit(struct drm_plane *plane) | |||
146 | * NOTE: really this should be atomic w/ mgr->apply() but | 176 | * NOTE: really this should be atomic w/ mgr->apply() but |
147 | * omapdss does not expose such an API | 177 | * omapdss does not expose such an API |
148 | */ | 178 | */ |
149 | if (omap_plane->num_unpins > 0) { | 179 | if (omap_plane->num_unpins > 0) |
150 | ret = omap_dispc_register_isr(dispc_isr, | 180 | install_irq(plane); |
151 | plane, id2irq[ovl->id]); | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * omapdss has upper limit on # of registered irq handlers, | ||
156 | * which we shouldn't hit.. but if we do the limit should | ||
157 | * be raised or bad things happen: | ||
158 | */ | ||
159 | WARN_ON(ret == -EBUSY); | ||
160 | 181 | ||
161 | } else { | 182 | } else { |
162 | struct omap_drm_private *priv = dev->dev_private; | 183 | struct omap_drm_private *priv = dev->dev_private; |
@@ -375,6 +396,19 @@ int omap_plane_dpms(struct drm_plane *plane, int mode) | |||
375 | return r; | 396 | return r; |
376 | } | 397 | } |
377 | 398 | ||
399 | void omap_plane_on_endwin(struct drm_plane *plane, | ||
400 | void (*fxn)(void *), void *arg) | ||
401 | { | ||
402 | struct omap_plane *omap_plane = to_omap_plane(plane); | ||
403 | |||
404 | mutex_lock(&omap_plane->unpin_mutex); | ||
405 | omap_plane->endwin.fxn = fxn; | ||
406 | omap_plane->endwin.arg = arg; | ||
407 | mutex_unlock(&omap_plane->unpin_mutex); | ||
408 | |||
409 | install_irq(plane); | ||
410 | } | ||
411 | |||
378 | static const struct drm_plane_funcs omap_plane_funcs = { | 412 | static const struct drm_plane_funcs omap_plane_funcs = { |
379 | .update_plane = omap_plane_update, | 413 | .update_plane = omap_plane_update, |
380 | .disable_plane = omap_plane_disable, | 414 | .disable_plane = omap_plane_disable, |