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>
This commit is contained in:
parent
b66848eb85
commit
72d0c3363e
|
@ -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(
|
||||
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue