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

📄 bttv.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
        u32 gpiomask;        u32 muxsel[8];        u32 audiomux[6]; /* Tuner, Radio, internal, external, mute, stereo */        u32 gpiomask2; /* GPIO MUX mask */};static struct tvcard tvcards[] = {        /* default */        { 3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}},        /* MIRO */        { 4, 1, 0, 2,15, { 2, 3, 1, 1}, { 2, 0, 0, 0,10}},        /* Hauppauge */        { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},	/* STB */        { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1}},	/* Intel??? */        { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},	/* Diamond DTV2000 */        { 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3}},	/* AVerMedia TVPhone */        { 3, 1, 0, 3,15, { 2, 3, 1, 1}, {12, 0,11,11, 0}},        /* Matrix Vision MV-Delta */        { 5, 1, -1, 3, 0, { 2, 3, 1, 0, 0}},        /* Fly Video II */        { 3, 1, 0, 2, 0xc00, { 2, 3, 1, 1},         {0, 0xc00, 0x800, 0x400, 0xc00, 0}},        /* TurboTV */        { 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0}},        /* Newer Hauppauge (bt878) */	{ 3, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4}},        /* MIRO PCTV pro */        { 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10}},	/* ADS Technologies Channel Surfer TV (and maybe TV+FM) */	{ 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0},        /* AVerMedia TVCapture 98 */	{ 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0},        /* Aimslab VHX */        { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},        /* Zoltrix TV-Max */        { 3, 1, 0, 2,15, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}},        /* Pixelview PlayTV (bt878) */        { 3, 4, 0, 2, 0x01e000, { 2, 0, 1, 1}, {0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 }},};#define TVCARDS (sizeof(tvcards)/sizeof(tvcard))static void audio(struct bttv *btv, int mode){	btaor(tvcards[btv->type].gpiomask, ~tvcards[btv->type].gpiomask,              BT848_GPIO_OUT_EN);	switch (mode)	{	        case AUDIO_MUTE:                        btv->audio|=AUDIO_MUTE;			break; 		case AUDIO_UNMUTE:			btv->audio&=~AUDIO_MUTE;			mode=btv->audio;			break;		case AUDIO_OFF:			mode=AUDIO_OFF;			break;		case AUDIO_ON:			mode=btv->audio;			break;		default:			btv->audio&=AUDIO_MUTE;			btv->audio|=mode;			break;	}        /* if audio mute or not in H-lock, turn audio off */	if ((btv->audio&AUDIO_MUTE)#if 0		 || 	    (!btv->radio && !(btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC))#endif	    		)	        mode=AUDIO_OFF;        if ((mode == 0) && (btv->radio))		mode = 1;	btaor(tvcards[btv->type].audiomux[mode],              ~tvcards[btv->type].gpiomask, BT848_GPIO_DATA);}extern inline void bt848_dma(struct bttv *btv, uint state){	if (state)		btor(3, BT848_GPIO_DMA_CTL);	else		btand(~3, BT848_GPIO_DMA_CTL);}static void bt848_cap(struct bttv *btv, uint state){	if (state) 	{		btv->cap|=3;		bt848_set_risc_jmps(btv);	}	else	{		btv->cap&=~3;		bt848_set_risc_jmps(btv);	}}/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC*//* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C    PLL_X = Reference pre-divider (0=1, 1=2)    PLL_C = Post divider (0=6, 1=4)   PLL_I = Integer input    PLL_F = Fractional input       F_input = 28.636363 MHz:    PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0*/static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout){        unsigned char fl, fh, fi;                /* prevent overflows */        fin/=4;        fout/=4;        fout*=12;        fi=fout/fin;        fout=(fout%fin)*256;        fh=fout/fin;        fout=(fout%fin)*256;        fl=fout/fin;        /*printk("0x%02x 0x%02x 0x%02x\n", fi, fh, fl);*/        btwrite(fl, BT848_PLL_F_LO);        btwrite(fh, BT848_PLL_F_HI);        btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);}static int set_pll(struct bttv *btv){        int i;	unsigned long tv;        if (!btv->pll.pll_crystal)                return 0;        if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) {                /* no PLL needed */                if (btv->pll.pll_current == 0) {                        /* printk ("bttv%d: PLL: is off\n",btv->nr); */                        return 0;                }                printk ("bttv%d: PLL: switching off\n",btv->nr);                btwrite(0x00,BT848_TGCTRL);                btwrite(0x00,BT848_PLL_XCI);                btv->pll.pll_current = 0;                return 0;        }        if (btv->pll.pll_ofreq == btv->pll.pll_current) {                /* printk("bttv%d: PLL: no change required\n",btv->nr); */                return 1;        }                printk("bttv%d: PLL: %d => %d ... ",btv->nr,               btv->pll.pll_ifreq, btv->pll.pll_ofreq);	set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);	/*  Let other people run while the PLL stabilizes */	tv=jiffies+HZ/10;       /* .1 seconds */	do	{		schedule();	}	while(time_before(jiffies,tv));        for (i=0; i<10; i++)         {                if ((btread(BT848_DSTATUS)&BT848_DSTATUS_PLOCK))                        btwrite(0,BT848_DSTATUS);                else                {                        btwrite(0x08,BT848_TGCTRL);                        btv->pll.pll_current = btv->pll.pll_ofreq;                        printk("ok\n");                        return 1;                }                mdelay(10);        }        btv->pll.pll_current = 0;        printk("oops\n");        return -1;}static void bt848_muxsel(struct bttv *btv, unsigned int input){	btaor(tvcards[btv->type].gpiomask2,~tvcards[btv->type].gpiomask2,              BT848_GPIO_OUT_EN);	/* This seems to get rid of some synchronization problems */	btand(~(3<<5), BT848_IFORM);	mdelay(10);                 	input %= tvcards[btv->type].video_inputs;	if (input==tvcards[btv->type].svhs) 	{		btor(BT848_CONTROL_COMP, BT848_E_CONTROL);		btor(BT848_CONTROL_COMP, BT848_O_CONTROL);	}	else	{		btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);		btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);	}	btaor((tvcards[btv->type].muxsel[input&7]&3)<<5, ~(3<<5), BT848_IFORM);	audio(btv, (input!=tvcards[btv->type].tuner) ?               AUDIO_EXTERN : AUDIO_TUNER);	btaor(tvcards[btv->type].muxsel[input]>>4,		~tvcards[btv->type].gpiomask2, BT848_GPIO_DATA);}/* *	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. */ struct tvnorm {        u32 Fsc;        u16 swidth, sheight; /* scaled standard width, height */	u16 totalwidth;	u8 adelay, bdelay, iform;	u32 scaledtwidth;	u16 hdelayx1, hactivex1;	u16 vdelay;        u8 vbipack;};static struct tvnorm tvnorms[] = {	/* PAL-BDGHI */        /* max. active video is actually 922, but 924 is divisible by 4 and 3! */ 	/* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */#ifdef VIDEODAT        { 35468950,          924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),          1135, 186, 924, 0x20, 255},#else        { 35468950,          924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),          1135, 186, 924, 0x20, 255},#endif/*        { 35468950,           768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),	  944, 186, 922, 0x20, 255},*/	/* NTSC */	{ 28636363,          768, 480,  910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),          910, 128, 910, 0x1a, 144},/*	{ 28636363,          640, 480,  910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),          780, 122, 754, 0x1a, 144},*/#if 0	/* SECAM EAST */	{ 35468950,           768, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1),	  944, 186, 922, 0x20, 255},#else	/* SECAM L */        { 35468950,          924, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1),          1135, 186, 922, 0x20, 255},#endif        /* PAL-NC */        { 28636363,          640, 576,  910, 0x68, 0x5d, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),          780, 130, 734, 0x1a, 144},	/* PAL-M */	{ 28636363,           640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0),	  780, 135, 754, 0x1a, 144},	/* PAL-N */	{ 35468950,           768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1),	  944, 186, 922, 0x20, 144},	/* NTSC-Japan */	{ 28636363,          640, 480,  910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),	  780, 135, 754, 0x16, 144},};#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm))#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;  	DEBUG(printk(KERN_DEBUG "vbiodd: 0x%08x\n",(int)btv->vbi_odd));	DEBUG(printk(KERN_DEBUG "vbievn: 0x%08x\n",(int)btv->vbi_even));	DEBUG(printk(KERN_DEBUG "po: 0x%08x\n",(int)po));	DEBUG(printk(KERN_DEBUG "pe: 0x%08x\n",(int)pe));        	*(po++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(po++)=0;	for (i=0; i<16; i++) 	{		*(po++)=VBI_RISC;		*(po++)=kvirt_to_bus((unsigned long)btv->vbibuf+i*2048);	}	*(po++)=BT848_RISC_JUMP;	*(po++)=virt_to_bus(btv->risc_jmp+4);	*(pe++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(pe++)=0;	for (i=16; i<32; i++) 	{		*(pe++)=VBI_RISC;		*(pe++)=kvirt_to_bus((unsigned long)btv->vbibuf+i*2048);	}	*(pe++)=BT848_RISC_JUMP|BT848_RISC_IRQ|(0x01<<16);	*(pe++)=virt_to_bus(btv->risc_jmp+10);	DEBUG(printk(KERN_DEBUG "po: 0x%08x\n",(int)po));	DEBUG(printk(KERN_DEBUG "pe: 0x%08x\n",(int)pe));}int fmtbppx2[16] = {        8, 6, 4, 4, 4, 3, 2, 2, 4, 3, 0, 0, 0, 0, 2, 0 };int palette2fmt[] = {       0,       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_BtYUV,       -1,       -1,       -1,       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(int))static int make_rawrisctab(struct bttv *btv, unsigned int *ro,                            unsigned int *re, unsigned int *vbuf){        unsigned long line;	unsigned long bpl=1024;		/* bytes per line */	unsigned long vadr=(unsigned long) vbuf;	*(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0;	*(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=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++)=BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL;                *(ro++)=kvirt_to_bus(vadr);                *(re++)=BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL;                *(re++)=kvirt_to_bus(vadr+BTTV_MAX_FBUF/2);                vadr+=bpl;	}		*(ro++)=BT848_RISC_JUMP;	*(ro++)=btv->bus_vbi_even;	*(re++)=BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16);	*(re++)=btv->bus_vbi_odd;		return 0;}static int  make_prisctab(struct bttv *btv, unsigned int *ro,                          unsigned int *re,                           unsigned int *vbuf, unsigned short width,                          unsigned short height, unsigned short fmt){        unsigned long line, lmask;	unsigned long bl, blcr, blcb, rcmd;	unsigned long todo;	unsigned int **rp;	int inter;	unsigned long cbadr, cradr;	unsigned long vadr=(unsigned long) vbuf;	int shift, csize;		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>btv->win.cropheight/2) ? 1 : 0;		*(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3; *(ro++)=0;	*(re++)=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) ? &re : &ro; 	                	        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)++)=rcmd|bl;		 *((*rp)++)=blcb|(blcr<<16);		 *((*rp)++)=kvirt_to_bus(vadr);		 vadr+=bl;		 if((rcmd&(15<<28))==BT848_RISC_WRITE123)		 {		 	*((*rp)++)=kvirt_to_bus(cbadr);		 	cbadr+=blcb;		 	*((*rp)++)=kvirt_to_bus(cradr);		 	cradr+=blcr;		 }		 		 rcmd&=~BT848_RISC_SOL; /* only the first has SOL */		}	}	

⌨️ 快捷键说明

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