📄 bttv-risc.c
字号:
*(rp++)=cpu_to_le32(ri); if (0 != ra) *(rp++)=cpu_to_le32(ra); } } /* save pointer to jmp instruction address */ risc->jmp = rp; kfree(skips); return 0;}/* ---------------------------------------------------------- */voidbttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo, int width, int height, int interleaved, int norm){ const struct bttv_tvnorm *tvnorm; u32 xsf, sr; int vdelay; tvnorm = &bttv_tvnorms[norm]; vdelay = tvnorm->vdelay; if (vdelay < btv->vbi.lines*2) vdelay = btv->vbi.lines*2; xsf = (width*tvnorm->scaledtwidth)/tvnorm->swidth; geo->hscale = ((tvnorm->totalwidth*4096UL)/xsf-4096); geo->hdelay = tvnorm->hdelayx1; geo->hdelay = (geo->hdelay*width)/tvnorm->swidth; geo->hdelay &= 0x3fe; sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512; geo->vscale = (0x10000UL-sr) & 0x1fff; geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) | ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0); geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0; geo->vdelay = vdelay; geo->width = width; geo->sheight = tvnorm->sheight; if (btv->opt_combfilter) { geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); geo->comb = (width < 769) ? 1 : 0; } else { geo->vtc = 0; geo->comb = 0; }}voidbttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd){ int off = odd ? 0x80 : 0x00; if (geo->comb) btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); else btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); btwrite(geo->vtc, BT848_E_VTC+off); btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off); btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off); btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off); btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off); btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off); btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off); btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off); btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off); btwrite(geo->crop, BT848_E_CROP+off);}/* ---------------------------------------------------------- *//* risc group / risc main loop / dma management */voidbttv_set_dma(struct bttv *btv, int override, int irqflags){ unsigned long cmd; int capctl; btv->cap_ctl = 0; if (NULL != btv->odd) btv->cap_ctl |= 0x02; if (NULL != btv->even) btv->cap_ctl |= 0x01; if (NULL != btv->vcurr) btv->cap_ctl |= 0x0c; capctl = 0; capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00; /* capture */ capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00; /* vbi data */ capctl |= override; d2printk(KERN_DEBUG "bttv%d: capctl=%x irq=%d odd=%08Lx/%08Lx even=%08Lx/%08Lx\n", btv->nr,capctl,irqflags, btv->vcurr ? (u64)btv->vcurr->odd.dma : 0, btv->odd ? (u64)btv->odd->odd.dma : 0, btv->vcurr ? (u64)btv->vcurr->even.dma : 0, btv->even ? (u64)btv->even->even.dma : 0); cmd = BT848_RISC_JUMP; if (irqflags) { cmd |= BT848_RISC_IRQ | (irqflags << 16); mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT); } else { del_timer(&btv->timeout); } btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd); btaor(capctl, ~0x0f, BT848_CAP_CTL); if (capctl) { if (btv->dma_on) return; btwrite(btv->main.dma, BT848_RISC_STRT_ADD); btor(3, BT848_GPIO_DMA_CTL); btv->dma_on = 1; } else { if (!btv->dma_on) return; btand(~3, BT848_GPIO_DMA_CTL); btv->dma_on = 0; } return;}intbttv_risc_init_main(struct bttv *btv){ int rc; if ((rc = bttv_riscmem_alloc(btv->dev,&btv->main,PAGE_SIZE)) < 0) return rc; dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n", btv->nr,(u64)btv->main.dma); btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC | BT848_FIFO_STATUS_VRE); btv->main.cpu[1] = cpu_to_le32(0); btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP); btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2)); /* odd field */ btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP); btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2)); btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP); btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2)); btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC | BT848_FIFO_STATUS_VRO); btv->main.cpu[9] = cpu_to_le32(0); /* even field */ btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP); btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2)); btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP); btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2)); /* jump back to odd field */ btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP); btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2)); return 0;}intbttv_risc_hook(struct bttv *btv, int slot, struct bttv_riscmem *risc, int irqflags){ unsigned long cmd; unsigned long next = btv->main.dma + ((slot+2) << 2); if (NULL == risc) { d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=NULL\n", btv->nr,risc,slot); btv->main.cpu[slot+1] = cpu_to_le32(next); } else { d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n", btv->nr,risc,slot,(u64)risc->dma,irqflags); cmd = BT848_RISC_JUMP; if (irqflags) cmd |= BT848_RISC_IRQ | (irqflags << 16); risc->jmp[0] = cpu_to_le32(cmd); risc->jmp[1] = cpu_to_le32(next); btv->main.cpu[slot+1] = cpu_to_le32(risc->dma); } return 0;}voidbttv_dma_free(struct bttv *btv, struct bttv_buffer *buf){ if (in_interrupt()) BUG(); videobuf_waiton(&buf->vb,0,0); videobuf_dma_pci_unmap(btv->dev, &buf->vb.dma); videobuf_dma_free(&buf->vb.dma); bttv_riscmem_free(btv->dev,&buf->even); bttv_riscmem_free(btv->dev,&buf->odd); buf->vb.state = STATE_NEEDS_INIT;}intbttv_buffer_activate(struct bttv *btv, struct bttv_buffer *odd, struct bttv_buffer *even){ if (NULL != odd && NULL != even) { odd->vb.state = STATE_ACTIVE; even->vb.state = STATE_ACTIVE; bttv_apply_geo(btv, &odd->geo, 1); bttv_apply_geo(btv, &even->geo,0); bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &odd->odd, 0); bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &even->even, 0); btaor((odd->btformat & 0xf0) | (even->btformat & 0x0f), ~0xff, BT848_COLOR_FMT); btaor((odd->btswap & 0x0a) | (even->btswap & 0x05), ~0x0f, BT848_COLOR_CTL); } else if (NULL != odd) { odd->vb.state = STATE_ACTIVE; bttv_apply_geo(btv, &odd->geo,1); bttv_apply_geo(btv, &odd->geo,0); bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &odd->odd, 0); bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0); btaor(odd->btformat & 0xff, ~0xff, BT848_COLOR_FMT); btaor(odd->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL); } else if (NULL != even) { even->vb.state = STATE_ACTIVE; bttv_apply_geo(btv, &even->geo,1); bttv_apply_geo(btv, &even->geo,0); bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0); bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &even->even, 0); btaor(even->btformat & 0xff, ~0xff, BT848_COLOR_FMT); btaor(even->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL); } else { bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0); bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0); } return 0;}/* ---------------------------------------------------------- */intbttv_buffer_field(struct bttv *btv, int field, int def_field, int norm, int height){ const struct bttv_tvnorm *tvnorm = bttv_tvnorms + norm; /* check interleave, even+odd fields */ if (height > (tvnorm->sheight >> 1)) { field = VBUF_FIELD_ODD | VBUF_FIELD_EVEN | VBUF_FIELD_INTER; } else { if (field & def_field) { field = def_field; } else { field = (def_field & VBUF_FIELD_EVEN) ? VBUF_FIELD_ODD : VBUF_FIELD_EVEN; } } return field;}/* calculate geometry, build risc code */intbttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf){ const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm; buf->vb.field = bttv_buffer_field(btv,buf->vb.field, VBUF_FIELD_EVEN, buf->tvnorm,buf->vb.height); dprintk(KERN_DEBUG "bttv%d: buffer flags:%s%s%s format: %s size: %dx%d\n", btv->nr, (buf->vb.field & VBUF_FIELD_INTER) ? " interleave" : "", (buf->vb.field & VBUF_FIELD_ODD) ? " odd" : "", (buf->vb.field & VBUF_FIELD_EVEN) ? " even" : "", buf->fmt->name,buf->vb.width,buf->vb.height); /* packed pixel modes */ if (buf->fmt->flags & FORMAT_FLAGS_PACKED) { int bpl, padding, lines; bpl = (buf->fmt->depth >> 3) * buf->vb.width; /* calculate geometry */ if (buf->vb.field & VBUF_FIELD_INTER) { bttv_calc_geo(btv,&buf->geo,buf->vb.width, buf->vb.height,1,buf->tvnorm); lines = buf->vb.height >> 1; padding = bpl; } else { bttv_calc_geo(btv,&buf->geo,buf->vb.width, buf->vb.height,0,buf->tvnorm); lines = buf->vb.height; padding = 0; } /* build risc code */ if (buf->vb.field & VBUF_FIELD_ODD) bttv_risc_packed(btv,&buf->odd,buf->vb.dma.sglist, 0,bpl,padding,lines); if (buf->vb.field & VBUF_FIELD_EVEN) bttv_risc_packed(btv,&buf->even,buf->vb.dma.sglist, padding,bpl,padding,lines); } /* planar modes */ if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) { struct bttv_riscmem *risc; int uoffset, voffset; int ypadding, cpadding, lines; /* calculate chroma offsets */ uoffset = buf->vb.width * buf->vb.height; voffset = buf->vb.width * buf->vb.height; if (buf->fmt->flags & FORMAT_FLAGS_CrCb) { /* Y-Cr-Cb plane order */ uoffset >>= buf->fmt->hshift; uoffset >>= buf->fmt->vshift; uoffset += voffset; } else { /* Y-Cb-Cr plane order */ voffset >>= buf->fmt->hshift; voffset >>= buf->fmt->vshift; voffset += uoffset; } if (buf->vb.field & VBUF_FIELD_INTER) { bttv_calc_geo(btv,&buf->geo,buf->vb.width, buf->vb.height,1,buf->tvnorm); lines = buf->vb.height >> 1; ypadding = buf->vb.width; if (!buf->fmt->vshift) { /* chroma planes are interleaved too */ cpadding = buf->vb.width >> buf->fmt->hshift; } else { cpadding = 0; } bttv_risc_planar(btv,&buf->odd, buf->vb.dma.sglist, 0,buf->vb.width,ypadding,lines, uoffset,voffset,buf->fmt->hshift, buf->fmt->vshift >> 1, cpadding); bttv_risc_planar(btv,&buf->even, buf->vb.dma.sglist, ypadding,buf->vb.width,ypadding,lines, uoffset+cpadding, voffset+cpadding, buf->fmt->hshift, cpadding ? (buf->fmt->vshift>>1) : -1, cpadding); } else { if (buf->vb.field & VBUF_FIELD_ODD) risc = &buf->odd; else risc = &buf->even; bttv_calc_geo(btv,&buf->geo,buf->vb.width, buf->vb.height,0,buf->tvnorm); bttv_risc_planar(btv, risc, buf->vb.dma.sglist, 0,buf->vb.width,0,buf->vb.height, uoffset,voffset,buf->fmt->hshift, buf->fmt->vshift,0); } } /* raw data */ if (buf->fmt->flags & FORMAT_FLAGS_RAW) { /* build risc code */ buf->vb.field = VBUF_FIELD_INTER | VBUF_FIELD_ODD | VBUF_FIELD_EVEN; bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight, 1,buf->tvnorm); bttv_risc_packed(btv, &buf->odd, buf->vb.dma.sglist, 0, RAW_BPL, 0, RAW_LINES); bttv_risc_packed(btv, &buf->even, buf->vb.dma.sglist, buf->vb.size/2 , RAW_BPL, 0, RAW_LINES); } /* copy format info */ buf->btformat = buf->fmt->btformat; buf->btswap = buf->fmt->btswap; return 0;}/* ---------------------------------------------------------- *//* calculate geometry, build risc code */intbttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov, const struct bttv_format *fmt, struct bttv_buffer *buf){ int interleave; /* check interleave, even+odd fields */ buf->vb.field = bttv_buffer_field(btv, 0, VBUF_FIELD_ODD, ov->tvnorm,ov->height); dprintk(KERN_DEBUG "bttv%d: overlay flags:%s%s%s format: %s size: %dx%d\n", btv->nr, (buf->vb.field & VBUF_FIELD_INTER) ? " interleave" : "", (buf->vb.field & VBUF_FIELD_ODD) ? " odd" : "", (buf->vb.field & VBUF_FIELD_EVEN) ? " even" : "", fmt->name,ov->width,ov->height); /* calculate geometry */ interleave = buf->vb.field & VBUF_FIELD_INTER; bttv_calc_geo(btv,&buf->geo,ov->width,ov->height, interleave, ov->tvnorm); /* build risc code */ if (buf->vb.field & VBUF_FIELD_ODD) bttv_risc_overlay(btv, &buf->odd, fmt, ov, interleave | VBUF_FIELD_ODD); if (buf->vb.field & VBUF_FIELD_EVEN) bttv_risc_overlay(btv, &buf->even,fmt, ov, interleave | VBUF_FIELD_EVEN); /* copy format info */ buf->btformat = fmt->btformat; buf->btswap = fmt->btswap; return 0;}/* * Local variables: * c-basic-offset: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -