174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
268de959fSMauro Carvalho Chehab /*
368de959fSMauro Carvalho Chehab 
468de959fSMauro Carvalho Chehab     bttv-risc.c  --  interfaces to other kernel modules
568de959fSMauro Carvalho Chehab 
668de959fSMauro Carvalho Chehab     bttv risc code handling
768de959fSMauro Carvalho Chehab 	- memory management
868de959fSMauro Carvalho Chehab 	- generation
968de959fSMauro Carvalho Chehab 
1068de959fSMauro Carvalho Chehab     (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org>
1168de959fSMauro Carvalho Chehab 
1268de959fSMauro Carvalho Chehab 
1368de959fSMauro Carvalho Chehab */
1468de959fSMauro Carvalho Chehab 
1568de959fSMauro Carvalho Chehab #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1668de959fSMauro Carvalho Chehab 
1768de959fSMauro Carvalho Chehab #include <linux/module.h>
1868de959fSMauro Carvalho Chehab #include <linux/init.h>
1968de959fSMauro Carvalho Chehab #include <linux/slab.h>
2068de959fSMauro Carvalho Chehab #include <linux/pci.h>
2168de959fSMauro Carvalho Chehab #include <linux/vmalloc.h>
2268de959fSMauro Carvalho Chehab #include <linux/interrupt.h>
2368de959fSMauro Carvalho Chehab #include <asm/page.h>
2468de959fSMauro Carvalho Chehab #include <asm/pgtable.h>
2568de959fSMauro Carvalho Chehab #include <media/v4l2-ioctl.h>
2668de959fSMauro Carvalho Chehab 
2768de959fSMauro Carvalho Chehab #include "bttvp.h"
2868de959fSMauro Carvalho Chehab 
2968de959fSMauro Carvalho Chehab #define VCR_HACK_LINES 4
3068de959fSMauro Carvalho Chehab 
3168de959fSMauro Carvalho Chehab /* ---------------------------------------------------------- */
3268de959fSMauro Carvalho Chehab /* risc code generators                                       */
3368de959fSMauro Carvalho Chehab 
3468de959fSMauro Carvalho Chehab int
3568de959fSMauro Carvalho Chehab bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
3668de959fSMauro Carvalho Chehab 		 struct scatterlist *sglist,
3768de959fSMauro Carvalho Chehab 		 unsigned int offset, unsigned int bpl,
3868de959fSMauro Carvalho Chehab 		 unsigned int padding, unsigned int skip_lines,
3968de959fSMauro Carvalho Chehab 		 unsigned int store_lines)
4068de959fSMauro Carvalho Chehab {
4168de959fSMauro Carvalho Chehab 	u32 instructions,line,todo;
4268de959fSMauro Carvalho Chehab 	struct scatterlist *sg;
4368de959fSMauro Carvalho Chehab 	__le32 *rp;
4468de959fSMauro Carvalho Chehab 	int rc;
4568de959fSMauro Carvalho Chehab 
4668de959fSMauro Carvalho Chehab 	/* estimate risc mem: worst case is one write per page border +
4768de959fSMauro Carvalho Chehab 	   one write per scan line + sync + jump (all 2 dwords).  padding
4868de959fSMauro Carvalho Chehab 	   can cause next bpl to start close to a page border.  First DMA
4968de959fSMauro Carvalho Chehab 	   region may be smaller than PAGE_SIZE */
5068de959fSMauro Carvalho Chehab 	instructions  = skip_lines * 4;
5168de959fSMauro Carvalho Chehab 	instructions += (1 + ((bpl + padding) * store_lines)
5268de959fSMauro Carvalho Chehab 			 / PAGE_SIZE + store_lines) * 8;
5368de959fSMauro Carvalho Chehab 	instructions += 2 * 8;
5468de959fSMauro Carvalho Chehab 	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions)) < 0)
5568de959fSMauro Carvalho Chehab 		return rc;
5668de959fSMauro Carvalho Chehab 
5768de959fSMauro Carvalho Chehab 	/* sync instruction */
5868de959fSMauro Carvalho Chehab 	rp = risc->cpu;
5968de959fSMauro Carvalho Chehab 	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
6068de959fSMauro Carvalho Chehab 	*(rp++) = cpu_to_le32(0);
6168de959fSMauro Carvalho Chehab 
6268de959fSMauro Carvalho Chehab 	while (skip_lines-- > 0) {
6368de959fSMauro Carvalho Chehab 		*(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |
6468de959fSMauro Carvalho Chehab 				      BT848_RISC_EOL | bpl);
6568de959fSMauro Carvalho Chehab 	}
6668de959fSMauro Carvalho Chehab 
6768de959fSMauro Carvalho Chehab 	/* scan lines */
6868de959fSMauro Carvalho Chehab 	sg = sglist;
6968de959fSMauro Carvalho Chehab 	for (line = 0; line < store_lines; line++) {
7068de959fSMauro Carvalho Chehab 		if ((btv->opt_vcr_hack) &&
7168de959fSMauro Carvalho Chehab 		    (line >= (store_lines - VCR_HACK_LINES)))
7268de959fSMauro Carvalho Chehab 			continue;
7368de959fSMauro Carvalho Chehab 		while (offset && offset >= sg_dma_len(sg)) {
7468de959fSMauro Carvalho Chehab 			offset -= sg_dma_len(sg);
75872dfcfeSHans Verkuil 			sg = sg_next(sg);
7668de959fSMauro Carvalho Chehab 		}
7768de959fSMauro Carvalho Chehab 		if (bpl <= sg_dma_len(sg)-offset) {
7868de959fSMauro Carvalho Chehab 			/* fits into current chunk */
7968de959fSMauro Carvalho Chehab 			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
8068de959fSMauro Carvalho Chehab 					    BT848_RISC_EOL|bpl);
8168de959fSMauro Carvalho Chehab 			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
8268de959fSMauro Carvalho Chehab 			offset+=bpl;
8368de959fSMauro Carvalho Chehab 		} else {
8416790554SMauro Carvalho Chehab 			/* scanline needs to be split */
8568de959fSMauro Carvalho Chehab 			todo = bpl;
8668de959fSMauro Carvalho Chehab 			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
8768de959fSMauro Carvalho Chehab 					    (sg_dma_len(sg)-offset));
8868de959fSMauro Carvalho Chehab 			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
8968de959fSMauro Carvalho Chehab 			todo -= (sg_dma_len(sg)-offset);
9068de959fSMauro Carvalho Chehab 			offset = 0;
91872dfcfeSHans Verkuil 			sg = sg_next(sg);
9268de959fSMauro Carvalho Chehab 			while (todo > sg_dma_len(sg)) {
9368de959fSMauro Carvalho Chehab 				*(rp++)=cpu_to_le32(BT848_RISC_WRITE|
9468de959fSMauro Carvalho Chehab 						    sg_dma_len(sg));
9568de959fSMauro Carvalho Chehab 				*(rp++)=cpu_to_le32(sg_dma_address(sg));
9668de959fSMauro Carvalho Chehab 				todo -= sg_dma_len(sg);
97872dfcfeSHans Verkuil 				sg = sg_next(sg);
9868de959fSMauro Carvalho Chehab 			}
9968de959fSMauro Carvalho Chehab 			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
10068de959fSMauro Carvalho Chehab 					    todo);
10168de959fSMauro Carvalho Chehab 			*(rp++)=cpu_to_le32(sg_dma_address(sg));
10268de959fSMauro Carvalho Chehab 			offset += todo;
10368de959fSMauro Carvalho Chehab 		}
10468de959fSMauro Carvalho Chehab 		offset += padding;
10568de959fSMauro Carvalho Chehab 	}
10668de959fSMauro Carvalho Chehab 
10768de959fSMauro Carvalho Chehab 	/* save pointer to jmp instruction address */
10868de959fSMauro Carvalho Chehab 	risc->jmp = rp;
10968de959fSMauro Carvalho Chehab 	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
11068de959fSMauro Carvalho Chehab 	return 0;
11168de959fSMauro Carvalho Chehab }
11268de959fSMauro Carvalho Chehab 
11368de959fSMauro Carvalho Chehab static int
11468de959fSMauro Carvalho Chehab bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
11568de959fSMauro Carvalho Chehab 		 struct scatterlist *sglist,
11668de959fSMauro Carvalho Chehab 		 unsigned int yoffset,  unsigned int ybpl,
11768de959fSMauro Carvalho Chehab 		 unsigned int ypadding, unsigned int ylines,
11868de959fSMauro Carvalho Chehab 		 unsigned int uoffset,  unsigned int voffset,
11968de959fSMauro Carvalho Chehab 		 unsigned int hshift,   unsigned int vshift,
12068de959fSMauro Carvalho Chehab 		 unsigned int cpadding)
12168de959fSMauro Carvalho Chehab {
12268de959fSMauro Carvalho Chehab 	unsigned int instructions,line,todo,ylen,chroma;
12368de959fSMauro Carvalho Chehab 	__le32 *rp;
12468de959fSMauro Carvalho Chehab 	u32 ri;
12568de959fSMauro Carvalho Chehab 	struct scatterlist *ysg;
12668de959fSMauro Carvalho Chehab 	struct scatterlist *usg;
12768de959fSMauro Carvalho Chehab 	struct scatterlist *vsg;
12868de959fSMauro Carvalho Chehab 	int topfield = (0 == yoffset);
12968de959fSMauro Carvalho Chehab 	int rc;
13068de959fSMauro Carvalho Chehab 
13168de959fSMauro Carvalho Chehab 	/* estimate risc mem: worst case is one write per page border +
13268de959fSMauro Carvalho Chehab 	   one write per scan line (5 dwords)
13368de959fSMauro Carvalho Chehab 	   plus sync + jump (2 dwords) */
13468de959fSMauro Carvalho Chehab 	instructions  = ((3 + (ybpl + ypadding) * ylines * 2)
13568de959fSMauro Carvalho Chehab 			 / PAGE_SIZE) + ylines;
13668de959fSMauro Carvalho Chehab 	instructions += 2;
13768de959fSMauro Carvalho Chehab 	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
13868de959fSMauro Carvalho Chehab 		return rc;
13968de959fSMauro Carvalho Chehab 
14068de959fSMauro Carvalho Chehab 	/* sync instruction */
14168de959fSMauro Carvalho Chehab 	rp = risc->cpu;
14268de959fSMauro Carvalho Chehab 	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
14368de959fSMauro Carvalho Chehab 	*(rp++) = cpu_to_le32(0);
14468de959fSMauro Carvalho Chehab 
14568de959fSMauro Carvalho Chehab 	/* scan lines */
14668de959fSMauro Carvalho Chehab 	ysg = sglist;
14768de959fSMauro Carvalho Chehab 	usg = sglist;
14868de959fSMauro Carvalho Chehab 	vsg = sglist;
14968de959fSMauro Carvalho Chehab 	for (line = 0; line < ylines; line++) {
15068de959fSMauro Carvalho Chehab 		if ((btv->opt_vcr_hack) &&
15168de959fSMauro Carvalho Chehab 		    (line >= (ylines - VCR_HACK_LINES)))
15268de959fSMauro Carvalho Chehab 			continue;
15368de959fSMauro Carvalho Chehab 		switch (vshift) {
15468de959fSMauro Carvalho Chehab 		case 0:
15568de959fSMauro Carvalho Chehab 			chroma = 1;
15668de959fSMauro Carvalho Chehab 			break;
15768de959fSMauro Carvalho Chehab 		case 1:
15868de959fSMauro Carvalho Chehab 			if (topfield)
15968de959fSMauro Carvalho Chehab 				chroma = ((line & 1) == 0);
16068de959fSMauro Carvalho Chehab 			else
16168de959fSMauro Carvalho Chehab 				chroma = ((line & 1) == 1);
16268de959fSMauro Carvalho Chehab 			break;
16368de959fSMauro Carvalho Chehab 		case 2:
16468de959fSMauro Carvalho Chehab 			if (topfield)
16568de959fSMauro Carvalho Chehab 				chroma = ((line & 3) == 0);
16668de959fSMauro Carvalho Chehab 			else
16768de959fSMauro Carvalho Chehab 				chroma = ((line & 3) == 2);
16868de959fSMauro Carvalho Chehab 			break;
16968de959fSMauro Carvalho Chehab 		default:
17068de959fSMauro Carvalho Chehab 			chroma = 0;
17168de959fSMauro Carvalho Chehab 			break;
17268de959fSMauro Carvalho Chehab 		}
17368de959fSMauro Carvalho Chehab 
17468de959fSMauro Carvalho Chehab 		for (todo = ybpl; todo > 0; todo -= ylen) {
17568de959fSMauro Carvalho Chehab 			/* go to next sg entry if needed */
17668de959fSMauro Carvalho Chehab 			while (yoffset && yoffset >= sg_dma_len(ysg)) {
17768de959fSMauro Carvalho Chehab 				yoffset -= sg_dma_len(ysg);
178872dfcfeSHans Verkuil 				ysg = sg_next(ysg);
17968de959fSMauro Carvalho Chehab 			}
1806f7e780bSSamuel Williams 
1816f7e780bSSamuel Williams 			/* calculate max number of bytes we can write */
1826f7e780bSSamuel Williams 			ylen = todo;
1836f7e780bSSamuel Williams 			if (yoffset + ylen > sg_dma_len(ysg))
1846f7e780bSSamuel Williams 				ylen = sg_dma_len(ysg) - yoffset;
1856f7e780bSSamuel Williams 			if (chroma) {
18668de959fSMauro Carvalho Chehab 				while (uoffset && uoffset >= sg_dma_len(usg)) {
18768de959fSMauro Carvalho Chehab 					uoffset -= sg_dma_len(usg);
188872dfcfeSHans Verkuil 					usg = sg_next(usg);
18968de959fSMauro Carvalho Chehab 				}
19068de959fSMauro Carvalho Chehab 				while (voffset && voffset >= sg_dma_len(vsg)) {
19168de959fSMauro Carvalho Chehab 					voffset -= sg_dma_len(vsg);
192872dfcfeSHans Verkuil 					vsg = sg_next(vsg);
19368de959fSMauro Carvalho Chehab 				}
19468de959fSMauro Carvalho Chehab 
19568de959fSMauro Carvalho Chehab 				if (uoffset + (ylen>>hshift) > sg_dma_len(usg))
19668de959fSMauro Carvalho Chehab 					ylen = (sg_dma_len(usg) - uoffset) << hshift;
19768de959fSMauro Carvalho Chehab 				if (voffset + (ylen>>hshift) > sg_dma_len(vsg))
19868de959fSMauro Carvalho Chehab 					ylen = (sg_dma_len(vsg) - voffset) << hshift;
19968de959fSMauro Carvalho Chehab 				ri = BT848_RISC_WRITE123;
20068de959fSMauro Carvalho Chehab 			} else {
20168de959fSMauro Carvalho Chehab 				ri = BT848_RISC_WRITE1S23;
20268de959fSMauro Carvalho Chehab 			}
20368de959fSMauro Carvalho Chehab 			if (ybpl == todo)
20468de959fSMauro Carvalho Chehab 				ri |= BT848_RISC_SOL;
20568de959fSMauro Carvalho Chehab 			if (ylen == todo)
20668de959fSMauro Carvalho Chehab 				ri |= BT848_RISC_EOL;
20768de959fSMauro Carvalho Chehab 
20868de959fSMauro Carvalho Chehab 			/* write risc instruction */
20968de959fSMauro Carvalho Chehab 			*(rp++)=cpu_to_le32(ri | ylen);
21068de959fSMauro Carvalho Chehab 			*(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
21168de959fSMauro Carvalho Chehab 					    (ylen >> hshift));
21268de959fSMauro Carvalho Chehab 			*(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
21368de959fSMauro Carvalho Chehab 			yoffset += ylen;
21468de959fSMauro Carvalho Chehab 			if (chroma) {
21568de959fSMauro Carvalho Chehab 				*(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);
21668de959fSMauro Carvalho Chehab 				uoffset += ylen >> hshift;
21768de959fSMauro Carvalho Chehab 				*(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);
21868de959fSMauro Carvalho Chehab 				voffset += ylen >> hshift;
21968de959fSMauro Carvalho Chehab 			}
22068de959fSMauro Carvalho Chehab 		}
22168de959fSMauro Carvalho Chehab 		yoffset += ypadding;
22268de959fSMauro Carvalho Chehab 		if (chroma) {
22368de959fSMauro Carvalho Chehab 			uoffset += cpadding;
22468de959fSMauro Carvalho Chehab 			voffset += cpadding;
22568de959fSMauro Carvalho Chehab 		}
22668de959fSMauro Carvalho Chehab 	}
22768de959fSMauro Carvalho Chehab 
22868de959fSMauro Carvalho Chehab 	/* save pointer to jmp instruction address */
22968de959fSMauro Carvalho Chehab 	risc->jmp = rp;
23068de959fSMauro Carvalho Chehab 	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
23168de959fSMauro Carvalho Chehab 	return 0;
23268de959fSMauro Carvalho Chehab }
23368de959fSMauro Carvalho Chehab 
23468de959fSMauro Carvalho Chehab static int
23568de959fSMauro Carvalho Chehab bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
23668de959fSMauro Carvalho Chehab 		  const struct bttv_format *fmt, struct bttv_overlay *ov,
23768de959fSMauro Carvalho Chehab 		  int skip_even, int skip_odd)
23868de959fSMauro Carvalho Chehab {
23968de959fSMauro Carvalho Chehab 	int dwords, rc, line, maxy, start, end;
24068de959fSMauro Carvalho Chehab 	unsigned skip, nskips;
24168de959fSMauro Carvalho Chehab 	struct btcx_skiplist *skips;
24268de959fSMauro Carvalho Chehab 	__le32 *rp;
24368de959fSMauro Carvalho Chehab 	u32 ri,ra;
24468de959fSMauro Carvalho Chehab 	u32 addr;
24568de959fSMauro Carvalho Chehab 
24668de959fSMauro Carvalho Chehab 	/* skip list for window clipping */
2476da2ec56SKees Cook 	skips = kmalloc_array(ov->nclips, sizeof(*skips),GFP_KERNEL);
2486da2ec56SKees Cook 	if (NULL == skips)
24968de959fSMauro Carvalho Chehab 		return -ENOMEM;
25068de959fSMauro Carvalho Chehab 
25168de959fSMauro Carvalho Chehab 	/* estimate risc mem: worst case is (1.5*clip+1) * lines instructions
25268de959fSMauro Carvalho Chehab 	   + sync + jump (all 2 dwords) */
25368de959fSMauro Carvalho Chehab 	dwords  = (3 * ov->nclips + 2) *
25468de959fSMauro Carvalho Chehab 		((skip_even || skip_odd) ? (ov->w.height+1)>>1 :  ov->w.height);
25568de959fSMauro Carvalho Chehab 	dwords += 4;
25668de959fSMauro Carvalho Chehab 	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,dwords*4)) < 0) {
25768de959fSMauro Carvalho Chehab 		kfree(skips);
25868de959fSMauro Carvalho Chehab 		return rc;
25968de959fSMauro Carvalho Chehab 	}
26068de959fSMauro Carvalho Chehab 
26168de959fSMauro Carvalho Chehab 	/* sync instruction */
26268de959fSMauro Carvalho Chehab 	rp = risc->cpu;
26368de959fSMauro Carvalho Chehab 	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
26468de959fSMauro Carvalho Chehab 	*(rp++) = cpu_to_le32(0);
26568de959fSMauro Carvalho Chehab 
26668de959fSMauro Carvalho Chehab 	addr  = (unsigned long)btv->fbuf.base;
26768de959fSMauro Carvalho Chehab 	addr += btv->fbuf.fmt.bytesperline * ov->w.top;
26868de959fSMauro Carvalho Chehab 	addr += (fmt->depth >> 3)          * ov->w.left;
26968de959fSMauro Carvalho Chehab 
27068de959fSMauro Carvalho Chehab 	/* scan lines */
27168de959fSMauro Carvalho Chehab 	for (maxy = -1, line = 0; line < ov->w.height;
27268de959fSMauro Carvalho Chehab 	     line++, addr += btv->fbuf.fmt.bytesperline) {
27368de959fSMauro Carvalho Chehab 		if ((btv->opt_vcr_hack) &&
27468de959fSMauro Carvalho Chehab 		     (line >= (ov->w.height - VCR_HACK_LINES)))
27568de959fSMauro Carvalho Chehab 			continue;
27668de959fSMauro Carvalho Chehab 		if ((line%2) == 0  &&  skip_even)
27768de959fSMauro Carvalho Chehab 			continue;
27868de959fSMauro Carvalho Chehab 		if ((line%2) == 1  &&  skip_odd)
27968de959fSMauro Carvalho Chehab 			continue;
28068de959fSMauro Carvalho Chehab 
28168de959fSMauro Carvalho Chehab 		/* calculate clipping */
28268de959fSMauro Carvalho Chehab 		if (line > maxy)
28368de959fSMauro Carvalho Chehab 			btcx_calc_skips(line, ov->w.width, &maxy,
28468de959fSMauro Carvalho Chehab 					skips, &nskips, ov->clips, ov->nclips);
28568de959fSMauro Carvalho Chehab 
28668de959fSMauro Carvalho Chehab 		/* write out risc code */
28768de959fSMauro Carvalho Chehab 		for (start = 0, skip = 0; start < ov->w.width; start = end) {
28868de959fSMauro Carvalho Chehab 			if (skip >= nskips) {
28968de959fSMauro Carvalho Chehab 				ri  = BT848_RISC_WRITE;
29068de959fSMauro Carvalho Chehab 				end = ov->w.width;
29168de959fSMauro Carvalho Chehab 			} else if (start < skips[skip].start) {
29268de959fSMauro Carvalho Chehab 				ri  = BT848_RISC_WRITE;
29368de959fSMauro Carvalho Chehab 				end = skips[skip].start;
29468de959fSMauro Carvalho Chehab 			} else {
29568de959fSMauro Carvalho Chehab 				ri  = BT848_RISC_SKIP;
29668de959fSMauro Carvalho Chehab 				end = skips[skip].end;
29768de959fSMauro Carvalho Chehab 				skip++;
29868de959fSMauro Carvalho Chehab 			}
29968de959fSMauro Carvalho Chehab 			if (BT848_RISC_WRITE == ri)
30068de959fSMauro Carvalho Chehab 				ra = addr + (fmt->depth>>3)*start;
30168de959fSMauro Carvalho Chehab 			else
30268de959fSMauro Carvalho Chehab 				ra = 0;
30368de959fSMauro Carvalho Chehab 
30468de959fSMauro Carvalho Chehab 			if (0 == start)
30568de959fSMauro Carvalho Chehab 				ri |= BT848_RISC_SOL;
30668de959fSMauro Carvalho Chehab 			if (ov->w.width == end)
30768de959fSMauro Carvalho Chehab 				ri |= BT848_RISC_EOL;
30868de959fSMauro Carvalho Chehab 			ri |= (fmt->depth>>3) * (end-start);
30968de959fSMauro Carvalho Chehab 
31068de959fSMauro Carvalho Chehab 			*(rp++)=cpu_to_le32(ri);
31168de959fSMauro Carvalho Chehab 			if (0 != ra)
31268de959fSMauro Carvalho Chehab 				*(rp++)=cpu_to_le32(ra);
31368de959fSMauro Carvalho Chehab 		}
31468de959fSMauro Carvalho Chehab 	}
31568de959fSMauro Carvalho Chehab 
31668de959fSMauro Carvalho Chehab 	/* save pointer to jmp instruction address */
31768de959fSMauro Carvalho Chehab 	risc->jmp = rp;
31868de959fSMauro Carvalho Chehab 	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
31968de959fSMauro Carvalho Chehab 	kfree(skips);
32068de959fSMauro Carvalho Chehab 	return 0;
32168de959fSMauro Carvalho Chehab }
32268de959fSMauro Carvalho Chehab 
32368de959fSMauro Carvalho Chehab /* ---------------------------------------------------------- */
32468de959fSMauro Carvalho Chehab 
32568de959fSMauro Carvalho Chehab static void
32668de959fSMauro Carvalho Chehab bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
32768de959fSMauro Carvalho Chehab 		  int width, int height, int interleaved,
32868de959fSMauro Carvalho Chehab 		  const struct bttv_tvnorm *tvnorm)
32968de959fSMauro Carvalho Chehab {
33068de959fSMauro Carvalho Chehab 	u32 xsf, sr;
33168de959fSMauro Carvalho Chehab 	int vdelay;
33268de959fSMauro Carvalho Chehab 
33368de959fSMauro Carvalho Chehab 	int swidth       = tvnorm->swidth;
33468de959fSMauro Carvalho Chehab 	int totalwidth   = tvnorm->totalwidth;
33568de959fSMauro Carvalho Chehab 	int scaledtwidth = tvnorm->scaledtwidth;
33668de959fSMauro Carvalho Chehab 
33768de959fSMauro Carvalho Chehab 	if (btv->input == btv->dig) {
33868de959fSMauro Carvalho Chehab 		swidth       = 720;
33968de959fSMauro Carvalho Chehab 		totalwidth   = 858;
34068de959fSMauro Carvalho Chehab 		scaledtwidth = 858;
34168de959fSMauro Carvalho Chehab 	}
34268de959fSMauro Carvalho Chehab 
34368de959fSMauro Carvalho Chehab 	vdelay = tvnorm->vdelay;
34468de959fSMauro Carvalho Chehab 
34568de959fSMauro Carvalho Chehab 	xsf = (width*scaledtwidth)/swidth;
34668de959fSMauro Carvalho Chehab 	geo->hscale =  ((totalwidth*4096UL)/xsf-4096);
34768de959fSMauro Carvalho Chehab 	geo->hdelay =  tvnorm->hdelayx1;
34868de959fSMauro Carvalho Chehab 	geo->hdelay =  (geo->hdelay*width)/swidth;
34968de959fSMauro Carvalho Chehab 	geo->hdelay &= 0x3fe;
35068de959fSMauro Carvalho Chehab 	sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
35168de959fSMauro Carvalho Chehab 	geo->vscale =  (0x10000UL-sr) & 0x1fff;
35268de959fSMauro Carvalho Chehab 	geo->crop   =  ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
35368de959fSMauro Carvalho Chehab 		((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
35468de959fSMauro Carvalho Chehab 	geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
35568de959fSMauro Carvalho Chehab 	geo->vdelay  =  vdelay;
35668de959fSMauro Carvalho Chehab 	geo->width   =  width;
35768de959fSMauro Carvalho Chehab 	geo->sheight =  tvnorm->sheight;
35868de959fSMauro Carvalho Chehab 	geo->vtotal  =  tvnorm->vtotal;
35968de959fSMauro Carvalho Chehab 
36068de959fSMauro Carvalho Chehab 	if (btv->opt_combfilter) {
36168de959fSMauro Carvalho Chehab 		geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
36268de959fSMauro Carvalho Chehab 		geo->comb = (width < 769) ? 1 : 0;
36368de959fSMauro Carvalho Chehab 	} else {
36468de959fSMauro Carvalho Chehab 		geo->vtc  = 0;
36568de959fSMauro Carvalho Chehab 		geo->comb = 0;
36668de959fSMauro Carvalho Chehab 	}
36768de959fSMauro Carvalho Chehab }
36868de959fSMauro Carvalho Chehab 
36968de959fSMauro Carvalho Chehab static void
37068de959fSMauro Carvalho Chehab bttv_calc_geo		(struct bttv *                  btv,
37168de959fSMauro Carvalho Chehab 			 struct bttv_geometry *         geo,
37268de959fSMauro Carvalho Chehab 			 unsigned int                   width,
37368de959fSMauro Carvalho Chehab 			 unsigned int                   height,
37468de959fSMauro Carvalho Chehab 			 int                            both_fields,
37568de959fSMauro Carvalho Chehab 			 const struct bttv_tvnorm *     tvnorm,
37668de959fSMauro Carvalho Chehab 			 const struct v4l2_rect *       crop)
37768de959fSMauro Carvalho Chehab {
37868de959fSMauro Carvalho Chehab 	unsigned int c_width;
37968de959fSMauro Carvalho Chehab 	unsigned int c_height;
38068de959fSMauro Carvalho Chehab 	u32 sr;
38168de959fSMauro Carvalho Chehab 
38268de959fSMauro Carvalho Chehab 	if ((crop->left == tvnorm->cropcap.defrect.left
38368de959fSMauro Carvalho Chehab 	     && crop->top == tvnorm->cropcap.defrect.top
38468de959fSMauro Carvalho Chehab 	     && crop->width == tvnorm->cropcap.defrect.width
38568de959fSMauro Carvalho Chehab 	     && crop->height == tvnorm->cropcap.defrect.height
38668de959fSMauro Carvalho Chehab 	     && width <= tvnorm->swidth /* see PAL-Nc et al */)
38768de959fSMauro Carvalho Chehab 	    || btv->input == btv->dig) {
38868de959fSMauro Carvalho Chehab 		bttv_calc_geo_old(btv, geo, width, height,
38968de959fSMauro Carvalho Chehab 				  both_fields, tvnorm);
39068de959fSMauro Carvalho Chehab 		return;
39168de959fSMauro Carvalho Chehab 	}
39268de959fSMauro Carvalho Chehab 
39368de959fSMauro Carvalho Chehab 	/* For bug compatibility the image size checks permit scale
39468de959fSMauro Carvalho Chehab 	   factors > 16. See bttv_crop_calc_limits(). */
39568de959fSMauro Carvalho Chehab 	c_width = min((unsigned int) crop->width, width * 16);
39668de959fSMauro Carvalho Chehab 	c_height = min((unsigned int) crop->height, height * 16);
39768de959fSMauro Carvalho Chehab 
39868de959fSMauro Carvalho Chehab 	geo->width = width;
39968de959fSMauro Carvalho Chehab 	geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;
40068de959fSMauro Carvalho Chehab 	/* Even to store Cb first, odd for Cr. */
40168de959fSMauro Carvalho Chehab 	geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;
40268de959fSMauro Carvalho Chehab 
40368de959fSMauro Carvalho Chehab 	geo->sheight = c_height;
40468de959fSMauro Carvalho Chehab 	geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
40568de959fSMauro Carvalho Chehab 	sr = c_height >> !both_fields;
40668de959fSMauro Carvalho Chehab 	sr = (sr * 512U + (height >> 1)) / height - 512;
40768de959fSMauro Carvalho Chehab 	geo->vscale = (0x10000UL - sr) & 0x1fff;
40868de959fSMauro Carvalho Chehab 	geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;
40968de959fSMauro Carvalho Chehab 	geo->vtotal = tvnorm->vtotal;
41068de959fSMauro Carvalho Chehab 
41168de959fSMauro Carvalho Chehab 	geo->crop = (((geo->width   >> 8) & 0x03) |
41268de959fSMauro Carvalho Chehab 		     ((geo->hdelay  >> 6) & 0x0c) |
41368de959fSMauro Carvalho Chehab 		     ((geo->sheight >> 4) & 0x30) |
41468de959fSMauro Carvalho Chehab 		     ((geo->vdelay  >> 2) & 0xc0));
41568de959fSMauro Carvalho Chehab 
41668de959fSMauro Carvalho Chehab 	if (btv->opt_combfilter) {
41768de959fSMauro Carvalho Chehab 		geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
41868de959fSMauro Carvalho Chehab 		geo->comb = (width < 769) ? 1 : 0;
41968de959fSMauro Carvalho Chehab 	} else {
42068de959fSMauro Carvalho Chehab 		geo->vtc  = 0;
42168de959fSMauro Carvalho Chehab 		geo->comb = 0;
42268de959fSMauro Carvalho Chehab 	}
42368de959fSMauro Carvalho Chehab }
42468de959fSMauro Carvalho Chehab 
42568de959fSMauro Carvalho Chehab static void
42668de959fSMauro Carvalho Chehab bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
42768de959fSMauro Carvalho Chehab {
42868de959fSMauro Carvalho Chehab 	int off = odd ? 0x80 : 0x00;
42968de959fSMauro Carvalho Chehab 
43068de959fSMauro Carvalho Chehab 	if (geo->comb)
43168de959fSMauro Carvalho Chehab 		btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
43268de959fSMauro Carvalho Chehab 	else
43368de959fSMauro Carvalho Chehab 		btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
43468de959fSMauro Carvalho Chehab 
43568de959fSMauro Carvalho Chehab 	btwrite(geo->vtc,             BT848_E_VTC+off);
43668de959fSMauro Carvalho Chehab 	btwrite(geo->hscale >> 8,     BT848_E_HSCALE_HI+off);
43768de959fSMauro Carvalho Chehab 	btwrite(geo->hscale & 0xff,   BT848_E_HSCALE_LO+off);
43868de959fSMauro Carvalho Chehab 	btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
43968de959fSMauro Carvalho Chehab 	btwrite(geo->vscale & 0xff,   BT848_E_VSCALE_LO+off);
44068de959fSMauro Carvalho Chehab 	btwrite(geo->width & 0xff,    BT848_E_HACTIVE_LO+off);
44168de959fSMauro Carvalho Chehab 	btwrite(geo->hdelay & 0xff,   BT848_E_HDELAY_LO+off);
44268de959fSMauro Carvalho Chehab 	btwrite(geo->sheight & 0xff,  BT848_E_VACTIVE_LO+off);
44368de959fSMauro Carvalho Chehab 	btwrite(geo->vdelay & 0xff,   BT848_E_VDELAY_LO+off);
44468de959fSMauro Carvalho Chehab 	btwrite(geo->crop,            BT848_E_CROP+off);
44568de959fSMauro Carvalho Chehab 	btwrite(geo->vtotal>>8,       BT848_VTOTAL_HI);
44668de959fSMauro Carvalho Chehab 	btwrite(geo->vtotal & 0xff,   BT848_VTOTAL_LO);
44768de959fSMauro Carvalho Chehab }
44868de959fSMauro Carvalho Chehab 
44968de959fSMauro Carvalho Chehab /* ---------------------------------------------------------- */
45068de959fSMauro Carvalho Chehab /* risc group / risc main loop / dma management               */
45168de959fSMauro Carvalho Chehab 
45268de959fSMauro Carvalho Chehab void
45368de959fSMauro Carvalho Chehab bttv_set_dma(struct bttv *btv, int override)
45468de959fSMauro Carvalho Chehab {
45568de959fSMauro Carvalho Chehab 	unsigned long cmd;
45668de959fSMauro Carvalho Chehab 	int capctl;
45768de959fSMauro Carvalho Chehab 
45868de959fSMauro Carvalho Chehab 	btv->cap_ctl = 0;
45968de959fSMauro Carvalho Chehab 	if (NULL != btv->curr.top)      btv->cap_ctl |= 0x02;
46068de959fSMauro Carvalho Chehab 	if (NULL != btv->curr.bottom)   btv->cap_ctl |= 0x01;
46168de959fSMauro Carvalho Chehab 	if (NULL != btv->cvbi)          btv->cap_ctl |= 0x0c;
46268de959fSMauro Carvalho Chehab 
46368de959fSMauro Carvalho Chehab 	capctl  = 0;
46468de959fSMauro Carvalho Chehab 	capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00;  /* capture  */
46568de959fSMauro Carvalho Chehab 	capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00;  /* vbi data */
46668de959fSMauro Carvalho Chehab 	capctl |= override;
46768de959fSMauro Carvalho Chehab 
46868de959fSMauro Carvalho Chehab 	d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
46968de959fSMauro Carvalho Chehab 		 btv->c.nr,capctl,btv->loop_irq,
47068de959fSMauro Carvalho Chehab 		 btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
47168de959fSMauro Carvalho Chehab 		 btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
47268de959fSMauro Carvalho Chehab 		 btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,
47368de959fSMauro Carvalho Chehab 		 btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
47468de959fSMauro Carvalho Chehab 
47568de959fSMauro Carvalho Chehab 	cmd = BT848_RISC_JUMP;
47668de959fSMauro Carvalho Chehab 	if (btv->loop_irq) {
47768de959fSMauro Carvalho Chehab 		cmd |= BT848_RISC_IRQ;
47868de959fSMauro Carvalho Chehab 		cmd |= (btv->loop_irq  & 0x0f) << 16;
47968de959fSMauro Carvalho Chehab 		cmd |= (~btv->loop_irq & 0x0f) << 20;
48068de959fSMauro Carvalho Chehab 	}
48168de959fSMauro Carvalho Chehab 	if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
48268de959fSMauro Carvalho Chehab 		mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
48368de959fSMauro Carvalho Chehab 	} else {
48468de959fSMauro Carvalho Chehab 		del_timer(&btv->timeout);
48568de959fSMauro Carvalho Chehab 	}
48668de959fSMauro Carvalho Chehab 	btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
48768de959fSMauro Carvalho Chehab 
48868de959fSMauro Carvalho Chehab 	btaor(capctl, ~0x0f, BT848_CAP_CTL);
48968de959fSMauro Carvalho Chehab 	if (capctl) {
49068de959fSMauro Carvalho Chehab 		if (btv->dma_on)
49168de959fSMauro Carvalho Chehab 			return;
49268de959fSMauro Carvalho Chehab 		btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
49368de959fSMauro Carvalho Chehab 		btor(3, BT848_GPIO_DMA_CTL);
49468de959fSMauro Carvalho Chehab 		btv->dma_on = 1;
49568de959fSMauro Carvalho Chehab 	} else {
49668de959fSMauro Carvalho Chehab 		if (!btv->dma_on)
49768de959fSMauro Carvalho Chehab 			return;
49868de959fSMauro Carvalho Chehab 		btand(~3, BT848_GPIO_DMA_CTL);
49968de959fSMauro Carvalho Chehab 		btv->dma_on = 0;
50068de959fSMauro Carvalho Chehab 	}
50168de959fSMauro Carvalho Chehab 	return;
50268de959fSMauro Carvalho Chehab }
50368de959fSMauro Carvalho Chehab 
50468de959fSMauro Carvalho Chehab int
50568de959fSMauro Carvalho Chehab bttv_risc_init_main(struct bttv *btv)
50668de959fSMauro Carvalho Chehab {
50768de959fSMauro Carvalho Chehab 	int rc;
50868de959fSMauro Carvalho Chehab 
50968de959fSMauro Carvalho Chehab 	if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
51068de959fSMauro Carvalho Chehab 		return rc;
51168de959fSMauro Carvalho Chehab 	dprintk("%d: risc main @ %08llx\n",
51268de959fSMauro Carvalho Chehab 		btv->c.nr, (unsigned long long)btv->main.dma);
51368de959fSMauro Carvalho Chehab 
51468de959fSMauro Carvalho Chehab 	btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
51568de959fSMauro Carvalho Chehab 				       BT848_FIFO_STATUS_VRE);
51668de959fSMauro Carvalho Chehab 	btv->main.cpu[1] = cpu_to_le32(0);
51768de959fSMauro Carvalho Chehab 	btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
51868de959fSMauro Carvalho Chehab 	btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
51968de959fSMauro Carvalho Chehab 
52068de959fSMauro Carvalho Chehab 	/* top field */
52168de959fSMauro Carvalho Chehab 	btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
52268de959fSMauro Carvalho Chehab 	btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
52368de959fSMauro Carvalho Chehab 	btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
52468de959fSMauro Carvalho Chehab 	btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
52568de959fSMauro Carvalho Chehab 
52668de959fSMauro Carvalho Chehab 	btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
52768de959fSMauro Carvalho Chehab 				       BT848_FIFO_STATUS_VRO);
52868de959fSMauro Carvalho Chehab 	btv->main.cpu[9] = cpu_to_le32(0);
52968de959fSMauro Carvalho Chehab 
53068de959fSMauro Carvalho Chehab 	/* bottom field */
53168de959fSMauro Carvalho Chehab 	btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
53268de959fSMauro Carvalho Chehab 	btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
53368de959fSMauro Carvalho Chehab 	btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
53468de959fSMauro Carvalho Chehab 	btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
53568de959fSMauro Carvalho Chehab 
53668de959fSMauro Carvalho Chehab 	/* jump back to top field */
53768de959fSMauro Carvalho Chehab 	btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
53868de959fSMauro Carvalho Chehab 	btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
53968de959fSMauro Carvalho Chehab 
54068de959fSMauro Carvalho Chehab 	return 0;
54168de959fSMauro Carvalho Chehab }
54268de959fSMauro Carvalho Chehab 
54368de959fSMauro Carvalho Chehab int
54468de959fSMauro Carvalho Chehab bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
54568de959fSMauro Carvalho Chehab 	       int irqflags)
54668de959fSMauro Carvalho Chehab {
54768de959fSMauro Carvalho Chehab 	unsigned long cmd;
54868de959fSMauro Carvalho Chehab 	unsigned long next = btv->main.dma + ((slot+2) << 2);
54968de959fSMauro Carvalho Chehab 
55068de959fSMauro Carvalho Chehab 	if (NULL == risc) {
55168de959fSMauro Carvalho Chehab 		d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
55268de959fSMauro Carvalho Chehab 		btv->main.cpu[slot+1] = cpu_to_le32(next);
55368de959fSMauro Carvalho Chehab 	} else {
55468de959fSMauro Carvalho Chehab 		d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
55568de959fSMauro Carvalho Chehab 			 btv->c.nr, risc, slot,
55668de959fSMauro Carvalho Chehab 			 (unsigned long long)risc->dma, irqflags);
55768de959fSMauro Carvalho Chehab 		cmd = BT848_RISC_JUMP;
55868de959fSMauro Carvalho Chehab 		if (irqflags) {
55968de959fSMauro Carvalho Chehab 			cmd |= BT848_RISC_IRQ;
56068de959fSMauro Carvalho Chehab 			cmd |= (irqflags  & 0x0f) << 16;
56168de959fSMauro Carvalho Chehab 			cmd |= (~irqflags & 0x0f) << 20;
56268de959fSMauro Carvalho Chehab 		}
56368de959fSMauro Carvalho Chehab 		risc->jmp[0] = cpu_to_le32(cmd);
56468de959fSMauro Carvalho Chehab 		risc->jmp[1] = cpu_to_le32(next);
56568de959fSMauro Carvalho Chehab 		btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
56668de959fSMauro Carvalho Chehab 	}
56768de959fSMauro Carvalho Chehab 	return 0;
56868de959fSMauro Carvalho Chehab }
56968de959fSMauro Carvalho Chehab 
57068de959fSMauro Carvalho Chehab void
57168de959fSMauro Carvalho Chehab bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
57268de959fSMauro Carvalho Chehab {
57368de959fSMauro Carvalho Chehab 	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
57468de959fSMauro Carvalho Chehab 
57568de959fSMauro Carvalho Chehab 	BUG_ON(in_interrupt());
57668de959fSMauro Carvalho Chehab 	videobuf_waiton(q, &buf->vb, 0, 0);
57768de959fSMauro Carvalho Chehab 	videobuf_dma_unmap(q->dev, dma);
57868de959fSMauro Carvalho Chehab 	videobuf_dma_free(dma);
57968de959fSMauro Carvalho Chehab 	btcx_riscmem_free(btv->c.pci,&buf->bottom);
58068de959fSMauro Carvalho Chehab 	btcx_riscmem_free(btv->c.pci,&buf->top);
58168de959fSMauro Carvalho Chehab 	buf->vb.state = VIDEOBUF_NEEDS_INIT;
58268de959fSMauro Carvalho Chehab }
58368de959fSMauro Carvalho Chehab 
58468de959fSMauro Carvalho Chehab int
58568de959fSMauro Carvalho Chehab bttv_buffer_activate_vbi(struct bttv *btv,
58668de959fSMauro Carvalho Chehab 			 struct bttv_buffer *vbi)
58768de959fSMauro Carvalho Chehab {
58868de959fSMauro Carvalho Chehab 	struct btcx_riscmem *top;
58968de959fSMauro Carvalho Chehab 	struct btcx_riscmem *bottom;
59068de959fSMauro Carvalho Chehab 	int top_irq_flags;
59168de959fSMauro Carvalho Chehab 	int bottom_irq_flags;
59268de959fSMauro Carvalho Chehab 
59368de959fSMauro Carvalho Chehab 	top = NULL;
59468de959fSMauro Carvalho Chehab 	bottom = NULL;
59568de959fSMauro Carvalho Chehab 	top_irq_flags = 0;
59668de959fSMauro Carvalho Chehab 	bottom_irq_flags = 0;
59768de959fSMauro Carvalho Chehab 
59868de959fSMauro Carvalho Chehab 	if (vbi) {
59968de959fSMauro Carvalho Chehab 		unsigned int crop, vdelay;
60068de959fSMauro Carvalho Chehab 
60168de959fSMauro Carvalho Chehab 		vbi->vb.state = VIDEOBUF_ACTIVE;
60268de959fSMauro Carvalho Chehab 		list_del(&vbi->vb.queue);
60368de959fSMauro Carvalho Chehab 
60468de959fSMauro Carvalho Chehab 		/* VDELAY is start of video, end of VBI capturing. */
60568de959fSMauro Carvalho Chehab 		crop = btread(BT848_E_CROP);
60668de959fSMauro Carvalho Chehab 		vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
60768de959fSMauro Carvalho Chehab 
60868de959fSMauro Carvalho Chehab 		if (vbi->geo.vdelay > vdelay) {
60968de959fSMauro Carvalho Chehab 			vdelay = vbi->geo.vdelay & 0xfe;
61068de959fSMauro Carvalho Chehab 			crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
61168de959fSMauro Carvalho Chehab 
61268de959fSMauro Carvalho Chehab 			btwrite(vdelay, BT848_E_VDELAY_LO);
61368de959fSMauro Carvalho Chehab 			btwrite(crop,	BT848_E_CROP);
61468de959fSMauro Carvalho Chehab 			btwrite(vdelay, BT848_O_VDELAY_LO);
61568de959fSMauro Carvalho Chehab 			btwrite(crop,	BT848_O_CROP);
61668de959fSMauro Carvalho Chehab 		}
61768de959fSMauro Carvalho Chehab 
61868de959fSMauro Carvalho Chehab 		if (vbi->vbi_count[0] > 0) {
61968de959fSMauro Carvalho Chehab 			top = &vbi->top;
62068de959fSMauro Carvalho Chehab 			top_irq_flags = 4;
62168de959fSMauro Carvalho Chehab 		}
62268de959fSMauro Carvalho Chehab 
62368de959fSMauro Carvalho Chehab 		if (vbi->vbi_count[1] > 0) {
62468de959fSMauro Carvalho Chehab 			top_irq_flags = 0;
62568de959fSMauro Carvalho Chehab 			bottom = &vbi->bottom;
62668de959fSMauro Carvalho Chehab 			bottom_irq_flags = 4;
62768de959fSMauro Carvalho Chehab 		}
62868de959fSMauro Carvalho Chehab 	}
62968de959fSMauro Carvalho Chehab 
63068de959fSMauro Carvalho Chehab 	bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
63168de959fSMauro Carvalho Chehab 	bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
63268de959fSMauro Carvalho Chehab 
63368de959fSMauro Carvalho Chehab 	return 0;
63468de959fSMauro Carvalho Chehab }
63568de959fSMauro Carvalho Chehab 
63668de959fSMauro Carvalho Chehab int
63768de959fSMauro Carvalho Chehab bttv_buffer_activate_video(struct bttv *btv,
63868de959fSMauro Carvalho Chehab 			   struct bttv_buffer_set *set)
63968de959fSMauro Carvalho Chehab {
64068de959fSMauro Carvalho Chehab 	/* video capture */
64168de959fSMauro Carvalho Chehab 	if (NULL != set->top  &&  NULL != set->bottom) {
64268de959fSMauro Carvalho Chehab 		if (set->top == set->bottom) {
64368de959fSMauro Carvalho Chehab 			set->top->vb.state    = VIDEOBUF_ACTIVE;
64468de959fSMauro Carvalho Chehab 			if (set->top->vb.queue.next)
64568de959fSMauro Carvalho Chehab 				list_del(&set->top->vb.queue);
64668de959fSMauro Carvalho Chehab 		} else {
64768de959fSMauro Carvalho Chehab 			set->top->vb.state    = VIDEOBUF_ACTIVE;
64868de959fSMauro Carvalho Chehab 			set->bottom->vb.state = VIDEOBUF_ACTIVE;
64968de959fSMauro Carvalho Chehab 			if (set->top->vb.queue.next)
65068de959fSMauro Carvalho Chehab 				list_del(&set->top->vb.queue);
65168de959fSMauro Carvalho Chehab 			if (set->bottom->vb.queue.next)
65268de959fSMauro Carvalho Chehab 				list_del(&set->bottom->vb.queue);
65368de959fSMauro Carvalho Chehab 		}
65468de959fSMauro Carvalho Chehab 		bttv_apply_geo(btv, &set->top->geo, 1);
65568de959fSMauro Carvalho Chehab 		bttv_apply_geo(btv, &set->bottom->geo,0);
65668de959fSMauro Carvalho Chehab 		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
65768de959fSMauro Carvalho Chehab 			       set->top_irq);
65868de959fSMauro Carvalho Chehab 		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
65968de959fSMauro Carvalho Chehab 			       set->frame_irq);
66068de959fSMauro Carvalho Chehab 		btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
66168de959fSMauro Carvalho Chehab 		      ~0xff, BT848_COLOR_FMT);
66268de959fSMauro Carvalho Chehab 		btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
66368de959fSMauro Carvalho Chehab 		      ~0x0f, BT848_COLOR_CTL);
66468de959fSMauro Carvalho Chehab 	} else if (NULL != set->top) {
66568de959fSMauro Carvalho Chehab 		set->top->vb.state  = VIDEOBUF_ACTIVE;
66668de959fSMauro Carvalho Chehab 		if (set->top->vb.queue.next)
66768de959fSMauro Carvalho Chehab 			list_del(&set->top->vb.queue);
66868de959fSMauro Carvalho Chehab 		bttv_apply_geo(btv, &set->top->geo,1);
66968de959fSMauro Carvalho Chehab 		bttv_apply_geo(btv, &set->top->geo,0);
67068de959fSMauro Carvalho Chehab 		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
67168de959fSMauro Carvalho Chehab 			       set->frame_irq);
67268de959fSMauro Carvalho Chehab 		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,           0);
67368de959fSMauro Carvalho Chehab 		btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
67468de959fSMauro Carvalho Chehab 		btaor(set->top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
67568de959fSMauro Carvalho Chehab 	} else if (NULL != set->bottom) {
67668de959fSMauro Carvalho Chehab 		set->bottom->vb.state = VIDEOBUF_ACTIVE;
67768de959fSMauro Carvalho Chehab 		if (set->bottom->vb.queue.next)
67868de959fSMauro Carvalho Chehab 			list_del(&set->bottom->vb.queue);
67968de959fSMauro Carvalho Chehab 		bttv_apply_geo(btv, &set->bottom->geo,1);
68068de959fSMauro Carvalho Chehab 		bttv_apply_geo(btv, &set->bottom->geo,0);
68168de959fSMauro Carvalho Chehab 		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
68268de959fSMauro Carvalho Chehab 		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
68368de959fSMauro Carvalho Chehab 			       set->frame_irq);
68468de959fSMauro Carvalho Chehab 		btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
68568de959fSMauro Carvalho Chehab 		btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
68668de959fSMauro Carvalho Chehab 	} else {
68768de959fSMauro Carvalho Chehab 		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
68868de959fSMauro Carvalho Chehab 		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
68968de959fSMauro Carvalho Chehab 	}
69068de959fSMauro Carvalho Chehab 	return 0;
69168de959fSMauro Carvalho Chehab }
69268de959fSMauro Carvalho Chehab 
69368de959fSMauro Carvalho Chehab /* ---------------------------------------------------------- */
69468de959fSMauro Carvalho Chehab 
69568de959fSMauro Carvalho Chehab /* calculate geometry, build risc code */
69668de959fSMauro Carvalho Chehab int
69768de959fSMauro Carvalho Chehab bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
69868de959fSMauro Carvalho Chehab {
69968de959fSMauro Carvalho Chehab 	const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
70068de959fSMauro Carvalho Chehab 	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
70168de959fSMauro Carvalho Chehab 
70268de959fSMauro Carvalho Chehab 	dprintk("%d: buffer field: %s  format: %s  size: %dx%d\n",
70368de959fSMauro Carvalho Chehab 		btv->c.nr, v4l2_field_names[buf->vb.field],
70468de959fSMauro Carvalho Chehab 		buf->fmt->name, buf->vb.width, buf->vb.height);
70568de959fSMauro Carvalho Chehab 
70668de959fSMauro Carvalho Chehab 	/* packed pixel modes */
70768de959fSMauro Carvalho Chehab 	if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
70868de959fSMauro Carvalho Chehab 		int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
70968de959fSMauro Carvalho Chehab 		int bpf = bpl * (buf->vb.height >> 1);
71068de959fSMauro Carvalho Chehab 
71168de959fSMauro Carvalho Chehab 		bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
71268de959fSMauro Carvalho Chehab 			      V4L2_FIELD_HAS_BOTH(buf->vb.field),
71368de959fSMauro Carvalho Chehab 			      tvnorm,&buf->crop);
71468de959fSMauro Carvalho Chehab 
71568de959fSMauro Carvalho Chehab 		switch (buf->vb.field) {
71668de959fSMauro Carvalho Chehab 		case V4L2_FIELD_TOP:
71768de959fSMauro Carvalho Chehab 			bttv_risc_packed(btv,&buf->top,dma->sglist,
71868de959fSMauro Carvalho Chehab 					 /* offset */ 0,bpl,
71968de959fSMauro Carvalho Chehab 					 /* padding */ 0,/* skip_lines */ 0,
72068de959fSMauro Carvalho Chehab 					 buf->vb.height);
72168de959fSMauro Carvalho Chehab 			break;
72268de959fSMauro Carvalho Chehab 		case V4L2_FIELD_BOTTOM:
72368de959fSMauro Carvalho Chehab 			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
72468de959fSMauro Carvalho Chehab 					 0,bpl,0,0,buf->vb.height);
72568de959fSMauro Carvalho Chehab 			break;
72668de959fSMauro Carvalho Chehab 		case V4L2_FIELD_INTERLACED:
72768de959fSMauro Carvalho Chehab 			bttv_risc_packed(btv,&buf->top,dma->sglist,
72868de959fSMauro Carvalho Chehab 					 0,bpl,bpl,0,buf->vb.height >> 1);
72968de959fSMauro Carvalho Chehab 			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
73068de959fSMauro Carvalho Chehab 					 bpl,bpl,bpl,0,buf->vb.height >> 1);
73168de959fSMauro Carvalho Chehab 			break;
73268de959fSMauro Carvalho Chehab 		case V4L2_FIELD_SEQ_TB:
73368de959fSMauro Carvalho Chehab 			bttv_risc_packed(btv,&buf->top,dma->sglist,
73468de959fSMauro Carvalho Chehab 					 0,bpl,0,0,buf->vb.height >> 1);
73568de959fSMauro Carvalho Chehab 			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
73668de959fSMauro Carvalho Chehab 					 bpf,bpl,0,0,buf->vb.height >> 1);
73768de959fSMauro Carvalho Chehab 			break;
73868de959fSMauro Carvalho Chehab 		default:
73968de959fSMauro Carvalho Chehab 			BUG();
74068de959fSMauro Carvalho Chehab 		}
74168de959fSMauro Carvalho Chehab 	}
74268de959fSMauro Carvalho Chehab 
74368de959fSMauro Carvalho Chehab 	/* planar modes */
74468de959fSMauro Carvalho Chehab 	if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
74568de959fSMauro Carvalho Chehab 		int uoffset, voffset;
74668de959fSMauro Carvalho Chehab 		int ypadding, cpadding, lines;
74768de959fSMauro Carvalho Chehab 
74868de959fSMauro Carvalho Chehab 		/* calculate chroma offsets */
74968de959fSMauro Carvalho Chehab 		uoffset = buf->vb.width * buf->vb.height;
75068de959fSMauro Carvalho Chehab 		voffset = buf->vb.width * buf->vb.height;
75168de959fSMauro Carvalho Chehab 		if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
75268de959fSMauro Carvalho Chehab 			/* Y-Cr-Cb plane order */
75368de959fSMauro Carvalho Chehab 			uoffset >>= buf->fmt->hshift;
75468de959fSMauro Carvalho Chehab 			uoffset >>= buf->fmt->vshift;
75568de959fSMauro Carvalho Chehab 			uoffset  += voffset;
75668de959fSMauro Carvalho Chehab 		} else {
75768de959fSMauro Carvalho Chehab 			/* Y-Cb-Cr plane order */
75868de959fSMauro Carvalho Chehab 			voffset >>= buf->fmt->hshift;
75968de959fSMauro Carvalho Chehab 			voffset >>= buf->fmt->vshift;
76068de959fSMauro Carvalho Chehab 			voffset  += uoffset;
76168de959fSMauro Carvalho Chehab 		}
76268de959fSMauro Carvalho Chehab 
76368de959fSMauro Carvalho Chehab 		switch (buf->vb.field) {
76468de959fSMauro Carvalho Chehab 		case V4L2_FIELD_TOP:
76568de959fSMauro Carvalho Chehab 			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
76668de959fSMauro Carvalho Chehab 				      buf->vb.height,/* both_fields */ 0,
76768de959fSMauro Carvalho Chehab 				      tvnorm,&buf->crop);
76868de959fSMauro Carvalho Chehab 			bttv_risc_planar(btv, &buf->top, dma->sglist,
76968de959fSMauro Carvalho Chehab 					 0,buf->vb.width,0,buf->vb.height,
77068de959fSMauro Carvalho Chehab 					 uoffset,voffset,buf->fmt->hshift,
77168de959fSMauro Carvalho Chehab 					 buf->fmt->vshift,0);
77268de959fSMauro Carvalho Chehab 			break;
77368de959fSMauro Carvalho Chehab 		case V4L2_FIELD_BOTTOM:
77468de959fSMauro Carvalho Chehab 			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
77568de959fSMauro Carvalho Chehab 				      buf->vb.height,0,
77668de959fSMauro Carvalho Chehab 				      tvnorm,&buf->crop);
77768de959fSMauro Carvalho Chehab 			bttv_risc_planar(btv, &buf->bottom, dma->sglist,
77868de959fSMauro Carvalho Chehab 					 0,buf->vb.width,0,buf->vb.height,
77968de959fSMauro Carvalho Chehab 					 uoffset,voffset,buf->fmt->hshift,
78068de959fSMauro Carvalho Chehab 					 buf->fmt->vshift,0);
78168de959fSMauro Carvalho Chehab 			break;
78268de959fSMauro Carvalho Chehab 		case V4L2_FIELD_INTERLACED:
78368de959fSMauro Carvalho Chehab 			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
78468de959fSMauro Carvalho Chehab 				      buf->vb.height,1,
78568de959fSMauro Carvalho Chehab 				      tvnorm,&buf->crop);
78668de959fSMauro Carvalho Chehab 			lines    = buf->vb.height >> 1;
78768de959fSMauro Carvalho Chehab 			ypadding = buf->vb.width;
78868de959fSMauro Carvalho Chehab 			cpadding = buf->vb.width >> buf->fmt->hshift;
78968de959fSMauro Carvalho Chehab 			bttv_risc_planar(btv,&buf->top,
79068de959fSMauro Carvalho Chehab 					 dma->sglist,
79168de959fSMauro Carvalho Chehab 					 0,buf->vb.width,ypadding,lines,
79268de959fSMauro Carvalho Chehab 					 uoffset,voffset,
79368de959fSMauro Carvalho Chehab 					 buf->fmt->hshift,
79468de959fSMauro Carvalho Chehab 					 buf->fmt->vshift,
79568de959fSMauro Carvalho Chehab 					 cpadding);
79668de959fSMauro Carvalho Chehab 			bttv_risc_planar(btv,&buf->bottom,
79768de959fSMauro Carvalho Chehab 					 dma->sglist,
79868de959fSMauro Carvalho Chehab 					 ypadding,buf->vb.width,ypadding,lines,
79968de959fSMauro Carvalho Chehab 					 uoffset+cpadding,
80068de959fSMauro Carvalho Chehab 					 voffset+cpadding,
80168de959fSMauro Carvalho Chehab 					 buf->fmt->hshift,
80268de959fSMauro Carvalho Chehab 					 buf->fmt->vshift,
80368de959fSMauro Carvalho Chehab 					 cpadding);
80468de959fSMauro Carvalho Chehab 			break;
80568de959fSMauro Carvalho Chehab 		case V4L2_FIELD_SEQ_TB:
80668de959fSMauro Carvalho Chehab 			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
80768de959fSMauro Carvalho Chehab 				      buf->vb.height,1,
80868de959fSMauro Carvalho Chehab 				      tvnorm,&buf->crop);
80968de959fSMauro Carvalho Chehab 			lines    = buf->vb.height >> 1;
81068de959fSMauro Carvalho Chehab 			ypadding = buf->vb.width;
81168de959fSMauro Carvalho Chehab 			cpadding = buf->vb.width >> buf->fmt->hshift;
81268de959fSMauro Carvalho Chehab 			bttv_risc_planar(btv,&buf->top,
81368de959fSMauro Carvalho Chehab 					 dma->sglist,
81468de959fSMauro Carvalho Chehab 					 0,buf->vb.width,0,lines,
81568de959fSMauro Carvalho Chehab 					 uoffset >> 1,
81668de959fSMauro Carvalho Chehab 					 voffset >> 1,
81768de959fSMauro Carvalho Chehab 					 buf->fmt->hshift,
81868de959fSMauro Carvalho Chehab 					 buf->fmt->vshift,
81968de959fSMauro Carvalho Chehab 					 0);
82068de959fSMauro Carvalho Chehab 			bttv_risc_planar(btv,&buf->bottom,
82168de959fSMauro Carvalho Chehab 					 dma->sglist,
82268de959fSMauro Carvalho Chehab 					 lines * ypadding,buf->vb.width,0,lines,
82368de959fSMauro Carvalho Chehab 					 lines * ypadding + (uoffset >> 1),
82468de959fSMauro Carvalho Chehab 					 lines * ypadding + (voffset >> 1),
82568de959fSMauro Carvalho Chehab 					 buf->fmt->hshift,
82668de959fSMauro Carvalho Chehab 					 buf->fmt->vshift,
82768de959fSMauro Carvalho Chehab 					 0);
82868de959fSMauro Carvalho Chehab 			break;
82968de959fSMauro Carvalho Chehab 		default:
83068de959fSMauro Carvalho Chehab 			BUG();
83168de959fSMauro Carvalho Chehab 		}
83268de959fSMauro Carvalho Chehab 	}
83368de959fSMauro Carvalho Chehab 
83468de959fSMauro Carvalho Chehab 	/* raw data */
83568de959fSMauro Carvalho Chehab 	if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
83668de959fSMauro Carvalho Chehab 		/* build risc code */
83768de959fSMauro Carvalho Chehab 		buf->vb.field = V4L2_FIELD_SEQ_TB;
83868de959fSMauro Carvalho Chehab 		bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
83968de959fSMauro Carvalho Chehab 			      1,tvnorm,&buf->crop);
84068de959fSMauro Carvalho Chehab 		bttv_risc_packed(btv, &buf->top,  dma->sglist,
84168de959fSMauro Carvalho Chehab 				 /* offset */ 0, RAW_BPL, /* padding */ 0,
84268de959fSMauro Carvalho Chehab 				 /* skip_lines */ 0, RAW_LINES);
84368de959fSMauro Carvalho Chehab 		bttv_risc_packed(btv, &buf->bottom, dma->sglist,
84468de959fSMauro Carvalho Chehab 				 buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
84568de959fSMauro Carvalho Chehab 	}
84668de959fSMauro Carvalho Chehab 
84768de959fSMauro Carvalho Chehab 	/* copy format info */
84868de959fSMauro Carvalho Chehab 	buf->btformat = buf->fmt->btformat;
84968de959fSMauro Carvalho Chehab 	buf->btswap   = buf->fmt->btswap;
85068de959fSMauro Carvalho Chehab 	return 0;
85168de959fSMauro Carvalho Chehab }
85268de959fSMauro Carvalho Chehab 
85368de959fSMauro Carvalho Chehab /* ---------------------------------------------------------- */
85468de959fSMauro Carvalho Chehab 
85568de959fSMauro Carvalho Chehab /* calculate geometry, build risc code */
85668de959fSMauro Carvalho Chehab int
85768de959fSMauro Carvalho Chehab bttv_overlay_risc(struct bttv *btv,
85868de959fSMauro Carvalho Chehab 		  struct bttv_overlay *ov,
85968de959fSMauro Carvalho Chehab 		  const struct bttv_format *fmt,
86068de959fSMauro Carvalho Chehab 		  struct bttv_buffer *buf)
86168de959fSMauro Carvalho Chehab {
86268de959fSMauro Carvalho Chehab 	/* check interleave, bottom+top fields */
86368de959fSMauro Carvalho Chehab 	dprintk("%d: overlay fields: %s format: %s  size: %dx%d\n",
86468de959fSMauro Carvalho Chehab 		btv->c.nr, v4l2_field_names[buf->vb.field],
86568de959fSMauro Carvalho Chehab 		fmt->name, ov->w.width, ov->w.height);
86668de959fSMauro Carvalho Chehab 
86768de959fSMauro Carvalho Chehab 	/* calculate geometry */
86868de959fSMauro Carvalho Chehab 	bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
86968de959fSMauro Carvalho Chehab 		      V4L2_FIELD_HAS_BOTH(ov->field),
87068de959fSMauro Carvalho Chehab 		      &bttv_tvnorms[ov->tvnorm],&buf->crop);
87168de959fSMauro Carvalho Chehab 
87268de959fSMauro Carvalho Chehab 	/* build risc code */
87368de959fSMauro Carvalho Chehab 	switch (ov->field) {
87468de959fSMauro Carvalho Chehab 	case V4L2_FIELD_TOP:
87568de959fSMauro Carvalho Chehab 		bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 0);
87668de959fSMauro Carvalho Chehab 		break;
87768de959fSMauro Carvalho Chehab 	case V4L2_FIELD_BOTTOM:
87868de959fSMauro Carvalho Chehab 		bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
87968de959fSMauro Carvalho Chehab 		break;
88068de959fSMauro Carvalho Chehab 	case V4L2_FIELD_INTERLACED:
88168de959fSMauro Carvalho Chehab 		bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 1);
88268de959fSMauro Carvalho Chehab 		bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
88368de959fSMauro Carvalho Chehab 		break;
88468de959fSMauro Carvalho Chehab 	default:
88568de959fSMauro Carvalho Chehab 		BUG();
88668de959fSMauro Carvalho Chehab 	}
88768de959fSMauro Carvalho Chehab 
88868de959fSMauro Carvalho Chehab 	/* copy format info */
88968de959fSMauro Carvalho Chehab 	buf->btformat = fmt->btformat;
89068de959fSMauro Carvalho Chehab 	buf->btswap   = fmt->btswap;
89168de959fSMauro Carvalho Chehab 	buf->vb.field = ov->field;
89268de959fSMauro Carvalho Chehab 	return 0;
89368de959fSMauro Carvalho Chehab }
894