提交 72d0c336 编写于 作者: R Rob Clark 提交者: Greg Kroah-Hartman

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: NRob Clark <rob@ti.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 b66848eb
...@@ -118,25 +118,21 @@ static void omap_crtc_load_lut(struct drm_crtc *crtc) ...@@ -118,25 +118,21 @@ static void omap_crtc_load_lut(struct drm_crtc *crtc)
{ {
} }
static void page_flip_cb(void *arg) static void vblank_cb(void *arg)
{ {
static uint32_t sequence = 0;
struct drm_crtc *crtc = arg; struct drm_crtc *crtc = arg;
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct omap_crtc *omap_crtc = to_omap_crtc(crtc); struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
struct drm_pending_vblank_event *event = omap_crtc->event; struct drm_pending_vblank_event *event = omap_crtc->event;
struct drm_framebuffer *old_fb = omap_crtc->old_fb;
struct timeval now;
unsigned long flags; unsigned long flags;
struct timeval now;
WARN_ON(!event); WARN_ON(!event);
omap_crtc->event = NULL; omap_crtc->event = NULL;
omap_crtc->old_fb = NULL;
omap_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb);
/* wakeup userspace */ /* wakeup userspace */
/* TODO: this should happen *after* flip in vsync IRQ handler */
if (event) { if (event) {
spin_lock_irqsave(&dev->event_lock, flags); spin_lock_irqsave(&dev->event_lock, flags);
event->event.sequence = drm_vblank_count_and_time( event->event.sequence = drm_vblank_count_and_time(
...@@ -150,6 +146,23 @@ static void page_flip_cb(void *arg) ...@@ -150,6 +146,23 @@ static void page_flip_cb(void *arg)
} }
} }
static void page_flip_cb(void *arg)
{
struct drm_crtc *crtc = arg;
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
struct drm_framebuffer *old_fb = omap_crtc->old_fb;
omap_crtc->old_fb = NULL;
omap_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb);
/* really we'd like to setup the callback atomically w/ setting the
* new scanout buffer to avoid getting stuck waiting an extra vblank
* cycle.. for now go for correctness and later figure out speed..
*/
omap_plane_on_endwin(omap_crtc->plane, vblank_cb, crtc);
}
static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
struct drm_framebuffer *fb, struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event) struct drm_pending_vblank_event *event)
......
...@@ -85,6 +85,8 @@ int omap_plane_mode_set(struct drm_plane *plane, ...@@ -85,6 +85,8 @@ int omap_plane_mode_set(struct drm_plane *plane,
unsigned int crtc_w, unsigned int crtc_h, unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y, uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h); uint32_t src_w, uint32_t src_h);
void omap_plane_on_endwin(struct drm_plane *plane,
void (*fxn)(void *), void *arg);
struct drm_encoder *omap_encoder_init(struct drm_device *dev, struct drm_encoder *omap_encoder_init(struct drm_device *dev,
struct omap_overlay_manager *mgr); struct omap_overlay_manager *mgr);
......
...@@ -31,6 +31,11 @@ ...@@ -31,6 +31,11 @@
* plane funcs * plane funcs
*/ */
struct callback {
void (*fxn)(void *);
void *arg;
};
#define to_omap_plane(x) container_of(x, struct omap_plane, base) #define to_omap_plane(x) container_of(x, struct omap_plane, base)
struct omap_plane { struct omap_plane {
...@@ -58,6 +63,9 @@ struct omap_plane { ...@@ -58,6 +63,9 @@ struct omap_plane {
/* for deferred unpin when we need to wait for scanout complete irq */ /* for deferred unpin when we need to wait for scanout complete irq */
struct work_struct work; struct work_struct work;
/* callback on next endwin irq */
struct callback endwin;
}; };
/* map from ovl->id to the irq we are interested in for scanout-done */ /* 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,6 +92,7 @@ static void unpin_worker(struct work_struct *work)
{ {
struct omap_plane *omap_plane = struct omap_plane *omap_plane =
container_of(work, struct omap_plane, work); container_of(work, struct omap_plane, work);
struct callback endwin;
mutex_lock(&omap_plane->unpin_mutex); mutex_lock(&omap_plane->unpin_mutex);
DBG("unpinning %d of %d", omap_plane->num_unpins, DBG("unpinning %d of %d", omap_plane->num_unpins,
...@@ -96,7 +105,28 @@ static void unpin_worker(struct work_struct *work) ...@@ -96,7 +105,28 @@ static void unpin_worker(struct work_struct *work)
drm_gem_object_unreference_unlocked(bo); drm_gem_object_unreference_unlocked(bo);
omap_plane->num_unpins--; omap_plane->num_unpins--;
} }
endwin = omap_plane->endwin;
omap_plane->endwin.fxn = NULL;
mutex_unlock(&omap_plane->unpin_mutex); mutex_unlock(&omap_plane->unpin_mutex);
if (endwin.fxn)
endwin.fxn(endwin.arg);
}
static void install_irq(struct drm_plane *plane)
{
struct omap_plane *omap_plane = to_omap_plane(plane);
struct omap_overlay *ovl = omap_plane->ovl;
int ret;
ret = omap_dispc_register_isr(dispc_isr, plane, id2irq[ovl->id]);
/*
* omapdss has upper limit on # of registered irq handlers,
* which we shouldn't hit.. but if we do the limit should
* be raised or bad things happen:
*/
WARN_ON(ret == -EBUSY);
} }
/* push changes down to dss2 */ /* push changes down to dss2 */
...@@ -146,17 +176,8 @@ static int commit(struct drm_plane *plane) ...@@ -146,17 +176,8 @@ static int commit(struct drm_plane *plane)
* NOTE: really this should be atomic w/ mgr->apply() but * NOTE: really this should be atomic w/ mgr->apply() but
* omapdss does not expose such an API * omapdss does not expose such an API
*/ */
if (omap_plane->num_unpins > 0) { if (omap_plane->num_unpins > 0)
ret = omap_dispc_register_isr(dispc_isr, install_irq(plane);
plane, id2irq[ovl->id]);
}
/*
* omapdss has upper limit on # of registered irq handlers,
* which we shouldn't hit.. but if we do the limit should
* be raised or bad things happen:
*/
WARN_ON(ret == -EBUSY);
} else { } else {
struct omap_drm_private *priv = dev->dev_private; struct omap_drm_private *priv = dev->dev_private;
...@@ -375,6 +396,19 @@ int omap_plane_dpms(struct drm_plane *plane, int mode) ...@@ -375,6 +396,19 @@ int omap_plane_dpms(struct drm_plane *plane, int mode)
return r; return r;
} }
void omap_plane_on_endwin(struct drm_plane *plane,
void (*fxn)(void *), void *arg)
{
struct omap_plane *omap_plane = to_omap_plane(plane);
mutex_lock(&omap_plane->unpin_mutex);
omap_plane->endwin.fxn = fxn;
omap_plane->endwin.arg = arg;
mutex_unlock(&omap_plane->unpin_mutex);
install_irq(plane);
}
static const struct drm_plane_funcs omap_plane_funcs = { static const struct drm_plane_funcs omap_plane_funcs = {
.update_plane = omap_plane_update, .update_plane = omap_plane_update,
.disable_plane = omap_plane_disable, .disable_plane = omap_plane_disable,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册