summaryrefslogtreecommitdiff
path: root/linux/drivers/media/common
diff options
context:
space:
mode:
authorMichael Hunold <devnull@localhost>2002-12-19 19:38:06 +0000
committerMichael Hunold <devnull@localhost>2002-12-19 19:38:06 +0000
commit5c7770b64b4ec0e3d1b00b96e32a4cb4647b57f4 (patch)
treeadfd458e238bc3f2ae4d795ddd8be1eba26a9d6f /linux/drivers/media/common
parente0737ae1cb71b5ee270b434c0cd1c701008c5a33 (diff)
downloadmediapointer-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.h6
-rw-r--r--linux/drivers/media/common/saa7146_core.c238
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);
}