The patch number 9927 was added via Mauro Carvalho Chehab <[email protected]>
to http://linuxtv.org/hg/v4l-dvb master development tree.

Kernel patches in this development tree may be modified to be backward
compatible with older kernels. Compatibility modifications will be
removed before inclusion into the mainstream Kernel

If anyone has any objections, please let us know by sending a message to:
        [email protected]

------

From: Mauro Carvalho Chehab  <[email protected]>
em28xx: use a more standard way to specify video formats


This patch uses the same code for enumberating video formats that are
present on cx88, bttv and saa7134 drivers.

Priority: normal

Signed-off-by: Mauro Carvalho Chehab <[email protected]>


---

 linux/drivers/media/video/em28xx/em28xx-core.c  |   19 +++-
 linux/drivers/media/video/em28xx/em28xx-video.c |   72 +++++++++++-----
 linux/drivers/media/video/em28xx/em28xx.h       |    7 +
 3 files changed, 73 insertions(+), 25 deletions(-)

diff -r 7cbc9624e807 -r 6c9eda8f28e2 
linux/drivers/media/video/em28xx/em28xx-core.c
--- a/linux/drivers/media/video/em28xx/em28xx-core.c    Sat Dec 20 08:43:34 
2008 -0200
+++ b/linux/drivers/media/video/em28xx/em28xx-core.c    Sat Dec 20 10:06:37 
2008 -0200
@@ -621,10 +621,19 @@ int em28xx_capture_start(struct em28xx *
        return rc;
 }
 
-int em28xx_outfmt_set_yuv422(struct em28xx *dev)
-{
-       em28xx_write_reg(dev, EM28XX_R27_OUTFMT, 0x34);
-       em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10);
+int em28xx_set_outfmt(struct em28xx *dev)
+{
+       int ret;
+
+       ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT,
+                                   dev->format->reg | 0x20, 0x3f);
+       if (ret < 0)
+               return ret;
+
+       ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10);
+       if (ret < 0)
+               return ret;
+
        return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x11);
 }
 
@@ -686,7 +695,7 @@ int em28xx_resolution_set(struct em28xx 
        width = norm_maxw(dev);
        height = norm_maxh(dev) >> 1;
 
-       em28xx_outfmt_set_yuv422(dev);
+       em28xx_set_outfmt(dev);
        em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
        em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2);
        return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
