diff options
author | Michael Hunold <devnull@localhost> | 2002-12-29 22:15:54 +0000 |
---|---|---|
committer | Michael Hunold <devnull@localhost> | 2002-12-29 22:15:54 +0000 |
commit | 4ac441dd0b30a80cdcf026cc2952cc547bf5dbad (patch) | |
tree | 4c3a932425b22564f32df85049cc7674052b7702 /linux | |
parent | bc7712bb01e71d41013f0b642740832819849d30 (diff) | |
download | mediapointer-dvb-s2-4ac441dd0b30a80cdcf026cc2952cc547bf5dbad.tar.gz mediapointer-dvb-s2-4ac441dd0b30a80cdcf026cc2952cc547bf5dbad.tar.bz2 |
Major cleanup: the goal is to get rid of the budget card <=> saa7146.o <=> videodev.o dependency,
so we can later split up the av7110 driver into a av7110 and budget card driver.
I tested this on 2.4.18-3 (original RedHat 7.3 kernel) and 2.5.53.
Changes in detail:
saa7146:
- fixed the unitialised timer warnings
- split saa7146.o into saa7146.o and saa7146_vv.o:
all videodev (ie. v4l) related stuff is now encapsulated in saa7146_vv.o.
the extension (ie. mxb or dvb-ttpci) now has to make sure to register the v4l
devices via helper functions provided by saa7146_vv
mxb:
- changes to make the driver compile with the new saa7146 and saa7146_vv parts
- fix the vbi bypass issue for MXBs with saa7146, rev. 1 card
av7110:
- changes to make the driver compile with the new saa7146 and saa7146_vv parts
- some changes related to the upcoming av7110 <=> budget splitup, but they are
commented out
- changed the saa7146 PAL values to experimental values that look good to me, but
kept the old values as a comment. where are the original values from? there is
a big black border on most channels on the left side which annoyed me...
- changed from video/generic_usercopy() to dvb_usercopy() and put this into the
source code, not into compat.c
- moved the crc_32* stuff from compat.c to the source file where it is used
- now compat.[ch] was removed completely, all references were deleted from
all other files.
other:
- updated the README and TODO files
- changed "makelinks" to remove alps_bsru6 stuff from kernel when making the symlinks
- fixed the build files in "build-2.4"
- fixed all other files needed for 2.5.x kernel build
Diffstat (limited to 'linux')
23 files changed, 766 insertions, 749 deletions
diff --git a/linux/drivers/media/common/Makefile b/linux/drivers/media/common/Makefile index 5ececd228..526bf968c 100644 --- a/linux/drivers/media/common/Makefile +++ b/linux/drivers/media/common/Makefile @@ -1,8 +1,8 @@ -export-objs := video-buf.o +export-objs := saa7146_core.o saa7146_fops.o saa7146_video.o saa7146_vbi.o video-buf.o -saa7146-objs := saa7146_core.o saa7146_hlp.o saa7146_i2c.o \ - saa7146_vbi.o saa7146_video.o +saa7146-objs := saa7146_i2c.o saa7146_core.o +saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o obj-$(CONFIG_VIDEO_VIDEOBUF) += video-buf.o -obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o +obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o saa7146_vv.o diff --git a/linux/drivers/media/common/saa7146.h b/linux/drivers/media/common/saa7146.h index 4fd023dd5..b35b14672 100644 --- a/linux/drivers/media/common/saa7146.h +++ b/linux/drivers/media/common/saa7146.h @@ -35,8 +35,6 @@ from flaws in video-buf.c => Gerd Knorr */ #endif #endif -#define BOARD_CAN_DO_VBI(dev) (dev->revision != 0 && 0 != dev->ext->vbi) - extern unsigned int saa7146_debug; //#define DEBUG_PROLOG printk("(0x%08x)(0x%08x) %s: %s(): ",(dev==0?-1:(dev->mem==0?-1:saa7146_read(dev,RPS_ADDR0))),(dev==0?-1:(dev->mem==0?-1:saa7146_read(dev,IER))),__stringify(KBUILD_MODNAME),__FUNCTION__) @@ -77,9 +75,7 @@ struct saa7146_sub_info { #define SAA7146_AFTER 0x4 /* flags */ -#define SAA7146_EXT_PROVIDES_VIDEO 0x1 /* provides vbi device */ -#define SAA7146_EXT_PROVIDES_VBI 0x2 /* provides vbi device */ -#define SAA7146_EXT_SWAP_ODD_EVEN 0x4 /* needs odd/even fields swapped */ +#define SAA7146_EXT_SWAP_ODD_EVEN 0x1 /* needs odd/even fields swapped */ struct saa7146_extension { @@ -88,7 +84,7 @@ struct saa7146_extension int audios; u32 capabilities; - int flags; + int flags; struct list_head item; @@ -107,9 +103,7 @@ struct saa7146_extension struct saa7146_standard *stds; int num_stds; int (*std_callback)(struct saa7146_dev*, struct saa7146_standard *); - - int (*vbi)(struct saa7146_dev*); // want vbi - + struct saa7146_extension_ioctls *ioctls; /* extension functions */ @@ -191,7 +185,7 @@ struct saa7146_dmaqueue { }; struct saa7146_overlay { - struct saa7146_fh *fh; + struct saa7146_fh *fh; struct v4l2_window win; struct v4l2_clip clips[16]; int nclips; @@ -201,7 +195,7 @@ struct saa7146_overlay { struct saa7146_fh { struct saa7146_dev *dev; /* if this is a vbi or capture open */ - enum v4l2_buf_type type; + enum v4l2_buf_type type; /* video overlay */ struct saa7146_overlay ov; @@ -218,11 +212,8 @@ struct saa7146_fh { struct saa7146_dev { - struct video_device video_dev; - struct video_device vbi_dev; - /* used for loadable modules */ - struct module *module; + struct module *module; struct list_head item; @@ -231,7 +222,7 @@ struct saa7146_dev struct semaphore lock; struct semaphore i2c_lock; - unsigned char* mem; /* pointer to mapped IO memory */ + unsigned char *mem; /* pointer to mapped IO memory */ int revision; /* chip revision; needed for bug-workarounds*/ /* pci-device & irq stuff*/ @@ -239,19 +230,23 @@ struct saa7146_dev struct pci_dev *pci; /* extension handling */ - struct saa7146_extension* ext; /* indicates if handled by extension */ - void* ext_priv; /* pointer for extension private use (most likely some private data) */ + struct saa7146_extension *ext; /* indicates if handled by extension */ + void *ext_priv; /* pointer for extension private use (most likely some private data) */ + int video_minor, vbi_minor; + + void (*video_irq_done)(struct saa7146_dev *dev, unsigned long status); + void (*vbi_irq_done)(struct saa7146_dev *dev, unsigned long status); /* i2c-stuff */ u32 i2c_bitrate; - u32* i2c_mem; /* pointer to i2c memory */ + u32 *i2c_mem; /* pointer to i2c memory */ wait_queue_head_t i2c_wq; int i2c_op; /* memories */ - u32* clipping; /* pointer to clipping memory */ - u32* rps0; - u32* rps1; + u32 *clipping; /* pointer to clipping memory */ + u32 *rps0; + u32 *rps1; /* vbi capture */ struct saa7146_dmaqueue vbi_q; @@ -276,6 +271,7 @@ struct saa7146_dev all opens? currently, we do the latter, like all other drivers do... */ struct saa7146_standard *standard; + int vflip; int hflip; int current_hps_source; @@ -293,6 +289,10 @@ struct saa7146_use_ops { int (*capture_end)(struct saa7146_fh *fh); }; +/* from saa7146_fops.c */ +int saa7146_register_device(struct video_device *vid, struct saa7146_dev* dev, char *name, int type); +int saa7146_unregister_device(struct video_device *vid, struct saa7146_dev* dev); + /* from saa7146_i2c.c */ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate); int saa7146_i2c_transfer(struct saa7146_dev *saa, const struct i2c_msg msgs[], int num, int retries); @@ -306,6 +306,9 @@ void saa7146_set_hps_source_and_sync(struct saa7146_dev *saa, int source, int sy void saa7146_set_gpio(struct saa7146_dev *saa, u8 pin, u8 data); /* from saa7146_core.c */ +extern struct list_head saa7146_devices; +extern struct semaphore saa7146_devices_lock; + int saa7146_register_extension(struct saa7146_extension*); int saa7146_unregister_extension(struct saa7146_extension*); struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc); @@ -322,7 +325,6 @@ void saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *p /* from saa7146_video.c */ extern struct saa7146_use_ops saa7146_video_uops; -int video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg); /* from saa7146_vbi.c */ extern struct saa7146_use_ops saa7146_vbi_uops; diff --git a/linux/drivers/media/common/saa7146_core.c b/linux/drivers/media/common/saa7146_core.c index 46ce10842..1ebb7ed36 100644 --- a/linux/drivers/media/common/saa7146_core.c +++ b/linux/drivers/media/common/saa7146_core.c @@ -27,8 +27,9 @@ #endif /* global variables */ -static struct list_head devices; -static struct semaphore devices_lock; +struct list_head saa7146_devices; +struct semaphore saa7146_devices_lock; + static struct list_head extensions; static int initialized = 0; static int saa7146_num = 0; @@ -49,20 +50,7 @@ static void dump_registers(struct saa7146_dev* dev) } /********************************************************************************/ -/* common dma and page table functions */ - -void saa7146_dma_free(struct saa7146_dev *dev,struct saa7146_buf *buf) -{ - DEB_EE(("dev:%p, buf:%p\n",dev,buf)); - - if (in_interrupt()) - BUG(); - - videobuf_waiton(&buf->vb,0,0); - videobuf_dma_pci_unmap(dev->pci, &buf->vb.dma); - videobuf_dma_free(&buf->vb.dma); - buf->vb.state = STATE_NEEDS_INIT; -} +/* common page table functions */ #define SAA7146_PGTABLE_SIZE 4096 @@ -128,220 +116,9 @@ void saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *p } /********************************************************************************/ -/* file operations */ - -static -int video_open(struct inode *inode, struct file *file) -{ - unsigned int minor = minor(inode->i_rdev); - struct saa7146_dev *h = NULL, *dev = NULL; - struct list_head *list; - struct saa7146_fh *fh = NULL; - int result = 0; - - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - DEB_EE(("inode:%p, file:%p, minor:%d\n",inode,file,minor)); - - if (down_interruptible(&devices_lock)) - return -ERESTARTSYS; - - list_for_each(list,&devices) { - h = list_entry(list, struct saa7146_dev, item); - DEB_D(("trying: %p @ major %d,%d\n",h,h->video_dev.minor,h->vbi_dev.minor)); - if (h->video_dev.minor == minor) { - dev = h; - } - if (h->vbi_dev.minor == minor) { - type = V4L2_BUF_TYPE_VBI_CAPTURE; - dev = h; - } - } - DEB_D(("using: %p\n",dev)); - - if (NULL == dev) { - DEB_S(("no such video device.\n")); - result = -ENODEV; - goto out; - } - - /* check if an extension is registered */ - if( NULL == dev->ext ) { - DEB_S(("no extension registered for this device.\n")); - result = -ENODEV; - goto out; - } - - /* allocate per open data */ - fh = kmalloc(sizeof(*fh),GFP_KERNEL); - if (NULL == fh) { - DEB_S(("cannot allocate memory for per open data.\n")); - result = -ENOMEM; - goto out; - } - memset(fh,0,sizeof(*fh)); - - /* fixme: increase some usage counts */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - dev->ext->inc_use(dev); - MOD_INC_USE_COUNT; -#else - if( 0 == try_module_get(dev->ext->module)) { - result = -EINVAL; - goto out; - } -#endif - file->private_data = fh; - fh->dev = dev; - fh->type = type; - - dev->current_hps_source = SAA7146_HPS_SOURCE_PORT_A; - dev->current_hps_sync = SAA7146_HPS_SYNC_PORT_A; - - saa7146_video_uops.open(dev,fh); - if( 0 != BOARD_CAN_DO_VBI(dev) ) { - saa7146_vbi_uops.open(dev,fh); - } - - result = 0; -out: - if( fh != 0 && result != 0 ) { - kfree(fh); - } - up(&devices_lock); - return result; -} - -static int video_release(struct inode *inode, struct file *file) -{ - struct saa7146_fh *fh = file->private_data; - struct saa7146_dev *dev = fh->dev; - - DEB_EE(("inode:%p, file:%p\n",inode,file)); - - if (down_interruptible(&devices_lock)) - return -ERESTARTSYS; - - saa7146_video_uops.release(dev,fh,file); - if( 0 != BOARD_CAN_DO_VBI(dev) ) { - saa7146_vbi_uops.release(dev,fh,file); - } - - /* fixme: decrease some usage counts */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - dev->ext->dec_use(dev); - MOD_DEC_USE_COUNT; -#else - module_put(dev->ext->module); -#endif - file->private_data = NULL; - kfree(fh); - - up(&devices_lock); - - return 0; -} - -static int video_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) -{ -/* - DEB_EE(("inode:%p, file:%p, cmd:%d, arg:%li\n",inode, file, cmd, arg)); -*/ - return video_usercopy(inode, file, cmd, arg, video_do_ioctl); -} - -static int video_mmap(struct file *file, struct vm_area_struct * vma) -{ - struct saa7146_fh *fh = file->private_data; - struct saa7146_dev *dev = fh->dev; - struct videobuf_queue *q; - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",file, vma)); - q = &fh->video_q; - break; - } - case V4L2_BUF_TYPE_VBI_CAPTURE: { - DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",file, vma)); - q = &fh->vbi_q; - break; - } - default: - BUG(); - return 0; - } - return videobuf_mmap_mapper(vma,q); -} - -static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) -{ - struct saa7146_fh *fh = file->private_data; - struct saa7146_dev *dev = fh->dev; - struct videobuf_buffer *buf = NULL; - struct videobuf_queue *q; - - DEB_EE(("file:%p, poll:%p\n",file, wait)); - - if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { - if( 0 == fh->vbi_q.streaming ) - return videobuf_poll_stream(file, &fh->vbi_q, wait); - q = &fh->vbi_q; - } else { - q = &fh->video_q; - } - - if (!list_empty(&q->stream)) - buf = list_entry(q->stream.next, struct videobuf_buffer, stream); - - if (!buf) { - return POLLERR; - } - - poll_wait(file, &buf->done, wait); - if (buf->state == STATE_DONE || buf->state == STATE_ERROR) { - return POLLIN|POLLRDNORM; - } - - return 0; -} - -static ssize_t video_read(struct file *file, char *data, size_t count, loff_t *ppos) -{ - struct saa7146_fh *fh = file->private_data; - struct saa7146_dev *dev = fh->dev; - - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%d\n",file, data, count)); - return saa7146_video_uops.read(file,data,count,ppos); - } - case V4L2_BUF_TYPE_VBI_CAPTURE: { - DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%d\n",file, data, count)); - return saa7146_vbi_uops.read(file,data,count,ppos); - } - break; - default: - BUG(); - return 0; - } -} - -static struct file_operations video_fops = -{ - owner: THIS_MODULE, - open: video_open, - release: video_release, - read: video_read, - poll: video_poll, - mmap: video_mmap, - ioctl: video_ioctl, - llseek: no_llseek, -}; - -/********************************************************************************/ /* interrupt handler */ +/* FIXME: here are dependencies to the video and vbi code... */ static void interrupt_hw(int irq, void *dev_id, struct pt_regs *regs) { struct saa7146_dev *dev = (struct saa7146_dev*)dev_id; @@ -369,7 +146,9 @@ static void interrupt_hw(int irq, void *dev_id, struct pt_regs *regs) } if (0 != (isr & (MASK_27))) { DEB_INT(("irq: RPS0 (0x%08x).\n",isr)); - saa7146_video_uops.irq_done(dev,isr); + if( 0 != dev->video_irq_done ) { + dev->video_irq_done(dev,isr); + } isr &= ~MASK_27; } if (0 != (isr & (MASK_28))) { @@ -382,7 +161,9 @@ static void interrupt_hw(int irq, void *dev_id, struct pt_regs *regs) return; } DEB_INT(("irq: RPS1 (0x%08x).\n",isr)); - saa7146_vbi_uops.irq_done(dev,isr); + if( 0 != dev->vbi_irq_done ) { + dev->vbi_irq_done(dev,isr); + } } if (0 != (isr & (MASK_16|MASK_17))) { u32 status = saa7146_read(dev, I2C_STATUS); @@ -410,138 +191,9 @@ static void interrupt_hw(int irq, void *dev_id, struct pt_regs *regs) } } -/********************************************************************************/ -/* common buffer functions */ - -int saa7146_buffer_queue(struct saa7146_dev *dev, - struct saa7146_dmaqueue *q, - struct saa7146_buf *buf) -{ -#if DEBUG_SPINLOCKS - BUG_ON(!spin_is_locked(&dev->slock)); -#endif - DEB_EE(("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf)); - - if( NULL == q ) { - ERR(("internal error: fatal NULL pointer for q.\n")); - return 0; - } - - if (NULL == q->curr) { - q->curr = buf; - DEB_D(("immediately activating buffer %p\n", buf)); - buf->activate(dev,buf,NULL); - } else { - list_add_tail(&buf->vb.queue,&q->queue); - buf->vb.state = STATE_QUEUED; - DEB_D(("adding buffer %p to queue. (active buffer present)\n", buf)); - } - return 0; -} - -void saa7146_buffer_finish(struct saa7146_dev *dev, - struct saa7146_dmaqueue *q, - int state) -{ -#if DEBUG_SPINLOCKS - BUG_ON(!spin_is_locked(&dev->slock)); -#endif - if( NULL == q->curr ) { - ERR(("internal error: fatal NULL pointer for q->curr.\n")); - return; - } - - DEB_EE(("dev:%p, dmaq:%p, state:%d\n", dev, q, state)); - - /* finish current buffer */ - q->curr->vb.state = state; - do_gettimeofday(&q->curr->vb.ts); - wake_up(&q->curr->vb.done); - - q->curr = NULL; -} - -void saa7146_buffer_next(struct saa7146_dev *dev, - struct saa7146_dmaqueue *q, int vbi) -{ - struct saa7146_buf *buf,*next = NULL; - - if( NULL == q ) { - ERR(("internal error: fatal NULL pointer for q.\n")); - return; - } - - DEB_EE(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi)); - -#if DEBUG_SPINLOCKS - BUG_ON(!spin_is_locked(&dev->slock)); -#endif - if (!list_empty(&q->queue)) { - /* activate next one from queue */ - buf = list_entry(q->queue.next,struct saa7146_buf,vb.queue); - list_del(&buf->vb.queue); - 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)); - buf->activate(dev,buf,next); - } else { - DEB_D(("no next buffer. stopping.\n")); - if( 0 != vbi ) { - /* turn off video-dma3 */ - saa7146_write(dev,MC1, MASK_20); - } else { - /* nothing to do -- just prevent next video-dma1 transfer - by lowering the protection address */ - - // fixme: fix this for vflip != 0 - - saa7146_write(dev, PROT_ADDR1, 0); - /* write the address of the rps-program */ - saa7146_write(dev, RPS_ADDR0, virt_to_bus(&dev->rps0[ 0])); - /* turn on rps */ - saa7146_write(dev, MC1, (MASK_12 | MASK_28)); - } - del_timer(&q->timeout); - } -} - -void saa7146_buffer_timeout(unsigned long data) -{ - struct saa7146_dmaqueue *q = (struct saa7146_dmaqueue*)data; - struct saa7146_dev *dev = q->dev; - unsigned long flags; - - DEB_EE(("dev:%p, dmaq:%p\n", dev, q)); - - spin_lock_irqsave(&dev->slock,flags); - if (q->curr) { - DEB_D(("timeout on %p\n", q->curr)); - saa7146_buffer_finish(dev,q,STATE_ERROR); - } - - /* we don't restart the transfer here like other drivers do. when - a streaming capture is disabled, the timeout function will be - called for the current buffer. if we activate the next buffer now, - we mess up our capture logic. if a timeout occurs on another buffer, - then something is seriously broken before, so no need to buffer the - next capture IMHO... */ -/* - saa7146_buffer_next(dev,q); -*/ - spin_unlock_irqrestore(&dev->slock,flags); -} - /*********************************************************************************/ /* extension handling functions */ -static struct video_device device_template = -{ - .hardware = VID_HARDWARE_SAA7146, - .fops = &video_fops, - .minor = -1, -}; - void try_attach_extension_and_device(struct saa7146_dev *dev, struct saa7146_extension *ext) { int i = 0; @@ -554,9 +206,6 @@ void try_attach_extension_and_device(struct saa7146_dev *dev, struct saa7146_ext return; } - dev->vbi_dev.minor = -1; - dev->video_dev.minor = -1; - DEB_S(("Trying device %p...\n",dev)); /* first check the subvendor and subdevice ids */ @@ -593,36 +242,6 @@ void try_attach_extension_and_device(struct saa7146_dev *dev, struct saa7146_ext dev->ext = NULL; return; } - - /* v4l2 initialization stuff */ - dev->video_dev = device_template; - strncpy(dev->video_dev.name, ext->name, 32); - dev->video_dev.priv = dev; - - // fixme: -1 should be an insmod parameter *for the extension* (like "video_nr"); - if (video_register_device(&dev->video_dev,VFL_TYPE_GRABBER,-1) < 0) { - ERR(("cannot register capture v4l2 device. skipping.\n")); - /* in this case the extension has probably - already "done something", but the v4l2-device - could not be registered. this is not as bad as - it looks - you cannot access the device. - we simply call the 'release' function. */ - ext->detach(dev); - dev->ext = NULL; - return; - } - INFO(("%s: registered device video%d [v4l2]\n", dev->name,dev->video_dev.minor & 0x1f)); - - /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ - if( 0 != BOARD_CAN_DO_VBI(dev)) { - dev->vbi_dev = device_template; - strncpy(dev->vbi_dev.name, ext->name, 32); - dev->vbi_dev.priv = dev; - if (video_register_device(&dev->vbi_dev,VFL_TYPE_VBI,-1) < 0) { - ERR(("cannot register vbi v4l2 device. skipping.\n")); - } - INFO(("%s: registered device vbi%d [v4l2]\n", dev->name,dev->vbi_dev.minor & 0x1f)); - } } static int try_match_device_to_extension(struct saa7146_dev *dev) @@ -631,7 +250,7 @@ static int try_match_device_to_extension(struct saa7146_dev *dev) DEB_EE(("dev:%p\n",dev)); - if (down_interruptible(&devices_lock)) + if (down_interruptible(&saa7146_devices_lock)) return -ERESTARTSYS; list_for_each(list,&extensions) { @@ -639,7 +258,7 @@ static int try_match_device_to_extension(struct saa7146_dev *dev) try_attach_extension_and_device(dev,ext); } - up(&devices_lock); + up(&saa7146_devices_lock); return 0; } @@ -654,15 +273,15 @@ static int try_match_extension_to_device(struct saa7146_extension *ext) return 0; } - if (down_interruptible(&devices_lock)) + if (down_interruptible(&saa7146_devices_lock)) return -ERESTARTSYS; - list_for_each(list,&devices) { + list_for_each(list,&saa7146_devices) { dev = list_entry(list, struct saa7146_dev, item); try_attach_extension_and_device(dev,ext); } - up(&devices_lock); + up(&saa7146_devices_lock); return 0; } @@ -673,8 +292,8 @@ int saa7146_register_extension(struct saa7146_extension* ext) DEB_EE(("ext:%p\n",ext)); if( 0 == initialized ) { - INIT_LIST_HEAD(&devices); - init_MUTEX(&devices_lock); + INIT_LIST_HEAD(&saa7146_devices); + init_MUTEX(&saa7146_devices_lock); INIT_LIST_HEAD(&extensions); initialized = 1; } @@ -692,9 +311,9 @@ int saa7146_unregister_extension(struct saa7146_extension* ext) DEB_EE(("ext:%p\n",ext)); - down(&devices_lock); + down(&saa7146_devices_lock); - list_for_each(list,&devices) { + list_for_each(list,&saa7146_devices) { dev = list_entry(list, struct saa7146_dev, item); /* check if handled by this extension */ @@ -706,22 +325,13 @@ int saa7146_unregister_extension(struct saa7146_extension* ext) DEB_D(("ext->detach() failed. ignoring.\n")); } - video_unregister_device(&dev->video_dev); - if( 0 != BOARD_CAN_DO_VBI(dev)) { - video_unregister_device(&dev->vbi_dev); - } - dev->ext = NULL; - - /* make sure to erase the minor number... */ - dev->video_dev = device_template; - - dump_registers(dev); +// dump_registers(dev); } list_del(&ext->item); - up(&devices_lock); + up(&saa7146_devices_lock); return 0; } @@ -827,9 +437,6 @@ static int config_a_device(struct pci_dev *pci) goto kmalloc_error_4; memset(dev->i2c_mem, 0x00, SAA7146_I2C_MEM); - /* enable i2c-port pins, video-port-pins */ - saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); - /* the rest + print status message */ /* create a nice device name */ @@ -846,15 +453,15 @@ static int config_a_device(struct pci_dev *pci) init_MUTEX(&dev->i2c_lock); INIT_LIST_HEAD(&dev->item); - list_add_tail(&dev->item,&devices); + list_add_tail(&dev->item,&saa7146_devices); saa7146_num++; - saa7146_video_uops.init(dev); - saa7146_vbi_uops.init(dev); - dev->module = THIS_MODULE; init_waitqueue_head(&dev->i2c_wq); + dev->video_minor = -1; + dev->vbi_minor = -1; + return try_match_device_to_extension(dev); kmalloc_error_4: @@ -950,8 +557,8 @@ int __init saa7146_init_module(void) DEB_EE((".\n")); if( 0 == initialized ) { - INIT_LIST_HEAD(&devices); - init_MUTEX(&devices_lock); + INIT_LIST_HEAD(&saa7146_devices); + init_MUTEX(&saa7146_devices_lock); INIT_LIST_HEAD(&extensions); initialized = 1; } @@ -975,15 +582,18 @@ EXPORT_SYMBOL_GPL(saa7146_register_extension); EXPORT_SYMBOL_GPL(saa7146_unregister_extension); /* misc functions used by extension modules */ -EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync); EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc); EXPORT_SYMBOL_GPL(saa7146_pgtable_free); EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single); + EXPORT_SYMBOL_GPL(saa7146_i2c_transfer); EXPORT_SYMBOL_GPL(saa7146_i2c_adapter_prepare); EXPORT_SYMBOL_GPL(saa7146_debug); +EXPORT_SYMBOL_GPL(saa7146_devices); +EXPORT_SYMBOL_GPL(saa7146_devices_lock); + MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); -MODULE_DESCRIPTION("video4linux driver for saa7146-based video hardware"); +MODULE_DESCRIPTION("core driver for saa7146-based hardware"); MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/common/saa7146_fops.c b/linux/drivers/media/common/saa7146_fops.c new file mode 100644 index 000000000..d8202c65f --- /dev/null +++ b/linux/drivers/media/common/saa7146_fops.c @@ -0,0 +1,426 @@ +#include "saa7146.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) + #define KBUILD_MODNAME saa7146 +#endif + +#define BOARD_CAN_DO_VBI(dev) (dev->revision != 0 && dev->vbi_minor != -1) + +/********************************************************************************/ +/* common dma functions */ + +void saa7146_dma_free(struct saa7146_dev *dev,struct saa7146_buf *buf) +{ + DEB_EE(("dev:%p, buf:%p\n",dev,buf)); + + if (in_interrupt()) + BUG(); + + videobuf_waiton(&buf->vb,0,0); + videobuf_dma_pci_unmap(dev->pci, &buf->vb.dma); + videobuf_dma_free(&buf->vb.dma); + buf->vb.state = STATE_NEEDS_INIT; +} + + +/********************************************************************************/ +/* common buffer functions */ + +int saa7146_buffer_queue(struct saa7146_dev *dev, + struct saa7146_dmaqueue *q, + struct saa7146_buf *buf) +{ +#if DEBUG_SPINLOCKS + BUG_ON(!spin_is_locked(&dev->slock)); +#endif + DEB_EE(("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf)); + + if( NULL == q ) { + ERR(("internal error: fatal NULL pointer for q.\n")); + return 0; + } + + if (NULL == q->curr) { + q->curr = buf; + DEB_D(("immediately activating buffer %p\n", buf)); + buf->activate(dev,buf,NULL); + } else { + list_add_tail(&buf->vb.queue,&q->queue); + buf->vb.state = STATE_QUEUED; + DEB_D(("adding buffer %p to queue. (active buffer present)\n", buf)); + } + return 0; +} + +void saa7146_buffer_finish(struct saa7146_dev *dev, + struct saa7146_dmaqueue *q, + int state) +{ +#if DEBUG_SPINLOCKS + BUG_ON(!spin_is_locked(&dev->slock)); +#endif + if( NULL == q->curr ) { + ERR(("internal error: fatal NULL pointer for q->curr.\n")); + return; + } + + DEB_EE(("dev:%p, dmaq:%p, state:%d\n", dev, q, state)); + + /* finish current buffer */ + q->curr->vb.state = state; + do_gettimeofday(&q->curr->vb.ts); + wake_up(&q->curr->vb.done); + + q->curr = NULL; +} + +void saa7146_buffer_next(struct saa7146_dev *dev, + struct saa7146_dmaqueue *q, int vbi) +{ + struct saa7146_buf *buf,*next = NULL; + + if( NULL == q ) { + ERR(("internal error: fatal NULL pointer for q.\n")); + return; + } + + DEB_EE(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi)); + +#if DEBUG_SPINLOCKS + BUG_ON(!spin_is_locked(&dev->slock)); +#endif + if (!list_empty(&q->queue)) { + /* activate next one from queue */ + buf = list_entry(q->queue.next,struct saa7146_buf,vb.queue); + list_del(&buf->vb.queue); + 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)); + buf->activate(dev,buf,next); + } else { + DEB_D(("no next buffer. stopping.\n")); + if( 0 != vbi ) { + /* turn off video-dma3 */ + saa7146_write(dev,MC1, MASK_20); + } else { + /* nothing to do -- just prevent next video-dma1 transfer + by lowering the protection address */ + + // fixme: fix this for vflip != 0 + + saa7146_write(dev, PROT_ADDR1, 0); + /* write the address of the rps-program */ + saa7146_write(dev, RPS_ADDR0, virt_to_bus(&dev->rps0[ 0])); + /* turn on rps */ + saa7146_write(dev, MC1, (MASK_12 | MASK_28)); + } + del_timer(&q->timeout); + } +} + +void saa7146_buffer_timeout(unsigned long data) +{ + struct saa7146_dmaqueue *q = (struct saa7146_dmaqueue*)data; + struct saa7146_dev *dev = q->dev; + unsigned long flags; + + DEB_EE(("dev:%p, dmaq:%p\n", dev, q)); + + spin_lock_irqsave(&dev->slock,flags); + if (q->curr) { + DEB_D(("timeout on %p\n", q->curr)); + saa7146_buffer_finish(dev,q,STATE_ERROR); + } + + /* we don't restart the transfer here like other drivers do. when + a streaming capture is disabled, the timeout function will be + called for the current buffer. if we activate the next buffer now, + we mess up our capture logic. if a timeout occurs on another buffer, + then something is seriously broken before, so no need to buffer the + next capture IMHO... */ +/* + saa7146_buffer_next(dev,q); +*/ + spin_unlock_irqrestore(&dev->slock,flags); +} + +/********************************************************************************/ +/* file operations */ + +static +int video_open(struct inode *inode, struct file *file) +{ + unsigned int minor = minor(inode->i_rdev); + struct saa7146_dev *h = NULL, *dev = NULL; + struct list_head *list; + struct saa7146_fh *fh = NULL; + int result = 0; + + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + DEB_EE(("inode:%p, file:%p, minor:%d\n",inode,file,minor)); + + if (down_interruptible(&saa7146_devices_lock)) + return -ERESTARTSYS; + + list_for_each(list,&saa7146_devices) { + h = list_entry(list, struct saa7146_dev, item); + DEB_D(("trying: %p @ major %d,%d\n",h,h->video_minor,h->vbi_minor)); + if (h->video_minor == minor) { + dev = h; + } + if (h->vbi_minor == minor) { + type = V4L2_BUF_TYPE_VBI_CAPTURE; + dev = h; + } + } + DEB_D(("using: %p\n",dev)); + + if (NULL == dev) { + DEB_S(("no such video device.\n")); + result = -ENODEV; + goto out; + } + + /* check if an extension is registered */ + if( NULL == dev->ext ) { + DEB_S(("no extension registered for this device.\n")); + result = -ENODEV; + goto out; + } + + /* allocate per open data */ + fh = kmalloc(sizeof(*fh),GFP_KERNEL); + if (NULL == fh) { + DEB_S(("cannot allocate memory for per open data.\n")); + result = -ENOMEM; + goto out; + } + memset(fh,0,sizeof(*fh)); + + /* fixme: increase some usage counts */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) + dev->ext->inc_use(dev); + MOD_INC_USE_COUNT; +#else + if( 0 == try_module_get(dev->ext->module)) { + result = -EINVAL; + goto out; + } +#endif + file->private_data = fh; + fh->dev = dev; + fh->type = type; + + /* FIXME: what's this? */ + dev->current_hps_source = SAA7146_HPS_SOURCE_PORT_A; + dev->current_hps_sync = SAA7146_HPS_SYNC_PORT_A; + + saa7146_video_uops.open(dev,fh); + if( 0 != BOARD_CAN_DO_VBI(dev) ) { + saa7146_vbi_uops.open(dev,fh); + } + + result = 0; +out: + if( fh != 0 && result != 0 ) { + kfree(fh); + } + up(&saa7146_devices_lock); + return result; +} + +static int video_release(struct inode *inode, struct file *file) +{ + struct saa7146_fh *fh = file->private_data; + struct saa7146_dev *dev = fh->dev; + + DEB_EE(("inode:%p, file:%p\n",inode,file)); + + if (down_interruptible(&saa7146_devices_lock)) + return -ERESTARTSYS; + + saa7146_video_uops.release(dev,fh,file); + if( 0 != BOARD_CAN_DO_VBI(dev) ) { + saa7146_vbi_uops.release(dev,fh,file); + } + + /* fixme: decrease some usage counts */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) + dev->ext->dec_use(dev); + MOD_DEC_USE_COUNT; +#else + module_put(dev->ext->module); +#endif + file->private_data = NULL; + kfree(fh); + + up(&saa7146_devices_lock); + + return 0; +} + +int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg); +static int video_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ +/* + DEB_EE(("inode:%p, file:%p, cmd:%d, arg:%li\n",inode, file, cmd, arg)); +*/ + return video_usercopy(inode, file, cmd, arg, saa7146_video_do_ioctl); +} + +static int video_mmap(struct file *file, struct vm_area_struct * vma) +{ + struct saa7146_fh *fh = file->private_data; + struct saa7146_dev *dev = fh->dev; + struct videobuf_queue *q; + + switch (fh->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: { + DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",file, vma)); + q = &fh->video_q; + break; + } + case V4L2_BUF_TYPE_VBI_CAPTURE: { + DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",file, vma)); + q = &fh->vbi_q; + break; + } + default: + BUG(); + return 0; + } + return videobuf_mmap_mapper(vma,q); +} + +static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) +{ + struct saa7146_fh *fh = file->private_data; + struct saa7146_dev *dev = fh->dev; + struct videobuf_buffer *buf = NULL; + struct videobuf_queue *q; + + DEB_EE(("file:%p, poll:%p\n",file, wait)); + + if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { + if( 0 == fh->vbi_q.streaming ) + return videobuf_poll_stream(file, &fh->vbi_q, wait); + q = &fh->vbi_q; + } else { + q = &fh->video_q; + } + + if (!list_empty(&q->stream)) + buf = list_entry(q->stream.next, struct videobuf_buffer, stream); + + if (!buf) { + return POLLERR; + } + + poll_wait(file, &buf->done, wait); + if (buf->state == STATE_DONE || buf->state == STATE_ERROR) { + return POLLIN|POLLRDNORM; + } + + return 0; +} + +static ssize_t video_read(struct file *file, char *data, size_t count, loff_t *ppos) +{ + struct saa7146_fh *fh = file->private_data; + struct saa7146_dev *dev = fh->dev; + + switch (fh->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: { + DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%d\n",file, data, count)); + return saa7146_video_uops.read(file,data,count,ppos); + } + case V4L2_BUF_TYPE_VBI_CAPTURE: { + DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%d\n",file, data, count)); + return saa7146_vbi_uops.read(file,data,count,ppos); + } + break; + default: + BUG(); + return 0; + } +} + +static struct file_operations video_fops = +{ + owner: THIS_MODULE, + open: video_open, + release: video_release, + read: video_read, + poll: video_poll, + mmap: video_mmap, + ioctl: video_ioctl, + llseek: no_llseek, +}; + +static struct video_device device_template = +{ + .hardware = VID_HARDWARE_SAA7146, + .fops = &video_fops, + .minor = -1, +}; + +int saa7146_register_device(struct video_device *vid, struct saa7146_dev* dev, char *name, int type) +{ + *vid = device_template; + strncpy(vid->name, name, 32); + vid->priv = dev; + + // fixme: -1 should be an insmod parameter *for the extension* (like "video_nr"); + if (video_register_device(vid,type,-1) < 0) { + ERR(("cannot register vbi v4l2 device. skipping.\n")); + return -1; + } + + if( VFL_TYPE_GRABBER == type ) { + dev->video_minor = vid->minor; + INFO(("%s: registered device video%d [v4l2]\n", dev->name,vid->minor & 0x1f)); + } else { + dev->vbi_minor = vid->minor; + INFO(("%s: registered device vbi%d [v4l2]\n", dev->name,vid->minor & 0x1f)); + } + return 0; +} + +int saa7146_unregister_device(struct video_device *vid, struct saa7146_dev* dev) +{ + if( VFL_TYPE_GRABBER == vid->type ) { + dev->video_minor = -1; + dev->video_irq_done = saa7146_video_uops.irq_done; + } else { + dev->vbi_minor = -1; + dev->vbi_irq_done = saa7146_vbi_uops.irq_done; + } + video_unregister_device(vid); + return 0; +} + +static +int __init saa7146_vv_init_module(void) +{ + return 0; +} + + +static +void __exit saa7146_vv_cleanup_module(void) +{ +} + +module_init(saa7146_vv_init_module); +module_exit(saa7146_vv_cleanup_module); + +EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync); +EXPORT_SYMBOL_GPL(saa7146_register_device); +EXPORT_SYMBOL_GPL(saa7146_unregister_device); + +MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); +MODULE_DESCRIPTION("video4linux driver for saa7146-based hardware"); +MODULE_LICENSE("GPL"); + + diff --git a/linux/drivers/media/common/saa7146_vbi.c b/linux/drivers/media/common/saa7146_vbi.c index be318cfee..1b880ff9c 100644 --- a/linux/drivers/media/common/saa7146_vbi.c +++ b/linux/drivers/media/common/saa7146_vbi.c @@ -15,17 +15,13 @@ int vbi_workaround(struct saa7146_dev *dev) DECLARE_WAITQUEUE(wait, current); - DEB_VBI(("dev:%p",dev)); + DEB_VBI(("dev:%p\n",dev)); /* once again, a bug in the saa7146: the brs acquisition is buggy and especially the BXO-counter does not work as specified. there is this workaround, but please don't let me explain it. ;-) */ - if(0 != dev->ext->vbi) { - dev->ext->vbi(dev); - } - cpu = pci_alloc_consistent(dev->pci, 4096, &dma_addr); if (NULL == cpu) return -ENOMEM; @@ -451,3 +447,5 @@ struct saa7146_use_ops saa7146_vbi_uops = { .irq_done = vbi_irq_done, .read = vbi_read, }; + +EXPORT_SYMBOL_GPL(saa7146_vbi_uops); diff --git a/linux/drivers/media/common/saa7146_video.c b/linux/drivers/media/common/saa7146_video.c index 8c0f19239..2038e4748 100644 --- a/linux/drivers/media/common/saa7146_video.c +++ b/linux/drivers/media/common/saa7146_video.c @@ -64,10 +64,6 @@ int g_fmt(struct saa7146_fh *fh, struct v4l2_format *f) return 0; case V4L2_BUF_TYPE_VBI_CAPTURE: { - if( 0 == BOARD_CAN_DO_VBI(dev)) { - DEB_D(("this device does not support vbi.\n")); - return -ENODEV; - } f->fmt.vbi = fh->vbi_fmt; return 0; } @@ -681,8 +677,7 @@ int video_end(struct saa7146_fh *fh) * copying is done already, arg is a kernel fhinter. */ -int video_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) +int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; @@ -747,9 +742,6 @@ int video_do_ioctl(struct inode *inode, struct file *file, V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; - if( BOARD_CAN_DO_VBI(dev) != 0) { - cap->capabilities |= V4L2_CAP_VBI_CAPTURE; - } cap->capabilities |= dev->ext->capabilities; return 0; } @@ -1044,12 +1036,11 @@ int video_do_ioctl(struct inode *inode, struct file *file, } default: return v4l_compat_translate_ioctl(inode,file,cmd,arg, - video_do_ioctl); + saa7146_video_do_ioctl); } return 0; } - /*********************************************************************************/ /* buffer handling functions */ @@ -1209,6 +1200,8 @@ static void video_init(struct saa7146_dev *dev) { INIT_LIST_HEAD(&dev->video_q.queue); + + init_timer(&dev->video_q.timeout); dev->video_q.timeout.function = saa7146_buffer_timeout; dev->video_q.timeout.data = (unsigned long)(&dev->video_q); dev->video_q.dev = dev; @@ -1277,7 +1270,6 @@ void video_irq_done(struct saa7146_dev *dev, unsigned long st) spin_unlock(&dev->slock); } - static ssize_t video_read(struct file *file, char *data, size_t count, loff_t *ppos) { @@ -1310,3 +1302,5 @@ struct saa7146_use_ops saa7146_video_uops = { .capture_begin = video_begin, .capture_end = video_end, }; + +EXPORT_SYMBOL_GPL(saa7146_video_uops); diff --git a/linux/drivers/media/dvb/av7110/av7110.c b/linux/drivers/media/dvb/av7110/av7110.c index f0c75b5e5..77ccc15db 100644 --- a/linux/drivers/media/dvb/av7110/av7110.c +++ b/linux/drivers/media/dvb/av7110/av7110.c @@ -4517,7 +4517,7 @@ static int av7110_attach (struct saa7146_dev* dev) { av7110_t *av7110 = (av7110_t*)dev->ext_priv; - struct scatterlist *slist; + struct scatterlist *slist = NULL; int slen = 0; int length = TS_WIDTH*TS_HEIGHT; int pages = (length+PAGE_SIZE-1)/PAGE_SIZE; @@ -4525,8 +4525,13 @@ int av7110_attach (struct saa7146_dev* dev) DEB_EE(("dev: %p, av7110: %p\n",dev,av7110)); - av7110->dev=(struct saa7146_dev *)dev; + saa7146_video_uops.init(dev); + if( 0 != saa7146_register_device(&av7110->vd, dev, "av7710", VFL_TYPE_GRABBER)) { + ERR(("cannot register capture device. skipping.\n")); + return -1; + } + av7110->dev=(struct saa7146_dev *)dev; dvb_register_adapter(&av7110->dvb_adapter, av7110->card_type->name); saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_3200); @@ -4537,32 +4542,31 @@ int av7110_attach (struct saa7146_dev* dev) return -ENOMEM; } - av7110->grabbing = vmalloc(length); - if (!av7110->grabbing) { - printk(KERN_ERR "dvb: vmalloc() failed.\n"); - ret = -ENOMEM; - goto err; - } +// fixme if (av7110->card_type->type >= DVB_CARD_TT_BUDGET) + av7110->grabbing = vmalloc(length); + if (!av7110->grabbing) { + printk(KERN_ERR "dvb: vmalloc() failed.\n"); + ret = -ENOMEM; + goto err; + } - if (!(slist = videobuf_vmalloc_to_sg(av7110->grabbing, pages))) { - vfree(av7110->grabbing); - printk(KERN_ERR "dvb: videobuf_vmalloc_to_sg() failed.\n"); - ret = -ENOMEM; - goto err; - } + if (!(slist = videobuf_vmalloc_to_sg(av7110->grabbing, pages))) { + printk(KERN_ERR "dvb: videobuf_vmalloc_to_sg() failed.\n"); + ret = -ENOMEM; + goto err; + } - // FIXME: is direction ok? - if (saa7146_pgtable_alloc(dev->pci, &av7110->pt)) { - printk(KERN_ERR "dvb: saa7146_pgtable_alloc() failed.\n"); - kfree(slist); - vfree(av7110->grabbing); - ret = -ENOMEM; - goto err; - } - - slen = pci_map_sg(dev->pci,slist,pages,PCI_DMA_FROMDEVICE); - saa7146_pgtable_build_single(dev->pci, &av7110->pt, slist, slen); + if (saa7146_pgtable_alloc(dev->pci, &av7110->pt)) { + printk(KERN_ERR "dvb: saa7146_pgtable_alloc() failed.\n"); + ret = -ENOMEM; + goto err; + } + + slen = pci_map_sg(dev->pci,slist,pages,PCI_DMA_FROMDEVICE); + saa7146_pgtable_build_single(dev->pci, &av7110->pt, slist, slen); +// } + saa7146_write(dev, PCI_BT_V1, 0x1c00101f); saa7146_write(dev, BCS_CTRL, 0x80400040); @@ -4703,6 +4707,12 @@ int av7110_attach (struct saa7146_dev* dev) return 0; err: + if( NULL != av7110->grabbing ) { + vfree(av7110->grabbing); + } + if( NULL != slist ) { + kfree(slist); + } dvb_unregister_i2c_bus (master_xfer,av7110->i2c_bus->adapter, av7110->i2c_bus->id); dvb_unregister_adapter (av7110->dvb_adapter); return ret; @@ -4714,6 +4724,8 @@ int av7110_detach (struct saa7146_dev* saa) av7110_t *av7110 = (av7110_t*)saa->ext_priv; DEB_EE(("av7110: %p\n",av7110)); + saa7146_unregister_device(&av7110->vd, saa); + av7110->arm_rmmod=1; wake_up_interruptible(&av7110->arm_wait); @@ -4735,8 +4747,11 @@ int av7110_detach (struct saa7146_dev* saa) pci_free_consistent(saa->pci, 8192, av7110->debi_virt, av7110->debi_bus); - saa7146_pgtable_free(saa->pci, &av7110->pt); - +// fixme if (av7110->card_type->type >= DVB_CARD_TT_BUDGET) + saa7146_pgtable_free(saa->pci, &av7110->pt); + vfree(av7110->grabbing); +// } + dvb_unregister_i2c_bus (master_xfer,av7110->i2c_bus->adapter, av7110->i2c_bus->id); dvb_unregister_adapter (av7110->dvb_adapter); @@ -4784,12 +4799,12 @@ void av7110_dec_use(struct saa7146_dev* adap) #endif -/* FIXME: 0x3a seems to be a little too small, you'll notice a small black bar on - some channels. perhaps increase this to 0x42? looks good for me, but is not - based on facts... (MiHu) */ +/* FIXME: these values are experimental values that look better than the + values from the latest "official" driver -- at least for me... (MiHu) */ static struct saa7146_standard standard[] = { - { "PAL", V4L2_STD_PAL, 0x15, 288, 576, 0x3a, 720, 721, 576, 768 }, + { "PAL", V4L2_STD_PAL, 0x15, 288, 576, 0x4a, 708, 709, 576, 768 }, +// { "PAL", V4L2_STD_PAL, 0x15, 288, 576, 0x3a, 720, 721, 576, 768 }, /* FIXME: more to come here */ }; @@ -4799,11 +4814,9 @@ struct saa7146_extension av7110_extension = { .inputs = 1, .audios = 1, .capabilities = 0, - - /* FIXME: SAA7146_EXT_PROVIDES_VIDEO not true for budget cards, - separate these two... */ - .flags = SAA7146_EXT_PROVIDES_VIDEO|SAA7146_EXT_SWAP_ODD_EVEN, + .flags = SAA7146_EXT_SWAP_ODD_EVEN, + .devices = &sub_data[0], .module = THIS_MODULE, @@ -4816,8 +4829,6 @@ struct saa7146_extension av7110_extension = { .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), .std_callback = NULL, - .vbi = NULL, - .ioctls = &ioctls[0], .preinit = av7110_preinit, diff --git a/linux/drivers/media/dvb/av7110/av7110.h b/linux/drivers/media/dvb/av7110/av7110.h index 71dac7464..a379a3fcd 100644 --- a/linux/drivers/media/dvb/av7110/av7110.h +++ b/linux/drivers/media/dvb/av7110/av7110.h @@ -483,7 +483,7 @@ typedef struct av7110_s { struct dvb_device dvb_dev; dvb_net_t dvb_net; - struct video_device video; + struct video_device vd; struct saa7146_dev *dev; diff --git a/linux/drivers/media/dvb/dvb-core/compat.c b/linux/drivers/media/dvb/dvb-core/compat.c deleted file mode 100644 index 6d6d11d98..000000000 --- a/linux/drivers/media/dvb/dvb-core/compat.c +++ /dev/null @@ -1,131 +0,0 @@ -#include <linux/slab.h> -#include <linux/highmem.h> - -#include "compat.h" - -/** - * compatibility crap for old kernels. No guarantee for a working driver - * even when everything compiles. - */ - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) || !CONFIG_VIDEO_DEV -int generic_usercopy(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg)) -{ - char sbuf[128]; - void *mbuf = NULL; - void *parg = NULL; - int err = -EINVAL; - - /* Copy arguments into temp kernel buffer */ - switch (_IOC_DIR(cmd)) { - case _IOC_NONE: - parg = (void *)arg; - break; - case _IOC_READ: /* some v4l ioctls are marked wrong ... */ - case _IOC_WRITE: - case (_IOC_WRITE | _IOC_READ): - if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { - parg = sbuf; - } else { - /* too big to allocate from stack */ - mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); - if (NULL == mbuf) - return -ENOMEM; - parg = mbuf; - } - - err = -EFAULT; - if (copy_from_user(parg, (void *)arg, _IOC_SIZE(cmd))) - goto out; - break; - } - - /* call driver */ - if ((err = func(inode, file, cmd, parg)) == -ENOIOCTLCMD) - err = -EINVAL; - - if (err < 0) - goto out; - - /* Copy results into user buffer */ - switch (_IOC_DIR(cmd)) - { - case _IOC_READ: - case (_IOC_WRITE | _IOC_READ): - if (copy_to_user((void *)arg, parg, _IOC_SIZE(cmd))) - err = -EFAULT; - break; - } - -out: - if (mbuf) - kfree(mbuf); - - return err; -} -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -static -u32 crc32_table[256] = { - 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, - 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, - 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, - 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, - 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, - 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, - 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, - 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, - 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, - 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, - 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, - 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, - 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, - 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, - 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, - 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, - 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, - 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, - 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, - 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, - 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, - 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, - 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, - 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, - 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, - 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, - 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, - 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, - 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, - 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, - 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, - 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, - 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, - 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, - 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, - 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, - 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, - 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, - 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, - 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, - 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, - 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, - 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4}; - -u32 crc32_le (u32 crc, unsigned char const *data, size_t len) -{ - int i; - - for (i=0; i<len; i++) - crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *data++) & 0xff]; - - return crc; -} - -EXPORT_SYMBOL(crc32_le); - -#endif - diff --git a/linux/drivers/media/dvb/dvb-core/compat.h b/linux/drivers/media/dvb/dvb-core/compat.h deleted file mode 100644 index 369de4d34..000000000 --- a/linux/drivers/media/dvb/dvb-core/compat.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef __CRAP_H -#define __CRAP_H - -/** - * compatibility crap for old kernels. No guarantee for a working driver - * even when everything compiles. - */ - - -#include <linux/module.h> -#include <linux/list.h> -#include <linux/videodev.h> - - -#ifndef MODULE_LICENSE -#define MODULE_LICENSE(x) -#endif - -#ifndef list_for_each_safe -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) -#endif - -#ifndef __devexit_p -#if defined(MODULE) -#define __devexit_p(x) x -#else -#define __devexit_p(x) NULL -#endif -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) || !CONFIG_VIDEO_DEV -#define video_usercopy generic_usercopy - -extern int generic_usercopy(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg)); -#endif - -#ifndef minor -#define minor(dev) MINOR(dev) -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20)) -static inline -void cond_resched (void) -{ - if (current->need_resched) - schedule(); -} -#endif - - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -extern u32 crc32_le (u32 crc, unsigned char const *p, size_t len); -#else -#include <linux/crc32.h> -#endif - - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,48)) -static inline -int try_module_get(struct module *mod) -{ - if (!MOD_CAN_QUERY(mod)) - return 0; - __MOD_INC_USE_COUNT(mod); - return 1; -} - -#define module_put(mod) __MOD_DEC_USE_COUNT(mod) -#endif - - -#endif - diff --git a/linux/drivers/media/dvb/dvb-core/dmxdev.c b/linux/drivers/media/dvb/dvb-core/dmxdev.c index 280a76f6d..960d9705a 100644 --- a/linux/drivers/media/dvb/dvb-core/dmxdev.c +++ b/linux/drivers/media/dvb/dvb-core/dmxdev.c @@ -27,7 +27,6 @@ #include <linux/videodev.h> #include <asm/uaccess.h> -#include "compat.h" #include "dmxdev.h" diff --git a/linux/drivers/media/dvb/dvb-core/dvb_demux.c b/linux/drivers/media/dvb/dvb-core/dvb_demux.c index 3f5a46226..c90893215 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_demux.c @@ -26,9 +26,67 @@ #include <linux/poll.h> #include <linux/version.h> #include <asm/uaccess.h> + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +static +u32 crc32_table[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, + 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, + 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, + 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, + 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, + 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, + 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, + 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, + 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, + 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, + 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, + 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, + 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, + 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, + 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, + 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, + 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4}; + +static u32 crc32_le (u32 crc, unsigned char const *data, size_t len) +{ + int i; + + for (i=0; i<len; i++) + crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *data++) & 0xff]; + + return crc; +} +#else #include <linux/crc32.h> +#endif -#include "compat.h" #include "dvb_demux.h" #define NOBUFS diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c index 656515eb2..a4dc2b8e4 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -30,7 +30,6 @@ #include <linux/compatmac.h> #include <linux/list.h> -#include "compat.h" #include "dvb_frontend.h" #include "dvbdev.h" diff --git a/linux/drivers/media/dvb/dvb-core/dvb_i2c.c b/linux/drivers/media/dvb/dvb-core/dvb_i2c.c index 2c9f77e7f..53c48d4df 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_i2c.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_i2c.c @@ -23,10 +23,8 @@ #include <linux/list.h> #include <linux/module.h> -#include "compat.h" #include "dvb_i2c.h" - struct dvb_i2c_device { struct list_head list_head; struct module *owner; @@ -34,6 +32,18 @@ struct dvb_i2c_device { void (*detach) (struct dvb_i2c_bus *i2c); }; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,48)) +static inline +int try_module_get(struct module *mod) +{ + if (!MOD_CAN_QUERY(mod)) + return 0; + __MOD_INC_USE_COUNT(mod); + return 1; +} + +#define module_put(mod) __MOD_DEC_USE_COUNT(mod) +#endif LIST_HEAD(dvb_i2c_buslist); LIST_HEAD(dvb_i2c_devicelist); diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.c b/linux/drivers/media/dvb/dvb-core/dvbdev.c index 0fe8dcb4d..c6b39b66e 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.c +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.c @@ -39,7 +39,6 @@ #include <linux/slab.h> #include <linux/videodev.h> -#include "compat.h" #include "dvbdev.h" static int dvbdev_debug = 0; @@ -68,6 +67,67 @@ static char *dnames[] = { #define nums2minor(num,type,id) ((num << 6) | (id << 4) | type) #define DVB_DEVFS_FLAGS (DEVFS_FL_DEFAULT) +/* this is the same as video_usercopy() and should be replaced as + discussed already with something like generic_usercopy() */ +int dvb_usercopy(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg)) +{ + char sbuf[128]; + void *mbuf = NULL; + void *parg = NULL; + int err = -EINVAL; + + /* Copy arguments into temp kernel buffer */ + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: + parg = (void *)arg; + break; + case _IOC_READ: /* some v4l ioctls are marked wrong ... */ + case _IOC_WRITE: + case (_IOC_WRITE | _IOC_READ): + if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { + parg = sbuf; + } else { + /* too big to allocate from stack */ + mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); + if (NULL == mbuf) + return -ENOMEM; + parg = mbuf; + } + + err = -EFAULT; + if (copy_from_user(parg, (void *)arg, _IOC_SIZE(cmd))) + goto out; + break; + } + + /* call driver */ + if ((err = func(inode, file, cmd, parg)) == -ENOIOCTLCMD) + err = -EINVAL; + + if (err < 0) + goto out; + + /* Copy results into user buffer */ + switch (_IOC_DIR(cmd)) + { + case _IOC_READ: + case (_IOC_WRITE | _IOC_READ): + if (copy_to_user((void *)arg, parg, _IOC_SIZE(cmd))) + err = -EFAULT; + break; + } + +out: + if (mbuf) + kfree(mbuf); + + return err; +} + + static struct dvb_device* dvbdev_find_device (int minor) @@ -173,7 +233,7 @@ int dvb_generic_ioctl(struct inode *inode, struct file *file, if (!dvbdev->kernel_ioctl) return -EINVAL; - return video_usercopy (inode, file, cmd, arg, dvbdev->kernel_ioctl); + return dvb_usercopy (inode, file, cmd, arg, dvbdev->kernel_ioctl); } diff --git a/linux/drivers/media/dvb/frontends/alps_bsrv2.c b/linux/drivers/media/dvb/frontends/alps_bsrv2.c index e0ecd0e24..01175f24e 100644 --- a/linux/drivers/media/dvb/frontends/alps_bsrv2.c +++ b/linux/drivers/media/dvb/frontends/alps_bsrv2.c @@ -23,7 +23,6 @@ #include <linux/module.h> #include <linux/init.h> -#include "compat.h" #include "dvb_frontend.h" static int debug = 0; diff --git a/linux/drivers/media/dvb/frontends/alps_tdlb7.c b/linux/drivers/media/dvb/frontends/alps_tdlb7.c index 01369c615..e66af832b 100644 --- a/linux/drivers/media/dvb/frontends/alps_tdlb7.c +++ b/linux/drivers/media/dvb/frontends/alps_tdlb7.c @@ -51,7 +51,6 @@ #include <linux/fs.h> #include <linux/unistd.h> -#include "compat.h" #include "dvb_frontend.h" static int debug = 0; diff --git a/linux/drivers/media/dvb/frontends/alps_tdmb7.c b/linux/drivers/media/dvb/frontends/alps_tdmb7.c index 961d764dc..41e5d3a0a 100644 --- a/linux/drivers/media/dvb/frontends/alps_tdmb7.c +++ b/linux/drivers/media/dvb/frontends/alps_tdmb7.c @@ -23,7 +23,6 @@ #include <linux/init.h> #include <linux/module.h> -#include "compat.h" #include "dvb_frontend.h" diff --git a/linux/drivers/media/dvb/frontends/grundig_29504-401.c b/linux/drivers/media/dvb/frontends/grundig_29504-401.c index 27bc5e982..6e8b3ccea 100644 --- a/linux/drivers/media/dvb/frontends/grundig_29504-401.c +++ b/linux/drivers/media/dvb/frontends/grundig_29504-401.c @@ -25,7 +25,6 @@ #include <linux/module.h> #include <linux/init.h> -#include "compat.h" #include "dvb_frontend.h" static int debug = 0; diff --git a/linux/drivers/media/dvb/frontends/grundig_29504-491.c b/linux/drivers/media/dvb/frontends/grundig_29504-491.c index 6a2f0eaaf..0eff691c7 100644 --- a/linux/drivers/media/dvb/frontends/grundig_29504-491.c +++ b/linux/drivers/media/dvb/frontends/grundig_29504-491.c @@ -27,7 +27,6 @@ #include <linux/init.h> #include <linux/module.h> -#include "compat.h" #include "dvb_frontend.h" static int debug = 0; diff --git a/linux/drivers/media/dvb/frontends/stv0299.c b/linux/drivers/media/dvb/frontends/stv0299.c index ef1ceeebf..34f48ec38 100644 --- a/linux/drivers/media/dvb/frontends/stv0299.c +++ b/linux/drivers/media/dvb/frontends/stv0299.c @@ -33,7 +33,6 @@ #include <linux/init.h> #include <linux/module.h> -#include "compat.h" #include "dvb_frontend.h" static int debug = 0; diff --git a/linux/drivers/media/dvb/frontends/ves1820.c b/linux/drivers/media/dvb/frontends/ves1820.c index df0041beb..e549331c1 100644 --- a/linux/drivers/media/dvb/frontends/ves1820.c +++ b/linux/drivers/media/dvb/frontends/ves1820.c @@ -23,7 +23,6 @@ #include <linux/module.h> #include <linux/delay.h> -#include "compat.h" #include "dvb_frontend.h" diff --git a/linux/drivers/media/video/mxb.c b/linux/drivers/media/video/mxb.c index 5b3c4b824..ce8a4d9b4 100644 --- a/linux/drivers/media/video/mxb.c +++ b/linux/drivers/media/video/mxb.c @@ -33,6 +33,35 @@ #define I2C_SAA7111A 0x24 +/* All unused bytes are reserverd. */ +#define SAA711X_CHIP_VERSION 0x00 +#define SAA711X_ANALOG_INPUT_CONTROL_1 0x02 +#define SAA711X_ANALOG_INPUT_CONTROL_2 0x03 +#define SAA711X_ANALOG_INPUT_CONTROL_3 0x04 +#define SAA711X_ANALOG_INPUT_CONTROL_4 0x05 +#define SAA711X_HORIZONTAL_SYNC_START 0x06 +#define SAA711X_HORIZONTAL_SYNC_STOP 0x07 +#define SAA711X_SYNC_CONTROL 0x08 +#define SAA711X_LUMINANCE_CONTROL 0x09 +#define SAA711X_LUMINANCE_BRIGHTNESS 0x0A +#define SAA711X_LUMINANCE_CONTRAST 0x0B +#define SAA711X_CHROMA_SATURATION 0x0C +#define SAA711X_CHROMA_HUE_CONTROL 0x0D +#define SAA711X_CHROMA_CONTROL 0x0E +#define SAA711X_FORMAT_DELAY_CONTROL 0x10 +#define SAA711X_OUTPUT_CONTROL_1 0x11 +#define SAA711X_OUTPUT_CONTROL_2 0x12 +#define SAA711X_OUTPUT_CONTROL_3 0x13 +#define SAA711X_V_GATE_1_START 0x15 +#define SAA711X_V_GATE_1_STOP 0x16 +#define SAA711X_V_GATE_1_MSB 0x17 +#define SAA711X_TEXT_SLICER_STATUS 0x1A +#define SAA711X_DECODED_BYTES_OF_TS_1 0x1B +#define SAA711X_DECODED_BYTES_OF_TS_2 0x1C +#define SAA711X_STATUS_BYTE 0x1F + +#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0) + /* global variable */ static int mxb_num = 0; @@ -129,6 +158,9 @@ static struct saa7146_extension_ioctls ioctls[] = { struct mxb { + struct video_device video_dev; + struct video_device vbi_dev; + struct i2c_adapter i2c_adapter; struct i2c_client* saa7111a; @@ -169,6 +201,10 @@ static int mxb_probe(struct saa7146_dev* dev, unsigned int subvendor, unsigned i } memset(mxb, 0x0, sizeof(struct mxb)); + /* FIXME: enable i2c-port pins, video-port-pins + video port pins should be enabled here ?! */ + saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); + saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); if(i2c_add_adapter(&mxb->i2c_adapter) < 0) { DEB_S(("cannot register i2c-device. skipping.\n")); @@ -396,7 +432,7 @@ err: return 0; } -/* interrupt bh-handler. this gets called when irq_mask is != 0. +/* interrupt-handler. this gets called when irq_mask is != 0. it must clear the interrupt-bits in irq_mask it has handled */ /* void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask) @@ -410,11 +446,26 @@ static int mxb_attach(struct saa7146_dev* dev) { struct mxb* mxb = (struct mxb*)dev->ext_priv; + DEB_EE(("dev:%p\n",dev)); + /* checking for i2c-devices can be omitted here, because we already did this in "mxb_vl42_probe" */ - mxb_num++; + saa7146_video_uops.init(dev); + if( 0 != saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { + ERR(("cannot register capture v4l2 device. skipping.\n")); + return -1; + } + /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ + if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) { + saa7146_vbi_uops.init(dev); + if( 0 != saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) { + ERR(("cannot register vbi v4l2 device. skipping.\n")); + return -1; + } + } + i2c_inc_use_client(mxb->tea6420_1); i2c_inc_use_client(mxb->tea6420_2); i2c_inc_use_client(mxb->tea6415c); @@ -422,6 +473,7 @@ static int mxb_attach(struct saa7146_dev* dev) i2c_inc_use_client(mxb->saa7111a); i2c_inc_use_client(mxb->tuner); + mxb_num++; return mxb_init_done(dev); } @@ -429,6 +481,8 @@ static int mxb_detach(struct saa7146_dev* dev) { struct mxb* mxb = (struct mxb*)dev->ext_priv; + DEB_EE(("dev:%p\n",dev)); + i2c_dec_use_client(mxb->tea6420_1); i2c_dec_use_client(mxb->tea6420_2); i2c_dec_use_client(mxb->tea6415c); @@ -436,6 +490,11 @@ static int mxb_detach(struct saa7146_dev* dev) i2c_dec_use_client(mxb->saa7111a); i2c_dec_use_client(mxb->tuner); + saa7146_unregister_device(&mxb->video_dev,dev); + if( 0 != MXB_BOARD_CAN_DO_VBI(dev)) { + saa7146_unregister_device(&mxb->vbi_dev,dev); + } + mxb_num--; i2c_del_adapter(&mxb->i2c_adapter); @@ -447,16 +506,25 @@ static int mxb_detach(struct saa7146_dev* dev) static int mxb_vbi_bypass(struct saa7146_dev* dev) { struct mxb* mxb = (struct mxb*)dev->ext_priv; - int i = 1; + s32 byte = 0x0; + int result = 0; - /* switch bypass in saa7111a */ - /* fixme saa - if ( 0 != mxb->saa7111a->driver->command(mxb->saa7111a,SAA711X_VBI_BYPASS, &i)) { - DEB_D(("could not address saa7111a.\n")); - return -1; - } - */ - + DEB_EE(("dev:%p\n",dev)); + + /* switch bypass in saa7111a, this should be done in the + saa7111a driver of course... */ + if ( -1 == (result = i2c_smbus_read_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_3))) { + DEB_D(("could not read from saa7111a.\n")); + return -EFAULT; + } + byte = result; + byte &= 0xf0; + byte |= 0x0a; + + if ( 0 != (result = i2c_smbus_write_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_3, byte))) { + DEB_D(("could not write to saa7111a.\n")); + return -EFAULT; + } return 0; } @@ -464,12 +532,13 @@ static int mxb_vbi_bypass(struct saa7146_dev* dev) static int saa7111_set_gpio(struct saa7146_dev *dev, int bl) { struct mxb* mxb = (struct mxb*)dev->ext_priv; - s32 byte = 0x0; int result = 0; + DEB_EE(("dev:%p\n",dev)); + /* get the old register contents */ - if ( -1 == (byte = i2c_smbus_read_byte_data(mxb->saa7111a, 0x11))) { + if ( -1 == (byte = i2c_smbus_read_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_1))) { DEB_D(("could not read from saa711x\n")); return -EFAULT; } @@ -481,7 +550,7 @@ static int saa7111_set_gpio(struct saa7146_dev *dev, int bl) } /* write register contents back */ - if ( 0 != (result = i2c_smbus_write_byte_data(mxb->saa7111a, 0x11, byte))) { + if ( 0 != (result = i2c_smbus_write_byte_data(mxb->saa7111a, SAA711X_OUTPUT_CONTROL_1, byte))) { DEB_D(("could not write to saa711x\n")); return -EFAULT; } @@ -707,11 +776,10 @@ static int mxb_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) strcpy(t->name, "Television"); t->type = V4L2_TUNER_ANALOG_TV; - /* fixme: _CAP_NORM needed? */ t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */ t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */ - /* fixme: add the real signal strength here */ + /* FIXME: add the real signal strength here */ t->signal = 0xffff; t->afc = 0; @@ -953,10 +1021,10 @@ struct saa7146_extension extension = { .name = MXB_IDENTIFIER, .inputs = MXB_INPUTS, .audios = MXB_AUDIOS, - .capabilities = V4L2_CAP_TUNER, + .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE, + + .flags = 0, - .flags = SAA7146_EXT_PROVIDES_VIDEO|SAA7146_EXT_PROVIDES_VBI, - .devices = &sub_data[0], .module = THIS_MODULE, @@ -969,8 +1037,6 @@ struct saa7146_extension extension = { .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), .std_callback = &std_callback, - .vbi = mxb_vbi_bypass, - .ioctls = &ioctls[0], .preinit = mxb_preinit, |