diff options
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-video.c')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 84 |
1 files changed, 55 insertions, 29 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 8fe1beecfffa..ff37b4c15f44 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -90,10 +90,35 @@ MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); | |||
90 | /* supported video standards */ | 90 | /* supported video standards */ |
91 | static struct em28xx_fmt format[] = { | 91 | static struct em28xx_fmt format[] = { |
92 | { | 92 | { |
93 | .name = "16bpp YUY2, 4:2:2, packed", | 93 | .name = "16 bpp YUY2, 4:2:2, packed", |
94 | .fourcc = V4L2_PIX_FMT_YUYV, | 94 | .fourcc = V4L2_PIX_FMT_YUYV, |
95 | .depth = 16, | 95 | .depth = 16, |
96 | .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, | 96 | .reg = EM28XX_OUTFMT_YUV422_Y0UY1V, |
97 | }, { | ||
98 | .name = "16 bpp RGB 565, LE", | ||
99 | .fourcc = V4L2_PIX_FMT_RGB565, | ||
100 | .depth = 16, | ||
101 | .reg = EM28XX_OUTFMT_RGB_16_656, | ||
102 | }, { | ||
103 | .name = "8 bpp Bayer BGBG..GRGR", | ||
104 | .fourcc = V4L2_PIX_FMT_SBGGR8, | ||
105 | .depth = 8, | ||
106 | .reg = EM28XX_OUTFMT_RGB_8_BGBG, | ||
107 | }, { | ||
108 | .name = "8 bpp Bayer GRGR..BGBG", | ||
109 | .fourcc = V4L2_PIX_FMT_SGRBG8, | ||
110 | .depth = 8, | ||
111 | .reg = EM28XX_OUTFMT_RGB_8_GRGR, | ||
112 | }, { | ||
113 | .name = "8 bpp Bayer GBGB..RGRG", | ||
114 | .fourcc = V4L2_PIX_FMT_SGBRG8, | ||
115 | .depth = 8, | ||
116 | .reg = EM28XX_OUTFMT_RGB_8_GBGB, | ||
117 | }, { | ||
118 | .name = "12 bpp YUV411", | ||
119 | .fourcc = V4L2_PIX_FMT_YUV411P, | ||
120 | .depth = 12, | ||
121 | .reg = EM28XX_OUTFMT_YUV411, | ||
97 | }, | 122 | }, |
98 | }; | 123 | }; |
99 | 124 | ||
@@ -632,8 +657,8 @@ static void get_scale(struct em28xx *dev, | |||
632 | unsigned int width, unsigned int height, | 657 | unsigned int width, unsigned int height, |
633 | unsigned int *hscale, unsigned int *vscale) | 658 | unsigned int *hscale, unsigned int *vscale) |
634 | { | 659 | { |
635 | unsigned int maxw = norm_maxw(dev); | 660 | unsigned int maxw = norm_maxw(dev); |
636 | unsigned int maxh = norm_maxh(dev); | 661 | unsigned int maxh = norm_maxh(dev); |
637 | 662 | ||
638 | *hscale = (((unsigned long)maxw) << 12) / width - 4096L; | 663 | *hscale = (((unsigned long)maxw) << 12) / width - 4096L; |
639 | if (*hscale >= 0x4000) | 664 | if (*hscale >= 0x4000) |
@@ -733,13 +758,34 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
733 | return 0; | 758 | return 0; |
734 | } | 759 | } |
735 | 760 | ||
761 | static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc, | ||
762 | unsigned width, unsigned height) | ||
763 | { | ||
764 | struct em28xx_fmt *fmt; | ||
765 | |||
766 | fmt = format_by_fourcc(fourcc); | ||
767 | if (!fmt) | ||
768 | return -EINVAL; | ||
769 | |||
770 | dev->format = fmt; | ||
771 | dev->width = width; | ||
772 | dev->height = height; | ||
773 | |||
774 | /* set new image size */ | ||
775 | get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); | ||
776 | |||
777 | em28xx_set_alternate(dev); | ||
778 | em28xx_resolution_set(dev); | ||
779 | |||
780 | return 0; | ||
781 | } | ||
782 | |||
736 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 783 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
737 | struct v4l2_format *f) | 784 | struct v4l2_format *f) |
738 | { | 785 | { |
739 | struct em28xx_fh *fh = priv; | 786 | struct em28xx_fh *fh = priv; |
740 | struct em28xx *dev = fh->dev; | 787 | struct em28xx *dev = fh->dev; |
741 | int rc; | 788 | int rc; |
742 | struct em28xx_fmt *fmt; | ||
743 | 789 | ||
744 | rc = check_dev(dev); | 790 | rc = check_dev(dev); |
745 | if (rc < 0) | 791 | if (rc < 0) |
@@ -749,12 +795,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
749 | 795 | ||
750 | vidioc_try_fmt_vid_cap(file, priv, f); | 796 | vidioc_try_fmt_vid_cap(file, priv, f); |
751 | 797 | ||
752 | fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
753 | if (!fmt) { | ||
754 | rc = -EINVAL; | ||
755 | goto out; | ||
756 | } | ||
757 | |||
758 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { | 798 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { |
759 | em28xx_errdev("%s queue busy\n", __func__); | 799 | em28xx_errdev("%s queue busy\n", __func__); |
760 | rc = -EBUSY; | 800 | rc = -EBUSY; |
@@ -767,16 +807,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
767 | goto out; | 807 | goto out; |
768 | } | 808 | } |
769 | 809 | ||
770 | /* set new image size */ | 810 | rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat, |
771 | dev->width = f->fmt.pix.width; | 811 | f->fmt.pix.width, f->fmt.pix.height); |
772 | dev->height = f->fmt.pix.height; | ||
773 | dev->format = fmt; | ||
774 | get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); | ||
775 | |||
776 | em28xx_set_alternate(dev); | ||
777 | em28xx_resolution_set(dev); | ||
778 | |||
779 | rc = 0; | ||
780 | 812 | ||
781 | out: | 813 | out: |
782 | mutex_unlock(&dev->lock); | 814 | mutex_unlock(&dev->lock); |
@@ -1616,11 +1648,6 @@ static int em28xx_v4l2_open(struct file *filp) | |||
1616 | filp->private_data = fh; | 1648 | filp->private_data = fh; |
1617 | 1649 | ||
1618 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { | 1650 | if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { |
1619 | dev->width = norm_maxw(dev); | ||
1620 | dev->height = norm_maxh(dev); | ||
1621 | dev->hscale = 0; | ||
1622 | dev->vscale = 0; | ||
1623 | |||
1624 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); | 1651 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); |
1625 | em28xx_set_alternate(dev); | 1652 | em28xx_set_alternate(dev); |
1626 | em28xx_resolution_set(dev); | 1653 | em28xx_resolution_set(dev); |
@@ -1962,15 +1989,14 @@ int em28xx_register_analog_devices(struct em28xx *dev) | |||
1962 | 1989 | ||
1963 | /* set default norm */ | 1990 | /* set default norm */ |
1964 | dev->norm = em28xx_video_template.current_norm; | 1991 | dev->norm = em28xx_video_template.current_norm; |
1965 | dev->width = norm_maxw(dev); | ||
1966 | dev->height = norm_maxh(dev); | ||
1967 | dev->interlaced = EM28XX_INTERLACED_DEFAULT; | 1992 | dev->interlaced = EM28XX_INTERLACED_DEFAULT; |
1968 | dev->hscale = 0; | ||
1969 | dev->vscale = 0; | ||
1970 | dev->ctl_input = 0; | 1993 | dev->ctl_input = 0; |
1971 | 1994 | ||
1972 | /* Analog specific initialization */ | 1995 | /* Analog specific initialization */ |
1973 | dev->format = &format[0]; | 1996 | dev->format = &format[0]; |
1997 | em28xx_set_video_format(dev, format[0].fourcc, | ||
1998 | norm_maxw(dev), norm_maxh(dev)); | ||
1999 | |||
1974 | video_mux(dev, dev->ctl_input); | 2000 | video_mux(dev, dev->ctl_input); |
1975 | 2001 | ||
1976 | /* Audio defaults */ | 2002 | /* Audio defaults */ |