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

📄 bttv-driver.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
 *	PS: The manual is free for download in .pdf format from  *	www.brooktree.com - nicely done those folks. */ static inline void bt848_set_eogeo(struct bttv *btv, struct tvnorm *tvn,				   int odd, int width, int height){        u16 vscale, hscale;	u32 xsf, sr;	u16 hdelay;	u8 crop, vtc;	int inter = (height>tvn->sheight/2) ? 0 : 1;        int off = odd ? 0x80 : 0x00;	xsf = (width*tvn->scaledtwidth)/tvn->swidth;	hscale = ((tvn->totalwidth*4096UL)/xsf-4096);	hdelay =  tvn->hdelayx1;	hdelay =  (hdelay*width)/tvn->swidth;	hdelay &= 0x3fe;	sr=((tvn->sheight>>inter)*512)/height-512;	vscale=(0x10000UL-sr)&0x1fff;	crop=((width>>8)&0x03)|((hdelay>>6)&0x0c)|		((tvn->sheight>>4)&0x30)|((tvn->vdelay>>2)&0xc0);	vscale |= inter ? (BT848_VSCALE_INT<<8) : 0;	if (combfilter) {		/* Some people say interpolation looks bad ... */		vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);		if (width < 769)			btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);		else			btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);	} else {		vtc = 0;		btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);	}	btwrite(vtc, BT848_E_VTC+off);	btwrite(hscale>>8, BT848_E_HSCALE_HI+off);	btwrite(hscale&0xff, BT848_E_HSCALE_LO+off);	btaor((vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);	btwrite(vscale&0xff, BT848_E_VSCALE_LO+off);	btwrite(width&0xff, BT848_E_HACTIVE_LO+off);	btwrite(hdelay&0xff, BT848_E_HDELAY_LO+off);	btwrite(tvn->sheight&0xff, BT848_E_VACTIVE_LO+off);	btwrite(tvn->vdelay&0xff, BT848_E_VDELAY_LO+off);	btwrite(crop, BT848_E_CROP+off);}static void bt848_set_geo(struct bttv *btv,			  int no_irq_context){	u16 ewidth, eheight, owidth, oheight;	u16 format, bswap;	struct tvnorm *tvn;	tvn=&tvnorms[btv->win.norm];		btwrite(tvn->adelay, BT848_ADELAY);	btwrite(tvn->bdelay, BT848_BDELAY);	btaor(tvn->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), BT848_IFORM);	btwrite(tvn->vbipack, BT848_VBI_PACK_SIZE);	btwrite(1, BT848_VBI_PACK_DEL);        btv->pll.pll_ofreq = tvn->Fsc;	if (no_irq_context)		set_pll(btv);	btv->win.interlace = (btv->win.height>tvn->sheight/2) ? 1 : 0;	if (0 == btv->risc_cap_odd &&	    0 == btv->risc_cap_even) {		/* overlay only */		owidth  = btv->win.width;		oheight = btv->win.height;		ewidth  = btv->win.width;		eheight = btv->win.height;		format  = btv->win.color_fmt;		bswap   = btv->fb_color_ctl;	} else if (-1 != btv->gq_grab      &&		   0  == btv->risc_cap_odd &&		   !btv->win.interlace     &&		   btv->scr_on) {		/* odd field -> overlay, even field -> capture */		owidth  = btv->win.width;		oheight = btv->win.height;		ewidth  = btv->gbuf[btv->gq_grab].width;		eheight = btv->gbuf[btv->gq_grab].height;		format  = (btv->win.color_fmt & 0xf0) |			(btv->gbuf[btv->gq_grab].fmt & 0x0f);		bswap   = btv->fb_color_ctl & 0x0a;	} else {		/* capture only */		owidth  = btv->gbuf[btv->gq_grab].width;		oheight = btv->gbuf[btv->gq_grab].height;		ewidth  = btv->gbuf[btv->gq_grab].width;		eheight = btv->gbuf[btv->gq_grab].height;		format  = btv->gbuf[btv->gq_grab].fmt;		bswap   = 0;	}	/* program odd + even fields */	bt848_set_eogeo(btv, tvn, 1, owidth, oheight);	bt848_set_eogeo(btv, tvn, 0, ewidth, eheight);	btwrite(format, BT848_COLOR_FMT);	btwrite(bswap | BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);}static int bpp2fmt[4] = {        BT848_COLOR_FMT_RGB8, BT848_COLOR_FMT_RGB16,        BT848_COLOR_FMT_RGB24, BT848_COLOR_FMT_RGB32 };static void bt848_set_winsize(struct bttv *btv){        unsigned short format;	if (btv->picture.palette > 0 && btv->picture.palette <= VIDEO_PALETTE_YUV422) {		/* format set by VIDIOCSPICT */		format = palette2fmt[btv->picture.palette];	} else {		/* use default for the given color depth */		format = (btv->win.depth==15) ? BT848_COLOR_FMT_RGB15 :			bpp2fmt[(btv->win.bpp-1)&3];	}	btv->win.color_fmt = format;	if (bigendian &&	    format == BT848_COLOR_FMT_RGB32) {		btv->fb_color_ctl =			BT848_COLOR_CTL_WSWAP_ODD	|			BT848_COLOR_CTL_WSWAP_EVEN	|			BT848_COLOR_CTL_BSWAP_ODD	|			BT848_COLOR_CTL_BSWAP_EVEN;        } else if (bigendian &&		   (format == BT848_COLOR_FMT_RGB16 ||                    format == BT848_COLOR_FMT_RGB15)) {		btv->fb_color_ctl =			BT848_COLOR_CTL_BSWAP_ODD	|			BT848_COLOR_CTL_BSWAP_EVEN;        } else {		btv->fb_color_ctl = 0;	}	/*	RGB8 seems to be a 9x5x5 GRB color cube starting at	 *	color 16. Why the h... can't they even mention this in the	 *	data sheet?  [AC - because it's a standard format so I guess	 *	it never occurred to them]	 *	Enable dithering in this mode.	 */	if (format==BT848_COLOR_FMT_RGB8)                btand(~BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL); 	else	        btor(BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL);        bt848_set_geo(btv,1);}/* *	Grab into virtual memory. */static int vgrab(struct bttv *btv, struct video_mmap *mp){	unsigned int *ro, *re;	unsigned int *vbuf;	unsigned long flags;		if(btv->fbuffer==NULL)	{		if(fbuffer_alloc(btv))			return -ENOBUFS;	}	if(mp->frame >= gbuffers || mp->frame < 0)		return -EINVAL;	if(btv->gbuf[mp->frame].stat != GBUFFER_UNUSED)		return -EBUSY;			if(mp->height < 32 || mp->width < 48)		return -EINVAL;	if (mp->format >= PALETTEFMT_MAX)		return -EINVAL;	if (mp->height*mp->width*fmtbppx2[palette2fmt[mp->format]&0x0f]/2	    > gbufsize)		return -EINVAL;	if(-1 == palette2fmt[mp->format])		return -EINVAL;	/*	 *	Ok load up the BT848	 */	 	vbuf=(unsigned int *)(btv->fbuffer+gbufsize*mp->frame);	ro=btv->gbuf[mp->frame].risc;	re=ro+2048;        make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, mp->format);	if (bttv_debug)		printk("bttv%d: cap vgrab: queue %d (%d:%dx%d)\n",		       btv->nr,mp->frame,mp->format,mp->width,mp->height);       	spin_lock_irqsave(&btv->s_lock, flags);         btv->gbuf[mp->frame].stat    = GBUFFER_GRABBING;	btv->gbuf[mp->frame].fmt     = palette2fmt[mp->format];	btv->gbuf[mp->frame].width   = mp->width;	btv->gbuf[mp->frame].height  = mp->height;	btv->gbuf[mp->frame].ro      = virt_to_bus(ro);	btv->gbuf[mp->frame].re      = virt_to_bus(re);#if 1	if (mp->height <= tvnorms[btv->win.norm].sheight/2 &&	    mp->format != VIDEO_PALETTE_RAW)		btv->gbuf[mp->frame].ro = 0;#endif	if (-1 == btv->gq_grab && btv->gq_in == btv->gq_out) {		btv->gq_start = 1;		btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ);        }	btv->gqueue[btv->gq_in++] = mp->frame;	btv->gq_in = btv->gq_in % MAX_GBUFFERS;	btor(3, BT848_CAP_CTL);	btor(3, BT848_GPIO_DMA_CTL);	spin_unlock_irqrestore(&btv->s_lock, flags);	return 0;}static long bttv_write(struct video_device *v, const char *buf, unsigned long count, int nonblock){	return -EINVAL;}static long bttv_read(struct video_device *v, char *buf, unsigned long count, int nonblock){	struct bttv *btv= (struct bttv *)v;	int q,todo;	DECLARE_WAITQUEUE(wait, current);	/* BROKEN: RETURNS VBI WHEN IT SHOULD RETURN GRABBED VIDEO FRAME */	todo=count;	while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) 	{		if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, q))			return -EFAULT;		todo-=q;		buf+=q;		add_wait_queue(&btv->vbiq, &wait);		current->state = TASK_INTERRUPTIBLE;		if (todo && q==VBIBUF_SIZE-btv->vbip) 		{			if(nonblock)			{				remove_wait_queue(&btv->vbiq, &wait);                                current->state = TASK_RUNNING;				if(count==todo)					return -EWOULDBLOCK;				return count-todo;			}			schedule();				if(signal_pending(current))			{				remove_wait_queue(&btv->vbiq, &wait);                                current->state = TASK_RUNNING;				if(todo==count)					return -EINTR;				else					return count-todo;			}		}		remove_wait_queue(&btv->vbiq, &wait);                current->state = TASK_RUNNING;	}	if (todo) 	{		if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, todo))			return -EFAULT;		btv->vbip+=todo;	}	return count;}static inline void burst(int on){	tvnorms[0].scaledtwidth = 1135 - (on?BURSTOFFSET-2:0);	tvnorms[0].hdelayx1     = 186  - (on?BURSTOFFSET  :0);	tvnorms[2].scaledtwidth = 1135 - (on?BURSTOFFSET-2:0);	tvnorms[2].hdelayx1     = 186  - (on?BURSTOFFSET  :0);}/* * called from irq handler on fatal errors.  Takes the grabber chip * offline, flag it needs a reinitialization (which can't be done * from irq context) and wake up all sleeping proccesses.  They would * block forever else.  We also need someone who actually does the * reinitialization from process context... */static void bt848_offline(struct bttv *btv){	int i;	spin_lock(&btv->s_lock);	/* cancel all outstanding grab requests */	btv->gq_in = 0;	btv->gq_out = 0;	btv->gq_grab = -1;	for (i = 0; i < gbuffers; i++)		if (btv->gbuf[i].stat == GBUFFER_GRABBING)			btv->gbuf[i].stat = GBUFFER_ERROR;	/* disable screen overlay and DMA */	btv->risc_cap_odd  = 0;	btv->risc_cap_even = 0;	bt848_set_risc_jmps(btv,0);	/* flag the chip needs a restart */	btv->needs_restart = 1;	spin_unlock(&btv->s_lock);	wake_up_interruptible(&btv->vbiq);	wake_up_interruptible(&btv->capq);}static void bt848_restart(struct bttv *btv){ 	unsigned long irq_flags;	if (bttv_verbose)		printk("bttv%d: resetting chip\n",btv->nr);	btwrite(0xfffffUL, BT848_INT_STAT);	btand(~15, BT848_GPIO_DMA_CTL);	btwrite(0, BT848_SRESET);	btwrite(virt_to_bus(btv->risc_jmp+2),		BT848_RISC_STRT_ADD);	/* enforce pll reprogramming */	btv->pll.pll_current = 0;	set_pll(btv);	spin_lock_irqsave(&btv->s_lock, irq_flags);	btv->errors = 0;	btv->needs_restart = 0;	bt848_set_geo(btv,0);	bt848_set_risc_jmps(btv,-1);	spin_unlock_irqrestore(&btv->s_lock, irq_flags);}/* *	Open a bttv card. Right now the flags stuff is just playing */static int bttv_open(struct video_device *dev, int flags){	struct bttv *btv = (struct bttv *)dev;        int i,ret;	ret = -EBUSY;	if (bttv_debug)		printk("bttv%d: open called\n",btv->nr);	down(&btv->lock);	if (btv->user)		goto out_unlock;		btv->fbuffer=(unsigned char *) rvmalloc(gbuffers*gbufsize);	ret = -ENOMEM;	if (!btv->fbuffer)		goto out_unlock;        btv->gq_in = 0;        btv->gq_out = 0;	btv->gq_grab = -1;        for (i = 0; i < gbuffers; i++)                btv->gbuf[i].stat = GBUFFER_UNUSED;	if (btv->needs_restart)		bt848_restart(btv);        burst(0);	set_pll(btv);        btv->user++;	up(&btv->lock);        return 0; out_unlock:	up(&btv->lock);	return ret;}static void bttv_close(struct video_device *dev){	struct bttv *btv=(struct bttv *)dev; 	unsigned long irq_flags;	int need_wait;	down(&btv->lock);	btv->user--;	spin_lock_irqsave(&btv->s_lock, irq_flags);	need_wait = (-1 != btv->gq_grab);	btv->gq_start = 0;	btv->gq_in = 0;	btv->gq_out = 0;	btv->gq_grab = -1;	btv->scr_on = 0;	btv->risc_cap_odd = 0;	btv->risc_cap_even = 0;	bt848_set_risc_jmps(btv,-1);	spin_unlock_irqrestore(&btv->s_lock, irq_flags);	/*	 *	A word of warning. At this point the chip	 *	is still capturing because its FIFO hasn't emptied	 *	and the DMA control operations are posted PCI 	 *	operations.	 */	btread(BT848_I2C); 	/* This fixes the PCI posting delay */		if (need_wait) {		/*		 *	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 */	}		/*	 *	We have allowed it to drain.	 */	if(btv->fbuffer)		rvfree((void *) btv->fbuffer, gbuffers*gbufsize);	btv->fbuffer=0;	up(&btv->lock);}/***********************************//* ioctls and supporting functions *//***********************************/extern inline void bt848_bright(struct bttv *btv, uint bright){	btwrite(bright&0xff, BT848_BRIGHT);}extern inline void bt848_hue(struct bttv *btv, uint hue){	btwrite(hue&0xff, BT848_HUE);}extern inline void bt848_contrast(struct bttv *btv, uint cont){	unsigned int conthi;	conthi=(cont>>6)&4;	btwrite(cont&0xff, BT848_CONTRAST_LO);	btaor(conthi, ~4, BT848_E_CONTROL);	btaor(conthi, ~4, BT848_O_CONTROL);}extern inline void bt848_sat_u(struct bttv *btv, unsigned long data){	u32 datahi;	datahi=(data>>7)&2;	btwrite(data&0xff, BT848_SAT_U_LO);	btaor(datahi, ~2, BT848_E_CONTROL);	btaor(datahi, ~2, BT848_O_CONTROL);}static inline void bt848_sat_v(struct bttv *btv, unsigned long data){	u32 datahi;	datahi=(data>>8)&1;	btwrite(data&0xff, BT848_SAT_V_LO);	btaor(datahi, ~1, BT848_E_CONTROL);	btaor(datahi, ~1, BT848_O_CONTROL);}/* *	ioctl routine */ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg){	struct bttv *btv=(struct bttv *)dev; 	unsigned long irq_flags; 	int i,ret = 0;	if (bttv_debug > 1)		printk("bttv%d: ioctl 0x%x\n",btv->nr,cmd);	switch (cmd) {

⌨️ 快捷键说明

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