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 
34 int
35 bttv_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 
113 static int
114 bttv_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 
234 static int
235 bttv_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 
325 static void
326 bttv_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 
369 static void
370 bttv_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 
425 static void
426 bttv_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 
452 void
453 bttv_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 
504 int
505 bttv_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 
543 int
544 bttv_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 
570 void
571 bttv_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 
583 int
584 bttv_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 
635 int
636 bttv_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 */
695 int
696 bttv_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 */
855 int
856 bttv_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 }
893