📄 bttv-driver.c
字号:
{ 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; 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 int fmtbppx2[16] = { 8, 6, 4, 4, 4, 3, 2, 2, 4, 3, 0, 0, 0, 0, 2, 0 };static 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_YUY2, -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++)=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, 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; 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, unsigned int *ro, unsigned int *re, unsigned int *vbuf, unsigned short width, unsigned short height, unsigned short palette){ unsigned long line; unsigned long bpl; /* bytes per line */ unsigned long bl; unsigned long todo; unsigned int **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; } } 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){ int i, line, x, y, bpl, width, height, inter, maxw; unsigned int bpp, dx, sx, **rp, *ro, *re, flags, len; unsigned long adr; 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]. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -