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

📄 cx88-video.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
}static void cx8800_vid_irq(struct cx8800_dev *dev){	u32 status, mask, count;	status = cx_read(MO_VID_INTSTAT);	mask   = cx_read(MO_VID_INTMSK);	if (0 == (status & mask))		return;	cx_write(MO_VID_INTSTAT, status);	if (irq_debug  ||  (status & mask & ~0xff))		cx88_print_irqbits(dev->name, "irq vid",				   cx88_vid_irqs, status, mask);	/* risc op code error */	if (status & (1 << 16)) {		printk(KERN_WARNING "%s: video risc op code error\n",dev->name);		cx_clear(MO_VID_DMACNTRL, 0x11);		cx_clear(VID_CAPTURE_CONTROL, 0x06);		cx88_sram_channel_dump(dev, &cx88_sram_channels[SRAM_CH21]);	}		/* risc1 y */	if (status & 0x01) {		spin_lock(&dev->slock);		count = cx_read(MO_VIDY_GPCNT);		cx8800_wakeup(dev, &dev->vidq, count);		spin_unlock(&dev->slock);	}	/* risc1 vbi */	if (status & 0x08) {		spin_lock(&dev->slock);		count = cx_read(MO_VBI_GPCNT);		cx8800_wakeup(dev, &dev->vbiq, count);		spin_unlock(&dev->slock);	}	/* risc2 y */	if (status & 0x10) {		dprintk(2,"stopper video\n");		spin_lock(&dev->slock);		restart_video_queue(dev,&dev->vidq);		spin_unlock(&dev->slock);	}	/* risc2 vbi */	if (status & 0x80) {		dprintk(2,"stopper vbi\n");		spin_lock(&dev->slock);		cx8800_restart_vbi_queue(dev,&dev->vbiq);		spin_unlock(&dev->slock);	}}static irqreturn_t cx8800_irq(int irq, void *dev_id, struct pt_regs *regs){	struct cx8800_dev *dev = dev_id;	u32 status, mask;	int loop, handled = 0;	for (loop = 0; loop < 10; loop++) {		status = cx_read(MO_PCI_INTSTAT);		mask   = cx_read(MO_PCI_INTMSK);		if (0 == (status & mask))			goto out;		handled = 1;		cx_write(MO_PCI_INTSTAT, status);		if (irq_debug  ||  (status & mask & ~0x1f))			cx88_print_irqbits(dev->name, "irq pci",					   cx88_pci_irqs, status, mask);		if (status & 1)			cx8800_vid_irq(dev);	};	if (10 == loop) {		printk(KERN_WARNING "%s: irq loop -- clearing mask\n",		       dev->name);		cx_write(MO_PCI_INTMSK,0);	}	 out:	return IRQ_RETVAL(handled);}/* ----------------------------------------------------------- *//* exported stuff                                              */static struct file_operations video_fops ={	.owner	       = THIS_MODULE,	.open	       = video_open,	.release       = video_release,	.read	       = video_read,	.poll          = video_poll,	.mmap	       = video_mmap,	.ioctl	       = video_ioctl,	.llseek        = no_llseek,};struct video_device cx8800_video_template ={	.name          = "cx8800-video",	.type          = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES,	.hardware      = 0,	.fops          = &video_fops,	.minor         = -1,};struct video_device cx8800_vbi_template ={	.name          = "cx8800-vbi",	.type          = VID_TYPE_TELETEXT|VID_TYPE_TUNER,	.hardware      = 0,	.fops          = &video_fops,	.minor         = -1,};static struct file_operations radio_fops ={	.owner         = THIS_MODULE,	.open          = video_open,	.release       = video_release,	.ioctl         = radio_ioctl,	.llseek        = no_llseek,};struct video_device cx8800_radio_template ={	.name          = "cx8800-radio",	.type          = VID_TYPE_TUNER,	.hardware      = 0,	.fops          = &radio_fops,	.minor         = -1,};/* ----------------------------------------------------------- */static void cx8800_shutdown(struct cx8800_dev *dev){	/* disable RISC controller + IRQs */	cx_write(MO_DEV_CNTRL2, 0);	/* stop dma transfers */	cx_write(MO_VID_DMACNTRL, 0x0);	cx_write(MO_AUD_DMACNTRL, 0x0);	cx_write(MO_TS_DMACNTRL, 0x0);	cx_write(MO_VIP_DMACNTRL, 0x0);	cx_write(MO_GPHST_DMACNTRL, 0x0);	/* stop interupts */	cx_write(MO_PCI_INTMSK, 0x0);	cx_write(MO_VID_INTMSK, 0x0);	cx_write(MO_AUD_INTMSK, 0x0);	cx_write(MO_TS_INTMSK, 0x0);	cx_write(MO_VIP_INTMSK, 0x0);	cx_write(MO_GPHST_INTMSK, 0x0);	/* stop capturing */	cx_write(VID_CAPTURE_CONTROL, 0);}static int cx8800_reset(struct cx8800_dev *dev){	dprintk(1,"cx8800_reset\n");	cx8800_shutdown(dev);		/* clear irq status */	cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int	cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int	cx_write(MO_INT1_STAT,   0xFFFFFFFF); // Clear RISC int	/* wait a bit */	set_current_state(TASK_INTERRUPTIBLE);	schedule_timeout(HZ/10);		/* init sram */	cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH21], 720*4, 0);	cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH22], 128, 0);	cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH23], 128, 0);	cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH24], 128, 0);	cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH25], 128, 0);	cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH26], 128, 0);		/* misc init ... */	cx_write(MO_INPUT_FORMAT, ((1 << 13) |   // agc enable				   (1 << 12) |   // agc gain				   (1 << 11) |   // adaptibe agc				   (0 << 10) |   // chroma agc				   (0 <<  9) |   // ckillen				   (7)));	/* setup image format */	cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);	/* setup FIFO Threshholds */	cx_write(MO_PDMA_STHRSH,   0x0807);	cx_write(MO_PDMA_DTHRSH,   0x0807);	/* fixes flashing of image */	cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);	cx_write(MO_AGC_BACK_VBI,  0x00E00555);		cx_write(MO_VID_INTSTAT,   0xFFFFFFFF); // Clear PIV int	cx_write(MO_PCI_INTSTAT,   0xFFFFFFFF); // Clear PCI int	cx_write(MO_INT1_STAT,     0xFFFFFFFF); // Clear RISC int	return 0;}static struct video_device *vdev_init(struct cx8800_dev *dev,				      struct video_device *template,				      char *type){	struct video_device *vfd;	vfd = video_device_alloc();	if (NULL == vfd)		return NULL;	*vfd = *template;	vfd->minor   = -1;	vfd->dev     = &dev->pci->dev;	vfd->release = video_device_release;	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",		 dev->name, type, cx88_boards[dev->board].name);	return vfd;}static void cx8800_unregister_video(struct cx8800_dev *dev){	if (dev->radio_dev) {		if (-1 != dev->radio_dev->minor)			video_unregister_device(dev->radio_dev);		else			video_device_release(dev->radio_dev);		dev->radio_dev = NULL;	}	if (dev->vbi_dev) {		if (-1 != dev->vbi_dev->minor)			video_unregister_device(dev->vbi_dev);		else			video_device_release(dev->vbi_dev);		dev->vbi_dev = NULL;	}	if (dev->video_dev) {		if (-1 != dev->video_dev->minor)			video_unregister_device(dev->video_dev);		else			video_device_release(dev->video_dev);		dev->video_dev = NULL;	}}static int __devinit cx8800_initdev(struct pci_dev *pci_dev,				    const struct pci_device_id *pci_id){	struct cx8800_dev *dev;	unsigned int i;	int err;	dev = kmalloc(sizeof(*dev),GFP_KERNEL);	if (NULL == dev)		return -ENOMEM;	memset(dev,0,sizeof(*dev));	/* pci init */	dev->pci = pci_dev;	if (pci_enable_device(pci_dev)) {		err = -EIO;		goto fail1;	}	sprintf(dev->name,"cx%x[%d]",pci_dev->device,cx8800_devcount);	/* pci quirks */	cx88_pci_quirks(dev->name, dev->pci, &latency);	if (UNSET != latency) {		printk(KERN_INFO "%s: setting pci latency timer to %d\n",		       dev->name,latency);		pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, latency);	}	/* print pci info */	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);        pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);        printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, "	       "latency: %d, mmio: 0x%lx\n", dev->name,	       pci_name(pci_dev), dev->pci_rev, pci_dev->irq,	       dev->pci_lat,pci_resource_start(pci_dev,0));	pci_set_master(pci_dev);	if (!pci_dma_supported(pci_dev,0xffffffff)) {		printk("%s: Oops: no 32bit PCI DMA ???\n",dev->name);		err = -EIO;		goto fail1;	}	/* board config */	dev->board = card[cx8800_devcount];	for (i = 0; UNSET == dev->board  &&  i < cx88_idcount; i++) 		if (pci_dev->subsystem_vendor == cx88_subids[i].subvendor &&		    pci_dev->subsystem_device == cx88_subids[i].subdevice)			dev->board = cx88_subids[i].card;	if (UNSET == dev->board) {		dev->board = CX88_BOARD_UNKNOWN;		cx88_card_list(dev);	}        printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",	       dev->name,pci_dev->subsystem_vendor,	       pci_dev->subsystem_device,cx88_boards[dev->board].name,	       dev->board, card[cx8800_devcount] == dev->board ?	       "insmod option" : "autodetected");	dev->tuner_type = tuner[cx8800_devcount];	if (UNSET == dev->tuner_type)		dev->tuner_type = cx88_boards[dev->board].tuner_type;	/* get mmio */	if (!request_mem_region(pci_resource_start(pci_dev,0),				pci_resource_len(pci_dev,0),				dev->name)) {		err = -EBUSY;		printk(KERN_ERR "%s: can't get MMIO memory @ 0x%lx\n",		       dev->name,pci_resource_start(pci_dev,0));		goto fail1;	}	dev->lmmio = ioremap(pci_resource_start(pci_dev,0),			     pci_resource_len(pci_dev,0));	dev->bmmio = (u8*)dev->lmmio;	/* initialize driver struct */        init_MUTEX(&dev->lock);	dev->slock = SPIN_LOCK_UNLOCKED;	dev->tvnorm = tvnorms;	/* init video dma queues */	INIT_LIST_HEAD(&dev->vidq.active);	INIT_LIST_HEAD(&dev->vidq.queued);	dev->vidq.timeout.function = cx8800_vid_timeout;	dev->vidq.timeout.data     = (unsigned long)dev;	init_timer(&dev->vidq.timeout);	cx88_risc_stopper(dev->pci,&dev->vidq.stopper,			  MO_VID_DMACNTRL,0x11,0x00);	/* init vbi dma queues */	INIT_LIST_HEAD(&dev->vbiq.active);	INIT_LIST_HEAD(&dev->vbiq.queued);	dev->vbiq.timeout.function = cx8800_vbi_timeout;	dev->vbiq.timeout.data     = (unsigned long)dev;	init_timer(&dev->vbiq.timeout);	cx88_risc_stopper(dev->pci,&dev->vbiq.stopper,			  MO_VID_DMACNTRL,0x88,0x00);	/* initialize hardware */	cx8800_reset(dev);	/* get irq */	err = request_irq(pci_dev->irq, cx8800_irq,			  SA_SHIRQ | SA_INTERRUPT, dev->name, dev);	if (err < 0) {		printk(KERN_ERR "%s: can't get IRQ %d\n",		       dev->name,pci_dev->irq);		goto fail2;	}	/* register i2c bus + load i2c helpers */	cx8800_i2c_init(dev);	cx88_card_setup(dev);	/* load and configure helper modules */	if (TUNER_ABSENT != dev->tuner_type)		request_module("tuner");	if (cx88_boards[dev->board].needs_tda9887)		request_module("tda9887");	if (dev->tuner_type != UNSET)		cx8800_call_i2c_clients(dev,TUNER_SET_TYPE,&dev->tuner_type);	/* register v4l devices */	dev->video_dev = vdev_init(dev,&cx8800_video_template,"video");	err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,				    video_nr[cx8800_devcount]);	if (err < 0) {		printk(KERN_INFO "%s: can't register video device\n",		       dev->name);		goto fail3;	}	printk(KERN_INFO "%s: registered device video%d [v4l2]\n",	       dev->name,dev->video_dev->minor & 0x1f);	dev->vbi_dev = vdev_init(dev,&cx8800_vbi_template,"vbi");	err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,				    vbi_nr[cx8800_devcount]);	if (err < 0) {		printk(KERN_INFO "%s: can't register vbi device\n",		       dev->name);		goto fail3;	}	printk(KERN_INFO "%s: registered device vbi%d\n",	       dev->name,dev->vbi_dev->minor & 0x1f);	if (dev->has_radio) {		dev->radio_dev = vdev_init(dev,&cx8800_radio_template,"radio");		err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,					    radio_nr[cx8800_devcount]);		if (err < 0) {			printk(KERN_INFO "%s: can't register radio device\n",			       dev->name);			goto fail3;		}		printk(KERN_INFO "%s: registered device radio%d\n",		       dev->name,dev->radio_dev->minor & 0x1f);	}	/* everything worked */	list_add_tail(&dev->devlist,&cx8800_devlist);	pci_set_drvdata(pci_dev,dev);	cx8800_devcount++;	/* initial device configuration */	down(&dev->lock);	init_controls(dev);	set_tvnorm(dev,tvnorms);	video_mux(dev,0);	up(&dev->lock);	/* start tvaudio thread */	init_completion(&dev->texit);	dev->tpid = kernel_thread(cx88_audio_thread, dev, 0);	return 0; fail3:	cx8800_unregister_video(dev);	if (0 == dev->i2c_rc)		i2c_bit_del_bus(&dev->i2c_adap);	free_irq(pci_dev->irq, dev); fail2:	release_mem_region(pci_resource_start(pci_dev,0),			   pci_resource_len(pci_dev,0)); fail1:	kfree(dev);	return err;}static void __devexit cx8800_finidev(struct pci_dev *pci_dev){        struct cx8800_dev *dev = pci_get_drvdata(pci_dev);	/* stop thread */	dev->shutdown = 1;	if (dev->tpid >= 0)		wait_for_completion(&dev->texit);	cx8800_shutdown(dev);	pci_disable_device(pci_dev);	/* unregister stuff */		if (0 == dev->i2c_rc)		i2c_bit_del_bus(&dev->i2c_adap);	free_irq(pci_dev->irq, dev);	release_mem_region(pci_resource_start(pci_dev,0),			   pci_resource_len(pci_dev,0));	cx8800_unregister_video(dev);	pci_set_drvdata(pci_dev, NULL);	/* free memory */	btcx_riscmem_free(dev->pci,&dev->vidq.stopper);	list_del(&dev->devlist);	cx8800_devcount--;	kfree(dev);}static int cx8800_suspend(struct pci_dev *pci_dev, u32 state){        struct cx8800_dev *dev = pci_get_drvdata(pci_dev);	printk("%s: suspend %d\n", dev->name, state);	cx8800_shutdown(dev);	del_timer(&dev->vidq.timeout);		pci_save_state(pci_dev, dev->state.pci_cfg);	if (0 != pci_set_power_state(pci_dev, state)) {		pci_disable_device(pci_dev);		dev->state.disabled = 1;	}	return 0;}static int cx8800_resume(struct pci_dev *pci_dev){        struct cx8800_dev *dev = pci_get_drvdata(pci_dev);	printk("%s: resume\n", dev->name);	if (dev->state.disabled) {		pci_enable_device(pci_dev);		dev->state.disabled = 0;	}	pci_set_power_state(pci_dev, 0);	pci_restore_state(pci_dev, dev->state.pci_cfg);	/* re-initialize hardware */	cx8800_reset(dev);	/* restart video capture */	spin_lock(&dev->slock);	restart_video_queue(dev,&dev->vidq);	spin_unlock(&dev->slock);	return 0;}/*

⌨️ 快捷键说明

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