⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cx88-mpeg.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
		return -EIO;	pci_set_master(dev->pci);	if (!pci_dma_supported(dev->pci,DMA_32BIT_MASK)) {		printk("%s/2: Oops: no 32bit PCI DMA ???\n",dev->core->name);		return -EIO;	}	pci_read_config_byte(dev->pci, PCI_CLASS_REVISION, &dev->pci_rev);	pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER,  &dev->pci_lat);	printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, "	       "latency: %d, mmio: 0x%llx\n", dev->core->name,	       pci_name(dev->pci), dev->pci_rev, dev->pci->irq,	       dev->pci_lat,(unsigned long long)pci_resource_start(dev->pci,0));	/* initialize driver struct */#if 0	/* moved to cx88_core_get */	init_MUTEX(&core->lock);#endif	spin_lock_init(&dev->slock);	/* init dma queue */	INIT_LIST_HEAD(&dev->mpegq.active);	INIT_LIST_HEAD(&dev->mpegq.queued);	dev->mpegq.timeout.function = cx8802_timeout;	dev->mpegq.timeout.data     = (unsigned long)dev;	init_timer(&dev->mpegq.timeout);	cx88_risc_stopper(dev->pci,&dev->mpegq.stopper,			  MO_TS_DMACNTRL,0x11,0x00);	/* get irq */	err = request_irq(dev->pci->irq, cx8802_irq,			  IRQF_SHARED | IRQF_DISABLED, dev->core->name, dev);	if (err < 0) {		printk(KERN_ERR "%s: can't get IRQ %d\n",		       dev->core->name, dev->pci->irq);		return err;	}	cx_set(MO_PCI_INTMSK, core->pci_irqmask);	/* everything worked */	pci_set_drvdata(dev->pci,dev);	return 0;}static void cx8802_fini_common(struct cx8802_dev *dev){	dprintk( 2, "cx8802_fini_common\n" );	cx8802_stop_dma(dev);	pci_disable_device(dev->pci);	/* unregister stuff */	free_irq(dev->pci->irq, dev);	pci_set_drvdata(dev->pci, NULL);	/* free memory */	btcx_riscmem_free(dev->pci,&dev->mpegq.stopper);}/* ----------------------------------------------------------- */static int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state){	struct cx8802_dev *dev = pci_get_drvdata(pci_dev);	struct cx88_core *core = dev->core;	/* stop mpeg dma */	spin_lock(&dev->slock);	if (!list_empty(&dev->mpegq.active)) {		dprintk( 2, "suspend\n" );		printk("%s: suspend mpeg\n", core->name);		cx8802_stop_dma(dev);		del_timer(&dev->mpegq.timeout);	}	spin_unlock(&dev->slock);#if 1	/* FIXME -- shutdown device */	cx88_shutdown(dev->core);#endif	pci_save_state(pci_dev);	if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {		pci_disable_device(pci_dev);		dev->state.disabled = 1;	}	return 0;}static int cx8802_resume_common(struct pci_dev *pci_dev){	struct cx8802_dev *dev = pci_get_drvdata(pci_dev);	struct cx88_core *core = dev->core;	int err;	if (dev->state.disabled) {		err=pci_enable_device(pci_dev);		if (err) {			printk(KERN_ERR "%s: can't enable device\n",					       dev->core->name);			return err;		}		dev->state.disabled = 0;	}	err=pci_set_power_state(pci_dev, PCI_D0);	if (err) {		printk(KERN_ERR "%s: can't enable device\n",					       dev->core->name);		pci_disable_device(pci_dev);		dev->state.disabled = 1;		return err;	}	pci_restore_state(pci_dev);#if 1	/* FIXME: re-initialize hardware */	cx88_reset(dev->core);#endif	/* restart video+vbi capture */	spin_lock(&dev->slock);	if (!list_empty(&dev->mpegq.active)) {		printk("%s: resume mpeg\n", core->name);		cx8802_restart_queue(dev,&dev->mpegq);	}	spin_unlock(&dev->slock);	return 0;}#if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \    defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE)struct cx8802_dev * cx8802_get_device(struct inode *inode){	int minor = iminor(inode);	struct cx8802_dev *dev;	list_for_each_entry(dev, &cx8802_devlist, devlist)		if (dev->mpeg_dev && dev->mpeg_dev->minor == minor)			return dev;	return NULL;}EXPORT_SYMBOL(cx8802_get_device);#endifstruct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype){	struct cx8802_driver *d;	list_for_each_entry(d, &dev->drvlist, drvlist)		if (d->type_id == btype)			return d;	return NULL;}/* Driver asked for hardware access. */static int cx8802_request_acquire(struct cx8802_driver *drv){	struct cx88_core *core = drv->core;	/* Fail a request for hardware if the device is busy. */	if (core->active_type_id != CX88_BOARD_NONE &&	    core->active_type_id != drv->type_id)		return -EBUSY;	core->input = CX88_VMUX_DVB;	if (drv->advise_acquire)	{		mutex_lock(&drv->core->lock);		core->active_ref++;		if (core->active_type_id == CX88_BOARD_NONE) {			core->active_type_id = drv->type_id;			drv->advise_acquire(drv);		}		mutex_unlock(&drv->core->lock);		mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));	}	return 0;}/* Driver asked to release hardware. */static int cx8802_request_release(struct cx8802_driver *drv){	struct cx88_core *core = drv->core;	mutex_lock(&drv->core->lock);	if (drv->advise_release && --core->active_ref == 0)	{		drv->advise_release(drv);		core->active_type_id = CX88_BOARD_NONE;		mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));	}	mutex_unlock(&drv->core->lock);	return 0;}static int cx8802_check_driver(struct cx8802_driver *drv){	if (drv == NULL)		return -ENODEV;	if ((drv->type_id != CX88_MPEG_DVB) &&		(drv->type_id != CX88_MPEG_BLACKBIRD))		return -EINVAL;	if ((drv->hw_access != CX8802_DRVCTL_SHARED) &&		(drv->hw_access != CX8802_DRVCTL_EXCLUSIVE))		return -EINVAL;	if ((drv->probe == NULL) ||		(drv->remove == NULL) ||		(drv->advise_acquire == NULL) ||		(drv->advise_release == NULL))		return -EINVAL;	return 0;}int cx8802_register_driver(struct cx8802_driver *drv){	struct cx8802_dev *dev;	struct cx8802_driver *driver;	int err, i = 0;	printk(KERN_INFO	       "cx88/2: registering cx8802 driver, type: %s access: %s\n",	       drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",	       drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");	if ((err = cx8802_check_driver(drv)) != 0) {		printk(KERN_ERR "cx88/2: cx8802_driver is invalid\n");		return err;	}	list_for_each_entry(dev, &cx8802_devlist, devlist) {		printk(KERN_INFO		       "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",		       dev->core->name, dev->pci->subsystem_vendor,		       dev->pci->subsystem_device, dev->core->board.name,		       dev->core->boardnr);		/* Bring up a new struct for each driver instance */		driver = kzalloc(sizeof(*drv),GFP_KERNEL);		if (driver == NULL)			return -ENOMEM;		/* Snapshot of the driver registration data */		drv->core = dev->core;		drv->suspend = cx8802_suspend_common;		drv->resume = cx8802_resume_common;		drv->request_acquire = cx8802_request_acquire;		drv->request_release = cx8802_request_release;		memcpy(driver, drv, sizeof(*driver));		err = drv->probe(driver);		if (err == 0) {			i++;			mutex_lock(&drv->core->lock);			list_add_tail(&driver->drvlist, &dev->drvlist);			mutex_unlock(&drv->core->lock);		} else {			printk(KERN_ERR			       "%s/2: cx8802 probe failed, err = %d\n",			       dev->core->name, err);		}	}	return i ? 0 : -ENODEV;}int cx8802_unregister_driver(struct cx8802_driver *drv){	struct cx8802_dev *dev;	struct cx8802_driver *d, *dtmp;	int err = 0;	printk(KERN_INFO	       "cx88/2: unregistering cx8802 driver, type: %s access: %s\n",	       drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",	       drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");	list_for_each_entry(dev, &cx8802_devlist, devlist) {		printk(KERN_INFO		       "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",		       dev->core->name, dev->pci->subsystem_vendor,		       dev->pci->subsystem_device, dev->core->board.name,		       dev->core->boardnr);		list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) {			/* only unregister the correct driver type */			if (d->type_id != drv->type_id)				continue;			err = d->remove(d);			if (err == 0) {				mutex_lock(&drv->core->lock);				list_del(&d->drvlist);				mutex_unlock(&drv->core->lock);				kfree(d);			} else				printk(KERN_ERR "%s/2: cx8802 driver remove "				       "failed (%d)\n", dev->core->name, err);		}	}	return err;}/* ----------------------------------------------------------- */static int __devinit cx8802_probe(struct pci_dev *pci_dev,			       const struct pci_device_id *pci_id){	struct cx8802_dev *dev;	struct cx88_core  *core;	int err;#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)	struct videobuf_dvb_frontend *demod;	int i;#endif	/* general setup */	core = cx88_core_get(pci_dev);	if (NULL == core)		return -EINVAL;	printk("%s/2: cx2388x 8802 Driver Manager\n", core->name);	err = -ENODEV;	if (!core->board.mpeg)		goto fail_core;	err = -ENOMEM;	dev = kzalloc(sizeof(*dev),GFP_KERNEL);	if (NULL == dev)		goto fail_core;	dev->pci = pci_dev;	dev->core = core;	err = cx8802_init_common(dev);	if (err != 0)		goto fail_free;	INIT_LIST_HEAD(&dev->drvlist);	list_add_tail(&dev->devlist,&cx8802_devlist);#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)	mutex_init(&dev->frontends.lock);	INIT_LIST_HEAD(&dev->frontends.felist);	if (core->board.num_frontends)		printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, core->board.num_frontends);	for (i = 1; i <= core->board.num_frontends; i++) {		demod = videobuf_dvb_alloc_frontend(&dev->frontends, i);		if(demod == NULL) {			printk(KERN_ERR "%s() failed to alloc\n", __func__);			err = -ENOMEM;			goto fail_free;		}	}#endif	/* Maintain a reference so cx88-video can query the 8802 device. */	core->dvbdev = dev;	/* now autoload cx88-dvb or cx88-blackbird */	request_modules(dev);	return 0; fail_free:	kfree(dev); fail_core:	cx88_core_put(core,pci_dev);	return err;}static void __devexit cx8802_remove(struct pci_dev *pci_dev){	struct cx8802_dev *dev;	dev = pci_get_drvdata(pci_dev);	dprintk( 1, "%s\n", __func__);	if (!list_empty(&dev->drvlist)) {		struct cx8802_driver *drv, *tmp;		int err;		printk(KERN_WARNING "%s/2: Trying to remove cx8802 driver "		       "while cx8802 sub-drivers still loaded?!\n",		       dev->core->name);		list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) {			err = drv->remove(drv);			if (err == 0) {				mutex_lock(&drv->core->lock);				list_del(&drv->drvlist);				mutex_unlock(&drv->core->lock);			} else				printk(KERN_ERR "%s/2: cx8802 driver remove "				       "failed (%d)\n", dev->core->name, err);			kfree(drv);		}	}	/* Destroy any 8802 reference. */	dev->core->dvbdev = NULL;	/* common */	cx8802_fini_common(dev);	cx88_core_put(dev->core,dev->pci);	kfree(dev);}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 cx8802_pci_driver = {	.name     = "cx88-mpeg driver manager",	.id_table = cx8802_pci_tbl,	.probe    = cx8802_probe,	.remove   = __devexit_p(cx8802_remove),#if 0	/* TODO: Implement this */	.suspend  = cx8802_suspend_common,	.resume   = cx8802_resume_common,#endif};static int cx8802_init(void){	printk(KERN_INFO "cx88/2: cx2388x MPEG-TS Driver Manager version %d.%d.%d loaded\n",	       (CX88_VERSION_CODE >> 16) & 0xff,	       (CX88_VERSION_CODE >>  8) & 0xff,	       CX88_VERSION_CODE & 0xff);#ifdef SNAPSHOT	printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",	       SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);#endif	return pci_register_driver(&cx8802_pci_driver);}static void cx8802_fini(void){	pci_unregister_driver(&cx8802_pci_driver);}module_init(cx8802_init);module_exit(cx8802_fini);EXPORT_SYMBOL(cx8802_buf_prepare);EXPORT_SYMBOL(cx8802_buf_queue);EXPORT_SYMBOL(cx8802_cancel_buffers);EXPORT_SYMBOL(cx8802_register_driver);EXPORT_SYMBOL(cx8802_unregister_driver);EXPORT_SYMBOL(cx8802_get_driver);#if 0EXPORT_SYMBOL(cx8802_suspend_common);EXPORT_SYMBOL(cx8802_resume_common);#endif/* ----------------------------------------------------------- *//* * Local variables: * c-basic-offset: 8 * End: * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -