aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/vivi.c97
1 files changed, 67 insertions, 30 deletions
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 0d1ad7f63d09..523f78c48472 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -128,12 +128,31 @@ struct vivi_fmt {
128 int depth; 128 int depth;
129}; 129};
130 130
131static struct vivi_fmt format = { 131static struct vivi_fmt formats[] = {
132 .name = "4:2:2, packed, YUYV", 132 {
133 .fourcc = V4L2_PIX_FMT_YUYV, 133 .name = "4:2:2, packed, YUYV",
134 .depth = 16, 134 .fourcc = V4L2_PIX_FMT_YUYV,
135 .depth = 16,
136 },
135}; 137};
136 138
139static struct vivi_fmt *get_format(struct v4l2_format *f)
140{
141 struct vivi_fmt *fmt;
142 unsigned int k;
143
144 for (k = 0; k < ARRAY_SIZE(formats); k++) {
145 fmt = &formats[k];
146 if (fmt->fourcc == f->fmt.pix.pixelformat)
147 break;
148 }
149
150 if (k == ARRAY_SIZE(formats))
151 return NULL;
152
153 return &formats[k];
154}
155
137struct sg_to_addr { 156struct sg_to_addr {
138 int pos; 157 int pos;
139 struct scatterlist *sg; 158 struct scatterlist *sg;
@@ -248,16 +267,20 @@ static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos)
248 for (color = 0; color < 4; color++) { 267 for (color = 0; color < 4; color++) {
249 p = buf + color; 268 p = buf + color;
250 269
251 switch (color) { 270 switch (fh->fmt->fourcc) {
252 case 0: 271 case V4L2_PIX_FMT_YUYV:
253 case 2: 272 switch (color) {
254 *p = r_y; 273 case 0:
255 break; 274 case 2:
256 case 1: 275 *p = r_y;
257 *p = g_u; 276 break;
258 break; 277 case 1:
259 case 3: 278 *p = g_u;
260 *p = b_v; 279 break;
280 case 3:
281 *p = b_v;
282 break;
283 }
261 break; 284 break;
262 } 285 }
263 } 286 }
@@ -622,11 +645,15 @@ static int vidioc_querycap(struct file *file, void *priv,
622static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, 645static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
623 struct v4l2_fmtdesc *f) 646 struct v4l2_fmtdesc *f)
624{ 647{
625 if (f->index > 0) 648 struct vivi_fmt *fmt;
649
650 if (f->index >= ARRAY_SIZE(formats))
626 return -EINVAL; 651 return -EINVAL;
627 652
628 strlcpy(f->description, format.name, sizeof(f->description)); 653 fmt = &formats[f->index];
629 f->pixelformat = format.fourcc; 654
655 strlcpy(f->description, fmt->name, sizeof(f->description));
656 f->pixelformat = fmt->fourcc;
630 return 0; 657 return 0;
631} 658}
632 659
@@ -656,13 +683,12 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
656 enum v4l2_field field; 683 enum v4l2_field field;
657 unsigned int maxw, maxh; 684 unsigned int maxw, maxh;
658 685
659 if (format.fourcc != f->fmt.pix.pixelformat) { 686 fmt = get_format(f);
660 dprintk(dev, 1, "Fourcc format (0x%08x) invalid. " 687 if (!fmt) {
661 "Driver accepts only 0x%08x\n", 688 dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n",
662 f->fmt.pix.pixelformat, format.fourcc); 689 f->fmt.pix.pixelformat);
663 return -EINVAL; 690 return -EINVAL;
664 } 691 }
665 fmt = &format;
666 692
667 field = f->fmt.pix.field; 693 field = f->fmt.pix.field;
668 694
@@ -701,7 +727,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
701 struct vivi_fh *fh = priv; 727 struct vivi_fh *fh = priv;
702 struct videobuf_queue *q = &fh->vb_vidq; 728 struct videobuf_queue *q = &fh->vb_vidq;
703 unsigned char r, g, b; 729 unsigned char r, g, b;
704 int k; 730 int k, is_yuv;
705 731
706 int ret = vidioc_try_fmt_vid_cap(file, fh, f); 732 int ret = vidioc_try_fmt_vid_cap(file, fh, f);
707 if (ret < 0) 733 if (ret < 0)
@@ -715,7 +741,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
715 goto out; 741 goto out;
716 } 742 }
717 743
718 fh->fmt = &format; 744 fh->fmt = get_format(f);
719 fh->width = f->fmt.pix.width; 745 fh->width = f->fmt.pix.width;
720 fh->height = f->fmt.pix.height; 746 fh->height = f->fmt.pix.height;
721 fh->vb_vidq.field = f->fmt.pix.field; 747 fh->vb_vidq.field = f->fmt.pix.field;
@@ -726,10 +752,23 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
726 r = bars[k][0]; 752 r = bars[k][0];
727 g = bars[k][1]; 753 g = bars[k][1];
728 b = bars[k][2]; 754 b = bars[k][2];
755 is_yuv = 0;
729 756
730 fh->bars[k][0] = TO_Y(r, g, b); /* Luma */ 757 switch (fh->fmt->fourcc) {
731 fh->bars[k][1] = TO_U(r, g, b); /* Cb */ 758 case V4L2_PIX_FMT_YUYV:
732 fh->bars[k][2] = TO_V(r, g, b); /* Cr */ 759 is_yuv = 1;
760 break;
761 }
762
763 if (is_yuv) {
764 fh->bars[k][0] = TO_Y(r, g, b); /* Luma */
765 fh->bars[k][1] = TO_U(r, g, b); /* Cb */
766 fh->bars[k][2] = TO_V(r, g, b); /* Cr */
767 } else {
768 fh->bars[k][0] = r;
769 fh->bars[k][1] = g;
770 fh->bars[k][2] = b;
771 }
733 } 772 }
734 773
735 ret = 0; 774 ret = 0;
@@ -885,8 +924,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
885 File operations for the device 924 File operations for the device
886 ------------------------------------------------------------------*/ 925 ------------------------------------------------------------------*/
887 926
888#define line_buf_size(norm) (norm_maxw(norm)*(format.depth+7)/8)
889
890static int vivi_open(struct inode *inode, struct file *file) 927static int vivi_open(struct inode *inode, struct file *file)
891{ 928{
892 int minor = iminor(inode); 929 int minor = iminor(inode);
@@ -935,7 +972,7 @@ unlock:
935 fh->dev = dev; 972 fh->dev = dev;
936 973
937 fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 974 fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
938 fh->fmt = &format; 975 fh->fmt = &formats[0];
939 fh->width = 640; 976 fh->width = 640;
940 fh->height = 480; 977 fh->height = 480;
941 978