diff options
Diffstat (limited to 'drivers/media/video/cx231xx/cx231xx-vbi.c')
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-vbi.c | 109 |
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; } |