diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-07-02 16:34:04 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-07-05 13:30:07 -0400 |
commit | ed5f1431ebeeba8cc6739e9cd905a7895b66184c (patch) | |
tree | 46abb23eee864b1f483322a2c0fd89ef9332b43f | |
parent | f797608cc4f19b44b83ec39c87e14af6fa07826d (diff) |
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: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 79 |
1 files changed, 49 insertions, 30 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index b96a138d9d03..702fe8d6742e 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -746,13 +746,41 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
746 | return 0; | 746 | return 0; |
747 | } | 747 | } |
748 | 748 | ||
749 | static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc, | ||
750 | unsigned width, unsigned height) | ||
751 | { | ||
752 | struct em28xx_fmt *fmt; | ||
753 | |||
754 | /* FIXME: This is the only supported fmt */ | ||
755 | if (dev->board.is_27xx) { | ||
756 | fourcc = V4L2_PIX_FMT_RGB565; | ||
757 | width = 640; | ||
758 | height = 480; | ||
759 | } | ||
760 | |||
761 | fmt = format_by_fourcc(fourcc); | ||
762 | if (!fmt) | ||
763 | return -EINVAL; | ||
764 | |||
765 | dev->format = fmt; | ||
766 | dev->width = width; | ||
767 | dev->height = height; | ||
768 | |||
769 | /* set new image size */ | ||
770 | get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); | ||
771 | |||
772 | em28xx_set_alternate(dev); | ||
773 | em28xx_resolution_set(dev); | ||
774 | |||
775 | return 0; | ||
776 | } | ||
777 | |||
749 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 778 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
750 | struct v4l2_format *f) | 779 | struct v4l2_format *f) |
751 | { | 780 | { |
752 | struct em28xx_fh *fh = priv; | 781 | struct em28xx_fh *fh = priv; |
753 | struct em28xx *dev = fh->dev; | 782 | struct em28xx *dev = fh->dev; |
754 | int rc; | 783 | int rc; |
755 | struct em28xx_fmt *fmt; | ||
756 | 784 | ||
757 | rc = check_dev(dev); | 785 | rc = check_dev(dev); |
758 | if (rc < 0) | 786 | if (rc < 0) |
@@ -760,18 +788,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
760 | 788 | ||
761 | mutex_lock(&dev->lock); | 789 | mutex_lock(&dev->lock); |
762 | 790 | ||
763 | /* FIXME: This is the only supported fmt */ | ||
764 | if (dev->board.is_27xx) | ||
765 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565; | ||
766 | |||
767 | vidioc_try_fmt_vid_cap(file, priv, f); | 791 | vidioc_try_fmt_vid_cap(file, priv, f); |
768 | 792 | ||
769 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
770 | if (!fmt) { | ||
771 | rc = -EINVAL; | ||
772 | goto out; | ||
773 | } | ||
774 | |||
775 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { | 793 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { |
776 | em28xx_errdev("%s queue busy\n", __func__); | 794 | em28xx_errdev("%s queue busy\n", __func__); |
777 | rc = -EBUSY; | 795 | rc = -EBUSY; |
@@ -784,16 +802,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
784 | goto out; | 802 | goto out; |
785 | } | 803 | } |
786 | 804 | ||
787 | /* set new image size */ | 805 | rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat, |
788 | dev->width = f->fmt.pix.width; | 806 | f->fmt.pix.width, f->fmt.pix.height); |
789 | dev->height = f->fmt.pix.height; | ||
790 | dev->format = fmt; | ||
791 | get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); | ||
792 | |||
793 | em28xx_set_alternate(dev); | ||
794 | em28xx_resolution_set(dev); | ||
795 | |||
796 | rc = 0; | ||
797 | 807 | ||
798 | out: | 808 | out: |
799 | mutex_unlock(&dev->lock); | 809 | mutex_unlock(&dev->lock); |
@@ -1377,9 +1387,24 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
1377 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | 1387 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, |
1378 | struct v4l2_fmtdesc *f) | 1388 | struct v4l2_fmtdesc *f) |
1379 | { | 1389 | { |
1390 | struct em28xx_fh *fh = priv; | ||
1391 | struct em28xx *dev = fh->dev; | ||
1392 | |||
1380 | if (unlikely(f->index >= ARRAY_SIZE(format))) | 1393 | if (unlikely(f->index >= ARRAY_SIZE(format))) |
1381 | return -EINVAL; | 1394 | return -EINVAL; |
1382 | 1395 | ||
1396 | if (dev->board.is_27xx) { | ||
1397 | struct em28xx_fmt *fmt; | ||
1398 | if (f->index) | ||
1399 | return -EINVAL; | ||
1400 | |||
1401 | f->pixelformat = V4L2_PIX_FMT_RGB565; | ||
1402 | fmt = format_by_fourcc(f->pixelformat); | ||
1403 | strlcpy(f->description, fmt->name, sizeof(f->description)); | ||
1404 | |||
1405 | return 0; | ||
1406 | } | ||
1407 | |||
1383 | strlcpy(f->description, format[f->index].name, sizeof(f->description)); | 1408 | strlcpy(f->description, format[f->index].name, sizeof(f->description)); |
1384 | f->pixelformat = format[f->index].fourcc; | 1409 | f->pixelformat = format[f->index].fourcc; |
1385 | 1410 | ||
@@ -1633,11 +1658,6 @@ static int em28xx_v4l2_open(struct file *filp) | |||
1633 | filp->private_data = fh; | 1658 | filp->private_data = fh; |
1634 | 1659 | ||
1635 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { | 1660 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { |
1636 | dev->width = norm_maxw(dev); | ||
1637 | dev->height = norm_maxh(dev); | ||
1638 | dev->hscale = 0; | ||
1639 | dev->vscale = 0; | ||
1640 | |||
1641 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); | 1661 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); |
1642 | em28xx_set_alternate(dev); | 1662 | em28xx_set_alternate(dev); |
1643 | em28xx_resolution_set(dev); | 1663 | em28xx_resolution_set(dev); |
@@ -1979,15 +1999,14 @@ int em28xx_register_analog_devices(struct em28xx *dev) | |||
1979 | 1999 | ||
1980 | /* set default norm */ | 2000 | /* set default norm */ |
1981 | dev->norm = em28xx_video_template.current_norm; | 2001 | dev->norm = em28xx_video_template.current_norm; |
1982 | dev->width = norm_maxw(dev); | ||
1983 | dev->height = norm_maxh(dev); | ||
1984 | dev->interlaced = EM28XX_INTERLACED_DEFAULT; | 2002 | dev->interlaced = EM28XX_INTERLACED_DEFAULT; |
1985 | dev->hscale = 0; | ||
1986 | dev->vscale = 0; | ||
1987 | dev->ctl_input = 0; | 2003 | dev->ctl_input = 0; |
1988 | 2004 | ||
1989 | /* Analog specific initialization */ | 2005 | /* Analog specific initialization */ |
1990 | dev->format = &format[0]; | 2006 | dev->format = &format[0]; |
2007 | em28xx_set_video_format(dev, format[0].fourcc, | ||
2008 | norm_maxw(dev), norm_maxh(dev)); | ||
2009 | |||
1991 | video_mux(dev, dev->ctl_input); | 2010 | video_mux(dev, dev->ctl_input); |
1992 | 2011 | ||
1993 | /* Audio defaults */ | 2012 | /* Audio defaults */ |