📄 bttv-driver.c
字号:
.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 + -