summaryrefslogtreecommitdiff
path: root/drivers/staging/omapdrm/omap_fb.c
diff options
context:
space:
mode:
authorRob Clark <rob@ti.com>2012-03-05 16:48:35 (GMT)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-03-07 21:38:07 (GMT)
commitb33f34d3d10b9b00ca568740e7099da107d525b9 (patch)
treef63a9d59ae626af10018a38eb63b7f318c4a4800 /drivers/staging/omapdrm/omap_fb.c
parent9f18c95abba6dbfd13c86e0b8f3e7219df753f7e (diff)
downloadlinux-fsl-qoriq-b33f34d3d10b9b00ca568740e7099da107d525b9.tar.xz
staging: drm/omap: defer unpin until scanout completes
When flipping, defer unpinning until scanout completes, as indicated by the appropriate END_WIN irq. This also re-organizes things a bit, in replacing omap_fb_{pin,unpin} with omap_fb_replace(), to make it easier to add support for scanout synchronized DMM refill mode (flipping by just reprogramming DMM synchronized with DSS scanout). Signed-off-by: Rob Clark <rob@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/omapdrm/omap_fb.c')
-rw-r--r--drivers/staging/omapdrm/omap_fb.c84
1 files changed, 49 insertions, 35 deletions
diff --git a/drivers/staging/omapdrm/omap_fb.c b/drivers/staging/omapdrm/omap_fb.c
index 08e2e35..fcb248f 100644
--- a/drivers/staging/omapdrm/omap_fb.c
+++ b/drivers/staging/omapdrm/omap_fb.c
@@ -137,41 +137,6 @@ static const struct drm_framebuffer_funcs omap_framebuffer_funcs = {
.dirty = omap_framebuffer_dirty,
};
-/* pins buffer in preparation for scanout */
-int omap_framebuffer_pin(struct drm_framebuffer *fb)
-{
- struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
- int ret, i, n = drm_format_num_planes(omap_fb->format->pixel_format);
-
- for (i = 0; i < n; i++) {
- struct plane *plane = &omap_fb->planes[i];
- ret = omap_gem_get_paddr(plane->bo, &plane->paddr, true);
- if (ret)
- goto fail;
- }
-
- return 0;
-
-fail:
- while (--i > 0) {
- struct plane *plane = &omap_fb->planes[i];
- omap_gem_put_paddr(plane->bo);
- }
- return ret;
-}
-
-/* releases buffer when done with scanout */
-void omap_framebuffer_unpin(struct drm_framebuffer *fb)
-{
- struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
- int i, n = drm_format_num_planes(omap_fb->format->pixel_format);
-
- for (i = 0; i < n; i++) {
- struct plane *plane = &omap_fb->planes[i];
- omap_gem_put_paddr(plane->bo);
- }
-}
-
/* update ovl info for scanout, handles cases of multi-planar fb's, etc.
*/
void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y,
@@ -201,6 +166,55 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y,
}
}
+/* Call for unpin 'a' (if not NULL), and pin 'b' (if not NULL). Although
+ * buffers to unpin are just just pushed to the unpin fifo so that the
+ * caller can defer unpin until vblank.
+ *
+ * Note if this fails (ie. something went very wrong!), all buffers are
+ * unpinned, and the caller disables the overlay. We could have tried
+ * to revert back to the previous set of pinned buffers but if things are
+ * hosed there is no guarantee that would succeed.
+ */
+int omap_framebuffer_replace(struct drm_framebuffer *a,
+ struct drm_framebuffer *b, void *arg,
+ void (*unpin)(void *arg, struct drm_gem_object *bo))
+{
+ int ret = 0, i, na, nb;
+ struct omap_framebuffer *ofba = to_omap_framebuffer(a);
+ struct omap_framebuffer *ofbb = to_omap_framebuffer(b);
+
+ na = a ? drm_format_num_planes(a->pixel_format) : 0;
+ nb = b ? drm_format_num_planes(b->pixel_format) : 0;
+
+ for (i = 0; i < max(na, nb); i++) {
+ struct plane *pa, *pb;
+
+ pa = (i < na) ? &ofba->planes[i] : NULL;
+ pb = (i < nb) ? &ofbb->planes[i] : NULL;
+
+ if (pa) {
+ unpin(arg, pa->bo);
+ pa->paddr = 0;
+ }
+
+ if (pb && !ret)
+ ret = omap_gem_get_paddr(pb->bo, &pb->paddr, true);
+ }
+
+ if (ret) {
+ /* something went wrong.. unpin what has been pinned */
+ for (i = 0; i < nb; i++) {
+ struct plane *pb = &ofba->planes[i];
+ if (pb->paddr) {
+ unpin(arg, pb->bo);
+ pb->paddr = 0;
+ }
+ }
+ }
+
+ return ret;
+}
+
struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p)
{
struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);