aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/omapdrm/omap_fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/omapdrm/omap_fb.c')
-rw-r--r--drivers/staging/omapdrm/omap_fb.c124
1 files changed, 85 insertions, 39 deletions
diff --git a/drivers/staging/omapdrm/omap_fb.c b/drivers/staging/omapdrm/omap_fb.c
index d021a7ec58df..04b235b6724a 100644
--- a/drivers/staging/omapdrm/omap_fb.c
+++ b/drivers/staging/omapdrm/omap_fb.c
@@ -59,6 +59,20 @@ static const struct format formats[] = {
{ OMAP_DSS_COLOR_UYVY, DRM_FORMAT_UYVY, {{2, 1}}, true },
};
+/* convert from overlay's pixel formats bitmask to an array of fourcc's */
+uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats,
+ uint32_t max_formats, enum omap_color_mode supported_modes)
+{
+ uint32_t nformats = 0;
+ int i = 0;
+
+ for (i = 0; i < ARRAY_SIZE(formats) && nformats < max_formats; i++)
+ if (formats[i].dss_format & supported_modes)
+ pixel_formats[nformats++] = formats[i].pixel_format;
+
+ return nformats;
+}
+
/* per-plane info for the fb: */
struct plane {
struct drm_gem_object *bo;
@@ -87,7 +101,7 @@ static int omap_framebuffer_create_handle(struct drm_framebuffer *fb,
static void omap_framebuffer_destroy(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);
+ int i, n = drm_format_num_planes(fb->pixel_format);
DBG("destroy: FB ID: %d (%p)", fb->base.id, fb);
@@ -123,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,
@@ -187,10 +166,59 @@ 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);
- if (p >= drm_format_num_planes(omap_fb->format->pixel_format))
+ if (p >= drm_format_num_planes(fb->pixel_format))
return NULL;
return omap_fb->planes[p].bo;
}
@@ -249,6 +277,24 @@ void omap_framebuffer_flush(struct drm_framebuffer *fb,
}
}
+#ifdef CONFIG_DEBUG_FS
+void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m)
+{
+ struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
+ int i, n = drm_format_num_planes(fb->pixel_format);
+
+ seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height,
+ (char *)&fb->pixel_format);
+
+ for (i = 0; i < n; i++) {
+ struct plane *plane = &omap_fb->planes[i];
+ seq_printf(m, " %d: offset=%d pitch=%d, obj: ",
+ i, plane->offset, plane->pitch);
+ omap_gem_describe(plane->bo, m);
+ }
+}
+#endif
+
struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd)
{
@@ -337,8 +383,8 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
plane->bo = bos[i];
plane->offset = mode_cmd->offsets[i];
- plane->pitch = mode_cmd->pitches[i];
- plane->paddr = pitch;
+ plane->pitch = pitch;
+ plane->paddr = 0;
}
drm_helper_mode_fill_fb_struct(fb, mode_cmd);