aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging
diff options
context:
space:
mode:
authorRob Clark <rob@ti.com>2012-03-11 22:11:21 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-03-13 18:44:44 -0400
commit72d0c3363e88d1816b0fef3687ff58e6553a7889 (patch)
tree37df0421313dc94b41f9217032d784c3c6288c66 /drivers/staging
parentb66848eb85c2a646c852ea4644f43e1a86517245 (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.c27
-rw-r--r--drivers/staging/omapdrm/omap_drv.h2
-rw-r--r--drivers/staging/omapdrm/omap_plane.c56
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
121static void page_flip_cb(void *arg) 121static 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
149static 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
153static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, 166static 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);
88void omap_plane_on_endwin(struct drm_plane *plane,
89 void (*fxn)(void *), void *arg);
88 90
89struct drm_encoder *omap_encoder_init(struct drm_device *dev, 91struct 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
34struct 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
36struct omap_plane { 41struct 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
116static 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
399void 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
378static const struct drm_plane_funcs omap_plane_funcs = { 412static 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,