Commit 2ada815f authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

[media] saa7134: convert to vb2

Convert the saa7134 driver to vb2.

Note that while this uses the vb2-dma-sg version, the VB2_USERPTR mode is
disabled. The DMA hardware only supports DMAing full pages, and in the
USERPTR memory model the first and last scatter-gather buffer is almost
never a full page.

In practice this means that we can't use the VB2_USERPTR mode.

This has been tested with raw video, compressed video, VBI, radio, DVB and
video overlays.

Unfortunately, a vb2 conversion is one of those things you cannot split
up in smaller patches, it's all or nothing. This patch switches the whole
driver over to vb2, using the vb2 ioctl and fop helper functions.
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
parent a00e6888
config VIDEO_SAA7134
tristate "Philips SAA7134 support"
depends on VIDEO_DEV && PCI && I2C
select VIDEOBUF_DMA_SG
select VIDEOBUF2_DMA_SG
select VIDEO_TUNER
select VIDEO_TVEEPROM
select CRC32
......@@ -37,7 +37,7 @@ config VIDEO_SAA7134_RC
config VIDEO_SAA7134_DVB
tristate "DVB/ATSC Support for saa7134 based TV cards"
depends on VIDEO_SAA7134 && DVB_CORE
select VIDEOBUF_DVB
select VIDEOBUF2_DVB
select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT
......
......@@ -203,16 +203,16 @@ int saa7134_buffer_count(unsigned int size, unsigned int count)
int saa7134_buffer_startpage(struct saa7134_buf *buf)
{
return saa7134_buffer_pages(buf->vb.bsize) * buf->vb.i;
return saa7134_buffer_pages(vb2_plane_size(&buf->vb2, 0)) * buf->vb2.v4l2_buf.index;
}
unsigned long saa7134_buffer_base(struct saa7134_buf *buf)
{
unsigned long base;
struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
base = saa7134_buffer_startpage(buf) * 4096;
base += dma->sglist[0].offset;
base += dma->sgl[0].offset;
return base;
}
......@@ -242,9 +242,11 @@ int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
BUG_ON(NULL == pt || NULL == pt->cpu);
ptr = pt->cpu + startpage;
for (i = 0; i < length; i++, list++)
for (i = 0; i < length; i++, list = sg_next(list)) {
for (p = 0; p * 4096 < list->length; p++, ptr++)
*ptr = cpu_to_le32(sg_dma_address(list) - list->offset);
*ptr = cpu_to_le32(sg_dma_address(list) +
list->offset + p * 4096);
}
return 0;
}
......@@ -258,44 +260,31 @@ void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt)
/* ------------------------------------------------------------------ */
void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf)
{
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
BUG_ON(in_interrupt());
videobuf_waiton(q, &buf->vb, 0, 0);
videobuf_dma_unmap(q->dev, dma);
videobuf_dma_free(dma);
buf->vb.state = VIDEOBUF_NEEDS_INIT;
}
/* ------------------------------------------------------------------ */
int saa7134_buffer_queue(struct saa7134_dev *dev,
struct saa7134_dmaqueue *q,
struct saa7134_buf *buf)
{
struct saa7134_buf *next = NULL;
unsigned long flags;
assert_spin_locked(&dev->slock);
spin_lock_irqsave(&dev->slock, flags);
dprintk("buffer_queue %p\n", buf);
if (NULL == q->curr) {
if (!q->need_two) {
q->curr = buf;
buf->activate(dev, buf, NULL);
} else if (list_empty(&q->queue)) {
list_add_tail(&buf->vb.queue,&q->queue);
buf->vb.state = VIDEOBUF_QUEUED;
list_add_tail(&buf->entry, &q->queue);
} else {
next = list_entry(q->queue.next, struct saa7134_buf,
vb.queue);
entry);
q->curr = buf;
buf->activate(dev, buf, next);
}
} else {
list_add_tail(&buf->vb.queue, &q->queue);
buf->vb.state = VIDEOBUF_QUEUED;
list_add_tail(&buf->entry, &q->queue);
}
spin_unlock_irqrestore(&dev->slock, flags);
return 0;
}
......@@ -303,13 +292,12 @@ void saa7134_buffer_finish(struct saa7134_dev *dev,
struct saa7134_dmaqueue *q,
unsigned int state)
{
assert_spin_locked(&dev->slock);
dprintk("buffer_finish %p\n", q->curr);
/* finish current buffer */
q->curr->vb.state = state;
v4l2_get_timestamp(&q->curr->vb.ts);
wake_up(&q->curr->vb.done);
v4l2_get_timestamp(&q->curr->vb2.v4l2_buf.timestamp);
q->curr->vb2.v4l2_buf.sequence = q->seq_nr++;
vb2_buffer_done(&q->curr->vb2, state);
q->curr = NULL;
}
......@@ -323,13 +311,12 @@ void saa7134_buffer_next(struct saa7134_dev *dev,
if (!list_empty(&q->queue)) {
/* activate next one from queue */
buf = list_entry(q->queue.next, struct saa7134_buf, vb.queue);
buf = list_entry(q->queue.next, struct saa7134_buf, entry);
dprintk("buffer_next %p [prev=%p/next=%p]\n",
buf, q->queue.prev, q->queue.next);
list_del(&buf->vb.queue);
list_del(&buf->entry);
if (!list_empty(&q->queue))
next = list_entry(q->queue.next, struct saa7134_buf,
vb.queue);
next = list_entry(q->queue.next, struct saa7134_buf, entry);
q->curr = buf;
buf->activate(dev, buf, next);
dprintk("buffer_next #2 prev=%p/next=%p\n",
......@@ -339,10 +326,6 @@ void saa7134_buffer_next(struct saa7134_dev *dev,
dprintk("buffer_next %p\n", NULL);
saa7134_set_dmabits(dev);
del_timer(&q->timeout);
if (card_has_mpeg(dev))
if (dev->ts_started)
saa7134_ts_stop(dev);
}
}
......@@ -363,12 +346,32 @@ void saa7134_buffer_timeout(unsigned long data)
try to start over with the next one. */
if (q->curr) {
dprintk("timeout on %p\n", q->curr);
saa7134_buffer_finish(dev, q, VIDEOBUF_ERROR);
saa7134_buffer_finish(dev, q, VB2_BUF_STATE_ERROR);
}
saa7134_buffer_next(dev, q);
spin_unlock_irqrestore(&dev->slock, flags);
}
void saa7134_stop_streaming(struct saa7134_dev *dev, struct saa7134_dmaqueue *q)
{
unsigned long flags;
struct list_head *pos, *n;
struct saa7134_buf *tmp;
spin_lock_irqsave(&dev->slock, flags);
if (!list_empty(&q->queue)) {
list_for_each_safe(pos, n, &q->queue) {
tmp = list_entry(pos, struct saa7134_buf, entry);
vb2_buffer_done(&tmp->vb2, VB2_BUF_STATE_ERROR);
list_del(pos);
tmp = NULL;
}
}
spin_unlock_irqrestore(&dev->slock, flags);
saa7134_buffer_timeout((unsigned long)q); /* also calls del_timer(&q->timeout) */
}
EXPORT_SYMBOL_GPL(saa7134_stop_streaming);
/* ------------------------------------------------------------------ */
int saa7134_set_dmabits(struct saa7134_dev *dev)
......@@ -388,7 +391,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev)
ctrl |= SAA7134_MAIN_CTRL_TE0;
irq |= SAA7134_IRQ1_INTE_RA0_1 |
SAA7134_IRQ1_INTE_RA0_0;
cap = dev->video_q.curr->vb.field;
cap = dev->field;
}
/* video capture -- dma 1+2 (planar modes) */
......@@ -1046,6 +1049,8 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
dev->video_dev = vdev_init(dev,&saa7134_video_template,"video");
dev->video_dev->ctrl_handler = &dev->ctrl_handler;
dev->video_dev->lock = &dev->lock;
dev->video_dev->queue = &dev->video_vbq;
err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
video_nr[dev->nr]);
if (err < 0) {
......@@ -1058,6 +1063,8 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
dev->vbi_dev = vdev_init(dev, &saa7134_video_template, "vbi");
dev->vbi_dev->ctrl_handler = &dev->ctrl_handler;
dev->vbi_dev->lock = &dev->lock;
dev->vbi_dev->queue = &dev->vbi_vbq;
err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
vbi_nr[dev->nr]);
......@@ -1069,6 +1076,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
if (card_has_radio(dev)) {
dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio");
dev->radio_dev->ctrl_handler = &dev->radio_ctrl_handler;
dev->radio_dev->lock = &dev->lock;
err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
radio_nr[dev->nr]);
if (err < 0)
......@@ -1188,7 +1196,7 @@ static int saa7134_buffer_requeue(struct saa7134_dev *dev,
if (!list_empty(&q->queue))
next = list_entry(q->queue.next, struct saa7134_buf,
vb.queue);
entry);
buf->activate(dev, buf, next);
return 0;
......
......@@ -602,10 +602,10 @@ static int configure_tda827x_fe(struct saa7134_dev *dev,
struct tda1004x_config *cdec_conf,
struct tda827x_config *tuner_conf)
{
struct videobuf_dvb_frontend *fe0;
struct vb2_dvb_frontend *fe0;
/* Get the first frontend */
fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
if (!fe0)
return -EINVAL;
......@@ -1215,29 +1215,38 @@ static int dvb_init(struct saa7134_dev *dev)
{
int ret;
int attach_xc3028 = 0;
struct videobuf_dvb_frontend *fe0;
struct vb2_dvb_frontend *fe0;
struct vb2_queue *q;
/* FIXME: add support for multi-frontend */
mutex_init(&dev->frontends.lock);
INIT_LIST_HEAD(&dev->frontends.felist);
printk(KERN_INFO "%s() allocating 1 frontend\n", __func__);
fe0 = videobuf_dvb_alloc_frontend(&dev->frontends, 1);
fe0 = vb2_dvb_alloc_frontend(&dev->frontends, 1);
if (!fe0) {
printk(KERN_ERR "%s() failed to alloc\n", __func__);
return -ENOMEM;
}
/* init struct videobuf_dvb */
/* init struct vb2_dvb */
dev->ts.nr_bufs = 32;
dev->ts.nr_packets = 32*4;
fe0->dvb.name = dev->name;
videobuf_queue_sg_init(&fe0->dvb.dvbq, &saa7134_ts_qops,
&dev->pci->dev, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_ALTERNATE,
sizeof(struct saa7134_buf),
&dev->ts_q, NULL);
q = &fe0->dvb.dvbq;
q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
q->io_modes = VB2_MMAP | VB2_READ;
q->drv_priv = &dev->ts_q;
q->ops = &saa7134_ts_qops;
q->mem_ops = &vb2_dma_sg_memops;
q->buf_struct_size = sizeof(struct saa7134_buf);
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->lock = &dev->lock;
ret = vb2_queue_init(q);
if (ret) {
vb2_dvb_dealloc_frontends(&dev->frontends);
return ret;
}
switch (dev->board) {
case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
......@@ -1876,7 +1885,7 @@ static int dvb_init(struct saa7134_dev *dev)
fe0->dvb.frontend->callback = saa7134_tuner_callback;
/* register everything else */
ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
ret = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
&dev->pci->dev, adapter_nr, 0);
/* this sequence is necessary to make the tda1004x load its firmware
......@@ -1893,16 +1902,17 @@ static int dvb_init(struct saa7134_dev *dev)
return ret;
detach_frontend:
videobuf_dvb_dealloc_frontends(&dev->frontends);
vb2_dvb_dealloc_frontends(&dev->frontends);
vb2_queue_release(&fe0->dvb.dvbq);
return -EINVAL;
}
static int dvb_fini(struct saa7134_dev *dev)
{
struct videobuf_dvb_frontend *fe0;
struct vb2_dvb_frontend *fe0;
/* Get the first frontend */
fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
if (!fe0)
return -EINVAL;
......@@ -1933,7 +1943,8 @@ static int dvb_fini(struct saa7134_dev *dev)
}
}
}
videobuf_dvb_unregister_bus(&dev->frontends);
vb2_dvb_unregister_bus(&dev->frontends);
vb2_queue_release(&fe0->dvb.dvbq);
return 0;
}
......
......@@ -48,11 +48,16 @@ MODULE_PARM_DESC(debug,"enable debug messages");
/* ------------------------------------------------------------------ */
static void ts_reset_encoder(struct saa7134_dev* dev);
static int ts_init_encoder(struct saa7134_dev* dev)
static int start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct saa7134_dmaqueue *dmaq = vq->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
u32 leading_null_bytes = 0;
int err;
err = saa7134_ts_start_streaming(vq, count);
if (err)
return err;
/* If more cards start to need this, then this
should probably be added to the card definitions. */
......@@ -63,109 +68,43 @@ static int ts_init_encoder(struct saa7134_dev* dev)
leading_null_bytes = 1;
break;
}
ts_reset_encoder(dev);
saa_call_all(dev, core, init, leading_null_bytes);
/* Unmute audio */
saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6));
dev->empress_started = 1;
return 0;
}
static void ts_reset_encoder(struct saa7134_dev* dev)
static void stop_streaming(struct vb2_queue *vq)
{
if (!dev->empress_started)
return;
struct saa7134_dmaqueue *dmaq = vq->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
saa7134_ts_stop_streaming(vq);
saa_writeb(SAA7134_SPECIAL_MODE, 0x00);
msleep(10);
msleep(20);
saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
msleep(100);
dev->empress_started = 0;
}
/* ------------------------------------------------------------------ */
static int ts_open(struct file *file)
{
struct video_device *vdev = video_devdata(file);
struct saa7134_dev *dev = video_drvdata(file);
struct saa7134_fh *fh;
/* allocate + initialize per filehandle data */
fh = kzalloc(sizeof(*fh), GFP_KERNEL);
if (NULL == fh)
return -ENOMEM;
v4l2_fh_init(&fh->fh, vdev);
file->private_data = fh;
fh->is_empress = true;
v4l2_fh_add(&fh->fh);
/* Unmute audio */
/* Mute audio */
saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6));
return 0;
}
static int ts_release(struct file *file)
{
struct saa7134_dev *dev = video_drvdata(file);
struct saa7134_fh *fh = file->private_data;
if (res_check(fh, RESOURCE_EMPRESS)) {
videobuf_stop(&dev->empress_vbq);
videobuf_mmap_free(&dev->empress_vbq);
/* stop the encoder */
ts_reset_encoder(dev);
/* Mute audio */
saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
}
v4l2_fh_del(&fh->fh);
v4l2_fh_exit(&fh->fh);
return 0;
}
static ssize_t
ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
{
struct saa7134_dev *dev = video_drvdata(file);
if (res_locked(dev, RESOURCE_EMPRESS))
return -EBUSY;
if (!dev->empress_started)
ts_init_encoder(dev);
return videobuf_read_stream(&dev->empress_vbq,
data, count, ppos, 0,
file->f_flags & O_NONBLOCK);
}
static unsigned int
ts_poll(struct file *file, struct poll_table_struct *wait)
{
unsigned long req_events = poll_requested_events(wait);
struct saa7134_dev *dev = video_drvdata(file);
struct saa7134_fh *fh = file->private_data;
unsigned int rc = 0;
if (v4l2_event_pending(&fh->fh))
rc = POLLPRI;
else if (req_events & POLLPRI)
poll_wait(file, &fh->fh.wait, wait);
return rc | videobuf_poll_stream(file, &dev->empress_vbq, wait);
saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
dev->empress_started = 0;
}
static struct vb2_ops saa7134_empress_qops = {
.queue_setup = saa7134_ts_queue_setup,
.buf_init = saa7134_ts_buffer_init,
.buf_prepare = saa7134_ts_buffer_prepare,
.buf_finish = saa7134_ts_buffer_finish,
.buf_queue = saa7134_vb2_buffer_queue,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
};
static int
ts_mmap(struct file *file, struct vm_area_struct * vma)
{
struct saa7134_dev *dev = video_drvdata(file);
return videobuf_mmap_mapper(&dev->empress_vbq, vma);
}
/* ------------------------------------------------------------------ */
static int empress_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
......@@ -235,11 +174,11 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv,
static const struct v4l2_file_operations ts_fops =
{
.owner = THIS_MODULE,
.open = ts_open,
.release = ts_release,
.read = ts_read,
.poll = ts_poll,
.mmap = ts_mmap,
.open = v4l2_fh_open,
.release = vb2_fop_release,
.read = vb2_fop_read,
.poll = vb2_fop_poll,
.mmap = vb2_fop_mmap,
.ioctl = video_ioctl2,
};
......@@ -249,12 +188,12 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = {
.vidioc_try_fmt_vid_cap = empress_try_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = empress_s_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = empress_g_fmt_vid_cap,
.vidioc_reqbufs = saa7134_reqbufs,
.vidioc_querybuf = saa7134_querybuf,
.vidioc_qbuf = saa7134_qbuf,
.vidioc_dqbuf = saa7134_dqbuf,
.vidioc_streamon = saa7134_streamon,
.vidioc_streamoff = saa7134_streamoff,
.vidioc_reqbufs = vb2_ioctl_reqbufs,
.vidioc_querybuf = vb2_ioctl_querybuf,
.vidioc_qbuf = vb2_ioctl_qbuf,
.vidioc_dqbuf = vb2_ioctl_dqbuf,
.vidioc_streamon = vb2_ioctl_streamon,
.vidioc_streamoff = vb2_ioctl_streamoff,
.vidioc_g_frequency = saa7134_g_frequency,
.vidioc_s_frequency = saa7134_s_frequency,
.vidioc_g_tuner = saa7134_g_tuner,
......@@ -317,6 +256,7 @@ static bool empress_ctrl_filter(const struct v4l2_ctrl *ctrl)
static int empress_init(struct saa7134_dev *dev)
{
struct v4l2_ctrl_handler *hdl = &dev->empress_ctrl_handler;
struct vb2_queue *q;
int err;
dprintk("%s: %s\n",dev->name,__func__);
......@@ -326,6 +266,7 @@ static int empress_init(struct saa7134_dev *dev)
*(dev->empress_dev) = saa7134_empress_template;
dev->empress_dev->v4l2_dev = &dev->v4l2_dev;
dev->empress_dev->release = video_device_release;
dev->empress_dev->lock = &dev->lock;
snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
"%s empress (%s)", dev->name,
saa7134_boards[dev->board].name);
......@@ -342,6 +283,26 @@ static int empress_init(struct saa7134_dev *dev)
INIT_WORK(&dev->empress_workqueue, empress_signal_update);
q = &dev->empress_vbq;
q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
/*
* Do not add VB2_USERPTR: the saa7134 DMA engine cannot handle
* transfers that do not start at the beginning of a page. A USERPTR
* can start anywhere in a page, so USERPTR support is a no-go.
*/
q->io_modes = VB2_MMAP | VB2_READ;
q->drv_priv = &dev->ts_q;
q->ops = &saa7134_empress_qops;
q->gfp_flags = GFP_DMA32;
q->mem_ops = &vb2_dma_sg_memops;
q->buf_struct_size = sizeof(struct saa7134_buf);
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->lock = &dev->lock;
err = vb2_queue_init(q);
if (err)
return err;
dev->empress_dev->queue = q;
video_set_drvdata(dev->empress_dev, dev);
err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER,
empress_nr[dev->nr]);
......@@ -355,13 +316,6 @@ static int empress_init(struct saa7134_dev *dev)
printk(KERN_INFO "%s: registered device %s [mpeg]\n",
dev->name, video_device_node_name(dev->empress_dev));
videobuf_queue_sg_init(&dev->empress_vbq, &saa7134_ts_qops,
&dev->pci->dev, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_ALTERNATE,
sizeof(struct saa7134_buf),
&dev->ts_q, NULL);
empress_signal_update(&dev->empress_workqueue);
return 0;
}
......@@ -374,6 +328,7 @@ static int empress_fini(struct saa7134_dev *dev)
return 0;
flush_work(&dev->empress_workqueue);
video_unregister_device(dev->empress_dev);
vb2_queue_release(&dev->empress_vbq);
v4l2_ctrl_handler_free(&dev->empress_ctrl_handler);
dev->empress_dev = NULL;
return 0;
......
......@@ -39,26 +39,29 @@ MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]");
printk(KERN_DEBUG "%s/ts: " fmt, dev->name , ## arg)
/* ------------------------------------------------------------------ */
static int buffer_activate(struct saa7134_dev *dev,
struct saa7134_buf *buf,
struct saa7134_buf *next)
{
dprintk("buffer_activate [%p]",buf);
buf->vb.state = VIDEOBUF_ACTIVE;
buf->top_seen = 0;
if (!dev->ts_started)
dev->ts_field = V4L2_FIELD_TOP;
if (NULL == next)
next = buf;
if (V4L2_FIELD_TOP == buf->vb.field) {
if (V4L2_FIELD_TOP == dev->ts_field) {
dprintk("- [top] buf=%p next=%p\n",buf,next);
saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(buf));
saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(next));
dev->ts_field = V4L2_FIELD_BOTTOM;
} else {
dprintk("- [bottom] buf=%p next=%p\n",buf,next);
saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(next));
saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(buf));
dev->ts_field = V4L2_FIELD_TOP;
}
/* start DMA */
......@@ -72,99 +75,123 @@ static int buffer_activate(struct saa7134_dev *dev,
return 0;
}
static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
enum v4l2_field field)
int saa7134_ts_buffer_init(struct vb2_buffer *vb2)
{
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
dmaq->curr = NULL;
buf->activate = buffer_activate;
return 0;
}
EXPORT_SYMBOL_GPL(saa7134_ts_buffer_init);
int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2)
{
struct saa7134_dmaqueue *dmaq = q->priv_data;
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
struct saa7134_buf *buf = container_of(vb, struct saa7134_buf, vb);
struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
unsigned int lines, llength, size;
int err;
int ret;
dprintk("buffer_prepare [%p,%s]\n", buf, v4l2_field_names[field]);
dprintk("buffer_prepare [%p]\n", buf);
llength = TS_PACKET_SIZE;
lines = dev->ts.nr_packets;
size = lines * llength;
if (0 != buf->vb.baddr && buf->vb.bsize < size)
if (vb2_plane_size(vb2, 0) < size)
return -EINVAL;
if (buf->vb.size != size) {
saa7134_dma_free(q,buf);
}
if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
vb2_set_plane_payload(vb2, 0, size);
vb2->v4l2_buf.field = dev->field;
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
dprintk("buffer_prepare: needs_init\n");
buf->vb.width = llength;
buf->vb.height = lines;
buf->vb.size = size;
err = videobuf_iolock(q,&buf->vb,NULL);
if (err)
goto oops;
err = saa7134_pgtable_build(dev->pci, &dmaq->pt,
dma->sglist,
dma->sglen,
saa7134_buffer_startpage(buf));
if (err)
goto oops;
}
buf->vb.state = VIDEOBUF_PREPARED;
buf->activate = buffer_activate;
buf->vb.field = field;
return 0;
oops:
saa7134_dma_free(q,buf);
return err;
ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
if (!ret)
return -EIO;
return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
saa7134_buffer_startpage(buf));
}
EXPORT_SYMBOL_GPL(saa7134_ts_buffer_prepare);
static int
buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
void saa7134_ts_buffer_finish(struct vb2_buffer *vb2)
{
struct saa7134_dmaqueue *dmaq = q->priv_data;
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
*size = TS_PACKET_SIZE * dev->ts.nr_packets;
if (0 == *count)
*count = dev->ts.nr_bufs;
*count = saa7134_buffer_count(*size,*count);
dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
}
EXPORT_SYMBOL_GPL(saa7134_ts_buffer_finish);
int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
struct saa7134_dmaqueue *dmaq = q->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
int size = TS_PACKET_SIZE * dev->ts.nr_packets;
if (0 == *nbuffers)
*nbuffers = dev->ts.nr_bufs;
*nbuffers = saa7134_buffer_count(size, *nbuffers);
if (*nbuffers < 3)
*nbuffers = 3;
*nplanes = 1;
sizes[0] = size;
return 0;
}
EXPORT_SYMBOL_GPL(saa7134_ts_queue_setup);
static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct saa7134_dmaqueue *dmaq = q->priv_data;
struct saa7134_dmaqueue *dmaq = vq->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
saa7134_buffer_queue(dev,&dev->ts_q,buf);
/*
* Planar video capture and TS share the same DMA channel,
* so only one can be active at a time.
*/
if (vb2_is_busy(&dev->video_vbq) && dev->fmt->planar) {
struct saa7134_buf *buf, *tmp;
list_for_each_entry_safe(buf, tmp, &dmaq->queue, entry) {
list_del(&buf->entry);
vb2_buffer_done(&buf->vb2, VB2_BUF_STATE_QUEUED);
}
if (dmaq->curr) {
vb2_buffer_done(&dmaq->curr->vb2, VB2_BUF_STATE_QUEUED);
dmaq->curr = NULL;
}
return -EBUSY;
}
dmaq->seq_nr = 0;
return 0;
}
EXPORT_SYMBOL_GPL(saa7134_ts_start_streaming);
static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
void saa7134_ts_stop_streaming(struct vb2_queue *vq)
{
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
struct saa7134_dmaqueue *dmaq = q->priv_data;
struct saa7134_dmaqueue *dmaq = vq->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
if (dev->ts_started)
saa7134_ts_stop(dev);
saa7134_dma_free(q,buf);
saa7134_ts_stop(dev);
saa7134_stop_streaming(dev, dmaq);
}
struct videobuf_queue_ops saa7134_ts_qops = {
.buf_setup = buffer_setup,
.buf_prepare = buffer_prepare,
.buf_queue = buffer_queue,
.buf_release = buffer_release,
EXPORT_SYMBOL_GPL(saa7134_ts_stop_streaming);
struct vb2_ops saa7134_ts_qops = {
.queue_setup = saa7134_ts_queue_setup,
.buf_init = saa7134_ts_buffer_init,
.buf_prepare = saa7134_ts_buffer_prepare,
.buf_finish = saa7134_ts_buffer_finish,
.buf_queue = saa7134_vb2_buffer_queue,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
.stop_streaming = saa7134_ts_stop_streaming,
};
EXPORT_SYMBOL_GPL(saa7134_ts_qops);
......@@ -229,7 +256,8 @@ int saa7134_ts_stop(struct saa7134_dev *dev)
{
dprintk("TS stop\n");
BUG_ON(!dev->ts_started);
if (!dev->ts_started)
return 0;
/* Stop TS stream */
switch (saa7134_boards[dev->board].ts_type) {
......@@ -250,7 +278,8 @@ int saa7134_ts_start(struct saa7134_dev *dev)
{
dprintk("TS start\n");
BUG_ON(dev->ts_started);
if (WARN_ON(dev->ts_started))
return 0;
/* dma: setup channel 5 (= TS) */
saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff);
......@@ -306,15 +335,15 @@ void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status)
spin_lock(&dev->slock);
if (dev->ts_q.curr) {
field = dev->ts_q.curr->vb.field;
if (field == V4L2_FIELD_TOP) {
field = dev->ts_field;
if (field != V4L2_FIELD_TOP) {
if ((status & 0x100000) != 0x000000)
goto done;
} else {
if ((status & 0x100000) != 0x100000)
goto done;
}
saa7134_buffer_finish(dev, &dev->ts_q, VIDEOBUF_DONE);
saa7134_buffer_finish(dev, &dev->ts_q, VB2_BUF_STATE_DONE);
}
saa7134_buffer_next(dev,&dev->ts_q);
......
......@@ -81,10 +81,10 @@ static int buffer_activate(struct saa7134_dev *dev,
struct saa7134_buf *buf,
struct saa7134_buf *next)
{
struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_queue->drv_priv;
unsigned long control, base;
dprintk("buffer_activate [%p]\n", buf);
buf->vb.state = VIDEOBUF_ACTIVE;
buf->top_seen = 0;
task_init(dev, buf, TASK_A);
......@@ -96,7 +96,7 @@ static int buffer_activate(struct saa7134_dev *dev,
base = saa7134_buffer_base(buf);
control = SAA7134_RS_CONTROL_BURST_16 |
SAA7134_RS_CONTROL_ME |
(dev->vbi_q.pt.dma >> 12);
(dmaq->pt.dma >> 12);
saa_writel(SAA7134_RS_BA1(2), base);
saa_writel(SAA7134_RS_BA2(2), base + dev->vbi_hlen * dev->vbi_vlen);
saa_writel(SAA7134_RS_PITCH(2), dev->vbi_hlen);
......@@ -108,93 +108,83 @@ static int buffer_activate(struct saa7134_dev *dev,
/* start DMA */
saa7134_set_dmabits(dev);
mod_timer(&dev->vbi_q.timeout, jiffies + BUFFER_TIMEOUT);
mod_timer(&dmaq->timeout, jiffies + BUFFER_TIMEOUT);
return 0;
}
static int buffer_prepare(struct videobuf_queue *q,
struct videobuf_buffer *vb,
enum v4l2_field field)
static int buffer_prepare(struct vb2_buffer *vb2)
{
struct saa7134_dmaqueue *dmaq = q->priv_data;
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
unsigned int size;
int err;
int ret;
size = dev->vbi_hlen * dev->vbi_vlen * 2;
if (0 != buf->vb.baddr && buf->vb.bsize < size)
if (vb2_plane_size(vb2, 0) < size)
return -EINVAL;
if (buf->vb.size != size)
saa7134_dma_free(q,buf);
if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
buf->vb.width = dev->vbi_hlen;
buf->vb.height = dev->vbi_vlen;
buf->vb.size = size;
err = videobuf_iolock(q,&buf->vb,NULL);
if (err)
goto oops;
err = saa7134_pgtable_build(dev->pci, &dmaq->pt,
dma->sglist,
dma->sglen,
saa7134_buffer_startpage(buf));
if (err)
goto oops;
}
buf->vb.state = VIDEOBUF_PREPARED;
buf->activate = buffer_activate;
buf->vb.field = field;
return 0;
vb2_set_plane_payload(vb2, 0, size);
oops:
saa7134_dma_free(q,buf);
return err;
ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
if (!ret)
return -EIO;
return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
saa7134_buffer_startpage(buf));
}
static int
buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
struct saa7134_dmaqueue *dmaq = q->priv_data;
struct saa7134_dmaqueue *dmaq = q->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
unsigned int size;
dev->vbi_vlen = dev->tvnorm->vbi_v_stop_0 - dev->tvnorm->vbi_v_start_0 + 1;
if (dev->vbi_vlen > VBI_LINE_COUNT)
dev->vbi_vlen = VBI_LINE_COUNT;
dev->vbi_hlen = VBI_LINE_LENGTH;
*size = dev->vbi_hlen * dev->vbi_vlen * 2;
if (0 == *count)
*count = vbibufs;
*count = saa7134_buffer_count(*size,*count);
size = dev->vbi_hlen * dev->vbi_vlen * 2;
*nbuffers = saa7134_buffer_count(size, *nbuffers);
*nplanes = 1;
sizes[0] = size;
return 0;
}
static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
static int buffer_init(struct vb2_buffer *vb2)
{
struct saa7134_dmaqueue *dmaq = q->priv_data;
struct saa7134_dev *dev = dmaq->dev;
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
saa7134_buffer_queue(dev,&dev->vbi_q,buf);
dmaq->curr = NULL;
buf->activate = buffer_activate;
return 0;
}
static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
static void buffer_finish(struct vb2_buffer *vb2)
{
struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
struct saa7134_dev *dev = dmaq->dev;
struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
saa7134_dma_free(q,buf);
dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
}
struct videobuf_queue_ops saa7134_vbi_qops = {
.buf_setup = buffer_setup,
.buf_prepare = buffer_prepare,
.buf_queue = buffer_queue,
.buf_release = buffer_release,
struct vb2_ops saa7134_vbi_qops = {
.queue_setup = queue_setup,
.buf_init = buffer_init,
.buf_prepare = buffer_prepare,
.buf_finish = buffer_finish,
.buf_queue = saa7134_vb2_buffer_queue,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
.start_streaming = saa7134_vb2_start_streaming,
.stop_streaming = saa7134_vb2_stop_streaming,
};
/* ------------------------------------------------------------------ */
......@@ -224,7 +214,6 @@ void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status)
{
spin_lock(&dev->slock);
if (dev->vbi_q.curr) {
dev->vbi_fieldcount++;
/* make sure we have seen both fields */
if ((status & 0x10) == 0x00) {
dev->vbi_q.curr->top_seen = 1;
......@@ -233,8 +222,7 @@ void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status)
if (!dev->vbi_q.curr->top_seen)
goto done;
dev->vbi_q.curr->vb.field_count = dev->vbi_fieldcount;
saa7134_buffer_finish(dev, &dev->vbi_q, VIDEOBUF_DONE);
saa7134_buffer_finish(dev, &dev->vbi_q, VB2_BUF_STATE_DONE);
}
saa7134_buffer_next(dev, &dev->vbi_q);
......
This diff is collapsed.
......@@ -41,11 +41,11 @@
#include <media/tuner.h>
#include <media/rc-core.h>
#include <media/ir-kbd-i2c.h>
#include <media/videobuf-dma-sg.h>
#include <media/videobuf2-dma-sg.h>
#include <sound/core.h>
#include <sound/pcm.h>
#if IS_ENABLED(CONFIG_VIDEO_SAA7134_DVB)
#include <media/videobuf-dvb.h>
#include <media/videobuf2-dvb.h>
#endif
#include "tda8290.h"
......@@ -453,13 +453,15 @@ struct saa7134_thread {
/* buffer for one video/vbi/ts frame */
struct saa7134_buf {
/* common v4l buffer stuff -- must be first */
struct videobuf_buffer vb;
struct vb2_buffer vb2;
/* saa7134 specific */
unsigned int top_seen;
int (*activate)(struct saa7134_dev *dev,
struct saa7134_buf *buf,
struct saa7134_buf *next);
struct list_head entry;
};
struct saa7134_dmaqueue {
......@@ -468,16 +470,10 @@ struct saa7134_dmaqueue {
struct list_head queue;
struct timer_list timeout;
unsigned int need_two;
unsigned int seq_nr;
struct saa7134_pgtable pt;
};
/* video filehandle status */
struct saa7134_fh {
struct v4l2_fh fh;
bool is_empress;
unsigned int resources;
};
/* dmasound dsp status */
struct saa7134_dmasound {
struct mutex lock;
......@@ -583,20 +579,35 @@ struct saa7134_dev {
struct v4l2_window win;
struct v4l2_clip clips[8];
unsigned int nclips;
struct v4l2_fh *overlay_owner;
/* video+ts+vbi capture */
struct saa7134_dmaqueue video_q;
struct videobuf_queue video_vbq;
struct vb2_queue video_vbq;
struct saa7134_dmaqueue vbi_q;
struct videobuf_queue vbi_vbq;
unsigned int video_fieldcount;
unsigned int vbi_fieldcount;
struct vb2_queue vbi_vbq;
enum v4l2_field field;
struct saa7134_format *fmt;
unsigned int width, height;
unsigned int vbi_hlen, vbi_vlen;
struct pm_qos_request qos_request;
/* SAA7134_MPEG_* */
struct saa7134_ts ts;
struct saa7134_dmaqueue ts_q;
enum v4l2_field ts_field;
int ts_started;
struct saa7134_mpeg_ops *mops;
/* SAA7134_MPEG_EMPRESS only */
struct video_device *empress_dev;
struct v4l2_subdev *empress_sd;
struct vb2_queue empress_vbq;
struct work_struct empress_workqueue;
int empress_started;
struct v4l2_ctrl_handler empress_ctrl_handler;
/* various v4l controls */
struct saa7134_tvnorm *tvnorm; /* video */
struct saa7134_tvaudio *tvaudio;
......@@ -633,23 +644,9 @@ struct saa7134_dev {
/* I2C keyboard data */
struct IR_i2c_init_data init_data;
/* SAA7134_MPEG_* */
struct saa7134_ts ts;
struct saa7134_dmaqueue ts_q;
int ts_started;
struct saa7134_mpeg_ops *mops;
/* SAA7134_MPEG_EMPRESS only */
struct video_device *empress_dev;
struct v4l2_subdev *empress_sd;
struct videobuf_queue empress_vbq;
struct work_struct empress_workqueue;
int empress_started;
struct v4l2_ctrl_handler empress_ctrl_handler;
#if IS_ENABLED(CONFIG_VIDEO_SAA7134_DVB)
/* SAA7134_MPEG_DVB only */
struct videobuf_dvb_frontends frontends;
struct vb2_dvb_frontends frontends;
int (*original_demod_sleep)(struct dvb_frontend *fe);
int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg);
......@@ -703,14 +700,12 @@ struct saa7134_dev {
_rc; \
})
static inline int res_check(struct saa7134_fh *fh, unsigned int bit)
static inline bool is_empress(struct file *file)
{
return fh->resources & bit;
}
struct video_device *vdev = video_devdata(file);
struct saa7134_dev *dev = video_get_drvdata(vdev);
static inline int res_locked(struct saa7134_dev *dev, unsigned int bit)
{
return dev->resources & bit;
return vdev->queue == &dev->empress_vbq;
}
/* ----------------------------------------------------------- */
......@@ -741,7 +736,7 @@ void saa7134_buffer_finish(struct saa7134_dev *dev, struct saa7134_dmaqueue *q,
unsigned int state);
void saa7134_buffer_next(struct saa7134_dev *dev, struct saa7134_dmaqueue *q);
void saa7134_buffer_timeout(unsigned long data);
void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf);
void saa7134_stop_streaming(struct saa7134_dev *dev, struct saa7134_dmaqueue *q);
int saa7134_set_dmabits(struct saa7134_dev *dev);
......@@ -775,6 +770,10 @@ extern unsigned int video_debug;
extern struct video_device saa7134_video_template;
extern struct video_device saa7134_radio_template;
void saa7134_vb2_buffer_queue(struct vb2_buffer *vb);
int saa7134_vb2_start_streaming(struct vb2_queue *vq, unsigned int count);
void saa7134_vb2_stop_streaming(struct vb2_queue *vq);
int saa7134_s_std(struct file *file, void *priv, v4l2_std_id id);
int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id);
int saa7134_querystd(struct file *file, void *priv, v4l2_std_id *std);
......@@ -791,16 +790,6 @@ int saa7134_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f);
int saa7134_s_frequency(struct file *file, void *priv,
const struct v4l2_frequency *f);
int saa7134_reqbufs(struct file *file, void *priv,
struct v4l2_requestbuffers *p);
int saa7134_querybuf(struct file *file, void *priv,
struct v4l2_buffer *b);
int saa7134_qbuf(struct file *file, void *priv, struct v4l2_buffer *b);
int saa7134_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b);
int saa7134_streamon(struct file *file, void *priv,
enum v4l2_buf_type type);
int saa7134_streamoff(struct file *file, void *priv,
enum v4l2_buf_type type);
int saa7134_videoport_init(struct saa7134_dev *dev);
void saa7134_set_tvnorm_hw(struct saa7134_dev *dev);
......@@ -817,7 +806,16 @@ void saa7134_video_fini(struct saa7134_dev *dev);
#define TS_PACKET_SIZE 188 /* TS packets 188 bytes */
extern struct videobuf_queue_ops saa7134_ts_qops;
int saa7134_ts_buffer_init(struct vb2_buffer *vb2);
int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2);
void saa7134_ts_buffer_finish(struct vb2_buffer *vb2);
int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[]);
int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count);
void saa7134_ts_stop_streaming(struct vb2_queue *vq);
extern struct vb2_ops saa7134_ts_qops;
int saa7134_ts_init1(struct saa7134_dev *dev);
int saa7134_ts_fini(struct saa7134_dev *dev);
......@@ -834,7 +832,7 @@ int saa7134_ts_stop(struct saa7134_dev *dev);
/* ----------------------------------------------------------- */
/* saa7134-vbi.c */
extern struct videobuf_queue_ops saa7134_vbi_qops;
extern struct vb2_ops saa7134_vbi_qops;
extern struct video_device saa7134_vbi_template;
int saa7134_vbi_init1(struct saa7134_dev *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment