[2/2] drm/omap: drm API update: addfb2

Message ID 1323737384-3145-3-git-send-email-rob.clark@linaro.org
State New
Headers show

Commit Message

Rob Clark Dec. 13, 2011, 12:49 a.m.
From: Rob Clark <rob@ti.com>

Update to reflect changes in:
"drm: add an fb creation ioctl that takes a pixel format v5"

Signed-off-by: Rob Clark <rob@ti.com>
---
 drivers/staging/omapdrm/omap_drv.h   |   53 ++++++++++++++++++-
 drivers/staging/omapdrm/omap_fb.c    |   96 ++++++++++++++++++++++++++-------
 drivers/staging/omapdrm/omap_fbdev.c |   29 ++++++----
 3 files changed, 143 insertions(+), 35 deletions(-)

Comments

Greg KH Dec. 13, 2011, 12:56 a.m. | #1
On Mon, Dec 12, 2011 at 06:49:44PM -0600, Rob Clark wrote:
> From: Rob Clark <rob@ti.com>
> 
> Update to reflect changes in:
> "drm: add an fb creation ioctl that takes a pixel format v5"

This one I'm going to have to wait for the drm api merges to happen, so
I'll just wait for them to go into Linus's tree before taking them, ok?

thanks,

greg k-h
Rob Clark Dec. 13, 2011, 1:02 a.m. | #2
On Mon, Dec 12, 2011 at 6:56 PM, Greg KH <greg@kroah.com> wrote:
> On Mon, Dec 12, 2011 at 06:49:44PM -0600, Rob Clark wrote:
>> From: Rob Clark <rob@ti.com>
>>
>> Update to reflect changes in:
>> "drm: add an fb creation ioctl that takes a pixel format v5"
>
> This one I'm going to have to wait for the drm api merges to happen, so
> I'll just wait for them to go into Linus's tree before taking them, ok?

Yup, thanks.  That was the intention.  Let me know if it gets
confusing to know which patches can go now and which have dependency
on other trees, and I can setup a git tree on freedesktop which
branches for the parts that depend on other trees.  I'm not sure if it
begins to get a mess to keep track otherwise.

BR,
-R

> thanks,
>
> greg k-h
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
Rob Clark Dec. 14, 2011, 2:18 a.m. | #3
On Mon, Dec 12, 2011 at 6:56 PM, Greg KH <greg@kroah.com> wrote:
> On Mon, Dec 12, 2011 at 06:49:44PM -0600, Rob Clark wrote:
>> From: Rob Clark <rob@ti.com>
>>
>> Update to reflect changes in:
>> "drm: add an fb creation ioctl that takes a pixel format v5"
>
> This one I'm going to have to wait for the drm api merges to happen, so
> I'll just wait for them to go into Linus's tree before taking them, ok?

oh, heh.. I found a couple small cleanups to this patch (adding a
"const" to a table, and such).. since this can't be applied until
drm-next is merged, if you don't mind I'd like to resend this one in a
patchset along with the patches adding drm_plane support, which I'm
pretty close to ready to send.

BR,
-R

> thanks,
>
> greg k-h
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
Greg KH Dec. 14, 2011, 6:45 p.m. | #4
On Tue, Dec 13, 2011 at 08:18:03PM -0600, Rob Clark wrote:
> On Mon, Dec 12, 2011 at 6:56 PM, Greg KH <greg@kroah.com> wrote:
> > On Mon, Dec 12, 2011 at 06:49:44PM -0600, Rob Clark wrote:
> >> From: Rob Clark <rob@ti.com>
> >>
> >> Update to reflect changes in:
> >> "drm: add an fb creation ioctl that takes a pixel format v5"
> >
> > This one I'm going to have to wait for the drm api merges to happen, so
> > I'll just wait for them to go into Linus's tree before taking them, ok?
> 
> oh, heh.. I found a couple small cleanups to this patch (adding a
> "const" to a table, and such).. since this can't be applied until
> drm-next is merged, if you don't mind I'd like to resend this one in a
> patchset along with the patches adding drm_plane support, which I'm
> pretty close to ready to send.

Ok, I've dropped it from my queue now.

greg k-h

Patch

diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h
index 8dd7d74..bc8daa7 100644
--- a/drivers/staging/omapdrm/omap_drv.h
+++ b/drivers/staging/omapdrm/omap_drv.h
@@ -76,9 +76,9 @@  void omap_connector_flush(struct drm_connector *connector,
 void omap_connector_dpms(struct drm_connector *connector, int mode);
 
 struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
-		struct drm_file *file, struct drm_mode_fb_cmd *mode_cmd);
+		struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd);
 struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
-		struct drm_mode_fb_cmd *mode_cmd, struct drm_gem_object *bo);
+		struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos);
 struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb);
 int omap_framebuffer_get_buffer(struct drm_framebuffer *fb, int x, int y,
 		void **vaddr, dma_addr_t *paddr, unsigned int *screen_width);
@@ -128,4 +128,53 @@  static inline int align_pitch(int pitch, int width, int bpp)
 	return ALIGN(pitch, 8 * bytespp);
 }
 
+/* should these be made into common util helpers?
+ */
+
+static inline int num_planes(uint32_t pixel_format)
+{
+	switch (pixel_format) {
+	default:
+		return 1;
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
+		return 2;
+	case DRM_FORMAT_YUV410:
+	case DRM_FORMAT_YVU410:
+	case DRM_FORMAT_YUV411:
+	case DRM_FORMAT_YVU411:
+	case DRM_FORMAT_YUV420:
+	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_YUV422:
+	case DRM_FORMAT_YVU422:
+	case DRM_FORMAT_YUV444:
+	case DRM_FORMAT_YVU444:
+		return 3;
+	}
+}
+
+static inline int objects_lookup(struct drm_device *dev,
+		struct drm_file *filp, uint32_t pixel_format,
+		struct drm_gem_object **bos, uint32_t *handles)
+{
+	int i, n = num_planes(pixel_format);
+
+	for (i = 0; i < n; i++) {
+		bos[i] = drm_gem_object_lookup(dev, filp, handles[i]);
+		if (!bos[i]) {
+			goto fail;
+		}
+	}
+
+	return 0;
+
+fail:
+	while (--i > 0) {
+		drm_gem_object_unreference_unlocked(bos[i]);
+	}
+	return -ENOENT;
+}
+
 #endif /* __OMAP_DRV_H__ */
diff --git a/drivers/staging/omapdrm/omap_fb.c b/drivers/staging/omapdrm/omap_fb.c
index 0b50c5b..b28fee3 100644
--- a/drivers/staging/omapdrm/omap_fb.c
+++ b/drivers/staging/omapdrm/omap_fb.c
@@ -22,11 +22,41 @@ 
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
 
-
 /*
  * framebuffer funcs
  */
 
