V4L/DVB (9236): Teach vivi about multiple pixel formats
authorMagnus Damm <damm@igel.co.jp>
Tue, 14 Oct 2008 15:47:09 +0000 (12:47 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 17 Oct 2008 20:24:57 +0000 (17:24 -0300)
This patch contains the ground work to add support for multiple
pixel formats to vivi.c

Signed-off-by: Magnus Damm <damm@igel.co.jp>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/vivi.c

index 0d1ad7f..523f78c 100644 (file)
@@ -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;