xref: /linux/drivers/media/pci/bt8xx/bttv-risc.c (revision 981368e1440b76f68b1ac8f5fb14e739f80ecc4e)
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 ((line >= (store_lines - VCR_HACK_LINES)) &&
71 		    (btv->opt_vcr_hack ||
72 		    (V4L2_FIELD_HAS_BOTH(btv->field) ||
73 		     btv->field == V4L2_FIELD_ALTERNATE)))
74 			continue;
75 		while (offset && offset >= sg_dma_len(sg)) {
76 			offset -= sg_dma_len(sg);
77 			sg = sg_next(sg);
78 		}
79 		if (bpl <= sg_dma_len(sg)-offset) {
80 			/* fits into current chunk */
81 			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
82 					    BT848_RISC_EOL|bpl);
83 			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
84 			offset+=bpl;
85 		} else {
86 			/* scanline needs to be split */
87 			todo = bpl;
88 			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
89 					    (sg_dma_len(sg)-offset));
90 			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
91 			todo -= (sg_dma_len(sg)-offset);
92 			offset = 0;
93 			sg = sg_next(sg);
94 			while (todo > sg_dma_len(sg)) {
95 				*(rp++)=cpu_to_le32(BT848_RISC_WRITE|
96 						    sg_dma_len(sg));
97 				*(rp++)=cpu_to_le32(sg_dma_address(sg));
98 				todo -= sg_dma_len(sg);
99 				sg = sg_next(sg);
100 			}
101 			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
102 					    todo);
103 			*(rp++)=cpu_to_le32(sg_dma_address(sg));
104 			offset += todo;
105 		}
106 		offset += padding;
107 	}
108 
109 	/* save pointer to jmp instruction address */
110 	risc->jmp = rp;
111 	WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
112 	return 0;
113 }
114 
115 static int
116 bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
117 		 struct scatterlist *sglist,
118 		 unsigned int yoffset,  unsigned int ybpl,
119 		 unsigned int ypadding, unsigned int ylines,
120 		 unsigned int uoffset,  unsigned int voffset,
121 		 unsigned int hshift,   unsigned int vshift,
122 		 unsigned int cpadding)
123 {
124 	unsigned int instructions,line,todo,ylen,chroma;
125 	__le32 *rp;
126 	u32 ri;
127 	struct scatterlist *ysg;
128 	struct scatterlist *usg;
129 	struct scatterlist *vsg;
130 	int topfield = (0 == yoffset);
131 	int rc;
132 
133 	/* estimate risc mem: worst case is one write per page border +
134 	   one write per scan line (5 dwords)
135 	   plus sync + jump (2 dwords) */
136 	instructions  = ((3 + (ybpl + ypadding) * ylines * 2)
137 			 / PAGE_SIZE) + ylines;
138 	instructions += 2;
139 	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
140 		return rc;
141 
142 	/* sync instruction */
143 	rp = risc->cpu;
144 	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
145 	*(rp++) = cpu_to_le32(0);
146 
147 	/* scan lines */
148 	ysg = sglist;
149 	usg = sglist;
150 	vsg = sglist;
151 	for (line = 0; line < ylines; line++) {
152 		if ((btv->opt_vcr_hack) &&
153 		    (line >= (ylines - VCR_HACK_LINES)))
154 			continue;
155 		switch (vshift) {
156 		case 0:
157 			chroma = 1;
158 			break;
159 		case 1:
160 			if (topfield)
161 				chroma = ((line & 1) == 0);
162 			else
163 				chroma = ((line & 1) == 1);
164 			break;
165 		case 2:
166 			if (topfield)
167 				chroma = ((line & 3) == 0);
168 			else
169 				chroma = ((line & 3) == 2);
170 			break;
171 		default:
172 			chroma = 0;
173 			break;
174 		}
175 
176 		for (todo = ybpl; todo > 0; todo -= ylen) {
177 			/* go to next sg entry if needed */
178 			while (yoffset && yoffset >= sg_dma_len(ysg)) {
179 				yoffset -= sg_dma_len(ysg);
180 				ysg = sg_next(ysg);
181 			}
182 
183 			/* calculate max number of bytes we can write */
184 			ylen = todo;
185 			if (yoffset + ylen > sg_dma_len(ysg))
186 				ylen = sg_dma_len(ysg) - yoffset;
187 			if (chroma) {
188 				while (uoffset && uoffset >= sg_dma_len(usg)) {
189 					uoffset -= sg_dma_len(usg);
190 					usg = sg_next(usg);
191 				}
192 				while (voffset && voffset >= sg_dma_len(vsg)) {
193 					voffset -= sg_dma_len(vsg);
194 					vsg = sg_next(vsg);
195 				}
196 
197 				if (uoffset + (ylen>>hshift) > sg_dma_len(usg))
198 					ylen = (sg_dma_len(usg) - uoffset) << hshift;
199 				if (voffset + (ylen>>hshift) > sg_dma_len(vsg))
200 					ylen = (sg_dma_len(vsg) - voffset) << hshift;
201 				ri = BT848_RISC_WRITE123;
202 			} else {
203 				ri = BT848_RISC_WRITE1S23;
204 			}
205 			if (ybpl == todo)
206 				ri |= BT848_RISC_SOL;
207 			if (ylen == todo)
208 				ri |= BT848_RISC_EOL;
209 
210 			/* write risc instruction */
211 			*(rp++)=cpu_to_le32(ri | ylen);
212 			*(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
213 					    (ylen >> hshift));
214 			*(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
215 			yoffset += ylen;
216 			if (chroma) {
217 				*(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);
218 				uoffset += ylen >> hshift;
219 				*(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);
220 				voffset += ylen >> hshift;
221 			}
222 		}
223 		yoffset += ypadding;
224 		if (chroma) {
225 			uoffset += cpadding;
226 			voffset += cpadding;
227 		}
228 	}
229 
230 	/* save pointer to jmp instruction address */
231 	risc->jmp = rp;
232 	WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
233 	return 0;
234 }
235 
236 /* ---------------------------------------------------------- */
237 
238 static void
239 bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
240 		  int width, int height, int interleaved,
241 		  const struct bttv_tvnorm *tvnorm)
242 {
243 	u32 xsf, sr;
244 	int vdelay;
245 
246 	int swidth       = tvnorm->swidth;
247 	int totalwidth   = tvnorm->totalwidth;
248 	int scaledtwidth = tvnorm->scaledtwidth;
249 
250 	if (btv->input == btv->dig) {
251 		swidth       = 720;
252 		totalwidth   = 858;
253 		scaledtwidth = 858;
254 	}
255 
256 	vdelay = tvnorm->vdelay;
257 
258 	xsf = (width*scaledtwidth)/swidth;
259 	geo->hscale =  ((totalwidth*4096UL)/xsf-4096);
260 	geo->hdelay =  tvnorm->hdelayx1;
261 	geo->hdelay =  (geo->hdelay*width)/swidth;
262 	geo->hdelay &= 0x3fe;
263 	sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
264 	geo->vscale =  (0x10000UL-sr) & 0x1fff;
265 	geo->crop   =  ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
266 		((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
267 	geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
268 	geo->vdelay  =  vdelay;
269 	geo->width   =  width;
270 	geo->sheight =  tvnorm->sheight;
271 	geo->vtotal  =  tvnorm->vtotal;
272 
273 	if (btv->opt_combfilter) {
274 		geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
275 		geo->comb = (width < 769) ? 1 : 0;
276 	} else {
277 		geo->vtc  = 0;
278 		geo->comb = 0;
279 	}
280 }
281 
282 static void
283 bttv_calc_geo		(struct bttv *                  btv,
284 			 struct bttv_geometry *         geo,
285 			 unsigned int                   width,
286 			 unsigned int                   height,
287 			 int                            both_fields,
288 			 const struct bttv_tvnorm *     tvnorm,
289 			 const struct v4l2_rect *       crop)
290 {
291 	unsigned int c_width;
292 	unsigned int c_height;
293 	u32 sr;
294 
295 	if ((crop->left == tvnorm->cropcap.defrect.left
296 	     && crop->top == tvnorm->cropcap.defrect.top
297 	     && crop->width == tvnorm->cropcap.defrect.width
298 	     && crop->height == tvnorm->cropcap.defrect.height
299 	     && width <= tvnorm->swidth /* see PAL-Nc et al */)
300 	    || btv->input == btv->dig) {
301 		bttv_calc_geo_old(btv, geo, width, height,
302 				  both_fields, tvnorm);
303 		return;
304 	}
305 
306 	/* For bug compatibility the image size checks permit scale
307 	   factors > 16. See bttv_crop_calc_limits(). */
308 	c_width = min((unsigned int) crop->width, width * 16);
309 	c_height = min((unsigned int) crop->height, height * 16);
310 
311 	geo->width = width;
312 	geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;
313 	/* Even to store Cb first, odd for Cr. */
314 	geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;
315 
316 	geo->sheight = c_height;
317 	geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
318 	sr = c_height >> !both_fields;
319 	sr = (sr * 512U + (height >> 1)) / height - 512;
320 	geo->vscale = (0x10000UL - sr) & 0x1fff;
321 	geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;
322 	geo->vtotal = tvnorm->vtotal;
323 
324 	geo->crop = (((geo->width   >> 8) & 0x03) |
325 		     ((geo->hdelay  >> 6) & 0x0c) |
326 		     ((geo->sheight >> 4) & 0x30) |
327 		     ((geo->vdelay  >> 2) & 0xc0));
328 
329 	if (btv->opt_combfilter) {
330 		geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
331 		geo->comb = (width < 769) ? 1 : 0;
332 	} else {
333 		geo->vtc  = 0;
334 		geo->comb = 0;
335 	}
336 }
337 
338 static void
339 bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
340 {
341 	int off = odd ? 0x80 : 0x00;
342 
343 	if (geo->comb)
344 		btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
345 	else
346 		btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
347 
348 	btwrite(geo->vtc,             BT848_E_VTC+off);
349 	btwrite(geo->hscale >> 8,     BT848_E_HSCALE_HI+off);
350 	btwrite(geo->hscale & 0xff,   BT848_E_HSCALE_LO+off);
351 	btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
352 	btwrite(geo->vscale & 0xff,   BT848_E_VSCALE_LO+off);
353 	btwrite(geo->width & 0xff,    BT848_E_HACTIVE_LO+off);
354 	btwrite(geo->hdelay & 0xff,   BT848_E_HDELAY_LO+off);
355 	btwrite(geo->sheight & 0xff,  BT848_E_VACTIVE_LO+off);
356 	btwrite(geo->vdelay & 0xff,   BT848_E_VDELAY_LO+off);
357 	btwrite(geo->crop,            BT848_E_CROP+off);
358 	btwrite(geo->vtotal>>8,       BT848_VTOTAL_HI);
359 	btwrite(geo->vtotal & 0xff,   BT848_VTOTAL_LO);
360 }
361 
362 /* ---------------------------------------------------------- */
363 /* risc group / risc main loop / dma management               */
364 
365 static void bttv_set_risc_status(struct bttv *btv)
366 {
367 	unsigned long cmd = BT848_RISC_JUMP;
368 	if (btv->loop_irq) {
369 		cmd |= BT848_RISC_IRQ;
370 		cmd |= (btv->loop_irq  & 0x0f) << 16;
371 		cmd |= (~btv->loop_irq & 0x0f) << 20;
372 	}
373 	btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
374 }
375 
376 static void bttv_set_irq_timer(struct bttv *btv)
377 {
378 	if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi)
379 		mod_timer(&btv->timeout, jiffies + BTTV_TIMEOUT);
380 	else
381 		del_timer(&btv->timeout);
382 }
383 
384 static int bttv_set_capture_control(struct bttv *btv, int start_capture)
385 {
386 	int capctl = 0;
387 
388 	if (btv->curr.top || btv->curr.bottom)
389 		capctl = BT848_CAP_CTL_CAPTURE_ODD |
390 			 BT848_CAP_CTL_CAPTURE_EVEN;
391 
392 	if (btv->cvbi)
393 		capctl |= BT848_CAP_CTL_CAPTURE_VBI_ODD |
394 			  BT848_CAP_CTL_CAPTURE_VBI_EVEN;
395 
396 	capctl |= start_capture;
397 
398 	btaor(capctl, ~0x0f, BT848_CAP_CTL);
399 
400 	return capctl;
401 }
402 
403 static void bttv_start_dma(struct bttv *btv)
404 {
405 	if (btv->dma_on)
406 		return;
407 	btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
408 	btor(BT848_GPIO_DMA_CTL_RISC_ENABLE | BT848_GPIO_DMA_CTL_FIFO_ENABLE,
409 	     BT848_GPIO_DMA_CTL);
410 	btv->dma_on = 1;
411 }
412 
413 static void bttv_stop_dma(struct bttv *btv)
414 {
415 	if (!btv->dma_on)
416 		return;
417 	btand(~(BT848_GPIO_DMA_CTL_RISC_ENABLE |
418 		BT848_GPIO_DMA_CTL_FIFO_ENABLE), BT848_GPIO_DMA_CTL);
419 	btv->dma_on = 0;
420 }
421 
422 void bttv_set_dma(struct bttv *btv, int start_capture)
423 {
424 	int capctl = 0;
425 
426 	bttv_set_risc_status(btv);
427 	bttv_set_irq_timer(btv);
428 	capctl = bttv_set_capture_control(btv, start_capture);
429 
430 	if (capctl)
431 		bttv_start_dma(btv);
432 	else
433 		bttv_stop_dma(btv);
434 
435 	d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
436 		 btv->c.nr,capctl,btv->loop_irq,
437 		 btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
438 		 btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
439 		 btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,
440 		 btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
441 }
442 
443 int
444 bttv_risc_init_main(struct bttv *btv)
445 {
446 	int rc;
447 
448 	if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
449 		return rc;
450 	dprintk("%d: risc main @ %08llx\n",
451 		btv->c.nr, (unsigned long long)btv->main.dma);
452 
453 	btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
454 				       BT848_FIFO_STATUS_VRE);
455 	btv->main.cpu[1] = cpu_to_le32(0);
456 	btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
457 	btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
458 
459 	/* top field */
460 	btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
461 	btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
462 	btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
463 	btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
464 
465 	btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
466 				       BT848_FIFO_STATUS_VRO);
467 	btv->main.cpu[9] = cpu_to_le32(0);
468 
469 	/* bottom field */
470 	btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
471 	btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
472 	btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
473 	btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
474 
475 	/* jump back to top field */
476 	btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
477 	btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
478 
479 	return 0;
480 }
481 
482 int
483 bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
484 	       int irqflags)
485 {
486 	unsigned long cmd;
487 	unsigned long next = btv->main.dma + ((slot+2) << 2);
488 
489 	if (NULL == risc) {
490 		d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
491 		btv->main.cpu[slot+1] = cpu_to_le32(next);
492 	} else {
493 		d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
494 			 btv->c.nr, risc, slot,
495 			 (unsigned long long)risc->dma, irqflags);
496 		cmd = BT848_RISC_JUMP;
497 		if (irqflags) {
498 			cmd |= BT848_RISC_IRQ;
499 			cmd |= (irqflags  & 0x0f) << 16;
500 			cmd |= (~irqflags & 0x0f) << 20;
501 		}
502 		risc->jmp[0] = cpu_to_le32(cmd);
503 		risc->jmp[1] = cpu_to_le32(next);
504 		btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
505 	}
506 	return 0;
507 }
508 
509 int bttv_buffer_risc_vbi(struct bttv *btv, struct bttv_buffer *buf)
510 {
511 	int r = 0;
512 	unsigned int offset;
513 	unsigned int bpl = 2044; /* max. vbipack */
514 	unsigned int padding = VBI_BPL - bpl;
515 	unsigned int skip_lines0 = 0;
516 	unsigned int skip_lines1 = 0;
517 	unsigned int min_vdelay = MIN_VDELAY;
518 
519 	const struct bttv_tvnorm *tvnorm = btv->vbi_fmt.tvnorm;
520 	struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vbuf.vb2_buf, 0);
521 	struct scatterlist *list = sgt->sgl;
522 
523 	if (btv->vbi_fmt.fmt.count[0] > 0)
524 		skip_lines0 = max(0, (btv->vbi_fmt.fmt.start[0] -
525 					tvnorm->vbistart[0]));
526 	if (btv->vbi_fmt.fmt.count[1] > 0)
527 		skip_lines1 = max(0, (btv->vbi_fmt.fmt.start[1] -
528 					tvnorm->vbistart[1]));
529 
530 	if (btv->vbi_fmt.fmt.count[0] > 0) {
531 		r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, padding,
532 				     skip_lines0, btv->vbi_fmt.fmt.count[0]);
533 		if (r)
534 			return r;
535 	}
536 
537 	if (btv->vbi_fmt.fmt.count[1] > 0) {
538 		offset = btv->vbi_fmt.fmt.count[0] * VBI_BPL;
539 		r = bttv_risc_packed(btv, &buf->bottom, list, offset, bpl,
540 				     padding, skip_lines1,
541 				     btv->vbi_fmt.fmt.count[1]);
542 		if (r)
543 			return r;
544 	}
545 
546 	if (btv->vbi_fmt.end >= tvnorm->cropcap.bounds.top)
547 		min_vdelay += btv->vbi_fmt.end - tvnorm->cropcap.bounds.top;
548 
549 	/* For bttv_buffer_activate_vbi(). */
550 	buf->geo.vdelay = min_vdelay;
551 
552 	return r;
553 }
554 
555 int
556 bttv_buffer_activate_vbi(struct bttv *btv,
557 			 struct bttv_buffer *vbi)
558 {
559 	struct btcx_riscmem *top;
560 	struct btcx_riscmem *bottom;
561 	int top_irq_flags;
562 	int bottom_irq_flags;
563 
564 	top = NULL;
565 	bottom = NULL;
566 	top_irq_flags = 0;
567 	bottom_irq_flags = 0;
568 
569 	if (vbi) {
570 		unsigned int crop, vdelay;
571 
572 		list_del(&vbi->list);
573 
574 		/* VDELAY is start of video, end of VBI capturing. */
575 		crop = btread(BT848_E_CROP);
576 		vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
577 
578 		if (vbi->geo.vdelay > vdelay) {
579 			vdelay = vbi->geo.vdelay & 0xfe;
580 			crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
581 
582 			btwrite(vdelay, BT848_E_VDELAY_LO);
583 			btwrite(crop,	BT848_E_CROP);
584 			btwrite(vdelay, BT848_O_VDELAY_LO);
585 			btwrite(crop,	BT848_O_CROP);
586 		}
587 
588 		if (btv->vbi_count[0] > 0) {
589 			top = &vbi->top;
590 			top_irq_flags = 4;
591 		}
592 
593 		if (btv->vbi_count[1] > 0) {
594 			top_irq_flags = 0;
595 			bottom = &vbi->bottom;
596 			bottom_irq_flags = 4;
597 		}
598 	}
599 
600 	bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
601 	bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
602 
603 	return 0;
604 }
605 
606 int
607 bttv_buffer_activate_video(struct bttv *btv,
608 			   struct bttv_buffer_set *set)
609 {
610 	/* video capture */
611 	if (NULL != set->top  &&  NULL != set->bottom) {
612 		if (set->top == set->bottom) {
613 			if (set->top->list.next)
614 				list_del(&set->top->list);
615 		} else {
616 			if (set->top->list.next)
617 				list_del(&set->top->list);
618 			if (set->bottom->list.next)
619 				list_del(&set->bottom->list);
620 		}
621 		bttv_apply_geo(btv, &set->top->geo, 1);
622 		bttv_apply_geo(btv, &set->bottom->geo,0);
623 		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
624 			       set->top_irq);
625 		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
626 			       set->frame_irq);
627 		btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
628 		      ~0xff, BT848_COLOR_FMT);
629 		btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
630 		      ~0x0f, BT848_COLOR_CTL);
631 	} else if (NULL != set->top) {
632 		if (set->top->list.next)
633 			list_del(&set->top->list);
634 		bttv_apply_geo(btv, &set->top->geo,1);
635 		bttv_apply_geo(btv, &set->top->geo,0);
636 		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
637 			       set->frame_irq);
638 		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,           0);
639 		btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
640 		btaor(set->top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
641 	} else if (NULL != set->bottom) {
642 		if (set->bottom->list.next)
643 			list_del(&set->bottom->list);
644 		bttv_apply_geo(btv, &set->bottom->geo,1);
645 		bttv_apply_geo(btv, &set->bottom->geo,0);
646 		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
647 		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
648 			       set->frame_irq);
649 		btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
650 		btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
651 	} else {
652 		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
653 		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
654 	}
655 	return 0;
656 }
657 
658 /* ---------------------------------------------------------- */
659 
660 /* calculate geometry, build risc code */
661 int
662 bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
663 {
664 	int r = 0;
665 	const struct bttv_tvnorm *tvnorm = bttv_tvnorms + btv->tvnorm;
666 	struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vbuf.vb2_buf, 0);
667 	struct scatterlist *list = sgt->sgl;
668 	unsigned long size = (btv->fmt->depth * btv->width * btv->height) >> 3;
669 
670 	/* packed pixel modes */
671 	if (btv->fmt->flags & FORMAT_FLAGS_PACKED) {
672 		int bpl = (btv->fmt->depth >> 3) * btv->width;
673 		int bpf = bpl * (btv->height >> 1);
674 
675 		bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
676 			      V4L2_FIELD_HAS_BOTH(buf->vbuf.field), tvnorm,
677 			      &btv->crop[!!btv->do_crop].rect);
678 		switch (buf->vbuf.field) {
679 		case V4L2_FIELD_TOP:
680 			r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,
681 					     0, btv->height);
682 			break;
683 		case V4L2_FIELD_BOTTOM:
684 			r = bttv_risc_packed(btv, &buf->bottom, list, 0, bpl,
685 					     0, 0, btv->height);
686 			break;
687 		case V4L2_FIELD_INTERLACED:
688 			r = bttv_risc_packed(btv, &buf->top, list, 0, bpl,
689 					     bpl, 0, btv->height >> 1);
690 			r = bttv_risc_packed(btv, &buf->bottom, list, bpl,
691 					     bpl, bpl, 0, btv->height >> 1);
692 			break;
693 		case V4L2_FIELD_SEQ_TB:
694 			r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,
695 					     0, btv->height >> 1);
696 			r = bttv_risc_packed(btv, &buf->bottom, list, bpf,
697 					     bpl, 0, 0, btv->height >> 1);
698 			break;
699 		default:
700 			WARN_ON(1);
701 			return -EINVAL;
702 		}
703 	}
704 	/* planar modes */
705 	if (btv->fmt->flags & FORMAT_FLAGS_PLANAR) {
706 		int uoffset, voffset;
707 		int ypadding, cpadding, lines;
708 
709 		/* calculate chroma offsets */
710 		uoffset = btv->width * btv->height;
711 		voffset = btv->width * btv->height;
712 		if (btv->fmt->flags & FORMAT_FLAGS_CrCb) {
713 			/* Y-Cr-Cb plane order */
714 			uoffset >>= btv->fmt->hshift;
715 			uoffset >>= btv->fmt->vshift;
716 			uoffset  += voffset;
717 		} else {
718 			/* Y-Cb-Cr plane order */
719 			voffset >>= btv->fmt->hshift;
720 			voffset >>= btv->fmt->vshift;
721 			voffset  += uoffset;
722 		}
723 		switch (buf->vbuf.field) {
724 		case V4L2_FIELD_TOP:
725 			bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
726 				      0, tvnorm,
727 				      &btv->crop[!!btv->do_crop].rect);
728 			r = bttv_risc_planar(btv, &buf->top, list, 0,
729 					     btv->width, 0, btv->height,
730 					     uoffset, voffset,
731 					     btv->fmt->hshift,
732 					     btv->fmt->vshift, 0);
733 			break;
734 		case V4L2_FIELD_BOTTOM:
735 			bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
736 				      0, tvnorm,
737 				      &btv->crop[!!btv->do_crop].rect);
738 			r = bttv_risc_planar(btv, &buf->bottom, list, 0,
739 					     btv->width, 0, btv->height,
740 					     uoffset, voffset,
741 					     btv->fmt->hshift,
742 					     btv->fmt->vshift, 0);
743 			break;
744 		case V4L2_FIELD_INTERLACED:
745 			bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
746 				      1, tvnorm,
747 				      &btv->crop[!!btv->do_crop].rect);
748 			lines = btv->height >> 1;
749 			ypadding = btv->width;
750 			cpadding = btv->width >> btv->fmt->hshift;
751 			r = bttv_risc_planar(btv, &buf->top, list, 0,
752 					     btv->width, ypadding, lines,
753 					     uoffset, voffset,
754 					     btv->fmt->hshift,
755 					     btv->fmt->vshift, cpadding);
756 
757 			r = bttv_risc_planar(btv, &buf->bottom, list,
758 					     ypadding, btv->width, ypadding,
759 					     lines,  uoffset + cpadding,
760 					     voffset + cpadding,
761 					     btv->fmt->hshift,
762 					     btv->fmt->vshift, cpadding);
763 			break;
764 		case V4L2_FIELD_SEQ_TB:
765 			bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
766 				      1, tvnorm,
767 				      &btv->crop[!!btv->do_crop].rect);
768 			lines = btv->height >> 1;
769 			ypadding = btv->width;
770 			cpadding = btv->width >> btv->fmt->hshift;
771 			r = bttv_risc_planar(btv, &buf->top, list, 0,
772 					     btv->width, 0, lines,
773 					     uoffset >> 1, voffset >> 1,
774 					     btv->fmt->hshift,
775 					     btv->fmt->vshift, 0);
776 			r = bttv_risc_planar(btv, &buf->bottom, list,
777 					     lines * ypadding,
778 					     btv->width, 0, lines,
779 					     lines * ypadding + (uoffset >> 1),
780 					     lines * ypadding + (voffset >> 1),
781 					     btv->fmt->hshift,
782 					     btv->fmt->vshift, 0);
783 			break;
784 		default:
785 			WARN_ON(1);
786 			return -EINVAL;
787 		}
788 	}
789 	/* raw data */
790 	if (btv->fmt->flags & FORMAT_FLAGS_RAW) {
791 		/* build risc code */
792 		buf->vbuf.field = V4L2_FIELD_SEQ_TB;
793 		bttv_calc_geo(btv, &buf->geo, tvnorm->swidth, tvnorm->sheight,
794 			      1, tvnorm, &btv->crop[!!btv->do_crop].rect);
795 		r = bttv_risc_packed(btv, &buf->top, list, 0, RAW_BPL, 0, 0,
796 				     RAW_LINES);
797 		r = bttv_risc_packed(btv, &buf->bottom, list, size / 2,
798 				     RAW_BPL, 0, 0, RAW_LINES);
799 	}
800 
801 	/* copy format info */
802 	buf->btformat = btv->fmt->btformat;
803 	buf->btswap   = btv->fmt->btswap;
804 
805 	return r;
806 }
807