Skip to content

Commit

Permalink
staging: drm/omap: send page-flip event after endwin
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Rob Clark authored and Greg Kroah-Hartman committed Mar 13, 2012
1 parent b66848e commit 72d0c33
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 18 deletions.
27 changes: 20 additions & 7 deletions drivers/staging/omapdrm/omap_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_device *dev = crtc->dev;
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
struct drm_pending_vblank_event *event = omap_crtc->event;
struct drm_framebuffer *old_fb = omap_crtc->old_fb;
struct timeval now;
unsigned long flags;
struct timeval now;

WARN_ON(!event);

omap_crtc->event = NULL;
omap_crtc->old_fb = NULL;

omap_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb);

/* wakeup userspace */
/* TODO: this should happen *after* flip in vsync IRQ handler */
if (event) {
spin_lock_irqsave(&dev->event_lock, flags);
event->event.sequence = drm_vblank_count_and_time(
Expand All @@ -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,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event)
Expand Down
2 changes: 2 additions & 0 deletions drivers/staging/omapdrm/omap_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ int omap_plane_mode_set(struct drm_plane *plane,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
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 omap_overlay_manager *mgr);
Expand Down
56 changes: 45 additions & 11 deletions drivers/staging/omapdrm/omap_plane.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
* plane funcs
*/

struct callback {
void (*fxn)(void *);
void *arg;
};

#define to_omap_plane(x) container_of(x, struct omap_plane, base)

struct omap_plane {
Expand Down Expand Up @@ -58,6 +63,9 @@ struct omap_plane {

/* for deferred unpin when we need to wait for scanout complete irq */
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 */
Expand All @@ -84,6 +92,7 @@ static void unpin_worker(struct work_struct *work)
{
struct omap_plane *omap_plane =
container_of(work, struct omap_plane, work);
struct callback endwin;

mutex_lock(&omap_plane->unpin_mutex);
DBG("unpinning %d of %d", omap_plane->num_unpins,
Expand All @@ -96,7 +105,28 @@ static void unpin_worker(struct work_struct *work)
drm_gem_object_unreference_unlocked(bo);
omap_plane->num_unpins--;
}
endwin = omap_plane->endwin;
omap_plane->endwin.fxn = NULL;
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 */
Expand Down Expand Up @@ -146,17 +176,8 @@ static int commit(struct drm_plane *plane)
* NOTE: really this should be atomic w/ mgr->apply() but
* omapdss does not expose such an API
*/
if (omap_plane->num_unpins > 0) {
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);
if (omap_plane->num_unpins > 0)
install_irq(plane);

} else {
struct omap_drm_private *priv = dev->dev_private;
Expand Down Expand Up @@ -375,6 +396,19 @@ int omap_plane_dpms(struct drm_plane *plane, int mode)
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 = {
.update_plane = omap_plane_update,
.disable_plane = omap_plane_disable,
Expand Down

0 comments on commit 72d0c33

Please sign in to comment.