summaryrefslogtreecommitdiff
path: root/drivers/media/pci/saa7134/saa7134-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/pci/saa7134/saa7134-core.c')
-rw-r--r--drivers/media/pci/saa7134/saa7134-core.c130
1 files changed, 67 insertions, 63 deletions
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index 1362b4aab473..be19a051a492 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -69,6 +69,10 @@ module_param_named(no_overlay, saa7134_no_overlay, int, 0444);
MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)"
" [some VIA/SIS chipsets are known to have problem with overlay]");
+bool saa7134_userptr;
+module_param(saa7134_userptr, bool, 0644);
+MODULE_PARM_DESC(saa7134_userptr, "enable page-aligned userptr support");
+
static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
static unsigned int vbi_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
@@ -203,16 +207,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;
}
@@ -237,14 +241,16 @@ int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
unsigned int startpage)
{
__le32 *ptr;
- unsigned int i,p;
+ unsigned int i, p;
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 +264,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);
- dprintk("buffer_queue %p\n",buf);
+ 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);
+ 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);
+ next = list_entry(q->queue.next, struct saa7134_buf,
+ entry);
q->curr = buf;
- buf->activate(dev,buf,next);
+ 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 +296,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);
+ 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,36 +315,31 @@ 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);
+ buf, q->queue.prev, q->queue.next);
+ 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);
+ buf->activate(dev, buf, next);
dprintk("buffer_next #2 prev=%p/next=%p\n",
- q->queue.prev,q->queue.next);
+ q->queue.prev, q->queue.next);
} else {
/* nothing to do -- just stop DMA */
- dprintk("buffer_next %p\n",NULL);
+ 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);
}
}
void saa7134_buffer_timeout(unsigned long data)
{
- struct saa7134_dmaqueue *q = (struct saa7134_dmaqueue*)data;
+ struct saa7134_dmaqueue *q = (struct saa7134_dmaqueue *)data;
struct saa7134_dev *dev = q->dev;
unsigned long flags;
- spin_lock_irqsave(&dev->slock,flags);
+ spin_lock_irqsave(&dev->slock, flags);
/* try to reset the hardware (SWRST) */
saa_writeb(SAA7134_REGION_ENABLE, 0x00);
@@ -362,13 +349,33 @@ void saa7134_buffer_timeout(unsigned long data)
/* flag current buffer as failed,
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);
+ dprintk("timeout on %p\n", q->curr);
+ saa7134_buffer_finish(dev, q, VB2_BUF_STATE_ERROR);
}
- saa7134_buffer_next(dev,q);
- spin_unlock_irqrestore(&dev->slock,flags);
+ 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,12 +395,11 @@ 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) */
- if (dev->video_q.curr &&
- dev->video_q.curr->fmt->planar) {
+ if (dev->video_q.curr && dev->fmt->planar) {
ctrl |= SAA7134_MAIN_CTRL_TE4 |
SAA7134_MAIN_CTRL_TE5;
}
@@ -1047,6 +1053,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) {
@@ -1059,6 +1067,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]);
@@ -1070,6 +1080,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)
@@ -1189,7 +1200,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;
@@ -1360,10 +1371,3 @@ EXPORT_SYMBOL(saa7134_pgtable_free);
EXPORT_SYMBOL(saa7134_pgtable_build);
EXPORT_SYMBOL(saa7134_pgtable_alloc);
EXPORT_SYMBOL(saa7134_set_dmabits);
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */