[PATCH 2/12] Update saa7146 capture core
From: Michael Hunold
Date: Fri Dec 19 2003 - 07:58:16 EST
V4L: - fix a bunch of race conditions and locking bugs in video and vbi capture code on device closure
V4L: - use vmalloc_32() instead of vmalloc() in saa7146_vmalloc_build_pgtable(). this makes sure that the pagetable is in lowmem kernel memory
V4L: - i2c timeout fix by Gerd Knorr
V4L: - SAA7146_I2C_SHORT_DELAY flag to speed up I2C access by Oliver Endriss
V4L: - move saa7146_set_gpio() from saa7146_vv to saa7146_core, it's needed by DVB budget drivers
V4L: - add "new" saa7146_wait_for_debi_done() function, remove other versions from av7110 and budget.ci
V4L: - make budget-ci use this gpio function and the new wait_...() function,
V4L: - make saa7146_pgtable_build_single() deliver a return code, make sanity checks of the arguments
V4L: - sanitize enabling of video input pins and i2c pins, use some default values, so the hardware is always in a sane state
V4L: - remove SAA7146_EXT_SWAP_ODD_EVEN flag + handling, fix the hardware initialization instead
V4L: - change minimal picture size to 48x32 just like other drivers
V4L: - set up arbitrition control for video dma3 correctly
V4L: - remove unnecessary code for capture to framebuffer memory, it's handled in the generic code
diff -uNrwB --new-file linux-2.6.0/drivers/media/common/saa7146_core.c linux-2.6.0-p/drivers/media/common/saa7146_core.c
--- linux-2.6.0/drivers/media/common/saa7146_core.c 2003-12-18 03:59:06.000000000 +0100
+++ linux-2.6.0-p/drivers/media/common/saa7146_core.c 2003-12-17 14:00:22.000000000 +0100
@@ -45,10 +45,65 @@
#endif
/****************************************************************************
+ * gpio and debi helper functions
+ ****************************************************************************/
+
+/* write "data" to the gpio-pin "pin" */
+void saa7146_set_gpio(struct saa7146_dev *dev, u8 pin, u8 data)
+{
+ u32 value = 0;
+
+ /* sanity check */
+ if(pin > 3)
+ return;
+
+ /* read old register contents */
+ value = saa7146_read(dev, GPIO_CTRL );
+
+ value &= ~(0xff << (8*pin));
+ value |= (data << (8*pin));
+
+ saa7146_write(dev, GPIO_CTRL, value);
+}
+
+/* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */
+int saa7146_wait_for_debi_done(struct saa7146_dev *dev)
+{
+ int start;
+
+ /* wait for registers to be programmed */
+ start = jiffies;
+ while (1) {
+ if (saa7146_read(dev, MC2) & 2)
+ break;
+ if (jiffies-start > HZ/20) {
+ DEB_S(("timed out while waiting for registers getting programmed\n"));
+ return -ETIMEDOUT;
+ }
+ }
+
+ /* wait for transfer to complete */
+ start = jiffies;
+ while (1) {
+ if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S))
+ break;
+ saa7146_read(dev, MC2);
+ if (jiffies-start > HZ/4) {
+ DEB_S(("timed out while waiting for transfer completion\n"));
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+/****************************************************************************
* general helper functions
****************************************************************************/
-/* this is videobuf_vmalloc_to_sg() from video-buf.c */
+/* this is videobuf_vmalloc_to_sg() from video-buf.c
+ make sure virt has been allocated with vmalloc_32(), otherwise the BUG()
+ may be triggered on highmem machines */
static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
{
struct scatterlist *sglist;
@@ -84,7 +139,7 @@
{
struct scatterlist *slist = NULL;
int pages = (length+PAGE_SIZE-1)/PAGE_SIZE;
- char *mem = vmalloc(length);
+ char *mem = vmalloc_32(length);
int slen = 0;
if (NULL == mem) {
@@ -103,7 +158,9 @@
}
slen = pci_map_sg(pci,slist,pages,PCI_DMA_FROMDEVICE);
- saa7146_pgtable_build_single(pci, pt, slist, slen);
+ if (0 != saa7146_pgtable_build_single(pci, pt, slist, slen)) {
+ return NULL;
+ }
/* fixme: here's a memory leak: slist never gets freed by any other
function ...*/
@@ -139,7 +196,7 @@
return 0;
}
-void saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
+int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
struct scatterlist *list, int sglen )
{
u32 *ptr, fill;
@@ -148,6 +205,11 @@
BUG_ON( 0 == sglen);
+ if (list->offset > PAGE_SIZE) {
+ DEB_D(("offset > PAGE_SIZE. this should not happen."));
+ return -EINVAL;
+ }
+
/* if we have a user buffer, the first page may not be
aligned to a page boundary. */
pt->offset = list->offset;
@@ -177,6 +239,7 @@
printk("ptr1 %d: 0x%08x\n",i,ptr[i]);
}
*/
+ return 0;
}
/********************************************************************************/
@@ -322,7 +384,7 @@
saa7146_write(dev, MC1, MASK_31);
*/
- /* disable alle irqs */
+ /* disable all irqs */
saa7146_write(dev, IER, 0);
/* shut down all dma transfers */
@@ -381,8 +443,8 @@
dev->module = THIS_MODULE;
init_waitqueue_head(&dev->i2c_wq);
- /* set some default values */
- saa7146_write(dev, BCS_CTRL, 0x80400040);
+ /* set some sane pci arbitrition values */
+ saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
if( 0 != ext->probe) {
if( 0 != ext->probe(dev) ) {
@@ -508,6 +570,7 @@
EXPORT_SYMBOL_GPL(saa7146_pgtable_free);
EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single);
EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable);
+EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done);
EXPORT_SYMBOL_GPL(saa7146_setgpio);
diff -uNrwB --new-file linux-2.6.0/drivers/media/common/saa7146_fops.c linux-2.6.0-p/drivers/media/common/saa7146_fops.c
--- linux-2.6.0/drivers/media/common/saa7146_fops.c 2003-12-18 03:58:49.000000000 +0100
+++ linux-2.6.0-p/drivers/media/common/saa7146_fops.c 2003-12-18 12:18:53.000000000 +0100
@@ -86,7 +86,7 @@
return;
}
- DEB_EE(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi));
+ DEB_INT(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi));
#if DEBUG_SPINLOCKS
BUG_ON(!spin_is_locked(&dev->slock));
@@ -98,10 +98,10 @@
if (!list_empty(&q->queue))
next = list_entry(q->queue.next,struct saa7146_buf, vb.queue);
q->curr = buf;
- DEB_D(("next buffer: buf:%p, prev:%p, next:%p\n", buf, q->queue.prev,q->queue.next));
+ DEB_INT(("next buffer: buf:%p, prev:%p, next:%p\n", buf, q->queue.prev,q->queue.next));
buf->activate(dev,buf,next);
} else {
- DEB_D(("no next buffer. stopping.\n"));
+ DEB_INT(("no next buffer. stopping.\n"));
if( 0 != vbi ) {
/* turn off video-dma3 */
saa7146_write(dev,MC1, MASK_20);
@@ -229,10 +229,10 @@
if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
DEB_S(("initializing vbi...\n"));
- saa7146_vbi_uops.open(dev,fh);
+ saa7146_vbi_uops.open(dev,file);
} else {
DEB_S(("initializing video...\n"));
- saa7146_video_uops.open(dev,fh);
+ saa7146_video_uops.open(dev,file);
}
result = 0;
@@ -255,9 +255,9 @@
return -ERESTARTSYS;
if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
- saa7146_vbi_uops.release(dev,fh,file);
+ saa7146_vbi_uops.release(dev,file);
} else {
- saa7146_video_uops.release(dev,fh,file);
+ saa7146_video_uops.release(dev,file);
}
module_put(dev->ext->module);
@@ -372,7 +372,7 @@
{
u32 isr = status;
- DEB_EE(("dev:%p, isr:0x%08x\n",dev,(u32)status));
+ DEB_INT(("dev:%p, isr:0x%08x\n",dev,(u32)status));
if (0 != (isr & (MASK_27))) {
DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
@@ -410,6 +410,12 @@
DEB_EE(("dev:%p\n",dev));
+ /* set default values for video parts of the saa7146 */
+ saa7146_write(dev, BCS_CTRL, 0x80400040);
+
+ /* enable video-port pins */
+ saa7146_write(dev, MC1, (MASK_10 | MASK_26));
+
/* save per-device extension data (one extension can
handle different devices that might need different
configuration data) */
diff -uNrwB --new-file linux-2.6.0/drivers/media/common/saa7146_hlp.c linux-2.6.0-p/drivers/media/common/saa7146_hlp.c
--- linux-2.6.0/drivers/media/common/saa7146_hlp.c 2003-12-18 03:58:58.000000000 +0100
+++ linux-2.6.0-p/drivers/media/common/saa7146_hlp.c 2003-11-20 11:01:06.000000000 +0100
@@ -660,24 +660,6 @@
vv->current_hps_sync = sync;
}
-/* write "data" to the gpio-pin "pin" */
-void saa7146_set_gpio(struct saa7146_dev *dev, u8 pin, u8 data)
-{
- u32 value = 0;
-
- /* sanity check */
- if(pin > 3)
- return;
-
- /* read old register contents */
- value = saa7146_read(dev, GPIO_CTRL );
-
- value &= ~(0xff << (8*pin));
- value |= (data << (8*pin));
-
- saa7146_write(dev, GPIO_CTRL, value);
-}
-
/* reprogram hps, enable(1) / disable(0) video */
void saa7146_set_overlay(struct saa7146_dev *dev, struct saa7146_fh *fh, int v)
{
@@ -710,13 +692,15 @@
/* calculate starting address */
where = (which-1)*0x18;
+/*
if( 0 != (dev->ext_vv_data->flags & SAA7146_EXT_SWAP_ODD_EVEN)) {
saa7146_write(dev, where, vdma->base_even);
saa7146_write(dev, where+0x04, vdma->base_odd);
} else {
+*/
saa7146_write(dev, where, vdma->base_odd);
saa7146_write(dev, where+0x04, vdma->base_even);
- }
+// }
saa7146_write(dev, where+0x08, vdma->prot_addr);
saa7146_write(dev, where+0x0c, vdma->pitch);
saa7146_write(dev, where+0x10, vdma->base_page);
@@ -971,12 +955,13 @@
unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B;
unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
+/*
if( 0 != (dev->ext_vv_data->flags & SAA7146_EXT_SWAP_ODD_EVEN)) {
unsigned long tmp = e_wait;
e_wait = o_wait;
o_wait = tmp;
}
-
+*/
/* wait for o_fid_a/b / e_fid_a/b toggle only if rps register 0 is not set*/
WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | o_wait);
WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | e_wait);
diff -uNrwB --new-file linux-2.6.0/drivers/media/common/saa7146_i2c.c linux-2.6.0-p/drivers/media/common/saa7146_i2c.c
--- linux-2.6.0/drivers/media/common/saa7146_i2c.c 2003-12-18 03:59:44.000000000 +0100
+++ linux-2.6.0-p/drivers/media/common/saa7146_i2c.c 2003-12-10 14:06:57.000000000 +0100
@@ -186,7 +186,7 @@
{
u32 status = 0, mc2 = 0;
int trial = 0;
- int timeout;
+ unsigned long timeout;
/* write out i2c-command */
DEB_I2C(("before: 0x%08x (status: 0x%08x), %d\n",*dword,saa7146_read(dev, I2C_STATUS), dev->i2c_op));
@@ -218,7 +218,7 @@
if( 0 != mc2 ) {
break;
}
- if (jiffies > timeout) {
+ if (time_after(jiffies,timeout)) {
printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for MC2\n");
return -EIO;
}
@@ -233,7 +233,7 @@
status = saa7146_i2c_status(dev);
if ((status & 0x3) != 1)
break;
- if (jiffies > timeout) {
+ if (time_after(jiffies,timeout)) {
/* this is normal when probing the bus
* (no answer from nonexisistant device...)
*/
@@ -301,7 +301,8 @@
goto out;
}
- if (count > 3) short_delay = 1;
+ if ( count > 3 || 0 != (SAA7146_I2C_SHORT_DELAY & dev->ext->flags) )
+ short_delay = 1;
do {
/* reset the i2c-device if necessary */
@@ -403,19 +404,29 @@
{
DEB_EE(("bitrate: 0x%08x\n",bitrate));
+ /* enable i2c-port pins */
+ saa7146_write(dev, MC1, (MASK_08 | MASK_24));
+
dev->i2c_bitrate = bitrate;
saa7146_i2c_reset(dev);
if( NULL != i2c_adapter ) {
memset(i2c_adapter,0,sizeof(struct i2c_adapter));
strcpy(i2c_adapter->name, dev->name);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+ i2c_adapter->data = dev;
+#else
i2c_set_adapdata(i2c_adapter,dev);
- i2c_adapter->class = I2C_ADAP_CLASS_TV_ANALOG;
+#endif
i2c_adapter->algo = &saa7146_algo;
i2c_adapter->algo_data = NULL;
i2c_adapter->id = I2C_ALGO_SAA7146;
i2c_adapter->timeout = SAA7146_I2C_TIMEOUT;
i2c_adapter->retries = SAA7146_I2C_RETRIES;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#else
+ i2c_adapter->class = I2C_ADAP_CLASS_TV_ANALOG;
+#endif
}
return 0;
diff -uNrwB --new-file linux-2.6.0/drivers/media/common/saa7146_vbi.c linux-2.6.0-p/drivers/media/common/saa7146_vbi.c
--- linux-2.6.0/drivers/media/common/saa7146_vbi.c 2003-12-18 03:57:59.000000000 +0100
+++ linux-2.6.0-p/drivers/media/common/saa7146_vbi.c 2003-12-15 21:51:01.000000000 +0100
@@ -41,7 +41,11 @@
/* wait for vbi_a or vbi_b*/
if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
DEB_D(("...using port b\n"));
+ WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_E_FID_B);
+ WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_O_FID_B);
+/*
WRITE_RPS1(CMD_PAUSE | MASK_09);
+*/
} else {
DEB_D(("...using port a\n"));
WRITE_RPS1(CMD_PAUSE | MASK_10);
@@ -137,10 +141,10 @@
unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
/*
- vdma3.base_even = (u32)dev->ov_fb.base+2048*70;
- vdma3.base_odd = (u32)dev->ov_fb.base;
- vdma3.prot_addr = (u32)dev->ov_fb.base+2048*164;
- vdma3.pitch = 2048;
+ vdma3.base_even = 0xc8000000+2560*70;
+ vdma3.base_odd = 0xc8000000;
+ vdma3.prot_addr = 0xc8000000+2560*164;
+ vdma3.pitch = 2560;
vdma3.base_page = 0;
vdma3.num_line_byte = (64<<16)|((vbi_pixel_to_capture)<<0); // set above!
*/
@@ -244,7 +249,9 @@
err = videobuf_iolock(dev->pci,&buf->vb,NULL);
if (err)
goto oops;
- saa7146_pgtable_build_single(dev->pci, &buf->pt[2], buf->vb.dma.sglist, buf->vb.dma.sglen);
+ err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2], buf->vb.dma.sglist, buf->vb.dma.sglen);
+ if (0 != err)
+ return err;
}
buf->vb.state = STATE_PREPARED;
buf->activate = buffer_activate;
@@ -303,7 +310,7 @@
/* ------------------------------------------------------------------ */
-static void vbi_stop(struct saa7146_fh *fh)
+static void vbi_stop(struct saa7146_fh *fh, struct file *file)
{
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
@@ -321,23 +328,29 @@
/* shut down dma 3 transfers */
saa7146_write(dev, MC1, MASK_20);
+ if (vv->vbi_q.curr) {
+ saa7146_buffer_finish(dev,&vv->vbi_q,STATE_DONE);
+ }
+
+ videobuf_queue_cancel(file,&fh->vbi_q);
+
vv->vbi_streaming = NULL;
del_timer(&vv->vbi_q.timeout);
del_timer(&fh->vbi_read_timeout);
- DEB_VBI(("out\n"));
spin_unlock_irqrestore(&dev->slock, flags);
}
static void vbi_read_timeout(unsigned long data)
{
- struct saa7146_fh *fh = (struct saa7146_fh *)data;
+ struct file *file = (struct file*)data;
+ struct saa7146_fh *fh = file->private_data;
struct saa7146_dev *dev = fh->dev;
DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
- vbi_stop(fh);
+ vbi_stop(fh, file);
}
static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
@@ -354,10 +367,21 @@
init_waitqueue_head(&vv->vbi_wq);
}
-static void vbi_open(struct saa7146_dev *dev, struct saa7146_fh *fh)
+static void vbi_open(struct saa7146_dev *dev, struct file *file)
{
+ struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
+
+ u32 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
+ int ret = 0;
+
DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
+ /* adjust arbitrition control for video dma 3 */
+ arbtr_ctrl &= ~0x1f0000;
+ arbtr_ctrl |= 0x1d0000;
+ saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
+ saa7146_write(dev, MC2, (MASK_04|MASK_20));
+
memset(&fh->vbi_fmt,0,sizeof(fh->vbi_fmt));
fh->vbi_fmt.sampling_rate = 27000000;
@@ -380,21 +404,32 @@
init_timer(&fh->vbi_read_timeout);
fh->vbi_read_timeout.function = vbi_read_timeout;
- fh->vbi_read_timeout.data = (unsigned long)fh;
+ fh->vbi_read_timeout.data = (unsigned long)file;
- /* fixme: enable this again, if the dvb-c w/ analog module work properly */
-/*
- vbi_workaround(dev);
-*/
+ /* initialize the brs */
+ if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
+ saa7146_write(dev, BRS_CTRL, MASK_30|MASK_29 | (7 << 19));
+ } else {
+ saa7146_write(dev, BRS_CTRL, 0x00000001);
+
+ if (0 != (ret = vbi_workaround(dev))) {
+ DEB_VBI(("vbi workaround failed!\n"));
+ /* return ret;*/
+ }
+ }
+
+ /* upload brs register */
+ saa7146_write(dev, MC2, (MASK_08|MASK_24));
}
-static void vbi_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct file *file)
+static void vbi_close(struct saa7146_dev *dev, struct file *file)
{
+ struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
struct saa7146_vv *vv = dev->vv_data;
DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
if( fh == vv->vbi_streaming ) {
- vbi_stop(fh);
+ vbi_stop(fh, file);
}
}
diff -uNrwB --new-file linux-2.6.0/drivers/media/common/saa7146_video.c linux-2.6.0-p/drivers/media/common/saa7146_video.c
--- linux-2.6.0/drivers/media/common/saa7146_video.c 2003-12-18 03:59:05.000000000 +0100
+++ linux-2.6.0-p/drivers/media/common/saa7146_video.c 2003-12-17 14:00:22.000000000 +0100
@@ -116,7 +116,7 @@
DEB_D(("no fb fmt set.\n"));
return -EINVAL;
}
- if (win->w.width < 64 || win->w.height < 64) {
+ if (win->w.width < 48 || win->w.height < 32) {
DEB_D(("min width/height. (%d,%d)\n",win->w.width,win->w.height));
return -EINVAL;
}
@@ -661,7 +661,7 @@
*/
} else {
struct saa7146_pgtable *pt = &buf->pt[0];
- saa7146_pgtable_build_single(pci, pt, list, length);
+ return saa7146_pgtable_build_single(pci, pt, list, length);
}
return 0;
@@ -704,7 +704,7 @@
return 0;
}
-static int video_end(struct saa7146_fh *fh)
+static int video_end(struct saa7146_fh *fh, struct file *file)
{
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
@@ -735,82 +735,11 @@
saa7146_write(dev, MC1, 0x00700000);
vv->streaming = NULL;
- spin_unlock_irqrestore(&dev->slock, flags);
-
- return 0;
-}
-
-/* capturing to framebuffer */
-
-int overlay_reqbufs(struct saa7146_dev *dev, struct v4l2_requestbuffers *req)
-{
-/* struct saa7146_fh *fh = file->private_data;
- if (req->count > VIDEO_MAX_FRAME)
- req->count = VIDEO_MAX_FRAME;
-
- *size = fh->video_fmt.sizeimage;
-
-*/
- return 0;
-}
-int overlay_querybuf(struct saa7146_dev *dev, struct v4l2_buffer *buf)
-{
- return 0;
-}
-int overlay_qbuf(struct saa7146_dev *dev, struct v4l2_buffer *b)
-{
-/* if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) {
- DEB_D(("index %d out of bounds.\n",b->index));
- goto -EINVAL;
- }
-
- buf = q->bufs[b->index];
- if (NULL == buf) {
- printk("videobuf_qbuf: NULL == buf\n");
- goto done;
- }
- if (0 == buf->baddr) {
- printk("videobuf_qbuf: 0 == buf->baddr\n");
- goto done;
- }
- if (buf->state == STATE_QUEUED ||
- buf->state == STATE_ACTIVE) {
- printk("videobuf_qbuf: already queued or activated.\n");
- goto done;
- }
-
- field = videobuf_next_field(q);
- retval = q->ops->buf_prepare(file,buf,field);
- if (0 != retval) {
- printk("videobuf_qbuf: buf_prepare() failed.\n");
- goto done;
- }
+ videobuf_queue_cancel(file,&fh->video_q);
- list_add_tail(&buf->stream,&q->stream);
- if (q->streaming) {
- spin_lock_irqsave(q->irqlock,flags);
- q->ops->buf_queue(file,buf);
- spin_unlock_irqrestore(q->irqlock,flags);
- }
- retval = 0;
+ spin_unlock_irqrestore(&dev->slock, flags);
- done:
- up(&q->lock);
- return retval;
-*/
- return 0;
-}
-int overlay_dqbuf(struct saa7146_dev *dev, struct v4l2_buffer *buf)
-{
- return 0;
-}
-int overlay_streamon(struct saa7146_dev *dev)
-{
- return 0;
-}
-int overlay_streamoff(struct saa7146_dev *dev)
-{
return 0;
}
@@ -818,7 +746,7 @@
/*
* This function is _not_ called directly, but from
* video_generic_ioctl (and maybe others). userspace
- * copying is done already, arg is a kernel fhinter.
+ * copying is done already, arg is a kernel pointer.
*/
int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg)
@@ -1141,38 +1069,24 @@
case VIDIOC_REQBUFS: {
struct v4l2_requestbuffers *req = arg;
DEB_D(("VIDIOC_REQBUFS, type:%d\n",req->type));
-/*
- if( req->type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
- return overlay_reqbufs(dev,req);
- }
-*/
return videobuf_reqbufs(file,q,req);
}
case VIDIOC_QUERYBUF: {
struct v4l2_buffer *buf = arg;
DEB_D(("VIDIOC_QUERYBUF, type:%d, offset:%d\n",buf->type,buf->m.offset));
-/* if( buf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
- return overlay_querybuf(dev,buf);
- }
- */ return videobuf_querybuf(q,buf);
+ return videobuf_querybuf(q,buf);
}
case VIDIOC_QBUF: {
struct v4l2_buffer *buf = arg;
int ret = 0;
-/* if( buf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
- return overlay_qbuf(dev,buf);
- }
- */ ret = videobuf_qbuf(file,q,buf);
+ ret = videobuf_qbuf(file,q,buf);
DEB_D(("VIDIOC_QBUF: ret:%d, index:%d\n",ret,buf->index));
return ret;
}
case VIDIOC_DQBUF: {
struct v4l2_buffer *buf = arg;
int ret = 0;
-/* if( buf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
- return overlay_dqbuf(dev,buf);
- }
- */ ret = videobuf_dqbuf(file,q,buf);
+ ret = videobuf_dqbuf(file,q,buf);
DEB_D(("VIDIOC_DQBUF: ret:%d, index:%d\n",ret,buf->index));
return ret;
}
@@ -1180,29 +1094,18 @@
int *type = arg;
DEB_D(("VIDIOC_STREAMON, type:%d\n",*type));
- if( 0 != ops->capture_begin ) {
- if( 0 != (err = ops->capture_begin(fh))) {
+ if( 0 != (err = video_begin(fh))) {
return err;
}
- }
-/* if( *type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
- err = overlay_streamon(dev);
- } else { */
err = videobuf_streamon(file,q);
-/* } */
return err;
}
case VIDIOC_STREAMOFF: {
int *type = arg;
DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type));
- if( 0 != ops->capture_end ) {
- ops->capture_end(fh);
- }
-/* if( *type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
- return overlay_streamoff(dev);
- }
- */ err = videobuf_streamoff(file,q);
+ video_end(fh, file);
+ err = videobuf_streamoff(file,q);
return err;
}
case VIDIOCGMBUF:
@@ -1267,8 +1170,8 @@
DEB_CAP(("vbuf:%p\n",vb));
/* sanity checks */
- if (fh->video_fmt.width < 64 ||
- fh->video_fmt.height < 64 ||
+ if (fh->video_fmt.width < 48 ||
+ fh->video_fmt.height < 32 ||
fh->video_fmt.width > vv->standard->h_max_out ||
fh->video_fmt.height > vv->standard->v_max_out) {
DEB_D(("w (%d) / h (%d) out of bounds.\n",fh->video_fmt.width,fh->video_fmt.height));
@@ -1407,8 +1310,9 @@
}
-static void video_open(struct saa7146_dev *dev, struct saa7146_fh *fh)
+static void video_open(struct saa7146_dev *dev, struct file *file)
{
+ struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
struct saa7146_format *sfmt;
fh->video_fmt.width = 384;
@@ -1429,8 +1333,9 @@
}
-static void video_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct file *file)
+static void video_close(struct saa7146_dev *dev, struct file *file)
{
+ struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
struct saa7146_vv *vv = dev->vv_data;
unsigned long flags;
@@ -1443,10 +1348,8 @@
}
if( fh == vv->streaming ) {
- video_end(fh);
+ video_end(fh, file);
}
-
- videobuf_queue_cancel(file,&fh->video_q);
}
@@ -1489,7 +1392,7 @@
return -EAGAIN;
}
ret = videobuf_read_one(file,&fh->video_q , data, count, ppos);
- video_end(fh);
+ video_end(fh, file);
/* restart overlay if it was active before */
if( 0 != restart_overlay ) {
@@ -1505,6 +1408,4 @@
.release = video_close,
.irq_done = video_irq_done,
.read = video_read,
- .capture_begin = video_begin,
- .capture_end = video_end,
};
diff -uNrwB --new-file linux-2.6.0/include/media/saa7146.h linux-2.6.0-p/include/media/saa7146.h
--- linux-2.6.0/include/media/saa7146.h 2003-12-18 03:58:04.000000000 +0100
+++ linux-2.6.0-p/include/media/saa7146.h 2003-12-08 16:19:01.000000000 +0100
@@ -87,6 +87,7 @@
{
char name[32]; /* name of the device */
#define SAA7146_USE_I2C_IRQ 0x1
+#define SAA7146_I2C_SHORT_DELAY 0x2
int flags;
/* pairs of subvendor and subdevice ids for
@@ -162,9 +163,10 @@
struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc);
int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt);
void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt);
-void saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length );
+int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length );
char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt);
void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data);
+int saa7146_wait_for_debi_done(struct saa7146_dev *dev);
/* some memory sizes */
#define SAA7146_I2C_MEM ( 1*PAGE_SIZE)
@@ -187,6 +189,9 @@
#define SAA7146_GPIO_OUTLO 0x40
#define SAA7146_GPIO_OUTHI 0x50
+/* debi defines */
+#define DEBINOSWAP 0x000e0000
+
/* define for the register programming sequencer (rps) */
#define CMD_NOP 0x00000000 /* No operation */
#define CMD_CLR_EVENT 0x00000000 /* Clear event */
diff -uNrwB --new-file linux-2.6.0/include/media/saa7146_vv.h linux-2.6.0-p/include/media/saa7146_vv.h
--- linux-2.6.0/include/media/saa7146_vv.h 2003-12-18 03:58:08.000000000 +0100
+++ linux-2.6.0-p/include/media/saa7146_vv.h 2003-12-17 14:00:22.000000000 +0100
@@ -149,7 +149,7 @@
};
/* flags */
-#define SAA7146_EXT_SWAP_ODD_EVEN 0x1 /* needs odd/even fields swapped */
+// #define SAA7146_EXT_SWAP_ODD_EVEN 0x1 /* needs odd/even fields swapped */
#define SAA7146_USE_PORT_B_FOR_VBI 0x2 /* use input port b for vbi hardware bug workaround */
struct saa7146_ext_vv
@@ -171,12 +171,10 @@
struct saa7146_use_ops {
void (*init)(struct saa7146_dev *, struct saa7146_vv *);
- void(*open)(struct saa7146_dev *, struct saa7146_fh *);
- void (*release)(struct saa7146_dev *, struct saa7146_fh *,struct file *);
+ void(*open)(struct saa7146_dev *, struct file *);
+ void (*release)(struct saa7146_dev *, struct file *);
void (*irq_done)(struct saa7146_dev *, unsigned long status);
ssize_t (*read)(struct file *, char *, size_t, loff_t *);
- int (*capture_begin)(struct saa7146_fh *);
- int (*capture_end)(struct saa7146_fh *);
};
/* from saa7146_fops.c */
diff -ura linux-2.6.0.p/drivers/media/common/saa7146_video.c linux-2.6.0.p2/drivers/media/common/saa7146_video.c
--- linux-2.6.0.p/drivers/media/common/saa7146_video.c 2003-12-19 10:38:46.000000000 +0100
+++ linux-2.6.0.p2/drivers/media/common/saa7146_video.c 2003-12-19 10:40:43.000000000 +0100
@@ -736,8 +736,6 @@
vv->streaming = NULL;
- videobuf_queue_cancel(file,&fh->video_q);
-
spin_unlock_irqrestore(&dev->slock, flags);
return 0;
@@ -1105,8 +1103,8 @@
int *type = arg;
DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type));
- video_end(fh, file);
err = videobuf_streamoff(file,q);
+ video_end(fh, file);
return err;
}
case VIDIOCGMBUF:
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/