diff -r 7cbc9624e807 -r 6c9eda8f28e2 
linux/drivers/media/video/em28xx/em28xx-video.c
--- a/linux/drivers/media/video/em28xx/em28xx-video.c   Sat Dec 20 08:43:34 
2008 -0200
+++ b/linux/drivers/media/video/em28xx/em28xx-video.c   Sat Dec 20 10:06:37 
2008 -0200
@@ -95,6 +95,16 @@ MODULE_PARM_DESC(video_debug, "enable de
 
 /* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
 static unsigned long em28xx_devused;
+
+/* supported video standards */
+static struct em28xx_fmt format[] = {
+       {
+               .name     = "16bpp YUY2, 4:2:2, packed",
+               .fourcc   = V4L2_PIX_FMT_YUYV,
+               .depth    = 16,
+               .reg      = 0x14,
+       },
+};
 
 /* supported controls */
 /* Common to all boards */
@@ -390,7 +400,8 @@ buffer_setup(struct videobuf_queue *vq, 
        struct em28xx        *dev = fh->dev;
        struct v4l2_frequency f;
 
-       *size = 16 * fh->dev->width * fh->dev->height >> 3;
+       *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 
3;
+
        if (0 == *count)
                *count = EM28XX_DEF_BUF;
 
@@ -443,9 +454,7 @@ buffer_prepare(struct videobuf_queue *vq
        struct em28xx        *dev = fh->dev;
        int                  rc = 0, urb_init = 0;
 
-       /* FIXME: It assumes depth = 16 */
-       /* The only currently supported format is 16 bits/pixel */
-       buf->vb.size = 16 * dev->width * dev->height >> 3;
+       buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth + 
7) >> 3;
 
        if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
                return -EINVAL;
@@ -542,7 +551,7 @@ static int em28xx_config(struct em28xx *
        dev->mute = 1;          /* maybe not the right place... */
        dev->volume = 0x1f;
 
-       em28xx_outfmt_set_yuv422(dev);
+       em28xx_set_outfmt(dev);
        em28xx_colorlevels_set_default(dev);
        em28xx_compression_disable(dev);
 
@@ -710,8 +719,8 @@ static int vidioc_g_fmt_vid_cap(struct f
 
        f->fmt.pix.width = dev->width;
        f->fmt.pix.height = dev->height;
-       f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
-       f->fmt.pix.bytesperline = dev->width * 2;
+       f->fmt.pix.pixelformat = dev->format->fourcc;
+       f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;
        f->fmt.pix.sizeimage = f->fmt.pix.bytesperline  * dev->height;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 
@@ -721,6 +730,17 @@ static int vidioc_g_fmt_vid_cap(struct f
 
        mutex_unlock(&dev->lock);
        return 0;
+}
+
+static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(format); i++)
+               if (format[i].fourcc == fourcc)
+                       return &format[i];
+
+       return NULL;
 }
 
 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
@@ -733,6 +753,14 @@ static int vidioc_try_fmt_vid_cap(struct
        unsigned int          maxw   = norm_maxw(dev);
        unsigned int          maxh   = norm_maxh(dev);
        unsigned int          hscale, vscale;
+       struct em28xx_fmt     *fmt;
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       if (!fmt) {
+               em28xx_videodbg("Fourcc format (%08x) invalid.\n",
+                               f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
 
        /* width must even because of the YUYV format
           height must be even because of interlacing */
@@ -771,9 +799,9 @@ static int vidioc_try_fmt_vid_cap(struct
 
        f->fmt.pix.width = width;
        f->fmt.pix.height = height;
-       f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
-       f->fmt.pix.bytesperline = width * 2;
-       f->fmt.pix.sizeimage = width * 2 * height;
+       f->fmt.pix.pixelformat = fmt->fourcc;
+       f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3;
+       f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
        f->fmt.pix.field = V4L2_FIELD_INTERLACED;
 
@@ -786,6 +814,7 @@ static int vidioc_s_fmt_vid_cap(struct f
        struct em28xx_fh      *fh  = priv;
        struct em28xx         *dev = fh->dev;
        int                   rc;
+       struct em28xx_fmt     *fmt;
 
        rc = check_dev(dev);
        if (rc < 0)
@@ -794,6 +823,10 @@ static int vidioc_s_fmt_vid_cap(struct f
        mutex_lock(&dev->lock);
 
        vidioc_try_fmt_vid_cap(file, priv, f);
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       if (!fmt)
+               return -EINVAL;
 
        if (videobuf_queue_is_busy(&fh->vb_vidq)) {
                em28xx_errdev("%s queue busy\n", __func__);
@@ -810,6 +843,7 @@ static int vidioc_s_fmt_vid_cap(struct f
        /* set new image size */
        dev->width = f->fmt.pix.width;
        dev->height = f->fmt.pix.height;
+       dev->format = fmt;
        get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
 
        em28xx_set_alternate(dev);
@@ -1347,15 +1381,13 @@ static int vidioc_querycap(struct file *
 }
 
 static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *fmtd)
-{
-       if (fmtd->index != 0)
-               return -EINVAL;
-
-       fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       strcpy(fmtd->description, "Packed YUY2");
-       fmtd->pixelformat = V4L2_PIX_FMT_YUYV;
-       memset(fmtd->reserved, 0, sizeof(fmtd->reserved));
+                                       struct v4l2_fmtdesc *f)
+{
+       if (unlikely(f->index >= ARRAY_SIZE(format)))
+               return -EINVAL;
+
+       strlcpy(f->description, format[f->index].name, sizeof(f->description));
+       f->pixelformat = format[f->index].fourcc;
 
        return 0;
 }
@@ -2144,6 +2176,7 @@ static int em28xx_init_dev(struct em28xx
        dev->em28xx_write_regs_req = em28xx_write_regs_req;
        dev->em28xx_read_reg_req = em28xx_read_reg_req;
        dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800;
+       dev->format = &format[0];
 
        em28xx_pre_card_setup(dev);
 
@@ -2565,3 +2598,4 @@ static void __exit em28xx_module_exit(vo
 
 module_init(em28xx_module_init);
 module_exit(em28xx_module_exit);
+
diff -r 7cbc9624e807 -r 6c9eda8f28e2 linux/drivers/media/video/em28xx/em28xx.h
--- a/linux/drivers/media/video/em28xx/em28xx.h Sat Dec 20 08:43:34 2008 -0200
+++ b/linux/drivers/media/video/em28xx/em28xx.h Sat Dec 20 10:06:37 2008 -0200
@@ -210,9 +210,12 @@ struct em28xx_usb_isoc_ctl {
 
 };
 
+/* Struct to enumberate video formats */
 struct em28xx_fmt {
        char  *name;
        u32   fourcc;          /* v4l2 format id */
+       int   depth;
+       int   reg;
 };
 
 /* buffer for one video frame */
@@ -438,6 +441,8 @@ struct em28xx {
        unsigned int stream_on:1;       /* Locks streams */
        unsigned int has_audio_class:1;
        unsigned int has_alsa_audio:1;
+
+       struct em28xx_fmt *format;
 
        struct em28xx_IR *ir;
 
@@ -577,7 +582,7 @@ int em28xx_audio_setup(struct em28xx *de
 
 int em28xx_colorlevels_set_default(struct em28xx *dev);
 int em28xx_capture_start(struct em28xx *dev, int start);
-int em28xx_outfmt_set_yuv422(struct em28xx *dev);
+int em28xx_set_outfmt(struct em28xx *dev);
 int em28xx_resolution_set(struct em28xx *dev);
 int em28xx_set_alternate(struct em28xx *dev);
 int em28xx_init_isoc(struct em28xx *dev, int max_packets,


---

Patch is available at: 
http://linuxtv.org/hg/v4l-dvb/rev/6c9eda8f28e298b3e7b0345d823843b601eccbf7

_______________________________________________
linuxtv-commits mailing list
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to