+struct format {
+	enum omap_color_mode dss_format;
+	uint32_t pixel_format;
+	int stride_bpp;               /* this times width is stride */
+	bool yuv;
+};
+
+static struct format formats[] = {
+	/* 16bpp [A]RGB: */
+	{ OMAP_DSS_COLOR_RGB16,       DRM_FORMAT_RGB565,   2, false }, /* RGB16-565 */
+	{ OMAP_DSS_COLOR_RGB12U,      DRM_FORMAT_RGBX4444, 2, false }, /* RGB12x-4444 */
+	{ OMAP_DSS_COLOR_RGBX16,      DRM_FORMAT_XRGB4444, 2, false }, /* xRGB12-4444 */
+	{ OMAP_DSS_COLOR_RGBA16,      DRM_FORMAT_RGBA4444, 2, false }, /* RGBA12-4444 */
+	{ OMAP_DSS_COLOR_ARGB16,      DRM_FORMAT_ABGR4444, 2, false }, /* ARGB16-4444 */
+	{ OMAP_DSS_COLOR_XRGB16_1555, DRM_FORMAT_XRGB1555, 2, false }, /* xRGB15-1555 */
+	{ OMAP_DSS_COLOR_ARGB16_1555, DRM_FORMAT_ARGB1555, 2, false }, /* ARGB16-1555 */
+	/* 24bpp RGB: */
+	{ OMAP_DSS_COLOR_RGB24P,      DRM_FORMAT_RGB888,   3, false }, /* RGB24-888 */
+	/* 32bpp [A]RGB: */
+	{ OMAP_DSS_COLOR_RGBX32,      DRM_FORMAT_RGBX8888, 4, false }, /* RGBx24-8888 */
+	{ OMAP_DSS_COLOR_RGB24U,      DRM_FORMAT_XRGB8888, 4, false }, /* xRGB24-8888 */
+	{ OMAP_DSS_COLOR_RGBA32,      DRM_FORMAT_RGBA8888, 4, false }, /* RGBA32-8888 */
+	{ OMAP_DSS_COLOR_ARGB32,      DRM_FORMAT_ARGB8888, 4, false }, /* ARGB32-8888 */
+	/* YUV: */
+/* TODO: multi-planar support..
+	{ OMAP_DSS_COLOR_NV12,        DRM_FORMAT_NV12,     1, true },
+ */
+	{ OMAP_DSS_COLOR_YUV2,        DRM_FORMAT_YUYV,     2, true },
+	{ OMAP_DSS_COLOR_UYVY,        DRM_FORMAT_UYVY,     2, true },
+};
+
 #define to_omap_framebuffer(x) container_of(x, struct omap_framebuffer, base)
 
 struct omap_framebuffer {
@@ -171,39 +201,61 @@  void omap_framebuffer_flush(struct drm_framebuffer *fb,
 }
 
 struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
-		struct drm_file *file, struct drm_mode_fb_cmd *mode_cmd)
+		struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd)
 {
-	struct drm_gem_object *bo;
+	struct drm_gem_object *bos[4];
 	struct drm_framebuffer *fb;
-	bo = drm_gem_object_lookup(dev, file, mode_cmd->handle);
-	if (!bo) {
-		return ERR_PTR(-ENOENT);
-	}
-	fb = omap_framebuffer_init(dev, mode_cmd, bo);
-	if (!fb) {
-		return ERR_PTR(-ENOMEM);
+	int ret;
+
+	ret = objects_lookup(dev, file, mode_cmd->pixel_format,
+			bos, mode_cmd->handles);
+	if (ret)
+		return ERR_PTR(ret);
+
+	fb = omap_framebuffer_init(dev, mode_cmd, bos);
+	if (IS_ERR(fb)) {
+		int i, n = num_planes(mode_cmd->pixel_format);
+		for (i = 0; i < n; i++)
+			drm_gem_object_unreference_unlocked(bos[i]);
+		return fb;
 	}
 	return fb;
 }
 
 struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
-		struct drm_mode_fb_cmd *mode_cmd, struct drm_gem_object *bo)
+		struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)
 {
 	struct omap_framebuffer *omap_fb;
 	struct drm_framebuffer *fb = NULL;
-	int size, ret;
+	struct format *format = NULL;
+	int i, size, ret;
 
-	DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%d)",
+	DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4s)",
 			dev, mode_cmd, mode_cmd->width, mode_cmd->height,
-			mode_cmd->bpp);
+			(char *)&mode_cmd->pixel_format);
+
+	for (i = 0; i < ARRAY_SIZE(formats); i++) {
+		if (formats[i].pixel_format == mode_cmd->pixel_format) {
+			format = &formats[i];
+			break;
+		}
+	}
+
+	if (!format) {
+		dev_err(dev->dev, "unsupported pixel format: %4s\n",
+				(char *)&mode_cmd->pixel_format);
+		ret = -EINVAL;
+		goto fail;
+	}
 
 	/* in case someone tries to feed us a completely bogus stride: */
-	mode_cmd->pitch = align_pitch(mode_cmd->pitch,
-			mode_cmd->width, mode_cmd->bpp);
+	mode_cmd->pitches[0] = align_pitch(mode_cmd->pitches[0],
+			mode_cmd->width, format->stride_bpp);
 
 	omap_fb = kzalloc(sizeof(*omap_fb), GFP_KERNEL);
 	if (!omap_fb) {
 		dev_err(dev->dev, "could not allocate fb\n");
+		ret = -ENOMEM;
 		goto fail;
 	}
 
@@ -216,17 +268,19 @@  struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
 
 	DBG("create: FB ID: %d (%p)", fb->base.id, fb);
 
-	size = PAGE_ALIGN(mode_cmd->pitch * mode_cmd->height);
+	size = PAGE_ALIGN(mode_cmd->pitches[0] * mode_cmd->height);
 
