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
34int
35bttv_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
113static int
114bttv_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
236static void
237bttv_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
280static void
281bttv_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
336static void
337bttv_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
363static 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
374static 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
382static 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
401static 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
411static 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
420void 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
441int
442bttv_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
480int
481bttv_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
507int 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
553int
554bttv_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
604int
605bttv_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 */
659int
660bttv_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