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>
This commit is contained in:
parent
ae27c563a6
commit
839b9d2c59
|
@ -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) {
|
||||
/* Video1 plane does not support global alpha on OMAP3 */
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
|
||||
vout->win.global_alpha = 255;
|
||||
else
|
||||
vout->win.global_alpha = f->fmt.win.global_alpha;
|
||||
enum omap_dss_trans_key_type key_type =
|
||||
OMAP_DSS_COLOR_KEY_GFX_DST;
|
||||
int enable;
|
||||
|
||||
vout->win.chromakey = f->fmt.win.chromakey;
|
||||
/* Video1 plane does not support global alpha on OMAP3 */
|
||||
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
|
||||
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;
|
||||
|
||||
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())
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue