V4L/DVB (13932): em28xx: add PAL support for VBI

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>
This commit is contained in:
Devin Heitmueller 2009-11-24 23:17:25 -03:00 committed by Mauro Carvalho Chehab
parent 6a2071006b
commit 66d9cbad53
4 changed files with 66 additions and 31 deletions

View 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);

View 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) {

View 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;
}
}

View 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;