aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/em28xx/em28xx-video.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-07-02 16:34:04 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-07-05 13:30:07 -0400
commited5f1431ebeeba8cc6739e9cd905a7895b66184c (patch)
tree46abb23eee864b1f483322a2c0fd89ef9332b43f /drivers/media/video/em28xx/em28xx-video.c
parentf797608cc4f19b44b83ec39c87e14af6fa07826d (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>
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-video.c')
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c79
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
749static 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
749static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, 778static 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
798out: 808out:
799 mutex_unlock(&dev->lock); 809 mutex_unlock(&dev->lock);
@@ -1377,9 +1387,24 @@ static int vidioc_querycap(struct file *file, void *priv,
1377static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, 1387static 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 */