Skip to content

Commit

Permalink
[media] media: au0828 - convert to use videobuf2
Browse files Browse the repository at this point in the history
Convert au0828 to use videobuf2. Tested with NTSC.
Tested video and vbi devices with xawtv, tvtime,
and vlc. Ran v4l2-compliance to ensure there are
no failures.

Video compliance test results summary:
Total: 75, Succeeded: 75, Failed: 0, Warnings: 18

Vbi compliance test results summary:
Total: 75, Succeeded: 75, Failed: 0, Warnings: 0

Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
Reviewed-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
  • Loading branch information
Shuah Khan authored and mchehab committed Feb 2, 2015
1 parent 9bc1022 commit 05439b1
Show file tree
Hide file tree
Showing 4 changed files with 442 additions and 706 deletions.
2 changes: 1 addition & 1 deletion drivers/media/usb/au0828/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ config VIDEO_AU0828
depends on I2C && INPUT && DVB_CORE && USB
select I2C_ALGOBIT
select VIDEO_TVEEPROM
select VIDEOBUF_VMALLOC
select VIDEOBUF2_VMALLOC
select DVB_AU8522_DTV if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT
Expand Down
122 changes: 39 additions & 83 deletions drivers/media/usb/au0828/au0828-vbi.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,111 +28,67 @@
#include <linux/init.h>
#include <linux/slab.h>

static unsigned int vbibufs = 5;
module_param(vbibufs, int, 0644);
MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32");

/* ------------------------------------------------------------------ */

static void
free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)
static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
struct au0828_fh *fh = vq->priv_data;
struct au0828_dev *dev = fh->dev;
unsigned long flags = 0;
if (in_interrupt())
BUG();

/* We used to wait for the buffer to finish here, but this didn't work
because, as we were keeping the state as VIDEOBUF_QUEUED,
videobuf_queue_cancel marked it as finished for us.
(Also, it could wedge forever if the hardware was misconfigured.)
This should be safe; by the time we get here, the buffer isn't
queued anymore. If we ever start marking the buffers as
VIDEOBUF_ACTIVE, it won't be, though.
*/
spin_lock_irqsave(&dev->slock, flags);
if (dev->isoc_ctl.vbi_buf == buf)
dev->isoc_ctl.vbi_buf = NULL;
spin_unlock_irqrestore(&dev->slock, flags);
struct au0828_dev *dev = vb2_get_drv_priv(vq);
unsigned long img_size = dev->vbi_width * dev->vbi_height * 2;
unsigned long size;

videobuf_vmalloc_free(&buf->vb);
buf->vb.state = VIDEOBUF_NEEDS_INIT;
}

static int
vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
{
struct au0828_fh *fh = q->priv_data;
struct au0828_dev *dev = fh->dev;
size = fmt ? (fmt->fmt.vbi.samples_per_line *
(fmt->fmt.vbi.count[0] + fmt->fmt.vbi.count[1])) : img_size;
if (size < img_size)
return -EINVAL;

*size = dev->vbi_width * dev->vbi_height * 2;
*nplanes = 1;
sizes[0] = size;

if (0 == *count)
*count = vbibufs;
if (*count < 2)
*count = 2;
if (*count > 32)
*count = 32;
return 0;
}

static int
vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
enum v4l2_field field)
static int vbi_buffer_prepare(struct vb2_buffer *vb)
{
struct au0828_fh *fh = q->priv_data;
struct au0828_dev *dev = fh->dev;
struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
int rc = 0;
unsigned long size;

buf->vb.size = dev->vbi_width * dev->vbi_height * 2;
size = dev->vbi_width * dev->vbi_height * 2;

if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
if (vb2_plane_size(vb, 0) < size) {
pr_err("%s data will not fit into plane (%lu < %lu)\n",
__func__, vb2_plane_size(vb, 0), size);
return -EINVAL;

buf->vb.width = dev->vbi_width;
buf->vb.height = dev->vbi_height;
buf->vb.field = field;

if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
rc = videobuf_iolock(q, &buf->vb, NULL);
if (rc < 0)
goto fail;
}
vb2_set_plane_payload(&buf->vb, 0, size);

buf->vb.state = VIDEOBUF_PREPARED;
return 0;

fail:
free_buffer(q, buf);
return rc;
}

static void
vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
{
struct au0828_buffer *buf = container_of(vb,
struct au0828_buffer,
vb);
struct au0828_fh *fh = vq->priv_data;
struct au0828_dev *dev = fh->dev;
struct au0828_dmaqueue *vbiq = &dev->vbiq;

buf->vb.state = VIDEOBUF_QUEUED;
list_add_tail(&buf->vb.queue, &vbiq->active);
}

static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
vbi_buffer_queue(struct vb2_buffer *vb)
{
struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
free_buffer(q, buf);
struct au0828_dmaqueue *vbiq = &dev->vbiq;
unsigned long flags = 0;

buf->mem = vb2_plane_vaddr(vb, 0);
buf->length = vb2_plane_size(vb, 0);

spin_lock_irqsave(&dev->slock, flags);
list_add_tail(&buf->list, &vbiq->active);
spin_unlock_irqrestore(&dev->slock, flags);
}

struct videobuf_queue_ops au0828_vbi_qops = {
.buf_setup = vbi_setup,
.buf_prepare = vbi_prepare,
.buf_queue = vbi_queue,
.buf_release = vbi_release,
struct vb2_ops au0828_vbi_qops = {
.queue_setup = vbi_queue_setup,
.buf_prepare = vbi_buffer_prepare,
.buf_queue = vbi_buffer_queue,
.start_streaming = au0828_start_analog_streaming,
.stop_streaming = au0828_stop_vbi_streaming,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
};
Loading

0 comments on commit 05439b1

Please sign in to comment.