diff options
author | Michael Hunold <devnull@localhost> | 2002-12-19 19:38:06 +0000 |
---|---|---|
committer | Michael Hunold <devnull@localhost> | 2002-12-19 19:38:06 +0000 |
commit | 5c7770b64b4ec0e3d1b00b96e32a4cb4647b57f4 (patch) | |
tree | adfd458e238bc3f2ae4d795ddd8be1eba26a9d6f /linux/drivers/media/common | |
parent | e0737ae1cb71b5ee270b434c0cd1c701008c5a33 (diff) | |
download | mediapointer-dvb-s2-5c7770b64b4ec0e3d1b00b96e32a4cb4647b57f4.tar.gz mediapointer-dvb-s2-5c7770b64b4ec0e3d1b00b96e32a4cb4647b57f4.tar.bz2 |
Necessary fixes to the saa7146_core to allow the driver to
be build statically into the kernel.
Diffstat (limited to 'linux/drivers/media/common')
-rw-r--r-- | linux/drivers/media/common/saa7146.h | 6 | ||||
-rw-r--r-- | linux/drivers/media/common/saa7146_core.c | 238 |
2 files changed, 154 insertions, 90 deletions
diff --git a/linux/drivers/media/common/saa7146.h b/linux/drivers/media/common/saa7146.h index 98fc45a92..67f1c5793 100644 --- a/linux/drivers/media/common/saa7146.h +++ b/linux/drivers/media/common/saa7146.h @@ -15,6 +15,7 @@ #include <linux/i2c.h> /* for i2c subsystem */ #include <linux/i2c-id.h> #include <asm/io.h> /* for accessing devices */ +#include <linux/stringify.h> #include <linux/videodev2.h> #include "video-buf.h" @@ -28,7 +29,10 @@ #define saa7146_write(sxy,adr,dat) writel((dat),(sxy->mem+(adr))) #define saa7146_read(sxy,adr) readl(sxy->mem+(adr)) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) #define BUG_ON(condition) do { if ((condition)!=0) BUG(); } while(0) +#endif + #define BOARD_CAN_DO_VBI(dev) (dev->revision != 0 && 0 != dev->ext->vbi) extern int debug; @@ -76,6 +80,8 @@ struct saa7146_extension int audios; u32 capabilities; + struct list_head item; + /* pairs of subvendor and subdevice ids for supported devices, last entry 0xffff, 0xfff */ struct saa7146_sub_info *devices; diff --git a/linux/drivers/media/common/saa7146_core.c b/linux/drivers/media/common/saa7146_core.c index 8b3cb62ff..a99992429 100644 --- a/linux/drivers/media/common/saa7146_core.c +++ b/linux/drivers/media/common/saa7146_core.c @@ -29,6 +29,8 @@ /* global variables */ static struct list_head devices; static struct semaphore devices_lock; +static struct list_head extensions; +static int initialized = 0; static int saa7146_num = 0; static int debug = 0; @@ -518,116 +520,160 @@ static struct video_device device_template = .minor = -1, }; -int saa7146_register_extension(struct saa7146_extension* ext) +void try_attach_extension_and_device(struct saa7146_dev *dev, struct saa7146_extension *ext) { - struct saa7146_dev *dev = NULL; - struct list_head *list = NULL;; + int i = 0; + int found = 0; - DEB_EE(("ext:%p\n",ext)); + DEB_EE(("dev:%p, ext:%p, num:%d\n",dev,ext,saa7146_num)); - if (down_interruptible(&devices_lock)) - return -ERESTARTSYS; + /* check if already handled by extension */ + if( 0 != dev->ext ) { + return; + } - list_for_each(list,&devices) { - int i = 0; - int found = 0; - dev = list_entry(list, struct saa7146_dev, item); + dev->vbi_dev.minor = -1; + dev->video_dev.minor = -1; - /* check if already handled by extension */ - if( 0 != dev->ext ) { - continue; - } + DEB_S(("Trying device %p...\n",dev)); - dev->vbi_dev.minor = -1; - dev->video_dev.minor = -1; - - DEB_S(("Trying device %p...\n",dev)); - - /* first check the subvendor and subdevice ids */ - for(i = 0;;i++) { - if( 0xffff == ext->devices[i].subvendor - && 0xffff == ext->devices[i].subdevice ) { - break; - } - if( ext->devices[i].subvendor == dev->pci->subsystem_vendor - && ext->devices[i].subdevice == dev->pci->subsystem_device ) { - found = 1; - break; - } - } - if( 0 == found ) { - DEB_S(("extension %p does not handle this device. skipping.\n",ext)); - continue; + /* first check the subvendor and subdevice ids */ + for(i = 0;;i++) { + if( 0xffff == ext->devices[i].subvendor + && 0xffff == ext->devices[i].subdevice ) { + break; } + if( ext->devices[i].subvendor == dev->pci->subsystem_vendor + && ext->devices[i].subdevice == dev->pci->subsystem_device ) { + found = 1; + break; + } + } + if( 0 == found ) { + DEB_S(("extension %p does not handle this device. skipping.\n",ext)); + return; + } - if( 0 != ext->preinit(dev) ) { - DEB_S(("ext->preinit() failed for %p. skipping.\n",dev)); - continue; - } + if( 0 != ext->preinit(dev) ) { + DEB_S(("ext->preinit() failed for %p. skipping.\n",dev)); + return; + } - if( 0 != ext->use_kernel_i2c ) { - /* register new i2c-bus */ - if(i2c_add_adapter(dev->i2c_adapter) < 0) { - DEB_S(("cannot register i2c-device. skipping.\n")); - continue; - } + if( 0 != ext->use_kernel_i2c ) { + /* register new i2c-bus */ + if(i2c_add_adapter(dev->i2c_adapter) < 0) { + DEB_S(("cannot register i2c-device. skipping.\n")); + return; } + } - if( 0 != ext->probe(dev, dev->pci->subsystem_vendor, dev->pci->subsystem_device) ) { - DEB_D(("ext->probe() failed for %p. skipping device.\n",dev)); - if( 0 != ext->use_kernel_i2c ) - i2c_del_adapter(dev->i2c_adapter); - continue; - } + if( 0 != ext->probe(dev, dev->pci->subsystem_vendor, dev->pci->subsystem_device) ) { + DEB_D(("ext->probe() failed for %p. skipping device.\n",dev)); + if( 0 != ext->use_kernel_i2c ) + i2c_del_adapter(dev->i2c_adapter); + return; + } - dev->ext = ext; + dev->ext = ext; - if( 0 != ext->attach(dev) ) { - DEB_D(("ext->attach() failed for %p. skipping device.\n",dev)); - if( 0 != ext->use_kernel_i2c ) - i2c_del_adapter(dev->i2c_adapter); - dev->ext = NULL; - continue; - } + if( 0 != ext->attach(dev) ) { + DEB_D(("ext->attach() failed for %p. skipping device.\n",dev)); + if( 0 != ext->use_kernel_i2c ) + i2c_del_adapter(dev->i2c_adapter); + 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); - if( 0 != ext->use_kernel_i2c ) - i2c_del_adapter(dev->i2c_adapter); - dev->ext = NULL; - continue; - } - INFO(("%s: registered device video%d [v4l2],%d\n", dev->name,dev->video_dev.minor & 0x1f,dev->vbi_dev.minor & 0x1f)); + /* 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); + if( 0 != ext->use_kernel_i2c ) + i2c_del_adapter(dev->i2c_adapter); + dev->ext = NULL; + return; + } + INFO(("%s: registered device video%d [v4l2],%d\n", dev->name,dev->video_dev.minor & 0x1f,dev->vbi_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)); + /* 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) +{ + struct list_head *list = NULL; + + DEB_EE(("dev:%p\n",dev)); + + if (down_interruptible(&devices_lock)) + return -ERESTARTSYS; + + list_for_each(list,&extensions) { + struct saa7146_extension *ext = list_entry(list, struct saa7146_extension, item); + try_attach_extension_and_device(dev,ext); } up(&devices_lock); + return 0; +} + +static int try_match_extension_to_device(struct saa7146_extension *ext) +{ + struct list_head *list = NULL; + + DEB_EE(("ext:%p, num:%d\n",ext,saa7146_num)); + + if( 0 == saa7146_num ) { + return 0; + } + if (down_interruptible(&devices_lock)) + return -ERESTARTSYS; + + list_for_each(list,&devices) { + struct saa7146_dev *dev = list_entry(list, struct saa7146_dev, item); + try_attach_extension_and_device(dev,ext); + } + + up(&devices_lock); return 0; } +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(&extensions); + initialized = 1; + } + + INIT_LIST_HEAD(&ext->item); + list_add_tail(&ext->item,&extensions); + + return try_match_extension_to_device(ext); +} + int saa7146_unregister_extension(struct saa7146_extension* ext) { struct saa7146_dev *dev = NULL; @@ -665,6 +711,7 @@ int saa7146_unregister_extension(struct saa7146_extension* ext) // dump_registers(dev); } + list_del(&ext->item); up(&devices_lock); @@ -808,7 +855,7 @@ static int config_a_device(struct pci_dev *pci) dev->module = THIS_MODULE; - return 0; + return try_match_device_to_extension(dev); kmalloc_error_5: kfree( dev->i2c_adapter ); @@ -860,6 +907,8 @@ static void unconfig_a_device(struct saa7146_dev* dev) static int __devinit saa7146_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { + DEB_EE(("pdev:%p\n",pdev)); + if (config_a_device(pdev)) return -EINVAL; @@ -872,6 +921,7 @@ void __devexit saa7146_remove_one(struct pci_dev *pdev) { struct saa7146_dev* dev = (struct saa7146_dev*) pci_get_drvdata(pdev); + DEB_EE(("pdev:%p\n",pdev)); unconfig_a_device(dev); } @@ -897,8 +947,15 @@ struct pci_driver saa7146_driver = { static int __init saa7146_init_module(void) { - INIT_LIST_HEAD(&devices); - init_MUTEX(&devices_lock); + DEB_EE((".")); + + if( 0 == initialized ) { + INIT_LIST_HEAD(&devices); + init_MUTEX(&devices_lock); + INIT_LIST_HEAD(&extensions); + initialized = 1; + } + return pci_module_init(&saa7146_driver); } @@ -906,6 +963,7 @@ int __init saa7146_init_module(void) static void __exit saa7146_cleanup_module(void) { + DEB_EE((".")); pci_unregister_driver(&saa7146_driver); } |