From: Michael Hunold fix a bunch of race conditions and locking bugs in video and vbi capture code on device closure use vmalloc_32() instead of vmalloc() in saa7146_vmalloc_build_pgtable(). this makes sure that the pagetable is in lowmem kernel memory i2c timeout fix by Gerd Knorr SAA7146_I2C_SHORT_DELAY flag to speed up I2C access by Oliver Endriss move saa7146_set_gpio() from saa7146_vv to saa7146_core, it's needed by DVB budget drivers add "new" saa7146_wait_for_debi_done() function, remove other versions from av7110 and budget.ci make budget-ci use this gpio function and the new wait_...() function, make saa7146_pgtable_build_single() deliver a return code, make sanity checks of the arguments sanitize enabling of video input pins and i2c pins, use some default values, so the hardware is always in a sane state remove SAA7146_EXT_SWAP_ODD_EVEN flag + handling, fix the hardware initialization instead change minimal picture size to 48x32 just like other drivers set up arbitrition control for video dma3 correctly remove unnecessary code for capture to framebuffer memory, it's handled in the generic code 25-akpm/drivers/media/common/saa7146_core.c | 78 +++++++++++++-- 25-akpm/drivers/media/common/saa7146_fops.c | 22 ++-- 25-akpm/drivers/media/common/saa7146_hlp.c | 25 ---- 25-akpm/drivers/media/common/saa7146_i2c.c | 15 ++ 25-akpm/drivers/media/common/saa7146_vbi.c | 68 +++++++++---- 25-akpm/drivers/media/common/saa7146_video.c | 138 +++------------------------ 25-akpm/include/media/saa7146.h | 7 + 25-akpm/include/media/saa7146_vv.h | 8 - 8 files changed, 182 insertions(+), 179 deletions(-) diff -puN drivers/media/common/saa7146_core.c~dvb-02-update-saa7146-capture-core drivers/media/common/saa7146_core.c --- 25/drivers/media/common/saa7146_core.c~dvb-02-update-saa7146-capture-core Fri Dec 19 14:53:31 2003 +++ 25-akpm/drivers/media/common/saa7146_core.c Fri Dec 19 14:53:31 2003 @@ -45,10 +45,65 @@ static void dump_registers(struct saa714 #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 @@ char *saa7146_vmalloc_build_pgtable(stru { 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 @@ char *saa7146_vmalloc_build_pgtable(stru } 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 @@ int saa7146_pgtable_alloc(struct pci_dev 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 @@ void saa7146_pgtable_build_single(struct 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 @@ void saa7146_pgtable_build_single(struct printk("ptr1 %d: 0x%08x\n",i,ptr[i]); } */ + return 0; } /********************************************************************************/ @@ -322,7 +385,7 @@ static int saa7146_init_one(struct pci_d saa7146_write(dev, MC1, MASK_31); */ - /* disable alle irqs */ + /* disable all irqs */ saa7146_write(dev, IER, 0); /* shut down all dma transfers */ @@ -381,8 +444,8 @@ static int saa7146_init_one(struct pci_d 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 +571,7 @@ EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc) 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 -puN drivers/media/common/saa7146_fops.c~dvb-02-update-saa7146-capture-core drivers/media/common/saa7146_fops.c --- 25/drivers/media/common/saa7146_fops.c~dvb-02-update-saa7146-capture-core Fri Dec 19 14:53:31 2003 +++ 25-akpm/drivers/media/common/saa7146_fops.c Fri Dec 19 14:53:31 2003 @@ -86,7 +86,7 @@ void saa7146_buffer_next(struct saa7146_ 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 @@ void saa7146_buffer_next(struct saa7146_ 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 @@ static int fops_open(struct inode *inode 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 @@ static int fops_release(struct inode *in 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 @@ void vv_callback(struct saa7146_dev *dev { 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 @@ int saa7146_vv_init(struct saa7146_dev* 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 -puN drivers/media/common/saa7146_hlp.c~dvb-02-update-saa7146-capture-core drivers/media/common/saa7146_hlp.c --- 25/drivers/media/common/saa7146_hlp.c~dvb-02-update-saa7146-capture-core Fri Dec 19 14:53:31 2003 +++ 25-akpm/drivers/media/common/saa7146_hlp.c Fri Dec 19 14:53:31 2003 @@ -660,24 +660,6 @@ void saa7146_set_hps_source_and_sync(str 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 @@ void saa7146_write_out_dma(struct saa714 /* 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 @@ static void program_capture_engine(struc 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 -puN drivers/media/common/saa7146_i2c.c~dvb-02-update-saa7146-capture-core drivers/media/common/saa7146_i2c.c --- 25/drivers/media/common/saa7146_i2c.c~dvb-02-update-saa7146-capture-core Fri Dec 19 14:53:31 2003 +++ 25-akpm/drivers/media/common/saa7146_i2c.c Fri Dec 19 14:53:34 2003 @@ -301,7 +301,8 @@ int saa7146_i2c_transfer(struct saa7146_ 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 @@ int saa7146_i2c_adapter_prepare(struct s { 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 -puN drivers/media/common/saa7146_vbi.c~dvb-02-update-saa7146-capture-core drivers/media/common/saa7146_vbi.c --- 25/drivers/media/common/saa7146_vbi.c~dvb-02-update-saa7146-capture-core Fri Dec 19 14:53:31 2003 +++ 25-akpm/drivers/media/common/saa7146_vbi.c Fri Dec 19 14:53:34 2003 @@ -41,7 +41,11 @@ static int vbi_workaround(struct saa7146 /* 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 @@ void saa7146_set_vbi_capture(struct saa7 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 +248,9 @@ static int buffer_prepare(struct file *f 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 +309,7 @@ static struct videobuf_queue_ops vbi_qop /* ------------------------------------------------------------------ */ -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 +327,29 @@ static void vbi_stop(struct saa7146_fh * /* 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 +366,21 @@ static void vbi_init(struct saa7146_dev 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 +403,32 @@ static void vbi_open(struct saa7146_dev 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 -puN drivers/media/common/saa7146_video.c~dvb-02-update-saa7146-capture-core drivers/media/common/saa7146_video.c --- 25/drivers/media/common/saa7146_video.c~dvb-02-update-saa7146-capture-core Fri Dec 19 14:53:31 2003 +++ 25-akpm/drivers/media/common/saa7146_video.c Fri Dec 19 14:53:34 2003 @@ -116,7 +116,7 @@ static int try_win(struct saa7146_dev *d 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 @@ static int saa7146_pgtable_build(struct */ } 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 @@ static int video_begin(struct saa7146_fh 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,9 @@ static int video_end(struct saa7146_fh * 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; - } - - 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 +745,7 @@ int overlay_streamoff(struct saa7146_dev /* * 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 +1068,24 @@ int saa7146_video_do_ioctl(struct inode 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 +1093,18 @@ int saa7146_video_do_ioctl(struct inode 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); + err = videobuf_streamoff(file,q); + video_end(fh, file); return err; } case VIDIOCGMBUF: @@ -1267,8 +1169,8 @@ static int buffer_prepare(struct file *f 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 +1309,9 @@ static void video_init(struct saa7146_de } -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 +1332,9 @@ static void video_open(struct saa7146_de } -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 +1347,8 @@ static void video_close(struct saa7146_d } if( fh == vv->streaming ) { - video_end(fh); + video_end(fh, file); } - - videobuf_queue_cancel(file,&fh->video_q); } @@ -1489,7 +1391,7 @@ static ssize_t video_read(struct file *f 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 +1407,4 @@ struct saa7146_use_ops saa7146_video_uop .release = video_close, .irq_done = video_irq_done, .read = video_read, - .capture_begin = video_begin, - .capture_end = video_end, }; diff -puN include/media/saa7146.h~dvb-02-update-saa7146-capture-core include/media/saa7146.h --- 25/include/media/saa7146.h~dvb-02-update-saa7146-capture-core Fri Dec 19 14:53:31 2003 +++ 25-akpm/include/media/saa7146.h Fri Dec 19 14:53:34 2003 @@ -87,6 +87,7 @@ struct saa7146_extension { 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 @@ int saa7146_unregister_extension(struct 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 @@ void saa7146_setgpio(struct saa7146_dev #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 -puN include/media/saa7146_vv.h~dvb-02-update-saa7146-capture-core include/media/saa7146_vv.h --- 25/include/media/saa7146_vv.h~dvb-02-update-saa7146-capture-core Fri Dec 19 14:53:31 2003 +++ 25-akpm/include/media/saa7146_vv.h Fri Dec 19 14:53:34 2003 @@ -149,7 +149,7 @@ struct saa7146_extension_ioctls }; /* 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_ext_vv 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 */ _