Path: blob/master/drivers/media/video/au0828/au0828-vbi.c
17988 views
/*1au0828-vbi.c - VBI driver for au082823Copyright (C) 2010 Devin Heitmueller <[email protected]>45This work was sponsored by GetWellNetwork Inc.67This program is free software; you can redistribute it and/or modify8it under the terms of the GNU General Public License as published by9the Free Software Foundation; either version 2 of the License, or10(at your option) any later version.1112This program is distributed in the hope that it will be useful,13but WITHOUT ANY WARRANTY; without even the implied warranty of14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the15GNU General Public License for more details.1617You should have received a copy of the GNU General Public License18along with this program; if not, write to the Free Software19Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA2002110-1301, USA.21*/2223#include <linux/kernel.h>24#include <linux/module.h>25#include <linux/init.h>26#include <linux/slab.h>2728#include "au0828.h"2930static unsigned int vbibufs = 5;31module_param(vbibufs, int, 0644);32MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32");3334/* ------------------------------------------------------------------ */3536static void37free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)38{39struct au0828_fh *fh = vq->priv_data;40struct au0828_dev *dev = fh->dev;41unsigned long flags = 0;42if (in_interrupt())43BUG();4445/* We used to wait for the buffer to finish here, but this didn't work46because, as we were keeping the state as VIDEOBUF_QUEUED,47videobuf_queue_cancel marked it as finished for us.48(Also, it could wedge forever if the hardware was misconfigured.)4950This should be safe; by the time we get here, the buffer isn't51queued anymore. If we ever start marking the buffers as52VIDEOBUF_ACTIVE, it won't be, though.53*/54spin_lock_irqsave(&dev->slock, flags);55if (dev->isoc_ctl.vbi_buf == buf)56dev->isoc_ctl.vbi_buf = NULL;57spin_unlock_irqrestore(&dev->slock, flags);5859videobuf_vmalloc_free(&buf->vb);60buf->vb.state = VIDEOBUF_NEEDS_INIT;61}6263static int64vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)65{66struct au0828_fh *fh = q->priv_data;67struct au0828_dev *dev = fh->dev;6869*size = dev->vbi_width * dev->vbi_height * 2;7071if (0 == *count)72*count = vbibufs;73if (*count < 2)74*count = 2;75if (*count > 32)76*count = 32;77return 0;78}7980static int81vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,82enum v4l2_field field)83{84struct au0828_fh *fh = q->priv_data;85struct au0828_dev *dev = fh->dev;86struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);87int rc = 0;8889buf->vb.size = dev->vbi_width * dev->vbi_height * 2;9091if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)92return -EINVAL;9394buf->vb.width = dev->vbi_width;95buf->vb.height = dev->vbi_height;96buf->vb.field = field;9798if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {99rc = videobuf_iolock(q, &buf->vb, NULL);100if (rc < 0)101goto fail;102}103104buf->vb.state = VIDEOBUF_PREPARED;105return 0;106107fail:108free_buffer(q, buf);109return rc;110}111112static void113vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)114{115struct au0828_buffer *buf = container_of(vb,116struct au0828_buffer,117vb);118struct au0828_fh *fh = vq->priv_data;119struct au0828_dev *dev = fh->dev;120struct au0828_dmaqueue *vbiq = &dev->vbiq;121122buf->vb.state = VIDEOBUF_QUEUED;123list_add_tail(&buf->vb.queue, &vbiq->active);124}125126static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)127{128struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);129free_buffer(q, buf);130}131132struct videobuf_queue_ops au0828_vbi_qops = {133.buf_setup = vbi_setup,134.buf_prepare = vbi_prepare,135.buf_queue = vbi_queue,136.buf_release = vbi_release,137};138139140