cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bttv-risc.c (25327B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3
      4    bttv-risc.c  --  interfaces to other kernel modules
      5
      6    bttv risc code handling
      7	- memory management
      8	- generation
      9
     10    (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org>
     11
     12
     13*/
     14
     15#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     16
     17#include <linux/module.h>
     18#include <linux/init.h>
     19#include <linux/slab.h>
     20#include <linux/pci.h>
     21#include <linux/vmalloc.h>
     22#include <linux/interrupt.h>
     23#include <linux/pgtable.h>
     24#include <asm/page.h>
     25#include <media/v4l2-ioctl.h>
     26
     27#include "bttvp.h"
     28
     29#define VCR_HACK_LINES 4
     30
     31/* ---------------------------------------------------------- */
     32/* risc code generators                                       */
     33
     34int
     35bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
     36		 struct scatterlist *sglist,
     37		 unsigned int offset, unsigned int bpl,
     38		 unsigned int padding, unsigned int skip_lines,
     39		 unsigned int store_lines)
     40{
     41	u32 instructions,line,todo;
     42	struct scatterlist *sg;
     43	__le32 *rp;
     44	int rc;
     45
     46	/* estimate risc mem: worst case is one write per page border +
     47	   one write per scan line + sync + jump (all 2 dwords).  padding
     48	   can cause next bpl to start close to a page border.  First DMA
     49	   region may be smaller than PAGE_SIZE */
     50	instructions  = skip_lines * 4;
     51	instructions += (1 + ((bpl + padding) * store_lines)
     52			 / PAGE_SIZE + store_lines) * 8;
     53	instructions += 2 * 8;
     54	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions)) < 0)
     55		return rc;
     56
     57	/* sync instruction */
     58	rp = risc->cpu;
     59	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
     60	*(rp++) = cpu_to_le32(0);
     61
     62	while (skip_lines-- > 0) {
     63		*(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |
     64				      BT848_RISC_EOL | bpl);
     65	}
     66
     67	/* scan lines */
     68	sg = sglist;
     69	for (line = 0; line < store_lines; line++) {
     70		if ((btv->opt_vcr_hack) &&
     71		    (line >= (store_lines - VCR_HACK_LINES)))
     72			continue;
     73		while (offset && offset >= sg_dma_len(sg)) {
     74			offset -= sg_dma_len(sg);
     75			sg = sg_next(sg);
     76		}
     77		if (bpl <= sg_dma_len(sg)-offset) {
     78			/* fits into current chunk */
     79			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
     80					    BT848_RISC_EOL|bpl);
     81			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
     82			offset+=bpl;
     83		} else {
     84			/* scanline needs to be split */
     85			todo = bpl;
     86			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
     87					    (sg_dma_len(sg)-offset));
     88			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
     89			todo -= (sg_dma_len(sg)-offset);
     90			offset = 0;
     91			sg = sg_next(sg);
     92			while (todo > sg_dma_len(sg)) {
     93				*(rp++)=cpu_to_le32(BT848_RISC_WRITE|
     94						    sg_dma_len(sg));
     95				*(rp++)=cpu_to_le32(sg_dma_address(sg));
     96				todo -= sg_dma_len(sg);
     97				sg = sg_next(sg);
     98			}
     99			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
    100					    todo);
    101			*(rp++)=cpu_to_le32(sg_dma_address(sg));
    102			offset += todo;
    103		}
    104		offset += padding;
    105	}
    106
    107	/* save pointer to jmp instruction address */
    108	risc->jmp = rp;
    109	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
    110	return 0;
    111}
    112
    113static int
    114bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
    115		 struct scatterlist *sglist,
    116		 unsigned int yoffset,  unsigned int ybpl,
    117		 unsigned int ypadding, unsigned int ylines,
    118		 unsigned int uoffset,  unsigned int voffset,
    119		 unsigned int hshift,   unsigned int vshift,
    120		 unsigned int cpadding)
    121{
    122	unsigned int instructions,line,todo,ylen,chroma;
    123	__le32 *rp;
    124	u32 ri;
    125	struct scatterlist *ysg;
    126	struct scatterlist *usg;
    127	struct scatterlist *vsg;
    128	int topfield = (0 == yoffset);
    129	int rc;
    130
    131	/* estimate risc mem: worst case is one write per page border +
    132	   one write per scan line (5 dwords)
    133	   plus sync + jump (2 dwords) */
    134	instructions  = ((3 + (ybpl + ypadding) * ylines * 2)
    135			 / PAGE_SIZE) + ylines;
    136	instructions += 2;
    137	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
    138		return rc;
    139
    140	/* sync instruction */
    141	rp = risc->cpu;
    142	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
    143	*(rp++) = cpu_to_le32(0);
    144
    145	/* scan lines */
    146	ysg = sglist;
    147	usg = sglist;
    148	vsg = sglist;
    149	for (line = 0; line < ylines; line++) {
    150		if ((btv->opt_vcr_hack) &&
    151		    (line >= (ylines - VCR_HACK_LINES)))
    152			continue;
    153		switch (vshift) {
    154		case 0:
    155			chroma = 1;
    156			break;
    157		case 1:
    158			if (topfield)
    159				chroma = ((line & 1) == 0);
    160			else
    161				chroma = ((line & 1) == 1);
    162			break;
    163		case 2:
    164			if (topfield)
    165				chroma = ((line & 3) == 0);
    166			else
    167				chroma = ((line & 3) == 2);
    168			break;
    169		default:
    170			chroma = 0;
    171			break;
    172		}
    173
    174		for (todo = ybpl; todo > 0; todo -= ylen) {
    175			/* go to next sg entry if needed */
    176			while (yoffset && yoffset >= sg_dma_len(ysg)) {
    177				yoffset -= sg_dma_len(ysg);
    178				ysg = sg_next(ysg);
    179			}
    180
    181			/* calculate max number of bytes we can write */
    182			ylen = todo;
    183			if (yoffset + ylen > sg_dma_len(ysg))
    184				ylen = sg_dma_len(ysg) - yoffset;
    185			if (chroma) {
    186				while (uoffset && uoffset >= sg_dma_len(usg)) {
    187					uoffset -= sg_dma_len(usg);
    188					usg = sg_next(usg);
    189				}
    190				while (voffset && voffset >= sg_dma_len(vsg)) {
    191					voffset -= sg_dma_len(vsg);
    192					vsg = sg_next(vsg);
    193				}
    194
    195				if (uoffset + (ylen>>hshift) > sg_dma_len(usg))
    196					ylen = (sg_dma_len(usg) - uoffset) << hshift;
    197				if (voffset + (ylen>>hshift) > sg_dma_len(vsg))
    198					ylen = (sg_dma_len(vsg) - voffset) << hshift;
    199				ri = BT848_RISC_WRITE123;
    200			} else {
    201				ri = BT848_RISC_WRITE1S23;
    202			}
    203			if (ybpl == todo)
    204				ri |= BT848_RISC_SOL;
    205			if (ylen == todo)
    206				ri |= BT848_RISC_EOL;
    207
    208			/* write risc instruction */
    209			*(rp++)=cpu_to_le32(ri | ylen);
    210			*(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
    211					    (ylen >> hshift));
    212			*(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
    213			yoffset += ylen;
    214			if (chroma) {
    215				*(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);
    216				uoffset += ylen >> hshift;
    217				*(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);
    218				voffset += ylen >> hshift;
    219			}
    220		}
    221		yoffset += ypadding;
    222		if (chroma) {
    223			uoffset += cpadding;
    224			voffset += cpadding;
    225		}
    226	}
    227
    228	/* save pointer to jmp instruction address */
    229	risc->jmp = rp;
    230	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
    231	return 0;
    232}
    233
    234static int
    235bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
    236		  const struct bttv_format *fmt, struct bttv_overlay *ov,
    237		  int skip_even, int skip_odd)
    238{
    239	int dwords, rc, line, maxy, start, end;
    240	unsigned skip, nskips;
    241	struct btcx_skiplist *skips;
    242	__le32 *rp;
    243	u32 ri,ra;
    244	u32 addr;
    245
    246	/* skip list for window clipping */
    247	skips = kmalloc_array(ov->nclips, sizeof(*skips),GFP_KERNEL);
    248	if (NULL == skips)
    249		return -ENOMEM;
    250
    251	/* estimate risc mem: worst case is (1.5*clip+1) * lines instructions
    252	   + sync + jump (all 2 dwords) */
    253	dwords  = (3 * ov->nclips + 2) *
    254		((skip_even || skip_odd) ? (ov->w.height+1)>>1 :  ov->w.height);
    255	dwords += 4;
    256	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,dwords*4)) < 0) {
    257		kfree(skips);
    258		return rc;
    259	}
    260
    261	/* sync instruction */
    262	rp = risc->cpu;
    263	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
    264	*(rp++) = cpu_to_le32(0);
    265
    266	addr  = (unsigned long)btv->fbuf.base;
    267	addr += btv->fbuf.fmt.bytesperline * ov->w.top;
    268	addr += (fmt->depth >> 3)          * ov->w.left;
    269
    270	/* scan lines */
    271	for (maxy = -1, line = 0; line < ov->w.height;
    272	     line++, addr += btv->fbuf.fmt.bytesperline) {
    273		if ((btv->opt_vcr_hack) &&
    274		     (line >= (ov->w.height - VCR_HACK_LINES)))
    275			continue;
    276		if ((line%2) == 0  &&  skip_even)
    277			continue;
    278		if ((line%2) == 1  &&  skip_odd)
    279			continue;
    280
    281		/* calculate clipping */
    282		if (line > maxy)
    283			btcx_calc_skips(line, ov->w.width, &maxy,
    284					skips, &nskips, ov->clips, ov->nclips);
    285
    286		/* write out risc code */
    287		for (start = 0, skip = 0; start < ov->w.width; start = end) {
    288			if (skip >= nskips) {
    289				ri  = BT848_RISC_WRITE;
    290				end = ov->w.width;
    291			} else if (start < skips[skip].start) {
    292				ri  = BT848_RISC_WRITE;
    293				end = skips[skip].start;
    294			} else {
    295				ri  = BT848_RISC_SKIP;
    296				end = skips[skip].end;
    297				skip++;
    298			}
    299			if (BT848_RISC_WRITE == ri)
    300				ra = addr + (fmt->depth>>3)*start;
    301			else
    302				ra = 0;
    303
    304			if (0 == start)
    305				ri |= BT848_RISC_SOL;
    306			if (ov->w.width == end)
    307				ri |= BT848_RISC_EOL;
    308			ri |= (fmt->depth>>3) * (end-start);
    309
    310			*(rp++)=cpu_to_le32(ri);
    311			if (0 != ra)
    312				*(rp++)=cpu_to_le32(ra);
    313		}
    314	}
    315
    316	/* save pointer to jmp instruction address */
    317	risc->jmp = rp;
    318	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
    319	kfree(skips);
    320	return 0;
    321}
    322
    323/* ---------------------------------------------------------- */
    324
    325static void
    326bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
    327		  int width, int height, int interleaved,
    328		  const struct bttv_tvnorm *tvnorm)
    329{
    330	u32 xsf, sr;
    331	int vdelay;
    332
    333	int swidth       = tvnorm->swidth;
    334	int totalwidth   = tvnorm->totalwidth;
    335	int scaledtwidth = tvnorm->scaledtwidth;
    336
    337	if (btv->input == btv->dig) {
    338		swidth       = 720;
    339		totalwidth   = 858;
    340		scaledtwidth = 858;
    341	}
    342
    343	vdelay = tvnorm->vdelay;
    344
    345	xsf = (width*scaledtwidth)/swidth;
    346	geo->hscale =  ((totalwidth*4096UL)/xsf-4096);
    347	geo->hdelay =  tvnorm->hdelayx1;
    348	geo->hdelay =  (geo->hdelay*width)/swidth;
    349	geo->hdelay &= 0x3fe;
    350	sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
    351	geo->vscale =  (0x10000UL-sr) & 0x1fff;
    352	geo->crop   =  ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
    353		((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
    354	geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
    355	geo->vdelay  =  vdelay;
    356	geo->width   =  width;
    357	geo->sheight =  tvnorm->sheight;
    358	geo->vtotal  =  tvnorm->vtotal;
    359
    360	if (btv->opt_combfilter) {
    361		geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
    362		geo->comb = (width < 769) ? 1 : 0;
    363	} else {
    364		geo->vtc  = 0;
    365		geo->comb = 0;
    366	}
    367}
    368
    369static void
    370bttv_calc_geo		(struct bttv *                  btv,
    371			 struct bttv_geometry *         geo,
    372			 unsigned int                   width,
    373			 unsigned int                   height,
    374			 int                            both_fields,
    375			 const struct bttv_tvnorm *     tvnorm,
    376			 const struct v4l2_rect *       crop)
    377{
    378	unsigned int c_width;
    379	unsigned int c_height;
    380	u32 sr;
    381
    382	if ((crop->left == tvnorm->cropcap.defrect.left
    383	     && crop->top == tvnorm->cropcap.defrect.top
    384	     && crop->width == tvnorm->cropcap.defrect.width
    385	     && crop->height == tvnorm->cropcap.defrect.height
    386	     && width <= tvnorm->swidth /* see PAL-Nc et al */)
    387	    || btv->input == btv->dig) {
    388		bttv_calc_geo_old(btv, geo, width, height,
    389				  both_fields, tvnorm);
    390		return;
    391	}
    392
    393	/* For bug compatibility the image size checks permit scale
    394	   factors > 16. See bttv_crop_calc_limits(). */
    395	c_width = min((unsigned int) crop->width, width * 16);
    396	c_height = min((unsigned int) crop->height, height * 16);
    397
    398	geo->width = width;
    399	geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;
    400	/* Even to store Cb first, odd for Cr. */
    401	geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;
    402
    403	geo->sheight = c_height;
    404	geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
    405	sr = c_height >> !both_fields;
    406	sr = (sr * 512U + (height >> 1)) / height - 512;
    407	geo->vscale = (0x10000UL - sr) & 0x1fff;
    408	geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;
    409	geo->vtotal = tvnorm->vtotal;
    410
    411	geo->crop = (((geo->width   >> 8) & 0x03) |
    412		     ((geo->hdelay  >> 6) & 0x0c) |
    413		     ((geo->sheight >> 4) & 0x30) |
    414		     ((geo->vdelay  >> 2) & 0xc0));
    415
    416	if (btv->opt_combfilter) {
    417		geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
    418		geo->comb = (width < 769) ? 1 : 0;
    419	} else {
    420		geo->vtc  = 0;
    421		geo->comb = 0;
    422	}
    423}
    424
    425static void
    426bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
    427{
    428	int off = odd ? 0x80 : 0x00;
    429
    430	if (geo->comb)
    431		btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
    432	else
    433		btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
    434
    435	btwrite(geo->vtc,             BT848_E_VTC+off);
    436	btwrite(geo->hscale >> 8,     BT848_E_HSCALE_HI+off);
    437	btwrite(geo->hscale & 0xff,   BT848_E_HSCALE_LO+off);
    438	btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
    439	btwrite(geo->vscale & 0xff,   BT848_E_VSCALE_LO+off);
    440	btwrite(geo->width & 0xff,    BT848_E_HACTIVE_LO+off);
    441	btwrite(geo->hdelay & 0xff,   BT848_E_HDELAY_LO+off);
    442	btwrite(geo->sheight & 0xff,  BT848_E_VACTIVE_LO+off);
    443	btwrite(geo->vdelay & 0xff,   BT848_E_VDELAY_LO+off);
    444	btwrite(geo->crop,            BT848_E_CROP+off);
    445	btwrite(geo->vtotal>>8,       BT848_VTOTAL_HI);
    446	btwrite(geo->vtotal & 0xff,   BT848_VTOTAL_LO);
    447}
    448
    449/* ---------------------------------------------------------- */
    450/* risc group / risc main loop / dma management               */
    451
    452void
    453bttv_set_dma(struct bttv *btv, int override)
    454{
    455	unsigned long cmd;
    456	int capctl;
    457
    458	btv->cap_ctl = 0;
    459	if (NULL != btv->curr.top)      btv->cap_ctl |= 0x02;
    460	if (NULL != btv->curr.bottom)   btv->cap_ctl |= 0x01;
    461	if (NULL != btv->cvbi)          btv->cap_ctl |= 0x0c;
    462
    463	capctl  = 0;
    464	capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00;  /* capture  */
    465	capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00;  /* vbi data */
    466	capctl |= override;
    467
    468	d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
    469		 btv->c.nr,capctl,btv->loop_irq,
    470		 btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
    471		 btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
    472		 btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,
    473		 btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
    474
    475	cmd = BT848_RISC_JUMP;
    476	if (btv->loop_irq) {
    477		cmd |= BT848_RISC_IRQ;
    478		cmd |= (btv->loop_irq  & 0x0f) << 16;
    479		cmd |= (~btv->loop_irq & 0x0f) << 20;
    480	}
    481	if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
    482		mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
    483	} else {
    484		del_timer(&btv->timeout);
    485	}
    486	btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
    487
    488	btaor(capctl, ~0x0f, BT848_CAP_CTL);
    489	if (capctl) {
    490		if (btv->dma_on)
    491			return;
    492		btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
    493		btor(3, BT848_GPIO_DMA_CTL);
    494		btv->dma_on = 1;
    495	} else {
    496		if (!btv->dma_on)
    497			return;
    498		btand(~3, BT848_GPIO_DMA_CTL);
    499		btv->dma_on = 0;
    500	}
    501	return;
    502}
    503
    504int
    505bttv_risc_init_main(struct bttv *btv)
    506{
    507	int rc;
    508
    509	if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
    510		return rc;
    511	dprintk("%d: risc main @ %08llx\n",
    512		btv->c.nr, (unsigned long long)btv->main.dma);
    513
    514	btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
    515				       BT848_FIFO_STATUS_VRE);
    516	btv->main.cpu[1] = cpu_to_le32(0);
    517	btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
    518	btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
    519
    520	/* top field */
    521	btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
    522	btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
    523	btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
    524	btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
    525
    526	btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
    527				       BT848_FIFO_STATUS_VRO);
    528	btv->main.cpu[9] = cpu_to_le32(0);
    529
    530	/* bottom field */
    531	btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
    532	btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
    533	btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
    534	btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
    535
    536	/* jump back to top field */
    537	btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
    538	btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
    539
    540	return 0;
    541}
    542
    543int
    544bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
    545	       int irqflags)
    546{
    547	unsigned long cmd;
    548	unsigned long next = btv->main.dma + ((slot+2) << 2);
    549
    550	if (NULL == risc) {
    551		d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
    552		btv->main.cpu[slot+1] = cpu_to_le32(next);
    553	} else {
    554		d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
    555			 btv->c.nr, risc, slot,
    556			 (unsigned long long)risc->dma, irqflags);
    557		cmd = BT848_RISC_JUMP;
    558		if (irqflags) {
    559			cmd |= BT848_RISC_IRQ;
    560			cmd |= (irqflags  & 0x0f) << 16;
    561			cmd |= (~irqflags & 0x0f) << 20;
    562		}
    563		risc->jmp[0] = cpu_to_le32(cmd);
    564		risc->jmp[1] = cpu_to_le32(next);
    565		btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
    566	}
    567	return 0;
    568}
    569
    570void
    571bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
    572{
    573	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
    574
    575	videobuf_waiton(q, &buf->vb, 0, 0);
    576	videobuf_dma_unmap(q->dev, dma);
    577	videobuf_dma_free(dma);
    578	btcx_riscmem_free(btv->c.pci,&buf->bottom);
    579	btcx_riscmem_free(btv->c.pci,&buf->top);
    580	buf->vb.state = VIDEOBUF_NEEDS_INIT;
    581}
    582
    583int
    584bttv_buffer_activate_vbi(struct bttv *btv,
    585			 struct bttv_buffer *vbi)
    586{
    587	struct btcx_riscmem *top;
    588	struct btcx_riscmem *bottom;
    589	int top_irq_flags;
    590	int bottom_irq_flags;
    591
    592	top = NULL;
    593	bottom = NULL;
    594	top_irq_flags = 0;
    595	bottom_irq_flags = 0;
    596
    597	if (vbi) {
    598		unsigned int crop, vdelay;
    599
    600		vbi->vb.state = VIDEOBUF_ACTIVE;
    601		list_del(&vbi->vb.queue);
    602
    603		/* VDELAY is start of video, end of VBI capturing. */
    604		crop = btread(BT848_E_CROP);
    605		vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
    606
    607		if (vbi->geo.vdelay > vdelay) {
    608			vdelay = vbi->geo.vdelay & 0xfe;
    609			crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
    610
    611			btwrite(vdelay, BT848_E_VDELAY_LO);
    612			btwrite(crop,	BT848_E_CROP);
    613			btwrite(vdelay, BT848_O_VDELAY_LO);
    614			btwrite(crop,	BT848_O_CROP);
    615		}
    616
    617		if (vbi->vbi_count[0] > 0) {
    618			top = &vbi->top;
    619			top_irq_flags = 4;
    620		}
    621
    622		if (vbi->vbi_count[1] > 0) {
    623			top_irq_flags = 0;
    624			bottom = &vbi->bottom;
    625			bottom_irq_flags = 4;
    626		}
    627	}
    628
    629	bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
    630	bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
    631
    632	return 0;
    633}
    634
    635int
    636bttv_buffer_activate_video(struct bttv *btv,
    637			   struct bttv_buffer_set *set)
    638{
    639	/* video capture */
    640	if (NULL != set->top  &&  NULL != set->bottom) {
    641		if (set->top == set->bottom) {
    642			set->top->vb.state    = VIDEOBUF_ACTIVE;
    643			if (set->top->vb.queue.next)
    644				list_del(&set->top->vb.queue);
    645		} else {
    646			set->top->vb.state    = VIDEOBUF_ACTIVE;
    647			set->bottom->vb.state = VIDEOBUF_ACTIVE;
    648			if (set->top->vb.queue.next)
    649				list_del(&set->top->vb.queue);
    650			if (set->bottom->vb.queue.next)
    651				list_del(&set->bottom->vb.queue);
    652		}
    653		bttv_apply_geo(btv, &set->top->geo, 1);
    654		bttv_apply_geo(btv, &set->bottom->geo,0);
    655		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
    656			       set->top_irq);
    657		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
    658			       set->frame_irq);
    659		btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
    660		      ~0xff, BT848_COLOR_FMT);
    661		btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
    662		      ~0x0f, BT848_COLOR_CTL);
    663	} else if (NULL != set->top) {
    664		set->top->vb.state  = VIDEOBUF_ACTIVE;
    665		if (set->top->vb.queue.next)
    666			list_del(&set->top->vb.queue);
    667		bttv_apply_geo(btv, &set->top->geo,1);
    668		bttv_apply_geo(btv, &set->top->geo,0);
    669		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
    670			       set->frame_irq);
    671		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,           0);
    672		btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
    673		btaor(set->top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
    674	} else if (NULL != set->bottom) {
    675		set->bottom->vb.state = VIDEOBUF_ACTIVE;
    676		if (set->bottom->vb.queue.next)
    677			list_del(&set->bottom->vb.queue);
    678		bttv_apply_geo(btv, &set->bottom->geo,1);
    679		bttv_apply_geo(btv, &set->bottom->geo,0);
    680		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
    681		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
    682			       set->frame_irq);
    683		btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
    684		btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
    685	} else {
    686		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
    687		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
    688	}
    689	return 0;
    690}
    691
    692/* ---------------------------------------------------------- */
    693
    694/* calculate geometry, build risc code */
    695int
    696bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
    697{
    698	const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
    699	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
    700
    701	dprintk("%d: buffer field: %s  format: 0x%08x  size: %dx%d\n",
    702		btv->c.nr, v4l2_field_names[buf->vb.field],
    703		buf->fmt->fourcc, buf->vb.width, buf->vb.height);
    704
    705	/* packed pixel modes */
    706	if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
    707		int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
    708		int bpf = bpl * (buf->vb.height >> 1);
    709
    710		bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
    711			      V4L2_FIELD_HAS_BOTH(buf->vb.field),
    712			      tvnorm,&buf->crop);
    713
    714		switch (buf->vb.field) {
    715		case V4L2_FIELD_TOP:
    716			bttv_risc_packed(btv,&buf->top,dma->sglist,
    717					 /* offset */ 0,bpl,
    718					 /* padding */ 0,/* skip_lines */ 0,
    719					 buf->vb.height);
    720			break;
    721		case V4L2_FIELD_BOTTOM:
    722			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
    723					 0,bpl,0,0,buf->vb.height);
    724			break;
    725		case V4L2_FIELD_INTERLACED:
    726			bttv_risc_packed(btv,&buf->top,dma->sglist,
    727					 0,bpl,bpl,0,buf->vb.height >> 1);
    728			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
    729					 bpl,bpl,bpl,0,buf->vb.height >> 1);
    730			break;
    731		case V4L2_FIELD_SEQ_TB:
    732			bttv_risc_packed(btv,&buf->top,dma->sglist,
    733					 0,bpl,0,0,buf->vb.height >> 1);
    734			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
    735					 bpf,bpl,0,0,buf->vb.height >> 1);
    736			break;
    737		default:
    738			BUG();
    739		}
    740	}
    741
    742	/* planar modes */
    743	if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
    744		int uoffset, voffset;
    745		int ypadding, cpadding, lines;
    746
    747		/* calculate chroma offsets */
    748		uoffset = buf->vb.width * buf->vb.height;
    749		voffset = buf->vb.width * buf->vb.height;
    750		if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
    751			/* Y-Cr-Cb plane order */
    752			uoffset >>= buf->fmt->hshift;
    753			uoffset >>= buf->fmt->vshift;
    754			uoffset  += voffset;
    755		} else {
    756			/* Y-Cb-Cr plane order */
    757			voffset >>= buf->fmt->hshift;
    758			voffset >>= buf->fmt->vshift;
    759			voffset  += uoffset;
    760		}
    761
    762		switch (buf->vb.field) {
    763		case V4L2_FIELD_TOP:
    764			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
    765				      buf->vb.height,/* both_fields */ 0,
    766				      tvnorm,&buf->crop);
    767			bttv_risc_planar(btv, &buf->top, dma->sglist,
    768					 0,buf->vb.width,0,buf->vb.height,
    769					 uoffset,voffset,buf->fmt->hshift,
    770					 buf->fmt->vshift,0);
    771			break;
    772		case V4L2_FIELD_BOTTOM:
    773			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
    774				      buf->vb.height,0,
    775				      tvnorm,&buf->crop);
    776			bttv_risc_planar(btv, &buf->bottom, dma->sglist,
    777					 0,buf->vb.width,0,buf->vb.height,
    778					 uoffset,voffset,buf->fmt->hshift,
    779					 buf->fmt->vshift,0);
    780			break;
    781		case V4L2_FIELD_INTERLACED:
    782			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
    783				      buf->vb.height,1,
    784				      tvnorm,&buf->crop);
    785			lines    = buf->vb.height >> 1;
    786			ypadding = buf->vb.width;
    787			cpadding = buf->vb.width >> buf->fmt->hshift;
    788			bttv_risc_planar(btv,&buf->top,
    789					 dma->sglist,
    790					 0,buf->vb.width,ypadding,lines,
    791					 uoffset,voffset,
    792					 buf->fmt->hshift,
    793					 buf->fmt->vshift,
    794					 cpadding);
    795			bttv_risc_planar(btv,&buf->bottom,
    796					 dma->sglist,
    797					 ypadding,buf->vb.width,ypadding,lines,
    798					 uoffset+cpadding,
    799					 voffset+cpadding,
    800					 buf->fmt->hshift,
    801					 buf->fmt->vshift,
    802					 cpadding);
    803			break;
    804		case V4L2_FIELD_SEQ_TB:
    805			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
    806				      buf->vb.height,1,
    807				      tvnorm,&buf->crop);
    808			lines    = buf->vb.height >> 1;
    809			ypadding = buf->vb.width;
    810			cpadding = buf->vb.width >> buf->fmt->hshift;
    811			bttv_risc_planar(btv,&buf->top,
    812					 dma->sglist,
    813					 0,buf->vb.width,0,lines,
    814					 uoffset >> 1,
    815					 voffset >> 1,
    816					 buf->fmt->hshift,
    817					 buf->fmt->vshift,
    818					 0);
    819			bttv_risc_planar(btv,&buf->bottom,
    820					 dma->sglist,
    821					 lines * ypadding,buf->vb.width,0,lines,
    822					 lines * ypadding + (uoffset >> 1),
    823					 lines * ypadding + (voffset >> 1),
    824					 buf->fmt->hshift,
    825					 buf->fmt->vshift,
    826					 0);
    827			break;
    828		default:
    829			BUG();
    830		}
    831	}
    832
    833	/* raw data */
    834	if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
    835		/* build risc code */
    836		buf->vb.field = V4L2_FIELD_SEQ_TB;
    837		bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
    838			      1,tvnorm,&buf->crop);
    839		bttv_risc_packed(btv, &buf->top,  dma->sglist,
    840				 /* offset */ 0, RAW_BPL, /* padding */ 0,
    841				 /* skip_lines */ 0, RAW_LINES);
    842		bttv_risc_packed(btv, &buf->bottom, dma->sglist,
    843				 buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
    844	}
    845
    846	/* copy format info */
    847	buf->btformat = buf->fmt->btformat;
    848	buf->btswap   = buf->fmt->btswap;
    849	return 0;
    850}
    851
    852/* ---------------------------------------------------------- */
    853
    854/* calculate geometry, build risc code */
    855int
    856bttv_overlay_risc(struct bttv *btv,
    857		  struct bttv_overlay *ov,
    858		  const struct bttv_format *fmt,
    859		  struct bttv_buffer *buf)
    860{
    861	/* check interleave, bottom+top fields */
    862	dprintk("%d: overlay fields: %s format: 0x%08x  size: %dx%d\n",
    863		btv->c.nr, v4l2_field_names[buf->vb.field],
    864		fmt->fourcc, ov->w.width, ov->w.height);
    865
    866	/* calculate geometry */
    867	bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
    868		      V4L2_FIELD_HAS_BOTH(ov->field),
    869		      &bttv_tvnorms[ov->tvnorm],&buf->crop);
    870
    871	/* build risc code */
    872	switch (ov->field) {
    873	case V4L2_FIELD_TOP:
    874		bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 0);
    875		break;
    876	case V4L2_FIELD_BOTTOM:
    877		bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
    878		break;
    879	case V4L2_FIELD_INTERLACED:
    880		bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 1);
    881		bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
    882		break;
    883	default:
    884		BUG();
    885	}
    886
    887	/* copy format info */
    888	buf->btformat = fmt->btformat;
    889	buf->btswap   = fmt->btswap;
    890	buf->vb.field = ov->field;
    891	return 0;
    892}