xref: /linux/drivers/media/pci/bt8xx/bttv-risc.c (revision 52990390f91c1c39ca742fc8f390b29891d95127)
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 /* ---------------------------------------------------------- */
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 void
364 bttv_set_dma(struct bttv *btv, int override)
365 {
366 	unsigned long cmd;
367 	int capctl;
368 
369 	btv->cap_ctl = 0;
370 	if (NULL != btv->curr.top)      btv->cap_ctl |= 0x02;
371 	if (NULL != btv->curr.bottom)   btv->cap_ctl |= 0x01;
372 	if (NULL != btv->cvbi)          btv->cap_ctl |= 0x0c;
373 
374 	capctl  = 0;
375 	capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00;  /* capture  */
376 	capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00;  /* vbi data */
377 	capctl |= override;
378 
379 	d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
380 		 btv->c.nr,capctl,btv->loop_irq,
381 		 btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
382 		 btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
383 		 btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,
384 		 btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
385 
386 	cmd = BT848_RISC_JUMP;
387 	if (btv->loop_irq) {
388 		cmd |= BT848_RISC_IRQ;
389 		cmd |= (btv->loop_irq  & 0x0f) << 16;
390 		cmd |= (~btv->loop_irq & 0x0f) << 20;
391 	}
392 	if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
393 		mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
394 	} else {
395 		del_timer(&btv->timeout);
396 	}
397 	btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
398 
399 	btaor(capctl, ~0x0f, BT848_CAP_CTL);
400 	if (capctl) {
401 		if (btv->dma_on)
402 			return;
403 		btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
404 		btor(3, BT848_GPIO_DMA_CTL);
405 		btv->dma_on = 1;
406 	} else {
407 		if (!btv->dma_on)
408 			return;
409 		btand(~3, BT848_GPIO_DMA_CTL);
410 		btv->dma_on = 0;
411 	}
412 	return;
413 }
414 
415 int
416 bttv_risc_init_main(struct bttv *btv)
417 {
418 	int rc;
419 
420 	if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
421 		return rc;
422 	dprintk("%d: risc main @ %08llx\n",
423 		btv->c.nr, (unsigned long long)btv->main.dma);
424 
425 	btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
426 				       BT848_FIFO_STATUS_VRE);
427 	btv->main.cpu[1] = cpu_to_le32(0);
428 	btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
429 	btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
430 
431 	/* top field */
432 	btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
433 	btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
434 	btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
435 	btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
436 
437 	btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
438 				       BT848_FIFO_STATUS_VRO);
439 	btv->main.cpu[9] = cpu_to_le32(0);
440 
441 	/* bottom field */
442 	btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
443 	btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
444 	btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
445 	btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
446 
447 	/* jump back to top field */
448 	btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
449 	btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
450 
451 	return 0;
452 }
453 
454 int
455 bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
456 	       int irqflags)
457 {
458 	unsigned long cmd;
459 	unsigned long next = btv->main.dma + ((slot+2) << 2);
460 
461 	if (NULL == risc) {
462 		d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
463 		btv->main.cpu[slot+1] = cpu_to_le32(next);
464 	} else {
465 		d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
466 			 btv->c.nr, risc, slot,
467 			 (unsigned long long)risc->dma, irqflags);
468 		cmd = BT848_RISC_JUMP;
469 		if (irqflags) {
470 			cmd |= BT848_RISC_IRQ;
471 			cmd |= (irqflags  & 0x0f) << 16;
472 			cmd |= (~irqflags & 0x0f) << 20;
473 		}
474 		risc->jmp[0] = cpu_to_le32(cmd);
475 		risc->jmp[1] = cpu_to_le32(next);
476 		btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
477 	}
478 	return 0;
479 }
480 
481 void
482 bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
483 {
484 	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
485 
486 	videobuf_waiton(q, &buf->vb, 0, 0);
487 	videobuf_dma_unmap(q->dev, dma);
488 	videobuf_dma_free(dma);
489 	btcx_riscmem_free(btv->c.pci,&buf->bottom);
490 	btcx_riscmem_free(btv->c.pci,&buf->top);
491 	buf->vb.state = VIDEOBUF_NEEDS_INIT;
492 }
493 
494 int
495 bttv_buffer_activate_vbi(struct bttv *btv,
496 			 struct bttv_buffer *vbi)
497 {
498 	struct btcx_riscmem *top;
499 	struct btcx_riscmem *bottom;
500 	int top_irq_flags;
501 	int bottom_irq_flags;
502 
503 	top = NULL;
504 	bottom = NULL;
505 	top_irq_flags = 0;
506 	bottom_irq_flags = 0;
507 
508 	if (vbi) {
509 		unsigned int crop, vdelay;
510 
511 		vbi->vb.state = VIDEOBUF_ACTIVE;
512 		list_del(&vbi->vb.queue);
513 
514 		/* VDELAY is start of video, end of VBI capturing. */
515 		crop = btread(BT848_E_CROP);
516 		vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
517 
518 		if (vbi->geo.vdelay > vdelay) {
519 			vdelay = vbi->geo.vdelay & 0xfe;
520 			crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
521 
522 			btwrite(vdelay, BT848_E_VDELAY_LO);
523 			btwrite(crop,	BT848_E_CROP);
524 			btwrite(vdelay, BT848_O_VDELAY_LO);
525 			btwrite(crop,	BT848_O_CROP);
526 		}
527 
528 		if (vbi->vbi_count[0] > 0) {
529 			top = &vbi->top;
530 			top_irq_flags = 4;
531 		}
532 
533 		if (vbi->vbi_count[1] > 0) {
534 			top_irq_flags = 0;
535 			bottom = &vbi->bottom;
536 			bottom_irq_flags = 4;
537 		}
538 	}
539 
540 	bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
541 	bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
542 
543 	return 0;
544 }
545 
546 int
547 bttv_buffer_activate_video(struct bttv *btv,
548 			   struct bttv_buffer_set *set)
549 {
550 	/* video capture */
551 	if (NULL != set->top  &&  NULL != set->bottom) {
552 		if (set->top == set->bottom) {
553 			set->top->vb.state    = VIDEOBUF_ACTIVE;
554 			if (set->top->vb.queue.next)
555 				list_del(&set->top->vb.queue);
556 		} else {
557 			set->top->vb.state    = VIDEOBUF_ACTIVE;
558 			set->bottom->vb.state = VIDEOBUF_ACTIVE;
559 			if (set->top->vb.queue.next)
560 				list_del(&set->top->vb.queue);
561 			if (set->bottom->vb.queue.next)
562 				list_del(&set->bottom->vb.queue);
563 		}
564 		bttv_apply_geo(btv, &set->top->geo, 1);
565 		bttv_apply_geo(btv, &set->bottom->geo,0);
566 		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
567 			       set->top_irq);
568 		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
569 			       set->frame_irq);
570 		btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
571 		      ~0xff, BT848_COLOR_FMT);
572 		btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
573 		      ~0x0f, BT848_COLOR_CTL);
574 	} else if (NULL != set->top) {
575 		set->top->vb.state  = VIDEOBUF_ACTIVE;
576 		if (set->top->vb.queue.next)
577 			list_del(&set->top->vb.queue);
578 		bttv_apply_geo(btv, &set->top->geo,1);
579 		bttv_apply_geo(btv, &set->top->geo,0);
580 		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
581 			       set->frame_irq);
582 		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,           0);
583 		btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
584 		btaor(set->top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
585 	} else if (NULL != set->bottom) {
586 		set->bottom->vb.state = VIDEOBUF_ACTIVE;
587 		if (set->bottom->vb.queue.next)
588 			list_del(&set->bottom->vb.queue);
589 		bttv_apply_geo(btv, &set->bottom->geo,1);
590 		bttv_apply_geo(btv, &set->bottom->geo,0);
591 		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
592 		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
593 			       set->frame_irq);
594 		btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
595 		btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
596 	} else {
597 		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
598 		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
599 	}
600 	return 0;
601 }
602 
603 /* ---------------------------------------------------------- */
604 
605 /* calculate geometry, build risc code */
606 int
607 bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
608 {
609 	const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
610 	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
611 
612 	dprintk("%d: buffer field: %s  format: 0x%08x  size: %dx%d\n",
613 		btv->c.nr, v4l2_field_names[buf->vb.field],
614 		buf->fmt->fourcc, buf->vb.width, buf->vb.height);
615 
616 	/* packed pixel modes */
617 	if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
618 		int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
619 		int bpf = bpl * (buf->vb.height >> 1);
620 
621 		bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
622 			      V4L2_FIELD_HAS_BOTH(buf->vb.field),
623 			      tvnorm,&buf->crop);
624 
625 		switch (buf->vb.field) {
626 		case V4L2_FIELD_TOP:
627 			bttv_risc_packed(btv,&buf->top,dma->sglist,
628 					 /* offset */ 0,bpl,
629 					 /* padding */ 0,/* skip_lines */ 0,
630 					 buf->vb.height);
631 			break;
632 		case V4L2_FIELD_BOTTOM:
633 			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
634 					 0,bpl,0,0,buf->vb.height);
635 			break;
636 		case V4L2_FIELD_INTERLACED:
637 			bttv_risc_packed(btv,&buf->top,dma->sglist,
638 					 0,bpl,bpl,0,buf->vb.height >> 1);
639 			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
640 					 bpl,bpl,bpl,0,buf->vb.height >> 1);
641 			break;
642 		case V4L2_FIELD_SEQ_TB:
643 			bttv_risc_packed(btv,&buf->top,dma->sglist,
644 					 0,bpl,0,0,buf->vb.height >> 1);
645 			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
646 					 bpf,bpl,0,0,buf->vb.height >> 1);
647 			break;
648 		default:
649 			BUG();
650 		}
651 	}
652 
653 	/* planar modes */
654 	if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
655 		int uoffset, voffset;
656 		int ypadding, cpadding, lines;
657 
658 		/* calculate chroma offsets */
659 		uoffset = buf->vb.width * buf->vb.height;
660 		voffset = buf->vb.width * buf->vb.height;
661 		if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
662 			/* Y-Cr-Cb plane order */
663 			uoffset >>= buf->fmt->hshift;
664 			uoffset >>= buf->fmt->vshift;
665 			uoffset  += voffset;
666 		} else {
667 			/* Y-Cb-Cr plane order */
668 			voffset >>= buf->fmt->hshift;
669 			voffset >>= buf->fmt->vshift;
670 			voffset  += uoffset;
671 		}
672 
673 		switch (buf->vb.field) {
674 		case V4L2_FIELD_TOP:
675 			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
676 				      buf->vb.height,/* both_fields */ 0,
677 				      tvnorm,&buf->crop);
678 			bttv_risc_planar(btv, &buf->top, dma->sglist,
679 					 0,buf->vb.width,0,buf->vb.height,
680 					 uoffset,voffset,buf->fmt->hshift,
681 					 buf->fmt->vshift,0);
682 			break;
683 		case V4L2_FIELD_BOTTOM:
684 			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
685 				      buf->vb.height,0,
686 				      tvnorm,&buf->crop);
687 			bttv_risc_planar(btv, &buf->bottom, dma->sglist,
688 					 0,buf->vb.width,0,buf->vb.height,
689 					 uoffset,voffset,buf->fmt->hshift,
690 					 buf->fmt->vshift,0);
691 			break;
692 		case V4L2_FIELD_INTERLACED:
693 			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
694 				      buf->vb.height,1,
695 				      tvnorm,&buf->crop);
696 			lines    = buf->vb.height >> 1;
697 			ypadding = buf->vb.width;
698 			cpadding = buf->vb.width >> buf->fmt->hshift;
699 			bttv_risc_planar(btv,&buf->top,
700 					 dma->sglist,
701 					 0,buf->vb.width,ypadding,lines,
702 					 uoffset,voffset,
703 					 buf->fmt->hshift,
704 					 buf->fmt->vshift,
705 					 cpadding);
706 			bttv_risc_planar(btv,&buf->bottom,
707 					 dma->sglist,
708 					 ypadding,buf->vb.width,ypadding,lines,
709 					 uoffset+cpadding,
710 					 voffset+cpadding,
711 					 buf->fmt->hshift,
712 					 buf->fmt->vshift,
713 					 cpadding);
714 			break;
715 		case V4L2_FIELD_SEQ_TB:
716 			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
717 				      buf->vb.height,1,
718 				      tvnorm,&buf->crop);
719 			lines    = buf->vb.height >> 1;
720 			ypadding = buf->vb.width;
721 			cpadding = buf->vb.width >> buf->fmt->hshift;
722 			bttv_risc_planar(btv,&buf->top,
723 					 dma->sglist,
724 					 0,buf->vb.width,0,lines,
725 					 uoffset >> 1,
726 					 voffset >> 1,
727 					 buf->fmt->hshift,
728 					 buf->fmt->vshift,
729 					 0);
730 			bttv_risc_planar(btv,&buf->bottom,
731 					 dma->sglist,
732 					 lines * ypadding,buf->vb.width,0,lines,
733 					 lines * ypadding + (uoffset >> 1),
734 					 lines * ypadding + (voffset >> 1),
735 					 buf->fmt->hshift,
736 					 buf->fmt->vshift,
737 					 0);
738 			break;
739 		default:
740 			BUG();
741 		}
742 	}
743 
744 	/* raw data */
745 	if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
746 		/* build risc code */
747 		buf->vb.field = V4L2_FIELD_SEQ_TB;
748 		bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
749 			      1,tvnorm,&buf->crop);
750 		bttv_risc_packed(btv, &buf->top,  dma->sglist,
751 				 /* offset */ 0, RAW_BPL, /* padding */ 0,
752 				 /* skip_lines */ 0, RAW_LINES);
753 		bttv_risc_packed(btv, &buf->bottom, dma->sglist,
754 				 buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
755 	}
756 
757 	/* copy format info */
758 	buf->btformat = buf->fmt->btformat;
759 	buf->btswap   = buf->fmt->btswap;
760 	return 0;
761 }
762