From 4d20dfc053c7e0b2d155cbc6cb0817717753e2b5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 26 Mar 2016 19:24:01 +0200 Subject: drm: omapdrm: fb: Limit number of planes per framebuffer to two The only multi-planar format supported by the driver is NV12, there will thus never be more than two planes per framebuffer. Signed-off-by: Laurent Pinchart Reviewed-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_fb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_fb.c') diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 5f3337f1e9aa..7646df33f9a1 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -36,7 +36,7 @@ struct format { struct { int stride_bpp; /* this times width is stride */ int sub_y; /* sub-sample in y dimension */ - } planes[4]; + } planes[2]; bool yuv; }; @@ -90,7 +90,7 @@ struct omap_framebuffer { struct drm_framebuffer base; int pin_count; const struct format *format; - struct plane planes[4]; + struct plane planes[2]; /* lock for pinning (pin_count and planes.paddr) */ struct mutex lock; }; -- cgit v1.2.3 From c9028b39597fbdcdac96641e12cc656a27c137c1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 7 Jun 2016 00:45:35 +0300 Subject: drm: omapdrm: fb: Use format information provided by the DRM core The driver stores in a custom structure named format several pieces of information about the format that are available in the DRM core. Remove them and get the information from the DRM core instead. Signed-off-by: Laurent Pinchart Reviewed-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_fb.c | 91 ++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 45 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_fb.c') diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 7646df33f9a1..6315d68989fc 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -29,37 +29,30 @@ * framebuffer funcs */ -/* per-format info: */ -struct format { +/* DSS to DRM formats mapping */ +static const struct { enum omap_color_mode dss_format; uint32_t pixel_format; - struct { - int stride_bpp; /* this times width is stride */ - int sub_y; /* sub-sample in y dimension */ - } planes[2]; - bool yuv; -}; - -static const struct format formats[] = { +} formats[] = { /* 16bpp [A]RGB: */ - { OMAP_DSS_COLOR_RGB16, DRM_FORMAT_RGB565, {{2, 1}}, false }, /* RGB16-565 */ - { OMAP_DSS_COLOR_RGB12U, DRM_FORMAT_RGBX4444, {{2, 1}}, false }, /* RGB12x-4444 */ - { OMAP_DSS_COLOR_RGBX16, DRM_FORMAT_XRGB4444, {{2, 1}}, false }, /* xRGB12-4444 */ - { OMAP_DSS_COLOR_RGBA16, DRM_FORMAT_RGBA4444, {{2, 1}}, false }, /* RGBA12-4444 */ - { OMAP_DSS_COLOR_ARGB16, DRM_FORMAT_ARGB4444, {{2, 1}}, false }, /* ARGB16-4444 */ - { OMAP_DSS_COLOR_XRGB16_1555, DRM_FORMAT_XRGB1555, {{2, 1}}, false }, /* xRGB15-1555 */ - { OMAP_DSS_COLOR_ARGB16_1555, DRM_FORMAT_ARGB1555, {{2, 1}}, false }, /* ARGB16-1555 */ + { OMAP_DSS_COLOR_RGB16, DRM_FORMAT_RGB565 }, /* RGB16-565 */ + { OMAP_DSS_COLOR_RGB12U, DRM_FORMAT_RGBX4444 }, /* RGB12x-4444 */ + { OMAP_DSS_COLOR_RGBX16, DRM_FORMAT_XRGB4444 }, /* xRGB12-4444 */ + { OMAP_DSS_COLOR_RGBA16, DRM_FORMAT_RGBA4444 }, /* RGBA12-4444 */ + { OMAP_DSS_COLOR_ARGB16, DRM_FORMAT_ARGB4444 }, /* ARGB16-4444 */ + { OMAP_DSS_COLOR_XRGB16_1555, DRM_FORMAT_XRGB1555 }, /* xRGB15-1555 */ + { OMAP_DSS_COLOR_ARGB16_1555, DRM_FORMAT_ARGB1555 }, /* ARGB16-1555 */ /* 24bpp RGB: */ - { OMAP_DSS_COLOR_RGB24P, DRM_FORMAT_RGB888, {{3, 1}}, false }, /* RGB24-888 */ + { OMAP_DSS_COLOR_RGB24P, DRM_FORMAT_RGB888 }, /* RGB24-888 */ /* 32bpp [A]RGB: */ - { OMAP_DSS_COLOR_RGBX32, DRM_FORMAT_RGBX8888, {{4, 1}}, false }, /* RGBx24-8888 */ - { OMAP_DSS_COLOR_RGB24U, DRM_FORMAT_XRGB8888, {{4, 1}}, false }, /* xRGB24-8888 */ - { OMAP_DSS_COLOR_RGBA32, DRM_FORMAT_RGBA8888, {{4, 1}}, false }, /* RGBA32-8888 */ - { OMAP_DSS_COLOR_ARGB32, DRM_FORMAT_ARGB8888, {{4, 1}}, false }, /* ARGB32-8888 */ + { OMAP_DSS_COLOR_RGBX32, DRM_FORMAT_RGBX8888 }, /* RGBx24-8888 */ + { OMAP_DSS_COLOR_RGB24U, DRM_FORMAT_XRGB8888 }, /* xRGB24-8888 */ + { OMAP_DSS_COLOR_RGBA32, DRM_FORMAT_RGBA8888 }, /* RGBA32-8888 */ + { OMAP_DSS_COLOR_ARGB32, DRM_FORMAT_ARGB8888 }, /* ARGB32-8888 */ /* YUV: */ - { OMAP_DSS_COLOR_NV12, DRM_FORMAT_NV12, {{1, 1}, {1, 2}}, true }, - { OMAP_DSS_COLOR_YUV2, DRM_FORMAT_YUYV, {{2, 1}}, true }, - { OMAP_DSS_COLOR_UYVY, DRM_FORMAT_UYVY, {{2, 1}}, true }, + { OMAP_DSS_COLOR_NV12, DRM_FORMAT_NV12 }, + { OMAP_DSS_COLOR_YUV2, DRM_FORMAT_YUYV }, + { OMAP_DSS_COLOR_UYVY, DRM_FORMAT_UYVY }, }; /* convert from overlay's pixel formats bitmask to an array of fourcc's */ @@ -89,7 +82,8 @@ struct plane { struct omap_framebuffer { struct drm_framebuffer base; int pin_count; - const struct format *format; + const struct drm_format_info *format; + enum omap_color_mode dss_format; struct plane planes[2]; /* lock for pinning (pin_count and planes.paddr) */ struct mutex lock; @@ -128,13 +122,13 @@ static const struct drm_framebuffer_funcs omap_framebuffer_funcs = { }; static uint32_t get_linear_addr(struct plane *plane, - const struct format *format, int n, int x, int y) + const struct drm_format_info *format, int n, int x, int y) { uint32_t offset; - offset = plane->offset + - (x * format->planes[n].stride_bpp) + - (y * plane->pitch / format->planes[n].sub_y); + offset = plane->offset + + (x * format->cpp[n] / (n == 0 ? 1 : format->hsub)) + + (y * plane->pitch / (n == 0 ? 1 : format->vsub)); return plane->paddr + offset; } @@ -153,11 +147,11 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, struct omap_drm_window *win, struct omap_overlay_info *info) { struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); - const struct format *format = omap_fb->format; + const struct drm_format_info *format = omap_fb->format; struct plane *plane = &omap_fb->planes[0]; uint32_t x, y, orient = 0; - info->color_mode = format->dss_format; + info->color_mode = omap_fb->dss_format; info->pos_x = win->crtc_x; info->pos_y = win->crtc_y; @@ -231,9 +225,9 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, } /* convert to pixels: */ - info->screen_width /= format->planes[0].stride_bpp; + info->screen_width /= format->cpp[0]; - if (format->dss_format == OMAP_DSS_COLOR_NV12) { + if (omap_fb->dss_format == OMAP_DSS_COLOR_NV12) { plane = &omap_fb->planes[1]; if (info->rotation_type == OMAP_DSS_ROT_TILER) { @@ -382,23 +376,26 @@ struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev, struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos) { + const struct drm_format_info *format = NULL; struct omap_framebuffer *omap_fb = NULL; struct drm_framebuffer *fb = NULL; - const struct format *format = NULL; - int ret, i, n = drm_format_num_planes(mode_cmd->pixel_format); + enum omap_color_mode dss_format = 0; + int ret, i; DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)", dev, mode_cmd, mode_cmd->width, mode_cmd->height, (char *)&mode_cmd->pixel_format); + format = drm_format_info(mode_cmd->pixel_format); + for (i = 0; i < ARRAY_SIZE(formats); i++) { if (formats[i].pixel_format == mode_cmd->pixel_format) { - format = &formats[i]; + dss_format = formats[i].dss_format; break; } } - if (!format) { + if (!format || !dss_format) { dev_err(dev->dev, "unsupported pixel format: %4.4s\n", (char *)&mode_cmd->pixel_format); ret = -EINVAL; @@ -413,28 +410,32 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, fb = &omap_fb->base; omap_fb->format = format; + omap_fb->dss_format = dss_format; mutex_init(&omap_fb->lock); - for (i = 0; i < n; i++) { + for (i = 0; i < format->num_planes; i++) { struct plane *plane = &omap_fb->planes[i]; - int size, pitch = mode_cmd->pitches[i]; + unsigned int pitch = mode_cmd->pitches[i]; + unsigned int hsub = i == 0 ? 1 : format->hsub; + unsigned int vsub = i == 0 ? 1 : format->vsub; + unsigned int size; - if (pitch < (mode_cmd->width * format->planes[i].stride_bpp)) { + if (pitch < mode_cmd->width * format->cpp[i] / hsub) { dev_err(dev->dev, "provided buffer pitch is too small! %d < %d\n", - pitch, mode_cmd->width * format->planes[i].stride_bpp); + pitch, mode_cmd->width * format->cpp[i] / hsub); ret = -EINVAL; goto fail; } - if (pitch % format->planes[i].stride_bpp != 0) { + if (pitch % format->cpp[i] != 0) { dev_err(dev->dev, "buffer pitch (%d bytes) is not a multiple of pixel size (%d bytes)\n", - pitch, format->planes[i].stride_bpp); + pitch, format->cpp[i]); ret = -EINVAL; goto fail; } - size = pitch * mode_cmd->height / format->planes[i].sub_y; + size = pitch * mode_cmd->height / vsub; if (size > (omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i])) { dev_err(dev->dev, "provided buffer object is too small! %d < %d\n", -- cgit v1.2.3 From a39c94e8138f4708b92245a7021ad4d40376360f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 26 Mar 2016 19:51:57 +0200 Subject: drm: omapdrm: fb: Simplify objects lookup when creating framebuffer Merge the single-user objects_lookup inline function into its caller, allowing reuse of the error code path. Signed-off-by: Laurent Pinchart Reviewed-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_drv.h | 25 ------------------------- drivers/gpu/drm/omapdrm/omap_fb.c | 29 ++++++++++++++++++----------- 2 files changed, 18 insertions(+), 36 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_fb.c') diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 7d9dd5400cef..919c14d3503c 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -236,29 +236,4 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev, uint32_t pipe2vbl(struct drm_crtc *crtc); struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder); -/* should these be made into common util helpers? - */ - -static inline int objects_lookup( - struct drm_file *filp, uint32_t pixel_format, - struct drm_gem_object **bos, const uint32_t *handles) -{ - int i, n = drm_format_num_planes(pixel_format); - - for (i = 0; i < n; i++) { - bos[i] = drm_gem_object_lookup(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/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 6315d68989fc..195ab4c86244 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -354,22 +354,29 @@ void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m) struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev, struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd) { + unsigned int num_planes = drm_format_num_planes(mode_cmd->pixel_format); struct drm_gem_object *bos[4]; struct drm_framebuffer *fb; - int ret; + int i; - ret = objects_lookup(file, mode_cmd->pixel_format, - bos, mode_cmd->handles); - if (ret) - return ERR_PTR(ret); + for (i = 0; i < num_planes; i++) { + bos[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]); + if (!bos[i]) { + fb = ERR_PTR(-ENOENT); + goto error; + } + } fb = omap_framebuffer_init(dev, mode_cmd, bos); - if (IS_ERR(fb)) { - int i, n = drm_format_num_planes(mode_cmd->pixel_format); - for (i = 0; i < n; i++) - drm_gem_object_unreference_unlocked(bos[i]); - return fb; - } + if (IS_ERR(fb)) + goto error; + + return fb; + +error: + while (--i > 0) + drm_gem_object_unreference_unlocked(bos[i]); + return fb; } -- cgit v1.2.3 From 6941e3d12b3284ea5b8d32b7023221700cad5f49 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 26 Mar 2016 20:01:13 +0200 Subject: drm: omapdrm: fb: Simplify mode command checks when creating framebuffer The hardware requires all planes to have an identical pitch in number of pixels. Given that all supported formats use the same number of bytes per pixel in all planes, framebuffer creation checks can be simplified. The implementations assumes that no format use more than two planes which is true with the existing hardware. Signed-off-by: Laurent Pinchart Reviewed-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_fb.c | 50 ++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 27 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_fb.c') diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 195ab4c86244..016aac9a7731 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -387,6 +387,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, struct omap_framebuffer *omap_fb = NULL; struct drm_framebuffer *fb = NULL; enum omap_color_mode dss_format = 0; + unsigned int pitch = mode_cmd->pitches[0]; int ret, i; DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)", @@ -420,41 +421,36 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, omap_fb->dss_format = dss_format; mutex_init(&omap_fb->lock); + /* + * The code below assumes that no format use more than two planes, and + * that the two planes of multiplane formats need the same number of + * bytes per pixel. + */ + if (format->num_planes == 2 && pitch != mode_cmd->pitches[1]) { + dev_err(dev->dev, "pitches differ between planes 0 and 1\n"); + ret = -EINVAL; + goto fail; + } + + if (pitch % format->cpp[0]) { + dev_err(dev->dev, + "buffer pitch (%u bytes) is not a multiple of pixel size (%u bytes)\n", + pitch, format->cpp[0]); + ret = -EINVAL; + goto fail; + } + for (i = 0; i < format->num_planes; i++) { struct plane *plane = &omap_fb->planes[i]; - unsigned int pitch = mode_cmd->pitches[i]; - unsigned int hsub = i == 0 ? 1 : format->hsub; unsigned int vsub = i == 0 ? 1 : format->vsub; unsigned int size; - if (pitch < mode_cmd->width * format->cpp[i] / hsub) { - dev_err(dev->dev, "provided buffer pitch is too small! %d < %d\n", - pitch, mode_cmd->width * format->cpp[i] / hsub); - ret = -EINVAL; - goto fail; - } - - if (pitch % format->cpp[i] != 0) { - dev_err(dev->dev, - "buffer pitch (%d bytes) is not a multiple of pixel size (%d bytes)\n", - pitch, format->cpp[i]); - ret = -EINVAL; - goto fail; - } - size = pitch * mode_cmd->height / vsub; - if (size > (omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i])) { - dev_err(dev->dev, "provided buffer object is too small! %d < %d\n", - bos[i]->size - mode_cmd->offsets[i], size); - ret = -EINVAL; - goto fail; - } - - if (i > 0 && pitch != mode_cmd->pitches[i - 1]) { + if (size > omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i]) { dev_err(dev->dev, - "pitches are not the same between framebuffer planes %d != %d\n", - pitch, mode_cmd->pitches[i - 1]); + "provided buffer object is too small! %d < %d\n", + bos[i]->size - mode_cmd->offsets[i], size); ret = -EINVAL; goto fail; } -- cgit v1.2.3 From a078a3ddc7209474e8dd827743390e9ed4bc6881 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 26 Mar 2016 20:02:49 +0200 Subject: drm: omapdrm: fb: Turn framebuffer creation error messages into debug Don't print userspace parameters validation failures as error messages to avoid giving userspace the ability to flood the kernel log. Signed-off-by: Laurent Pinchart Reviewed-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_fb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_fb.c') diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 016aac9a7731..a30f2060c1d6 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -404,8 +404,8 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, } if (!format || !dss_format) { - dev_err(dev->dev, "unsupported pixel format: %4.4s\n", - (char *)&mode_cmd->pixel_format); + dev_dbg(dev->dev, "unsupported pixel format: %4.4s\n", + (char *)&mode_cmd->pixel_format); ret = -EINVAL; goto fail; } @@ -427,13 +427,13 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, * bytes per pixel. */ if (format->num_planes == 2 && pitch != mode_cmd->pitches[1]) { - dev_err(dev->dev, "pitches differ between planes 0 and 1\n"); + dev_dbg(dev->dev, "pitches differ between planes 0 and 1\n"); ret = -EINVAL; goto fail; } if (pitch % format->cpp[0]) { - dev_err(dev->dev, + dev_dbg(dev->dev, "buffer pitch (%u bytes) is not a multiple of pixel size (%u bytes)\n", pitch, format->cpp[0]); ret = -EINVAL; @@ -448,7 +448,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, size = pitch * mode_cmd->height / vsub; if (size > omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i]) { - dev_err(dev->dev, + dev_dbg(dev->dev, "provided buffer object is too small! %d < %d\n", bos[i]->size - mode_cmd->offsets[i], size); ret = -EINVAL; -- cgit v1.2.3