Path: blob/master/drivers/media/video/bt8xx/bttv-risc.c
10785 views
/*12bttv-risc.c -- interfaces to other kernel modules34bttv risc code handling5- memory management6- generation78(c) 2000-2003 Gerd Knorr <[email protected]>910This program is free software; you can redistribute it and/or modify11it under the terms of the GNU General Public License as published by12the Free Software Foundation; either version 2 of the License, or13(at your option) any later version.1415This program is distributed in the hope that it will be useful,16but WITHOUT ANY WARRANTY; without even the implied warranty of17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the18GNU General Public License for more details.1920You should have received a copy of the GNU General Public License21along with this program; if not, write to the Free Software22Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.2324*/2526#include <linux/module.h>27#include <linux/init.h>28#include <linux/slab.h>29#include <linux/pci.h>30#include <linux/vmalloc.h>31#include <linux/interrupt.h>32#include <asm/page.h>33#include <asm/pgtable.h>34#include <media/v4l2-ioctl.h>3536#include "bttvp.h"3738#define VCR_HACK_LINES 43940/* ---------------------------------------------------------- */41/* risc code generators */4243int44bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,45struct scatterlist *sglist,46unsigned int offset, unsigned int bpl,47unsigned int padding, unsigned int skip_lines,48unsigned int store_lines)49{50u32 instructions,line,todo;51struct scatterlist *sg;52__le32 *rp;53int rc;5455/* estimate risc mem: worst case is one write per page border +56one write per scan line + sync + jump (all 2 dwords). padding57can cause next bpl to start close to a page border. First DMA58region may be smaller than PAGE_SIZE */59instructions = skip_lines * 4;60instructions += (1 + ((bpl + padding) * store_lines)61/ PAGE_SIZE + store_lines) * 8;62instructions += 2 * 8;63if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions)) < 0)64return rc;6566/* sync instruction */67rp = risc->cpu;68*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);69*(rp++) = cpu_to_le32(0);7071while (skip_lines-- > 0) {72*(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |73BT848_RISC_EOL | bpl);74}7576/* scan lines */77sg = sglist;78for (line = 0; line < store_lines; line++) {79if ((btv->opt_vcr_hack) &&80(line >= (store_lines - VCR_HACK_LINES)))81continue;82while (offset && offset >= sg_dma_len(sg)) {83offset -= sg_dma_len(sg);84sg++;85}86if (bpl <= sg_dma_len(sg)-offset) {87/* fits into current chunk */88*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|89BT848_RISC_EOL|bpl);90*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);91offset+=bpl;92} else {93/* scanline needs to be splitted */94todo = bpl;95*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|96(sg_dma_len(sg)-offset));97*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);98todo -= (sg_dma_len(sg)-offset);99offset = 0;100sg++;101while (todo > sg_dma_len(sg)) {102*(rp++)=cpu_to_le32(BT848_RISC_WRITE|103sg_dma_len(sg));104*(rp++)=cpu_to_le32(sg_dma_address(sg));105todo -= sg_dma_len(sg);106sg++;107}108*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|109todo);110*(rp++)=cpu_to_le32(sg_dma_address(sg));111offset += todo;112}113offset += padding;114}115116/* save pointer to jmp instruction address */117risc->jmp = rp;118BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);119return 0;120}121122static int123bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,124struct scatterlist *sglist,125unsigned int yoffset, unsigned int ybpl,126unsigned int ypadding, unsigned int ylines,127unsigned int uoffset, unsigned int voffset,128unsigned int hshift, unsigned int vshift,129unsigned int cpadding)130{131unsigned int instructions,line,todo,ylen,chroma;132__le32 *rp;133u32 ri;134struct scatterlist *ysg;135struct scatterlist *usg;136struct scatterlist *vsg;137int topfield = (0 == yoffset);138int rc;139140/* estimate risc mem: worst case is one write per page border +141one write per scan line (5 dwords)142plus sync + jump (2 dwords) */143instructions = ((3 + (ybpl + ypadding) * ylines * 2)144/ PAGE_SIZE) + ylines;145instructions += 2;146if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)147return rc;148149/* sync instruction */150rp = risc->cpu;151*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);152*(rp++) = cpu_to_le32(0);153154/* scan lines */155ysg = sglist;156usg = sglist;157vsg = sglist;158for (line = 0; line < ylines; line++) {159if ((btv->opt_vcr_hack) &&160(line >= (ylines - VCR_HACK_LINES)))161continue;162switch (vshift) {163case 0:164chroma = 1;165break;166case 1:167if (topfield)168chroma = ((line & 1) == 0);169else170chroma = ((line & 1) == 1);171break;172case 2:173if (topfield)174chroma = ((line & 3) == 0);175else176chroma = ((line & 3) == 2);177break;178default:179chroma = 0;180break;181}182183for (todo = ybpl; todo > 0; todo -= ylen) {184/* go to next sg entry if needed */185while (yoffset && yoffset >= sg_dma_len(ysg)) {186yoffset -= sg_dma_len(ysg);187ysg++;188}189while (uoffset && uoffset >= sg_dma_len(usg)) {190uoffset -= sg_dma_len(usg);191usg++;192}193while (voffset && voffset >= sg_dma_len(vsg)) {194voffset -= sg_dma_len(vsg);195vsg++;196}197198/* calculate max number of bytes we can write */199ylen = todo;200if (yoffset + ylen > sg_dma_len(ysg))201ylen = sg_dma_len(ysg) - yoffset;202if (chroma) {203if (uoffset + (ylen>>hshift) > sg_dma_len(usg))204ylen = (sg_dma_len(usg) - uoffset) << hshift;205if (voffset + (ylen>>hshift) > sg_dma_len(vsg))206ylen = (sg_dma_len(vsg) - voffset) << hshift;207ri = BT848_RISC_WRITE123;208} else {209ri = BT848_RISC_WRITE1S23;210}211if (ybpl == todo)212ri |= BT848_RISC_SOL;213if (ylen == todo)214ri |= BT848_RISC_EOL;215216/* write risc instruction */217*(rp++)=cpu_to_le32(ri | ylen);218*(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |219(ylen >> hshift));220*(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);221yoffset += ylen;222if (chroma) {223*(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);224uoffset += ylen >> hshift;225*(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);226voffset += ylen >> hshift;227}228}229yoffset += ypadding;230if (chroma) {231uoffset += cpadding;232voffset += cpadding;233}234}235236/* save pointer to jmp instruction address */237risc->jmp = rp;238BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);239return 0;240}241242static int243bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,244const struct bttv_format *fmt, struct bttv_overlay *ov,245int skip_even, int skip_odd)246{247int dwords, rc, line, maxy, start, end;248unsigned skip, nskips;249struct btcx_skiplist *skips;250__le32 *rp;251u32 ri,ra;252u32 addr;253254/* skip list for window clipping */255if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))256return -ENOMEM;257258/* estimate risc mem: worst case is (1.5*clip+1) * lines instructions259+ sync + jump (all 2 dwords) */260dwords = (3 * ov->nclips + 2) *261((skip_even || skip_odd) ? (ov->w.height+1)>>1 : ov->w.height);262dwords += 4;263if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,dwords*4)) < 0) {264kfree(skips);265return rc;266}267268/* sync instruction */269rp = risc->cpu;270*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);271*(rp++) = cpu_to_le32(0);272273addr = (unsigned long)btv->fbuf.base;274addr += btv->fbuf.fmt.bytesperline * ov->w.top;275addr += (fmt->depth >> 3) * ov->w.left;276277/* scan lines */278for (maxy = -1, line = 0; line < ov->w.height;279line++, addr += btv->fbuf.fmt.bytesperline) {280if ((btv->opt_vcr_hack) &&281(line >= (ov->w.height - VCR_HACK_LINES)))282continue;283if ((line%2) == 0 && skip_even)284continue;285if ((line%2) == 1 && skip_odd)286continue;287288/* calculate clipping */289if (line > maxy)290btcx_calc_skips(line, ov->w.width, &maxy,291skips, &nskips, ov->clips, ov->nclips);292293/* write out risc code */294for (start = 0, skip = 0; start < ov->w.width; start = end) {295if (skip >= nskips) {296ri = BT848_RISC_WRITE;297end = ov->w.width;298} else if (start < skips[skip].start) {299ri = BT848_RISC_WRITE;300end = skips[skip].start;301} else {302ri = BT848_RISC_SKIP;303end = skips[skip].end;304skip++;305}306if (BT848_RISC_WRITE == ri)307ra = addr + (fmt->depth>>3)*start;308else309ra = 0;310311if (0 == start)312ri |= BT848_RISC_SOL;313if (ov->w.width == end)314ri |= BT848_RISC_EOL;315ri |= (fmt->depth>>3) * (end-start);316317*(rp++)=cpu_to_le32(ri);318if (0 != ra)319*(rp++)=cpu_to_le32(ra);320}321}322323/* save pointer to jmp instruction address */324risc->jmp = rp;325BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);326kfree(skips);327return 0;328}329330/* ---------------------------------------------------------- */331332static void333bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,334int width, int height, int interleaved,335const struct bttv_tvnorm *tvnorm)336{337u32 xsf, sr;338int vdelay;339340int swidth = tvnorm->swidth;341int totalwidth = tvnorm->totalwidth;342int scaledtwidth = tvnorm->scaledtwidth;343344if (btv->input == btv->dig) {345swidth = 720;346totalwidth = 858;347scaledtwidth = 858;348}349350vdelay = tvnorm->vdelay;351352xsf = (width*scaledtwidth)/swidth;353geo->hscale = ((totalwidth*4096UL)/xsf-4096);354geo->hdelay = tvnorm->hdelayx1;355geo->hdelay = (geo->hdelay*width)/swidth;356geo->hdelay &= 0x3fe;357sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;358geo->vscale = (0x10000UL-sr) & 0x1fff;359geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |360((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);361geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;362geo->vdelay = vdelay;363geo->width = width;364geo->sheight = tvnorm->sheight;365geo->vtotal = tvnorm->vtotal;366367if (btv->opt_combfilter) {368geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);369geo->comb = (width < 769) ? 1 : 0;370} else {371geo->vtc = 0;372geo->comb = 0;373}374}375376static void377bttv_calc_geo (struct bttv * btv,378struct bttv_geometry * geo,379unsigned int width,380unsigned int height,381int both_fields,382const struct bttv_tvnorm * tvnorm,383const struct v4l2_rect * crop)384{385unsigned int c_width;386unsigned int c_height;387u32 sr;388389if ((crop->left == tvnorm->cropcap.defrect.left390&& crop->top == tvnorm->cropcap.defrect.top391&& crop->width == tvnorm->cropcap.defrect.width392&& crop->height == tvnorm->cropcap.defrect.height393&& width <= tvnorm->swidth /* see PAL-Nc et al */)394|| btv->input == btv->dig) {395bttv_calc_geo_old(btv, geo, width, height,396both_fields, tvnorm);397return;398}399400/* For bug compatibility the image size checks permit scale401factors > 16. See bttv_crop_calc_limits(). */402c_width = min((unsigned int) crop->width, width * 16);403c_height = min((unsigned int) crop->height, height * 16);404405geo->width = width;406geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;407/* Even to store Cb first, odd for Cr. */408geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;409410geo->sheight = c_height;411geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;412sr = c_height >> !both_fields;413sr = (sr * 512U + (height >> 1)) / height - 512;414geo->vscale = (0x10000UL - sr) & 0x1fff;415geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;416geo->vtotal = tvnorm->vtotal;417418geo->crop = (((geo->width >> 8) & 0x03) |419((geo->hdelay >> 6) & 0x0c) |420((geo->sheight >> 4) & 0x30) |421((geo->vdelay >> 2) & 0xc0));422423if (btv->opt_combfilter) {424geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);425geo->comb = (width < 769) ? 1 : 0;426} else {427geo->vtc = 0;428geo->comb = 0;429}430}431432static void433bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)434{435int off = odd ? 0x80 : 0x00;436437if (geo->comb)438btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);439else440btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);441442btwrite(geo->vtc, BT848_E_VTC+off);443btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off);444btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off);445btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);446btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off);447btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off);448btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off);449btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off);450btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off);451btwrite(geo->crop, BT848_E_CROP+off);452btwrite(geo->vtotal>>8, BT848_VTOTAL_HI);453btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO);454}455456/* ---------------------------------------------------------- */457/* risc group / risc main loop / dma management */458459void460bttv_set_dma(struct bttv *btv, int override)461{462unsigned long cmd;463int capctl;464465btv->cap_ctl = 0;466if (NULL != btv->curr.top) btv->cap_ctl |= 0x02;467if (NULL != btv->curr.bottom) btv->cap_ctl |= 0x01;468if (NULL != btv->cvbi) btv->cap_ctl |= 0x0c;469470capctl = 0;471capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00; /* capture */472capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00; /* vbi data */473capctl |= override;474475d2printk(KERN_DEBUG476"bttv%d: capctl=%x lirq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",477btv->c.nr,capctl,btv->loop_irq,478btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,479btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,480btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0,481btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);482483cmd = BT848_RISC_JUMP;484if (btv->loop_irq) {485cmd |= BT848_RISC_IRQ;486cmd |= (btv->loop_irq & 0x0f) << 16;487cmd |= (~btv->loop_irq & 0x0f) << 20;488}489if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {490mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);491} else {492del_timer(&btv->timeout);493}494btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);495496btaor(capctl, ~0x0f, BT848_CAP_CTL);497if (capctl) {498if (btv->dma_on)499return;500btwrite(btv->main.dma, BT848_RISC_STRT_ADD);501btor(3, BT848_GPIO_DMA_CTL);502btv->dma_on = 1;503} else {504if (!btv->dma_on)505return;506btand(~3, BT848_GPIO_DMA_CTL);507btv->dma_on = 0;508}509return;510}511512int513bttv_risc_init_main(struct bttv *btv)514{515int rc;516517if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)518return rc;519dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n",520btv->c.nr,(unsigned long long)btv->main.dma);521522btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |523BT848_FIFO_STATUS_VRE);524btv->main.cpu[1] = cpu_to_le32(0);525btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);526btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));527528/* top field */529btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);530btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));531btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);532btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));533534btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |535BT848_FIFO_STATUS_VRO);536btv->main.cpu[9] = cpu_to_le32(0);537538/* bottom field */539btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);540btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));541btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);542btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));543544/* jump back to top field */545btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);546btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));547548return 0;549}550551int552bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,553int irqflags)554{555unsigned long cmd;556unsigned long next = btv->main.dma + ((slot+2) << 2);557558if (NULL == risc) {559d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=NULL\n",560btv->c.nr,risc,slot);561btv->main.cpu[slot+1] = cpu_to_le32(next);562} else {563d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n",564btv->c.nr,risc,slot,(unsigned long long)risc->dma,irqflags);565cmd = BT848_RISC_JUMP;566if (irqflags) {567cmd |= BT848_RISC_IRQ;568cmd |= (irqflags & 0x0f) << 16;569cmd |= (~irqflags & 0x0f) << 20;570}571risc->jmp[0] = cpu_to_le32(cmd);572risc->jmp[1] = cpu_to_le32(next);573btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);574}575return 0;576}577578void579bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)580{581struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);582583BUG_ON(in_interrupt());584videobuf_waiton(q, &buf->vb, 0, 0);585videobuf_dma_unmap(q->dev, dma);586videobuf_dma_free(dma);587btcx_riscmem_free(btv->c.pci,&buf->bottom);588btcx_riscmem_free(btv->c.pci,&buf->top);589buf->vb.state = VIDEOBUF_NEEDS_INIT;590}591592int593bttv_buffer_activate_vbi(struct bttv *btv,594struct bttv_buffer *vbi)595{596struct btcx_riscmem *top;597struct btcx_riscmem *bottom;598int top_irq_flags;599int bottom_irq_flags;600601top = NULL;602bottom = NULL;603top_irq_flags = 0;604bottom_irq_flags = 0;605606if (vbi) {607unsigned int crop, vdelay;608609vbi->vb.state = VIDEOBUF_ACTIVE;610list_del(&vbi->vb.queue);611612/* VDELAY is start of video, end of VBI capturing. */613crop = btread(BT848_E_CROP);614vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);615616if (vbi->geo.vdelay > vdelay) {617vdelay = vbi->geo.vdelay & 0xfe;618crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);619620btwrite(vdelay, BT848_E_VDELAY_LO);621btwrite(crop, BT848_E_CROP);622btwrite(vdelay, BT848_O_VDELAY_LO);623btwrite(crop, BT848_O_CROP);624}625626if (vbi->vbi_count[0] > 0) {627top = &vbi->top;628top_irq_flags = 4;629}630631if (vbi->vbi_count[1] > 0) {632top_irq_flags = 0;633bottom = &vbi->bottom;634bottom_irq_flags = 4;635}636}637638bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);639bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);640641return 0;642}643644int645bttv_buffer_activate_video(struct bttv *btv,646struct bttv_buffer_set *set)647{648/* video capture */649if (NULL != set->top && NULL != set->bottom) {650if (set->top == set->bottom) {651set->top->vb.state = VIDEOBUF_ACTIVE;652if (set->top->vb.queue.next)653list_del(&set->top->vb.queue);654} else {655set->top->vb.state = VIDEOBUF_ACTIVE;656set->bottom->vb.state = VIDEOBUF_ACTIVE;657if (set->top->vb.queue.next)658list_del(&set->top->vb.queue);659if (set->bottom->vb.queue.next)660list_del(&set->bottom->vb.queue);661}662bttv_apply_geo(btv, &set->top->geo, 1);663bttv_apply_geo(btv, &set->bottom->geo,0);664bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,665set->top_irq);666bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,667set->frame_irq);668btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),669~0xff, BT848_COLOR_FMT);670btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),671~0x0f, BT848_COLOR_CTL);672} else if (NULL != set->top) {673set->top->vb.state = VIDEOBUF_ACTIVE;674if (set->top->vb.queue.next)675list_del(&set->top->vb.queue);676bttv_apply_geo(btv, &set->top->geo,1);677bttv_apply_geo(btv, &set->top->geo,0);678bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,679set->frame_irq);680bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);681btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);682btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);683} else if (NULL != set->bottom) {684set->bottom->vb.state = VIDEOBUF_ACTIVE;685if (set->bottom->vb.queue.next)686list_del(&set->bottom->vb.queue);687bttv_apply_geo(btv, &set->bottom->geo,1);688bttv_apply_geo(btv, &set->bottom->geo,0);689bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);690bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,691set->frame_irq);692btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);693btaor(set->bottom->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);694} else {695bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);696bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);697}698return 0;699}700701/* ---------------------------------------------------------- */702703/* calculate geometry, build risc code */704int705bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)706{707const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;708struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);709710dprintk(KERN_DEBUG711"bttv%d: buffer field: %s format: %s size: %dx%d\n",712btv->c.nr, v4l2_field_names[buf->vb.field],713buf->fmt->name, buf->vb.width, buf->vb.height);714715/* packed pixel modes */716if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {717int bpl = (buf->fmt->depth >> 3) * buf->vb.width;718int bpf = bpl * (buf->vb.height >> 1);719720bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,721V4L2_FIELD_HAS_BOTH(buf->vb.field),722tvnorm,&buf->crop);723724switch (buf->vb.field) {725case V4L2_FIELD_TOP:726bttv_risc_packed(btv,&buf->top,dma->sglist,727/* offset */ 0,bpl,728/* padding */ 0,/* skip_lines */ 0,729buf->vb.height);730break;731case V4L2_FIELD_BOTTOM:732bttv_risc_packed(btv,&buf->bottom,dma->sglist,7330,bpl,0,0,buf->vb.height);734break;735case V4L2_FIELD_INTERLACED:736bttv_risc_packed(btv,&buf->top,dma->sglist,7370,bpl,bpl,0,buf->vb.height >> 1);738bttv_risc_packed(btv,&buf->bottom,dma->sglist,739bpl,bpl,bpl,0,buf->vb.height >> 1);740break;741case V4L2_FIELD_SEQ_TB:742bttv_risc_packed(btv,&buf->top,dma->sglist,7430,bpl,0,0,buf->vb.height >> 1);744bttv_risc_packed(btv,&buf->bottom,dma->sglist,745bpf,bpl,0,0,buf->vb.height >> 1);746break;747default:748BUG();749}750}751752/* planar modes */753if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {754int uoffset, voffset;755int ypadding, cpadding, lines;756757/* calculate chroma offsets */758uoffset = buf->vb.width * buf->vb.height;759voffset = buf->vb.width * buf->vb.height;760if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {761/* Y-Cr-Cb plane order */762uoffset >>= buf->fmt->hshift;763uoffset >>= buf->fmt->vshift;764uoffset += voffset;765} else {766/* Y-Cb-Cr plane order */767voffset >>= buf->fmt->hshift;768voffset >>= buf->fmt->vshift;769voffset += uoffset;770}771772switch (buf->vb.field) {773case V4L2_FIELD_TOP:774bttv_calc_geo(btv,&buf->geo,buf->vb.width,775buf->vb.height,/* both_fields */ 0,776tvnorm,&buf->crop);777bttv_risc_planar(btv, &buf->top, dma->sglist,7780,buf->vb.width,0,buf->vb.height,779uoffset,voffset,buf->fmt->hshift,780buf->fmt->vshift,0);781break;782case V4L2_FIELD_BOTTOM:783bttv_calc_geo(btv,&buf->geo,buf->vb.width,784buf->vb.height,0,785tvnorm,&buf->crop);786bttv_risc_planar(btv, &buf->bottom, dma->sglist,7870,buf->vb.width,0,buf->vb.height,788uoffset,voffset,buf->fmt->hshift,789buf->fmt->vshift,0);790break;791case V4L2_FIELD_INTERLACED:792bttv_calc_geo(btv,&buf->geo,buf->vb.width,793buf->vb.height,1,794tvnorm,&buf->crop);795lines = buf->vb.height >> 1;796ypadding = buf->vb.width;797cpadding = buf->vb.width >> buf->fmt->hshift;798bttv_risc_planar(btv,&buf->top,799dma->sglist,8000,buf->vb.width,ypadding,lines,801uoffset,voffset,802buf->fmt->hshift,803buf->fmt->vshift,804cpadding);805bttv_risc_planar(btv,&buf->bottom,806dma->sglist,807ypadding,buf->vb.width,ypadding,lines,808uoffset+cpadding,809voffset+cpadding,810buf->fmt->hshift,811buf->fmt->vshift,812cpadding);813break;814case V4L2_FIELD_SEQ_TB:815bttv_calc_geo(btv,&buf->geo,buf->vb.width,816buf->vb.height,1,817tvnorm,&buf->crop);818lines = buf->vb.height >> 1;819ypadding = buf->vb.width;820cpadding = buf->vb.width >> buf->fmt->hshift;821bttv_risc_planar(btv,&buf->top,822dma->sglist,8230,buf->vb.width,0,lines,824uoffset >> 1,825voffset >> 1,826buf->fmt->hshift,827buf->fmt->vshift,8280);829bttv_risc_planar(btv,&buf->bottom,830dma->sglist,831lines * ypadding,buf->vb.width,0,lines,832lines * ypadding + (uoffset >> 1),833lines * ypadding + (voffset >> 1),834buf->fmt->hshift,835buf->fmt->vshift,8360);837break;838default:839BUG();840}841}842843/* raw data */844if (buf->fmt->flags & FORMAT_FLAGS_RAW) {845/* build risc code */846buf->vb.field = V4L2_FIELD_SEQ_TB;847bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,8481,tvnorm,&buf->crop);849bttv_risc_packed(btv, &buf->top, dma->sglist,850/* offset */ 0, RAW_BPL, /* padding */ 0,851/* skip_lines */ 0, RAW_LINES);852bttv_risc_packed(btv, &buf->bottom, dma->sglist,853buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);854}855856/* copy format info */857buf->btformat = buf->fmt->btformat;858buf->btswap = buf->fmt->btswap;859return 0;860}861862/* ---------------------------------------------------------- */863864/* calculate geometry, build risc code */865int866bttv_overlay_risc(struct bttv *btv,867struct bttv_overlay *ov,868const struct bttv_format *fmt,869struct bttv_buffer *buf)870{871/* check interleave, bottom+top fields */872dprintk(KERN_DEBUG873"bttv%d: overlay fields: %s format: %s size: %dx%d\n",874btv->c.nr, v4l2_field_names[buf->vb.field],875fmt->name,ov->w.width,ov->w.height);876877/* calculate geometry */878bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,879V4L2_FIELD_HAS_BOTH(ov->field),880&bttv_tvnorms[ov->tvnorm],&buf->crop);881882/* build risc code */883switch (ov->field) {884case V4L2_FIELD_TOP:885bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 0);886break;887case V4L2_FIELD_BOTTOM:888bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);889break;890case V4L2_FIELD_INTERLACED:891bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 1);892bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);893break;894default:895BUG();896}897898/* copy format info */899buf->btformat = fmt->btformat;900buf->btswap = fmt->btswap;901buf->vb.field = ov->field;902return 0;903}904905/*906* Local variables:907* c-basic-offset: 8908* End:909*/910911912