summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/saa7134/saa7134-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/video/saa7134/saa7134-core.c')
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-core.c167
1 files changed, 118 insertions, 49 deletions
diff --git a/linux/drivers/media/video/saa7134/saa7134-core.c b/linux/drivers/media/video/saa7134/saa7134-core.c
index 7f5b65776..996b8149f 100644
--- a/linux/drivers/media/video/saa7134/saa7134-core.c
+++ b/linux/drivers/media/video/saa7134/saa7134-core.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-core.c,v 1.12 2004/10/13 10:39:00 kraxel Exp $
+ * $Id: saa7134-core.c,v 1.13 2004/10/19 16:02:05 kraxel Exp $
*
* device driver for philips saa7134 based TV cards
* driver core
@@ -38,8 +38,6 @@ MODULE_DESCRIPTION("v4l2 driver module for saa7130/34 based TV cards");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_LICENSE("GPL");
-#define SAA7134_MAXBOARDS 8
-
/* ------------------------------------------------------------------ */
static unsigned int irq_debug = 0;
@@ -58,10 +56,6 @@ static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
MODULE_PARM(video_nr,"1-" __stringify(SAA7134_MAXBOARDS) "i");
MODULE_PARM_DESC(video_nr,"video device number");
-static unsigned int ts_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
-MODULE_PARM(ts_nr,"1-" __stringify(SAA7134_MAXBOARDS) "i");
-MODULE_PARM_DESC(ts_nr,"ts device number");
-
static unsigned int vbi_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
MODULE_PARM(vbi_nr,"1-" __stringify(SAA7134_MAXBOARDS) "i");
MODULE_PARM_DESC(vbi_nr,"vbi device number");
@@ -94,8 +88,10 @@ static unsigned int latency = UNSET;
MODULE_PARM(latency,"i");
MODULE_PARM_DESC(latency,"pci latency timer");
-struct list_head saa7134_devlist;
-unsigned int saa7134_devcount;
+static DECLARE_MUTEX(devlist_lock);
+LIST_HEAD(saa7134_devlist);
+static LIST_HEAD(mops_list);
+static unsigned int saa7134_devcount;
#define dprintk(fmt, arg...) if (core_debug) \
printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg)
@@ -596,7 +592,7 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
saa7134_irq_vbi_done(dev,status);
if ((report & SAA7134_IRQ_REPORT_DONE_RA2) &&
- card_has_ts(dev))
+ card_has_mpeg(dev))
saa7134_irq_ts_done(dev,status);
if ((report & SAA7134_IRQ_REPORT_DONE_RA3))
@@ -643,7 +639,7 @@ static int saa7134_hwinit1(struct saa7134_dev *dev)
saa7134_track_gpio(dev,"pre-init");
saa7134_video_init1(dev);
saa7134_vbi_init1(dev);
- if (card_has_ts(dev))
+ if (card_has_mpeg(dev))
saa7134_ts_init1(dev);
saa7134_input_init1(dev);
@@ -719,7 +715,7 @@ static int saa7134_hwfini(struct saa7134_dev *dev)
saa7134_oss_fini(dev);
break;
}
- if (card_has_ts(dev))
+ if (card_has_mpeg(dev))
saa7134_ts_fini(dev);
saa7134_input_fini(dev);
saa7134_vbi_fini(dev);
@@ -784,13 +780,6 @@ static void saa7134_unregister_video(struct saa7134_dev *dev)
video_device_release(dev->video_dev);
dev->video_dev = NULL;
}
- if (dev->ts_dev) {
- if (-1 != dev->ts_dev->minor)
- video_unregister_device(dev->ts_dev);
- else
- video_device_release(dev->ts_dev);
- dev->ts_dev = NULL;
- }
if (dev->vbi_dev) {
if (-1 != dev->vbi_dev->minor)
video_unregister_device(dev->vbi_dev);
@@ -807,10 +796,38 @@ static void saa7134_unregister_video(struct saa7134_dev *dev)
}
}
+static void mpeg_ops_attach(struct saa7134_mpeg_ops *ops,
+ struct saa7134_dev *dev)
+{
+ int err;
+
+ if (NULL != dev->mops)
+ return;
+ if (saa7134_boards[dev->board].mpeg != ops->type)
+ return;
+ err = ops->init(dev);
+ if (0 != err)
+ return;
+ dev->mops = ops;
+}
+
+static void mpeg_ops_detach(struct saa7134_mpeg_ops *ops,
+ struct saa7134_dev *dev)
+{
+ if (NULL == dev->mops)
+ return;
+ if (dev->mops != ops)
+ return;
+ dev->mops->fini(dev);
+ dev->mops = NULL;
+}
+
static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
const struct pci_device_id *pci_id)
{
struct saa7134_dev *dev;
+ struct list_head *item;
+ struct saa7134_mpeg_ops *mops;
int err;
dev = kmalloc(sizeof(*dev),GFP_KERNEL);
@@ -824,7 +841,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
err = -EIO;
goto fail1;
}
- sprintf(dev->name,"saa%x[%d]",pci_dev->device,saa7134_devcount);
+
+ dev->nr = saa7134_devcount;
+ sprintf(dev->name,"saa%x[%d]",pci_dev->device,dev->nr);
/* pci quirks */
if (pci_pci_problems) {
@@ -866,21 +885,21 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
/* board config */
dev->board = pci_id->driver_data;
- if (card[saa7134_devcount] >= 0 &&
- card[saa7134_devcount] < saa7134_bcount)
- dev->board = card[saa7134_devcount];
+ if (card[dev->nr] >= 0 &&
+ card[dev->nr] < saa7134_bcount)
+ dev->board = card[dev->nr];
if (SAA7134_BOARD_NOAUTO == dev->board) {
must_configure_manually();
dev->board = SAA7134_BOARD_UNKNOWN;
}
dev->tuner_type = saa7134_boards[dev->board].tuner_type;
dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
- if (UNSET != tuner[saa7134_devcount])
- dev->tuner_type = tuner[saa7134_devcount];
+ if (UNSET != tuner[dev->nr])
+ dev->tuner_type = tuner[dev->nr];
printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
dev->name,pci_dev->subsystem_vendor,
pci_dev->subsystem_device,saa7134_boards[dev->board].name,
- dev->board, card[saa7134_devcount] == dev->board ?
+ dev->board, card[dev->nr] == dev->board ?
"insmod option" : "autodetected");
/* get mmio */
@@ -927,8 +946,12 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
request_module("tuner");
if (dev->tda9887_conf)
request_module("tda9887");
- if (card_has_ts(dev))
+ if (card_is_empress(dev)) {
+ request_module("saa7134-empress");
request_module("saa6752hs");
+ }
+ if (card_is_dvb(dev))
+ request_module("saa7134-dvb");
#ifdef VIDIOC_G_PRIORITY
v4l2_prio_init(&dev->prio);
@@ -937,7 +960,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
/* register v4l devices */
dev->video_dev = vdev_init(dev,&saa7134_video_template,"video");
err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
- video_nr[saa7134_devcount]);
+ video_nr[dev->nr]);
if (err < 0) {
printk(KERN_INFO "%s: can't register video device\n",
dev->name);
@@ -946,22 +969,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
printk(KERN_INFO "%s: registered device video%d [v4l2]\n",
dev->name,dev->video_dev->minor & 0x1f);
- if (card_has_ts(dev)) {
- dev->ts_dev = vdev_init(dev,&saa7134_ts_template,"ts");
- err = video_register_device(dev->ts_dev,VFL_TYPE_GRABBER,
- ts_nr[saa7134_devcount]);
- if (err < 0) {
- printk(KERN_INFO "%s: can't register video device\n",
- dev->name);
- goto fail4;
- }
- printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
- dev->name,dev->ts_dev->minor & 0x1f);
- }
-
dev->vbi_dev = vdev_init(dev,&saa7134_vbi_template,"vbi");
err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
- vbi_nr[saa7134_devcount]);
+ vbi_nr[dev->nr]);
if (err < 0)
goto fail4;
printk(KERN_INFO "%s: registered device vbi%d\n",
@@ -970,7 +980,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
if (card_has_radio(dev)) {
dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio");
err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
- radio_nr[saa7134_devcount]);
+ radio_nr[dev->nr]);
if (err < 0)
goto fail4;
printk(KERN_INFO "%s: registered device radio%d\n",
@@ -985,7 +995,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
if (oss) {
err = dev->oss.minor_dsp =
register_sound_dsp(&saa7134_dsp_fops,
- dsp_nr[saa7134_devcount]);
+ dsp_nr[dev->nr]);
if (err < 0) {
goto fail4;
}
@@ -994,7 +1004,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
err = dev->oss.minor_mixer =
register_sound_mixer(&saa7134_mixer_fops,
- mixer_nr[saa7134_devcount]);
+ mixer_nr[dev->nr]);
if (err < 0)
goto fail5;
printk(KERN_INFO "%s: registered device mixer%d\n",
@@ -1004,9 +1014,16 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
}
/* everything worked */
- list_add_tail(&dev->devlist,&saa7134_devlist);
pci_set_drvdata(pci_dev,dev);
saa7134_devcount++;
+
+ down(&devlist_lock);
+ list_for_each(item,&mops_list) {
+ mops = list_entry(item, struct saa7134_mpeg_ops, next);
+ mpeg_ops_attach(mops, dev);
+ }
+ list_add_tail(&dev->devlist,&saa7134_devlist);
+ up(&devlist_lock);
return 0;
fail5:
@@ -1036,6 +1053,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
{
struct saa7134_dev *dev = pci_get_drvdata(pci_dev);
+ struct list_head *item;
+ struct saa7134_mpeg_ops *mops;
/* debugging ... */
if (irq_debug) {
@@ -1056,6 +1075,15 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
saa7134_hwfini(dev);
/* unregister */
+ down(&devlist_lock);
+ list_del(&dev->devlist);
+ list_for_each(item,&mops_list) {
+ mops = list_entry(item, struct saa7134_mpeg_ops, next);
+ mpeg_ops_detach(mops, dev);
+ }
+ up(&devlist_lock);
+ saa7134_devcount--;
+
saa7134_i2c_unregister(dev);
switch (dev->pci->device) {
case PCI_DEVICE_ID_PHILIPS_SAA7134:
@@ -1081,16 +1109,50 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
pci_set_drvdata(pci_dev, NULL);
/* free memory */
- list_del(&dev->devlist);
- saa7134_devcount--;
kfree(dev);
}
+/* ----------------------------------------------------------- */
+
+int saa7134_ts_register(struct saa7134_mpeg_ops *ops)
+{
+ struct list_head *item;
+ struct saa7134_dev *dev;
+
+ down(&devlist_lock);
+ list_for_each(item,&saa7134_devlist) {
+ dev = list_entry(item, struct saa7134_dev, devlist);
+ mpeg_ops_attach(ops, dev);
+ }
+ list_add_tail(&ops->next,&mops_list);
+ up(&devlist_lock);
+ return 0;
+}
+
+void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops)
+{
+ struct list_head *item;
+ struct saa7134_dev *dev;
+
+ down(&devlist_lock);
+ list_del(&ops->next);
+ list_for_each(item,&saa7134_devlist) {
+ dev = list_entry(item, struct saa7134_dev, devlist);
+ mpeg_ops_detach(ops, dev);
+ }
+ up(&devlist_lock);
+}
+
+EXPORT_SYMBOL(saa7134_ts_register);
+EXPORT_SYMBOL(saa7134_ts_unregister);
+
+/* ----------------------------------------------------------- */
+
static struct pci_driver saa7134_pci_driver = {
.name = "saa7134",
.id_table = saa7134_pci_tbl,
.probe = saa7134_initdev,
- .remove = saa7134_finidev,
+ .remove = __devexit_p(saa7134_finidev),
};
static int saa7134_init(void)
@@ -1116,6 +1178,13 @@ module_init(saa7134_init);
module_exit(saa7134_fini);
/* ----------------------------------------------------------- */
+
+EXPORT_SYMBOL(saa7134_print_ioctl);
+EXPORT_SYMBOL(saa7134_i2c_call_clients);
+EXPORT_SYMBOL(saa7134_devlist);
+EXPORT_SYMBOL(saa7134_boards);
+
+/* ----------------------------------------------------------- */
/*
* Local variables:
* c-basic-offset: 8