summaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx231xx/cx231xx-vbi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx231xx/cx231xx-vbi.c')
-rw-r--r--drivers/media/video/cx231xx/cx231xx-vbi.c109
1 files changed, 61 insertions, 48 deletions
diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/video/cx231xx/cx231xx-vbi.c
index 689c5e25776..1d914488dbb 100644
--- a/drivers/media/video/cx231xx/cx231xx-vbi.c
+++ b/drivers/media/video/cx231xx/cx231xx-vbi.c
@@ -102,7 +102,7 @@ static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb)
return 0;
}
- buf = dev->vbi_mode.isoc_ctl.buf;
+ buf = dev->vbi_mode.bulk_ctl.buf;
/* get buffer pointer and length */
p_buffer = urb->transfer_buffer;
@@ -180,7 +180,7 @@ vbi_buffer_setup(struct videobuf_queue *vq, unsigned int *count,
height = ((dev->norm & V4L2_STD_625_50) ?
PAL_VBI_LINES : NTSC_VBI_LINES);
- *size = (dev->width * height * 2);
+ *size = (dev->width * height * 2 * 2);
if (0 == *count)
*count = CX231XX_DEF_VBI_BUF;
@@ -209,8 +209,8 @@ static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
VIDEOBUF_ACTIVE, it won't be, though.
*/
spin_lock_irqsave(&dev->vbi_mode.slock, flags);
- if (dev->vbi_mode.isoc_ctl.buf == buf)
- dev->vbi_mode.isoc_ctl.buf = NULL;
+ if (dev->vbi_mode.bulk_ctl.buf == buf)
+ dev->vbi_mode.bulk_ctl.buf = NULL;
spin_unlock_irqrestore(&dev->vbi_mode.slock, flags);
videobuf_vmalloc_free(&buf->vb);
@@ -230,7 +230,7 @@ vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
height = ((dev->norm & V4L2_STD_625_50) ?
PAL_VBI_LINES : NTSC_VBI_LINES);
- buf->vb.size = ((dev->width << 1) * height);
+ buf->vb.size = ((dev->width << 1) * height * 2);
if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
return -EINVAL;
@@ -246,7 +246,7 @@ vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
goto fail;
}
- if (!dev->vbi_mode.isoc_ctl.num_bufs)
+ if (!dev->vbi_mode.bulk_ctl.num_bufs)
urb_init = 1;
if (urb_init) {
@@ -328,7 +328,7 @@ static void cx231xx_irq_vbi_callback(struct urb *urb)
/* Copy data from URB */
spin_lock(&dev->vbi_mode.slock);
- rc = dev->vbi_mode.isoc_ctl.isoc_copy(dev, urb);
+ rc = dev->vbi_mode.bulk_ctl.bulk_copy(dev, urb);
spin_unlock(&dev->vbi_mode.slock);
/* Reset status */
@@ -351,34 +351,34 @@ void cx231xx_uninit_vbi_isoc(struct cx231xx *dev)
cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_uninit_vbi_isoc\n");
- dev->vbi_mode.isoc_ctl.nfields = -1;
- for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) {
- urb = dev->vbi_mode.isoc_ctl.urb[i];
+ dev->vbi_mode.bulk_ctl.nfields = -1;
+ for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
+ urb = dev->vbi_mode.bulk_ctl.urb[i];
if (urb) {
if (!irqs_disabled())
usb_kill_urb(urb);
else
usb_unlink_urb(urb);
- if (dev->vbi_mode.isoc_ctl.transfer_buffer[i]) {
+ if (dev->vbi_mode.bulk_ctl.transfer_buffer[i]) {
- kfree(dev->vbi_mode.isoc_ctl.
+ kfree(dev->vbi_mode.bulk_ctl.
transfer_buffer[i]);
- dev->vbi_mode.isoc_ctl.transfer_buffer[i] =
+ dev->vbi_mode.bulk_ctl.transfer_buffer[i] =
NULL;
}
usb_free_urb(urb);
- dev->vbi_mode.isoc_ctl.urb[i] = NULL;
+ dev->vbi_mode.bulk_ctl.urb[i] = NULL;
}
- dev->vbi_mode.isoc_ctl.transfer_buffer[i] = NULL;
+ dev->vbi_mode.bulk_ctl.transfer_buffer[i] = NULL;
}
- kfree(dev->vbi_mode.isoc_ctl.urb);
- kfree(dev->vbi_mode.isoc_ctl.transfer_buffer);
+ kfree(dev->vbi_mode.bulk_ctl.urb);
+ kfree(dev->vbi_mode.bulk_ctl.transfer_buffer);
- dev->vbi_mode.isoc_ctl.urb = NULL;
- dev->vbi_mode.isoc_ctl.transfer_buffer = NULL;
- dev->vbi_mode.isoc_ctl.num_bufs = 0;
+ dev->vbi_mode.bulk_ctl.urb = NULL;
+ dev->vbi_mode.bulk_ctl.transfer_buffer = NULL;
+ dev->vbi_mode.bulk_ctl.num_bufs = 0;
cx231xx_capture_start(dev, 0, Vbi);
}
@@ -389,7 +389,7 @@ EXPORT_SYMBOL_GPL(cx231xx_uninit_vbi_isoc);
*/
int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
int num_bufs, int max_pkt_size,
- int (*isoc_copy) (struct cx231xx *dev,
+ int (*bulk_copy) (struct cx231xx *dev,
struct urb *urb))
{
struct cx231xx_dmaqueue *dma_q = &dev->vbi_mode.vidq;
@@ -408,8 +408,8 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
usb_rcvbulkpipe(dev->udev,
dev->vbi_mode.end_point_addr));
- dev->vbi_mode.isoc_ctl.isoc_copy = isoc_copy;
- dev->vbi_mode.isoc_ctl.num_bufs = num_bufs;
+ dev->vbi_mode.bulk_ctl.bulk_copy = bulk_copy;
+ dev->vbi_mode.bulk_ctl.num_bufs = num_bufs;
dma_q->pos = 0;
dma_q->is_partial_line = 0;
dma_q->last_sav = 0;
@@ -421,42 +421,42 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
for (i = 0; i < 8; i++)
dma_q->partial_buf[i] = 0;
- dev->vbi_mode.isoc_ctl.urb = kzalloc(sizeof(void *) * num_bufs,
+ dev->vbi_mode.bulk_ctl.urb = kzalloc(sizeof(void *) * num_bufs,
GFP_KERNEL);
- if (!dev->vbi_mode.isoc_ctl.urb) {
+ if (!dev->vbi_mode.bulk_ctl.urb) {
cx231xx_errdev("cannot alloc memory for usb buffers\n");
return -ENOMEM;
}
- dev->vbi_mode.isoc_ctl.transfer_buffer =
+ dev->vbi_mode.bulk_ctl.transfer_buffer =
kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
- if (!dev->vbi_mode.isoc_ctl.transfer_buffer) {
+ if (!dev->vbi_mode.bulk_ctl.transfer_buffer) {
cx231xx_errdev("cannot allocate memory for usbtransfer\n");
- kfree(dev->vbi_mode.isoc_ctl.urb);
+ kfree(dev->vbi_mode.bulk_ctl.urb);
return -ENOMEM;
}
- dev->vbi_mode.isoc_ctl.max_pkt_size = max_pkt_size;
- dev->vbi_mode.isoc_ctl.buf = NULL;
+ dev->vbi_mode.bulk_ctl.max_pkt_size = max_pkt_size;
+ dev->vbi_mode.bulk_ctl.buf = NULL;
- sb_size = max_packets * dev->vbi_mode.isoc_ctl.max_pkt_size;
+ sb_size = max_packets * dev->vbi_mode.bulk_ctl.max_pkt_size;
/* allocate urbs and transfer buffers */
- for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) {
+ for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
cx231xx_err(DRIVER_NAME
- ": cannot alloc isoc_ctl.urb %i\n", i);
+ ": cannot alloc bulk_ctl.urb %i\n", i);
cx231xx_uninit_vbi_isoc(dev);
return -ENOMEM;
}
- dev->vbi_mode.isoc_ctl.urb[i] = urb;
+ dev->vbi_mode.bulk_ctl.urb[i] = urb;
urb->transfer_flags = 0;
- dev->vbi_mode.isoc_ctl.transfer_buffer[i] =
+ dev->vbi_mode.bulk_ctl.transfer_buffer[i] =
kzalloc(sb_size, GFP_KERNEL);
- if (!dev->vbi_mode.isoc_ctl.transfer_buffer[i]) {
+ if (!dev->vbi_mode.bulk_ctl.transfer_buffer[i]) {
cx231xx_err(DRIVER_NAME
": unable to allocate %i bytes for transfer"
" buffer %i%s\n", sb_size, i,
@@ -467,15 +467,15 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
pipe = usb_rcvbulkpipe(dev->udev, dev->vbi_mode.end_point_addr);
usb_fill_bulk_urb(urb, dev->udev, pipe,
- dev->vbi_mode.isoc_ctl.transfer_buffer[i],
+ dev->vbi_mode.bulk_ctl.transfer_buffer[i],
sb_size, cx231xx_irq_vbi_callback, dma_q);
}
init_waitqueue_head(&dma_q->wq);
/* submit urbs and enables IRQ */
- for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) {
- rc = usb_submit_urb(dev->vbi_mode.isoc_ctl.urb[i], GFP_ATOMIC);
+ for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
+ rc = usb_submit_urb(dev->vbi_mode.bulk_ctl.urb[i], GFP_ATOMIC);
if (rc) {
cx231xx_err(DRIVER_NAME
": submit of urb %i failed (error=%i)\n", i,
@@ -536,7 +536,7 @@ static inline void vbi_buffer_filled(struct cx231xx *dev,
buf->vb.field_count++;
do_gettimeofday(&buf->vb.ts);
- dev->vbi_mode.isoc_ctl.buf = NULL;
+ dev->vbi_mode.bulk_ctl.buf = NULL;
list_del(&buf->vb.queue);
wake_up(&buf->vb.done);
@@ -549,11 +549,16 @@ u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
struct cx231xx_buffer *buf;
u32 _line_size = dev->width * 2;
- if (dma_q->current_field != field_number)
+ if (dma_q->current_field == -1) {
+ /* Just starting up */
cx231xx_reset_vbi_buffer(dev, dma_q);
+ }
+
+ if (dma_q->current_field != field_number)
+ dma_q->lines_completed = 0;
/* get the buffer pointer */
- buf = dev->vbi_mode.isoc_ctl.buf;
+ buf = dev->vbi_mode.bulk_ctl.buf;
/* Remember the field number for next time */
dma_q->current_field = field_number;
@@ -597,8 +602,8 @@ u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
vbi_buffer_filled(dev, dma_q, buf);
dma_q->pos = 0;
- buf = NULL;
dma_q->lines_completed = 0;
+ cx231xx_reset_vbi_buffer(dev, dma_q);
}
}
@@ -618,7 +623,7 @@ static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q,
if (list_empty(&dma_q->active)) {
cx231xx_err(DRIVER_NAME ": No active queue to serve\n");
- dev->vbi_mode.isoc_ctl.buf = NULL;
+ dev->vbi_mode.bulk_ctl.buf = NULL;
*buf = NULL;
return;
}
@@ -630,7 +635,7 @@ static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q,
outp = videobuf_to_vmalloc(&(*buf)->vb);
memset(outp, 0, (*buf)->vb.size);
- dev->vbi_mode.isoc_ctl.buf = *buf;
+ dev->vbi_mode.bulk_ctl.buf = *buf;
return;
}
@@ -640,7 +645,7 @@ void cx231xx_reset_vbi_buffer(struct cx231xx *dev,
{
struct cx231xx_buffer *buf;
- buf = dev->vbi_mode.isoc_ctl.buf;
+ buf = dev->vbi_mode.bulk_ctl.buf;
if (buf == NULL) {
/* first try to get the buffer */
@@ -664,7 +669,7 @@ int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
void *startwrite;
int offset, lencopy;
- buf = dev->vbi_mode.isoc_ctl.buf;
+ buf = dev->vbi_mode.bulk_ctl.buf;
if (buf == NULL)
return -EINVAL;
@@ -679,6 +684,11 @@ int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
offset = (dma_q->lines_completed * _line_size) +
current_line_bytes_copied;
+ if (dma_q->current_field == 2) {
+ /* Populate the second half of the frame */
+ offset += (dev->width * 2 * dma_q->lines_per_field);
+ }
+
/* prepare destination address */
startwrite = p_out_buffer + offset;
@@ -697,5 +707,8 @@ u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev,
height = ((dev->norm & V4L2_STD_625_50) ?
PAL_VBI_LINES : NTSC_VBI_LINES);
- return (dma_q->lines_completed == height) ? 1 : 0;
+ if (dma_q->lines_completed == height && dma_q->current_field == 2)
+ return 1;
+ else
+ return 0;
}