V4L/DVB (13932): em28xx: add PAL support for VBI
authorDevin Heitmueller <dheitmueller@kernellabs.com>
Wed, 25 Nov 2009 02:17:25 +0000 (23:17 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 26 Feb 2010 18:10:32 +0000 (15:10 -0300)
Make the VBI support work for PAL standards in addition to NTSC.

This work was sponsored by EyeMagnet Limited.

Thanks go out to Andy Walls for providing a CD containing test PAL/VBI captures
and to Steven Toth for providing a PVR-350 to do signal generation with.

Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/em28xx/em28xx-core.c
drivers/media/video/em28xx/em28xx-vbi.c
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/em28xx/em28xx.h

index b311d45..5a37ecc 100644 (file)
@@ -691,9 +691,15 @@ int em28xx_set_outfmt(struct em28xx *dev)
        if (em28xx_vbi_supported(dev) == 1) {
                vinctrl |= EM28XX_VINCTRL_VBI_RAW;
                em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
-               em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
-               em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, 0xb4);
-               em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, 0x0c);
+               em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, dev->vbi_width/4);
+               em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, dev->vbi_height);
+               if (dev->norm & V4L2_STD_525_60) {
+                       /* NTSC */
+                       em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
+               } else if (dev->norm & V4L2_STD_625_50) {
+                       /* PAL */
+                       em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
+               }
        }
 
        return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
@@ -760,6 +766,13 @@ int em28xx_resolution_set(struct em28xx *dev)
        width = norm_maxw(dev);
        height = norm_maxh(dev);
 
+       /* Properly setup VBI */
+       dev->vbi_width = 720;
+       if (dev->norm & V4L2_STD_525_60)
+               dev->vbi_height = 12;
+       else
+               dev->vbi_height = 18;
+
        if (!dev->progressive)
                height >>= norm_maxh(dev);
 
index 94943e5..c7dce39 100644 (file)
@@ -71,7 +71,11 @@ free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf)
 static int
 vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
 {
-       *size = 720 * 12 * 2;
+       struct em28xx_fh     *fh  = q->priv_data;
+       struct em28xx        *dev = fh->dev;
+
+       *size = dev->vbi_width * dev->vbi_height * 2;
+
        if (0 == *count)
                *count = vbibufs;
        if (*count < 2)
@@ -85,19 +89,18 @@ static int
 vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
            enum v4l2_field field)
 {
+       struct em28xx_fh     *fh  = q->priv_data;
+       struct em28xx        *dev = fh->dev;
        struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
        int                  rc = 0;
-       unsigned int size;
-
-       size = 720 * 12 * 2;
 
-       buf->vb.size = size;
+       buf->vb.size = dev->vbi_width * dev->vbi_height * 2;
 
        if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
                return -EINVAL;
 
-       buf->vb.width  = 720;
-       buf->vb.height = 12;
+       buf->vb.width  = dev->vbi_width;
+       buf->vb.height = dev->vbi_height;
        buf->vb.field  = field;
 
        if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
index 849b18c..ac2bd93 100644 (file)
@@ -282,7 +282,7 @@ static void em28xx_copy_vbi(struct em28xx *dev,
 {
        void *startwrite, *startread;
        int  offset;
-       int bytesperline = 720;
+       int bytesperline = dev->vbi_width;
 
        if (dev == NULL) {
                em28xx_isocdbg("dev is null\n");
@@ -323,8 +323,8 @@ static void em28xx_copy_vbi(struct em28xx *dev,
 
        /* Make sure the bottom field populates the second half of the frame */
        if (buf->top_field == 0) {
-               startwrite += bytesperline * 0x0c;
-               offset += bytesperline * 0x0c;
+               startwrite += bytesperline * dev->vbi_height;
+               offset += bytesperline * dev->vbi_height;
        }
 
        memcpy(startwrite, startread, len);
@@ -578,8 +578,7 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb)
                        dev->cur_field = p[2];
                }
 
-               /* FIXME: get rid of hard-coded value */
-               vbi_size = 720 * 0x0c;
+               vbi_size = dev->vbi_width * dev->vbi_height;
 
                if (dev->capture_type == 0) {
                        if (dev->vbi_read >= vbi_size) {
@@ -1850,18 +1849,27 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv,
 static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
                                struct v4l2_format *format)
 {
-       format->fmt.vbi.samples_per_line = 720;
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+
+       format->fmt.vbi.samples_per_line = dev->vbi_width;
        format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
        format->fmt.vbi.offset = 0;
        format->fmt.vbi.flags = 0;
+       format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
+       format->fmt.vbi.count[0] = dev->vbi_height;
+       format->fmt.vbi.count[1] = dev->vbi_height;
 
        /* Varies by video standard (NTSC, PAL, etc.) */
-       /* FIXME: hard-coded for NTSC support */
-       format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; /* FIXME: ??? */
-       format->fmt.vbi.count[0] = 12;
-       format->fmt.vbi.count[1] = 12;
-       format->fmt.vbi.start[0] = 10;
-       format->fmt.vbi.start[1] = 273;
+       if (dev->norm & V4L2_STD_525_60) {
+               /* NTSC */
+               format->fmt.vbi.start[0] = 10;
+               format->fmt.vbi.start[1] = 273;
+       } else if (dev->norm & V4L2_STD_625_50) {
+               /* PAL */
+               format->fmt.vbi.start[0] = 6;
+               format->fmt.vbi.start[1] = 318;
+       }
 
        return 0;
 }
@@ -1869,18 +1877,27 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
 static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv,
                                struct v4l2_format *format)
 {
-       format->fmt.vbi.samples_per_line = 720;
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+
+       format->fmt.vbi.samples_per_line = dev->vbi_width;
        format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
        format->fmt.vbi.offset = 0;
        format->fmt.vbi.flags = 0;
+       format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
+       format->fmt.vbi.count[0] = dev->vbi_height;
+       format->fmt.vbi.count[1] = dev->vbi_height;
 
        /* Varies by video standard (NTSC, PAL, etc.) */
-       /* FIXME: hard-coded for NTSC support */
-       format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; /* FIXME: ??? */
-       format->fmt.vbi.count[0] = 12;
-       format->fmt.vbi.count[1] = 12;
-       format->fmt.vbi.start[0] = 10;
-       format->fmt.vbi.start[1] = 273;
+       if (dev->norm & V4L2_STD_525_60) {
+               /* NTSC */
+               format->fmt.vbi.start[0] = 10;
+               format->fmt.vbi.start[1] = 273;
+       } else if (dev->norm & V4L2_STD_625_50) {
+               /* PAL */
+               format->fmt.vbi.start[0] = 6;
+               format->fmt.vbi.start[1] = 318;
+       }
 
        return 0;
 }
@@ -1922,7 +1939,8 @@ static int vidioc_querybuf(struct file *file, void *priv,
                   At a minimum, it causes a crash in zvbi since it does
                   a memcpy based on the source buffer length */
                int result = videobuf_querybuf(&fh->vb_vbiq, b);
-               b->length = 17280;
+               b->length = dev->vbi_width * dev->vbi_height * 2;
+
                return result;
        }
 }
index 80d9b4f..71e90dc 100644 (file)
@@ -552,7 +552,8 @@ struct em28xx {
        int capture_type;
        int vbi_read;
        unsigned char cur_field;
-
+       unsigned int vbi_width;
+       unsigned int vbi_height; /* lines per field */
 
        struct work_struct         request_module_wk;