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