summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil-cisco@xs4all.nl>2019-07-30 03:38:16 -0300
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2019-08-13 11:35:05 -0300
commit839b9d2c59b3b3e74cb58b457615ff61154d8a41 (patch)
tree3b6ac201a69ba720948e2693942ac514cc69e608
parentae27c563a6185d47a904c2d71b72580266cb9d86 (diff)
downloadlinux-0-day-839b9d2c59b3b3e74cb58b457615ff61154d8a41.tar.gz
linux-0-day-839b9d2c59b3b3e74cb58b457615ff61154d8a41.tar.xz
media: omap_vout: fix various v4l2-compliance failures
This patch fixes the following v4l2-compliance failures: - FIELD_ANY could be returned, which is not allowed. - JPEG colorspace was set instead of SRGB. - No control events. - Empty bus_info in QUERYCAP. - Overlay format handling wasn't zeroing bitmap/clips and didn't return the chromakey correctly. - G_FBUF didn't fill in many of the v4l2_framebuffer values. Now also return the base address of the corresponding framebuffer that this overlays. - Missing ENUM/G/S_OUTPUT ioctls. - ROTATE/VFLIP controls were added when the HW didn't support them. With these changes 'v4l2-compliance' passes all non-streaming tests. Tested on a Pandaboard and a Beagle XM board. Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
-rw-r--r--drivers/media/platform/omap/omap_vout.c170
-rw-r--r--drivers/media/platform/omap/omap_voutlib.c6
2 files changed, 134 insertions, 42 deletions
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
index b0f03c2ca65d9..97b9089baa41c 100644
--- a/drivers/media/platform/omap/omap_vout.c
+++ b/drivers/media/platform/omap/omap_vout.c
@@ -43,6 +43,7 @@
#include <media/videobuf-dma-contig.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
#include <video/omapvrfb.h>
#include <video/omapfb_dss.h>
@@ -159,13 +160,13 @@ static int omap_vout_try_format(struct v4l2_pix_format *pix)
ifmt = 0;
pix->pixelformat = omap_formats[ifmt].pixelformat;
- pix->field = V4L2_FIELD_ANY;
+ pix->field = V4L2_FIELD_NONE;
switch (pix->pixelformat) {
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_UYVY:
default:
- pix->colorspace = V4L2_COLORSPACE_JPEG;
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
bpp = YUYV_BPP;
break;
case V4L2_PIX_FMT_RGB565:
@@ -836,10 +837,16 @@ static void omap_vout_buffer_release(struct videobuf_queue *q,
static __poll_t omap_vout_poll(struct file *file,
struct poll_table_struct *wait)
{
+ __poll_t req_events = poll_requested_events(wait);
struct omap_vout_device *vout = video_drvdata(file);
struct videobuf_queue *q = &vout->vbq;
+ __poll_t res = 0;
- return videobuf_poll_stream(file, q, wait);
+ if (req_events & EPOLLPRI)
+ res = v4l2_ctrl_poll(file, wait);
+ if (req_events & (EPOLLOUT | EPOLLWRNORM))
+ res |= videobuf_poll_stream(file, q, wait);
+ return res;
}
static void omap_vout_vm_open(struct vm_area_struct *vma)
@@ -1039,7 +1046,8 @@ static int vidioc_querycap(struct file *file, void *fh,
strscpy(cap->driver, VOUT_NAME, sizeof(cap->driver));
strscpy(cap->card, vout->vfd->name, sizeof(cap->card));
- cap->bus_info[0] = '\0';
+ snprintf(cap->bus_info, sizeof(cap->bus_info),
+ "platform:%s.%d", VOUT_NAME, vout->vid);
return 0;
}
@@ -1176,12 +1184,8 @@ static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh,
ret = omap_vout_try_window(&vout->fbuf, win);
- if (!ret) {
- if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
- win->global_alpha = 255;
- else
- win->global_alpha = f->fmt.win.global_alpha;
- }
+ if (!ret && !(ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA))
+ win->global_alpha = 0;
return ret;
}
@@ -1201,13 +1205,35 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh,
ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win);
if (!ret) {
+ enum omap_dss_trans_key_type key_type =
+ OMAP_DSS_COLOR_KEY_GFX_DST;
+ int enable;
+
/* Video1 plane does not support global alpha on OMAP3 */
- if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
- vout->win.global_alpha = 255;
+ if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA)
+ vout->win.global_alpha = win->global_alpha;
+ else
+ win->global_alpha = 0;
+ if (vout->fbuf.flags & (V4L2_FBUF_FLAG_CHROMAKEY |
+ V4L2_FBUF_FLAG_SRC_CHROMAKEY))
+ enable = 1;
else
- vout->win.global_alpha = f->fmt.win.global_alpha;
+ enable = 0;
+ if (vout->fbuf.flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY)
+ key_type = OMAP_DSS_COLOR_KEY_VID_SRC;
+
+ if (ovl->manager && ovl->manager->get_manager_info &&
+ ovl->manager->set_manager_info) {
+ struct omap_overlay_manager_info info;
- vout->win.chromakey = f->fmt.win.chromakey;
+ ovl->manager->get_manager_info(ovl->manager, &info);
+ info.trans_enabled = enable;
+ info.trans_key_type = key_type;
+ info.trans_key = vout->win.chromakey;
+
+ if (ovl->manager->set_manager_info(ovl->manager, &info))
+ ret = -EINVAL;
+ }
}
mutex_unlock(&vout->lock);
return ret;
@@ -1216,11 +1242,9 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh,
static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh,
struct v4l2_format *f)
{
- u32 key_value = 0;
struct omap_overlay *ovl;
struct omapvideo_info *ovid;
struct omap_vout_device *vout = video_drvdata(file);
- struct omap_overlay_manager_info info;
struct v4l2_window *win = &f->fmt.win;
ovid = &vout->vid_info;
@@ -1228,13 +1252,14 @@ static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh,
win->w = vout->win.w;
win->field = vout->win.field;
- win->global_alpha = vout->win.global_alpha;
-
- if (ovl->manager && ovl->manager->get_manager_info) {
- ovl->manager->get_manager_info(ovl->manager, &info);
- key_value = info.trans_key;
- }
- win->chromakey = key_value;
+ win->chromakey = vout->win.chromakey;
+ if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA)
+ win->global_alpha = vout->win.global_alpha;
+ else
+ win->global_alpha = 0;
+ win->clips = NULL;
+ win->clipcount = 0;
+ win->bitmap = NULL;
return 0;
}
@@ -1733,15 +1758,34 @@ static int vidioc_g_fbuf(struct file *file, void *fh,
struct omapvideo_info *ovid;
struct omap_vout_device *vout = video_drvdata(file);
struct omap_overlay_manager_info info;
+ struct omap_video_timings *timing;
+ struct omap_dss_device *dssdev;
ovid = &vout->vid_info;
ovl = ovid->overlays[0];
+ /* get the display device attached to the overlay */
+ dssdev = ovl->get_device(ovl);
- /* The video overlay must stay within the framebuffer and can't be
- positioned independently. */
- a->flags = V4L2_FBUF_FLAG_OVERLAY;
- a->capability = V4L2_FBUF_CAP_LOCAL_ALPHA | V4L2_FBUF_CAP_CHROMAKEY
- | V4L2_FBUF_CAP_SRC_CHROMAKEY;
+ if (!dssdev)
+ return -EINVAL;
+
+ timing = &dssdev->panel.timings;
+
+ vout->fbuf.fmt.height = timing->y_res;
+ vout->fbuf.fmt.width = timing->x_res;
+ a->fmt.field = V4L2_FIELD_NONE;
+ a->fmt.colorspace = V4L2_COLORSPACE_SRGB;
+ a->fmt.pixelformat = V4L2_PIX_FMT_RGBA32;
+ a->fmt.height = vout->fbuf.fmt.height;
+ a->fmt.width = vout->fbuf.fmt.width;
+ a->fmt.bytesperline = vout->fbuf.fmt.width * 4;
+ a->fmt.sizeimage = a->fmt.height * a->fmt.bytesperline;
+ a->base = vout->fbuf.base;
+
+ a->flags = vout->fbuf.flags;
+ a->capability = vout->fbuf.capability;
+ a->flags &= ~(V4L2_FBUF_FLAG_SRC_CHROMAKEY | V4L2_FBUF_FLAG_CHROMAKEY |
+ V4L2_FBUF_FLAG_LOCAL_ALPHA);
if (ovl->manager && ovl->manager->get_manager_info) {
ovl->manager->get_manager_info(ovl->manager, &info);
@@ -1749,9 +1793,6 @@ static int vidioc_g_fbuf(struct file *file, void *fh,
a->flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY;
if (info.trans_key_type == OMAP_DSS_COLOR_KEY_GFX_DST)
a->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
- }
- if (ovl->manager && ovl->manager->get_manager_info) {
- ovl->manager->get_manager_info(ovl->manager, &info);
if (info.partial_alpha_enabled)
a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
}
@@ -1759,6 +1800,27 @@ static int vidioc_g_fbuf(struct file *file, void *fh,
return 0;
}
+static int vidioc_enum_output(struct file *file, void *priv_fh,
+ struct v4l2_output *out)
+{
+ if (out->index)
+ return -EINVAL;
+ snprintf(out->name, sizeof(out->name), "Overlay");
+ out->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY;
+ return 0;
+}
+
+static int vidioc_g_output(struct file *file, void *priv_fh, unsigned int *i)
+{
+ *i = 0;
+ return 0;
+}
+
+static int vidioc_s_output(struct file *file, void *priv_fh, unsigned int i)
+{
+ return i ? -EINVAL : 0;
+}
+
static const struct v4l2_ioctl_ops vout_ioctl_ops = {
.vidioc_querycap = vidioc_querycap,
.vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
@@ -1772,12 +1834,17 @@ static const struct v4l2_ioctl_ops vout_ioctl_ops = {
.vidioc_g_fmt_vid_out_overlay = vidioc_g_fmt_vid_overlay,
.vidioc_g_selection = vidioc_g_selection,
.vidioc_s_selection = vidioc_s_selection,
+ .vidioc_enum_output = vidioc_enum_output,
+ .vidioc_g_output = vidioc_g_output,
+ .vidioc_s_output = vidioc_s_output,
.vidioc_reqbufs = vidioc_reqbufs,
.vidioc_querybuf = vidioc_querybuf,
.vidioc_qbuf = vidioc_qbuf,
.vidioc_dqbuf = vidioc_dqbuf,
.vidioc_streamon = vidioc_streamon,
.vidioc_streamoff = vidioc_streamoff,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
static const struct v4l2_file_operations omap_vout_fops = {
@@ -1808,32 +1875,41 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
/* Default pixel format is RGB 5-6-5 */
pix->pixelformat = V4L2_PIX_FMT_RGB565;
- pix->field = V4L2_FIELD_ANY;
+ pix->field = V4L2_FIELD_NONE;
pix->bytesperline = pix->width * 2;
pix->sizeimage = pix->bytesperline * pix->height;
- pix->colorspace = V4L2_COLORSPACE_JPEG;
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
vout->bpp = RGB565_BPP;
vout->fbuf.fmt.width = display->panel.timings.x_res;
vout->fbuf.fmt.height = display->panel.timings.y_res;
/* Set the data structures for the overlay parameters*/
- vout->win.global_alpha = 255;
- vout->fbuf.flags = 0;
+ vout->fbuf.flags = V4L2_FBUF_FLAG_OVERLAY;
vout->fbuf.capability = V4L2_FBUF_CAP_LOCAL_ALPHA |
- V4L2_FBUF_CAP_SRC_CHROMAKEY | V4L2_FBUF_CAP_CHROMAKEY;
- vout->win.chromakey = 0;
+ V4L2_FBUF_CAP_SRC_CHROMAKEY | V4L2_FBUF_CAP_CHROMAKEY |
+ V4L2_FBUF_CAP_EXTERNOVERLAY;
+ if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) {
+ vout->win.global_alpha = 255;
+ vout->fbuf.capability |= V4L2_FBUF_CAP_GLOBAL_ALPHA;
+ vout->fbuf.flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
+ } else {
+ vout->win.global_alpha = 0;
+ }
+ vout->win.field = V4L2_FIELD_NONE;
omap_vout_new_format(pix, &vout->fbuf, &vout->crop, &vout->win);
hdl = &vout->ctrl_handler;
v4l2_ctrl_handler_init(hdl, 3);
- v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops,
- V4L2_CID_ROTATE, 0, 270, 90, 0);
+ if (vout->vid_info.rotation_type == VOUT_ROT_VRFB) {
+ v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops,
+ V4L2_CID_ROTATE, 0, 270, 90, 0);
+ v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops,
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
+ }
v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops,
V4L2_CID_BG_COLOR, 0, 0xffffff, 1, 0);
- v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops,
- V4L2_CID_VFLIP, 0, 1, 1, 0);
if (hdl->error)
return hdl->error;
@@ -1930,6 +2006,10 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
struct omap2video_device *vid_dev = container_of(v4l2_dev,
struct omap2video_device, v4l2_dev);
+ struct omap_overlay *ovl = vid_dev->overlays[0];
+ struct omap_overlay_info info;
+
+ ovl->get_overlay_info(ovl, &info);
for (k = 0; k < pdev->num_resources; k++) {
@@ -1950,6 +2030,14 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
vout->vid_info.overlays[0] = vid_dev->overlays[k + 1];
vout->vid_info.num_overlays = 1;
vout->vid_info.id = k + 1;
+ /*
+ * Set the framebuffer base, this allows applications to find
+ * the fb corresponding to this overlay.
+ *
+ * To be precise: fbuf.base should match smem_start of
+ * struct fb_fix_screeninfo.
+ */
+ vout->fbuf.base = (void *)info.paddr;
/* Set VRFB as rotation_type for omap2 and omap3 */
if (omap_vout_dss_omap24xx() || omap_vout_dss_omap34xx())
diff --git a/drivers/media/platform/omap/omap_voutlib.c b/drivers/media/platform/omap/omap_voutlib.c
index 58a25fdf0cce8..480a7e95533d9 100644
--- a/drivers/media/platform/omap/omap_voutlib.c
+++ b/drivers/media/platform/omap/omap_voutlib.c
@@ -95,7 +95,11 @@ int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
/* We now have a valid preview window, so go with it */
new_win->w = try_win;
- new_win->field = V4L2_FIELD_ANY;
+ new_win->field = V4L2_FIELD_NONE;
+ new_win->clips = NULL;
+ new_win->clipcount = 0;
+ new_win->bitmap = NULL;
+
return 0;
}
EXPORT_SYMBOL_GPL(omap_vout_try_window);