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

📄 bttv-driver.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
        } else {                for (i=0; i<h; i++, p+=128)                         p[0]|=lmask&rmask;        }               }static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr){	u32 line, x, y, bpl, width, height, inter, maxw;	u32 bpp, dx, sx, **rp, *ro, *re, flags, len;	u32 adr;	int i;	unsigned char *clipmap, *clipline, cbit, lastbit, outofmem;	/* take care: bpp != btv->win.bpp is allowed here */	bpp = fmtbppx2[btv->win.color_fmt&0xf]/2;	bpl=btv->win.bpl;	adr=btv->win.vidadr + btv->win.x * btv->win.bpp + btv->win.y * bpl;	inter=(btv->win.interlace&1)^1;	width=btv->win.width;	height=btv->win.height;	if (bttv_debug > 1)		printk("bttv%d: clip1: pal=%d size=%dx%d, bpl=%d bpp=%d\n",		       btv->nr,btv->picture.palette,width,height,bpl,bpp);	if(width > 1023)		width = 1023;		/* sanity check */	if(height > 625)		height = 625;		/* sanity check */	ro=btv->risc_scr_odd;	re=btv->risc_scr_even;	if (bttv_debug)		printk("bttv%d: clip: ro=%08lx re=%08lx\n",		       btv->nr,virt_to_bus(ro), virt_to_bus(re));	if ((clipmap=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL) {		/* can't clip, don't generate any risc code */		*(ro++)=cpu_to_le32(BT848_RISC_JUMP);		*(ro++)=cpu_to_le32(btv->bus_vbi_even);		*(re++)=cpu_to_le32(BT848_RISC_JUMP);		*(re++)=cpu_to_le32(btv->bus_vbi_odd);	}	if (ncr < 0) {	/* bitmap was pased */		memcpy(clipmap, (unsigned char *)cr, VIDEO_CLIPMAP_SIZE);	} else {	/* convert rectangular clips to a bitmap */		memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */		for (i=0; i<ncr; i++)			clip_draw_rectangle(clipmap, cr[i].x, cr[i].y,				cr[i].width, cr[i].height);	}	/* clip against viewing window AND screen 	   so we do not have to rely on the user program	 */	maxw = (bpl - btv->win.x * btv->win.bpp) / bpp;	clip_draw_rectangle(clipmap, (width > maxw) ? maxw : width,			    0, 1024, 768);	clip_draw_rectangle(clipmap,0,(btv->win.y+height>btv->win.sheight) ?			    (btv->win.sheight-btv->win.y) : height,1024,768);	if (btv->win.x<0)		clip_draw_rectangle(clipmap, 0, 0, -(btv->win.x), 768);	if (btv->win.y<0)		clip_draw_rectangle(clipmap, 0, 0, 1024, -(btv->win.y));		*(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);        *(ro++)=cpu_to_le32(0);	*(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);        *(re++)=cpu_to_le32(0);		/* translate bitmap to risc code */        for (line=outofmem=0; line < (height<<inter) && !outofmem; line++)        {		y = line>>inter;		rp= (line&1) ? &re : &ro;		clipline = clipmap + (y<<7); /* running pointers ... */		lastbit = *clipline & 1;		for(x=dx=0,sx=0; x<=width && !outofmem;) {			if (0 == (x&7)) {				/* check bytes not bits if we can ... */				if (lastbit) {					while (0xff==*clipline && x<width-8) {						x  += 8;						dx += 8;						clipline++;					}				} else {					while (0x00==*clipline && x<width-8) {						x  += 8;						dx += 8;						clipline++;					}				}			}			cbit = *clipline & (1<<(x&7));			if (x < width && !lastbit == !cbit) {				dx++;			} else {				/* generate the dma controller code */				len = dx * bpp;				flags = ((bpp==4) ? BT848_RISC_BYTE3 : 0);				flags |= ((!sx) ? BT848_RISC_SOL : 0);				flags |= ((sx + dx == width) ? BT848_RISC_EOL : 0);				if (!lastbit) {					*((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|flags|len);					*((*rp)++)=cpu_to_le32(adr + bpp * sx);				} else {					*((*rp)++)=cpu_to_le32(BT848_RISC_SKIP|flags|len);				}				lastbit=cbit;				sx += dx;				dx = 1;				if (ro - btv->risc_scr_odd>(RISCMEM_LEN>>3) - 16)					outofmem++;				if (re - btv->risc_scr_even>(RISCMEM_LEN>>3) - 16)					outofmem++;			}			x++;			if (0 == (x&7))				clipline++;		}		if ((!inter)||(line&1))                        adr+=bpl;	}	vfree(clipmap);	/* outofmem flag relies on the following code to discard extra data */	*(ro++)=cpu_to_le32(BT848_RISC_JUMP);	*(ro++)=cpu_to_le32(btv->bus_vbi_even);	*(re++)=cpu_to_le32(BT848_RISC_JUMP);	*(re++)=cpu_to_le32(btv->bus_vbi_odd);	if (bttv_debug > 1)		printk("bttv%d: clip2: pal=%d size=%dx%d, bpl=%d bpp=%d\n",		       btv->nr,btv->picture.palette,width,height,bpl,bpp);}/* *	Set the registers for the size we have specified. Don't bother *	trying to understand this without the BT848 manual in front of *	you [AC].  * *	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;	int swidth       = tvn->swidth;	int totalwidth   = tvn->totalwidth;	int scaledtwidth = tvn->scaledtwidth;	if (bttv_tvcards[btv->type].muxsel[btv->channel] < 0) {		dprintk("bttv%d: DIGITAL_MODE_VIDEO override width\n",btv->nr);		swidth       = 720;		totalwidth   = 858;		scaledtwidth = 858;	}	xsf = (width*scaledtwidth)/swidth;	hscale = ((totalwidth*4096UL)/xsf-4096);	hdelay =  tvn->hdelayx1;	hdelay =  (hdelay*width)/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){	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);	if (bttv_tvcards[btv->type].muxsel[btv->channel] < 0)		btwrite(0x39, BT848_VBI_PACK_DEL);	else		btwrite(0x01, BT848_VBI_PACK_DEL);        btv->pll.pll_ofreq = tvn->Fsc;	if (!in_interrupt())		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);}/* *	Grab into virtual memory. */static int vgrab(struct bttv *btv, struct video_mmap *mp){	u32 *ro, *re;	u32 *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 ((unsigned int)mp->height * mp->width *	    fmtbppx2[palette2fmt[mp->format]&0x0f]/2 > gbufsize)		return -EINVAL;	if (UNSET == 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){	/* use bttv 0.9.x if you need capture via read() */	return -EINVAL;}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){	unsigned 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 = -1;	set_pll(btv);	spin_lock_irqsave(&btv->s_lock, irq_flags);	btv->errors = 0;	btv->needs_restart = 0;	bt848_set_geo(btv);	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;        unsigned int i;	int 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)

⌨️ 快捷键说明

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