|
@@ -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,
|