Commit ed5f1431 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

V4L/DVB (12169): em28xx-video: fix VIDIOC_G_FMT and VIDIOC_ENUMFMT with webcams

Webcams have different constraints than other v4l devices. This patch
makes the format ioctls to behave better. It also fixes a bug at open()
handler, that were always reseting resolution to the maximum available
one.
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent f797608c
...@@ -746,13 +746,41 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, ...@@ -746,13 +746,41 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
return 0; return 0;
} }
static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
unsigned width, unsigned height)
{
struct em28xx_fmt *fmt;
/* FIXME: This is the only supported fmt */
if (dev->board.is_27xx) {
fourcc = V4L2_PIX_FMT_RGB565;
width = 640;
height = 480;
}
fmt = format_by_fourcc(fourcc);
if (!fmt)
return -EINVAL;
dev->format = fmt;
dev->width = width;
dev->height = height;
/* set new image size */
get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
em28xx_set_alternate(dev);
em28xx_resolution_set(dev);
return 0;
}
static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f) struct v4l2_format *f)
{ {
struct em28xx_fh *fh = priv; struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev; struct em28xx *dev = fh->dev;
int rc; int rc;
struct em28xx_fmt *fmt;
rc = check_dev(dev); rc = check_dev(dev);
if (rc < 0) if (rc < 0)
...@@ -760,18 +788,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, ...@@ -760,18 +788,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
mutex_lock(&dev->lock); mutex_lock(&dev->lock);
/* FIXME: This is the only supported fmt */
if (dev->board.is_27xx)
f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;
vidioc_try_fmt_vid_cap(file, priv, f); vidioc_try_fmt_vid_cap(file, priv, f);
fmt = format_by_fourcc(f->fmt.pix.pixelformat);
if (!fmt) {
rc = -EINVAL;
goto out;
}
if (videobuf_queue_is_busy(&fh->vb_vidq)) { if (videobuf_queue_is_busy(&fh->vb_vidq)) {
em28xx_errdev("%s queue busy\n", __func__); em28xx_errdev("%s queue busy\n", __func__);
rc = -EBUSY; rc = -EBUSY;
...@@ -784,16 +802,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, ...@@ -784,16 +802,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
goto out; goto out;
} }
/* set new image size */ rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
dev->width = f->fmt.pix.width; f->fmt.pix.width, f->fmt.pix.height);
dev->height = f->fmt.pix.height;
dev->format = fmt;
get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
em28xx_set_alternate(dev);
em28xx_resolution_set(dev);
rc = 0;
out: out:
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
...@@ -1377,9 +1387,24 @@ static int vidioc_querycap(struct file *file, void *priv, ...@@ -1377,9 +1387,24 @@ static int vidioc_querycap(struct file *file, void *priv,
static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f) struct v4l2_fmtdesc *f)
{ {
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
if (unlikely(f->index >= ARRAY_SIZE(format))) if (unlikely(f->index >= ARRAY_SIZE(format)))
return -EINVAL; return -EINVAL;
if (dev->board.is_27xx) {
struct em28xx_fmt *fmt;
if (f->index)
return -EINVAL;
f->pixelformat = V4L2_PIX_FMT_RGB565;
fmt = format_by_fourcc(f->pixelformat);
strlcpy(f->description, fmt->name, sizeof(f->description));
return 0;
}
strlcpy(f->description, format[f->index].name, sizeof(f->description)); strlcpy(f->description, format[f->index].name, sizeof(f->description));
f->pixelformat = format[f->index].fourcc; f->pixelformat = format[f->index].fourcc;
...@@ -1633,11 +1658,6 @@ static int em28xx_v4l2_open(struct file *filp) ...@@ -1633,11 +1658,6 @@ static int em28xx_v4l2_open(struct file *filp)
filp->private_data = fh; filp->private_data = fh;
if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
dev->width = norm_maxw(dev);
dev->height = norm_maxh(dev);
dev->hscale = 0;
dev->vscale = 0;
em28xx_set_mode(dev, EM28XX_ANALOG_MODE); em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
em28xx_set_alternate(dev); em28xx_set_alternate(dev);
em28xx_resolution_set(dev); em28xx_resolution_set(dev);
...@@ -1979,15 +1999,14 @@ int em28xx_register_analog_devices(struct em28xx *dev) ...@@ -1979,15 +1999,14 @@ int em28xx_register_analog_devices(struct em28xx *dev)
/* set default norm */ /* set default norm */
dev->norm = em28xx_video_template.current_norm; dev->norm = em28xx_video_template.current_norm;
dev->width = norm_maxw(dev);
dev->height = norm_maxh(dev);
dev->interlaced = EM28XX_INTERLACED_DEFAULT; dev->interlaced = EM28XX_INTERLACED_DEFAULT;
dev->hscale = 0;
dev->vscale = 0;
dev->ctl_input = 0; dev->ctl_input = 0;
/* Analog specific initialization */ /* Analog specific initialization */
dev->format = &format[0]; dev->format = &format[0];
em28xx_set_video_format(dev, format[0].fourcc,
norm_maxw(dev), norm_maxh(dev));
video_mux(dev, dev->ctl_input); video_mux(dev, dev->ctl_input);
/* Audio defaults */ /* Audio defaults */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment