summaryrefslogtreecommitdiff
path: root/drivers/media/video/cx88/cx88-blackbird.c
diff options
context:
space:
mode:
authorSteven Toth <stoth@hauppauge.com>2006-12-02 21:15:51 -0200
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-12-10 08:50:47 -0200
commit6c5be74c86f102c2d4e123bc51d2fa93155fd794 (patch)
tree72bb1b00045f7c263721f113f92d286405ae96d7 /drivers/media/video/cx88/cx88-blackbird.c
parent91bb9be6ff4101652bb104f9f083f340e73ba6dd (diff)
V4L/DVB (4676): Dynamic cx88 mpeg port management for HVR1300 MPEG2/DVB-T support.
A series of patches to change the cx88 framework to allow the PCI mpeg port to be shared dynamically between different types of drivers or applications. This patch changes the cx88-dvb and cx88-blackbird drivers to become 'sub drivers' of a higher single cx88-mpeg driver. The cx88-mpeg driver is a superset of the previous cx88-mpeg/blackbird drivers and now owns the IRQ. cx88-dvb/blackbird now become mini drivers, registering themselves with cx88-mpeg through a standard interface with callbacks. Sub drivers request access to hardware via the cx88-mpeg driver. In turn the cx88-mpeg driver determines whether the hardware is busy and accepts or refuses the request, grant access using callbacks into the sub drivers. The net effect is that you are no longer able to tamper with the mpeg port from multiple different applications at the same time, potentially breaking a live mpeg2 hardware encoding or dvb stream. The mechanism extends to enable multiple dvb frontends to be registered and share the single resource. Signed-off-by: Steven Toth <stoth@hauppauge.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/cx88/cx88-blackbird.c')
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c178
1 files changed, 109 insertions, 69 deletions
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 46738321adaf..0037188d77d4 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -50,7 +50,6 @@ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
#define dprintk(level,fmt, arg...) if (debug >= level) \
printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg)
-static LIST_HEAD(cx8802_devlist);
/* ------------------------------------------------------------------ */
@@ -882,7 +881,7 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
BLACKBIRD_MPEG_CAPTURE,
BLACKBIRD_RAW_BITS_NONE);
- cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl);
+ cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook);
blackbird_initialize_codec(dev);
cx88_set_scale(dev->core, dev->width, dev->height,
@@ -914,11 +913,15 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
}
default:
- return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl);
+ return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook);
}
return 0;
}
+int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg);
+unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
+
static unsigned int mpeg_translate_ioctl(unsigned int cmd)
{
return cmd;
@@ -927,33 +930,48 @@ static unsigned int mpeg_translate_ioctl(unsigned int cmd)
static int mpeg_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- cmd = mpeg_translate_ioctl( cmd );
- return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl);
+ cmd = cx88_ioctl_translator( cmd );
+ return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook);
}
static int mpeg_open(struct inode *inode, struct file *file)
{
int minor = iminor(inode);
- struct cx8802_dev *h,*dev = NULL;
+ struct cx8802_dev *dev = NULL;
struct cx8802_fh *fh;
- struct list_head *list;
+ struct cx8802_driver *drv = NULL;
+ int err;
- list_for_each(list,&cx8802_devlist) {
- h = list_entry(list, struct cx8802_dev, devlist);
- if (h->mpeg_dev->minor == minor)
- dev = h;
- }
- if (NULL == dev)
+ dprintk( 1, "%s\n", __FUNCTION__);
+
+ dev = cx8802_get_device(inode);
+ if (dev == NULL)
return -ENODEV;
- if (blackbird_initialize_codec(dev) < 0)
+ /* Make sure we can acquire the hardware */
+ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+ if (drv) {
+ err = drv->request_acquire(drv);
+ if(err != 0) {
+ dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err);
+ return err;
+ }
+ }
+
+ if (blackbird_initialize_codec(dev) < 0) {
+ if (drv)
+ drv->request_release(drv);
return -EINVAL;
+ }
dprintk(1,"open minor=%d\n",minor);
/* allocate + initialize per filehandle data */
fh = kzalloc(sizeof(*fh),GFP_KERNEL);
- if (NULL == fh)
+ if (NULL == fh) {
+ if (drv)
+ drv->request_release(drv);
return -ENOMEM;
+ }
file->private_data = fh;
fh->dev = dev;
@@ -974,6 +992,8 @@ static int mpeg_open(struct inode *inode, struct file *file)
static int mpeg_release(struct inode *inode, struct file *file)
{
struct cx8802_fh *fh = file->private_data;
+ struct cx8802_dev *dev = NULL;
+ struct cx8802_driver *drv = NULL;
/* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */
blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
@@ -992,6 +1012,16 @@ static int mpeg_release(struct inode *inode, struct file *file)
videobuf_mmap_free(&fh->mpegq);
file->private_data = NULL;
kfree(fh);
+
+ /* Make sure we release the hardware */
+ dev = cx8802_get_device(inode);
+ if (dev == NULL)
+ return -ENODEV;
+
+ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+ if (drv)
+ drv->request_release(drv);
+
return 0;
}
@@ -1043,6 +1073,44 @@ static struct video_device cx8802_mpeg_template =
/* ------------------------------------------------------------------ */
+/* The CX8802 MPEG API will call this when we can use the hardware */
+static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv)
+{
+ struct cx88_core *core = drv->core;
+ int err = 0;
+
+ switch (core->board) {
+ case CX88_BOARD_HAUPPAUGE_HVR1300:
+ /* By default, core setup will leave the cx22702 out of reset, on the bus.
+ * We left the hardware on power up with the cx22702 active.
+ * We're being given access to re-arrange the GPIOs.
+ * Take the bus off the cx22702 and put the cx23416 on it.
+ */
+ cx_clear(MO_GP0_IO, 0x00000080); /* cx22702 in reset */
+ cx_set(MO_GP0_IO, 0x00000004); /* Disable the cx22702 */
+ break;
+ default:
+ err = -ENODEV;
+ }
+ return err;
+}
+
+/* The CX8802 MPEG API will call this when we need to release the hardware */
+static int cx8802_blackbird_advise_release(struct cx8802_driver *drv)
+{
+ struct cx88_core *core = drv->core;
+ int err = 0;
+
+ switch (core->board) {
+ case CX88_BOARD_HAUPPAUGE_HVR1300:
+ /* Exit leaving the cx23416 on the bus */
+ break;
+ default:
+ err = -ENODEV;
+ }
+ return err;
+}
+
static void blackbird_unregister_video(struct cx8802_dev *dev)
{
if (dev->mpeg_dev) {
@@ -1073,28 +1141,23 @@ static int blackbird_register_video(struct cx8802_dev *dev)
/* ----------------------------------------------------------- */
-static int __devinit blackbird_probe(struct pci_dev *pci_dev,
- const struct pci_device_id *pci_id)
+static int cx8802_blackbird_probe(struct cx8802_driver *drv)
{
- struct cx8802_dev *dev;
- struct cx88_core *core;
+ struct cx88_core *core = drv->core;
+ struct cx8802_dev *dev = core->dvbdev;
int err;
- /* general setup */
- core = cx88_core_get(pci_dev);
- if (NULL == core)
- return -EINVAL;
+ dprintk( 1, "%s\n", __FUNCTION__);
+ dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+ core->board,
+ core->name,
+ core->pci_bus,
+ core->pci_slot);
err = -ENODEV;
if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD))
goto fail_core;
- err = -ENOMEM;
- dev = kzalloc(sizeof(*dev),GFP_KERNEL);
- if (NULL == dev)
- goto fail_core;
- dev->pci = pci_dev;
- dev->core = core;
dev->width = 720;
dev->height = 576;
cx2341x_fill_defaults(&dev->params);
@@ -1106,64 +1169,36 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
dev->height = 576;
}
- err = cx8802_init_common(dev);
- if (0 != err)
- goto fail_free;
-
/* blackbird stuff */
printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
core->name);
host_setup(dev->core);
- list_add_tail(&dev->devlist,&cx8802_devlist);
blackbird_register_video(dev);
/* initial device configuration: needed ? */
return 0;
- fail_free:
- kfree(dev);
fail_core:
- cx88_core_put(core,pci_dev);
return err;
}
-static void __devexit blackbird_remove(struct pci_dev *pci_dev)
+static int cx8802_blackbird_remove(struct cx8802_driver *drv)
{
- struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
-
/* blackbird */
- blackbird_unregister_video(dev);
- list_del(&dev->devlist);
+ blackbird_unregister_video(drv->core->dvbdev);
- /* common */
- cx8802_fini_common(dev);
- cx88_core_put(dev->core,dev->pci);
- kfree(dev);
+ return 0;
}
-static struct pci_device_id cx8802_pci_tbl[] = {
- {
- .vendor = 0x14f1,
- .device = 0x8802,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },{
- /* --- end of list --- */
- }
-};
-MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
-
-static struct pci_driver blackbird_pci_driver = {
- .name = "cx88-blackbird",
- .id_table = cx8802_pci_tbl,
- .probe = blackbird_probe,
- .remove = __devexit_p(blackbird_remove),
-#ifdef CONFIG_PM
- .suspend = cx8802_suspend_common,
- .resume = cx8802_resume_common,
-#endif
+static struct cx8802_driver cx8802_blackbird_driver = {
+ .type_id = CX88_MPEG_BLACKBIRD,
+ .hw_access = CX8802_DRVCTL_SHARED,
+ .probe = cx8802_blackbird_probe,
+ .remove = cx8802_blackbird_remove,
+ .advise_acquire = cx8802_blackbird_advise_acquire,
+ .advise_release = cx8802_blackbird_advise_release,
};
static int blackbird_init(void)
@@ -1176,17 +1211,22 @@ static int blackbird_init(void)
printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
#endif
- return pci_register_driver(&blackbird_pci_driver);
+ cx88_ioctl_hook = mpeg_do_ioctl;
+ cx88_ioctl_translator = mpeg_translate_ioctl;
+ return cx8802_register_driver(&cx8802_blackbird_driver);
}
static void blackbird_fini(void)
{
- pci_unregister_driver(&blackbird_pci_driver);
+ cx8802_unregister_driver(&cx8802_blackbird_driver);
}
module_init(blackbird_init);
module_exit(blackbird_fini);
+EXPORT_SYMBOL(cx88_ioctl_hook);
+EXPORT_SYMBOL(cx88_ioctl_translator);
+
/* ----------------------------------------------------------- */
/*
* Local variables: