diff options
author | Michael Hunold <devnull@localhost> | 2003-01-08 17:41:32 +0000 |
---|---|---|
committer | Michael Hunold <devnull@localhost> | 2003-01-08 17:41:32 +0000 |
commit | d166085ef7eea32af71c4c20321f067a38bb394a (patch) | |
tree | 1cb9582a6374cdd92b69bd264d7fc7e1b1a43459 /linux/drivers/media/common | |
parent | c968f1b52110e481ca9e183729b3a6ad6a2d3aeb (diff) | |
download | mediapointer-dvb-s2-d166085ef7eea32af71c4c20321f067a38bb394a.tar.gz mediapointer-dvb-s2-d166085ef7eea32af71c4c20321f067a38bb394a.tar.bz2 |
Removed the whole "device<=>extension" matching crap, the pci subsystem
can do this much better. We now simply register one pci driver for
every extension and are done with it -- if a device actually exists, the
pci subsystem calls us back. That's it.
Warning: this triggers a bug in the 2.5.x module subsystem -- you should
*not* use the driver.av7110 script and modprobe the driver. You can
a) build your kernel staticall
b) insert the modules one by one with *insmod*
I already filed a bug report to lkml.
Fixed a bug in Kconfig which prevented the saa7146 modules from being build.
Diffstat (limited to 'linux/drivers/media/common')
-rw-r--r-- | linux/drivers/media/common/Kconfig | 2 | ||||
-rw-r--r-- | linux/drivers/media/common/saa7146.h | 23 | ||||
-rw-r--r-- | linux/drivers/media/common/saa7146_core.c | 284 |
3 files changed, 90 insertions, 219 deletions
diff --git a/linux/drivers/media/common/Kconfig b/linux/drivers/media/common/Kconfig index 87edcbb98..206ab6ea0 100644 --- a/linux/drivers/media/common/Kconfig +++ b/linux/drivers/media/common/Kconfig @@ -1,7 +1,7 @@ config VIDEO_SAA7146 tristate default y if DVB_AV7110=y || DVB_BUDGET=y || DVB_BUDGET_AV=y || VIDEO_MXB=y - default m if DVB_AV7110=y || DVB_BUDGET=m || DVB_BUDGET_AV=m || VIDEO_MXB=m + default m if DVB_AV7110=m || DVB_BUDGET=m || DVB_BUDGET_AV=m || VIDEO_MXB=m depends on VIDEO_DEV && PCI config VIDEO_VIDEOBUF diff --git a/linux/drivers/media/common/saa7146.h b/linux/drivers/media/common/saa7146.h index 39ecdda33..2b1329f89 100644 --- a/linux/drivers/media/common/saa7146.h +++ b/linux/drivers/media/common/saa7146.h @@ -54,13 +54,6 @@ struct saa7146_dev; struct saa7146_extension; struct saa7146_vv; -struct saa7146_sub_info { - unsigned int subvendor; - unsigned int subdevice; - char **name; - int type; -}; - /* saa7146 page table */ struct saa7146_pgtable { unsigned int size; @@ -70,6 +63,11 @@ struct saa7146_pgtable { unsigned long offset; }; +struct saa7146_pci_extension_data { + struct saa7146_extension *ext; + void *ext_priv; /* most likely a name string */ +}; + struct saa7146_extension { char name[32]; /* name of the device */ @@ -78,21 +76,20 @@ struct saa7146_extension struct saa7146_ext_vv *ext_vv_data; - struct list_head item; - /* pairs of subvendor and subdevice ids for supported devices, last entry 0xffff, 0xfff */ - struct saa7146_sub_info *devices; struct module *module; - + struct pci_driver driver; + struct pci_device_id *pci_tbl; + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) void (*inc_use)(struct saa7146_dev*); void (*dec_use)(struct saa7146_dev*); #endif /* extension functions */ - int (*probe)(struct saa7146_dev*, unsigned int subvendor, unsigned int subdevice); - int (*attach)(struct saa7146_dev *, struct saa7146_sub_info *); + int (*probe)(struct saa7146_dev *); + int (*attach)(struct saa7146_dev *, struct saa7146_pci_extension_data *); int (*detach)(struct saa7146_dev*); u32 irq_mask; /* mask to indicate, which irq-events are handled by the extension */ diff --git a/linux/drivers/media/common/saa7146_core.c b/linux/drivers/media/common/saa7146_core.c index f45830613..67f2d3734 100644 --- a/linux/drivers/media/common/saa7146_core.c +++ b/linux/drivers/media/common/saa7146_core.c @@ -193,153 +193,18 @@ static void interrupt_hw(int irq, void *dev_id, struct pt_regs *regs) } /*********************************************************************************/ -/* extension handling functions */ - -void try_attach_extension_and_device(struct saa7146_dev *dev, struct saa7146_extension *ext) -{ - int i = 0; - int found = 0; - - DEB_EE(("dev:%p, ext:%p, num:%d\n",dev,ext,saa7146_num)); - - /* check if already handled by extension */ - if( 0 != dev->ext ) { - return; - } - - 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)); - return; - } - - dev->ext = ext; - if( 0 != ext->probe) { - if( 0 != ext->probe(dev, dev->pci->subsystem_vendor, dev->pci->subsystem_device) ) { - DEB_D(("ext->probe() failed for %p. skipping device.\n",dev)); - dev->ext = NULL; - return; - } - } - - if( 0 != ext->attach(dev, &ext->devices[i]) ) { - DEB_D(("ext->attach() failed for %p. skipping device.\n",dev)); - dev->ext = NULL; - return; - } -} - -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(&saa7146_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(&saa7146_devices_lock); - return 0; -} - -static int try_match_extension_to_device(struct saa7146_extension *ext) -{ - struct list_head *list = NULL; - struct saa7146_dev *dev = NULL; - - DEB_EE(("ext:%p, num:%d\n",ext,saa7146_num)); - - if( 0 == saa7146_num ) { - return 0; - } - - if (down_interruptible(&saa7146_devices_lock)) - return -ERESTARTSYS; - - list_for_each(list,&saa7146_devices) { - dev = list_entry(list, struct saa7146_dev, item); - try_attach_extension_and_device(dev,ext); - } - - up(&saa7146_devices_lock); - return 0; -} - -int saa7146_register_extension(struct saa7146_extension* ext) -{ - DEB_EE(("ext:%p\n",ext)); - - if( 0 == initialized ) { - INIT_LIST_HEAD(&saa7146_devices); - init_MUTEX(&saa7146_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; - struct list_head *list = NULL;; - - DEB_EE(("ext:%p\n",ext)); - - down(&saa7146_devices_lock); - - list_for_each(list,&saa7146_devices) { - dev = list_entry(list, struct saa7146_dev, item); - - /* check if handled by this extension */ - if( ext != dev->ext ) { - continue; - } - - if( 0 != ext->detach(dev) ) { - DEB_D(("ext->detach() failed. ignoring.\n")); - } - - dump_registers(dev); - dev->ext = NULL; - - } - list_del(&ext->item); - - up(&saa7146_devices_lock); - - return 0; -} - -/*********************************************************************************/ /* configuration-functions */ -static int config_a_device(struct pci_dev *pci) +static +int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent) { unsigned long adr = 0, len = 0; struct saa7146_dev* dev = kmalloc (sizeof(struct saa7146_dev),GFP_KERNEL); - + + struct saa7146_pci_extension_data *pci_ext = (struct saa7146_pci_extension_data *)ent->driver_data; + struct saa7146_extension* ext = pci_ext->ext; + int err = 0; + if (!(dev = kmalloc (sizeof(struct saa7146_dev),GFP_KERNEL))) { ERR(("out of memory.\n")); return -ENOMEM; @@ -352,8 +217,8 @@ static int config_a_device(struct pci_dev *pci) if (pci_enable_device(pci)) { ERR(("pci_enable_device() failed.\n")); - kfree(dev); - return -EIO; + err = -EIO; + goto pci_error; } /* enable bus-mastering */ @@ -363,8 +228,8 @@ static int config_a_device(struct pci_dev *pci) /* get chip-revision; this is needed to enable bug-fixes */ if( 0 > pci_read_config_dword(dev->pci, PCI_CLASS_REVISION, &dev->revision)) { ERR(("pci_read_config_dword() failed.\n")); - kfree(dev); - return -ENODEV; + err = -ENODEV; + goto pci_error; } dev->revision &= 0xf; @@ -374,15 +239,14 @@ static int config_a_device(struct pci_dev *pci) if (!request_mem_region(pci_resource_start(pci,0), pci_resource_len(pci,0), "saa7146")) { ERR(("request_mem_region() failed.\n")); - kfree(dev); - return -ENODEV; + err = -ENODEV; + goto pci_error; } if (!(dev->mem = ioremap(adr,len))) { ERR(("ioremap() failed.\n")); - release_mem_region(adr,len); - kfree(dev); - return -ENODEV; + err = -ENODEV; + goto ioremap_error; } /* we don't do a master reset here anymore, it screws up @@ -406,26 +270,30 @@ static int config_a_device(struct pci_dev *pci) dev->name, dev)) { ERR(("request_irq() failed.\n")); - iounmap(dev->mem); - release_mem_region(adr,len); - kfree(dev); - return -EINVAL; + err = -ENODEV; + goto irq_error; } /* get memory for various stuff */ dev->rps0 = (u32*)kmalloc(SAA7146_RPS_MEM, GFP_KERNEL); - if( NULL == dev->rps0 ) + if( NULL == dev->rps0 ) { + err = -ENOMEM; goto kmalloc_error_1; + } memset(dev->rps0, 0x0, SAA7146_RPS_MEM); dev->rps1 = (u32*)kmalloc(SAA7146_RPS_MEM, GFP_KERNEL); - if( NULL == dev->rps1 ) + if( NULL == dev->rps1 ) { + err = -ENOMEM; goto kmalloc_error_2; + } memset(dev->rps1, 0x0, SAA7146_RPS_MEM); dev->i2c_mem = (u32*)kmalloc(SAA7146_I2C_MEM, GFP_KERNEL); - if( NULL == dev->i2c_mem ) + if( NULL == dev->i2c_mem ) { + err = -ENOMEM; goto kmalloc_error_3; + } memset(dev->i2c_mem, 0x00, SAA7146_I2C_MEM); /* the rest + print status message */ @@ -434,7 +302,7 @@ static int config_a_device(struct pci_dev *pci) sprintf(&dev->name[0], "saa7146 (%d)",saa7146_num); INFO(("found saa7146 @ mem 0x%08x (revision %d, irq %d) (0x%04x,0x%04x).\n", (unsigned int)dev->mem, dev->revision,dev->pci->irq,dev->pci->subsystem_vendor,dev->pci->subsystem_device)); - dev->ext = NULL; + dev->ext = ext; pci_set_drvdata(pci,dev); @@ -451,25 +319,49 @@ static int config_a_device(struct pci_dev *pci) dev->module = THIS_MODULE; init_waitqueue_head(&dev->i2c_wq); - return try_match_device_to_extension(dev); + if( 0 != ext->probe) { + if( 0 != ext->probe(dev) ) { + DEB_D(("ext->probe() failed for %p. skipping device.\n",dev)); + err = -ENODEV; + goto probe_error; + } + } + if( 0 != ext->attach(dev,pci_ext) ) { + DEB_D(("ext->attach() failed for %p. skipping device.\n",dev)); + err = -ENODEV; + goto attach_error; + } + err = 0; + goto out; +attach_error: +probe_error: + pci_set_drvdata(pci,NULL); + kfree( dev->i2c_mem ); kmalloc_error_3: kfree( dev->rps1 ); kmalloc_error_2: kfree( dev->rps0 ); kmalloc_error_1: - ERR(("kmalloc() failed.\n")); + free_irq(dev->pci->irq, (void *)dev); +irq_error: iounmap(dev->mem); +ioremap_error: release_mem_region(adr,len); +pci_error: kfree(dev); - - return -ENOMEM; +out: + return err; } -static void unconfig_a_device(struct saa7146_dev* dev) +static +void saa7146_remove_one(struct pci_dev *pdev) { + struct saa7146_dev* dev = (struct saa7146_dev*) pci_get_drvdata(pdev); DEB_EE(("dev:%p\n",dev)); + dev->ext->detach(dev); + /* shut down all video dma transfers */ saa7146_write(dev, MC1, 0x00ff0000); @@ -492,68 +384,51 @@ static void unconfig_a_device(struct saa7146_dev* dev) saa7146_num--; } +/*********************************************************************************/ +/* extension handling functions */ -static -int __devinit saa7146_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +int saa7146_register_extension(struct saa7146_extension* ext) { - DEB_EE(("pdev:%p\n",pdev)); + DEB_EE(("ext:%p\n",ext)); - if (config_a_device(pdev)) - return -EINVAL; + if( 0 == initialized ) { + INIT_LIST_HEAD(&saa7146_devices); + init_MUTEX(&saa7146_devices_lock); + INIT_LIST_HEAD(&extensions); + initialized = 1; + } - return 0; + ext->driver.name = "saa7146"; + ext->driver.id_table = ext->pci_tbl; + ext->driver.probe = saa7146_init_one; + ext->driver.remove = saa7146_remove_one; + + return pci_module_init(&ext->driver); } - -static -void __devexit saa7146_remove_one(struct pci_dev *pdev) +int saa7146_unregister_extension(struct saa7146_extension* ext) { - struct saa7146_dev* dev = (struct saa7146_dev*) pci_get_drvdata(pdev); - - DEB_EE(("pdev:%p\n",pdev)); - unconfig_a_device(dev); + DEB_EE(("ext:%p\n",ext)); + pci_unregister_driver(&ext->driver); + return 0; } - -static -struct pci_device_id saa7146_pci_tbl[] __devinitdata = { - { - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7146, - } , { - .vendor = 0, - } -}; - -MODULE_DEVICE_TABLE(pci, saa7146_pci_tbl); - -static -struct pci_driver saa7146_driver = { - .name = "saa7146", - .id_table = saa7146_pci_tbl, - .probe = saa7146_init_one, - .remove = __devexit_p(saa7146_remove_one) -}; - - static -int __init saa7146_init_module(void) +int saa7146_init_module(void) { + printk("saa7146_init_module()\n"); if( 0 == initialized ) { INIT_LIST_HEAD(&saa7146_devices); init_MUTEX(&saa7146_devices_lock); INIT_LIST_HEAD(&extensions); initialized = 1; } - - return pci_module_init(&saa7146_driver); + return 0; } - static void __exit saa7146_cleanup_module(void) { - pci_unregister_driver(&saa7146_driver); } module_init(saa7146_init_module); @@ -579,4 +454,3 @@ EXPORT_SYMBOL_GPL(saa7146_devices_lock); MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); MODULE_DESCRIPTION("driver for generic saa7146-based hardware"); MODULE_LICENSE("GPL"); - |