* [PATCH 00/16] cx88: convert to vb2
@ 2014-09-20 12:41 Hans Verkuil
2014-09-20 12:41 ` [PATCH 01/16] cx88: remove fmt from the buffer struct Hans Verkuil
` (15 more replies)
0 siblings, 16 replies; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media
This patch series converts the cx88 driver to vb2. Tested with NTSC and
PAL, video, vbi, audio, mpeg and dvb-t on a Hauppauge WinTV-HVR3000 and
a Hauppauge WinTV-HVR1300.
I see this as something for 3.19 so that there is enough time for testing
since this is a popular card.
Regards,
Hans
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 01/16] cx88: remove fmt from the buffer struct
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
@ 2014-09-20 12:41 ` Hans Verkuil
2014-09-20 12:41 ` [PATCH 02/16] cx88: drop the bogus 'queue' list in dmaqueue Hans Verkuil
` (14 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
This is a duplicate of dev->fmt and can be removed. As a consequence a
lot of tests that check if the format has changed midstream can be
removed as well: the format cannot change midstream, so this is a bogus
check.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/cx88/cx88-mpeg.c | 6 +-
drivers/media/pci/cx88/cx88-video.c | 116 ++++++++++++++----------------------
drivers/media/pci/cx88/cx88.h | 1 -
3 files changed, 46 insertions(+), 77 deletions(-)
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
index 74b7b86..2803b6f 100644
--- a/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -229,17 +229,13 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
dprintk(1,"[%p/%d] restart_queue - first active\n",
buf,buf->vb.i);
- } else if (prev->vb.width == buf->vb.width &&
- prev->vb.height == buf->vb.height &&
- prev->fmt == buf->fmt) {
+ } else {
list_move_tail(&buf->vb.queue, &q->active);
buf->vb.state = VIDEOBUF_ACTIVE;
buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(1,"[%p/%d] restart_queue - move to active\n",
buf,buf->vb.i);
- } else {
- return 0;
}
prev = buf;
}
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index ed8cb90..3075179 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -420,7 +420,7 @@ static int start_video_dma(struct cx8800_dev *dev,
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21],
buf->bpl, buf->risc.dma);
cx88_set_scale(core, buf->vb.width, buf->vb.height, buf->vb.field);
- cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma);
+ cx_write(MO_COLOR_CTRL, dev->fmt->cxformat | ColorFormatGamma);
/* reset counter */
cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET);
@@ -497,17 +497,13 @@ static int restart_video_queue(struct cx8800_dev *dev,
dprintk(2,"[%p/%d] restart_queue - first active\n",
buf,buf->vb.i);
- } else if (prev->vb.width == buf->vb.width &&
- prev->vb.height == buf->vb.height &&
- prev->fmt == buf->fmt) {
+ } else {
list_move_tail(&buf->vb.queue, &q->active);
buf->vb.state = VIDEOBUF_ACTIVE;
buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(2,"[%p/%d] restart_queue - move to active\n",
buf,buf->vb.i);
- } else {
- return 0;
}
prev = buf;
}
@@ -538,7 +534,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
struct cx88_core *core = dev->core;
struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
- int rc, init_buffer = 0;
+ int rc;
BUG_ON(NULL == dev->fmt);
if (dev->width < 48 || dev->width > norm_maxw(core->tvnorm) ||
@@ -548,59 +544,47 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
return -EINVAL;
- if (buf->fmt != dev->fmt ||
- buf->vb.width != dev->width ||
- buf->vb.height != dev->height ||
- buf->vb.field != field) {
- buf->fmt = dev->fmt;
- buf->vb.width = dev->width;
- buf->vb.height = dev->height;
- buf->vb.field = field;
- init_buffer = 1;
- }
-
+ buf->vb.width = dev->width;
+ buf->vb.height = dev->height;
+ buf->vb.field = field;
if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
- init_buffer = 1;
if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
goto fail;
}
- if (init_buffer) {
- buf->bpl = buf->vb.width * buf->fmt->depth >> 3;
- switch (buf->vb.field) {
- case V4L2_FIELD_TOP:
- cx88_risc_buffer(dev->pci, &buf->risc,
- dma->sglist, 0, UNSET,
- buf->bpl, 0, buf->vb.height);
- break;
- case V4L2_FIELD_BOTTOM:
- cx88_risc_buffer(dev->pci, &buf->risc,
- dma->sglist, UNSET, 0,
- buf->bpl, 0, buf->vb.height);
- break;
- case V4L2_FIELD_INTERLACED:
- cx88_risc_buffer(dev->pci, &buf->risc,
- dma->sglist, 0, buf->bpl,
- buf->bpl, buf->bpl,
- buf->vb.height >> 1);
- break;
- case V4L2_FIELD_SEQ_TB:
- cx88_risc_buffer(dev->pci, &buf->risc,
- dma->sglist,
- 0, buf->bpl * (buf->vb.height >> 1),
- buf->bpl, 0,
- buf->vb.height >> 1);
- break;
- case V4L2_FIELD_SEQ_BT:
- cx88_risc_buffer(dev->pci, &buf->risc,
- dma->sglist,
- buf->bpl * (buf->vb.height >> 1), 0,
- buf->bpl, 0,
- buf->vb.height >> 1);
- break;
- default:
- BUG();
- }
+ buf->bpl = buf->vb.width * dev->fmt->depth >> 3;
+ switch (buf->vb.field) {
+ case V4L2_FIELD_TOP:
+ cx88_risc_buffer(dev->pci, &buf->risc,
+ dma->sglist, 0, UNSET,
+ buf->bpl, 0, buf->vb.height);
+ break;
+ case V4L2_FIELD_BOTTOM:
+ cx88_risc_buffer(dev->pci, &buf->risc,
+ dma->sglist, UNSET, 0,
+ buf->bpl, 0, buf->vb.height);
+ break;
+ case V4L2_FIELD_SEQ_TB:
+ cx88_risc_buffer(dev->pci, &buf->risc,
+ dma->sglist,
+ 0, buf->bpl * (buf->vb.height >> 1),
+ buf->bpl, 0,
+ buf->vb.height >> 1);
+ break;
+ case V4L2_FIELD_SEQ_BT:
+ cx88_risc_buffer(dev->pci, &buf->risc,
+ dma->sglist,
+ buf->bpl * (buf->vb.height >> 1), 0,
+ buf->bpl, 0,
+ buf->vb.height >> 1);
+ break;
+ case V4L2_FIELD_INTERLACED:
+ default:
+ cx88_risc_buffer(dev->pci, &buf->risc,
+ dma->sglist, 0, buf->bpl,
+ buf->bpl, buf->bpl,
+ buf->vb.height >> 1);
+ break;
}
dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
buf, buf->vb.i,
@@ -646,22 +630,12 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
} else {
prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
- if (prev->vb.width == buf->vb.width &&
- prev->vb.height == buf->vb.height &&
- prev->fmt == buf->fmt) {
- list_add_tail(&buf->vb.queue,&q->active);
- buf->vb.state = VIDEOBUF_ACTIVE;
- buf->count = q->count++;
- prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
- dprintk(2,"[%p/%d] buffer_queue - append to active\n",
- buf, buf->vb.i);
-
- } else {
- list_add_tail(&buf->vb.queue,&q->queued);
- buf->vb.state = VIDEOBUF_QUEUED;
- dprintk(2,"[%p/%d] buffer_queue - first queued\n",
- buf, buf->vb.i);
- }
+ list_add_tail(&buf->vb.queue, &q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+ dprintk(2, "[%p/%d] buffer_queue - append to active\n",
+ buf, buf->vb.i);
}
}
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index 28893a6..ddc7991 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -319,7 +319,6 @@ struct cx88_buffer {
/* cx88 specific */
unsigned int bpl;
struct btcx_riscmem risc;
- const struct cx8800_fmt *fmt;
u32 count;
};
--
2.1.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 02/16] cx88: drop the bogus 'queue' list in dmaqueue.
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
2014-09-20 12:41 ` [PATCH 01/16] cx88: remove fmt from the buffer struct Hans Verkuil
@ 2014-09-20 12:41 ` Hans Verkuil
2014-10-28 18:58 ` Mauro Carvalho Chehab
2014-09-20 12:41 ` [PATCH 03/16] cx88: drop videobuf abuse in cx88-alsa Hans Verkuil
` (13 subsequent siblings)
15 siblings, 1 reply; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
This list is used some buffers have a different format, but that can
never happen. Remove it and all associated code.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/cx88/cx88-mpeg.c | 31 -----------------------------
drivers/media/pci/cx88/cx88-video.c | 39 +++----------------------------------
drivers/media/pci/cx88/cx88.h | 1 -
3 files changed, 3 insertions(+), 68 deletions(-)
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
index 2803b6f..5f59901 100644
--- a/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -210,37 +210,7 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
dprintk( 1, "cx8802_restart_queue\n" );
if (list_empty(&q->active))
- {
- struct cx88_buffer *prev;
- prev = NULL;
-
- dprintk(1, "cx8802_restart_queue: queue is empty\n" );
-
- for (;;) {
- if (list_empty(&q->queued))
- return 0;
- buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
- if (NULL == prev) {
- list_move_tail(&buf->vb.queue, &q->active);
- cx8802_start_dma(dev, q, buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
- buf->count = q->count++;
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
- dprintk(1,"[%p/%d] restart_queue - first active\n",
- buf,buf->vb.i);
-
- } else {
- list_move_tail(&buf->vb.queue, &q->active);
- buf->vb.state = VIDEOBUF_ACTIVE;
- buf->count = q->count++;
- prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
- dprintk(1,"[%p/%d] restart_queue - move to active\n",
- buf,buf->vb.i);
- }
- prev = buf;
- }
return 0;
- }
buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
@@ -486,7 +456,6 @@ static int cx8802_init_common(struct cx8802_dev *dev)
/* init dma queue */
INIT_LIST_HEAD(&dev->mpegq.active);
- INIT_LIST_HEAD(&dev->mpegq.queued);
dev->mpegq.timeout.function = cx8802_timeout;
dev->mpegq.timeout.data = (unsigned long)dev;
init_timer(&dev->mpegq.timeout);
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index 3075179..10fea4d 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -470,7 +470,7 @@ static int restart_video_queue(struct cx8800_dev *dev,
struct cx88_dmaqueue *q)
{
struct cx88_core *core = dev->core;
- struct cx88_buffer *buf, *prev;
+ struct cx88_buffer *buf;
if (!list_empty(&q->active)) {
buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
@@ -480,33 +480,8 @@ static int restart_video_queue(struct cx8800_dev *dev,
list_for_each_entry(buf, &q->active, vb.queue)
buf->count = q->count++;
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
- return 0;
- }
-
- prev = NULL;
- for (;;) {
- if (list_empty(&q->queued))
- return 0;
- buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
- if (NULL == prev) {
- list_move_tail(&buf->vb.queue, &q->active);
- start_video_dma(dev, q, buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
- buf->count = q->count++;
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
- dprintk(2,"[%p/%d] restart_queue - first active\n",
- buf,buf->vb.i);
-
- } else {
- list_move_tail(&buf->vb.queue, &q->active);
- buf->vb.state = VIDEOBUF_ACTIVE;
- buf->count = q->count++;
- prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
- dprintk(2,"[%p/%d] restart_queue - move to active\n",
- buf,buf->vb.i);
- }
- prev = buf;
}
+ return 0;
}
/* ------------------------------------------------------------------ */
@@ -613,13 +588,7 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
- if (!list_empty(&q->queued)) {
- list_add_tail(&buf->vb.queue,&q->queued);
- buf->vb.state = VIDEOBUF_QUEUED;
- dprintk(2,"[%p/%d] buffer_queue - append to queued\n",
- buf, buf->vb.i);
-
- } else if (list_empty(&q->active)) {
+ if (list_empty(&q->active)) {
list_add_tail(&buf->vb.queue,&q->active);
start_video_dma(dev, q, buf);
buf->vb.state = VIDEOBUF_ACTIVE;
@@ -1694,7 +1663,6 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
/* init video dma queues */
INIT_LIST_HEAD(&dev->vidq.active);
- INIT_LIST_HEAD(&dev->vidq.queued);
dev->vidq.timeout.function = cx8800_vid_timeout;
dev->vidq.timeout.data = (unsigned long)dev;
init_timer(&dev->vidq.timeout);
@@ -1703,7 +1671,6 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
/* init vbi dma queues */
INIT_LIST_HEAD(&dev->vbiq.active);
- INIT_LIST_HEAD(&dev->vbiq.queued);
dev->vbiq.timeout.function = cx8800_vbi_timeout;
dev->vbiq.timeout.data = (unsigned long)dev;
init_timer(&dev->vbiq.timeout);
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index ddc7991..77ec542 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -324,7 +324,6 @@ struct cx88_buffer {
struct cx88_dmaqueue {
struct list_head active;
- struct list_head queued;
struct timer_list timeout;
struct btcx_riscmem stopper;
u32 count;
--
2.1.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 03/16] cx88: drop videobuf abuse in cx88-alsa
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
2014-09-20 12:41 ` [PATCH 01/16] cx88: remove fmt from the buffer struct Hans Verkuil
2014-09-20 12:41 ` [PATCH 02/16] cx88: drop the bogus 'queue' list in dmaqueue Hans Verkuil
@ 2014-09-20 12:41 ` Hans Verkuil
2014-09-20 12:41 ` [PATCH 04/16] cx88: convert to vb2 Hans Verkuil
` (12 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
The alsa driver uses videobuf low-level functions that are not
available in vb2, so replace them by driver-specific functions.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/cx88/cx88-alsa.c | 107 ++++++++++++++++++++++++++++++-------
1 file changed, 89 insertions(+), 18 deletions(-)
diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c
index a72579a..73021a2 100644
--- a/drivers/media/pci/cx88/cx88-alsa.c
+++ b/drivers/media/pci/cx88/cx88-alsa.c
@@ -62,7 +62,10 @@
struct cx88_audio_buffer {
unsigned int bpl;
struct btcx_riscmem risc;
- struct videobuf_dmabuf dma;
+ void *vaddr;
+ struct scatterlist *sglist;
+ int sglen;
+ int nr_pages;
};
struct cx88_audio_dev {
@@ -84,8 +87,6 @@ struct cx88_audio_dev {
unsigned int period_size;
unsigned int num_periods;
- struct videobuf_dmabuf *dma_risc;
-
struct cx88_audio_buffer *buf;
struct snd_pcm_substream *substream;
@@ -290,19 +291,94 @@ static irqreturn_t cx8801_irq(int irq, void *dev_id)
return IRQ_RETVAL(handled);
}
+static int cx88_alsa_dma_init(struct cx88_audio_dev *chip, int nr_pages)
+{
+ struct cx88_audio_buffer *buf = chip->buf;
+ struct page *pg;
+ int i;
+
+ buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
+ if (NULL == buf->vaddr) {
+ dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages);
+ return -ENOMEM;
+ }
+
+ dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n",
+ (unsigned long)buf->vaddr,
+ nr_pages << PAGE_SHIFT);
+
+ memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT);
+ buf->nr_pages = nr_pages;
+
+ buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist));
+ if (NULL == buf->sglist)
+ goto vzalloc_err;
+
+ sg_init_table(buf->sglist, buf->nr_pages);
+ for (i = 0; i < buf->nr_pages; i++) {
+ pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE);
+ if (NULL == pg)
+ goto vmalloc_to_page_err;
+ sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0);
+ }
+ return 0;
+
+vmalloc_to_page_err:
+ vfree(buf->sglist);
+ buf->sglist = NULL;
+vzalloc_err:
+ vfree(buf->vaddr);
+ buf->vaddr = NULL;
+ return -ENOMEM;
+}
+
+static int cx88_alsa_dma_map(struct cx88_audio_dev *dev)
+{
+ struct cx88_audio_buffer *buf = dev->buf;
+
+ buf->sglen = dma_map_sg(&dev->pci->dev, buf->sglist,
+ buf->nr_pages, PCI_DMA_FROMDEVICE);
+
+ if (0 == buf->sglen) {
+ pr_warn("%s: cx88_alsa_map_sg failed\n", __func__);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int cx88_alsa_dma_unmap(struct cx88_audio_dev *dev)
+{
+ struct cx88_audio_buffer *buf = dev->buf;
+
+ if (!buf->sglen)
+ return 0;
+
+ dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->sglen, PCI_DMA_FROMDEVICE);
+ buf->sglen = 0;
+ return 0;
+}
+
+static int cx88_alsa_dma_free(struct cx88_audio_buffer *buf)
+{
+ vfree(buf->sglist);
+ buf->sglist = NULL;
+ vfree(buf->vaddr);
+ buf->vaddr = NULL;
+ return 0;
+}
+
static int dsp_buffer_free(snd_cx88_card_t *chip)
{
BUG_ON(!chip->dma_size);
dprintk(2,"Freeing buffer\n");
- videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc);
- videobuf_dma_free(chip->dma_risc);
- btcx_riscmem_free(chip->pci,&chip->buf->risc);
+ cx88_alsa_dma_unmap(chip);
+ cx88_alsa_dma_free(chip->buf);
+ btcx_riscmem_free(chip->pci, &chip->buf->risc);
kfree(chip->buf);
- chip->dma_risc = NULL;
- chip->dma_size = 0;
+ chip->buf = NULL;
return 0;
}
@@ -387,7 +463,6 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
struct snd_pcm_hw_params * hw_params)
{
snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
- struct videobuf_dmabuf *dma;
struct cx88_audio_buffer *buf;
int ret;
@@ -408,20 +483,19 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
if (NULL == buf)
return -ENOMEM;
+ chip->buf = buf;
buf->bpl = chip->period_size;
- dma = &buf->dma;
- videobuf_dma_init(dma);
- ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+ ret = cx88_alsa_dma_init(chip,
(PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
if (ret < 0)
goto error;
- ret = videobuf_dma_map(&chip->pci->dev, dma);
+ ret = cx88_alsa_dma_map(chip);
if (ret < 0)
goto error;
- ret = cx88_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
+ ret = cx88_risc_databuffer(chip->pci, &buf->risc, buf->sglist,
chip->period_size, chip->num_periods, 1);
if (ret < 0)
goto error;
@@ -430,10 +504,7 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
- chip->buf = buf;
- chip->dma_risc = dma;
-
- substream->runtime->dma_area = chip->dma_risc->vaddr;
+ substream->runtime->dma_area = chip->buf->vaddr;
substream->runtime->dma_bytes = chip->dma_size;
substream->runtime->dma_addr = 0;
return 0;
--
2.1.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 04/16] cx88: convert to vb2
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
` (2 preceding siblings ...)
2014-09-20 12:41 ` [PATCH 03/16] cx88: drop videobuf abuse in cx88-alsa Hans Verkuil
@ 2014-09-20 12:41 ` Hans Verkuil
2014-09-20 12:41 ` [PATCH 05/16] cx88: fix sparse warning Hans Verkuil
` (11 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
As usual, this patch is very large due to the fact that half a vb2 conversion
isn't possible. And since this affects blackbird, alsa, core, dvb, vbi and
video the changes are all over.
What made this more difficult was the peculiar way the risc program was setup.
The driver allowed for running out of buffers in which case the DMA would stop
and restart when the next buffer was queued. There was also a complicated
timeout system for when buffers weren't filled. This was replaced by a much
simpler scheme where there is always one buffer around and the DMA will just
cycle that buffer until a new buffer is queued. In that case the previous
buffer will be chained to the new buffer. An interrupt is generated at the
start of the new buffer telling the driver that the previous buffer can be
passed on to userspace.
Much simpler and more robust.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/cx88/Kconfig | 4 +-
drivers/media/pci/cx88/cx88-blackbird.c | 438 +++++++++-----------
drivers/media/pci/cx88/cx88-core.c | 83 +---
drivers/media/pci/cx88/cx88-dvb.c | 155 ++++---
drivers/media/pci/cx88/cx88-mpeg.c | 117 ++----
drivers/media/pci/cx88/cx88-vbi.c | 193 ++++-----
drivers/media/pci/cx88/cx88-video.c | 697 +++++++++-----------------------
drivers/media/pci/cx88/cx88.h | 64 ++-
8 files changed, 651 insertions(+), 1100 deletions(-)
diff --git a/drivers/media/pci/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig
index a63a9ad..d5b125e 100644
--- a/drivers/media/pci/cx88/Kconfig
+++ b/drivers/media/pci/cx88/Kconfig
@@ -3,7 +3,7 @@ config VIDEO_CX88
depends on VIDEO_DEV && PCI && I2C && RC_CORE
select I2C_ALGOBIT
select VIDEO_BTCX
- select VIDEOBUF_DMA_SG
+ select VIDEOBUF2_DMA_SG
select VIDEO_TUNER
select VIDEO_TVEEPROM
select VIDEO_WM8775 if MEDIA_SUBDRV_AUTOSELECT
@@ -45,7 +45,7 @@ config VIDEO_CX88_BLACKBIRD
config VIDEO_CX88_DVB
tristate "DVB/ATSC Support for cx2388x based TV cards"
depends on VIDEO_CX88 && DVB_CORE
- select VIDEOBUF_DVB
+ select VIDEOBUF2_DVB
select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index 150bb76..25d06f3 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -45,10 +45,6 @@ MODULE_AUTHOR("Jelle Foks <jelle@foks.us>, Gerd Knorr <kraxel@bytesex.org> [SuSE
MODULE_LICENSE("GPL");
MODULE_VERSION(CX88_VERSION);
-static unsigned int mpegbufs = 32;
-module_param(mpegbufs,int,0644);
-MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32");
-
static unsigned int debug;
module_param(debug,int,0644);
MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
@@ -589,9 +585,8 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
return 0;
}
-static int blackbird_start_codec(struct file *file, void *priv)
+static int blackbird_start_codec(struct cx8802_dev *dev)
{
- struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
struct cx88_core *core = dev->core;
/* start capturing to the host interface */
u32 reg;
@@ -647,45 +642,131 @@ static int blackbird_stop_codec(struct cx8802_dev *dev)
/* ------------------------------------------------------------------ */
-static int bb_buf_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 *num_buffers, unsigned int *num_planes,
+ unsigned int sizes[], void *alloc_ctxs[])
{
- struct cx8802_fh *fh = q->priv_data;
-
- fh->dev->ts_packet_size = 188 * 4; /* was: 512 */
- fh->dev->ts_packet_count = mpegbufs; /* was: 100 */
+ struct cx8802_dev *dev = q->drv_priv;
- *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count;
- *count = fh->dev->ts_packet_count;
+ *num_planes = 1;
+ dev->ts_packet_size = 188 * 4;
+ dev->ts_packet_count = 32;
+ sizes[0] = dev->ts_packet_size * dev->ts_packet_count;
return 0;
}
-static int
-bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
- enum v4l2_field field)
+static int buffer_prepare(struct vb2_buffer *vb)
{
- struct cx8802_fh *fh = q->priv_data;
- return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field);
+ struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
+ struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+
+ return cx8802_buf_prepare(vb->vb2_queue, dev, buf, dev->field);
}
-static void
-bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+static void buffer_finish(struct vb2_buffer *vb)
{
- struct cx8802_fh *fh = q->priv_data;
- cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb);
+ struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
+ struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
+
+ cx88_free_buffer(vb->vb2_queue, buf);
+
+ dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
}
-static void
-bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+static void buffer_queue(struct vb2_buffer *vb)
{
- cx88_free_buffer(q, (struct cx88_buffer*)vb);
+ struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
+ struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+
+ cx8802_buf_queue(dev, buf);
}
-static struct videobuf_queue_ops blackbird_qops = {
- .buf_setup = bb_buf_setup,
- .buf_prepare = bb_buf_prepare,
- .buf_queue = bb_buf_queue,
- .buf_release = bb_buf_release,
+static int start_streaming(struct vb2_queue *q, unsigned int count)
+{
+ struct cx8802_dev *dev = q->drv_priv;
+ struct cx88_dmaqueue *dmaq = &dev->mpegq;
+ struct cx8802_driver *drv;
+ struct cx88_buffer *buf;
+ unsigned long flags;
+ int err;
+
+ /* Make sure we can acquire the hardware */
+ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+ if (!drv) {
+ dprintk(1, "%s: blackbird driver is not loaded\n", __func__);
+ err = -ENODEV;
+ goto fail;
+ }
+
+ err = drv->request_acquire(drv);
+ if (err != 0) {
+ dprintk(1, "%s: Unable to acquire hardware, %d\n", __func__, err);
+ goto fail;
+ }
+
+ if (blackbird_initialize_codec(dev) < 0) {
+ drv->request_release(drv);
+ err = -EINVAL;
+ goto fail;
+ }
+
+ err = blackbird_start_codec(dev);
+ if (err == 0) {
+ buf = list_entry(dmaq->active.next, struct cx88_buffer, list);
+ cx8802_start_dma(dev, dmaq, buf);
+ return 0;
+ }
+
+fail:
+ spin_lock_irqsave(&dev->slock, flags);
+ while (!list_empty(&dmaq->active)) {
+ struct cx88_buffer *buf = list_entry(dmaq->active.next,
+ struct cx88_buffer, list);
+
+ list_del(&buf->list);
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+ }
+ spin_unlock_irqrestore(&dev->slock, flags);
+ return err;
+}
+
+static void stop_streaming(struct vb2_queue *q)
+{
+ struct cx8802_dev *dev = q->drv_priv;
+ struct cx88_dmaqueue *dmaq = &dev->mpegq;
+ struct cx8802_driver *drv = NULL;
+ unsigned long flags;
+
+ cx8802_cancel_buffers(dev);
+ blackbird_stop_codec(dev);
+
+ /* Make sure we release the hardware */
+ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+ WARN_ON(!drv);
+ if (drv)
+ drv->request_release(drv);
+
+ spin_lock_irqsave(&dev->slock, flags);
+ while (!list_empty(&dmaq->active)) {
+ struct cx88_buffer *buf = list_entry(dmaq->active.next,
+ struct cx88_buffer, list);
+
+ list_del(&buf->list);
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ }
+ spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+static struct vb2_ops blackbird_qops = {
+ .queue_setup = queue_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_finish = buffer_finish,
+ .buf_queue = buffer_queue,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .start_streaming = start_streaming,
+ .stop_streaming = stop_streaming,
};
/* ------------------------------------------------------------------ */
@@ -693,8 +774,8 @@ static struct videobuf_queue_ops blackbird_qops = {
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
- struct cx88_core *core = dev->core;
+ struct cx8802_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
strcpy(cap->driver, "cx88_blackbird");
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
@@ -717,50 +798,47 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
struct v4l2_format *f)
{
- struct cx8802_fh *fh = priv;
- struct cx8802_dev *dev = fh->dev;
+ struct cx8802_dev *dev = video_drvdata(file);
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
+ f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
f->fmt.pix.width = dev->width;
f->fmt.pix.height = dev->height;
- f->fmt.pix.field = fh->mpegq.field;
+ f->fmt.pix.field = dev->field;
dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
- dev->width, dev->height, fh->mpegq.field );
+ dev->width, dev->height, dev->field);
return 0;
}
static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
struct v4l2_format *f)
{
- struct cx8802_fh *fh = priv;
- struct cx8802_dev *dev = fh->dev;
+ struct cx8802_dev *dev = video_drvdata(file);
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
+ f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
- dev->width, dev->height, fh->mpegq.field );
+ dev->width, dev->height, dev->field);
return 0;
}
static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
struct v4l2_format *f)
{
- struct cx8802_fh *fh = priv;
- struct cx8802_dev *dev = fh->dev;
+ struct cx8802_dev *dev = video_drvdata(file);
struct cx88_core *core = dev->core;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
+ f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
dev->width = f->fmt.pix.width;
dev->height = f->fmt.pix.height;
- fh->mpegq.field = f->fmt.pix.field;
+ dev->field = f->fmt.pix.field;
cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
f->fmt.pix.height, f->fmt.pix.width);
@@ -769,57 +847,11 @@ static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
return 0;
}
-static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
-{
- struct cx8802_fh *fh = priv;
- return (videobuf_reqbufs(&fh->mpegq, p));
-}
-
-static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
-{
- struct cx8802_fh *fh = priv;
- return (videobuf_querybuf(&fh->mpegq, p));
-}
-
-static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
-{
- struct cx8802_fh *fh = priv;
- return (videobuf_qbuf(&fh->mpegq, p));
-}
-
-static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
-{
- struct cx8802_fh *fh = priv;
- return (videobuf_dqbuf(&fh->mpegq, p,
- file->f_flags & O_NONBLOCK));
-}
-
-static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
- struct cx8802_fh *fh = priv;
- struct cx8802_dev *dev = fh->dev;
-
- if (!dev->mpeg_active)
- blackbird_start_codec(file, fh);
- return videobuf_streamon(&fh->mpegq);
-}
-
-static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
- struct cx8802_fh *fh = priv;
- struct cx8802_dev *dev = fh->dev;
-
- if (dev->mpeg_active)
- blackbird_stop_codec(dev);
- return videobuf_streamoff(&fh->mpegq);
-}
-
static int vidioc_s_frequency (struct file *file, void *priv,
const struct v4l2_frequency *f)
{
- struct cx8802_fh *fh = priv;
- struct cx8802_dev *dev = fh->dev;
- struct cx88_core *core = dev->core;
+ struct cx8802_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
if (unlikely(UNSET == core->board.tuner_type))
return -EINVAL;
@@ -831,14 +863,14 @@ static int vidioc_s_frequency (struct file *file, void *priv,
cx88_set_freq (core,f);
blackbird_initialize_codec(dev);
cx88_set_scale(dev->core, dev->width, dev->height,
- fh->mpegq.field);
+ dev->field);
return 0;
}
static int vidioc_log_status (struct file *file, void *priv)
{
- struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
- struct cx88_core *core = dev->core;
+ struct cx8802_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
char name[32 + 2];
snprintf(name, sizeof(name), "%s/2", core->name);
@@ -850,15 +882,16 @@ static int vidioc_log_status (struct file *file, void *priv)
static int vidioc_enum_input (struct file *file, void *priv,
struct v4l2_input *i)
{
- struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
+ struct cx8802_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
return cx88_enum_input (core,i);
}
static int vidioc_g_frequency (struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct cx8802_fh *fh = priv;
- struct cx88_core *core = fh->dev->core;
+ struct cx8802_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
if (unlikely(UNSET == core->board.tuner_type))
return -EINVAL;
@@ -873,7 +906,8 @@ static int vidioc_g_frequency (struct file *file, void *priv,
static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
{
- struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
+ struct cx8802_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
*i = core->input;
return 0;
@@ -881,24 +915,24 @@ static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
{
- struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
+ struct cx8802_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
if (i >= 4)
return -EINVAL;
if (0 == INPUT(i).type)
return -EINVAL;
- mutex_lock(&core->lock);
cx88_newstation(core);
cx88_video_mux(core,i);
- mutex_unlock(&core->lock);
return 0;
}
static int vidioc_g_tuner (struct file *file, void *priv,
struct v4l2_tuner *t)
{
- struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
+ struct cx8802_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
u32 reg;
if (unlikely(UNSET == core->board.tuner_type))
@@ -920,7 +954,8 @@ static int vidioc_g_tuner (struct file *file, void *priv,
static int vidioc_s_tuner (struct file *file, void *priv,
const struct v4l2_tuner *t)
{
- struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
+ struct cx8802_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
if (UNSET == core->board.tuner_type)
return -EINVAL;
@@ -933,7 +968,8 @@ static int vidioc_s_tuner (struct file *file, void *priv,
static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
{
- struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
+ struct cx8802_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
*tvnorm = core->tvnorm;
return 0;
@@ -941,155 +977,21 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
{
- struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
-
- mutex_lock(&core->lock);
- cx88_set_tvnorm(core, id);
- mutex_unlock(&core->lock);
- return 0;
-}
-
-/* FIXME: cx88_ioctl_hook not implemented */
-
-static int mpeg_open(struct file *file)
-{
- struct video_device *vdev = video_devdata(file);
struct cx8802_dev *dev = video_drvdata(file);
- struct cx8802_fh *fh;
- struct cx8802_driver *drv = NULL;
- int err;
-
- dprintk( 1, "%s\n", __func__);
-
- mutex_lock(&dev->core->lock);
-
- /* Make sure we can acquire the hardware */
- drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
- if (!drv) {
- dprintk(1, "%s: blackbird driver is not loaded\n", __func__);
- mutex_unlock(&dev->core->lock);
- return -ENODEV;
- }
-
- err = drv->request_acquire(drv);
- if (err != 0) {
- dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
- mutex_unlock(&dev->core->lock);
- return err;
- }
-
- if (!dev->core->mpeg_users && blackbird_initialize_codec(dev) < 0) {
- drv->request_release(drv);
- mutex_unlock(&dev->core->lock);
- return -EINVAL;
- }
- dprintk(1, "open dev=%s\n", video_device_node_name(vdev));
-
- /* allocate + initialize per filehandle data */
- fh = kzalloc(sizeof(*fh),GFP_KERNEL);
- if (NULL == fh) {
- drv->request_release(drv);
- mutex_unlock(&dev->core->lock);
- return -ENOMEM;
- }
- v4l2_fh_init(&fh->fh, vdev);
- file->private_data = fh;
- fh->dev = dev;
-
- videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops,
- &dev->pci->dev, &dev->slock,
- V4L2_BUF_TYPE_VIDEO_CAPTURE,
- V4L2_FIELD_INTERLACED,
- sizeof(struct cx88_buffer),
- fh, NULL);
-
- /* FIXME: locking against other video device */
- cx88_set_scale(dev->core, dev->width, dev->height,
- fh->mpegq.field);
-
- dev->core->mpeg_users++;
- mutex_unlock(&dev->core->lock);
- v4l2_fh_add(&fh->fh);
- return 0;
-}
-
-static int mpeg_release(struct file *file)
-{
- struct cx8802_fh *fh = file->private_data;
- struct cx8802_dev *dev = fh->dev;
- struct cx8802_driver *drv = NULL;
-
- mutex_lock(&dev->core->lock);
-
- if (dev->mpeg_active && dev->core->mpeg_users == 1)
- blackbird_stop_codec(dev);
-
- cx8802_cancel_buffers(fh->dev);
- /* stop mpeg capture */
- videobuf_stop(&fh->mpegq);
-
- videobuf_mmap_free(&fh->mpegq);
-
- v4l2_fh_del(&fh->fh);
- v4l2_fh_exit(&fh->fh);
- file->private_data = NULL;
- kfree(fh);
-
- /* Make sure we release the hardware */
- drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
- WARN_ON(!drv);
- if (drv)
- drv->request_release(drv);
-
- dev->core->mpeg_users--;
-
- mutex_unlock(&dev->core->lock);
+ struct cx88_core *core = dev->core;
+ cx88_set_tvnorm(core, id);
return 0;
}
-static ssize_t
-mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
-{
- struct cx8802_fh *fh = file->private_data;
- struct cx8802_dev *dev = fh->dev;
-
- if (!dev->mpeg_active)
- blackbird_start_codec(file, fh);
-
- return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
- file->f_flags & O_NONBLOCK);
-}
-
-static unsigned int
-mpeg_poll(struct file *file, struct poll_table_struct *wait)
-{
- unsigned long req_events = poll_requested_events(wait);
- struct cx8802_fh *fh = file->private_data;
- struct cx8802_dev *dev = fh->dev;
-
- if (!dev->mpeg_active && (req_events & (POLLIN | POLLRDNORM)))
- blackbird_start_codec(file, fh);
-
- return v4l2_ctrl_poll(file, wait) | videobuf_poll_stream(file, &fh->mpegq, wait);
-}
-
-static int
-mpeg_mmap(struct file *file, struct vm_area_struct * vma)
-{
- struct cx8802_fh *fh = file->private_data;
-
- return videobuf_mmap_mapper(&fh->mpegq, vma);
-}
-
static const struct v4l2_file_operations mpeg_fops =
{
.owner = THIS_MODULE,
- .open = mpeg_open,
- .release = mpeg_release,
- .read = mpeg_read,
- .poll = mpeg_poll,
- .mmap = mpeg_mmap,
+ .open = v4l2_fh_open,
+ .release = vb2_fop_release,
+ .read = vb2_fop_read,
+ .poll = vb2_fop_poll,
+ .mmap = vb2_fop_mmap,
.unlocked_ioctl = video_ioctl2,
};
@@ -1099,12 +1001,12 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
- .vidioc_reqbufs = vidioc_reqbufs,
- .vidioc_querybuf = vidioc_querybuf,
- .vidioc_qbuf = vidioc_qbuf,
- .vidioc_dqbuf = vidioc_dqbuf,
- .vidioc_streamon = vidioc_streamon,
- .vidioc_streamoff = vidioc_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_s_frequency = vidioc_s_frequency,
.vidioc_log_status = vidioc_log_status,
.vidioc_enum_input = vidioc_enum_input,
@@ -1189,11 +1091,12 @@ static int blackbird_register_video(struct cx8802_dev *dev)
{
int err;
- dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci,
- &cx8802_mpeg_template,"mpeg");
+ dev->mpeg_dev = cx88_vdev_init(dev->core, dev->pci,
+ &cx8802_mpeg_template, "mpeg");
dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl;
video_set_drvdata(dev->mpeg_dev, dev);
- err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);
+ dev->mpeg_dev->queue = &dev->vb2_mpegq;
+ err = video_register_device(dev->mpeg_dev, VFL_TYPE_GRABBER, -1);
if (err < 0) {
printk(KERN_INFO "%s/2: can't register mpeg device\n",
dev->core->name);
@@ -1210,6 +1113,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
{
struct cx88_core *core = drv->core;
struct cx8802_dev *dev = core->dvbdev;
+ struct vb2_queue *q;
int err;
dprintk( 1, "%s\n", __func__);
@@ -1229,6 +1133,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
} else {
dev->height = 576;
}
+ dev->field = V4L2_FIELD_INTERLACED;
dev->cxhdl.port = CX2341X_PORT_STREAMING;
dev->cxhdl.width = dev->width;
dev->cxhdl.height = dev->height;
@@ -1252,11 +1157,28 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
cx88_video_mux(core,0);
cx2341x_handler_set_50hz(&dev->cxhdl, dev->height == 576);
cx2341x_handler_setup(&dev->cxhdl);
+
+ q = &dev->vb2_mpegq;
+ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
+ q->gfp_flags = GFP_DMA32;
+ q->min_buffers_needed = 2;
+ q->drv_priv = dev;
+ q->buf_struct_size = sizeof(struct cx88_buffer);
+ q->ops = &blackbird_qops;
+ q->mem_ops = &vb2_dma_sg_memops;
+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ q->lock = &core->lock;
+
+ err = vb2_queue_init(q);
+ if (err < 0)
+ goto fail_core;
+
blackbird_register_video(dev);
return 0;
- fail_core:
+fail_core:
return err;
}
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
index 7163023..f027408 100644
--- a/drivers/media/pci/cx88/cx88-core.c
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -76,11 +76,16 @@ static DEFINE_MUTEX(devlist);
static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
unsigned int offset, u32 sync_line,
unsigned int bpl, unsigned int padding,
- unsigned int lines, unsigned int lpi)
+ unsigned int lines, unsigned int lpi, bool jump)
{
struct scatterlist *sg;
unsigned int line,todo,sol;
+ if (jump) {
+ (*rp++) = cpu_to_le32(RISC_JUMP);
+ (*rp++) = 0;
+ }
+
/* sync instruction */
if (sync_line != NO_SYNC_LINE)
*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
@@ -147,7 +152,7 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
can cause next bpl to start close to a page border. First DMA
region may be smaller than PAGE_SIZE */
instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
- instructions += 2;
+ instructions += 4;
if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
return rc;
@@ -155,10 +160,10 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
rp = risc->cpu;
if (UNSET != top_offset)
rp = cx88_risc_field(rp, sglist, top_offset, 0,
- bpl, padding, lines, 0);
+ bpl, padding, lines, 0, true);
if (UNSET != bottom_offset)
rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
- bpl, padding, lines, 0);
+ bpl, padding, lines, 0, top_offset == UNSET);
/* save pointer to jmp instruction address */
risc->jmp = rp;
@@ -179,13 +184,13 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
there is no padding and no sync. First DMA region may be smaller
than PAGE_SIZE */
instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
- instructions += 1;
+ instructions += 3;
if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
return rc;
/* write risc instructions */
rp = risc->cpu;
- rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi);
+ rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi, !lpi);
/* save pointer to jmp instruction address */
risc->jmp = rp;
@@ -193,37 +198,10 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
return 0;
}
-int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
- u32 reg, u32 mask, u32 value)
-{
- __le32 *rp;
- int rc;
-
- if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
- return rc;
-
- /* write risc instructions */
- rp = risc->cpu;
- *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ2 | RISC_IMM);
- *(rp++) = cpu_to_le32(reg);
- *(rp++) = cpu_to_le32(value);
- *(rp++) = cpu_to_le32(mask);
- *(rp++) = cpu_to_le32(RISC_JUMP);
- *(rp++) = cpu_to_le32(risc->dma);
- return 0;
-}
-
void
-cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
+cx88_free_buffer(struct vb2_queue *q, struct cx88_buffer *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);
- btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
- buf->vb.state = VIDEOBUF_NEEDS_INIT;
+ btcx_riscmem_free(to_pci_dev(q->drv_priv), &buf->risc);
}
/* ------------------------------------------------------------------ */
@@ -539,33 +517,12 @@ void cx88_wakeup(struct cx88_core *core,
struct cx88_dmaqueue *q, u32 count)
{
struct cx88_buffer *buf;
- int bc;
-
- for (bc = 0;; bc++) {
- if (list_empty(&q->active))
- break;
- buf = list_entry(q->active.next,
- struct cx88_buffer, vb.queue);
- /* count comes from the hw and is is 16bit wide --
- * this trick handles wrap-arounds correctly for
- * up to 32767 buffers in flight... */
- if ((s16) (count - buf->count) < 0)
- break;
- v4l2_get_timestamp(&buf->vb.ts);
- dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
- count, buf->count);
- buf->vb.state = VIDEOBUF_DONE;
- list_del(&buf->vb.queue);
- wake_up(&buf->vb.done);
- }
- if (list_empty(&q->active)) {
- del_timer(&q->timeout);
- } else {
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
- }
- if (bc != 1)
- dprintk(2, "%s: %d buffers handled (should be 1)\n",
- __func__, bc);
+
+ buf = list_entry(q->active.next,
+ struct cx88_buffer, list);
+ v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+ list_del(&buf->list);
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
}
void cx88_shutdown(struct cx88_core *core)
@@ -1043,6 +1000,7 @@ struct video_device *cx88_vdev_init(struct cx88_core *core,
vfd->v4l2_dev = &core->v4l2_dev;
vfd->dev_parent = &pci->dev;
vfd->release = video_device_release;
+ vfd->lock = &core->lock;
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
core->name, type, core->board.name);
return vfd;
@@ -1114,7 +1072,6 @@ EXPORT_SYMBOL(cx88_shutdown);
EXPORT_SYMBOL(cx88_risc_buffer);
EXPORT_SYMBOL(cx88_risc_databuffer);
-EXPORT_SYMBOL(cx88_risc_stopper);
EXPORT_SYMBOL(cx88_free_buffer);
EXPORT_SYMBOL(cx88_sram_channels);
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
index 053ed1b..d7e5c45 100644
--- a/drivers/media/pci/cx88/cx88-dvb.c
+++ b/drivers/media/pci/cx88/cx88-dvb.c
@@ -82,43 +82,86 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
/* ------------------------------------------------------------------ */
-static int dvb_buf_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 *num_buffers, unsigned int *num_planes,
+ unsigned int sizes[], void *alloc_ctxs[])
{
- struct cx8802_dev *dev = q->priv_data;
+ struct cx8802_dev *dev = q->drv_priv;
+ *num_planes = 1;
dev->ts_packet_size = 188 * 4;
dev->ts_packet_count = dvb_buf_tscnt;
-
- *size = dev->ts_packet_size * dev->ts_packet_count;
- *count = dvb_buf_tscnt;
+ sizes[0] = dev->ts_packet_size * dev->ts_packet_count;
+ *num_buffers = dvb_buf_tscnt;
return 0;
}
-static int dvb_buf_prepare(struct videobuf_queue *q,
- struct videobuf_buffer *vb, enum v4l2_field field)
+static int buffer_prepare(struct vb2_buffer *vb)
+{
+ struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
+ struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+
+ return cx8802_buf_prepare(vb->vb2_queue, dev, buf, dev->field);
+}
+
+static void buffer_finish(struct vb2_buffer *vb)
+{
+ struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
+ struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
+
+ cx88_free_buffer(vb->vb2_queue, buf);
+
+ dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
+}
+
+static void buffer_queue(struct vb2_buffer *vb)
{
- struct cx8802_dev *dev = q->priv_data;
- return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field);
+ struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
+ struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+
+ cx8802_buf_queue(dev, buf);
}
-static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+static int start_streaming(struct vb2_queue *q, unsigned int count)
{
- struct cx8802_dev *dev = q->priv_data;
- cx8802_buf_queue(dev, (struct cx88_buffer*)vb);
+ struct cx8802_dev *dev = q->drv_priv;
+ struct cx88_dmaqueue *dmaq = &dev->mpegq;
+ struct cx88_buffer *buf;
+
+ buf = list_entry(dmaq->active.next, struct cx88_buffer, list);
+ cx8802_start_dma(dev, dmaq, buf);
+ return 0;
}
-static void dvb_buf_release(struct videobuf_queue *q,
- struct videobuf_buffer *vb)
+static void stop_streaming(struct vb2_queue *q)
{
- cx88_free_buffer(q, (struct cx88_buffer*)vb);
+ struct cx8802_dev *dev = q->drv_priv;
+ struct cx88_dmaqueue *dmaq = &dev->mpegq;
+ unsigned long flags;
+
+ cx8802_cancel_buffers(dev);
+
+ spin_lock_irqsave(&dev->slock, flags);
+ while (!list_empty(&dmaq->active)) {
+ struct cx88_buffer *buf = list_entry(dmaq->active.next,
+ struct cx88_buffer, list);
+
+ list_del(&buf->list);
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ }
+ spin_unlock_irqrestore(&dev->slock, flags);
}
-static const struct videobuf_queue_ops dvb_qops = {
- .buf_setup = dvb_buf_setup,
- .buf_prepare = dvb_buf_prepare,
- .buf_queue = dvb_buf_queue,
- .buf_release = dvb_buf_release,
+static struct vb2_ops dvb_qops = {
+ .queue_setup = queue_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_finish = buffer_finish,
+ .buf_queue = buffer_queue,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .start_streaming = start_streaming,
+ .stop_streaming = stop_streaming,
};
/* ------------------------------------------------------------------ */
@@ -130,7 +173,7 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
int ret = 0;
int fe_id;
- fe_id = videobuf_dvb_find_frontend(&dev->frontends, fe);
+ fe_id = vb2_dvb_find_frontend(&dev->frontends, fe);
if (!fe_id) {
printk(KERN_ERR "%s() No frontend found\n", __func__);
return -EINVAL;
@@ -154,8 +197,8 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
static void cx88_dvb_gate_ctrl(struct cx88_core *core, int open)
{
- struct videobuf_dvb_frontends *f;
- struct videobuf_dvb_frontend *fe;
+ struct vb2_dvb_frontends *f;
+ struct vb2_dvb_frontend *fe;
if (!core->dvbdev)
return;
@@ -166,9 +209,9 @@ static void cx88_dvb_gate_ctrl(struct cx88_core *core, int open)
return;
if (f->gate <= 1) /* undefined or fe0 */
- fe = videobuf_dvb_get_frontend(f, 1);
+ fe = vb2_dvb_get_frontend(f, 1);
else
- fe = videobuf_dvb_get_frontend(f, f->gate);
+ fe = vb2_dvb_get_frontend(f, f->gate);
if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
@@ -565,7 +608,7 @@ static const struct xc5000_config dvico_fusionhdtv7_tuner_config = {
static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
{
struct dvb_frontend *fe;
- struct videobuf_dvb_frontend *fe0 = NULL;
+ struct vb2_dvb_frontend *fe0 = NULL;
struct xc2028_ctrl ctl;
struct xc2028_config cfg = {
.i2c_adap = &dev->core->i2c_adap,
@@ -574,7 +617,7 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
};
/* Get the first frontend */
- fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+ fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
if (!fe0)
return -EINVAL;
@@ -611,10 +654,10 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
static int attach_xc4000(struct cx8802_dev *dev, struct xc4000_config *cfg)
{
struct dvb_frontend *fe;
- struct videobuf_dvb_frontend *fe0 = NULL;
+ struct vb2_dvb_frontend *fe0 = NULL;
/* Get the first frontend */
- fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+ fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
if (!fe0)
return -EINVAL;
@@ -745,7 +788,7 @@ static const struct stv0288_config tevii_tuner_earda_config = {
static int cx8802_alloc_frontends(struct cx8802_dev *dev)
{
struct cx88_core *core = dev->core;
- struct videobuf_dvb_frontend *fe = NULL;
+ struct vb2_dvb_frontend *fe = NULL;
int i;
mutex_init(&dev->frontends.lock);
@@ -757,10 +800,10 @@ static int cx8802_alloc_frontends(struct cx8802_dev *dev)
printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
core->board.num_frontends);
for (i = 1; i <= core->board.num_frontends; i++) {
- fe = videobuf_dvb_alloc_frontend(&dev->frontends, i);
+ fe = vb2_dvb_alloc_frontend(&dev->frontends, i);
if (!fe) {
printk(KERN_ERR "%s() failed to alloc\n", __func__);
- videobuf_dvb_dealloc_frontends(&dev->frontends);
+ vb2_dvb_dealloc_frontends(&dev->frontends);
return -ENOMEM;
}
}
@@ -958,7 +1001,7 @@ static const struct stv0299_config samsung_stv0299_config = {
static int dvb_register(struct cx8802_dev *dev)
{
struct cx88_core *core = dev->core;
- struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
+ struct vb2_dvb_frontend *fe0, *fe1 = NULL;
int mfe_shared = 0; /* bus not shared by default */
int res = -EINVAL;
@@ -968,7 +1011,7 @@ static int dvb_register(struct cx8802_dev *dev)
}
/* Get the first frontend */
- fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+ fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
if (!fe0)
goto frontend_detach;
@@ -1046,7 +1089,7 @@ static int dvb_register(struct cx8802_dev *dev)
goto frontend_detach;
}
/* MFE frontend 2 */
- fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
+ fe1 = vb2_dvb_get_frontend(&dev->frontends, 2);
if (!fe1)
goto frontend_detach;
/* DVB-T init */
@@ -1415,7 +1458,7 @@ static int dvb_register(struct cx8802_dev *dev)
goto frontend_detach;
}
/* MFE frontend 2 */
- fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
+ fe1 = vb2_dvb_get_frontend(&dev->frontends, 2);
if (!fe1)
goto frontend_detach;
/* DVB-T Init */
@@ -1594,7 +1637,7 @@ static int dvb_register(struct cx8802_dev *dev)
call_all(core, core, s_power, 0);
/* register everything */
- res = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
+ res = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
&dev->pci->dev, adapter_nr, mfe_shared);
if (res)
goto frontend_detach;
@@ -1602,7 +1645,7 @@ static int dvb_register(struct cx8802_dev *dev)
frontend_detach:
core->gate_ctrl = NULL;
- videobuf_dvb_dealloc_frontends(&dev->frontends);
+ vb2_dvb_dealloc_frontends(&dev->frontends);
return res;
}
@@ -1697,7 +1740,7 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
struct cx88_core *core = drv->core;
struct cx8802_dev *dev = drv->core->dvbdev;
int err;
- struct videobuf_dvb_frontend *fe;
+ struct vb2_dvb_frontend *fe;
int i;
dprintk( 1, "%s\n", __func__);
@@ -1726,19 +1769,31 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
err = -ENODEV;
for (i = 1; i <= core->board.num_frontends; i++) {
- fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
+ struct vb2_queue *q;
+
+ fe = vb2_dvb_get_frontend(&core->dvbdev->frontends, i);
if (fe == NULL) {
printk(KERN_ERR "%s() failed to get frontend(%d)\n",
__func__, i);
goto fail_probe;
}
- videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
- &dev->pci->dev, &dev->slock,
- V4L2_BUF_TYPE_VIDEO_CAPTURE,
- V4L2_FIELD_TOP,
- sizeof(struct cx88_buffer),
- dev, NULL);
- /* init struct videobuf_dvb */
+ q = &fe->dvb.dvbq;
+ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
+ q->gfp_flags = GFP_DMA32;
+ q->min_buffers_needed = 2;
+ q->drv_priv = dev;
+ q->buf_struct_size = sizeof(struct cx88_buffer);
+ q->ops = &dvb_qops;
+ q->mem_ops = &vb2_dma_sg_memops;
+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ q->lock = &core->lock;
+
+ err = vb2_queue_init(q);
+ if (err < 0)
+ goto fail_probe;
+
+ /* init struct vb2_dvb */
fe->dvb.name = dev->core->name;
}
@@ -1749,7 +1804,7 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
core->name, err);
return err;
fail_probe:
- videobuf_dvb_dealloc_frontends(&core->dvbdev->frontends);
+ vb2_dvb_dealloc_frontends(&core->dvbdev->frontends);
fail_core:
return err;
}
@@ -1761,7 +1816,7 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv)
dprintk( 1, "%s\n", __func__);
- videobuf_dvb_unregister_bus(&dev->frontends);
+ vb2_dvb_unregister_bus(&dev->frontends);
vp3054_i2c_remove(dev);
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
index 5f59901..7986ee0 100644
--- a/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -86,21 +86,21 @@ static LIST_HEAD(cx8802_devlist);
static DEFINE_MUTEX(cx8802_mutex);
/* ------------------------------------------------------------------ */
-static int cx8802_start_dma(struct cx8802_dev *dev,
+int cx8802_start_dma(struct cx8802_dev *dev,
struct cx88_dmaqueue *q,
struct cx88_buffer *buf)
{
struct cx88_core *core = dev->core;
dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n",
- buf->vb.width, buf->vb.height, buf->vb.field);
+ dev->width, dev->height, dev->field);
/* setup fifo + format */
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
dev->ts_packet_size, buf->risc.dma);
/* write TS length to chip */
- cx_write(MO_TS_LNGTH, buf->vb.width);
+ cx_write(MO_TS_LNGTH, dev->ts_packet_size);
/* FIXME: this needs a review.
* also: move to cx88-blackbird + cx88-dvb source files? */
@@ -212,47 +212,35 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
if (list_empty(&q->active))
return 0;
- buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+ buf = list_entry(q->active.next, struct cx88_buffer, list);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
- buf, buf->vb.i);
+ buf, buf->vb.v4l2_buf.index);
cx8802_start_dma(dev, q, buf);
- list_for_each_entry(buf, &q->active, vb.queue)
+ list_for_each_entry(buf, &q->active, list)
buf->count = q->count++;
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
return 0;
}
/* ------------------------------------------------------------------ */
-int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
+int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
struct cx88_buffer *buf, enum v4l2_field field)
{
int size = dev->ts_packet_size * dev->ts_packet_count;
- struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0);
int rc;
- dprintk(1, "%s: %p\n", __func__, buf);
- if (0 != buf->vb.baddr && buf->vb.bsize < size)
+ if (vb2_plane_size(&buf->vb, 0) < size)
return -EINVAL;
+ vb2_set_plane_payload(&buf->vb, 0, size);
- if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
- buf->vb.width = dev->ts_packet_size;
- buf->vb.height = dev->ts_packet_count;
- buf->vb.size = size;
- buf->vb.field = field /*V4L2_FIELD_TOP*/;
-
- if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
- goto fail;
- cx88_risc_databuffer(dev->pci, &buf->risc,
- dma->sglist,
- buf->vb.width, buf->vb.height, 0);
- }
- buf->vb.state = VIDEOBUF_PREPARED;
- return 0;
+ rc = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
+ if (!rc)
+ return -EIO;
- fail:
- cx88_free_buffer(q,buf);
- return rc;
+ cx88_risc_databuffer(dev->pci, &buf->risc, sgt->sgl,
+ dev->ts_packet_size, dev->ts_packet_count, 0);
+ return 0;
}
void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
@@ -261,35 +249,33 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
struct cx88_dmaqueue *cx88q = &dev->mpegq;
dprintk( 1, "cx8802_buf_queue\n" );
- /* add jump to stopper */
- buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
- buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
+ /* add jump to start */
+ buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8);
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8);
if (list_empty(&cx88q->active)) {
dprintk( 1, "queue is empty - first active\n" );
- list_add_tail(&buf->vb.queue,&cx88q->active);
- cx8802_start_dma(dev, cx88q, buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ list_add_tail(&buf->list, &cx88q->active);
buf->count = cx88q->count++;
- mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(1,"[%p/%d] %s - first active\n",
- buf, buf->vb.i, __func__);
+ buf, buf->vb.v4l2_buf.index, __func__);
} else {
+ buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
dprintk( 1, "queue is not empty - append to active\n" );
- prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue);
- list_add_tail(&buf->vb.queue,&cx88q->active);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ prev = list_entry(cx88q->active.prev, struct cx88_buffer, list);
+ list_add_tail(&buf->list, &cx88q->active);
buf->count = cx88q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk( 1, "[%p/%d] %s - append to active\n",
- buf, buf->vb.i, __func__);
+ buf, buf->vb.v4l2_buf.index, __func__);
}
}
/* ----------------------------------------------------------- */
-static void do_cancel_buffers(struct cx8802_dev *dev, const char *reason, int restart)
+static void do_cancel_buffers(struct cx8802_dev *dev)
{
struct cx88_dmaqueue *q = &dev->mpegq;
struct cx88_buffer *buf;
@@ -297,41 +283,18 @@ static void do_cancel_buffers(struct cx8802_dev *dev, const char *reason, int re
spin_lock_irqsave(&dev->slock,flags);
while (!list_empty(&q->active)) {
- buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
- list_del(&buf->vb.queue);
- buf->vb.state = VIDEOBUF_ERROR;
- wake_up(&buf->vb.done);
- dprintk(1,"[%p/%d] %s - dma=0x%08lx\n",
- buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
- }
- if (restart)
- {
- dprintk(1, "restarting queue\n" );
- cx8802_restart_queue(dev,q);
+ buf = list_entry(q->active.next, struct cx88_buffer, list);
+ list_del(&buf->list);
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&dev->slock,flags);
}
void cx8802_cancel_buffers(struct cx8802_dev *dev)
{
- struct cx88_dmaqueue *q = &dev->mpegq;
-
dprintk( 1, "cx8802_cancel_buffers" );
- del_timer_sync(&q->timeout);
- cx8802_stop_dma(dev);
- do_cancel_buffers(dev,"cancel",0);
-}
-
-static void cx8802_timeout(unsigned long data)
-{
- struct cx8802_dev *dev = (struct cx8802_dev*)data;
-
- dprintk(1, "%s\n",__func__);
-
- if (debug)
- cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
cx8802_stop_dma(dev);
- do_cancel_buffers(dev,"timeout",1);
+ do_cancel_buffers(dev);
}
static const char * cx88_mpeg_irqs[32] = {
@@ -377,19 +340,11 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev)
spin_unlock(&dev->slock);
}
- /* risc2 y */
- if (status & 0x10) {
- spin_lock(&dev->slock);
- cx8802_restart_queue(dev,&dev->mpegq);
- spin_unlock(&dev->slock);
- }
-
/* other general errors */
if (status & 0x1f0100) {
dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 );
spin_lock(&dev->slock);
cx8802_stop_dma(dev);
- cx8802_restart_queue(dev,&dev->mpegq);
spin_unlock(&dev->slock);
}
}
@@ -456,11 +411,6 @@ static int cx8802_init_common(struct cx8802_dev *dev)
/* init dma queue */
INIT_LIST_HEAD(&dev->mpegq.active);
- dev->mpegq.timeout.function = cx8802_timeout;
- dev->mpegq.timeout.data = (unsigned long)dev;
- init_timer(&dev->mpegq.timeout);
- cx88_risc_stopper(dev->pci,&dev->mpegq.stopper,
- MO_TS_DMACNTRL,0x11,0x00);
/* get irq */
err = request_irq(dev->pci->irq, cx8802_irq,
@@ -485,9 +435,6 @@ static void cx8802_fini_common(struct cx8802_dev *dev)
/* unregister stuff */
free_irq(dev->pci->irq, dev);
-
- /* free memory */
- btcx_riscmem_free(dev->pci,&dev->mpegq.stopper);
}
/* ----------------------------------------------------------- */
@@ -504,7 +451,6 @@ static int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
dprintk( 2, "suspend\n" );
printk("%s: suspend mpeg\n", core->name);
cx8802_stop_dma(dev);
- del_timer(&dev->mpegq.timeout);
}
spin_unlock_irqrestore(&dev->slock, flags);
@@ -872,6 +818,7 @@ module_pci_driver(cx8802_pci_driver);
EXPORT_SYMBOL(cx8802_buf_prepare);
EXPORT_SYMBOL(cx8802_buf_queue);
EXPORT_SYMBOL(cx8802_cancel_buffers);
+EXPORT_SYMBOL(cx8802_start_dma);
EXPORT_SYMBOL(cx8802_register_driver);
EXPORT_SYMBOL(cx8802_unregister_driver);
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
index f8f8389..26a1533 100644
--- a/drivers/media/pci/cx88/cx88-vbi.c
+++ b/drivers/media/pci/cx88/cx88-vbi.c
@@ -6,10 +6,6 @@
#include "cx88.h"
-static unsigned int vbibufs = 4;
-module_param(vbibufs,int,0644);
-MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");
-
static unsigned int vbi_debug;
module_param(vbi_debug,int,0644);
MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
@@ -22,8 +18,7 @@ MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
int cx8800_vbi_fmt (struct file *file, void *priv,
struct v4l2_format *f)
{
- struct cx8800_fh *fh = priv;
- struct cx8800_dev *dev = fh->dev;
+ struct cx8800_dev *dev = video_drvdata(file);
f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
@@ -54,7 +49,7 @@ static int cx8800_start_vbi_dma(struct cx8800_dev *dev,
/* setup fifo + format */
cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH24],
- buf->vb.width, buf->risc.dma);
+ VBI_LINE_LENGTH, buf->risc.dma);
cx_write(MO_VBOS_CONTROL, ( (1 << 18) | // comb filter delay fixup
(1 << 15) | // enable vbi capture
@@ -78,7 +73,7 @@ static int cx8800_start_vbi_dma(struct cx8800_dev *dev,
return 0;
}
-int cx8800_stop_vbi_dma(struct cx8800_dev *dev)
+void cx8800_stop_vbi_dma(struct cx8800_dev *dev)
{
struct cx88_core *core = dev->core;
@@ -91,7 +86,6 @@ int cx8800_stop_vbi_dma(struct cx8800_dev *dev)
/* disable irqs */
cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
cx_clear(MO_VID_INTMSK, 0x0f0088);
- return 0;
}
int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
@@ -102,144 +96,133 @@ int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
if (list_empty(&q->active))
return 0;
- buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+ buf = list_entry(q->active.next, struct cx88_buffer, list);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
- buf, buf->vb.i);
+ buf, buf->vb.v4l2_buf.index);
cx8800_start_vbi_dma(dev, q, buf);
- list_for_each_entry(buf, &q->active, vb.queue)
+ list_for_each_entry(buf, &q->active, list)
buf->count = q->count++;
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
return 0;
}
-void cx8800_vbi_timeout(unsigned long data)
-{
- struct cx8800_dev *dev = (struct cx8800_dev*)data;
- struct cx88_core *core = dev->core;
- struct cx88_dmaqueue *q = &dev->vbiq;
- struct cx88_buffer *buf;
- unsigned long flags;
-
- cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH24]);
-
- cx_clear(MO_VID_DMACNTRL, 0x88);
- cx_clear(VID_CAPTURE_CONTROL, 0x18);
-
- spin_lock_irqsave(&dev->slock,flags);
- while (!list_empty(&q->active)) {
- buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
- list_del(&buf->vb.queue);
- buf->vb.state = VIDEOBUF_ERROR;
- wake_up(&buf->vb.done);
- printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->core->name,
- buf, buf->vb.i, (unsigned long)buf->risc.dma);
- }
- cx8800_restart_vbi_queue(dev,q);
- spin_unlock_irqrestore(&dev->slock,flags);
-}
-
/* ------------------------------------------------------------------ */
-static int
-vbi_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 *num_buffers, unsigned int *num_planes,
+ unsigned int sizes[], void *alloc_ctxs[])
{
- *size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
- if (0 == *count)
- *count = vbibufs;
- if (*count < 2)
- *count = 2;
- if (*count > 32)
- *count = 32;
+ *num_planes = 1;
+ sizes[0] = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
return 0;
}
-static int
-vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
- enum v4l2_field field)
+
+static int buffer_prepare(struct vb2_buffer *vb)
{
- struct cx8800_fh *fh = q->priv_data;
- struct cx8800_dev *dev = fh->dev;
- struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
+ struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
+ struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
unsigned int size;
int rc;
size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
- if (0 != buf->vb.baddr && buf->vb.bsize < size)
+ if (vb2_plane_size(vb, 0) < size)
return -EINVAL;
+ vb2_set_plane_payload(vb, 0, size);
- if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
- struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
- buf->vb.width = VBI_LINE_LENGTH;
- buf->vb.height = VBI_LINE_COUNT;
- buf->vb.size = size;
- buf->vb.field = V4L2_FIELD_SEQ_TB;
-
- if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
- goto fail;
- cx88_risc_buffer(dev->pci, &buf->risc,
- dma->sglist,
- 0, buf->vb.width * buf->vb.height,
- buf->vb.width, 0,
- buf->vb.height);
- }
- buf->vb.state = VIDEOBUF_PREPARED;
+ rc = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
+ if (!rc)
+ return -EIO;
+
+ cx88_risc_buffer(dev->pci, &buf->risc, sgt->sgl,
+ 0, VBI_LINE_LENGTH * VBI_LINE_COUNT,
+ VBI_LINE_LENGTH, 0,
+ VBI_LINE_COUNT);
return 0;
+}
- fail:
- cx88_free_buffer(q,buf);
- return rc;
+static void buffer_finish(struct vb2_buffer *vb)
+{
+ struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
+ struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
+
+ cx88_free_buffer(vb->vb2_queue, buf);
+
+ dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
}
-static void
-vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+static void buffer_queue(struct vb2_buffer *vb)
{
- struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
+ struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
+ struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
struct cx88_buffer *prev;
- struct cx8800_fh *fh = vq->priv_data;
- struct cx8800_dev *dev = fh->dev;
struct cx88_dmaqueue *q = &dev->vbiq;
- /* add jump to stopper */
- buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
- buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+ /* add jump to start */
+ buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8);
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8);
if (list_empty(&q->active)) {
- list_add_tail(&buf->vb.queue,&q->active);
+ list_add_tail(&buf->list, &q->active);
cx8800_start_vbi_dma(dev, q, buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
buf->count = q->count++;
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(2,"[%p/%d] vbi_queue - first active\n",
- buf, buf->vb.i);
+ buf, buf->vb.v4l2_buf.index);
} else {
- prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
- list_add_tail(&buf->vb.queue,&q->active);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
+ prev = list_entry(q->active.prev, struct cx88_buffer, list);
+ list_add_tail(&buf->list, &q->active);
buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(2,"[%p/%d] buffer_queue - append to active\n",
- buf, buf->vb.i);
+ buf, buf->vb.v4l2_buf.index);
}
}
-static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+static int start_streaming(struct vb2_queue *q, unsigned int count)
{
- struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
+ struct cx8800_dev *dev = q->drv_priv;
+ struct cx88_dmaqueue *dmaq = &dev->vbiq;
+ struct cx88_buffer *buf = list_entry(dmaq->active.next,
+ struct cx88_buffer, list);
- cx88_free_buffer(q,buf);
+ cx8800_start_vbi_dma(dev, dmaq, buf);
+ return 0;
}
-const struct videobuf_queue_ops cx8800_vbi_qops = {
- .buf_setup = vbi_setup,
- .buf_prepare = vbi_prepare,
- .buf_queue = vbi_queue,
- .buf_release = vbi_release,
-};
+static void stop_streaming(struct vb2_queue *q)
+{
+ struct cx8800_dev *dev = q->drv_priv;
+ struct cx88_core *core = dev->core;
+ struct cx88_dmaqueue *dmaq = &dev->vbiq;
+ unsigned long flags;
-/* ------------------------------------------------------------------ */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
+ cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
+
+ cx_clear(MO_VID_DMACNTRL, 0x11);
+ cx_clear(VID_CAPTURE_CONTROL, 0x06);
+ cx8800_stop_vbi_dma(dev);
+ spin_lock_irqsave(&dev->slock, flags);
+ while (!list_empty(&dmaq->active)) {
+ struct cx88_buffer *buf = list_entry(dmaq->active.next,
+ struct cx88_buffer, list);
+
+ list_del(&buf->list);
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ }
+ spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+const struct vb2_ops cx8800_vbi_qops = {
+ .queue_setup = queue_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_finish = buffer_finish,
+ .buf_queue = buffer_queue,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .start_streaming = start_streaming,
+ .stop_streaming = stop_streaming,
+};
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index 10fea4d..9887da5 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -70,10 +70,6 @@ static unsigned int irq_debug;
module_param(irq_debug,int,0644);
MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
-static unsigned int vid_limit = 16;
-module_param(vid_limit,int,0644);
-MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
-
#define dprintk(level,fmt, arg...) if (video_debug >= level) \
printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
@@ -297,56 +293,6 @@ enum {
CX8800_AUD_CTLS = ARRAY_SIZE(cx8800_aud_ctls),
};
-/* ------------------------------------------------------------------- */
-/* resource management */
-
-static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bit)
-{
- struct cx88_core *core = dev->core;
- if (fh->resources & bit)
- /* have it already allocated */
- return 1;
-
- /* is it free? */
- mutex_lock(&core->lock);
- if (dev->resources & bit) {
- /* no, someone else uses it */
- mutex_unlock(&core->lock);
- return 0;
- }
- /* it's free, grab it */
- fh->resources |= bit;
- dev->resources |= bit;
- dprintk(1,"res: get %d\n",bit);
- mutex_unlock(&core->lock);
- return 1;
-}
-
-static
-int res_check(struct cx8800_fh *fh, unsigned int bit)
-{
- return (fh->resources & bit);
-}
-
-static
-int res_locked(struct cx8800_dev *dev, unsigned int bit)
-{
- return (dev->resources & bit);
-}
-
-static
-void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits)
-{
- struct cx88_core *core = dev->core;
- BUG_ON((fh->resources & bits) != bits);
-
- mutex_lock(&core->lock);
- fh->resources &= ~bits;
- dev->resources &= ~bits;
- dprintk(1,"res: put %d\n",bits);
- mutex_unlock(&core->lock);
-}
-
/* ------------------------------------------------------------------ */
int cx88_video_mux(struct cx88_core *core, unsigned int input)
@@ -419,7 +365,7 @@ static int start_video_dma(struct cx8800_dev *dev,
/* setup fifo + format */
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21],
buf->bpl, buf->risc.dma);
- cx88_set_scale(core, buf->vb.width, buf->vb.height, buf->vb.field);
+ cx88_set_scale(core, dev->width, dev->height, dev->field);
cx_write(MO_COLOR_CTRL, dev->fmt->cxformat | ColorFormatGamma);
/* reset counter */
@@ -473,376 +419,206 @@ static int restart_video_queue(struct cx8800_dev *dev,
struct cx88_buffer *buf;
if (!list_empty(&q->active)) {
- buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+ buf = list_entry(q->active.next, struct cx88_buffer, list);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
- buf, buf->vb.i);
+ buf, buf->vb.v4l2_buf.index);
start_video_dma(dev, q, buf);
- list_for_each_entry(buf, &q->active, vb.queue)
+ list_for_each_entry(buf, &q->active, list)
buf->count = q->count++;
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
}
return 0;
}
/* ------------------------------------------------------------------ */
-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 *num_buffers, unsigned int *num_planes,
+ unsigned int sizes[], void *alloc_ctxs[])
{
- struct cx8800_fh *fh = q->priv_data;
- struct cx8800_dev *dev = fh->dev;
-
- *size = dev->fmt->depth * dev->width * dev->height >> 3;
- if (0 == *count)
- *count = 32;
- if (*size * *count > vid_limit * 1024 * 1024)
- *count = (vid_limit * 1024 * 1024) / *size;
+ struct cx8800_dev *dev = q->drv_priv;
+
+ *num_planes = 1;
+ sizes[0] = (dev->fmt->depth * dev->width * dev->height) >> 3;
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 *vb)
{
- struct cx8800_fh *fh = q->priv_data;
- struct cx8800_dev *dev = fh->dev;
+ struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
struct cx88_core *core = dev->core;
- struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
- struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+ struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
int rc;
- BUG_ON(NULL == dev->fmt);
- if (dev->width < 48 || dev->width > norm_maxw(core->tvnorm) ||
- dev->height < 32 || dev->height > norm_maxh(core->tvnorm))
- return -EINVAL;
- buf->vb.size = (dev->width * dev->height * dev->fmt->depth) >> 3;
- if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
+ buf->bpl = dev->width * dev->fmt->depth >> 3;
+
+ if (vb2_plane_size(vb, 0) < dev->height * buf->bpl)
return -EINVAL;
+ vb2_set_plane_payload(vb, 0, dev->height * buf->bpl);
- buf->vb.width = dev->width;
- buf->vb.height = dev->height;
- buf->vb.field = field;
- if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
- if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
- goto fail;
- }
+ rc = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
+ if (!rc)
+ return -EIO;
- buf->bpl = buf->vb.width * dev->fmt->depth >> 3;
- switch (buf->vb.field) {
+ switch (dev->field) {
case V4L2_FIELD_TOP:
cx88_risc_buffer(dev->pci, &buf->risc,
- dma->sglist, 0, UNSET,
- buf->bpl, 0, buf->vb.height);
+ sgt->sgl, 0, UNSET,
+ buf->bpl, 0, dev->height);
break;
case V4L2_FIELD_BOTTOM:
cx88_risc_buffer(dev->pci, &buf->risc,
- dma->sglist, UNSET, 0,
- buf->bpl, 0, buf->vb.height);
+ sgt->sgl, UNSET, 0,
+ buf->bpl, 0, dev->height);
break;
case V4L2_FIELD_SEQ_TB:
cx88_risc_buffer(dev->pci, &buf->risc,
- dma->sglist,
- 0, buf->bpl * (buf->vb.height >> 1),
+ sgt->sgl,
+ 0, buf->bpl * (dev->height >> 1),
buf->bpl, 0,
- buf->vb.height >> 1);
+ dev->height >> 1);
break;
case V4L2_FIELD_SEQ_BT:
cx88_risc_buffer(dev->pci, &buf->risc,
- dma->sglist,
- buf->bpl * (buf->vb.height >> 1), 0,
+ sgt->sgl,
+ buf->bpl * (dev->height >> 1), 0,
buf->bpl, 0,
- buf->vb.height >> 1);
+ dev->height >> 1);
break;
case V4L2_FIELD_INTERLACED:
default:
cx88_risc_buffer(dev->pci, &buf->risc,
- dma->sglist, 0, buf->bpl,
+ sgt->sgl, 0, buf->bpl,
buf->bpl, buf->bpl,
- buf->vb.height >> 1);
+ dev->height >> 1);
break;
}
dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
- buf, buf->vb.i,
+ buf, buf->vb.v4l2_buf.index,
dev->width, dev->height, dev->fmt->depth, dev->fmt->name,
(unsigned long)buf->risc.dma);
-
- buf->vb.state = VIDEOBUF_PREPARED;
return 0;
+}
+
+static void buffer_finish(struct vb2_buffer *vb)
+{
+ struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
+ struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
+
+ cx88_free_buffer(vb->vb2_queue, buf);
- fail:
- cx88_free_buffer(q,buf);
- return rc;
+ dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
}
-static void
-buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+static void buffer_queue(struct vb2_buffer *vb)
{
- struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
+ struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
+ struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
struct cx88_buffer *prev;
- struct cx8800_fh *fh = vq->priv_data;
- struct cx8800_dev *dev = fh->dev;
struct cx88_core *core = dev->core;
struct cx88_dmaqueue *q = &dev->vidq;
- /* add jump to stopper */
- buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
- buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+ /* add jump to start */
+ buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8);
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8);
if (list_empty(&q->active)) {
- list_add_tail(&buf->vb.queue,&q->active);
+ list_add_tail(&buf->list, &q->active);
start_video_dma(dev, q, buf);
- buf->vb.state = VIDEOBUF_ACTIVE;
buf->count = q->count++;
- mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(2,"[%p/%d] buffer_queue - first active\n",
- buf, buf->vb.i);
+ buf, buf->vb.v4l2_buf.index);
} else {
- prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
- list_add_tail(&buf->vb.queue, &q->active);
- buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
+ prev = list_entry(q->active.prev, struct cx88_buffer, list);
+ list_add_tail(&buf->list, &q->active);
buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(2, "[%p/%d] buffer_queue - append to active\n",
- buf, buf->vb.i);
+ buf, buf->vb.v4l2_buf.index);
}
}
-static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+static int start_streaming(struct vb2_queue *q, unsigned int count)
{
- struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
+ struct cx8800_dev *dev = q->drv_priv;
+ struct cx88_dmaqueue *dmaq = &dev->vidq;
+ struct cx88_buffer *buf = list_entry(dmaq->active.next,
+ struct cx88_buffer, list);
- cx88_free_buffer(q,buf);
+ start_video_dma(dev, dmaq, buf);
+ return 0;
}
-static const struct videobuf_queue_ops cx8800_video_qops = {
- .buf_setup = buffer_setup,
- .buf_prepare = buffer_prepare,
- .buf_queue = buffer_queue,
- .buf_release = buffer_release,
-};
-
-/* ------------------------------------------------------------------ */
-
+static void stop_streaming(struct vb2_queue *q)
+{
+ struct cx8800_dev *dev = q->drv_priv;
+ struct cx88_core *core = dev->core;
+ struct cx88_dmaqueue *dmaq = &dev->vidq;
+ unsigned long flags;
-/* ------------------------------------------------------------------ */
+ cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
-static struct videobuf_queue *get_queue(struct file *file)
-{
- struct video_device *vdev = video_devdata(file);
- struct cx8800_fh *fh = file->private_data;
+ cx_clear(MO_VID_DMACNTRL, 0x11);
+ cx_clear(VID_CAPTURE_CONTROL, 0x06);
+ spin_lock_irqsave(&dev->slock, flags);
+ while (!list_empty(&dmaq->active)) {
+ struct cx88_buffer *buf = list_entry(dmaq->active.next,
+ struct cx88_buffer, list);
- switch (vdev->vfl_type) {
- case VFL_TYPE_GRABBER:
- return &fh->vidq;
- case VFL_TYPE_VBI:
- return &fh->vbiq;
- default:
- BUG();
- return NULL;
+ list_del(&buf->list);
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
}
+ spin_unlock_irqrestore(&dev->slock, flags);
}
-static int get_resource(struct file *file)
-{
- struct video_device *vdev = video_devdata(file);
+static struct vb2_ops cx8800_video_qops = {
+ .queue_setup = queue_setup,
+ .buf_prepare = buffer_prepare,
+ .buf_finish = buffer_finish,
+ .buf_queue = buffer_queue,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .start_streaming = start_streaming,
+ .stop_streaming = stop_streaming,
+};
- switch (vdev->vfl_type) {
- case VFL_TYPE_GRABBER:
- return RESOURCE_VIDEO;
- case VFL_TYPE_VBI:
- return RESOURCE_VBI;
- default:
- BUG();
- return 0;
- }
-}
+/* ------------------------------------------------------------------ */
-static int video_open(struct file *file)
+static int radio_open(struct file *file)
{
- struct video_device *vdev = video_devdata(file);
struct cx8800_dev *dev = video_drvdata(file);
struct cx88_core *core = dev->core;
- struct cx8800_fh *fh;
- enum v4l2_buf_type type = 0;
- int radio = 0;
-
- switch (vdev->vfl_type) {
- case VFL_TYPE_GRABBER:
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- break;
- case VFL_TYPE_VBI:
- type = V4L2_BUF_TYPE_VBI_CAPTURE;
- break;
- case VFL_TYPE_RADIO:
- radio = 1;
- break;
- }
-
- dprintk(1, "open dev=%s radio=%d type=%s\n",
- video_device_node_name(vdev), radio, v4l2_type_names[type]);
+ int ret = v4l2_fh_open(file);
- /* allocate + initialize per filehandle data */
- fh = kzalloc(sizeof(*fh),GFP_KERNEL);
- if (unlikely(!fh))
- return -ENOMEM;
-
- v4l2_fh_init(&fh->fh, vdev);
- file->private_data = fh;
- fh->dev = dev;
-
- mutex_lock(&core->lock);
+ if (ret)
+ return ret;
- videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops,
- &dev->pci->dev, &dev->slock,
- V4L2_BUF_TYPE_VIDEO_CAPTURE,
- V4L2_FIELD_INTERLACED,
- sizeof(struct cx88_buffer),
- fh, NULL);
- videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops,
- &dev->pci->dev, &dev->slock,
- V4L2_BUF_TYPE_VBI_CAPTURE,
- V4L2_FIELD_SEQ_TB,
- sizeof(struct cx88_buffer),
- fh, NULL);
-
- if (vdev->vfl_type == VFL_TYPE_RADIO) {
- dprintk(1,"video_open: setting radio device\n");
- cx_write(MO_GP3_IO, core->board.radio.gpio3);
- cx_write(MO_GP0_IO, core->board.radio.gpio0);
- cx_write(MO_GP1_IO, core->board.radio.gpio1);
- cx_write(MO_GP2_IO, core->board.radio.gpio2);
- if (core->board.radio.audioroute) {
- if (core->sd_wm8775) {
- call_all(core, audio, s_routing,
+ cx_write(MO_GP3_IO, core->board.radio.gpio3);
+ cx_write(MO_GP0_IO, core->board.radio.gpio0);
+ cx_write(MO_GP1_IO, core->board.radio.gpio1);
+ cx_write(MO_GP2_IO, core->board.radio.gpio2);
+ if (core->board.radio.audioroute) {
+ if (core->sd_wm8775) {
+ call_all(core, audio, s_routing,
core->board.radio.audioroute, 0, 0);
- }
- /* "I2S ADC mode" */
- core->tvaudio = WW_I2SADC;
- cx88_set_tvaudio(core);
- } else {
- /* FM Mode */
- core->tvaudio = WW_FM;
- cx88_set_tvaudio(core);
- cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
}
- call_all(core, tuner, s_radio);
- }
-
- core->users++;
- mutex_unlock(&core->lock);
- v4l2_fh_add(&fh->fh);
-
- return 0;
-}
-
-static ssize_t
-video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
-{
- struct video_device *vdev = video_devdata(file);
- struct cx8800_fh *fh = file->private_data;
-
- switch (vdev->vfl_type) {
- case VFL_TYPE_GRABBER:
- if (res_locked(fh->dev,RESOURCE_VIDEO))
- return -EBUSY;
- return videobuf_read_one(&fh->vidq, data, count, ppos,
- file->f_flags & O_NONBLOCK);
- case VFL_TYPE_VBI:
- if (!res_get(fh->dev,fh,RESOURCE_VBI))
- return -EBUSY;
- return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1,
- file->f_flags & O_NONBLOCK);
- default:
- BUG();
- return 0;
- }
-}
-
-static unsigned int
-video_poll(struct file *file, struct poll_table_struct *wait)
-{
- struct video_device *vdev = video_devdata(file);
- struct cx8800_fh *fh = file->private_data;
- struct cx88_buffer *buf;
- unsigned int rc = v4l2_ctrl_poll(file, wait);
-
- if (vdev->vfl_type == VFL_TYPE_VBI) {
- if (!res_get(fh->dev,fh,RESOURCE_VBI))
- return rc | POLLERR;
- return rc | videobuf_poll_stream(file, &fh->vbiq, wait);
- }
- mutex_lock(&fh->vidq.vb_lock);
- if (res_check(fh,RESOURCE_VIDEO)) {
- /* streaming capture */
- if (list_empty(&fh->vidq.stream))
- goto done;
- buf = list_entry(fh->vidq.stream.next,struct cx88_buffer,vb.stream);
+ /* "I2S ADC mode" */
+ core->tvaudio = WW_I2SADC;
+ cx88_set_tvaudio(core);
} else {
- /* read() capture */
- buf = (struct cx88_buffer*)fh->vidq.read_buf;
- if (NULL == buf)
- goto done;
+ /* FM Mode */
+ core->tvaudio = WW_FM;
+ cx88_set_tvaudio(core);
+ cx88_set_stereo(core, V4L2_TUNER_MODE_STEREO, 1);
}
- poll_wait(file, &buf->vb.done, wait);
- if (buf->vb.state == VIDEOBUF_DONE ||
- buf->vb.state == VIDEOBUF_ERROR)
- rc |= POLLIN|POLLRDNORM;
-done:
- mutex_unlock(&fh->vidq.vb_lock);
- return rc;
-}
-
-static int video_release(struct file *file)
-{
- struct cx8800_fh *fh = file->private_data;
- struct cx8800_dev *dev = fh->dev;
-
- /* turn off overlay */
- if (res_check(fh, RESOURCE_OVERLAY)) {
- /* FIXME */
- res_free(dev,fh,RESOURCE_OVERLAY);
- }
-
- /* stop video capture */
- if (res_check(fh, RESOURCE_VIDEO)) {
- videobuf_queue_cancel(&fh->vidq);
- res_free(dev,fh,RESOURCE_VIDEO);
- }
- if (fh->vidq.read_buf) {
- buffer_release(&fh->vidq,fh->vidq.read_buf);
- kfree(fh->vidq.read_buf);
- }
-
- /* stop vbi capture */
- if (res_check(fh, RESOURCE_VBI)) {
- videobuf_stop(&fh->vbiq);
- res_free(dev,fh,RESOURCE_VBI);
- }
-
- videobuf_mmap_free(&fh->vidq);
- videobuf_mmap_free(&fh->vbiq);
-
- mutex_lock(&dev->core->lock);
- v4l2_fh_del(&fh->fh);
- v4l2_fh_exit(&fh->fh);
- file->private_data = NULL;
- kfree(fh);
-
- dev->core->users--;
- if (!dev->core->users)
- call_all(dev->core, core, s_power, 0);
- mutex_unlock(&dev->core->lock);
-
+ call_all(core, tuner, s_radio);
return 0;
}
-static int
-video_mmap(struct file *file, struct vm_area_struct * vma)
-{
- return videobuf_mmap_mapper(get_queue(file), vma);
-}
-
/* ------------------------------------------------------------------ */
/* VIDEO CTRL IOCTLS */
@@ -945,12 +721,11 @@ static int cx8800_s_aud_ctrl(struct v4l2_ctrl *ctrl)
static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct cx8800_fh *fh = priv;
- struct cx8800_dev *dev = fh->dev;
+ struct cx8800_dev *dev = video_drvdata(file);
f->fmt.pix.width = dev->width;
f->fmt.pix.height = dev->height;
- f->fmt.pix.field = fh->vidq.field;
+ f->fmt.pix.field = dev->field;
f->fmt.pix.pixelformat = dev->fmt->fourcc;
f->fmt.pix.bytesperline =
(f->fmt.pix.width * dev->fmt->depth) >> 3;
@@ -963,7 +738,8 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
+ struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
const struct cx8800_fmt *fmt;
enum v4l2_field field;
unsigned int maxw, maxh;
@@ -1007,8 +783,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct cx8800_fh *fh = priv;
- struct cx8800_dev *dev = fh->dev;
+ struct cx8800_dev *dev = video_drvdata(file);
int err = vidioc_try_fmt_vid_cap (file,priv,f);
if (0 != err)
@@ -1016,7 +791,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
dev->width = f->fmt.pix.width;
dev->height = f->fmt.pix.height;
- fh->vidq.field = f->fmt.pix.field;
+ dev->field = f->fmt.pix.field;
return 0;
}
@@ -1050,8 +825,8 @@ EXPORT_SYMBOL(cx88_querycap);
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- struct cx8800_dev *dev = ((struct cx8800_fh *)priv)->dev;
- struct cx88_core *core = dev->core;
+ struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
strcpy(cap->driver, "cx8800");
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
@@ -1071,64 +846,10 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
return 0;
}
-static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
-{
- return videobuf_reqbufs(get_queue(file), p);
-}
-
-static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
-{
- return videobuf_querybuf(get_queue(file), p);
-}
-
-static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
-{
- return videobuf_qbuf(get_queue(file), p);
-}
-
-static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
-{
- return videobuf_dqbuf(get_queue(file), p,
- file->f_flags & O_NONBLOCK);
-}
-
-static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
- struct video_device *vdev = video_devdata(file);
- struct cx8800_fh *fh = priv;
- struct cx8800_dev *dev = fh->dev;
-
- if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
- (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE))
- return -EINVAL;
-
- if (unlikely(!res_get(dev, fh, get_resource(file))))
- return -EBUSY;
- return videobuf_streamon(get_queue(file));
-}
-
-static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
- struct video_device *vdev = video_devdata(file);
- struct cx8800_fh *fh = priv;
- struct cx8800_dev *dev = fh->dev;
- int err, res;
-
- if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
- (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE))
- return -EINVAL;
-
- res = get_resource(file);
- err = videobuf_streamoff(get_queue(file));
- if (err < 0)
- return err;
- res_free(dev,fh,res);
- return 0;
-}
-
static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
{
- struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
+ struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
*tvnorm = core->tvnorm;
return 0;
@@ -1136,11 +857,10 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id tvnorms)
{
- struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
+ struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
- mutex_lock(&core->lock);
cx88_set_tvnorm(core, tvnorms);
- mutex_unlock(&core->lock);
return 0;
}
@@ -1179,13 +899,15 @@ EXPORT_SYMBOL(cx88_enum_input);
static int vidioc_enum_input (struct file *file, void *priv,
struct v4l2_input *i)
{
- struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
+ struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
return cx88_enum_input (core,i);
}
static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
{
- struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
+ struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
*i = core->input;
return 0;
@@ -1193,24 +915,24 @@ static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
{
- struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
+ struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
if (i >= 4)
return -EINVAL;
if (0 == INPUT(i).type)
return -EINVAL;
- mutex_lock(&core->lock);
cx88_newstation(core);
cx88_video_mux(core,i);
- mutex_unlock(&core->lock);
return 0;
}
static int vidioc_g_tuner (struct file *file, void *priv,
struct v4l2_tuner *t)
{
- struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
+ struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
u32 reg;
if (unlikely(UNSET == core->board.tuner_type))
@@ -1232,7 +954,8 @@ static int vidioc_g_tuner (struct file *file, void *priv,
static int vidioc_s_tuner (struct file *file, void *priv,
const struct v4l2_tuner *t)
{
- struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
+ struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
if (UNSET == core->board.tuner_type)
return -EINVAL;
@@ -1246,8 +969,8 @@ static int vidioc_s_tuner (struct file *file, void *priv,
static int vidioc_g_frequency (struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct cx8800_fh *fh = priv;
- struct cx88_core *core = fh->dev->core;
+ struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
if (unlikely(UNSET == core->board.tuner_type))
return -EINVAL;
@@ -1271,7 +994,6 @@ int cx88_set_freq (struct cx88_core *core,
if (unlikely(f->tuner != 0))
return -EINVAL;
- mutex_lock(&core->lock);
cx88_newstation(core);
call_all(core, tuner, s_frequency, f);
call_all(core, tuner, g_frequency, &new_freq);
@@ -1281,8 +1003,6 @@ int cx88_set_freq (struct cx88_core *core,
msleep (10);
cx88_set_tvaudio(core);
- mutex_unlock(&core->lock);
-
return 0;
}
EXPORT_SYMBOL(cx88_set_freq);
@@ -1290,8 +1010,8 @@ EXPORT_SYMBOL(cx88_set_freq);
static int vidioc_s_frequency (struct file *file, void *priv,
const struct v4l2_frequency *f)
{
- struct cx8800_fh *fh = priv;
- struct cx88_core *core = fh->dev->core;
+ struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
return cx88_set_freq(core, f);
}
@@ -1300,7 +1020,8 @@ static int vidioc_s_frequency (struct file *file, void *priv,
static int vidioc_g_register (struct file *file, void *fh,
struct v4l2_dbg_register *reg)
{
- struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
+ struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
/* cx2388x has a 24-bit register space */
reg->val = cx_read(reg->reg & 0xfffffc);
@@ -1311,7 +1032,8 @@ static int vidioc_g_register (struct file *file, void *fh,
static int vidioc_s_register (struct file *file, void *fh,
const struct v4l2_dbg_register *reg)
{
- struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
+ struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
cx_write(reg->reg & 0xfffffc, reg->val);
return 0;
@@ -1325,7 +1047,8 @@ static int vidioc_s_register (struct file *file, void *fh,
static int radio_g_tuner (struct file *file, void *priv,
struct v4l2_tuner *t)
{
- struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
+ struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
if (unlikely(t->index > 0))
return -EINVAL;
@@ -1339,7 +1062,8 @@ static int radio_g_tuner (struct file *file, void *priv,
static int radio_s_tuner (struct file *file, void *priv,
const struct v4l2_tuner *t)
{
- struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
+ struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
if (0 != t->index)
return -EINVAL;
@@ -1350,32 +1074,6 @@ static int radio_s_tuner (struct file *file, void *priv,
/* ----------------------------------------------------------- */
-static void cx8800_vid_timeout(unsigned long data)
-{
- struct cx8800_dev *dev = (struct cx8800_dev*)data;
- struct cx88_core *core = dev->core;
- struct cx88_dmaqueue *q = &dev->vidq;
- struct cx88_buffer *buf;
- unsigned long flags;
-
- cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
-
- cx_clear(MO_VID_DMACNTRL, 0x11);
- cx_clear(VID_CAPTURE_CONTROL, 0x06);
-
- spin_lock_irqsave(&dev->slock,flags);
- while (!list_empty(&q->active)) {
- buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
- list_del(&buf->vb.queue);
- buf->vb.state = VIDEOBUF_ERROR;
- wake_up(&buf->vb.done);
- printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", core->name,
- buf, buf->vb.i, (unsigned long)buf->risc.dma);
- }
- restart_video_queue(dev,q);
- spin_unlock_irqrestore(&dev->slock,flags);
-}
-
static const char *cx88_vid_irqs[32] = {
"y_risci1", "u_risci1", "v_risci1", "vbi_risc1",
"y_risci2", "u_risci2", "v_risci2", "vbi_risc2",
@@ -1422,22 +1120,6 @@ static void cx8800_vid_irq(struct cx8800_dev *dev)
cx88_wakeup(core, &dev->vbiq, count);
spin_unlock(&dev->slock);
}
-
- /* risc2 y */
- if (status & 0x10) {
- dprintk(2,"stopper video\n");
- spin_lock(&dev->slock);
- restart_video_queue(dev,&dev->vidq);
- spin_unlock(&dev->slock);
- }
-
- /* risc2 vbi */
- if (status & 0x80) {
- dprintk(2,"stopper vbi\n");
- spin_lock(&dev->slock);
- cx8800_restart_vbi_queue(dev,&dev->vbiq);
- spin_unlock(&dev->slock);
- }
}
static irqreturn_t cx8800_irq(int irq, void *dev_id)
@@ -1476,11 +1158,11 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id)
static const struct v4l2_file_operations video_fops =
{
.owner = THIS_MODULE,
- .open = video_open,
- .release = video_release,
- .read = video_read,
- .poll = video_poll,
- .mmap = video_mmap,
+ .open = v4l2_fh_open,
+ .release = vb2_fop_release,
+ .read = vb2_fop_read,
+ .poll = vb2_fop_poll,
+ .mmap = vb2_fop_mmap,
.unlocked_ioctl = video_ioctl2,
};
@@ -1490,17 +1172,17 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
- .vidioc_reqbufs = vidioc_reqbufs,
- .vidioc_querybuf = vidioc_querybuf,
- .vidioc_qbuf = vidioc_qbuf,
- .vidioc_dqbuf = vidioc_dqbuf,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
.vidioc_g_std = vidioc_g_std,
.vidioc_s_std = vidioc_s_std,
.vidioc_enum_input = vidioc_enum_input,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
- .vidioc_streamon = vidioc_streamon,
- .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
.vidioc_g_tuner = vidioc_g_tuner,
.vidioc_s_tuner = vidioc_s_tuner,
.vidioc_g_frequency = vidioc_g_frequency,
@@ -1525,17 +1207,17 @@ static const struct v4l2_ioctl_ops vbi_ioctl_ops = {
.vidioc_g_fmt_vbi_cap = cx8800_vbi_fmt,
.vidioc_try_fmt_vbi_cap = cx8800_vbi_fmt,
.vidioc_s_fmt_vbi_cap = cx8800_vbi_fmt,
- .vidioc_reqbufs = vidioc_reqbufs,
- .vidioc_querybuf = vidioc_querybuf,
- .vidioc_qbuf = vidioc_qbuf,
- .vidioc_dqbuf = vidioc_dqbuf,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
.vidioc_g_std = vidioc_g_std,
.vidioc_s_std = vidioc_s_std,
.vidioc_enum_input = vidioc_enum_input,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
- .vidioc_streamon = vidioc_streamon,
- .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
.vidioc_g_tuner = vidioc_g_tuner,
.vidioc_s_tuner = vidioc_s_tuner,
.vidioc_g_frequency = vidioc_g_frequency,
@@ -1556,9 +1238,9 @@ static const struct video_device cx8800_vbi_template = {
static const struct v4l2_file_operations radio_fops =
{
.owner = THIS_MODULE,
- .open = video_open,
+ .open = radio_open,
.poll = v4l2_ctrl_poll,
- .release = video_release,
+ .release = v4l2_fh_release,
.unlocked_ioctl = video_ioctl2,
};
@@ -1622,6 +1304,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
{
struct cx8800_dev *dev;
struct cx88_core *core;
+ struct vb2_queue *q;
int err;
int i;
@@ -1663,19 +1346,9 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
/* init video dma queues */
INIT_LIST_HEAD(&dev->vidq.active);
- dev->vidq.timeout.function = cx8800_vid_timeout;
- dev->vidq.timeout.data = (unsigned long)dev;
- init_timer(&dev->vidq.timeout);
- cx88_risc_stopper(dev->pci,&dev->vidq.stopper,
- MO_VID_DMACNTRL,0x11,0x00);
/* init vbi dma queues */
INIT_LIST_HEAD(&dev->vbiq.active);
- dev->vbiq.timeout.function = cx8800_vbi_timeout;
- dev->vbiq.timeout.data = (unsigned long)dev;
- init_timer(&dev->vbiq.timeout);
- cx88_risc_stopper(dev->pci,&dev->vbiq.stopper,
- MO_VID_DMACNTRL,0x88,0x00);
/* get irq */
err = request_irq(pci_dev->irq, cx8800_irq,
@@ -1766,6 +1439,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
dev->width = 320;
dev->height = 240;
+ dev->field = V4L2_FIELD_INTERLACED;
dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
/* initial device configuration */
@@ -1775,11 +1449,44 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
v4l2_ctrl_handler_setup(&core->audio_hdl);
cx88_video_mux(core, 0);
+ q = &dev->vb2_vidq;
+ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
+ q->gfp_flags = GFP_DMA32;
+ q->min_buffers_needed = 2;
+ q->drv_priv = dev;
+ q->buf_struct_size = sizeof(struct cx88_buffer);
+ q->ops = &cx8800_video_qops;
+ q->mem_ops = &vb2_dma_sg_memops;
+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ q->lock = &core->lock;
+
+ err = vb2_queue_init(q);
+ if (err < 0)
+ goto fail_unreg;
+
+ q = &dev->vb2_vbiq;
+ q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+ q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
+ q->gfp_flags = GFP_DMA32;
+ q->min_buffers_needed = 2;
+ q->drv_priv = dev;
+ q->buf_struct_size = sizeof(struct cx88_buffer);
+ q->ops = &cx8800_vbi_qops;
+ q->mem_ops = &vb2_dma_sg_memops;
+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ q->lock = &core->lock;
+
+ err = vb2_queue_init(q);
+ if (err < 0)
+ goto fail_unreg;
+
/* register v4l devices */
dev->video_dev = cx88_vdev_init(core,dev->pci,
&cx8800_video_template,"video");
video_set_drvdata(dev->video_dev, dev);
dev->video_dev->ctrl_handler = &core->video_hdl;
+ dev->video_dev->queue = &dev->vb2_vidq;
err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
video_nr[core->nr]);
if (err < 0) {
@@ -1792,6 +1499,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi");
video_set_drvdata(dev->vbi_dev, dev);
+ dev->vbi_dev->queue = &dev->vb2_vbiq;
err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
vbi_nr[core->nr]);
if (err < 0) {
@@ -1865,7 +1573,6 @@ static void cx8800_finidev(struct pci_dev *pci_dev)
cx8800_unregister_video(dev);
/* free memory */
- btcx_riscmem_free(dev->pci,&dev->vidq.stopper);
cx88_core_put(core,dev->pci);
kfree(dev);
}
@@ -1882,12 +1589,10 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
if (!list_empty(&dev->vidq.active)) {
printk("%s/0: suspend video\n", core->name);
stop_video_dma(dev);
- del_timer(&dev->vidq.timeout);
}
if (!list_empty(&dev->vbiq.active)) {
printk("%s/0: suspend vbi\n", core->name);
cx8800_stop_vbi_dma(dev);
- del_timer(&dev->vbiq.timeout);
}
spin_unlock_irqrestore(&dev->slock, flags);
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index 77ec542..2dadaa6 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -29,9 +29,9 @@
#include <media/v4l2-fh.h>
#include <media/tuner.h>
#include <media/tveeprom.h>
-#include <media/videobuf-dma-sg.h>
+#include <media/videobuf2-dma-sg.h>
#include <media/cx2341x.h>
-#include <media/videobuf-dvb.h>
+#include <media/videobuf2-dvb.h>
#include <media/ir-kbd-i2c.h>
#include <media/wm8775.h>
@@ -41,7 +41,7 @@
#include <linux/mutex.h>
-#define CX88_VERSION "0.0.9"
+#define CX88_VERSION "1.0.0"
#define UNSET (-1U)
@@ -95,13 +95,13 @@ enum cx8802_board_access {
static inline unsigned int norm_maxw(v4l2_std_id norm)
{
- return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
+ return 720;
}
static inline unsigned int norm_maxh(v4l2_std_id norm)
{
- return (norm & V4L2_STD_625_50) ? 576 : 480;
+ return (norm & V4L2_STD_525_60) ? 480 : 576;
}
/* ----------------------------------------------------------- */
@@ -314,7 +314,8 @@ enum cx88_tvaudio {
/* buffer for one video frame */
struct cx88_buffer {
/* common v4l buffer stuff -- must be first */
- struct videobuf_buffer vb;
+ struct vb2_buffer vb;
+ struct list_head list;
/* cx88 specific */
unsigned int bpl;
@@ -324,8 +325,6 @@ struct cx88_buffer {
struct cx88_dmaqueue {
struct list_head active;
- struct timer_list timeout;
- struct btcx_riscmem stopper;
u32 count;
};
@@ -393,8 +392,6 @@ struct cx88_core {
struct mutex lock;
/* various v4l controls */
u32 freq;
- int users;
- int mpeg_users;
/* cx88-video needs to access cx8802 for hybrid tuner pll access. */
struct cx8802_dev *dvbdev;
@@ -457,18 +454,6 @@ struct cx8802_dev;
/* ----------------------------------------------------------- */
/* function 0: video stuff */
-struct cx8800_fh {
- struct v4l2_fh fh;
- struct cx8800_dev *dev;
- unsigned int resources;
-
- /* video capture */
- struct videobuf_queue vidq;
-
- /* vbi capture */
- struct videobuf_queue vbiq;
-};
-
struct cx8800_suspend_state {
int disabled;
};
@@ -489,10 +474,13 @@ struct cx8800_dev {
const struct cx8800_fmt *fmt;
unsigned int width, height;
+ unsigned field;
/* capture queues */
struct cx88_dmaqueue vidq;
+ struct vb2_queue vb2_vidq;
struct cx88_dmaqueue vbiq;
+ struct vb2_queue vb2_vbiq;
/* various v4l controls */
@@ -508,12 +496,6 @@ struct cx8800_dev {
/* ----------------------------------------------------------- */
/* function 2: mpeg stuff */
-struct cx8802_fh {
- struct v4l2_fh fh;
- struct cx8802_dev *dev;
- struct videobuf_queue mpegq;
-};
-
struct cx8802_suspend_state {
int disabled;
};
@@ -557,6 +539,7 @@ struct cx8802_dev {
/* dma queues */
struct cx88_dmaqueue mpegq;
+ struct vb2_queue vb2_mpegq;
u32 ts_packet_size;
u32 ts_packet_count;
@@ -570,6 +553,7 @@ struct cx8802_dev {
u32 mailbox;
int width;
int height;
+ unsigned field;
unsigned char mpeg_active; /* nonzero if mpeg encoder is active */
/* mpeg params */
@@ -578,7 +562,7 @@ struct cx8802_dev {
#if IS_ENABLED(CONFIG_VIDEO_CX88_DVB)
/* for dvb only */
- struct videobuf_dvb_frontends frontends;
+ struct vb2_dvb_frontends frontends;
#endif
#if IS_ENABLED(CONFIG_VIDEO_CX88_VP3054)
@@ -640,11 +624,8 @@ extern int
cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
struct scatterlist *sglist, unsigned int bpl,
unsigned int lines, unsigned int lpi);
-extern int
-cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
- u32 reg, u32 mask, u32 value);
extern void
-cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf);
+cx88_free_buffer(struct vb2_queue *q, struct cx88_buffer *buf);
extern void cx88_risc_disasm(struct cx88_core *core,
struct btcx_riscmem *risc);
@@ -662,7 +643,7 @@ extern struct video_device *cx88_vdev_init(struct cx88_core *core,
struct pci_dev *pci,
const struct video_device *template_,
const char *type);
-extern struct cx88_core* cx88_core_get(struct pci_dev *pci);
+extern struct cx88_core *cx88_core_get(struct pci_dev *pci);
extern void cx88_core_put(struct cx88_core *core,
struct pci_dev *pci);
@@ -682,12 +663,10 @@ int cx8800_start_vbi_dma(struct cx8800_dev *dev,
struct cx88_dmaqueue *q,
struct cx88_buffer *buf);
*/
-int cx8800_stop_vbi_dma(struct cx8800_dev *dev);
-int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
- struct cx88_dmaqueue *q);
-void cx8800_vbi_timeout(unsigned long data);
+void cx8800_stop_vbi_dma(struct cx8800_dev *dev);
+int cx8800_restart_vbi_queue(struct cx8800_dev *dev, struct cx88_dmaqueue *q);
-extern const struct videobuf_queue_ops cx8800_vbi_qops;
+extern const struct vb2_ops cx8800_vbi_qops;
/* ----------------------------------------------------------- */
/* cx88-i2c.c */
@@ -737,14 +716,17 @@ extern void cx88_i2c_init_ir(struct cx88_core *core);
/* ----------------------------------------------------------- */
/* cx88-mpeg.c */
-int cx8802_buf_prepare(struct videobuf_queue *q,struct cx8802_dev *dev,
+int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
struct cx88_buffer *buf, enum v4l2_field field);
void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf);
void cx8802_cancel_buffers(struct cx8802_dev *dev);
+int cx8802_start_dma(struct cx8802_dev *dev,
+ struct cx88_dmaqueue *q,
+ struct cx88_buffer *buf);
/* ----------------------------------------------------------- */
/* cx88-video.c*/
-int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i);
+int cx88_enum_input(struct cx88_core *core, struct v4l2_input *i);
int cx88_set_freq(struct cx88_core *core, const struct v4l2_frequency *f);
int cx88_video_mux(struct cx88_core *core, unsigned int input);
void cx88_querycap(struct file *file, struct cx88_core *core,
--
2.1.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 05/16] cx88: fix sparse warning
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
` (3 preceding siblings ...)
2014-09-20 12:41 ` [PATCH 04/16] cx88: convert to vb2 Hans Verkuil
@ 2014-09-20 12:41 ` Hans Verkuil
2014-09-20 12:41 ` [PATCH 06/16] cx88: return proper errors during fw load Hans Verkuil
` (10 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
drivers/media/pci/cx88/cx88-blackbird.c:476:25: warning: cast to restricted __le32
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/cx88/cx88-blackbird.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index 25d06f3..32abba4 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -428,7 +428,7 @@ static int blackbird_load_firmware(struct cx8802_dev *dev)
int i, retval = 0;
u32 value = 0;
u32 checksum = 0;
- u32 *dataptr;
+ __le32 *dataptr;
retval = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED);
retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
@@ -467,7 +467,7 @@ static int blackbird_load_firmware(struct cx8802_dev *dev)
/* transfer to the chip */
dprintk(1,"Loading firmware ...\n");
- dataptr = (u32*)firmware->data;
+ dataptr = (__le32 *)firmware->data;
for (i = 0; i < (firmware->size >> 2); i++) {
value = le32_to_cpu(*dataptr);
checksum += ~value;
--
2.1.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 06/16] cx88: return proper errors during fw load
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
` (4 preceding siblings ...)
2014-09-20 12:41 ` [PATCH 05/16] cx88: fix sparse warning Hans Verkuil
@ 2014-09-20 12:41 ` Hans Verkuil
2014-09-20 12:41 ` [PATCH 07/16] cx88: drop cx88_free_buffer Hans Verkuil
` (9 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
Don't return -1, return a proper error.
Replace dprintk(0, ...) by pr_err since firmware load errors should just be
reported as an error.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/cx88/cx88-blackbird.c | 32 +++++++++++++++-----------------
1 file changed, 15 insertions(+), 17 deletions(-)
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index 32abba4..11054cd 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -322,13 +322,13 @@ static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 dat
memory_read(dev->core, dev->mailbox - 4, &value);
if (value != 0x12345678) {
dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n");
- return -1;
+ return -EIO;
}
memory_read(dev->core, dev->mailbox, &flag);
if (flag) {
dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag);
- return -1;
+ return -EIO;
}
flag |= 1; /* tell 'em we're working on it */
@@ -354,8 +354,8 @@ static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 dat
if (0 != (flag & 4))
break;
if (time_after(jiffies,timeout)) {
- dprintk(0, "ERROR: API Mailbox timeout\n");
- return -1;
+ dprintk(0, "ERROR: API Mailbox timeout %x\n", command);
+ return -EIO;
}
udelay(10);
}
@@ -416,7 +416,7 @@ static int blackbird_find_mailbox(struct cx8802_dev *dev)
}
}
dprintk(0, "Mailbox signature values not found!\n");
- return -1;
+ return -EIO;
}
static int blackbird_load_firmware(struct cx8802_dev *dev)
@@ -445,24 +445,23 @@ static int blackbird_load_firmware(struct cx8802_dev *dev)
if (retval != 0) {
- dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n",
+ pr_err("Hotplug firmware request failed (%s).\n",
CX2341X_FIRM_ENC_FILENAME);
- dprintk(0, "Please fix your hotplug setup, the board will "
- "not work without firmware loaded!\n");
- return -1;
+ pr_err("Please fix your hotplug setup, the board will not work without firmware loaded!\n");
+ return -EIO;
}
if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) {
- dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n",
+ pr_err("Firmware size mismatch (have %zd, expected %d)\n",
firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE);
release_firmware(firmware);
- return -1;
+ return -EINVAL;
}
if (0 != memcmp(firmware->data, magic, 8)) {
- dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n");
+ pr_err("Firmware magic mismatch, wrong file?\n");
release_firmware(firmware);
- return -1;
+ return -EINVAL;
}
/* transfer to the chip */
@@ -480,12 +479,11 @@ static int blackbird_load_firmware(struct cx8802_dev *dev)
memory_read(dev->core, i, &value);
checksum -= ~value;
}
+ release_firmware(firmware);
if (checksum) {
- dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n");
- release_firmware(firmware);
- return -1;
+ pr_err("Firmware load might have failed (checksum mismatch).\n");
+ return -EIO;
}
- release_firmware(firmware);
dprintk(0, "Firmware upload successful.\n");
retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
--
2.1.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 07/16] cx88: drop cx88_free_buffer
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
` (5 preceding siblings ...)
2014-09-20 12:41 ` [PATCH 06/16] cx88: return proper errors during fw load Hans Verkuil
@ 2014-09-20 12:41 ` Hans Verkuil
2014-09-20 12:41 ` [PATCH 08/16] cx88: remove dependency on btcx-risc Hans Verkuil
` (8 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
Remove this function. This makes all vb2 queues behave the same, which
simplifies comparing the various vb2 queue op implementations.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/cx88/cx88-blackbird.c | 2 +-
drivers/media/pci/cx88/cx88-core.c | 7 -------
drivers/media/pci/cx88/cx88-dvb.c | 2 +-
drivers/media/pci/cx88/cx88-mpeg.c | 6 +++++-
drivers/media/pci/cx88/cx88-vbi.c | 2 +-
drivers/media/pci/cx88/cx88-video.c | 2 +-
drivers/media/pci/cx88/cx88.h | 2 --
7 files changed, 9 insertions(+), 14 deletions(-)
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index 11054cd..b24266e 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -667,7 +667,7 @@ static void buffer_finish(struct vb2_buffer *vb)
struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
- cx88_free_buffer(vb->vb2_queue, buf);
+ btcx_riscmem_free(dev->pci, &buf->risc);
dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
}
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
index f027408..902b662 100644
--- a/drivers/media/pci/cx88/cx88-core.c
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -198,12 +198,6 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
return 0;
}
-void
-cx88_free_buffer(struct vb2_queue *q, struct cx88_buffer *buf)
-{
- btcx_riscmem_free(to_pci_dev(q->drv_priv), &buf->risc);
-}
-
/* ------------------------------------------------------------------ */
/* our SRAM memory layout */
@@ -1072,7 +1066,6 @@ EXPORT_SYMBOL(cx88_shutdown);
EXPORT_SYMBOL(cx88_risc_buffer);
EXPORT_SYMBOL(cx88_risc_databuffer);
-EXPORT_SYMBOL(cx88_free_buffer);
EXPORT_SYMBOL(cx88_sram_channels);
EXPORT_SYMBOL(cx88_sram_channel_setup);
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
index d7e5c45..b5b88a6 100644
--- a/drivers/media/pci/cx88/cx88-dvb.c
+++ b/drivers/media/pci/cx88/cx88-dvb.c
@@ -110,7 +110,7 @@ static void buffer_finish(struct vb2_buffer *vb)
struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
- cx88_free_buffer(vb->vb2_queue, buf);
+ btcx_riscmem_free(dev->pci, &buf->risc);
dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
}
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
index 7986ee0..0589dcc 100644
--- a/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -238,8 +238,12 @@ int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
if (!rc)
return -EIO;
- cx88_risc_databuffer(dev->pci, &buf->risc, sgt->sgl,
+ rc = cx88_risc_databuffer(dev->pci, &buf->risc, sgt->sgl,
dev->ts_packet_size, dev->ts_packet_count, 0);
+ if (rc) {
+ btcx_riscmem_free(dev->pci, &buf->risc);
+ return rc;
+ }
return 0;
}
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
index 26a1533..8f20612 100644
--- a/drivers/media/pci/cx88/cx88-vbi.c
+++ b/drivers/media/pci/cx88/cx88-vbi.c
@@ -147,7 +147,7 @@ static void buffer_finish(struct vb2_buffer *vb)
struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
- cx88_free_buffer(vb->vb2_queue, buf);
+ btcx_riscmem_free(dev->pci, &buf->risc);
dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
}
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index 9887da5..c64f8f4 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -506,7 +506,7 @@ static void buffer_finish(struct vb2_buffer *vb)
struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
- cx88_free_buffer(vb->vb2_queue, buf);
+ btcx_riscmem_free(dev->pci, &buf->risc);
dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
}
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index 2dadaa6..16965c8 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -624,8 +624,6 @@ extern int
cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
struct scatterlist *sglist, unsigned int bpl,
unsigned int lines, unsigned int lpi);
-extern void
-cx88_free_buffer(struct vb2_queue *q, struct cx88_buffer *buf);
extern void cx88_risc_disasm(struct cx88_core *core,
struct btcx_riscmem *risc);
--
2.1.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 08/16] cx88: remove dependency on btcx-risc
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
` (6 preceding siblings ...)
2014-09-20 12:41 ` [PATCH 07/16] cx88: drop cx88_free_buffer Hans Verkuil
@ 2014-09-20 12:41 ` Hans Verkuil
2014-09-20 12:41 ` [PATCH 09/16] cx88: increase API command timeout Hans Verkuil
` (7 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
btcx-risc is for the bt8xx driver and other drivers shouldn't depend
on it. There is no benefit to use that module just to do a
pci_zalloc_consistent.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/cx88/Kconfig | 1 -
drivers/media/pci/cx88/Makefile | 1 -
drivers/media/pci/cx88/cx88-alsa.c | 7 +++++--
drivers/media/pci/cx88/cx88-blackbird.c | 5 ++++-
drivers/media/pci/cx88/cx88-core.c | 20 ++++++++++++--------
drivers/media/pci/cx88/cx88-dvb.c | 5 ++++-
drivers/media/pci/cx88/cx88-mpeg.c | 7 +++++--
drivers/media/pci/cx88/cx88-vbi.c | 5 ++++-
drivers/media/pci/cx88/cx88-video.c | 5 ++++-
drivers/media/pci/cx88/cx88.h | 16 +++++++++++-----
10 files changed, 49 insertions(+), 23 deletions(-)
diff --git a/drivers/media/pci/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig
index d5b125e..14b813d6 100644
--- a/drivers/media/pci/cx88/Kconfig
+++ b/drivers/media/pci/cx88/Kconfig
@@ -2,7 +2,6 @@ config VIDEO_CX88
tristate "Conexant 2388x (bt878 successor) support"
depends on VIDEO_DEV && PCI && I2C && RC_CORE
select I2C_ALGOBIT
- select VIDEO_BTCX
select VIDEOBUF2_DMA_SG
select VIDEO_TUNER
select VIDEO_TVEEPROM
diff --git a/drivers/media/pci/cx88/Makefile b/drivers/media/pci/cx88/Makefile
index 8619c1b..d3679c3 100644
--- a/drivers/media/pci/cx88/Makefile
+++ b/drivers/media/pci/cx88/Makefile
@@ -11,7 +11,6 @@ obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
ccflags-y += -Idrivers/media/i2c
-ccflags-y += -Idrivers/media/common
ccflags-y += -Idrivers/media/tuners
ccflags-y += -Idrivers/media/dvb-core
ccflags-y += -Idrivers/media/dvb-frontends
diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c
index 73021a2..7f8dc60 100644
--- a/drivers/media/pci/cx88/cx88-alsa.c
+++ b/drivers/media/pci/cx88/cx88-alsa.c
@@ -61,7 +61,7 @@
struct cx88_audio_buffer {
unsigned int bpl;
- struct btcx_riscmem risc;
+ struct cx88_riscmem risc;
void *vaddr;
struct scatterlist *sglist;
int sglen;
@@ -370,12 +370,15 @@ static int cx88_alsa_dma_free(struct cx88_audio_buffer *buf)
static int dsp_buffer_free(snd_cx88_card_t *chip)
{
+ struct cx88_riscmem *risc = &chip->buf->risc;
+
BUG_ON(!chip->dma_size);
dprintk(2,"Freeing buffer\n");
cx88_alsa_dma_unmap(chip);
cx88_alsa_dma_free(chip->buf);
- btcx_riscmem_free(chip->pci, &chip->buf->risc);
+ if (risc->cpu)
+ pci_free_consistent(chip->pci, risc->size, risc->cpu, risc->dma);
kfree(chip->buf);
chip->buf = NULL;
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index b24266e..f27a3f1 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -666,8 +666,11 @@ static void buffer_finish(struct vb2_buffer *vb)
struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
+ struct cx88_riscmem *risc = &buf->risc;
- btcx_riscmem_free(dev->pci, &buf->risc);
+ if (risc->cpu)
+ pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
+ memset(risc, 0, sizeof(*risc));
dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
}
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
index 902b662..bbdbb58 100644
--- a/drivers/media/pci/cx88/cx88-core.c
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -132,14 +132,13 @@ static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
return rp;
}
-int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+int cx88_risc_buffer(struct pci_dev *pci, struct cx88_riscmem *risc,
struct scatterlist *sglist,
unsigned int top_offset, unsigned int bottom_offset,
unsigned int bpl, unsigned int padding, unsigned int lines)
{
u32 instructions,fields;
__le32 *rp;
- int rc;
fields = 0;
if (UNSET != top_offset)
@@ -153,8 +152,11 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
region may be smaller than PAGE_SIZE */
instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
instructions += 4;
- if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
- return rc;
+ risc->size = instructions * 8;
+ risc->dma = 0;
+ risc->cpu = pci_zalloc_consistent(pci, risc->size, &risc->dma);
+ if (NULL == risc->cpu)
+ return -ENOMEM;
/* write risc instructions */
rp = risc->cpu;
@@ -171,13 +173,12 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
return 0;
}
-int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+int cx88_risc_databuffer(struct pci_dev *pci, struct cx88_riscmem *risc,
struct scatterlist *sglist, unsigned int bpl,
unsigned int lines, unsigned int lpi)
{
u32 instructions;
__le32 *rp;
- int rc;
/* estimate risc mem: worst case is one write per page border +
one write per scan line + syncs + jump (all 2 dwords). Here
@@ -185,8 +186,11 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
than PAGE_SIZE */
instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
instructions += 3;
- if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
- return rc;
+ risc->size = instructions * 8;
+ risc->dma = 0;
+ risc->cpu = pci_zalloc_consistent(pci, risc->size, &risc->dma);
+ if (NULL == risc->cpu)
+ return -ENOMEM;
/* write risc instructions */
rp = risc->cpu;
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
index b5b88a6..dd0deb1 100644
--- a/drivers/media/pci/cx88/cx88-dvb.c
+++ b/drivers/media/pci/cx88/cx88-dvb.c
@@ -109,8 +109,11 @@ static void buffer_finish(struct vb2_buffer *vb)
struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
+ struct cx88_riscmem *risc = &buf->risc;
- btcx_riscmem_free(dev->pci, &buf->risc);
+ if (risc->cpu)
+ pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
+ memset(risc, 0, sizeof(*risc));
dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
}
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
index 0589dcc..746c0ea 100644
--- a/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -228,6 +228,7 @@ int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
{
int size = dev->ts_packet_size * dev->ts_packet_count;
struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0);
+ struct cx88_riscmem *risc = &buf->risc;
int rc;
if (vb2_plane_size(&buf->vb, 0) < size)
@@ -238,10 +239,12 @@ int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
if (!rc)
return -EIO;
- rc = cx88_risc_databuffer(dev->pci, &buf->risc, sgt->sgl,
+ rc = cx88_risc_databuffer(dev->pci, risc, sgt->sgl,
dev->ts_packet_size, dev->ts_packet_count, 0);
if (rc) {
- btcx_riscmem_free(dev->pci, &buf->risc);
+ if (risc->cpu)
+ pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
+ memset(risc, 0, sizeof(*risc));
return rc;
}
return 0;
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
index 8f20612..4e0747a 100644
--- a/drivers/media/pci/cx88/cx88-vbi.c
+++ b/drivers/media/pci/cx88/cx88-vbi.c
@@ -146,8 +146,11 @@ static void buffer_finish(struct vb2_buffer *vb)
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
+ struct cx88_riscmem *risc = &buf->risc;
- btcx_riscmem_free(dev->pci, &buf->risc);
+ if (risc->cpu)
+ pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
+ memset(risc, 0, sizeof(*risc));
dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
}
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index c64f8f4..a74e21d 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -505,8 +505,11 @@ static void buffer_finish(struct vb2_buffer *vb)
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
+ struct cx88_riscmem *risc = &buf->risc;
- btcx_riscmem_free(dev->pci, &buf->risc);
+ if (risc->cpu)
+ pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
+ memset(risc, 0, sizeof(*risc));
dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
}
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index 16965c8..dd50177 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -35,7 +35,6 @@
#include <media/ir-kbd-i2c.h>
#include <media/wm8775.h>
-#include "btcx-risc.h"
#include "cx88-reg.h"
#include "tuner-xc2028.h"
@@ -311,6 +310,13 @@ enum cx88_tvaudio {
#define BUFFER_TIMEOUT msecs_to_jiffies(2000)
+struct cx88_riscmem {
+ unsigned int size;
+ __le32 *cpu;
+ __le32 *jmp;
+ dma_addr_t dma;
+};
+
/* buffer for one video frame */
struct cx88_buffer {
/* common v4l buffer stuff -- must be first */
@@ -319,7 +325,7 @@ struct cx88_buffer {
/* cx88 specific */
unsigned int bpl;
- struct btcx_riscmem risc;
+ struct cx88_riscmem risc;
u32 count;
};
@@ -616,17 +622,17 @@ extern void cx88_shutdown(struct cx88_core *core);
extern int cx88_reset(struct cx88_core *core);
extern int
-cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+cx88_risc_buffer(struct pci_dev *pci, struct cx88_riscmem *risc,
struct scatterlist *sglist,
unsigned int top_offset, unsigned int bottom_offset,
unsigned int bpl, unsigned int padding, unsigned int lines);
extern int
-cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+cx88_risc_databuffer(struct pci_dev *pci, struct cx88_riscmem *risc,
struct scatterlist *sglist, unsigned int bpl,
unsigned int lines, unsigned int lpi);
extern void cx88_risc_disasm(struct cx88_core *core,
- struct btcx_riscmem *risc);
+ struct cx88_riscmem *risc);
extern int cx88_sram_channel_setup(struct cx88_core *core,
const struct sram_channel *ch,
unsigned int bpl, u32 risc);
--
2.1.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 09/16] cx88: increase API command timeout
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
` (7 preceding siblings ...)
2014-09-20 12:41 ` [PATCH 08/16] cx88: remove dependency on btcx-risc Hans Verkuil
@ 2014-09-20 12:41 ` Hans Verkuil
2014-09-20 12:41 ` [PATCH 10/16] cx88: don't pollute the kernel log Hans Verkuil
` (6 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
The timeout is way too small. Especially complicated command like
CX2341X_ENC_STOP_CAPTURE takes much more time than 10 ms. Increase the
timeout to 1 second, just as ivtv does (the cx88-blackbird has the
same IP core for MPEG compression as ivtv).
This solves a nasty issue where STOP_CAPTURE would timeout and the
mailbox is left in a busy state, making it impossible to start streaming
a second time without reloading the driver first.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/cx88/cx88-blackbird.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index f27a3f1..32fb935 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -348,7 +348,7 @@ static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 dat
memory_write(dev->core, dev->mailbox, flag);
/* wait for firmware to handle the API command */
- timeout = jiffies + msecs_to_jiffies(10);
+ timeout = jiffies + msecs_to_jiffies(1000);
for (;;) {
memory_read(dev->core, dev->mailbox, &flag);
if (0 != (flag & 4))
--
2.1.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 10/16] cx88: don't pollute the kernel log
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
` (8 preceding siblings ...)
2014-09-20 12:41 ` [PATCH 09/16] cx88: increase API command timeout Hans Verkuil
@ 2014-09-20 12:41 ` Hans Verkuil
2014-09-20 12:41 ` [PATCH 11/16] cx88: move width, height and field to core struct Hans Verkuil
` (5 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
There is no reason to dump the sram code to the kernel log when you
stop streaming. Remove those calls to cx88_sram_channel_dump.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/cx88/cx88-vbi.c | 2 --
drivers/media/pci/cx88/cx88-video.c | 2 --
2 files changed, 4 deletions(-)
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
index 4e0747a..042f545 100644
--- a/drivers/media/pci/cx88/cx88-vbi.c
+++ b/drivers/media/pci/cx88/cx88-vbi.c
@@ -203,8 +203,6 @@ static void stop_streaming(struct vb2_queue *q)
struct cx88_dmaqueue *dmaq = &dev->vbiq;
unsigned long flags;
- cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
-
cx_clear(MO_VID_DMACNTRL, 0x11);
cx_clear(VID_CAPTURE_CONTROL, 0x06);
cx8800_stop_vbi_dma(dev);
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index a74e21d..85c3d0c 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -563,8 +563,6 @@ static void stop_streaming(struct vb2_queue *q)
struct cx88_dmaqueue *dmaq = &dev->vidq;
unsigned long flags;
- cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
-
cx_clear(MO_VID_DMACNTRL, 0x11);
cx_clear(VID_CAPTURE_CONTROL, 0x06);
spin_lock_irqsave(&dev->slock, flags);
--
2.1.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 11/16] cx88: move width, height and field to core struct
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
` (9 preceding siblings ...)
2014-09-20 12:41 ` [PATCH 10/16] cx88: don't pollute the kernel log Hans Verkuil
@ 2014-09-20 12:41 ` Hans Verkuil
2014-09-20 12:41 ` [PATCH 12/16] cx88: drop mpeg_active field Hans Verkuil
` (4 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
The width, height and field values are core fields since both vbi, video
and blackbird use the same video input.
Move those fields to the correct struct.
Also fix the field checks in the try_fmt functions: add V4L2_FIELD_SEQ_BT/TB
support and map incorrect field values to a correct field value instead of
returning an error.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/cx88/cx88-blackbird.c | 85 +++++++++++++++++++--------------
drivers/media/pci/cx88/cx88-cards.c | 5 ++
drivers/media/pci/cx88/cx88-dvb.c | 2 +-
drivers/media/pci/cx88/cx88-mpeg.c | 4 +-
drivers/media/pci/cx88/cx88-video.c | 75 ++++++++++++++---------------
drivers/media/pci/cx88/cx88.h | 9 ++--
6 files changed, 98 insertions(+), 82 deletions(-)
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index 32fb935..58e5254 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -515,12 +515,14 @@ DB* DVD | MPEG2 | 720x576PAL | CBR | 600 :Good | 6000 Kbps | 25fps | M
static void blackbird_codec_settings(struct cx8802_dev *dev)
{
+ struct cx88_core *core = dev->core;
+
/* assign frame size */
blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
- dev->height, dev->width);
+ core->height, core->width);
- dev->cxhdl.width = dev->width;
- dev->cxhdl.height = dev->height;
+ dev->cxhdl.width = core->width;
+ dev->cxhdl.height = core->height;
cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50);
cx2341x_handler_setup(&dev->cxhdl);
}
@@ -658,7 +660,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
- return cx8802_buf_prepare(vb->vb2_queue, dev, buf, dev->field);
+ return cx8802_buf_prepare(vb->vb2_queue, dev, buf);
}
static void buffer_finish(struct vb2_buffer *vb)
@@ -796,55 +798,75 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
return 0;
}
-static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx8802_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0;
f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.width = dev->width;
- f->fmt.pix.height = dev->height;
- f->fmt.pix.field = dev->field;
- dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
- dev->width, dev->height, dev->field);
+ f->fmt.pix.width = core->width;
+ f->fmt.pix.height = core->height;
+ f->fmt.pix.field = core->field;
return 0;
}
-static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx8802_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
+ unsigned maxw, maxh;
+ enum v4l2_field field;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0;
f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
- dev->width, dev->height, dev->field);
+
+ maxw = norm_maxw(core->tvnorm);
+ maxh = norm_maxh(core->tvnorm);
+
+ field = f->fmt.pix.field;
+
+ switch (field) {
+ case V4L2_FIELD_TOP:
+ case V4L2_FIELD_BOTTOM:
+ case V4L2_FIELD_INTERLACED:
+ case V4L2_FIELD_SEQ_BT:
+ case V4L2_FIELD_SEQ_TB:
+ break;
+ default:
+ field = (f->fmt.pix.height > maxh / 2)
+ ? V4L2_FIELD_INTERLACED
+ : V4L2_FIELD_BOTTOM;
+ break;
+ }
+ if (V4L2_FIELD_HAS_T_OR_B(field))
+ maxh /= 2;
+
+ v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
+ &f->fmt.pix.height, 32, maxh, 0, 0);
+ f->fmt.pix.field = field;
return 0;
}
-static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx8802_dev *dev = video_drvdata(file);
struct cx88_core *core = dev->core;
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
- f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count;
- f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- dev->width = f->fmt.pix.width;
- dev->height = f->fmt.pix.height;
- dev->field = f->fmt.pix.field;
+ vidioc_try_fmt_vid_cap(file, priv, f);
+ core->width = f->fmt.pix.width;
+ core->height = f->fmt.pix.height;
+ core->field = f->fmt.pix.field;
cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
f->fmt.pix.height, f->fmt.pix.width);
- dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
- f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
return 0;
}
@@ -863,8 +885,8 @@ static int vidioc_s_frequency (struct file *file, void *priv,
cx88_set_freq (core,f);
blackbird_initialize_codec(dev);
- cx88_set_scale(dev->core, dev->width, dev->height,
- dev->field);
+ cx88_set_scale(core, core->width, core->height,
+ core->field);
return 0;
}
@@ -1128,16 +1150,9 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))
goto fail_core;
- dev->width = 720;
- if (core->tvnorm & V4L2_STD_525_60) {
- dev->height = 480;
- } else {
- dev->height = 576;
- }
- dev->field = V4L2_FIELD_INTERLACED;
dev->cxhdl.port = CX2341X_PORT_STREAMING;
- dev->cxhdl.width = dev->width;
- dev->cxhdl.height = dev->height;
+ dev->cxhdl.width = core->width;
+ dev->cxhdl.height = core->height;
dev->cxhdl.func = blackbird_mbox_func;
dev->cxhdl.priv = dev;
err = cx2341x_handler_init(&dev->cxhdl, 36);
@@ -1156,7 +1171,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
// init_controls(core);
cx88_set_tvnorm(core,core->tvnorm);
cx88_video_mux(core,0);
- cx2341x_handler_set_50hz(&dev->cxhdl, dev->height == 576);
+ cx2341x_handler_set_50hz(&dev->cxhdl, core->height == 576);
cx2341x_handler_setup(&dev->cxhdl);
q = &dev->vb2_mpegq;
diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c
index e18a7ac..eb72185 100644
--- a/drivers/media/pci/cx88/cx88-cards.c
+++ b/drivers/media/pci/cx88/cx88-cards.c
@@ -3691,6 +3691,11 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
core->nr = nr;
sprintf(core->name, "cx88[%d]", core->nr);
+ core->tvnorm = V4L2_STD_NTSC_M;
+ core->width = 320;
+ core->height = 240;
+ core->field = V4L2_FIELD_INTERLACED;
+
strcpy(core->v4l2_dev.name, core->name);
if (v4l2_device_register(NULL, &core->v4l2_dev)) {
kfree(core);
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
index dd0deb1..c344bfd 100644
--- a/drivers/media/pci/cx88/cx88-dvb.c
+++ b/drivers/media/pci/cx88/cx88-dvb.c
@@ -101,7 +101,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
- return cx8802_buf_prepare(vb->vb2_queue, dev, buf, dev->field);
+ return cx8802_buf_prepare(vb->vb2_queue, dev, buf);
}
static void buffer_finish(struct vb2_buffer *vb)
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
index 746c0ea..f181a3a 100644
--- a/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -93,7 +93,7 @@ int cx8802_start_dma(struct cx8802_dev *dev,
struct cx88_core *core = dev->core;
dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n",
- dev->width, dev->height, dev->field);
+ core->width, core->height, core->field);
/* setup fifo + format */
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
@@ -224,7 +224,7 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
/* ------------------------------------------------------------------ */
int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
- struct cx88_buffer *buf, enum v4l2_field field)
+ struct cx88_buffer *buf)
{
int size = dev->ts_packet_size * dev->ts_packet_count;
struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0);
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index 85c3d0c..eadceeb 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -365,7 +365,7 @@ static int start_video_dma(struct cx8800_dev *dev,
/* setup fifo + format */
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21],
buf->bpl, buf->risc.dma);
- cx88_set_scale(core, dev->width, dev->height, dev->field);
+ cx88_set_scale(core, core->width, core->height, core->field);
cx_write(MO_COLOR_CTRL, dev->fmt->cxformat | ColorFormatGamma);
/* reset counter */
@@ -436,9 +436,10 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
unsigned int sizes[], void *alloc_ctxs[])
{
struct cx8800_dev *dev = q->drv_priv;
+ struct cx88_core *core = dev->core;
*num_planes = 1;
- sizes[0] = (dev->fmt->depth * dev->width * dev->height) >> 3;
+ sizes[0] = (dev->fmt->depth * core->width * core->height) >> 3;
return 0;
}
@@ -450,52 +451,52 @@ static int buffer_prepare(struct vb2_buffer *vb)
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
int rc;
- buf->bpl = dev->width * dev->fmt->depth >> 3;
+ buf->bpl = core->width * dev->fmt->depth >> 3;
- if (vb2_plane_size(vb, 0) < dev->height * buf->bpl)
+ if (vb2_plane_size(vb, 0) < core->height * buf->bpl)
return -EINVAL;
- vb2_set_plane_payload(vb, 0, dev->height * buf->bpl);
+ vb2_set_plane_payload(vb, 0, core->height * buf->bpl);
rc = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
if (!rc)
return -EIO;
- switch (dev->field) {
+ switch (core->field) {
case V4L2_FIELD_TOP:
cx88_risc_buffer(dev->pci, &buf->risc,
sgt->sgl, 0, UNSET,
- buf->bpl, 0, dev->height);
+ buf->bpl, 0, core->height);
break;
case V4L2_FIELD_BOTTOM:
cx88_risc_buffer(dev->pci, &buf->risc,
sgt->sgl, UNSET, 0,
- buf->bpl, 0, dev->height);
+ buf->bpl, 0, core->height);
break;
case V4L2_FIELD_SEQ_TB:
cx88_risc_buffer(dev->pci, &buf->risc,
sgt->sgl,
- 0, buf->bpl * (dev->height >> 1),
+ 0, buf->bpl * (core->height >> 1),
buf->bpl, 0,
- dev->height >> 1);
+ core->height >> 1);
break;
case V4L2_FIELD_SEQ_BT:
cx88_risc_buffer(dev->pci, &buf->risc,
sgt->sgl,
- buf->bpl * (dev->height >> 1), 0,
+ buf->bpl * (core->height >> 1), 0,
buf->bpl, 0,
- dev->height >> 1);
+ core->height >> 1);
break;
case V4L2_FIELD_INTERLACED:
default:
cx88_risc_buffer(dev->pci, &buf->risc,
sgt->sgl, 0, buf->bpl,
buf->bpl, buf->bpl,
- dev->height >> 1);
+ core->height >> 1);
break;
}
dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
buf, buf->vb.v4l2_buf.index,
- dev->width, dev->height, dev->fmt->depth, dev->fmt->name,
+ core->width, core->height, dev->fmt->depth, dev->fmt->name,
(unsigned long)buf->risc.dma);
return 0;
}
@@ -723,10 +724,11 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
- f->fmt.pix.width = dev->width;
- f->fmt.pix.height = dev->height;
- f->fmt.pix.field = dev->field;
+ f->fmt.pix.width = core->width;
+ f->fmt.pix.height = core->height;
+ f->fmt.pix.field = core->field;
f->fmt.pix.pixelformat = dev->fmt->fourcc;
f->fmt.pix.bytesperline =
(f->fmt.pix.width * dev->fmt->depth) >> 3;
@@ -749,30 +751,30 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
if (NULL == fmt)
return -EINVAL;
- field = f->fmt.pix.field;
- maxw = norm_maxw(core->tvnorm);
- maxh = norm_maxh(core->tvnorm);
+ maxw = norm_maxw(core->tvnorm);
+ maxh = norm_maxh(core->tvnorm);
- if (V4L2_FIELD_ANY == field) {
- field = (f->fmt.pix.height > maxh/2)
- ? V4L2_FIELD_INTERLACED
- : V4L2_FIELD_BOTTOM;
- }
+ field = f->fmt.pix.field;
switch (field) {
case V4L2_FIELD_TOP:
case V4L2_FIELD_BOTTOM:
- maxh = maxh / 2;
- break;
case V4L2_FIELD_INTERLACED:
+ case V4L2_FIELD_SEQ_BT:
+ case V4L2_FIELD_SEQ_TB:
break;
default:
- return -EINVAL;
+ field = (f->fmt.pix.height > maxh / 2)
+ ? V4L2_FIELD_INTERLACED
+ : V4L2_FIELD_BOTTOM;
+ break;
}
+ if (V4L2_FIELD_HAS_T_OR_B(field))
+ maxh /= 2;
- f->fmt.pix.field = field;
v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
&f->fmt.pix.height, 32, maxh, 0, 0);
+ f->fmt.pix.field = field;
f->fmt.pix.bytesperline =
(f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage =
@@ -785,14 +787,15 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx8800_dev *dev = video_drvdata(file);
+ struct cx88_core *core = dev->core;
int err = vidioc_try_fmt_vid_cap (file,priv,f);
if (0 != err)
return err;
- dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
- dev->width = f->fmt.pix.width;
- dev->height = f->fmt.pix.height;
- dev->field = f->fmt.pix.field;
+ dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ core->width = f->fmt.pix.width;
+ core->height = f->fmt.pix.height;
+ core->field = f->fmt.pix.field;
return 0;
}
@@ -1343,7 +1346,6 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
/* initialize driver struct */
spin_lock_init(&dev->slock);
- core->tvnorm = V4L2_STD_NTSC_M;
/* init video dma queues */
INIT_LIST_HEAD(&dev->vidq.active);
@@ -1438,10 +1440,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
/* Sets device info at pci_dev */
pci_set_drvdata(pci_dev, dev);
- dev->width = 320;
- dev->height = 240;
- dev->field = V4L2_FIELD_INTERLACED;
- dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+ dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
/* initial device configuration */
mutex_lock(&core->lock);
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index dd50177..862c609 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -379,6 +379,8 @@ struct cx88_core {
/* state info */
struct task_struct *kthread;
v4l2_std_id tvnorm;
+ unsigned width, height;
+ unsigned field;
enum cx88_tvaudio tvaudio;
u32 audiomode_manual;
u32 audiomode_current;
@@ -479,8 +481,6 @@ struct cx8800_dev {
unsigned char pci_rev,pci_lat;
const struct cx8800_fmt *fmt;
- unsigned int width, height;
- unsigned field;
/* capture queues */
struct cx88_dmaqueue vidq;
@@ -557,9 +557,6 @@ struct cx8802_dev {
#if IS_ENABLED(CONFIG_VIDEO_CX88_BLACKBIRD)
struct video_device *mpeg_dev;
u32 mailbox;
- int width;
- int height;
- unsigned field;
unsigned char mpeg_active; /* nonzero if mpeg encoder is active */
/* mpeg params */
@@ -721,7 +718,7 @@ extern void cx88_i2c_init_ir(struct cx88_core *core);
/* cx88-mpeg.c */
int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
- struct cx88_buffer *buf, enum v4l2_field field);
+ struct cx88_buffer *buf);
void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf);
void cx8802_cancel_buffers(struct cx8802_dev *dev);
int cx8802_start_dma(struct cx8802_dev *dev,
--
2.1.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 12/16] cx88: drop mpeg_active field.
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
` (10 preceding siblings ...)
2014-09-20 12:41 ` [PATCH 11/16] cx88: move width, height and field to core struct Hans Verkuil
@ 2014-09-20 12:41 ` Hans Verkuil
2014-09-20 12:41 ` [PATCH 13/16] cx88: don't allow changes while vb2_is_busy Hans Verkuil
` (3 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
The vb2 framework knows if streaming is in progress, no need to use
a separate field for that.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/cx88/cx88-blackbird.c | 11 +++++------
drivers/media/pci/cx88/cx88.h | 1 -
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index 58e5254..13b8ed3 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -536,9 +536,6 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
dprintk(1,"Initialize codec\n");
retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
if (retval < 0) {
-
- dev->mpeg_active = 0;
-
/* ping was not successful, reset and upload firmware */
cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */
cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */
@@ -622,7 +619,6 @@ static int blackbird_start_codec(struct cx8802_dev *dev)
BLACKBIRD_RAW_BITS_NONE
);
- dev->mpeg_active = 1;
return 0;
}
@@ -636,7 +632,6 @@ static int blackbird_stop_codec(struct cx8802_dev *dev)
cx2341x_handler_set_busy(&dev->cxhdl, 0);
- dev->mpeg_active = 0;
return 0;
}
@@ -875,18 +870,22 @@ static int vidioc_s_frequency (struct file *file, void *priv,
{
struct cx8802_dev *dev = video_drvdata(file);
struct cx88_core *core = dev->core;
+ bool streaming;
if (unlikely(UNSET == core->board.tuner_type))
return -EINVAL;
if (unlikely(f->tuner != 0))
return -EINVAL;
- if (dev->mpeg_active)
+ streaming = dev->vb2_mpegq.start_streaming_called;
+ if (streaming)
blackbird_stop_codec(dev);
cx88_set_freq (core,f);
blackbird_initialize_codec(dev);
cx88_set_scale(core, core->width, core->height,
core->field);
+ if (streaming)
+ blackbird_start_codec(dev);
return 0;
}
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index 862c609..93bc7cf 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -557,7 +557,6 @@ struct cx8802_dev {
#if IS_ENABLED(CONFIG_VIDEO_CX88_BLACKBIRD)
struct video_device *mpeg_dev;
u32 mailbox;
- unsigned char mpeg_active; /* nonzero if mpeg encoder is active */
/* mpeg params */
struct cx2341x_handler cxhdl;
--
2.1.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 13/16] cx88: don't allow changes while vb2_is_busy
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
` (11 preceding siblings ...)
2014-09-20 12:41 ` [PATCH 12/16] cx88: drop mpeg_active field Hans Verkuil
@ 2014-09-20 12:41 ` Hans Verkuil
2014-09-20 12:41 ` [PATCH 14/16] cx88: consistently use UNSET for absent tuner Hans Verkuil
` (2 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
Make sure that changing the standard or format is not allowed while
one or more of the video, vbi or mpeg vb2 queues are busy.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/cx88/cx88-blackbird.c | 8 ++++++--
drivers/media/pci/cx88/cx88-core.c | 7 +++++++
drivers/media/pci/cx88/cx88-video.c | 14 +++++++++++---
drivers/media/pci/cx88/cx88.h | 13 +++++++++----
4 files changed, 33 insertions(+), 9 deletions(-)
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index 13b8ed3..ff79782 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -855,6 +855,11 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct cx8802_dev *dev = video_drvdata(file);
struct cx88_core *core = dev->core;
+ if (vb2_is_busy(&dev->vb2_mpegq))
+ return -EBUSY;
+ if (core->v4ldev && (vb2_is_busy(&core->v4ldev->vb2_vidq) ||
+ vb2_is_busy(&core->v4ldev->vb2_vbiq)))
+ return -EBUSY;
vidioc_try_fmt_vid_cap(file, priv, f);
core->width = f->fmt.pix.width;
core->height = f->fmt.pix.height;
@@ -1002,8 +1007,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
struct cx8802_dev *dev = video_drvdata(file);
struct cx88_core *core = dev->core;
- cx88_set_tvnorm(core, id);
- return 0;
+ return cx88_set_tvnorm(core, id);
}
static const struct v4l2_file_operations mpeg_fops =
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
index bbdbb58..9fa4acb 100644
--- a/drivers/media/pci/cx88/cx88-core.c
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -864,6 +864,13 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
u32 bdelay,agcdelay,htotal;
u32 cxiformat, cxoformat;
+ if (norm == core->tvnorm)
+ return 0;
+ if (core->v4ldev && (vb2_is_busy(&core->v4ldev->vb2_vidq) ||
+ vb2_is_busy(&core->v4ldev->vb2_vbiq)))
+ return -EBUSY;
+ if (core->dvbdev && vb2_is_busy(&core->dvbdev->vb2_mpegq))
+ return -EBUSY;
core->tvnorm = norm;
fsc8 = norm_fsc8(norm);
adc_clock = xtal;
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index eadceeb..64d6a72 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -792,6 +792,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
if (0 != err)
return err;
+ if (vb2_is_busy(&dev->vb2_vidq) || vb2_is_busy(&dev->vb2_vbiq))
+ return -EBUSY;
+ if (core->dvbdev && vb2_is_busy(&core->dvbdev->vb2_mpegq))
+ return -EBUSY;
dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
core->width = f->fmt.pix.width;
core->height = f->fmt.pix.height;
@@ -864,9 +868,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id tvnorms)
struct cx8800_dev *dev = video_drvdata(file);
struct cx88_core *core = dev->core;
- cx88_set_tvnorm(core, tvnorms);
-
- return 0;
+ return cx88_set_tvnorm(core, tvnorms);
}
/* only one input in this sample driver */
@@ -1442,6 +1444,9 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+ /* Maintain a reference so cx88-blackbird can query the 8800 device. */
+ core->v4ldev = dev;
+
/* initial device configuration */
mutex_lock(&core->lock);
cx88_set_tvnorm(core, core->tvnorm);
@@ -1544,6 +1549,7 @@ fail_unreg:
free_irq(pci_dev->irq, dev);
mutex_unlock(&core->lock);
fail_core:
+ core->v4ldev = NULL;
cx88_core_put(core,dev->pci);
fail_free:
kfree(dev);
@@ -1572,6 +1578,8 @@ static void cx8800_finidev(struct pci_dev *pci_dev)
free_irq(pci_dev->irq, dev);
cx8800_unregister_video(dev);
+ core->v4ldev = NULL;
+
/* free memory */
cx88_core_put(core,dev->pci);
kfree(dev);
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index 93bc7cf..2fa4aa9 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -334,6 +334,9 @@ struct cx88_dmaqueue {
u32 count;
};
+struct cx8800_dev;
+struct cx8802_dev;
+
struct cx88_core {
struct list_head devlist;
atomic_t refcount;
@@ -401,8 +404,13 @@ struct cx88_core {
/* various v4l controls */
u32 freq;
- /* cx88-video needs to access cx8802 for hybrid tuner pll access. */
+ /*
+ * cx88-video needs to access cx8802 for hybrid tuner pll access and
+ * for vb2_is_busy() checks.
+ */
struct cx8802_dev *dvbdev;
+ /* cx88-blackbird needs to access cx8800 for vb2_is_busy() checks */
+ struct cx8800_dev *v4ldev;
enum cx88_board_type active_type_id;
int active_ref;
int active_fe_id;
@@ -456,9 +464,6 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev)
val; \
})
-struct cx8800_dev;
-struct cx8802_dev;
-
/* ----------------------------------------------------------- */
/* function 0: video stuff */
--
2.1.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 14/16] cx88: consistently use UNSET for absent tuner
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
` (12 preceding siblings ...)
2014-09-20 12:41 ` [PATCH 13/16] cx88: don't allow changes while vb2_is_busy Hans Verkuil
@ 2014-09-20 12:41 ` Hans Verkuil
2014-09-20 12:41 ` [PATCH 15/16] cx88: pci_disable_device comes after free_irq Hans Verkuil
2014-09-20 12:41 ` [PATCH 16/16] cx88: fix VBI support Hans Verkuil
15 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
Don't mix UNSET and TUNER_ABSENT: you have to pick one or the other. For
this driver selecting UNSET to represent an absent tuner resulting in
the fewest changes.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/cx88/cx88-cards.c | 66 ++++++++++++++++++-------------------
drivers/media/pci/cx88/cx88-video.c | 2 +-
2 files changed, 34 insertions(+), 34 deletions(-)
diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c
index eb72185..6bace43 100644
--- a/drivers/media/pci/cx88/cx88-cards.c
+++ b/drivers/media/pci/cx88/cx88-cards.c
@@ -347,7 +347,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_IODATA_GVVCP3PCI] = {
.name = "IODATA GV-VCP3/PCI",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -436,7 +436,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_KWORLD_DVB_T] = {
.name = "KWorld/VStream XPert DVB-T",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -455,7 +455,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = {
.name = "DViCO FusionHDTV DVB-T1",
- .tuner_type = TUNER_ABSENT, /* No analog tuner */
+ .tuner_type = UNSET, /* No analog tuner */
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -542,7 +542,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_HAUPPAUGE_DVB_T1] = {
.name = "Hauppauge Nova-T DVB-T",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -554,7 +554,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_CONEXANT_DVB_T1] = {
.name = "Conexant DVB-T reference design",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -579,7 +579,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = {
.name = "DViCO FusionHDTV DVB-T Plus",
- .tuner_type = TUNER_ABSENT, /* No analog tuner */
+ .tuner_type = UNSET, /* No analog tuner */
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -596,7 +596,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_DNTV_LIVE_DVB_T] = {
.name = "digitalnow DNTV Live! DVB-T",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -787,7 +787,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_ADSTECH_DVB_T_PCI] = {
.name = "ADS Tech Instant TV DVB-T PCI",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -806,7 +806,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1] = {
.name = "TerraTec Cinergy 1400 DVB-T",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.input = {{
.type = CX88_VMUX_DVB,
.vmux = 0,
@@ -924,7 +924,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_WINFAST_DTV1000] = {
.name = "WinFast DTV1000-T",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -972,7 +972,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1] = {
.name = "Hauppauge Nova-S-Plus DVB-S",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -998,7 +998,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_HAUPPAUGE_NOVASE2_S1] = {
.name = "Hauppauge Nova-SE2 DVB-S",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1010,7 +1010,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_KWORLD_DVBS_100] = {
.name = "KWorld DVB-S 100",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1102,7 +1102,7 @@ static const struct cx88_board cx88_boards[] = {
/* DTT 7579 Conexant CX22702-19 Conexant CX2388x */
/* Manenti Marco <marco_manenti@colman.it> */
.name = "KWorld/VStream XPert DVB-T with cx22702",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1121,7 +1121,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL] = {
.name = "DViCO FusionHDTV DVB-T Dual Digital",
- .tuner_type = TUNER_ABSENT, /* No analog tuner */
+ .tuner_type = UNSET, /* No analog tuner */
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1356,7 +1356,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_GENIATECH_DVBS] = {
.name = "Geniatech DVB-S",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1494,7 +1494,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_SAMSUNG_SMT_7020] = {
.name = "Samsung SMT 7020 DVB-S",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1506,7 +1506,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_ADSTECH_PTV_390] = {
.name = "ADS Tech Instant Video PCI",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1553,7 +1553,7 @@ static const struct cx88_board cx88_boards[] = {
[CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = {
.name = "DViCO FusionHDTV 5 PCI nano",
/* xc3008 tuner, digital only for now */
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -2069,7 +2069,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_TBS_8920] = {
.name = "TBS 8920 DVB-S/S2",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -2304,7 +2304,7 @@ static const struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_TWINHAN_VP1027_DVBS] = {
.name = "Twinhan VP-1027 DVB-S",
- .tuner_type = TUNER_ABSENT,
+ .tuner_type = UNSET,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -2921,33 +2921,33 @@ static const struct {
int fm;
const char *name;
} gdi_tuner[] = {
- [ 0x01 ] = { .id = TUNER_ABSENT,
+ [ 0x01 ] = { .id = UNSET,
.name = "NTSC_M" },
- [ 0x02 ] = { .id = TUNER_ABSENT,
+ [ 0x02 ] = { .id = UNSET,
.name = "PAL_B" },
- [ 0x03 ] = { .id = TUNER_ABSENT,
+ [ 0x03 ] = { .id = UNSET,
.name = "PAL_I" },
- [ 0x04 ] = { .id = TUNER_ABSENT,
+ [ 0x04 ] = { .id = UNSET,
.name = "PAL_D" },
- [ 0x05 ] = { .id = TUNER_ABSENT,
+ [ 0x05 ] = { .id = UNSET,
.name = "SECAM" },
- [ 0x10 ] = { .id = TUNER_ABSENT,
+ [ 0x10 ] = { .id = UNSET,
.fm = 1,
.name = "TEMIC_4049" },
[ 0x11 ] = { .id = TUNER_TEMIC_4136FY5,
.name = "TEMIC_4136" },
- [ 0x12 ] = { .id = TUNER_ABSENT,
+ [ 0x12 ] = { .id = UNSET,
.name = "TEMIC_4146" },
[ 0x20 ] = { .id = TUNER_PHILIPS_FQ1216ME,
.fm = 1,
.name = "PHILIPS_FQ1216_MK3" },
- [ 0x21 ] = { .id = TUNER_ABSENT, .fm = 1,
+ [ 0x21 ] = { .id = UNSET, .fm = 1,
.name = "PHILIPS_FQ1236_MK3" },
- [ 0x22 ] = { .id = TUNER_ABSENT,
+ [ 0x22 ] = { .id = UNSET,
.name = "PHILIPS_FI1236_MK3" },
- [ 0x23 ] = { .id = TUNER_ABSENT,
+ [ 0x23 ] = { .id = UNSET,
.name = "PHILIPS_FI1216_MK3" },
};
@@ -3564,7 +3564,7 @@ static void cx88_card_setup(struct cx88_core *core)
mode_mask &= ~T_RADIO;
}
- if (core->board.tuner_type != TUNER_ABSENT) {
+ if (core->board.tuner_type != UNSET) {
tun_setup.mode_mask = mode_mask;
tun_setup.type = core->board.tuner_type;
tun_setup.addr = core->board.tuner_addr;
@@ -3777,7 +3777,7 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
cx88_i2c_init(core, pci);
/* load tuner module, if needed */
- if (TUNER_ABSENT != core->board.tuner_type) {
+ if (UNSET != core->board.tuner_type) {
/* Ignore 0x6b and 0x6f on cx88 boards.
* FusionHDTV5 RT Gold has an ir receiver at 0x6b
* and an RTC at 0x6f which can get corrupted if probed. */
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index 64d6a72..d8a86cd 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -1532,7 +1532,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
}
/* start tvaudio thread */
- if (core->board.tuner_type != TUNER_ABSENT) {
+ if (core->board.tuner_type != UNSET) {
core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio");
if (IS_ERR(core->kthread)) {
err = PTR_ERR(core->kthread);
--
2.1.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 15/16] cx88: pci_disable_device comes after free_irq.
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
` (13 preceding siblings ...)
2014-09-20 12:41 ` [PATCH 14/16] cx88: consistently use UNSET for absent tuner Hans Verkuil
@ 2014-09-20 12:41 ` Hans Verkuil
2014-09-20 12:41 ` [PATCH 16/16] cx88: fix VBI support Hans Verkuil
15 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
Move pci_disable_device() down otherwise it will complain about an
unfreed irq.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/cx88/cx88-video.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index d8a86cd..a64ae31 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -1571,12 +1571,12 @@ static void cx8800_finidev(struct pci_dev *pci_dev)
cx88_ir_stop(core);
cx88_shutdown(core); /* FIXME */
- pci_disable_device(pci_dev);
/* unregister stuff */
free_irq(pci_dev->irq, dev);
cx8800_unregister_video(dev);
+ pci_disable_device(pci_dev);
core->v4ldev = NULL;
--
2.1.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 16/16] cx88: fix VBI support
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
` (14 preceding siblings ...)
2014-09-20 12:41 ` [PATCH 15/16] cx88: pci_disable_device comes after free_irq Hans Verkuil
@ 2014-09-20 12:41 ` Hans Verkuil
15 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2014-09-20 12:41 UTC (permalink / raw)
To: linux-media; +Cc: Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
Now works with both NTSC and PAL. Tested with CC/XDS for NTSC and
teletext/WSS for PAL. The start lines were wrong, the WSS signal
wasn't captured and there was no difference between NTSC and PAL
w.r.t. the count[] values so NTSC returned way too many lines.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/pci/cx88/cx88-vbi.c | 28 ++++++++++++++++++++--------
drivers/media/pci/cx88/cx88.h | 3 ++-
2 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
index 042f545..6ab6e27 100644
--- a/drivers/media/pci/cx88/cx88-vbi.c
+++ b/drivers/media/pci/cx88/cx88-vbi.c
@@ -23,20 +23,22 @@ int cx8800_vbi_fmt (struct file *file, void *priv,
f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
f->fmt.vbi.offset = 244;
- f->fmt.vbi.count[0] = VBI_LINE_COUNT;
- f->fmt.vbi.count[1] = VBI_LINE_COUNT;
if (dev->core->tvnorm & V4L2_STD_525_60) {
/* ntsc */
f->fmt.vbi.sampling_rate = 28636363;
f->fmt.vbi.start[0] = 10;
f->fmt.vbi.start[1] = 273;
+ f->fmt.vbi.count[0] = VBI_LINE_NTSC_COUNT;
+ f->fmt.vbi.count[1] = VBI_LINE_NTSC_COUNT;
} else if (dev->core->tvnorm & V4L2_STD_625_50) {
/* pal */
f->fmt.vbi.sampling_rate = 35468950;
- f->fmt.vbi.start[0] = 7 -1;
- f->fmt.vbi.start[1] = 319 -1;
+ f->fmt.vbi.start[0] = V4L2_VBI_ITU_625_F1_START + 5;
+ f->fmt.vbi.start[1] = V4L2_VBI_ITU_625_F2_START + 5;
+ f->fmt.vbi.count[0] = VBI_LINE_PAL_COUNT;
+ f->fmt.vbi.count[1] = VBI_LINE_PAL_COUNT;
}
return 0;
}
@@ -111,8 +113,13 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
unsigned int *num_buffers, unsigned int *num_planes,
unsigned int sizes[], void *alloc_ctxs[])
{
+ struct cx8800_dev *dev = q->drv_priv;
+
*num_planes = 1;
- sizes[0] = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
+ if (dev->core->tvnorm & V4L2_STD_525_60)
+ sizes[0] = VBI_LINE_NTSC_COUNT * VBI_LINE_LENGTH * 2;
+ else
+ sizes[0] = VBI_LINE_PAL_COUNT * VBI_LINE_LENGTH * 2;
return 0;
}
@@ -122,10 +129,15 @@ static int buffer_prepare(struct vb2_buffer *vb)
struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
+ unsigned int lines;
unsigned int size;
int rc;
- size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
+ if (dev->core->tvnorm & V4L2_STD_525_60)
+ lines = VBI_LINE_NTSC_COUNT;
+ else
+ lines = VBI_LINE_PAL_COUNT;
+ size = lines * VBI_LINE_LENGTH * 2;
if (vb2_plane_size(vb, 0) < size)
return -EINVAL;
vb2_set_plane_payload(vb, 0, size);
@@ -135,9 +147,9 @@ static int buffer_prepare(struct vb2_buffer *vb)
return -EIO;
cx88_risc_buffer(dev->pci, &buf->risc, sgt->sgl,
- 0, VBI_LINE_LENGTH * VBI_LINE_COUNT,
+ 0, VBI_LINE_LENGTH * lines,
VBI_LINE_LENGTH, 0,
- VBI_LINE_COUNT);
+ lines);
return 0;
}
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index 2fa4aa9..3b0ae75 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -61,7 +61,8 @@
#define FORMAT_FLAGS_PACKED 0x01
#define FORMAT_FLAGS_PLANAR 0x02
-#define VBI_LINE_COUNT 17
+#define VBI_LINE_PAL_COUNT 18
+#define VBI_LINE_NTSC_COUNT 12
#define VBI_LINE_LENGTH 2048
#define AUD_RDS_LINES 4
--
2.1.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 02/16] cx88: drop the bogus 'queue' list in dmaqueue.
2014-09-20 12:41 ` [PATCH 02/16] cx88: drop the bogus 'queue' list in dmaqueue Hans Verkuil
@ 2014-10-28 18:58 ` Mauro Carvalho Chehab
2014-10-29 7:54 ` Hans Verkuil
0 siblings, 1 reply; 20+ messages in thread
From: Mauro Carvalho Chehab @ 2014-10-28 18:58 UTC (permalink / raw)
To: Hans Verkuil; +Cc: linux-media, Hans Verkuil
Em Sat, 20 Sep 2014 14:41:37 +0200
Hans Verkuil <hverkuil@xs4all.nl> escreveu:
> From: Hans Verkuil <hans.verkuil@cisco.com>
>
> This list is used some buffers have a different format, but that can
> never happen. Remove it and all associated code.
>
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
> drivers/media/pci/cx88/cx88-mpeg.c | 31 -----------------------------
> drivers/media/pci/cx88/cx88-video.c | 39 +++----------------------------------
> drivers/media/pci/cx88/cx88.h | 1 -
> 3 files changed, 3 insertions(+), 68 deletions(-)
>
> diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
> index 2803b6f..5f59901 100644
> --- a/drivers/media/pci/cx88/cx88-mpeg.c
> +++ b/drivers/media/pci/cx88/cx88-mpeg.c
> @@ -210,37 +210,7 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
>
> dprintk( 1, "cx8802_restart_queue\n" );
> if (list_empty(&q->active))
> - {
> - struct cx88_buffer *prev;
> - prev = NULL;
> -
> - dprintk(1, "cx8802_restart_queue: queue is empty\n" );
This is not bogus code. What happens here is that sometimes the DMA
engine stops on cx88 and it needs to be restarted under some temporary
errors.
I don't remember the exact condition, as I don't touch on cx88 on
several years, but I think it happens when the signal drops (for
example, if the antenna cable gets removed, but not 100% sure).
So, removing this code will cause regressions.
Regards,
Mauro
> -
> - for (;;) {
> - if (list_empty(&q->queued))
> - return 0;
> - buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
> - if (NULL == prev) {
> - list_move_tail(&buf->vb.queue, &q->active);
> - cx8802_start_dma(dev, q, buf);
> - buf->vb.state = VIDEOBUF_ACTIVE;
> - buf->count = q->count++;
> - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
> - dprintk(1,"[%p/%d] restart_queue - first active\n",
> - buf,buf->vb.i);
> -
> - } else {
> - list_move_tail(&buf->vb.queue, &q->active);
> - buf->vb.state = VIDEOBUF_ACTIVE;
> - buf->count = q->count++;
> - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
> - dprintk(1,"[%p/%d] restart_queue - move to active\n",
> - buf,buf->vb.i);
> - }
> - prev = buf;
> - }
> return 0;
> - }
>
> buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
> dprintk(2,"restart_queue [%p/%d]: restart dma\n",
> @@ -486,7 +456,6 @@ static int cx8802_init_common(struct cx8802_dev *dev)
>
> /* init dma queue */
> INIT_LIST_HEAD(&dev->mpegq.active);
> - INIT_LIST_HEAD(&dev->mpegq.queued);
> dev->mpegq.timeout.function = cx8802_timeout;
> dev->mpegq.timeout.data = (unsigned long)dev;
> init_timer(&dev->mpegq.timeout);
> diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
> index 3075179..10fea4d 100644
> --- a/drivers/media/pci/cx88/cx88-video.c
> +++ b/drivers/media/pci/cx88/cx88-video.c
> @@ -470,7 +470,7 @@ static int restart_video_queue(struct cx8800_dev *dev,
> struct cx88_dmaqueue *q)
> {
> struct cx88_core *core = dev->core;
> - struct cx88_buffer *buf, *prev;
> + struct cx88_buffer *buf;
>
> if (!list_empty(&q->active)) {
> buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
> @@ -480,33 +480,8 @@ static int restart_video_queue(struct cx8800_dev *dev,
> list_for_each_entry(buf, &q->active, vb.queue)
> buf->count = q->count++;
> mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
> - return 0;
> - }
> -
> - prev = NULL;
> - for (;;) {
> - if (list_empty(&q->queued))
> - return 0;
> - buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
> - if (NULL == prev) {
> - list_move_tail(&buf->vb.queue, &q->active);
> - start_video_dma(dev, q, buf);
> - buf->vb.state = VIDEOBUF_ACTIVE;
> - buf->count = q->count++;
> - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
> - dprintk(2,"[%p/%d] restart_queue - first active\n",
> - buf,buf->vb.i);
> -
> - } else {
> - list_move_tail(&buf->vb.queue, &q->active);
> - buf->vb.state = VIDEOBUF_ACTIVE;
> - buf->count = q->count++;
> - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
> - dprintk(2,"[%p/%d] restart_queue - move to active\n",
> - buf,buf->vb.i);
> - }
> - prev = buf;
> }
> + return 0;
> }
>
> /* ------------------------------------------------------------------ */
> @@ -613,13 +588,7 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
> buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
> buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
>
> - if (!list_empty(&q->queued)) {
> - list_add_tail(&buf->vb.queue,&q->queued);
> - buf->vb.state = VIDEOBUF_QUEUED;
> - dprintk(2,"[%p/%d] buffer_queue - append to queued\n",
> - buf, buf->vb.i);
> -
> - } else if (list_empty(&q->active)) {
> + if (list_empty(&q->active)) {
> list_add_tail(&buf->vb.queue,&q->active);
> start_video_dma(dev, q, buf);
> buf->vb.state = VIDEOBUF_ACTIVE;
> @@ -1694,7 +1663,6 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
>
> /* init video dma queues */
> INIT_LIST_HEAD(&dev->vidq.active);
> - INIT_LIST_HEAD(&dev->vidq.queued);
> dev->vidq.timeout.function = cx8800_vid_timeout;
> dev->vidq.timeout.data = (unsigned long)dev;
> init_timer(&dev->vidq.timeout);
> @@ -1703,7 +1671,6 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
>
> /* init vbi dma queues */
> INIT_LIST_HEAD(&dev->vbiq.active);
> - INIT_LIST_HEAD(&dev->vbiq.queued);
> dev->vbiq.timeout.function = cx8800_vbi_timeout;
> dev->vbiq.timeout.data = (unsigned long)dev;
> init_timer(&dev->vbiq.timeout);
> diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
> index ddc7991..77ec542 100644
> --- a/drivers/media/pci/cx88/cx88.h
> +++ b/drivers/media/pci/cx88/cx88.h
> @@ -324,7 +324,6 @@ struct cx88_buffer {
>
> struct cx88_dmaqueue {
> struct list_head active;
> - struct list_head queued;
> struct timer_list timeout;
> struct btcx_riscmem stopper;
> u32 count;
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 02/16] cx88: drop the bogus 'queue' list in dmaqueue.
2014-10-28 18:58 ` Mauro Carvalho Chehab
@ 2014-10-29 7:54 ` Hans Verkuil
2014-10-29 8:42 ` Mauro Carvalho Chehab
0 siblings, 1 reply; 20+ messages in thread
From: Hans Verkuil @ 2014-10-29 7:54 UTC (permalink / raw)
To: Mauro Carvalho Chehab; +Cc: linux-media, Hans Verkuil
On 10/28/2014 07:58 PM, Mauro Carvalho Chehab wrote:
> Em Sat, 20 Sep 2014 14:41:37 +0200
> Hans Verkuil <hverkuil@xs4all.nl> escreveu:
>
>> From: Hans Verkuil <hans.verkuil@cisco.com>
>>
>> This list is used some buffers have a different format, but that can
>> never happen. Remove it and all associated code.
Urgh. Can you fix the commit log to:
"This list is only used if the width, height and/or format of a buffer has
changed, but that can never happen. Remove it and all associated code."
At least that's proper English :-)
>>
>> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
>> ---
>> drivers/media/pci/cx88/cx88-mpeg.c | 31 -----------------------------
>> drivers/media/pci/cx88/cx88-video.c | 39 +++----------------------------------
>> drivers/media/pci/cx88/cx88.h | 1 -
>> 3 files changed, 3 insertions(+), 68 deletions(-)
>>
>> diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
>> index 2803b6f..5f59901 100644
>> --- a/drivers/media/pci/cx88/cx88-mpeg.c
>> +++ b/drivers/media/pci/cx88/cx88-mpeg.c
>> @@ -210,37 +210,7 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
>>
>> dprintk( 1, "cx8802_restart_queue\n" );
>> if (list_empty(&q->active))
>> - {
>> - struct cx88_buffer *prev;
>> - prev = NULL;
>> -
>> - dprintk(1, "cx8802_restart_queue: queue is empty\n" );
>
> This is not bogus code. What happens here is that sometimes the DMA
> engine stops on cx88 and it needs to be restarted under some temporary
> errors.
>
> I don't remember the exact condition, as I don't touch on cx88 on
> several years, but I think it happens when the signal drops (for
> example, if the antenna cable gets removed, but not 100% sure).
>
> So, removing this code will cause regressions.
No, it won't. Read carefully how the 'queued' list is used: the only time
that an element is added to that list is in buffer_queue() if the width, height
or format has changed while streaming. But that can never happen (at least,
not after REQBUFS) and that case was removed in patch 01/16. So after patch
01/16 nobody is ever adding buffers to the queued list anymore and it can be
removed.
This patch has nothing to do with restarting DMA. Patch 04/16 is the one that
removes the restarting of DMA.
I did a fair amount of regression and duration testing to see if I could
reproduce a stopped DMA without being able to. I'm fairly certain that included
switching frequency between valid/invalid channels, but I can retry that just to
be sure.
I am very skeptical that this really has to do with DMA issues: it looks much more
like a poorly written driver. As my commit log to patch 04 says the cx88 driver
allows userspace to drain all buffers and at that moment it has to halt the DMA
and restart when a new buffer is queued up. But it is much simpler and more
robust to just keep streaming by always keeping one buffer around, just as almost
all other non-usb drivers do.
I have not been able to find any reports that actually mention that the DMA can
stop. The same change was done to cx23885 and no reports of any DMA problems have
been reported for that either, and I expect that both devices use very similar
DMA IP.
Regards,
Hans
>
> Regards,
> Mauro
>
>> -
>> - for (;;) {
>> - if (list_empty(&q->queued))
>> - return 0;
>> - buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
>> - if (NULL == prev) {
>> - list_move_tail(&buf->vb.queue, &q->active);
>> - cx8802_start_dma(dev, q, buf);
>> - buf->vb.state = VIDEOBUF_ACTIVE;
>> - buf->count = q->count++;
>> - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
>> - dprintk(1,"[%p/%d] restart_queue - first active\n",
>> - buf,buf->vb.i);
>> -
>> - } else {
>> - list_move_tail(&buf->vb.queue, &q->active);
>> - buf->vb.state = VIDEOBUF_ACTIVE;
>> - buf->count = q->count++;
>> - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
>> - dprintk(1,"[%p/%d] restart_queue - move to active\n",
>> - buf,buf->vb.i);
>> - }
>> - prev = buf;
>> - }
>> return 0;
>> - }
>>
>> buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
>> dprintk(2,"restart_queue [%p/%d]: restart dma\n",
>> @@ -486,7 +456,6 @@ static int cx8802_init_common(struct cx8802_dev *dev)
>>
>> /* init dma queue */
>> INIT_LIST_HEAD(&dev->mpegq.active);
>> - INIT_LIST_HEAD(&dev->mpegq.queued);
>> dev->mpegq.timeout.function = cx8802_timeout;
>> dev->mpegq.timeout.data = (unsigned long)dev;
>> init_timer(&dev->mpegq.timeout);
>> diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
>> index 3075179..10fea4d 100644
>> --- a/drivers/media/pci/cx88/cx88-video.c
>> +++ b/drivers/media/pci/cx88/cx88-video.c
>> @@ -470,7 +470,7 @@ static int restart_video_queue(struct cx8800_dev *dev,
>> struct cx88_dmaqueue *q)
>> {
>> struct cx88_core *core = dev->core;
>> - struct cx88_buffer *buf, *prev;
>> + struct cx88_buffer *buf;
>>
>> if (!list_empty(&q->active)) {
>> buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
>> @@ -480,33 +480,8 @@ static int restart_video_queue(struct cx8800_dev *dev,
>> list_for_each_entry(buf, &q->active, vb.queue)
>> buf->count = q->count++;
>> mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
>> - return 0;
>> - }
>> -
>> - prev = NULL;
>> - for (;;) {
>> - if (list_empty(&q->queued))
>> - return 0;
>> - buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
>> - if (NULL == prev) {
>> - list_move_tail(&buf->vb.queue, &q->active);
>> - start_video_dma(dev, q, buf);
>> - buf->vb.state = VIDEOBUF_ACTIVE;
>> - buf->count = q->count++;
>> - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
>> - dprintk(2,"[%p/%d] restart_queue - first active\n",
>> - buf,buf->vb.i);
>> -
>> - } else {
>> - list_move_tail(&buf->vb.queue, &q->active);
>> - buf->vb.state = VIDEOBUF_ACTIVE;
>> - buf->count = q->count++;
>> - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
>> - dprintk(2,"[%p/%d] restart_queue - move to active\n",
>> - buf,buf->vb.i);
>> - }
>> - prev = buf;
>> }
>> + return 0;
>> }
>>
>> /* ------------------------------------------------------------------ */
>> @@ -613,13 +588,7 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
>> buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
>> buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
>>
>> - if (!list_empty(&q->queued)) {
>> - list_add_tail(&buf->vb.queue,&q->queued);
>> - buf->vb.state = VIDEOBUF_QUEUED;
>> - dprintk(2,"[%p/%d] buffer_queue - append to queued\n",
>> - buf, buf->vb.i);
>> -
>> - } else if (list_empty(&q->active)) {
>> + if (list_empty(&q->active)) {
>> list_add_tail(&buf->vb.queue,&q->active);
>> start_video_dma(dev, q, buf);
>> buf->vb.state = VIDEOBUF_ACTIVE;
>> @@ -1694,7 +1663,6 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
>>
>> /* init video dma queues */
>> INIT_LIST_HEAD(&dev->vidq.active);
>> - INIT_LIST_HEAD(&dev->vidq.queued);
>> dev->vidq.timeout.function = cx8800_vid_timeout;
>> dev->vidq.timeout.data = (unsigned long)dev;
>> init_timer(&dev->vidq.timeout);
>> @@ -1703,7 +1671,6 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
>>
>> /* init vbi dma queues */
>> INIT_LIST_HEAD(&dev->vbiq.active);
>> - INIT_LIST_HEAD(&dev->vbiq.queued);
>> dev->vbiq.timeout.function = cx8800_vbi_timeout;
>> dev->vbiq.timeout.data = (unsigned long)dev;
>> init_timer(&dev->vbiq.timeout);
>> diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
>> index ddc7991..77ec542 100644
>> --- a/drivers/media/pci/cx88/cx88.h
>> +++ b/drivers/media/pci/cx88/cx88.h
>> @@ -324,7 +324,6 @@ struct cx88_buffer {
>>
>> struct cx88_dmaqueue {
>> struct list_head active;
>> - struct list_head queued;
>> struct timer_list timeout;
>> struct btcx_riscmem stopper;
>> u32 count;
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 02/16] cx88: drop the bogus 'queue' list in dmaqueue.
2014-10-29 7:54 ` Hans Verkuil
@ 2014-10-29 8:42 ` Mauro Carvalho Chehab
0 siblings, 0 replies; 20+ messages in thread
From: Mauro Carvalho Chehab @ 2014-10-29 8:42 UTC (permalink / raw)
To: Hans Verkuil; +Cc: linux-media, Hans Verkuil
Em Wed, 29 Oct 2014 08:54:20 +0100
Hans Verkuil <hverkuil@xs4all.nl> escreveu:
> On 10/28/2014 07:58 PM, Mauro Carvalho Chehab wrote:
> > Em Sat, 20 Sep 2014 14:41:37 +0200
> > Hans Verkuil <hverkuil@xs4all.nl> escreveu:
> >
> >> From: Hans Verkuil <hans.verkuil@cisco.com>
> >>
> >> This list is used some buffers have a different format, but that can
> >> never happen. Remove it and all associated code.
>
> Urgh. Can you fix the commit log to:
>
> "This list is only used if the width, height and/or format of a buffer has
> changed, but that can never happen. Remove it and all associated code."
>
> At least that's proper English :-)
Well, change it and resubmit ;) - After our discussions, of course.
>
> >>
> >> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> >> ---
> >> drivers/media/pci/cx88/cx88-mpeg.c | 31 -----------------------------
> >> drivers/media/pci/cx88/cx88-video.c | 39 +++----------------------------------
> >> drivers/media/pci/cx88/cx88.h | 1 -
> >> 3 files changed, 3 insertions(+), 68 deletions(-)
> >>
> >> diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
> >> index 2803b6f..5f59901 100644
> >> --- a/drivers/media/pci/cx88/cx88-mpeg.c
> >> +++ b/drivers/media/pci/cx88/cx88-mpeg.c
> >> @@ -210,37 +210,7 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
> >>
> >> dprintk( 1, "cx8802_restart_queue\n" );
> >> if (list_empty(&q->active))
> >> - {
> >> - struct cx88_buffer *prev;
> >> - prev = NULL;
> >> -
> >> - dprintk(1, "cx8802_restart_queue: queue is empty\n" );
> >
> > This is not bogus code. What happens here is that sometimes the DMA
> > engine stops on cx88 and it needs to be restarted under some temporary
> > errors.
> >
> > I don't remember the exact condition, as I don't touch on cx88 on
> > several years, but I think it happens when the signal drops (for
> > example, if the antenna cable gets removed, but not 100% sure).
> >
> > So, removing this code will cause regressions.
>
> No, it won't. Read carefully how the 'queued' list is used: the only time
> that an element is added to that list is in buffer_queue() if the width, height
> or format has changed while streaming. But that can never happen (at least,
> not after REQBUFS) and that case was removed in patch 01/16. So after patch
> 01/16 nobody is ever adding buffers to the queued list anymore and it can be
> removed.
>
> This patch has nothing to do with restarting DMA. Patch 04/16 is the one that
> removes the restarting of DMA.
>
> I did a fair amount of regression and duration testing to see if I could
> reproduce a stopped DMA without being able to. I'm fairly certain that included
> switching frequency between valid/invalid channels, but I can retry that just to
> be sure.
If I remember well, it is not switching between valid/invalid. That
happens if the signal is not too stable (e. g., either the chrominance
or luminance or audio carrier is not properly detected). You would likely
need a life weak signal and/or too much interference to be able to get it.
I'm pretty sure I got those "cx8802_restart_queue: " from time to time
without changing any parameters, during "normal" reception of some weak
channels where I used to live (basically, using internal antennas).
> I am very skeptical that this really has to do with DMA issues: it looks much more
> like a poorly written driver. As my commit log to patch 04 says the cx88 driver
> allows userspace to drain all buffers and at that moment it has to halt the DMA
> and restart when a new buffer is queued up. But it is much simpler and more
> robust to just keep streaming by always keeping one buffer around, just as almost
> all other non-usb drivers do.
>
> I have not been able to find any reports that actually mention that the DMA can
> stop. The same change was done to cx23885 and no reports of any DMA problems have
> been reported for that either, and I expect that both devices use very similar
> DMA IP.
Hmm... could be. I may try to test it with an internal antenna, but this can
take some time, as I'm currently trying to get rid of the patch backlog,
and I have other priorities to work after handling the backlog.
Regards,
Mauro
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2014-10-29 8:42 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-20 12:41 [PATCH 00/16] cx88: convert to vb2 Hans Verkuil
2014-09-20 12:41 ` [PATCH 01/16] cx88: remove fmt from the buffer struct Hans Verkuil
2014-09-20 12:41 ` [PATCH 02/16] cx88: drop the bogus 'queue' list in dmaqueue Hans Verkuil
2014-10-28 18:58 ` Mauro Carvalho Chehab
2014-10-29 7:54 ` Hans Verkuil
2014-10-29 8:42 ` Mauro Carvalho Chehab
2014-09-20 12:41 ` [PATCH 03/16] cx88: drop videobuf abuse in cx88-alsa Hans Verkuil
2014-09-20 12:41 ` [PATCH 04/16] cx88: convert to vb2 Hans Verkuil
2014-09-20 12:41 ` [PATCH 05/16] cx88: fix sparse warning Hans Verkuil
2014-09-20 12:41 ` [PATCH 06/16] cx88: return proper errors during fw load Hans Verkuil
2014-09-20 12:41 ` [PATCH 07/16] cx88: drop cx88_free_buffer Hans Verkuil
2014-09-20 12:41 ` [PATCH 08/16] cx88: remove dependency on btcx-risc Hans Verkuil
2014-09-20 12:41 ` [PATCH 09/16] cx88: increase API command timeout Hans Verkuil
2014-09-20 12:41 ` [PATCH 10/16] cx88: don't pollute the kernel log Hans Verkuil
2014-09-20 12:41 ` [PATCH 11/16] cx88: move width, height and field to core struct Hans Verkuil
2014-09-20 12:41 ` [PATCH 12/16] cx88: drop mpeg_active field Hans Verkuil
2014-09-20 12:41 ` [PATCH 13/16] cx88: don't allow changes while vb2_is_busy Hans Verkuil
2014-09-20 12:41 ` [PATCH 14/16] cx88: consistently use UNSET for absent tuner Hans Verkuil
2014-09-20 12:41 ` [PATCH 15/16] cx88: pci_disable_device comes after free_irq Hans Verkuil
2014-09-20 12:41 ` [PATCH 16/16] cx88: fix VBI support Hans Verkuil
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).