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

📄 bttv-driver.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		.adelay         = 0x68,		.bdelay         = 0x5d,		.iform          = (BT848_IFORM_NTSC|BT848_IFORM_XT0),		.scaledtwidth   = 910,		.hdelayx1       = 128,		.hactivex1      = 910,		.vdelay         = 0x1a,		.vbipack        = 144,		.sram           = 1,	},{		/* SECAM L */		.Fsc            = 35468950,		.swidth         = 924,		.sheight        = 576,		.totalwidth     = 1135,		.adelay         = 0x7f,		.bdelay         = 0xb0,		.iform          = (BT848_IFORM_SECAM|BT848_IFORM_XT1),		.scaledtwidth   = 1135,		.hdelayx1       = 186,		.hactivex1      = 922,		.vdelay         = 0x20,		.vbipack        = 255,		.sram           = 0, /* like PAL, correct? */	},{		/* PAL-NC */		.Fsc            = 28636363,		.swidth         = 640,		.sheight        = 576,		.totalwidth     = 910,		.adelay         = 0x68,		.bdelay         = 0x5d,		.iform          = (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),		.scaledtwidth   = 780,		.hdelayx1       = 130,		.hactivex1      = 734,		.vdelay         = 0x1a,		.vbipack        = 144,		.sram           = -1,	},{		/* PAL-M */		.Fsc            = 28636363,		.swidth         = 640,		.sheight        = 480,		.totalwidth     = 910,		.adelay         = 0x68,		.bdelay         = 0x5d,		.iform          = (BT848_IFORM_PAL_M|BT848_IFORM_XT0),		.scaledtwidth   = 780,		.hdelayx1       = 135,		.hactivex1      = 754,		.vdelay         = 0x1a,		.vbipack        = 144,		.sram           = -1,	},{		/* PAL-N */		.Fsc             35468950,		.swidth         = 768,		.sheight        = 576,		.totalwidth     = 1135,		.adelay         = 0x7f,		.bdelay         = 0x72,		.iform          = (BT848_IFORM_PAL_N|BT848_IFORM_XT1),		.scaledtwidth   = 944,		.hdelayx1       = 186,		.hactivex1      = 922,		.vdelay         = 0x20,		.vbipack        = 144,		.sram           = -1,	},{		/* NTSC-Japan */		.Fsc            = 28636363,		.swidth         = 640,		.sheight        = 480,		.totalwidth     = 910,		.adelay         = 0x68,		.bdelay         = 0x5d,		.iform          = (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),		.scaledtwidth   = 780,		.hdelayx1       = 135,		.hactivex1      = 754,		.vdelay         = 0x16,		.vbipack        = 144,		.sram           = -1,	},{		/* Quartzsight digital camera 		 * From Bt832 datasheet: 393x304 pixel @30Hz,		 * Visible: 352x288 pixel		 */                .Fsc            = 27000000,                .swidth         = 352,                .sheight        = 576, //2*288 ?                .totalwidth     = 392,                .adelay         = 0x68,                .bdelay         = 0x5d,                .iform          = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),                .scaledtwidth   = 392,                .hdelayx1       = 0x20,                .hactivex1      = 352,                .vdelay         = 0x08,                .vbipack        = 0, //255                .sram           = 2,        }};#define TVNORMS (sizeof(tvnorms)/sizeof(struct tvnorm))/* used to switch between the bt848's analog/digital video capture modes */void bt848A_set_timing(struct bttv *btv){	int i, len;	int table_idx = tvnorms[btv->win.norm].sram;	int fsc       = tvnorms[btv->win.norm].Fsc;	if (bttv_tvcards[btv->type].muxsel[btv->channel] < 0) {		dprintk("bttv%d: load digital timing table (table_idx=%d)\n",			btv->nr,table_idx);		/* timing change...reset timing generator address */       		btwrite(0x00, BT848_TGCTRL);       		btwrite(0x02, BT848_TGCTRL);       		btwrite(0x00, BT848_TGCTRL);		len=SRAM_Table[table_idx][0];		for(i = 1; i <= len; i++)			btwrite(SRAM_Table[table_idx][i],BT848_TGLB);		btv->pll.pll_ofreq = 27000000;		set_pll(btv);		btwrite(0x11, BT848_TGCTRL);		btwrite(0x41, BT848_DVSIF);	} else {		btv->pll.pll_ofreq = fsc;		set_pll(btv);		btwrite(0x0, BT848_DVSIF);	}}static void bttv_set_norm(struct bttv *btv, int new_norm){	unsigned long irq_flags;	if (bttv_tvcards[btv->type].muxsel[btv->channel] < 0 &&	    bttv_tvcards[btv->type].digital_mode == DIGITAL_MODE_CAMERA) {		//override norm by quartzsight mode		new_norm=7;		dprintk("bttv%d: set_norm fix-up digital: %d\n",			btv->nr, new_norm);	}	       	if (btv->win.norm != new_norm) {		btv->win.norm = new_norm;				make_vbitab(btv);		spin_lock_irqsave(&btv->s_lock, irq_flags);		bt848_set_winsize(btv);		spin_unlock_irqrestore(&btv->s_lock, irq_flags);				bt848A_set_timing(btv);		switch (btv->type) {		case BTTV_VOODOOTV_FM:			bttv_tda9880_setnorm(btv,new_norm);			break;#if 0		case BTTV_OSPREY540:			osprey_540_set_norm(btv,new_norm);			break;#endif		}	}}#define VBI_SPL 2044/* RISC command to write one VBI data line */#define VBI_RISC BT848_RISC_WRITE|VBI_SPL|BT848_RISC_EOL|BT848_RISC_SOLstatic void make_vbitab(struct bttv *btv){	int i;	unsigned int *po=(unsigned int *) btv->vbi_odd;	unsigned int *pe=(unsigned int *) btv->vbi_even;  	if (bttv_debug > 1)		printk("bttv%d: vbi1: po=%08lx pe=%08lx\n",		       btv->nr,virt_to_bus(po), virt_to_bus(pe));        	*(po++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(po++)=0;	for (i=0; i<VBI_MAXLINES; i++) {		*(po++)=cpu_to_le32(VBI_RISC);		*(po++)=cpu_to_le32(kvirt_to_bus((unsigned long)btv->vbibuf+i*2048));	}	*(po++)=cpu_to_le32(BT848_RISC_JUMP);	*(po++)=cpu_to_le32(virt_to_bus(btv->risc_jmp+4));	*(pe++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(pe++)=0;	for (i=VBI_MAXLINES; i<VBI_MAXLINES*2; i++) {		*(pe++)=cpu_to_le32(VBI_RISC);		*(pe++)=cpu_to_le32(kvirt_to_bus((unsigned long)btv->vbibuf+i*2048));	}	*(pe++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(0x01<<16));	*(pe++)=cpu_to_le32(virt_to_bus(btv->risc_jmp+10));	if (bttv_debug > 1)		printk("bttv%d: vbi2: po=%08lx pe=%08lx\n",		       btv->nr,virt_to_bus(po), virt_to_bus(pe));}static unsigned int fmtbppx2[16] = {        8, 6, 4, 4, 4, 3, 2, 2, 4, 3, 0, 0, 0, 0, 2, 0 };static unsigned int palette2fmt[] = {	UNSET,	BT848_COLOR_FMT_Y8,	BT848_COLOR_FMT_RGB8,	BT848_COLOR_FMT_RGB16,	BT848_COLOR_FMT_RGB24,	BT848_COLOR_FMT_RGB32,	BT848_COLOR_FMT_RGB15,	BT848_COLOR_FMT_YUY2,	BT848_COLOR_FMT_YUY2,	UNSET,	UNSET,	UNSET,	BT848_COLOR_FMT_RAW,	BT848_COLOR_FMT_YCrCb422,	BT848_COLOR_FMT_YCrCb411,	BT848_COLOR_FMT_YCrCb422,	BT848_COLOR_FMT_YCrCb411,};#define PALETTEFMT_MAX (sizeof(palette2fmt)/sizeof(palette2fmt[0]))static int make_rawrisctab(struct bttv *btv, u32 *ro, u32 *re, u32 *vbuf){	u32 line;	u32 bpl=1024;		/* bytes per line */	unsigned long vadr=(unsigned long) vbuf;	*(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);	        /* In PAL 650 blocks of 256 DWORDs are sampled, but only if VDELAY           is 2 and without separate VBI grabbing.           We'll have to handle this inside the IRQ handler ... */	for (line=0; line < 640; line++)	{                *(ro++)=cpu_to_le32(BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL);                *(ro++)=cpu_to_le32(kvirt_to_bus(vadr));                *(re++)=cpu_to_le32(BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL);                *(re++)=cpu_to_le32(kvirt_to_bus(vadr+gbufsize/2));                vadr+=bpl;	}		*(ro++)=cpu_to_le32(BT848_RISC_JUMP);	*(ro++)=cpu_to_le32(btv->bus_vbi_even);	*(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16));	*(re++)=cpu_to_le32(btv->bus_vbi_odd);		return 0;}static int  make_prisctab(struct bttv *btv, u32 *ro, u32 *re, u32 *vbuf,			  u16 width, u16 height, u16 fmt){	u16 line, lmask;	u32 bl, blcr, blcb, rcmd;	u32 todo;	u32 **rp;	int inter;	u32 cbadr, cradr;	unsigned long vadr=(unsigned long) vbuf;	u32 shift, csize;	if (bttv_debug > 1)		printk("bttv%d: prisc1: ro=%08lx re=%08lx\n",		       btv->nr,virt_to_bus(ro), virt_to_bus(re));	switch(fmt)	{        case VIDEO_PALETTE_YUV422P:                csize=(width*height)>>1;                shift=1;                lmask=0;                break;                        case VIDEO_PALETTE_YUV411P:                csize=(width*height)>>2;                shift=2;                lmask=0;                break;	 					 case VIDEO_PALETTE_YUV420P:                csize=(width*height)>>2;                shift=1;                lmask=1;                break;                	 case VIDEO_PALETTE_YUV410P:                csize=(width*height)>>4;                shift=2;                lmask=3;                break;                        default:                return -1;	}	cbadr=vadr+(width*height);	cradr=cbadr+csize;	inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0;		*(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);        *(ro++)=0;	*(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);        *(re++)=0;  	for (line=0; line < (height<<(1^inter)); line++)	{		if(line==height)		{			vadr+=csize<<1;			cbadr=vadr+(width*height);			cradr=cbadr+csize;		}	        if (inter) 		        rp= (line&1) ? &re : &ro;		else 	                rp= (line>=height) ? &ro : &re; 	                	        if(line&lmask)	        	rcmd=BT848_RISC_WRITE1S23|BT848_RISC_SOL;	        else	        	rcmd=BT848_RISC_WRITE123|BT848_RISC_SOL;	        todo=width;		while(todo)		{                 bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr);                 blcr=(PAGE_SIZE-((PAGE_SIZE-1)&cradr))<<shift;		 blcb=(PAGE_SIZE-((PAGE_SIZE-1)&cbadr))<<shift;		 bl=(blcr<bl) ? blcr : bl;		 bl=(blcb<bl) ? blcb : bl;		 bl=(bl>todo) ? todo : bl;		 blcr=bl>>shift;		 blcb=blcr;		 /* bl now containts the longest row that can be written */		 todo-=bl;		 if(!todo) rcmd|=BT848_RISC_EOL; /* if this is the last EOL */		 		 *((*rp)++)=cpu_to_le32(rcmd|bl);		 *((*rp)++)=cpu_to_le32(blcb|(blcr<<16));		 *((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr));		 vadr+=bl;		 if ((rcmd&(15<<28))==BT848_RISC_WRITE123)		 {		 	*((*rp)++)=cpu_to_le32(kvirt_to_bus(cbadr));		 	cbadr+=blcb;		 	*((*rp)++)=cpu_to_le32(kvirt_to_bus(cradr));		 	cradr+=blcr;		 }		 		 rcmd&=~BT848_RISC_SOL; /* only the first has SOL */		}	}		*(ro++)=cpu_to_le32(BT848_RISC_JUMP);	*(ro++)=cpu_to_le32(btv->bus_vbi_even);	*(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16));	*(re++)=cpu_to_le32(btv->bus_vbi_odd);		if (bttv_debug > 1)		printk("bttv%d: prisc2: ro=%08lx re=%08lx\n",		       btv->nr,virt_to_bus(ro), virt_to_bus(re));	return 0;}static int  make_vrisctab(struct bttv *btv, u32 *ro, u32 *re, u32 *vbuf,			  u16 width, u16 height, u16 palette){	u16 line;	u32 bpl;  /* bytes per line */	u32 bl;	u32 todo;	u32 **rp;	int inter;	unsigned long vadr=(unsigned long)vbuf;        if (palette==VIDEO_PALETTE_RAW)                 return make_rawrisctab(btv, ro, re, vbuf);        if (palette>=VIDEO_PALETTE_PLANAR)                return make_prisctab(btv, ro, re, vbuf, width, height, palette);	if (bttv_debug > 1)		printk("bttv%d: vrisc1: ro=%08lx re=%08lx\n",		       btv->nr,virt_to_bus(ro), virt_to_bus(re));		inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0;	bpl=width*fmtbppx2[palette2fmt[palette]&0xf]/2;		*(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);  	for (line=0; line < (height<<(1^inter)); line++)	{	        if (inter) 		        rp= (line&1) ? &re : &ro;		else 	                rp= (line>=height) ? &ro : &re; 		bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr);		if (bpl<=bl)                {		        *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|			        BT848_RISC_EOL|bpl); 			*((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr));			vadr+=bpl;		}		else		{		        todo=bpl;		        *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|bl);			*((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr));			vadr+=bl;			todo-=bl;			while (todo>PAGE_SIZE)			{			        *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|PAGE_SIZE);				*((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr));				vadr+=PAGE_SIZE;				todo-=PAGE_SIZE;			}			*((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|todo);			*((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr));			vadr+=todo;		}	}		*(ro++)=cpu_to_le32(BT848_RISC_JUMP);	*(ro++)=cpu_to_le32(btv->bus_vbi_even);	*(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16));	*(re++)=cpu_to_le32(btv->bus_vbi_odd);	if (bttv_debug > 1)		printk("bttv%d: vrisc2: ro=%08lx re=%08lx\n",		       btv->nr,virt_to_bus(ro), virt_to_bus(re));		return 0;}static unsigned char lmaskt[8] = { 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80};static unsigned char rmaskt[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};static void clip_draw_rectangle(unsigned char *clipmap, int x, int y, int w, int h){        unsigned char lmask, rmask, *p;        int W, l, r;	int i;	if (bttv_debug > 1)		printk("bttv clip: %dx%d+%d+%d\n",w,h,x,y);	/* bitmap is fixed width, 128 bytes (1024 pixels represented) */        if (x<0)        {                w+=x;                x=0;        }        if (y<0)        {                h+=y;                y=0;        }	if (w < 0 || h < 0)	/* catch bad clips */		return;	/* out of range data should just fall through */        if (y+h>=625)                h=625-y;        if (x+w>=1024)                w=1024-x;        l=x>>3;        r=(x+w-1)>>3;        W=r-l-1;        lmask=lmaskt[x&7];        rmask=rmaskt[(x+w-1)&7];        p=clipmap+128*y+l;                if (W>0)         {                for (i=0; i<h; i++, p+=128)                 {                        *p|=lmask;                        memset(p+1, 0xff, W);                        p[W+1]|=rmask;                }        } else if (!W) {                for (i=0; i<h; i++, p+=128)                 {                        p[0]|=lmask;                        p[1]|=rmask;                }

⌨️ 快捷键说明

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