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

📄 zr36120.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	clear_bit(STATE_VBI, &ztv->state);	zoran_common_close(ztv);        /*         *      This is sucky but right now I can't find a good way to         *      be sure its safe to free the buffer. We wait 5-6 fields         *      which is more than sufficient to be sure.         */        msleep(100);			/* Wait 1/10th of a second */	for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++)	{		if (item->memadr)			bfree(item->memadr, ZORAN_VBI_BUFSIZE);		item->memadr = 0;	}}/* * This read function could be used reentrant in a SMP situation. * * This is made possible by the spinlock which is kept till we * found and marked a buffer for our own use. The lock must * be released as soon as possible to prevent lock contention. */staticlong vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonblock){	struct zoran *ztv = dev->priv;	unsigned long max;	struct vidinfo* unused = 0;	struct vidinfo* done = 0;	DEBUG(printk(CARD_DEBUG "vbi_read(0x%p,%ld,%d)\n",CARD,buf,count,nonblock));	/* find ourself a free or completed buffer */	for (;;) {		struct vidinfo* item;		write_lock_irq(&ztv->lock);		for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++) {			if (!unused && item->status == FBUFFER_FREE)				unused = item;			if (!done && item->status == FBUFFER_DONE)				done = item;		}		if (done || unused)			break;		/* no more free buffers, wait for them. */		write_unlock_irq(&ztv->lock);		if (nonblock)			return -EWOULDBLOCK;		interruptible_sleep_on(&ztv->vbiq);		if (signal_pending(current))			return -EINTR;	}	/* Do we have 'ready' data? */	if (!done) {		/* no? than this will take a while... */		if (nonblock) {			write_unlock_irq(&ztv->lock);			return -EWOULDBLOCK;		}				/* mark the unused buffer as wanted */		unused->status = FBUFFER_BUSY;		unused->next = 0;		{ /* add to tail of queue */		  struct vidinfo* oldframe = ztv->workqueue;		  if (!oldframe) ztv->workqueue = unused;		  else {		    while (oldframe->next) oldframe = oldframe->next;		    oldframe->next = unused;		  }		}		write_unlock_irq(&ztv->lock);		/* tell the state machine we want it filled /NOW/ */		zoran_cap(ztv, 1);		/* wait till this buffer gets grabbed */		wait_event_interruptible(ztv->vbiq,				(unused->status != FBUFFER_BUSY));		/* see if a signal did it */		if (signal_pending(current))			return -EINTR;		done = unused;	}	else		write_unlock_irq(&ztv->lock);	/* Yes! we got data! */	max = done->bpl * -done->h;	if (count > max)		count = max;	/* check if the user gave us enough room to write the data */	if (!access_ok(VERIFY_WRITE, buf, count)) {		count = -EFAULT;		goto out;	}	/*	 * Now transform/strip the data from YUV to Y-only	 * NB. Assume the Y is in the LSB of the YUV data.	 */	{	unsigned char* optr = buf;	unsigned char* eptr = buf+count;	/* are we beeing accessed from an old driver? */	if (count == 2*19*2048) {		/*		 * Extreme HACK, old VBI programs expect 2048 points		 * of data, and we only got 864 orso. Double each 		 * datapoint and clear the rest of the line.		 * This way we have appear to have a		 * sample_frequency of 29.5 Mc.		 */		int x,y;		unsigned char* iptr = done->memadr+1;		for (y=done->h; optr<eptr && y<0; y++)		{			/* copy to doubled data to userland */			for (x=0; optr+1<eptr && x<-done->w; x++)			{				unsigned char a = iptr[x*2];				__put_user(a, optr++);				__put_user(a, optr++);			}			/* and clear the rest of the line */			for (x*=2; optr<eptr && x<done->bpl; x++)				__put_user(0, optr++);			/* next line */			iptr += done->bpl;		}	}	else {		/*		 * Other (probably newer) programs asked		 * us what geometry we are using, and are		 * reading the correct size.		 */		int x,y;		unsigned char* iptr = done->memadr+1;		for (y=done->h; optr<eptr && y<0; y++)		{			/* copy to doubled data to userland */			for (x=0; optr<eptr && x<-done->w; x++)				__put_user(iptr[x*2], optr++);			/* and clear the rest of the line */			for (;optr<eptr && x<done->bpl; x++)				__put_user(0, optr++);			/* next line */			iptr += done->bpl;		}	}	/* API compliance:	 * place the framenumber (half fieldnr) in the last long	 */	__put_user(done->fieldnr/2, ((ulong*)eptr)[-1]);	}	/* keep the engine running */	done->status = FBUFFER_FREE;	zoran_cap(ztv, 1);	/* tell listeners this buffer just became free */	wake_up_interruptible(&ztv->vbiq);	/* goodbye */out:	DEBUG(printk(CARD_DEBUG "vbi_read() returns %lu\n",CARD,count));	return count;}staticunsigned int vbi_poll(struct video_device *dev, struct file *file, poll_table *wait){	struct zoran *ztv = dev->priv;	struct vidinfo* item;	unsigned int mask = 0;	poll_wait(file, &ztv->vbiq, wait);	for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++)		if (item->status == FBUFFER_DONE)		{			mask |= (POLLIN | POLLRDNORM);			break;		}	DEBUG(printk(CARD_DEBUG "vbi_poll()=%x\n",CARD,mask));	return mask;}staticint vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg){	struct zoran* ztv = dev->priv;	switch (cmd) {	 case VIDIOCGVBIFMT:	 {		struct vbi_format f;		DEBUG(printk(CARD_DEBUG "VIDIOCGVBIINFO\n",CARD));		f.sampling_rate = 14750000UL;		f.samples_per_line = -ztv->readinfo[0].w;		f.sample_format = VIDEO_PALETTE_RAW;		f.start[0] = f.start[1] = ztv->readinfo[0].y;		f.start[1] += 312;		f.count[0] = f.count[1] = -ztv->readinfo[0].h;		f.flags = VBI_INTERLACED;		if (copy_to_user(arg,&f,sizeof(f)))			return -EFAULT;		break;	 }	 case VIDIOCSVBIFMT:	 {		struct vbi_format f;		int i;		if (copy_from_user(&f, arg,sizeof(f)))			return -EFAULT;		DEBUG(printk(CARD_DEBUG "VIDIOCSVBIINFO(%d,%d,%d,%d,%d,%d,%d,%x)\n",CARD,f.sampling_rate,f.samples_per_line,f.sample_format,f.start[0],f.start[1],f.count[0],f.count[1],f.flags));		/* lots of parameters are fixed... (PAL) */		if (f.sampling_rate != 14750000UL ||		    f.samples_per_line > 864 ||		    f.sample_format != VIDEO_PALETTE_RAW ||		    f.start[0] < 0 ||		    f.start[0] != f.start[1]-312 ||		    f.count[0] != f.count[1] ||		    f.start[0]+f.count[0] >= 288 ||		    f.flags != VBI_INTERLACED)			return -EINVAL;		write_lock_irq(&ztv->lock);		ztv->readinfo[0].y = f.start[0];		ztv->readinfo[0].w = -f.samples_per_line;		ztv->readinfo[0].h = -f.count[0];		ztv->readinfo[0].bpl = f.samples_per_line*ztv->readinfo[0].bpp;		for (i=1; i<ZORAN_VBI_BUFFERS; i++)			ztv->readinfo[i] = ztv->readinfo[i];		write_unlock_irq(&ztv->lock);		break;	 }	 default:		return -ENOIOCTLCMD;	}	return 0;}static struct video_device vbi_template={	.owner		= THIS_MODULE,	.name		= "UNSET",	.type		= VID_TYPE_CAPTURE|VID_TYPE_TELETEXT,	.hardware	= VID_HARDWARE_ZR36120,	.open		= vbi_open,	.close		= vbi_close,	.read		= vbi_read,	.write		= zoran_write,	.poll		= vbi_poll,	.ioctl		= vbi_ioctl,	.minor		= -1,};/* *      Scan for a Zoran chip, request the irq and map the io memory */staticint __init find_zoran(void){	int result;	struct zoran *ztv;	struct pci_dev *dev = NULL;	unsigned char revision;	int zoran_num=0;	while ((dev = pci_find_device(PCI_VENDOR_ID_ZORAN,PCI_DEVICE_ID_ZORAN_36120, dev)))	{		/* Ok, a ZR36120/ZR36125 found! */		ztv = &zorans[zoran_num];		ztv->dev = dev;		if (pci_enable_device(dev))			return -EIO;		pci_read_config_byte(dev, PCI_CLASS_REVISION, &revision);		printk(KERN_INFO "zoran: Zoran %x (rev %d) ",			dev->device, revision);		printk("bus: %d, devfn: %d, irq: %d, ",			dev->bus->number, dev->devfn, dev->irq);		printk("memory: 0x%08lx.\n", ztv->zoran_adr);		ztv->zoran_mem = ioremap(ztv->zoran_adr, 0x1000);		DEBUG(printk(KERN_DEBUG "zoran: mapped-memory at 0x%p\n",ztv->zoran_mem));		result = request_irq(dev->irq, zoran_irq,			SA_SHIRQ|SA_INTERRUPT,"zoran", ztv);		if (result==-EINVAL)		{			iounmap(ztv->zoran_mem);			printk(KERN_ERR "zoran: Bad irq number or handler\n");			return -EINVAL;		}		if (result==-EBUSY)			printk(KERN_ERR "zoran: IRQ %d busy, change your PnP config in BIOS\n",dev->irq);		if (result < 0) {			iounmap(ztv->zoran_mem);			return result;		}		/* Enable bus-mastering */		pci_set_master(dev);		zoran_num++;	}	if(zoran_num)		printk(KERN_INFO "zoran: %d Zoran card(s) found.\n",zoran_num);	return zoran_num;}staticint __init init_zoran(int card){	struct zoran *ztv = &zorans[card];	int	i;	/* if the given cardtype valid? */	if (cardtype[card]>=NRTVCARDS) {		printk(KERN_INFO "invalid cardtype(%d) detected\n",cardtype[card]);		return -1;	}	/* reset the zoran */	zrand(~ZORAN_PCI_SOFTRESET,ZORAN_PCI);	udelay(10);	zror(ZORAN_PCI_SOFTRESET,ZORAN_PCI);	udelay(10);	/* zoran chip specific details */	ztv->card = tvcards+cardtype[card];	/* point to the selected card */	ztv->norm = 0;				/* PAL */	ztv->tuner_freq = 0;	/* videocard details */	ztv->swidth = 800;	ztv->sheight = 600;	ztv->depth = 16;	/* State details */	ztv->fbuffer = 0;	ztv->overinfo.kindof = FBUFFER_OVERLAY;	ztv->overinfo.status = FBUFFER_FREE;	ztv->overinfo.x = 0;	ztv->overinfo.y = 0;	ztv->overinfo.w = 768; /* 640 */	ztv->overinfo.h = 576; /* 480 */	ztv->overinfo.format = VIDEO_PALETTE_RGB565;	ztv->overinfo.bpp = palette2fmt[ztv->overinfo.format].bpp;	ztv->overinfo.bpl = ztv->overinfo.bpp*ztv->swidth;	ztv->overinfo.busadr = 0;	ztv->overinfo.memadr = 0;	ztv->overinfo.overlay = 0;	for (i=0; i<ZORAN_MAX_FBUFFERS; i++) {		ztv->grabinfo[i] = ztv->overinfo;		ztv->grabinfo[i].kindof = FBUFFER_GRAB;	}	init_waitqueue_head(&ztv->grabq);	/* VBI details */	ztv->readinfo[0] = ztv->overinfo;	ztv->readinfo[0].kindof = FBUFFER_VBI;	ztv->readinfo[0].w = -864;	ztv->readinfo[0].h = -38;	ztv->readinfo[0].format = VIDEO_PALETTE_YUV422;	ztv->readinfo[0].bpp = palette2fmt[ztv->readinfo[0].format].bpp;	ztv->readinfo[0].bpl = 1024*ztv->readinfo[0].bpp;	for (i=1; i<ZORAN_VBI_BUFFERS; i++)		ztv->readinfo[i] = ztv->readinfo[0];	init_waitqueue_head(&ztv->vbiq);	/* maintenance data */	ztv->have_decoder = 0;	ztv->have_tuner = 0;	ztv->tuner_type = 0;	ztv->running = 0;	ztv->users = 0;	rwlock_init(&ztv->lock);	ztv->workqueue = 0;	ztv->fieldnr = 0;	ztv->lastfieldnr = 0;	if (triton1)		zrand(~ZORAN_VDC_TRICOM, ZORAN_VDC);	/* external FL determines TOP frame */	zror(ZORAN_VFEC_EXTFL, ZORAN_VFEC); 	/* set HSpol */	if (ztv->card->hsync_pos)		zrwrite(ZORAN_VFEH_HSPOL, ZORAN_VFEH);	/* set VSpol */	if (ztv->card->vsync_pos)		zrwrite(ZORAN_VFEV_VSPOL, ZORAN_VFEV);	/* Set the proper General Purpuse register bits */	/* implicit: no softreset, 0 waitstates */	zrwrite(ZORAN_PCI_SOFTRESET|(ztv->card->gpdir<<0),ZORAN_PCI);	/* implicit: 3 duration and recovery PCI clocks on guest 0-3 */	zrwrite(ztv->card->gpval<<24,ZORAN_GUEST);	/* clear interrupt status */	zrwrite(~0, ZORAN_ISR);	/*	 * i2c template	 */	ztv->i2c = zoran_i2c_bus_template;	sprintf(ztv->i2c.name,"zoran-%d",card);	ztv->i2c.data = ztv;	/*	 * Now add the template and register the device unit	 */	ztv->video_dev = zr36120_template;	strcpy(ztv->video_dev.name, ztv->i2c.name);	ztv->video_dev.priv = ztv;	if (video_register_device(&ztv->video_dev, VFL_TYPE_GRABBER, video_nr) < 0)		return -1;	ztv->vbi_dev = vbi_template;	strcpy(ztv->vbi_dev.name, ztv->i2c.name);	ztv->vbi_dev.priv = ztv;	if (video_register_device(&ztv->vbi_dev, VFL_TYPE_VBI, vbi_nr) < 0) {		video_unregister_device(&ztv->video_dev);		return -1;	}	i2c_register_bus(&ztv->i2c);	/* set interrupt mask - the PIN enable will be set later */	zrwrite(ZORAN_ICR_GIRQ0|ZORAN_ICR_GIRQ1|ZORAN_ICR_CODE, ZORAN_ICR);	printk(KERN_INFO "%s: installed %s\n",ztv->i2c.name,ztv->card->name);	return 0;}staticvoid release_zoran(int max){	struct zoran *ztv;	int i;	for (i=0;i<max; i++) 	{		ztv = &zorans[i];		/* turn off all capturing, DMA and IRQs */		/* reset the zoran */		zrand(~ZORAN_PCI_SOFTRESET,ZORAN_PCI);		udelay(10);		zror(ZORAN_PCI_SOFTRESET,ZORAN_PCI);		udelay(10);		/* first disable interrupts before unmapping the memory! */		zrwrite(0, ZORAN_ICR);		zrwrite(0xffffffffUL,ZORAN_ISR);		/* free it */		free_irq(ztv->dev->irq,ztv);     		/* unregister i2c_bus */		i2c_unregister_bus((&ztv->i2c));		/* unmap and free memory */		if (ztv->zoran_mem)			iounmap(ztv->zoran_mem);		video_unregister_device(&ztv->video_dev);		video_unregister_device(&ztv->vbi_dev);	}}void __exit zr36120_exit(void){	release_zoran(zoran_cards);}int __init zr36120_init(void){	int	card; 	handle_chipset();	zoran_cards = find_zoran();	if (zoran_cards<0)		/* no cards found, no need for a driver */		return -EIO;	/* initialize Zorans */	for (card=0; card<zoran_cards; card++) {		if (init_zoran(card)<0) {			/* only release the zorans we have registered */			release_zoran(card);			return -EIO;		} 	}	return 0;}module_init(zr36120_init);module_exit(zr36120_exit);

⌨️ 快捷键说明

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