diff options
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/vivi.c | 97 |
1 files changed, 67 insertions, 30 deletions
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 0d1ad7f63d0..523f78c4847 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -128,12 +128,31 @@ struct vivi_fmt { int depth; }; -static struct vivi_fmt format = { - .name = "4:2:2, packed, YUYV", - .fourcc = V4L2_PIX_FMT_YUYV, - .depth = 16, +static struct vivi_fmt formats[] = { + { + .name = "4:2:2, packed, YUYV", + .fourcc = V4L2_PIX_FMT_YUYV, + .depth = 16, + }, }; +static struct vivi_fmt *get_format(struct v4l2_format *f) +{ + struct vivi_fmt *fmt; + unsigned int k; + + for (k = 0; k < ARRAY_SIZE(formats); k++) { + fmt = &formats[k]; + if (fmt->fourcc == f->fmt.pix.pixelformat) + break; + } + + if (k == ARRAY_SIZE(formats)) + return NULL; + + return &formats[k]; +} + struct sg_to_addr { int pos; struct scatterlist *sg; @@ -248,16 +267,20 @@ static void gen_twopix(struct vivi_fh *fh, unsigned char *buf, int colorpos) for (color = 0; color < 4; color++) { p = buf + color; - switch (color) { - case 0: - case 2: - *p = r_y; - break; - case 1: - *p = g_u; - break; - case 3: - *p = b_v; + switch (fh->fmt->fourcc) { + case V4L2_PIX_FMT_YUYV: + switch (color) { + case 0: + case 2: + *p = r_y; + break; + case 1: + *p = g_u; + break; + case 3: + *p = b_v; + break; + } break; } } @@ -622,11 +645,15 @@ static int vidioc_querycap(struct file *file, void *priv, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - if (f->index > 0) + struct vivi_fmt *fmt; + + if (f->index >= ARRAY_SIZE(formats)) return -EINVAL; - strlcpy(f->description, format.name, sizeof(f->description)); - f->pixelformat = format.fourcc; + fmt = &formats[f->index]; + + strlcpy(f->description, fmt->name, sizeof(f->description)); + f->pixelformat = fmt->fourcc; return 0; } @@ -656,13 +683,12 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, enum v4l2_field field; unsigned int maxw, maxh; - if (format.fourcc != f->fmt.pix.pixelformat) { - dprintk(dev, 1, "Fourcc format (0x%08x) invalid. " - "Driver accepts only 0x%08x\n", - f->fmt.pix.pixelformat, format.fourcc); + fmt = get_format(f); + if (!fmt) { + dprintk(dev, 1, "Fourcc format (0x%08x) invalid.\n", + f->fmt.pix.pixelformat); return -EINVAL; } - fmt = &format; field = f->fmt.pix.field; @@ -701,7 +727,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct vivi_fh *fh = priv; struct videobuf_queue *q = &fh->vb_vidq; unsigned char r, g, b; - int k; + int k, is_yuv; int ret = vidioc_try_fmt_vid_cap(file, fh, f); if (ret < 0) @@ -715,7 +741,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, goto out; } - fh->fmt = &format; + fh->fmt = get_format(f); fh->width = f->fmt.pix.width; fh->height = f->fmt.pix.height; fh->vb_vidq.field = f->fmt.pix.field; @@ -726,10 +752,23 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, r = bars[k][0]; g = bars[k][1]; b = bars[k][2]; + is_yuv = 0; - fh->bars[k][0] = TO_Y(r, g, b); /* Luma */ - fh->bars[k][1] = TO_U(r, g, b); /* Cb */ - fh->bars[k][2] = TO_V(r, g, b); /* Cr */ + switch (fh->fmt->fourcc) { + case V4L2_PIX_FMT_YUYV: + is_yuv = 1; + break; + } + + if (is_yuv) { + fh->bars[k][0] = TO_Y(r, g, b); /* Luma */ + fh->bars[k][1] = TO_U(r, g, b); /* Cb */ + fh->bars[k][2] = TO_V(r, g, b); /* Cr */ + } else { + fh->bars[k][0] = r; + fh->bars[k][1] = g; + fh->bars[k][2] = b; + } } ret = 0; @@ -885,8 +924,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, File operations for the device ------------------------------------------------------------------*/ -#define line_buf_size(norm) (norm_maxw(norm)*(format.depth+7)/8) - static int vivi_open(struct inode *inode, struct file *file) { int minor = iminor(inode); @@ -935,7 +972,7 @@ unlock: fh->dev = dev; fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fh->fmt = &format; + fh->fmt = &formats[0]; fh->width = 640; fh->height = 480; |