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 	BUG_ON(in_interrupt());
576 	videobuf_waiton(q, &buf->vb, 0, 0);
577 	videobuf_dma_unmap(q->dev, dma);
578 	videobuf_dma_free(dma);
579 	btcx_riscmem_free(btv->c.pci,&buf->bottom);
580 	btcx_riscmem_free(btv->c.pci,&buf->top);
581 	buf->vb.state = VIDEOBUF_NEEDS_INIT;
582 }
583 
584 int
585 bttv_buffer_activate_vbi(struct bttv *btv,
586 			 struct bttv_buffer *vbi)
587 {
588 	struct btcx_riscmem *top;
589 	struct btcx_riscmem *bottom;
590 	int top_irq_flags;
591 	int bottom_irq_flags;
592 
593 	top = NULL;
594 	bottom = NULL;
595 	top_irq_flags = 0;
596 	bottom_irq_flags = 0;
597 
598 	if (vbi) {
599 		unsigned int crop, vdelay;
600 
601 		vbi->vb.state = VIDEOBUF_ACTIVE;
602 		list_del(&vbi->vb.queue);
603 
604 		/* VDELAY is start of video, end of VBI capturing. */
605 		crop = btread(BT848_E_CROP);
606 		vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
607 
608 		if (vbi->geo.vdelay > vdelay) {
609 			vdelay = vbi->geo.vdelay & 0xfe;
610 			crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
611 
612 			btwrite(vdelay, BT848_E_VDELAY_LO);
613 			btwrite(crop,	BT848_E_CROP);
614 			btwrite(vdelay, BT848_O_VDELAY_LO);
615 			btwrite(crop,	BT848_O_CROP);
616 		}
617 
618 		if (vbi->vbi_count[0] > 0) {
619 			top = &vbi->top;
620 			top_irq_flags = 4;
621 		}
622 
623 		if (vbi->vbi_count[1] > 0) {
624 			top_irq_flags = 0;
625 			bottom = &vbi->bottom;
626 			bottom_irq_flags = 4;
627 		}
628 	}
629 
630 	bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
631 	bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
632 
633 	return 0;
634 }
635 
636 int
637 bttv_buffer_activate_video(struct bttv *btv,
638 			   struct bttv_buffer_set *set)
639 {
640 	/* video capture */
641 	if (NULL != set->top  &&  NULL != set->bottom) {
642 		if (set->top == set->bottom) {
643 			set->top->vb.state    = VIDEOBUF_ACTIVE;
644 			if (set->top->vb.queue.next)
645 				list_del(&set->top->vb.queue);
646 		} else {
647 			set->top->vb.state    = VIDEOBUF_ACTIVE;
648 			set->bottom->vb.state = VIDEOBUF_ACTIVE;
649 			if (set->top->vb.queue.next)
650 				list_del(&set->top->vb.queue);
651 			if (set->bottom->vb.queue.next)
652 				list_del(&set->bottom->vb.queue);
653 		}
654 		bttv_apply_geo(btv, &set->top->geo, 1);
655 		bttv_apply_geo(btv, &set->bottom->geo,0);
656 		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
657 			       set->top_irq);
658 		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
659 			       set->frame_irq);
660 		btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
661 		      ~0xff, BT848_COLOR_FMT);
662 		btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
663 		      ~0x0f, BT848_COLOR_CTL);
664 	} else if (NULL != set->top) {
665 		set->top->vb.state  = VIDEOBUF_ACTIVE;
666 		if (set->top->vb.queue.next)
667 			list_del(&set->top->vb.queue);
668 		bttv_apply_geo(btv, &set->top->geo,1);
669 		bttv_apply_geo(btv, &set->top->geo,0);
670 		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
671 			       set->frame_irq);
672 		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,           0);
673 		btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
674 		btaor(set->top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
675 	} else if (NULL != set->bottom) {
676 		set->bottom->vb.state = VIDEOBUF_ACTIVE;
677 		if (set->bottom->vb.queue.next)
678 			list_del(&set->bottom->vb.queue);
679 		bttv_apply_geo(btv, &set->bottom->geo,1);
680 		bttv_apply_geo(btv, &set->bottom->geo,0);
681 		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
682 		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
683 			       set->frame_irq);
684 		btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
685 		btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
686 	} else {
687 		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
688 		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
689 	}
690 	return 0;
691 }
692 
693 /* ---------------------------------------------------------- */
694 
695 /* calculate geometry, build risc code */
696 int
697 bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
698 {
699 	const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
700 	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
701 
702 	dprintk("%d: buffer field: %s  format: 0x%08x  size: %dx%d\n",
703 		btv->c.nr, v4l2_field_names[buf->vb.field],
704 		buf->fmt->fourcc, buf->vb.width, buf->vb.height);
705 
706 	/* packed pixel modes */
707 	if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
708 		int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
709 		int bpf = bpl * (buf->vb.height >> 1);
710 
711 		bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
712 			      V4L2_FIELD_HAS_BOTH(buf->vb.field),
713 			      tvnorm,&buf->crop);
714 
715 		switch (buf->vb.field) {
716 		case V4L2_FIELD_TOP:
717 			bttv_risc_packed(btv,&buf->top,dma->sglist,
718 					 /* offset */ 0,bpl,
719 					 /* padding */ 0,/* skip_lines */ 0,
720 					 buf->vb.height);
721 			break;
722 		case V4L2_FIELD_BOTTOM:
723 			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
724 					 0,bpl,0,0,buf->vb.height);
725 			break;
726 		case V4L2_FIELD_INTERLACED:
727 			bttv_risc_packed(btv,&buf->top,dma->sglist,
728 					 0,bpl,bpl,0,buf->vb.height >> 1);
729 			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
730 					 bpl,bpl,bpl,0,buf->vb.height >> 1);
731 			break;
732 		case V4L2_FIELD_SEQ_TB:
733 			bttv_risc_packed(btv,&buf->top,dma->sglist,
734 					 0,bpl,0,0,buf->vb.height >> 1);
735 			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
736 					 bpf,bpl,0,0,buf->vb.height >> 1);
737 			break;
738 		default:
739 			BUG();
740 		}
741 	}
742 
743 	/* planar modes */
744 	if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
745 		int uoffset, voffset;
746 		int ypadding, cpadding, lines;
747 
748 		/* calculate chroma offsets */
749 		uoffset = buf->vb.width * buf->vb.height;
750 		voffset = buf->vb.width * buf->vb.height;
751 		if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
752 			/* Y-Cr-Cb plane order */
753 			uoffset >>= buf->fmt->hshift;
754 			uoffset >>= buf->fmt->vshift;
755 			uoffset  += voffset;
756 		} else {
757 			/* Y-Cb-Cr plane order */
758 			voffset >>= buf->fmt->hshift;
759 			voffset >>= buf->fmt->vshift;
760 			voffset  += uoffset;
761 		}
762 
763 		switch (buf->vb.field) {
764 		case V4L2_FIELD_TOP:
765 			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
766 				      buf->vb.height,/* both_fields */ 0,
767 				      tvnorm,&buf->crop);
768 			bttv_risc_planar(btv, &buf->top, dma->sglist,
769 					 0,buf->vb.width,0,buf->vb.height,
770 					 uoffset,voffset,buf->fmt->hshift,
771 					 buf->fmt->vshift,0);
772 			break;
773 		case V4L2_FIELD_BOTTOM:
774 			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
775 				      buf->vb.height,0,
776 				      tvnorm,&buf->crop);
777 			bttv_risc_planar(btv, &buf->bottom, dma->sglist,
778 					 0,buf->vb.width,0,buf->vb.height,
779 					 uoffset,voffset,buf->fmt->hshift,
780 					 buf->fmt->vshift,0);
781 			break;
782 		case V4L2_FIELD_INTERLACED:
783 			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
784 				      buf->vb.height,1,
785 				      tvnorm,&buf->crop);
786 			lines    = buf->vb.height >> 1;
787 			ypadding = buf->vb.width;
788 			cpadding = buf->vb.width >> buf->fmt->hshift;
789 			bttv_risc_planar(btv,&buf->top,
790 					 dma->sglist,
791 					 0,buf->vb.width,ypadding,lines,
792 					 uoffset,voffset,
793 					 buf->fmt->hshift,
794 					 buf->fmt->vshift,
795 					 cpadding);
796 			bttv_risc_planar(btv,&buf->bottom,
797 					 dma->sglist,
798 					 ypadding,buf->vb.width,ypadding,lines,
799 					 uoffset+cpadding,
800 					 voffset+cpadding,
801 					 buf->fmt->hshift,
802 					 buf->fmt->vshift,
803 					 cpadding);
804 			break;
805 		case V4L2_FIELD_SEQ_TB:
806 			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
807 				      buf->vb.height,1,
808 				      tvnorm,&buf->crop);
809 			lines    = buf->vb.height >> 1;
810 			ypadding = buf->vb.width;
811 			cpadding = buf->vb.width >> buf->fmt->hshift;
812 			bttv_risc_planar(btv,&buf->top,
813 					 dma->sglist,
814 					 0,buf->vb.width,0,lines,
815 					 uoffset >> 1,
816 					 voffset >> 1,
817 					 buf->fmt->hshift,
818 					 buf->fmt->vshift,
819 					 0);
820 			bttv_risc_planar(btv,&buf->bottom,
821 					 dma->sglist,
822 					 lines * ypadding,buf->vb.width,0,lines,
823 					 lines * ypadding + (uoffset >> 1),
824 					 lines * ypadding + (voffset >> 1),
825 					 buf->fmt->hshift,
826 					 buf->fmt->vshift,
827 					 0);
828 			break;
829 		default:
830 			BUG();
831 		}
832 	}
833 
834 	/* raw data */
835 	if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
836 		/* build risc code */
837 		buf->vb.field = V4L2_FIELD_SEQ_TB;
838 		bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
839 			      1,tvnorm,&buf->crop);
840 		bttv_risc_packed(btv, &buf->top,  dma->sglist,
841 				 /* offset */ 0, RAW_BPL, /* padding */ 0,
842 				 /* skip_lines */ 0, RAW_LINES);
843 		bttv_risc_packed(btv, &buf->bottom, dma->sglist,
844 				 buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
845 	}
846 
847 	/* copy format info */
848 	buf->btformat = buf->fmt->btformat;
849 	buf->btswap   = buf->fmt->btswap;
850 	return 0;
851 }
852 
853 /* ---------------------------------------------------------- */
854 
855 /* calculate geometry, build risc code */
856 int
857 bttv_overlay_risc(struct bttv *btv,
858 		  struct bttv_overlay *ov,
859 		  const struct bttv_format *fmt,
860 		  struct bttv_buffer *buf)
861 {
862 	/* check interleave, bottom+top fields */
863 	dprintk("%d: overlay fields: %s format: 0x%08x  size: %dx%d\n",
864 		btv->c.nr, v4l2_field_names[buf->vb.field],
865 		fmt->fourcc, ov->w.width, ov->w.height);
866 
867 	/* calculate geometry */
868 	bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
869 		      V4L2_FIELD_HAS_BOTH(ov->field),
870 		      &bttv_tvnorms[ov->tvnorm],&buf->crop);
871 
872 	/* build risc code */
873 	switch (ov->field) {
874 	case V4L2_FIELD_TOP:
875 		bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 0);
876 		break;
877 	case V4L2_FIELD_BOTTOM:
878 		bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
879 		break;
880 	case V4L2_FIELD_INTERLACED:
881 		bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 1);
882 		bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
883 		break;
884 	default:
885 		BUG();
886 	}
887 
888 	/* copy format info */
889 	buf->btformat = fmt->btformat;
890 	buf->btswap   = fmt->btswap;
891 	buf->vb.field = ov->field;
892 	return 0;
893 }
894