-	if (size > bo->size) {
+	if (size > bos[0]->size) {
 		dev_err(dev->dev, "provided buffer object is too small!\n");
+		ret = -EINVAL;
 		goto fail;
 	}
 
-	omap_fb->bo = bo;
+	omap_fb->bo = bos[0];
 	omap_fb->size = size;
 
-	if (omap_gem_get_paddr(bo, &omap_fb->paddr, true)) {
+	ret = omap_gem_get_paddr(bos[0], &omap_fb->paddr, true);
+	if (ret) {
 		dev_err(dev->dev, "could not map (paddr)!\n");
 		goto fail;
 	}
@@ -239,5 +293,5 @@  fail:
 	if (fb) {
 		omap_framebuffer_destroy(fb);
 	}
-	return NULL;
+	return ERR_PTR(ret);
 }
diff --git a/drivers/staging/omapdrm/omap_fbdev.c b/drivers/staging/omapdrm/omap_fbdev.c
index 093ae2f..205eb23 100644
--- a/drivers/staging/omapdrm/omap_fbdev.c
+++ b/drivers/staging/omapdrm/omap_fbdev.c
@@ -129,7 +129,7 @@  static int omap_fbdev_create(struct drm_fb_helper *helper,
 	struct drm_framebuffer *fb = NULL;
 	union omap_gem_size gsize;
 	struct fb_info *fbi = NULL;
-	struct drm_mode_fb_cmd mode_cmd = {0};
+	struct drm_mode_fb_cmd2 mode_cmd = {0};
 	dma_addr_t paddr;
 	void __iomem *vaddr;
 	int size, screen_width;
@@ -145,37 +145,42 @@  static int omap_fbdev_create(struct drm_fb_helper *helper,
 			sizes->surface_height, sizes->surface_bpp,
 			sizes->fb_width, sizes->fb_height);
 
+	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+			sizes->surface_depth);
+
 	mode_cmd.width = sizes->surface_width;
 	mode_cmd.height = sizes->surface_height;
 
-	mode_cmd.bpp = sizes->surface_bpp;
-	mode_cmd.depth = sizes->surface_depth;
-
-	mode_cmd.pitch = align_pitch(
-			mode_cmd.width * ((mode_cmd.bpp + 7) / 8),
-			mode_cmd.width, mode_cmd.bpp);
+	mode_cmd.pitches[0] = align_pitch(
+			mode_cmd.width * ((sizes->surface_bpp + 7) / 8),
+			mode_cmd.width, sizes->surface_bpp);
 
 	fbdev->ywrap_enabled = priv->has_dmm && ywrap_enabled;
 	if (fbdev->ywrap_enabled) {
 		/* need to align pitch to page size if using DMM scrolling */
-		mode_cmd.pitch = ALIGN(mode_cmd.pitch, PAGE_SIZE);
+		mode_cmd.pitches[0] = ALIGN(mode_cmd.pitches[0], PAGE_SIZE);
 	}
 
 	/* allocate backing bo */
 	gsize = (union omap_gem_size){
-		.bytes = PAGE_ALIGN(mode_cmd.pitch * mode_cmd.height),
+		.bytes = PAGE_ALIGN(mode_cmd.pitches[0] * mode_cmd.height),
 	};
 	DBG("allocating %d bytes for fb %d", gsize.bytes, dev->primary->index);
 	fbdev->bo = omap_gem_new(dev, gsize, OMAP_BO_SCANOUT | OMAP_BO_WC);
 	if (!fbdev->bo) {
 		dev_err(dev->dev, "failed to allocate buffer object\n");
+		ret = -ENOMEM;
 		goto fail;
 	}
 
-	fb = omap_framebuffer_init(dev, &mode_cmd, fbdev->bo);
-	if (!fb) {
+	fb = omap_framebuffer_init(dev, &mode_cmd, &fbdev->bo);
+	if (IS_ERR(fb)) {
 		dev_err(dev->dev, "failed to allocate fb\n");
-		ret = -ENOMEM;
+		/* note: if fb creation failed, we can't rely on fb destroy
+		 * to unref the bo:
+		 */
+		drm_gem_object_unreference(fbdev->bo);
+		ret = PTR_ERR(fb);
 		goto fail;
 	}