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

📄 zr36120.c

📁 pxa270下的摄像头mtd91111的驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
{	u16 Wt, Wa, Ht, Ha, HStart, VStart;};static struct tvnorm tvnorms[] = {	/* PAL-BDGHI *//*	{ 864, 720, 625, 576, 131, 21 },*//*00*/	{ 864, 768, 625, 576, 81, 17 },	/* NTSC *//*01*/	{ 858, 720, 525, 480, 121, 10 },	/* SECAM *//*02*/	{ 864, 720, 625, 576, 131, 21 },	/* BW50 *//*03*/	{ 864, 720, 625, 576, 131, 21 },	/* BW60 *//*04*/	{ 858, 720, 525, 480, 121, 10 }};#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm))/* * Program the chip for a setup as described in the vidinfo struct. * * Side-effects: calculates vidXshift, vidInterlace, * vidHeight, vidWidth which are used in a later stage * to calculate the overlay mask * * This is an internal function, as such it does not check the * validity of the struct members... Spectaculair crashes will * follow /very/ quick when you're wrong and the chip right :) */staticvoid zoran_set_geo(struct zoran* ztv, struct vidinfo* i){	ulong	top, bot;	int	stride;	int	winWidth, winHeight;	int	maxWidth, maxHeight, maxXOffset, maxYOffset;	long	vfec;DEBUG(printk(CARD_DEBUG "set_geo(rect=(%d,%d,%d,%d), norm=%d, format=%d, bpp=%d, bpl=%d, busadr=%lx, overlay=%p)\n",CARD,i->x,i->y,i->w,i->h,ztv->norm,i->format,i->bpp,i->bpl,i->busadr,i->overlay));	/*	 * make sure the DMA transfers are inhibited during our	 * reprogramming of the chip	 */	zrand(~ZORAN_VDC_VIDEN,ZORAN_VDC);	maxWidth = tvnorms[ztv->norm].Wa;	maxHeight = tvnorms[ztv->norm].Ha/2;	maxXOffset = tvnorms[ztv->norm].HStart;	maxYOffset = tvnorms[ztv->norm].VStart;	/* setup vfec register (keep ExtFl,TopField and VCLKPol settings) */	vfec = (zrread(ZORAN_VFEC) & (ZORAN_VFEC_EXTFL|ZORAN_VFEC_TOPFIELD|ZORAN_VFEC_VCLKPOL)) |	       (palette2fmt[i->format].mode & (ZORAN_VFEC_RGB|ZORAN_VFEC_ERRDIF|ZORAN_VFEC_LE|ZORAN_VFEC_PACK24));	/*	 * Set top, bottom ptrs. Since these must be DWORD aligned,	 * possible adjust the x and the width of the window.	 * so the endposition stay the same. The vidXshift will make	 * sure we are not writing pixels before the requested x.	 */	ztv->vidXshift = 0;	winWidth = i->w;	if (winWidth < 0)		winWidth = -winWidth;	top = i->busadr + i->x*i->bpp + i->y*i->bpl;	if (top & 3) {		ztv->vidXshift = (top & 3) / i->bpp;		winWidth += ztv->vidXshift;		DEBUG(printk(KERN_DEBUG "       window-x shifted %d pixels left\n",ztv->vidXshift));		top &= ~3;	}	/*	 * bottom points to next frame but in interleaved mode we want	 * to 'mix' the 2 frames to one capture, so 'bot' points to one	 * (physical) line below the top line.	 */	bot = top + i->bpl;	zrwrite(top,ZORAN_VTOP);	zrwrite(bot,ZORAN_VBOT);	/*	 * Make sure the winWidth is DWORD aligned too,	 * thereby automaticly making sure the stride to the	 * next line is DWORD aligned too (as required by spec).	 */	if ((winWidth*i->bpp) & 3) {DEBUG(printk(KERN_DEBUG "       window-width enlarged by %d pixels\n",(winWidth*i->bpp) & 3));		winWidth += (winWidth*i->bpp) & 3;	}	/* determine the DispMode and stride */	if (i->h >= 0 && i->h <= maxHeight) {		/* single frame grab suffices for this height. */		vfec |= ZORAN_VFEC_DISPMOD;		ztv->vidInterlace = 0;		stride = i->bpl - (winWidth*i->bpp);		winHeight = i->h;	}	else {		/* interleaving needed for this height */		ztv->vidInterlace = 1;		stride = i->bpl*2 - (winWidth*i->bpp);		winHeight = i->h/2;	}	if (winHeight < 0)	/* can happen for VBI! */		winHeight = -winHeight;	/* safety net, sometimes bpl is too short??? */	if (stride<0) {DEBUG(printk(CARD_DEBUG "WARNING stride = %d\n",CARD,stride));		stride = 0;	}	zraor((winHeight<<12)|(winWidth<<0),~(ZORAN_VDC_VIDWINHT|ZORAN_VDC_VIDWINWID), ZORAN_VDC);	zraor(stride<<16,~ZORAN_VSTR_DISPSTRIDE,ZORAN_VSTR);	/* remember vidWidth, vidHeight for overlay calculations */	ztv->vidWidth = winWidth;	ztv->vidHeight = winHeight;DEBUG(printk(KERN_DEBUG "       top=%08lx, bottom=%08lx\n",top,bot));DEBUG(printk(KERN_DEBUG "       winWidth=%d, winHeight=%d\n",winWidth,winHeight));DEBUG(printk(KERN_DEBUG "       maxWidth=%d, maxHeight=%d\n",maxWidth,maxHeight));DEBUG(printk(KERN_DEBUG "       stride=%d\n",stride));	/*	 * determine horizontal scales and crops	 */	if (i->w < 0) {		int Hstart = 1;		int Hend = Hstart + winWidth;DEBUG(printk(KERN_DEBUG "       Y: scale=0, start=%d, end=%d\n", Hstart, Hend));		zraor((Hstart<<10)|(Hend<<0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH);	}	else {		int Wa = maxWidth;		int X = (winWidth*64+Wa-1)/Wa;		int We = winWidth*64/X;		int HorDcm = 64-X;		int hcrop1 = 2*(Wa-We)/4;		/*		 * BUGFIX: Juha Nurmela <junki@qn-lpr2-165.quicknet.inet.fi> 		 * found the solution to the color phase shift.		 * See ChangeLog for the full explanation)		 */		int Hstart = (maxXOffset + hcrop1) | 1;		int Hend = Hstart + We - 1;DEBUG(printk(KERN_DEBUG "       X: scale=%d, start=%d, end=%d\n", HorDcm, Hstart, Hend));		zraor((Hstart<<10)|(Hend<<0),~(ZORAN_VFEH_HSTART|ZORAN_VFEH_HEND),ZORAN_VFEH);		vfec |= HorDcm<<14;		if (HorDcm<16)			vfec |= ZORAN_VFEC_HFILTER_1; /* no filter */		else if (HorDcm<32)			vfec |= ZORAN_VFEC_HFILTER_3; /* 3 tap filter */		else if (HorDcm<48)			vfec |= ZORAN_VFEC_HFILTER_4; /* 4 tap filter */		else	vfec |= ZORAN_VFEC_HFILTER_5; /* 5 tap filter */	}	/*	 * Determine vertical scales and crops	 *	 * when height is negative, we want to read starting at line 0	 * One day someone might need access to these lines...	 */	if (i->h < 0) {		int Vstart = 0;		int Vend = Vstart + winHeight;DEBUG(printk(KERN_DEBUG "       Y: scale=0, start=%d, end=%d\n", Vstart, Vend));		zraor((Vstart<<10)|(Vend<<0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV);	}	else {		int Ha = maxHeight;		int Y = (winHeight*64+Ha-1)/Ha;		int He = winHeight*64/Y;		int VerDcm = 64-Y;		int vcrop1 = 2*(Ha-He)/4;		int Vstart = maxYOffset + vcrop1;		int Vend = Vstart + He - 1;DEBUG(printk(KERN_DEBUG "       Y: scale=%d, start=%d, end=%d\n", VerDcm, Vstart, Vend));		zraor((Vstart<<10)|(Vend<<0),~(ZORAN_VFEV_VSTART|ZORAN_VFEV_VEND),ZORAN_VFEV);		vfec |= VerDcm<<8;	}DEBUG(printk(KERN_DEBUG "       F: format=%d(=%s)\n",i->format,palette2fmt[i->format].name));	/* setup the requested format */	zrwrite(vfec, ZORAN_VFEC);}staticvoid zoran_common_open(struct zoran* ztv, int flags){	UNUSED(flags);	/* already opened? */	if (ztv->users++ != 0)		return;	/* unmute audio */	/* /what/ audio? */	ztv->state = 0;	/* setup the encoder to the initial values */	ztv->picture.colour=254<<7;	ztv->picture.brightness=128<<8;	ztv->picture.hue=128<<8;	ztv->picture.contrast=216<<7;	i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_SET_PICTURE, &ztv->picture);	/* default to the composite input since my camera is there */	zoran_muxsel(ztv, 0, VIDEO_MODE_PAL);}staticvoid zoran_common_close(struct zoran* ztv){	if (--ztv->users != 0)		return;	/* mute audio */	/* /what/ audio? */	/* stop the chip */	zoran_cap(ztv, 0);}/* * Open a zoran card. Right now the flags are just a hack */static int zoran_open(struct video_device *dev, int flags){	struct zoran *ztv = (struct zoran*)dev;	struct vidinfo* item;	char* pos;	DEBUG(printk(CARD_DEBUG "open(dev,%d)\n",CARD,flags));	/*********************************************	 * We really should be doing lazy allocing...	 *********************************************/	/* allocate a frame buffer */	if (!ztv->fbuffer)		ztv->fbuffer = bmalloc(ZORAN_MAX_FBUFSIZE);	if (!ztv->fbuffer) {		/* could not get a buffer, bail out */		return -ENOBUFS;	}	/* at this time we _always_ have a framebuffer */	memset(ztv->fbuffer,0,ZORAN_MAX_FBUFSIZE);	if (!ztv->overinfo.overlay)		ztv->overinfo.overlay = (void*)kmalloc(1024*1024/8, GFP_KERNEL);	if (!ztv->overinfo.overlay) {		/* could not get an overlay buffer, bail out */		bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE);		return -ENOBUFS;	}	/* at this time we _always_ have a overlay */	/* clear buffer status, and give them a DMAable address */	pos = ztv->fbuffer;	for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++)	{		item->status = FBUFFER_FREE;		item->memadr = pos;		item->busadr = virt_to_bus(pos);		pos += ZORAN_MAX_FBUFFER;	}	/* do the common part of all open's */	zoran_common_open(ztv, flags);	return 0;}staticvoid zoran_close(struct video_device* dev){	struct zoran *ztv = (struct zoran*)dev;	DEBUG(printk(CARD_DEBUG "close(dev)\n",CARD));	/* driver specific closure */	clear_bit(STATE_OVERLAY, &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.         */        current->state = TASK_UNINTERRUPTIBLE;        schedule_timeout(HZ/10);        /* Wait 1/10th of a second */	/* free the allocated framebuffer */	if (ztv->fbuffer)		bfree( ztv->fbuffer, ZORAN_MAX_FBUFSIZE );	ztv->fbuffer = 0;	if (ztv->overinfo.overlay)		kfree( ztv->overinfo.overlay );	ztv->overinfo.overlay = 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 zoran_read(struct video_device* dev, char* buf, unsigned long count, int nonblock){	struct zoran *ztv = (struct zoran*)dev;	unsigned long max;	struct vidinfo* unused = 0;	struct vidinfo* done = 0;	DEBUG(printk(CARD_DEBUG "zoran_read(%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->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; 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->grabq);		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->w = 320;		unused->h = 240;		unused->format = VIDEO_PALETTE_RGB24;		unused->bpp = palette2fmt[unused->format].bpp;		unused->bpl = unused->w * unused->bpp;		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 */		while (unused->status == FBUFFER_BUSY) {			interruptible_sleep_on(&ztv->grabq);			/* 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;	if (copy_to_user((void*)buf, done->memadr, count))		count = -EFAULT;	/* keep the engine running */	done->status = FBUFFER_FREE;//	zoran_cap(ztv,1);	/* tell listeners this buffer became free */	wake_up_interruptible(&ztv->grabq);	/* goodbye */	DEBUG(printk(CARD_DEBUG "zoran_read() returns %lu\n",CARD,count));	return count;}staticlong zoran_write(struct video_device* dev, const char* buf, unsigned long count, int nonblock){	struct zoran *ztv = (struct zoran *)dev;	UNUSED(ztv); UNUSED(dev); UNUSED(buf); UNUSED(count); UNUSED(nonblock);	DEBUG(printk(CARD_DEBUG "zoran_write\n",CARD));	return -EINVAL;}#if LINUX_VERSION_CODE >= 0x020100staticunsigned int zoran_poll(struct video_device *dev, struct file *file, poll_table *wait){	struct zoran *ztv = (struct zoran *)dev;	struct vidinfo* item;	unsigned int mask = 0;	poll_wait(file, &ztv->grabq, wait);	for (item=ztv->grabinfo; item!=ztv->grabinfo+ZORAN_MAX_FBUFFERS; item++)		if (item->status == FBUFFER_DONE)		{			mask |= (POLLIN | POLLRDNORM);			break;		}	DEBUG(printk(CARD_DEBUG "zoran_poll()=%x\n",CARD,mask));	return mask;}#endif/* append a new clipregion to the vector of video_clips */staticvoid new_clip(struct video_window* vw, struct video_clip* vcp, int x, int y, int w, int h){	vcp[vw->clipcount].x = x;	vcp[vw->clipcount].y = y;	vcp[vw->clipcount].width = w;	vcp[vw->clipcount].height = h;	vw->clipcount++;}staticint zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg){	struct zoran* ztv = (struct zoran*)dev;	switch (cmd) {	 case VIDIOCGCAP:	 {		struct video_capability c;		DEBUG(printk(CARD_DEBUG "VIDIOCGCAP\n",CARD));		strcpy(c.name,ztv->video_dev.name);		c.type = VID_TYPE_CAPTURE|			 VID_TYPE_OVERLAY|			 VID_TYPE_CLIPPING|			 VID_TYPE_FRAMERAM|			 VID_TYPE_SCALES;		if (ztv->have_tuner)			c.type |= VID_TYPE_TUNER;		if (ztv->have_decoder) {			c.channels = ztv->card->video_inputs;			c.audios = ztv->card->audio_inputs;		} else			/* no decoder -> no channels */			c.channels = c.audios = 0;		c.maxwidth = 768;		c.maxheight = 576;		c.minwidth = 32;		c.minheight = 32;		if (copy_to_user(arg,&c,sizeof(c)))			return -EFAULT;		break;	 }	 case VIDIOCGCHAN:	 {		struct video_channel v;		int mux;		if (copy_from_user(&v, arg,sizeof(v)))			return -EFAULT;		DEBUG(printk(CARD_DEBUG "VIDIOCGCHAN(%d)\n",CARD,v.channel));		v.flags=VIDEO_VC_AUDIO#ifdef VIDEO_VC_NORM			|VIDEO_VC_NORM#endif			;		v.tuners=0;		v.type=VIDEO_TYPE_CAMERA;#ifdef I_EXPECT_POSSIBLE_NORMS_IN_THE_API		v.norm=VIDEO_MODE_PAL|		       VIDEO_MODE_NTSC|		       VIDEO_MODE_SECAM;#else		v.norm=VIDEO_MODE_PAL;#endif		/* too many inputs? no decoder -> no channels */		if (!ztv->have_decoder || v.channel < 0 ||  v.channel >= ztv->card->video_inputs)			return -EINVAL;		/* now determine the name of the channel */		mux = ztv->card->video_mux[v.channel];		if (mux & IS_TUNER) {			/* lets assume only one tuner, yes? */			strcpy(v.name,"Television");			v.type = VIDEO_TYPE_TV;			if (ztv->have_tuner) {

⌨️ 快捷键说明

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