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

📄 zr36120.c

📁 pxa270下的摄像头mtd91111的驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
				v.flags |= VIDEO_VC_TUNER;				v.tuners = 1;			}		}		else if (mux & IS_SVHS)			sprintf(v.name,"S-Video-%d",v.channel);		else			sprintf(v.name,"CVBS-%d",v.channel);		if (copy_to_user(arg,&v,sizeof(v)))			return -EFAULT;		break;	 }	 case VIDIOCSCHAN:	 {	/* set video channel */		struct video_channel v;		if (copy_from_user(&v, arg,sizeof(v)))			return -EFAULT;		DEBUG(printk(CARD_DEBUG "VIDIOCSCHAN(%d,%d)\n",CARD,v.channel,v.norm));		/* too many inputs? no decoder -> no channels */		if (!ztv->have_decoder || v.channel >= ztv->card->video_inputs || v.channel < 0)			return -EINVAL;		if (v.norm != VIDEO_MODE_PAL &&		    v.norm != VIDEO_MODE_NTSC &&		    v.norm != VIDEO_MODE_SECAM &&		    v.norm != VIDEO_MODE_AUTO)			return -EOPNOTSUPP;		/* make it happen, nr1! */		return zoran_muxsel(ztv,v.channel,v.norm);	 }	 case VIDIOCGTUNER:	 {		struct video_tuner v;		if (copy_from_user(&v, arg,sizeof(v)))			return -EFAULT;		DEBUG(printk(CARD_DEBUG "VIDIOCGTUNER(%d)\n",CARD,v.tuner));		/* Only no or one tuner for now */		if (!ztv->have_tuner || v.tuner)			return -EINVAL;		strcpy(v.name,"Television");		v.rangelow  = 0;		v.rangehigh = ~0;		v.flags     = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;		v.mode      = ztv->norm;		v.signal    = 0xFFFF; /* unknown */		if (copy_to_user(arg,&v,sizeof(v)))			return -EFAULT;		break;	 }	 case VIDIOCSTUNER:	 {		struct video_tuner v;		if (copy_from_user(&v, arg, sizeof(v)))			return -EFAULT;		DEBUG(printk(CARD_DEBUG "VIDIOCSTUNER(%d,%d)\n",CARD,v.tuner,v.mode));		/* Only no or one tuner for now */		if (!ztv->have_tuner || v.tuner)			return -EINVAL;		/* and it only has certain valid modes */		if( v.mode != VIDEO_MODE_PAL &&		    v.mode != VIDEO_MODE_NTSC &&		    v.mode != VIDEO_MODE_SECAM)			return -EOPNOTSUPP;		/* engage! */		return zoran_muxsel(ztv,v.tuner,v.mode);	 }	 case VIDIOCGPICT:	 {		struct video_picture p = ztv->picture;		DEBUG(printk(CARD_DEBUG "VIDIOCGPICT\n",CARD));		p.depth = ztv->depth;		switch (p.depth) {		 case  8: p.palette=VIDEO_PALETTE_YUV422;			  break;		 case 15: p.palette=VIDEO_PALETTE_RGB555;			  break;		 case 16: p.palette=VIDEO_PALETTE_RGB565;			  break;		 case 24: p.palette=VIDEO_PALETTE_RGB24;			  break;		 case 32: p.palette=VIDEO_PALETTE_RGB32;			  break;		}		if (copy_to_user(arg, &p, sizeof(p)))			return -EFAULT;		break;	 }	 case VIDIOCSPICT:	 {		struct video_picture p;		if (copy_from_user(&p, arg,sizeof(p)))			return -EFAULT;		DEBUG(printk(CARD_DEBUG "VIDIOCSPICT(%d,%d,%d,%d,%d,%d,%d)\n",CARD,p.brightness,p.hue,p.colour,p.contrast,p.whiteness,p.depth,p.palette));		/* depth must match with framebuffer */		if (p.depth != ztv->depth)			return -EINVAL;		/* check if palette matches this bpp */		if (p.palette>NRPALETTES ||		    palette2fmt[p.palette].bpp != ztv->overinfo.bpp)			return -EINVAL;		write_lock_irq(&ztv->lock);		ztv->overinfo.format = p.palette;		ztv->picture = p;		write_unlock_irq(&ztv->lock);		/* tell the decoder */		i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &p);		break;	 }	 case VIDIOCGWIN:	 {		struct video_window vw;		DEBUG(printk(CARD_DEBUG "VIDIOCGWIN\n",CARD));		read_lock(&ztv->lock);		vw.x      = ztv->overinfo.x;		vw.y      = ztv->overinfo.y;		vw.width  = ztv->overinfo.w;		vw.height = ztv->overinfo.h;		vw.chromakey= 0;		vw.flags  = 0;		if (ztv->vidInterlace)			vw.flags|=VIDEO_WINDOW_INTERLACE;		read_unlock(&ztv->lock);		if (copy_to_user(arg,&vw,sizeof(vw)))			return -EFAULT;		break;	 }	 case VIDIOCSWIN:	 {		struct video_window vw;		struct video_clip *vcp;		int on;		if (copy_from_user(&vw,arg,sizeof(vw)))			return -EFAULT;		DEBUG(printk(CARD_DEBUG "VIDIOCSWIN(%d,%d,%d,%d,%x,%d)\n",CARD,vw.x,vw.y,vw.width,vw.height,vw.flags,vw.clipcount));		if (vw.flags)			return -EINVAL;		if (vw.clipcount <0 || vw.clipcount>256)			return -EDOM;   /* Too many! */		/*		 *      Do any clips.		 */		vcp = vmalloc(sizeof(struct video_clip)*(vw.clipcount+4));		if (vcp==NULL)			return -ENOMEM;		if (vw.clipcount && copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount)) {			vfree(vcp);			return -EFAULT;		}		on = ztv->running;		if (on)			zoran_cap(ztv, 0);		/*		 * strange, it seems xawtv sometimes calls us with 0		 * width and/or height. Ignore these values		 */		if (vw.x == 0)			vw.x = ztv->overinfo.x;		if (vw.y == 0)			vw.y = ztv->overinfo.y;		/* by now we are committed to the new data... */		write_lock_irq(&ztv->lock);		ztv->overinfo.x = vw.x;		ztv->overinfo.y = vw.y;		ztv->overinfo.w = vw.width;		ztv->overinfo.h = vw.height;		write_unlock_irq(&ztv->lock);		/*		 *      Impose display clips		 */		if (vw.x+vw.width > ztv->swidth)			new_clip(&vw, vcp, ztv->swidth-vw.x, 0, vw.width-1, vw.height-1);		if (vw.y+vw.height > ztv->sheight)			new_clip(&vw, vcp, 0, ztv->sheight-vw.y, vw.width-1, vw.height-1);		/* built the requested clipping zones */		zoran_set_geo(ztv, &ztv->overinfo);		zoran_built_overlay(ztv, vw.clipcount, vcp);		vfree(vcp);		/* if we were on, restart the video engine */		if (on)			zoran_cap(ztv, 1);		break;	 }	 case VIDIOCCAPTURE:	 {		int v;		if (get_user(v, (int *)arg))			return -EFAULT;		DEBUG(printk(CARD_DEBUG "VIDIOCCAPTURE(%d)\n",CARD,v));		if (v==0) {			clear_bit(STATE_OVERLAY, &ztv->state);			zoran_cap(ztv, 1);		}		else {			/* is VIDIOCSFBUF, VIDIOCSWIN done? */			if (ztv->overinfo.busadr==0 || ztv->overinfo.w==0 || ztv->overinfo.h==0)				return -EINVAL;			set_bit(STATE_OVERLAY, &ztv->state);			zoran_cap(ztv, 1);		}		break;	 }	 case VIDIOCGFBUF:	 {		struct video_buffer v;		DEBUG(printk(CARD_DEBUG "VIDIOCGFBUF\n",CARD));		read_lock(&ztv->lock);		v.base   = (void *)ztv->overinfo.busadr;		v.height = ztv->sheight;		v.width  = ztv->swidth;		v.depth  = ztv->depth;		v.bytesperline = ztv->overinfo.bpl;		read_unlock(&ztv->lock);		if(copy_to_user(arg, &v,sizeof(v)))			return -EFAULT;		break;	 }	 case VIDIOCSFBUF:	 {		struct video_buffer v;#if LINUX_VERSION_CODE >= 0x020100			if(!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_ADMIN))#else			if(!suser())#endif			return -EPERM;		if (copy_from_user(&v, arg,sizeof(v)))			return -EFAULT;		DEBUG(printk(CARD_DEBUG "VIDIOCSFBUF(%p,%d,%d,%d,%d)\n",CARD,v.base, v.width,v.height,v.depth,v.bytesperline));		if (v.depth!=15 && v.depth!=16 && v.depth!=24 && v.depth!=32)			return -EINVAL;		if (v.bytesperline<1)			return -EINVAL;		if (ztv->running)			return -EBUSY;		write_lock_irq(&ztv->lock);		ztv->overinfo.busadr  = (ulong)v.base;		ztv->sheight      = v.height;		ztv->swidth       = v.width;		ztv->depth        = v.depth;		/* bits per pixel */		ztv->overinfo.bpp = ((v.depth+1)&0x38)/8;/* bytes per pixel */		ztv->overinfo.bpl = v.bytesperline;	/* bytes per line */		write_unlock_irq(&ztv->lock);		break;	 }	 case VIDIOCKEY:	 {		/* Will be handled higher up .. */		break;	 }	 case VIDIOCSYNC:	 {		int i;		if (get_user(i, (int *) arg))			return -EFAULT;		DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d)\n",CARD,i));		if (i<0 || i>ZORAN_MAX_FBUFFERS)			return -EINVAL;		switch (ztv->grabinfo[i].status) {		 case FBUFFER_FREE:			return -EINVAL;		 case FBUFFER_BUSY:			/* wait till this buffer gets grabbed */			while (ztv->grabinfo[i].status == FBUFFER_BUSY) {				interruptible_sleep_on(&ztv->grabq);				/* see if a signal did it */				if (signal_pending(current))					return -EINTR;			}			/* don't fall through; a DONE buffer is not UNUSED */			break;		 case FBUFFER_DONE:			ztv->grabinfo[i].status = FBUFFER_FREE;			/* tell ppl we have a spare buffer */			wake_up_interruptible(&ztv->grabq);			break;		}		DEBUG(printk(CARD_DEBUG "VIDEOCSYNC(%d) returns\n",CARD,i));		break;	 }	 case VIDIOCMCAPTURE:	 {		struct video_mmap vm;		struct vidinfo* frame;		if (copy_from_user(&vm,arg,sizeof(vm)))			return -EFAULT;		DEBUG(printk(CARD_DEBUG "VIDIOCMCAPTURE(%d,(%d,%d),%d)\n",CARD,vm.frame,vm.width,vm.height,vm.format));		if (vm.frame<0 || vm.frame>ZORAN_MAX_FBUFFERS ||		    vm.width<32 || vm.width>768 ||		    vm.height<32 || vm.height>576 ||		    vm.format>NRPALETTES ||		    palette2fmt[vm.format].mode == 0)			return -EINVAL;		/* we are allowed to take over UNUSED and DONE buffers */		frame = &ztv->grabinfo[vm.frame];		if (frame->status == FBUFFER_BUSY)			return -EBUSY;		/* setup the other parameters if they are given */		write_lock_irq(&ztv->lock);		frame->w = vm.width;		frame->h = vm.height;		frame->format = vm.format;		frame->bpp = palette2fmt[frame->format].bpp;		frame->bpl = frame->w*frame->bpp;		frame->status = FBUFFER_BUSY;		frame->next = 0;		{ /* add to tail of queue */		  struct vidinfo* oldframe = ztv->workqueue;		  if (!oldframe) ztv->workqueue = frame;		  else {		    while (oldframe->next) oldframe = oldframe->next;		    oldframe->next = frame;		  }		}		write_unlock_irq(&ztv->lock);		zoran_cap(ztv, 1);		break;	 }	 case VIDIOCGMBUF:	 {		struct video_mbuf mb;		int i;		DEBUG(printk(CARD_DEBUG "VIDIOCGMBUF\n",CARD));		mb.size = ZORAN_MAX_FBUFSIZE;		mb.frames = ZORAN_MAX_FBUFFERS;		for (i=0; i<ZORAN_MAX_FBUFFERS; i++)			mb.offsets[i] = i*ZORAN_MAX_FBUFFER;		if(copy_to_user(arg, &mb,sizeof(mb)))			return -EFAULT;		break;	 }	 case VIDIOCGUNIT:	 {		struct video_unit vu;		DEBUG(printk(CARD_DEBUG "VIDIOCGUNIT\n",CARD));		vu.video = ztv->video_dev.minor;		vu.vbi = ztv->vbi_dev.minor;		vu.radio = VIDEO_NO_UNIT;		vu.audio = VIDEO_NO_UNIT;		vu.teletext = VIDEO_NO_UNIT;		if(copy_to_user(arg, &vu,sizeof(vu)))			return -EFAULT;		break;	 }	 case VIDIOCGFREQ:	 {		unsigned long v = ztv->tuner_freq;		if (copy_to_user(arg,&v,sizeof(v)))			return -EFAULT;		DEBUG(printk(CARD_DEBUG "VIDIOCGFREQ\n",CARD));		break;	 }	 case VIDIOCSFREQ:	 {		unsigned long v;		if (copy_from_user(&v, arg, sizeof(v)))			return -EFAULT;		DEBUG(printk(CARD_DEBUG "VIDIOCSFREQ\n",CARD));		if (ztv->have_tuner) {			int fixme = v;			if (i2c_control_device(&(ztv->i2c), I2C_DRIVERID_TUNER, TUNER_SET_TVFREQ, &fixme) < 0)				return -EAGAIN;		}		ztv->tuner_freq = v;		break;	 }	 /* Why isn't this in the API?	  * And why doesn't it take a buffer number?	 case BTTV_FIELDNR: 	 {		unsigned long v = ztv->lastfieldnr;		if (copy_to_user(arg,&v,sizeof(v)))			return -EFAULT;		DEBUG(printk(CARD_DEBUG "BTTV_FIELDNR\n",CARD));		break;	 }	 */	 default:		return -ENOIOCTLCMD;	}	return 0;}staticint zoran_mmap(struct video_device* dev, const char* adr, unsigned long size){	struct zoran* ztv = (struct zoran*)dev;	unsigned long start = (unsigned long)adr;	unsigned long pos;	DEBUG(printk(CARD_DEBUG "zoran_mmap(0x%p,%ld)\n",CARD,adr,size));	/* sanity checks */	if (size > ZORAN_MAX_FBUFSIZE || !ztv->fbuffer)		return -EINVAL;	/* start mapping the whole shabang to user memory */	pos = (unsigned long)ztv->fbuffer;	while (size>0) {		unsigned long page = virt_to_phys((void*)pos);		if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))			return -EAGAIN;		start += PAGE_SIZE;		pos += PAGE_SIZE;		size -= PAGE_SIZE;	}	return 0;}static struct video_device zr36120_template={	owner:		THIS_MODULE,	name:		"UNSET",	type:		VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY,	hardware:	VID_HARDWARE_ZR36120,	open:		zoran_open,	close:		zoran_close,	read:		zoran_read,	write:		zoran_write,	poll:		zoran_poll,	ioctl:		zoran_ioctl,	mmap:		zoran_mmap,	minor:		-1,};staticint vbi_open(struct video_device *dev, int flags){	struct zoran *ztv = (struct zoran*)dev->priv;	struct vidinfo* item;	DEBUG(printk(CARD_DEBUG "vbi_open(dev,%d)\n",CARD,flags));	/*	 * During VBI device open, we continiously grab VBI-like	 * data in the vbi buffer when we have nothing to do.	 * Only when there is an explicit request for VBI data	 * (read call) we /force/ a read.	 */	/* allocate buffers */	for (item=ztv->readinfo; item!=ztv->readinfo+ZORAN_VBI_BUFFERS; item++)	{		item->status = FBUFFER_FREE;		/* alloc */		if (!item->memadr) {			item->memadr = bmalloc(ZORAN_VBI_BUFSIZE);			if (!item->memadr) {				/* could not get a buffer, bail out */				while (item != ztv->readinfo) {					item--;					bfree(item->memadr, ZORAN_VBI_BUFSIZE);					item->memadr = 0;					item->busadr = 0;				}				return -ENOBUFS;			}		}		/* determine the DMAable address */		item->busadr = virt_to_bus(item->memadr);	}	/* do the common part of all open's */	zoran_common_open(ztv, flags);	set_bit(STATE_VBI, &ztv->state);	/* start read-ahead */	zoran_cap(ztv, 1);	return 0;}staticvoid vbi_close(struct video_device *dev){	struct zoran *ztv = (struct zoran*)dev->priv;	struct vidinfo* item;	DEBUG(printk(CARD_DEBUG "vbi_close(dev)\n",CARD));	/* driver specific closure */

⌨️ 快捷键说明

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