[go: nahoru, domu]

1/*
2
3    bttv-risc.c  --  interfaces to other kernel modules
4
5    bttv risc code handling
6	- memory management
7	- generation
8
9    (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org>
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
25*/
26
27#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/slab.h>
32#include <linux/pci.h>
33#include <linux/vmalloc.h>
34#include <linux/interrupt.h>
35#include <asm/page.h>
36#include <asm/pgtable.h>
37#include <media/v4l2-ioctl.h>
38
39#include "bttvp.h"
40
41#define VCR_HACK_LINES 4
42
43/* ---------------------------------------------------------- */
44/* risc code generators                                       */
45
46int
47bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
48		 struct scatterlist *sglist,
49		 unsigned int offset, unsigned int bpl,
50		 unsigned int padding, unsigned int skip_lines,
51		 unsigned int store_lines)
52{
53	u32 instructions,line,todo;
54	struct scatterlist *sg;
55	__le32 *rp;
56	int rc;
57
58	/* estimate risc mem: worst case is one write per page border +
59	   one write per scan line + sync + jump (all 2 dwords).  padding
60	   can cause next bpl to start close to a page border.  First DMA
61	   region may be smaller than PAGE_SIZE */
62	instructions  = skip_lines * 4;
63	instructions += (1 + ((bpl + padding) * store_lines)
64			 / PAGE_SIZE + store_lines) * 8;
65	instructions += 2 * 8;
66	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions)) < 0)
67		return rc;
68
69	/* sync instruction */
70	rp = risc->cpu;
71	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
72	*(rp++) = cpu_to_le32(0);
73
74	while (skip_lines-- > 0) {
75		*(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |
76				      BT848_RISC_EOL | bpl);
77	}
78
79	/* scan lines */
80	sg = sglist;
81	for (line = 0; line < store_lines; line++) {
82		if ((btv->opt_vcr_hack) &&
83		    (line >= (store_lines - VCR_HACK_LINES)))
84			continue;
85		while (offset && offset >= sg_dma_len(sg)) {
86			offset -= sg_dma_len(sg);
87			sg++;
88		}
89		if (bpl <= sg_dma_len(sg)-offset) {
90			/* fits into current chunk */
91			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
92					    BT848_RISC_EOL|bpl);
93			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
94			offset+=bpl;
95		} else {
96			/* scanline needs to be splitted */
97			todo = bpl;
98			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
99					    (sg_dma_len(sg)-offset));
100			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
101			todo -= (sg_dma_len(sg)-offset);
102			offset = 0;
103			sg++;
104			while (todo > sg_dma_len(sg)) {
105				*(rp++)=cpu_to_le32(BT848_RISC_WRITE|
106						    sg_dma_len(sg));
107				*(rp++)=cpu_to_le32(sg_dma_address(sg));
108				todo -= sg_dma_len(sg);
109				sg++;
110			}
111			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
112					    todo);
113			*(rp++)=cpu_to_le32(sg_dma_address(sg));
114			offset += todo;
115		}
116		offset += padding;
117	}
118
119	/* save pointer to jmp instruction address */
120	risc->jmp = rp;
121	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
122	return 0;
123}
124
125static int
126bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
127		 struct scatterlist *sglist,
128		 unsigned int yoffset,  unsigned int ybpl,
129		 unsigned int ypadding, unsigned int ylines,
130		 unsigned int uoffset,  unsigned int voffset,
131		 unsigned int hshift,   unsigned int vshift,
132		 unsigned int cpadding)
133{
134	unsigned int instructions,line,todo,ylen,chroma;
135	__le32 *rp;
136	u32 ri;
137	struct scatterlist *ysg;
138	struct scatterlist *usg;
139	struct scatterlist *vsg;
140	int topfield = (0 == yoffset);
141	int rc;
142
143	/* estimate risc mem: worst case is one write per page border +
144	   one write per scan line (5 dwords)
145	   plus sync + jump (2 dwords) */
146	instructions  = ((3 + (ybpl + ypadding) * ylines * 2)
147			 / PAGE_SIZE) + ylines;
148	instructions += 2;
149	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
150		return rc;
151
152	/* sync instruction */
153	rp = risc->cpu;
154	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
155	*(rp++) = cpu_to_le32(0);
156
157	/* scan lines */
158	ysg = sglist;
159	usg = sglist;
160	vsg = sglist;
161	for (line = 0; line < ylines; line++) {
162		if ((btv->opt_vcr_hack) &&
163		    (line >= (ylines - VCR_HACK_LINES)))
164			continue;
165		switch (vshift) {
166		case 0:
167			chroma = 1;
168			break;
169		case 1:
170			if (topfield)
171				chroma = ((line & 1) == 0);
172			else
173				chroma = ((line & 1) == 1);
174			break;
175		case 2:
176			if (topfield)
177				chroma = ((line & 3) == 0);
178			else
179				chroma = ((line & 3) == 2);
180			break;
181		default:
182			chroma = 0;
183			break;
184		}
185
186		for (todo = ybpl; todo > 0; todo -= ylen) {
187			/* go to next sg entry if needed */
188			while (yoffset && yoffset >= sg_dma_len(ysg)) {
189				yoffset -= sg_dma_len(ysg);
190				ysg++;
191			}
192			while (uoffset && uoffset >= sg_dma_len(usg)) {
193				uoffset -= sg_dma_len(usg);
194				usg++;
195			}
196			while (voffset && voffset >= sg_dma_len(vsg)) {
197				voffset -= sg_dma_len(vsg);
198				vsg++;
199			}
200
201			/* calculate max number of bytes we can write */
202			ylen = todo;
203			if (yoffset + ylen > sg_dma_len(ysg))
204				ylen = sg_dma_len(ysg) - yoffset;
205			if (chroma) {
206				if (uoffset + (ylen>>hshift) > sg_dma_len(usg))
207					ylen = (sg_dma_len(usg) - uoffset) << hshift;
208				if (voffset + (ylen>>hshift) > sg_dma_len(vsg))
209					ylen = (sg_dma_len(vsg) - voffset) << hshift;
210				ri = BT848_RISC_WRITE123;
211			} else {
212				ri = BT848_RISC_WRITE1S23;
213			}
214			if (ybpl == todo)
215				ri |= BT848_RISC_SOL;
216			if (ylen == todo)
217				ri |= BT848_RISC_EOL;
218
219			/* write risc instruction */
220			*(rp++)=cpu_to_le32(ri | ylen);
221			*(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
222					    (ylen >> hshift));
223			*(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
224			yoffset += ylen;
225			if (chroma) {
226				*(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);
227				uoffset += ylen >> hshift;
228				*(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);
229				voffset += ylen >> hshift;
230			}
231		}
232		yoffset += ypadding;
233		if (chroma) {
234			uoffset += cpadding;
235			voffset += cpadding;
236		}
237	}
238
239	/* save pointer to jmp instruction address */
240	risc->jmp = rp;
241	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
242	return 0;
243}
244
245static int
246bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
247		  const struct bttv_format *fmt, struct bttv_overlay *ov,
248		  int skip_even, int skip_odd)
249{
250	int dwords, rc, line, maxy, start, end;
251	unsigned skip, nskips;
252	struct btcx_skiplist *skips;
253	__le32 *rp;
254	u32 ri,ra;
255	u32 addr;
256
257	/* skip list for window clipping */
258	if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
259		return -ENOMEM;
260
261	/* estimate risc mem: worst case is (1.5*clip+1) * lines instructions
262	   + sync + jump (all 2 dwords) */
263	dwords  = (3 * ov->nclips + 2) *
264		((skip_even || skip_odd) ? (ov->w.height+1)>>1 :  ov->w.height);
265	dwords += 4;
266	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,dwords*4)) < 0) {
267		kfree(skips);
268		return rc;
269	}
270
271	/* sync instruction */
272	rp = risc->cpu;
273	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
274	*(rp++) = cpu_to_le32(0);
275
276	addr  = (unsigned long)btv->fbuf.base;
277	addr += btv->fbuf.fmt.bytesperline * ov->w.top;
278	addr += (fmt->depth >> 3)          * ov->w.left;
279
280	/* scan lines */
281	for (maxy = -1, line = 0; line < ov->w.height;
282	     line++, addr += btv->fbuf.fmt.bytesperline) {
283		if ((btv->opt_vcr_hack) &&
284		     (line >= (ov->w.height - VCR_HACK_LINES)))
285			continue;
286		if ((line%2) == 0  &&  skip_even)
287			continue;
288		if ((line%2) == 1  &&  skip_odd)
289			continue;
290
291		/* calculate clipping */
292		if (line > maxy)
293			btcx_calc_skips(line, ov->w.width, &maxy,
294					skips, &nskips, ov->clips, ov->nclips);
295
296		/* write out risc code */
297		for (start = 0, skip = 0; start < ov->w.width; start = end) {
298			if (skip >= nskips) {
299				ri  = BT848_RISC_WRITE;
300				end = ov->w.width;
301			} else if (start < skips[skip].start) {
302				ri  = BT848_RISC_WRITE;
303				end = skips[skip].start;
304			} else {
305				ri  = BT848_RISC_SKIP;
306				end = skips[skip].end;
307				skip++;
308			}
309			if (BT848_RISC_WRITE == ri)
310				ra = addr + (fmt->depth>>3)*start;
311			else
312				ra = 0;
313
314			if (0 == start)
315				ri |= BT848_RISC_SOL;
316			if (ov->w.width == end)
317				ri |= BT848_RISC_EOL;
318			ri |= (fmt->depth>>3) * (end-start);
319
320			*(rp++)=cpu_to_le32(ri);
321			if (0 != ra)
322				*(rp++)=cpu_to_le32(ra);
323		}
324	}
325
326	/* save pointer to jmp instruction address */
327	risc->jmp = rp;
328	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
329	kfree(skips);
330	return 0;
331}
332
333/* ---------------------------------------------------------- */
334
335static void
336bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
337		  int width, int height, int interleaved,
338		  const struct bttv_tvnorm *tvnorm)
339{
340	u32 xsf, sr;
341	int vdelay;
342
343	int swidth       = tvnorm->swidth;
344	int totalwidth   = tvnorm->totalwidth;
345	int scaledtwidth = tvnorm->scaledtwidth;
346
347	if (btv->input == btv->dig) {
348		swidth       = 720;
349		totalwidth   = 858;
350		scaledtwidth = 858;
351	}
352
353	vdelay = tvnorm->vdelay;
354
355	xsf = (width*scaledtwidth)/swidth;
356	geo->hscale =  ((totalwidth*4096UL)/xsf-4096);
357	geo->hdelay =  tvnorm->hdelayx1;
358	geo->hdelay =  (geo->hdelay*width)/swidth;
359	geo->hdelay &= 0x3fe;
360	sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
361	geo->vscale =  (0x10000UL-sr) & 0x1fff;
362	geo->crop   =  ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
363		((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
364	geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
365	geo->vdelay  =  vdelay;
366	geo->width   =  width;
367	geo->sheight =  tvnorm->sheight;
368	geo->vtotal  =  tvnorm->vtotal;
369
370	if (btv->opt_combfilter) {
371		geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
372		geo->comb = (width < 769) ? 1 : 0;
373	} else {
374		geo->vtc  = 0;
375		geo->comb = 0;
376	}
377}
378
379static void
380bttv_calc_geo		(struct bttv *                  btv,
381			 struct bttv_geometry *         geo,
382			 unsigned int                   width,
383			 unsigned int                   height,
384			 int                            both_fields,
385			 const struct bttv_tvnorm *     tvnorm,
386			 const struct v4l2_rect *       crop)
387{
388	unsigned int c_width;
389	unsigned int c_height;
390	u32 sr;
391
392	if ((crop->left == tvnorm->cropcap.defrect.left
393	     && crop->top == tvnorm->cropcap.defrect.top
394	     && crop->width == tvnorm->cropcap.defrect.width
395	     && crop->height == tvnorm->cropcap.defrect.height
396	     && width <= tvnorm->swidth /* see PAL-Nc et al */)
397	    || btv->input == btv->dig) {
398		bttv_calc_geo_old(btv, geo, width, height,
399				  both_fields, tvnorm);
400		return;
401	}
402
403	/* For bug compatibility the image size checks permit scale
404	   factors > 16. See bttv_crop_calc_limits(). */
405	c_width = min((unsigned int) crop->width, width * 16);
406	c_height = min((unsigned int) crop->height, height * 16);
407
408	geo->width = width;
409	geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;
410	/* Even to store Cb first, odd for Cr. */
411	geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;
412
413	geo->sheight = c_height;
414	geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
415	sr = c_height >> !both_fields;
416	sr = (sr * 512U + (height >> 1)) / height - 512;
417	geo->vscale = (0x10000UL - sr) & 0x1fff;
418	geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;
419	geo->vtotal = tvnorm->vtotal;
420
421	geo->crop = (((geo->width   >> 8) & 0x03) |
422		     ((geo->hdelay  >> 6) & 0x0c) |
423		     ((geo->sheight >> 4) & 0x30) |
424		     ((geo->vdelay  >> 2) & 0xc0));
425
426	if (btv->opt_combfilter) {
427		geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
428		geo->comb = (width < 769) ? 1 : 0;
429	} else {
430		geo->vtc  = 0;
431		geo->comb = 0;
432	}
433}
434
435static void
436bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
437{
438	int off = odd ? 0x80 : 0x00;
439
440	if (geo->comb)
441		btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
442	else
443		btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
444
445	btwrite(geo->vtc,             BT848_E_VTC+off);
446	btwrite(geo->hscale >> 8,     BT848_E_HSCALE_HI+off);
447	btwrite(geo->hscale & 0xff,   BT848_E_HSCALE_LO+off);
448	btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
449	btwrite(geo->vscale & 0xff,   BT848_E_VSCALE_LO+off);
450	btwrite(geo->width & 0xff,    BT848_E_HACTIVE_LO+off);
451	btwrite(geo->hdelay & 0xff,   BT848_E_HDELAY_LO+off);
452	btwrite(geo->sheight & 0xff,  BT848_E_VACTIVE_LO+off);
453	btwrite(geo->vdelay & 0xff,   BT848_E_VDELAY_LO+off);
454	btwrite(geo->crop,            BT848_E_CROP+off);
455	btwrite(geo->vtotal>>8,       BT848_VTOTAL_HI);
456	btwrite(geo->vtotal & 0xff,   BT848_VTOTAL_LO);
457}
458
459/* ---------------------------------------------------------- */
460/* risc group / risc main loop / dma management               */
461
462void
463bttv_set_dma(struct bttv *btv, int override)
464{
465	unsigned long cmd;
466	int capctl;
467
468	btv->cap_ctl = 0;
469	if (NULL != btv->curr.top)      btv->cap_ctl |= 0x02;
470	if (NULL != btv->curr.bottom)   btv->cap_ctl |= 0x01;
471	if (NULL != btv->cvbi)          btv->cap_ctl |= 0x0c;
472
473	capctl  = 0;
474	capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00;  /* capture  */
475	capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00;  /* vbi data */
476	capctl |= override;
477
478	d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
479		 btv->c.nr,capctl,btv->loop_irq,
480		 btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
481		 btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
482		 btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,
483		 btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
484
485	cmd = BT848_RISC_JUMP;
486	if (btv->loop_irq) {
487		cmd |= BT848_RISC_IRQ;
488		cmd |= (btv->loop_irq  & 0x0f) << 16;
489		cmd |= (~btv->loop_irq & 0x0f) << 20;
490	}
491	if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
492		mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
493	} else {
494		del_timer(&btv->timeout);
495	}
496	btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
497
498	btaor(capctl, ~0x0f, BT848_CAP_CTL);
499	if (capctl) {
500		if (btv->dma_on)
501			return;
502		btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
503		btor(3, BT848_GPIO_DMA_CTL);
504		btv->dma_on = 1;
505	} else {
506		if (!btv->dma_on)
507			return;
508		btand(~3, BT848_GPIO_DMA_CTL);
509		btv->dma_on = 0;
510	}
511	return;
512}
513
514int
515bttv_risc_init_main(struct bttv *btv)
516{
517	int rc;
518
519	if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
520		return rc;
521	dprintk("%d: risc main @ %08llx\n",
522		btv->c.nr, (unsigned long long)btv->main.dma);
523
524	btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
525				       BT848_FIFO_STATUS_VRE);
526	btv->main.cpu[1] = cpu_to_le32(0);
527	btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
528	btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
529
530	/* top field */
531	btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
532	btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
533	btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
534	btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
535
536	btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
537				       BT848_FIFO_STATUS_VRO);
538	btv->main.cpu[9] = cpu_to_le32(0);
539
540	/* bottom field */
541	btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
542	btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
543	btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
544	btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
545
546	/* jump back to top field */
547	btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
548	btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
549
550	return 0;
551}
552
553int
554bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
555	       int irqflags)
556{
557	unsigned long cmd;
558	unsigned long next = btv->main.dma + ((slot+2) << 2);
559
560	if (NULL == risc) {
561		d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
562		btv->main.cpu[slot+1] = cpu_to_le32(next);
563	} else {
564		d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
565			 btv->c.nr, risc, slot,
566			 (unsigned long long)risc->dma, irqflags);
567		cmd = BT848_RISC_JUMP;
568		if (irqflags) {
569			cmd |= BT848_RISC_IRQ;
570			cmd |= (irqflags  & 0x0f) << 16;
571			cmd |= (~irqflags & 0x0f) << 20;
572		}
573		risc->jmp[0] = cpu_to_le32(cmd);
574		risc->jmp[1] = cpu_to_le32(next);
575		btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
576	}
577	return 0;
578}
579
580void
581bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
582{
583	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
584
585	BUG_ON(in_interrupt());
586	videobuf_waiton(q, &buf->vb, 0, 0);
587	videobuf_dma_unmap(q->dev, dma);
588	videobuf_dma_free(dma);
589	btcx_riscmem_free(btv->c.pci,&buf->bottom);
590	btcx_riscmem_free(btv->c.pci,&buf->top);
591	buf->vb.state = VIDEOBUF_NEEDS_INIT;
592}
593
594int
595bttv_buffer_activate_vbi(struct bttv *btv,
596			 struct bttv_buffer *vbi)
597{
598	struct btcx_riscmem *top;
599	struct btcx_riscmem *bottom;
600	int top_irq_flags;
601	int bottom_irq_flags;
602
603	top = NULL;
604	bottom = NULL;
605	top_irq_flags = 0;
606	bottom_irq_flags = 0;
607
608	if (vbi) {
609		unsigned int crop, vdelay;
610
611		vbi->vb.state = VIDEOBUF_ACTIVE;
612		list_del(&vbi->vb.queue);
613
614		/* VDELAY is start of video, end of VBI capturing. */
615		crop = btread(BT848_E_CROP);
616		vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
617
618		if (vbi->geo.vdelay > vdelay) {
619			vdelay = vbi->geo.vdelay & 0xfe;
620			crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
621
622			btwrite(vdelay, BT848_E_VDELAY_LO);
623			btwrite(crop,	BT848_E_CROP);
624			btwrite(vdelay, BT848_O_VDELAY_LO);
625			btwrite(crop,	BT848_O_CROP);
626		}
627
628		if (vbi->vbi_count[0] > 0) {
629			top = &vbi->top;
630			top_irq_flags = 4;
631		}
632
633		if (vbi->vbi_count[1] > 0) {
634			top_irq_flags = 0;
635			bottom = &vbi->bottom;
636			bottom_irq_flags = 4;
637		}
638	}
639
640	bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
641	bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
642
643	return 0;
644}
645
646int
647bttv_buffer_activate_video(struct bttv *btv,
648			   struct bttv_buffer_set *set)
649{
650	/* video capture */
651	if (NULL != set->top  &&  NULL != set->bottom) {
652		if (set->top == set->bottom) {
653			set->top->vb.state    = VIDEOBUF_ACTIVE;
654			if (set->top->vb.queue.next)
655				list_del(&set->top->vb.queue);
656		} else {
657			set->top->vb.state    = VIDEOBUF_ACTIVE;
658			set->bottom->vb.state = VIDEOBUF_ACTIVE;
659			if (set->top->vb.queue.next)
660				list_del(&set->top->vb.queue);
661			if (set->bottom->vb.queue.next)
662				list_del(&set->bottom->vb.queue);
663		}
664		bttv_apply_geo(btv, &set->top->geo, 1);
665		bttv_apply_geo(btv, &set->bottom->geo,0);
666		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
667			       set->top_irq);
668		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
669			       set->frame_irq);
670		btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
671		      ~0xff, BT848_COLOR_FMT);
672		btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
673		      ~0x0f, BT848_COLOR_CTL);
674	} else if (NULL != set->top) {
675		set->top->vb.state  = VIDEOBUF_ACTIVE;
676		if (set->top->vb.queue.next)
677			list_del(&set->top->vb.queue);
678		bttv_apply_geo(btv, &set->top->geo,1);
679		bttv_apply_geo(btv, &set->top->geo,0);
680		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
681			       set->frame_irq);
682		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,           0);
683		btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
684		btaor(set->top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
685	} else if (NULL != set->bottom) {
686		set->bottom->vb.state = VIDEOBUF_ACTIVE;
687		if (set->bottom->vb.queue.next)
688			list_del(&set->bottom->vb.queue);
689		bttv_apply_geo(btv, &set->bottom->geo,1);
690		bttv_apply_geo(btv, &set->bottom->geo,0);
691		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
692		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
693			       set->frame_irq);
694		btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
695		btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
696	} else {
697		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
698		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
699	}
700	return 0;
701}
702
703/* ---------------------------------------------------------- */
704
705/* calculate geometry, build risc code */
706int
707bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
708{
709	const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
710	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
711
712	dprintk("%d: buffer field: %s  format: %s  size: %dx%d\n",
713		btv->c.nr, v4l2_field_names[buf->vb.field],
714		buf->fmt->name, buf->vb.width, buf->vb.height);
715
716	/* packed pixel modes */
717	if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
718		int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
719		int bpf = bpl * (buf->vb.height >> 1);
720
721		bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
722			      V4L2_FIELD_HAS_BOTH(buf->vb.field),
723			      tvnorm,&buf->crop);
724
725		switch (buf->vb.field) {
726		case V4L2_FIELD_TOP:
727			bttv_risc_packed(btv,&buf->top,dma->sglist,
728					 /* offset */ 0,bpl,
729					 /* padding */ 0,/* skip_lines */ 0,
730					 buf->vb.height);
731			break;
732		case V4L2_FIELD_BOTTOM:
733			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
734					 0,bpl,0,0,buf->vb.height);
735			break;
736		case V4L2_FIELD_INTERLACED:
737			bttv_risc_packed(btv,&buf->top,dma->sglist,
738					 0,bpl,bpl,0,buf->vb.height >> 1);
739			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
740					 bpl,bpl,bpl,0,buf->vb.height >> 1);
741			break;
742		case V4L2_FIELD_SEQ_TB:
743			bttv_risc_packed(btv,&buf->top,dma->sglist,
744					 0,bpl,0,0,buf->vb.height >> 1);
745			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
746					 bpf,bpl,0,0,buf->vb.height >> 1);
747			break;
748		default:
749			BUG();
750		}
751	}
752
753	/* planar modes */
754	if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
755		int uoffset, voffset;
756		int ypadding, cpadding, lines;
757
758		/* calculate chroma offsets */
759		uoffset = buf->vb.width * buf->vb.height;
760		voffset = buf->vb.width * buf->vb.height;
761		if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
762			/* Y-Cr-Cb plane order */
763			uoffset >>= buf->fmt->hshift;
764			uoffset >>= buf->fmt->vshift;
765			uoffset  += voffset;
766		} else {
767			/* Y-Cb-Cr plane order */
768			voffset >>= buf->fmt->hshift;
769			voffset >>= buf->fmt->vshift;
770			voffset  += uoffset;
771		}
772
773		switch (buf->vb.field) {
774		case V4L2_FIELD_TOP:
775			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
776				      buf->vb.height,/* both_fields */ 0,
777				      tvnorm,&buf->crop);
778			bttv_risc_planar(btv, &buf->top, dma->sglist,
779					 0,buf->vb.width,0,buf->vb.height,
780					 uoffset,voffset,buf->fmt->hshift,
781					 buf->fmt->vshift,0);
782			break;
783		case V4L2_FIELD_BOTTOM:
784			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
785				      buf->vb.height,0,
786				      tvnorm,&buf->crop);
787			bttv_risc_planar(btv, &buf->bottom, dma->sglist,
788					 0,buf->vb.width,0,buf->vb.height,
789					 uoffset,voffset,buf->fmt->hshift,
790					 buf->fmt->vshift,0);
791			break;
792		case V4L2_FIELD_INTERLACED:
793			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
794				      buf->vb.height,1,
795				      tvnorm,&buf->crop);
796			lines    = buf->vb.height >> 1;
797			ypadding = buf->vb.width;
798			cpadding = buf->vb.width >> buf->fmt->hshift;
799			bttv_risc_planar(btv,&buf->top,
800					 dma->sglist,
801					 0,buf->vb.width,ypadding,lines,
802					 uoffset,voffset,
803					 buf->fmt->hshift,
804					 buf->fmt->vshift,
805					 cpadding);
806			bttv_risc_planar(btv,&buf->bottom,
807					 dma->sglist,
808					 ypadding,buf->vb.width,ypadding,lines,
809					 uoffset+cpadding,
810					 voffset+cpadding,
811					 buf->fmt->hshift,
812					 buf->fmt->vshift,
813					 cpadding);
814			break;
815		case V4L2_FIELD_SEQ_TB:
816			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
817				      buf->vb.height,1,
818				      tvnorm,&buf->crop);
819			lines    = buf->vb.height >> 1;
820			ypadding = buf->vb.width;
821			cpadding = buf->vb.width >> buf->fmt->hshift;
822			bttv_risc_planar(btv,&buf->top,
823					 dma->sglist,
824					 0,buf->vb.width,0,lines,
825					 uoffset >> 1,
826					 voffset >> 1,
827					 buf->fmt->hshift,
828					 buf->fmt->vshift,
829					 0);
830			bttv_risc_planar(btv,&buf->bottom,
831					 dma->sglist,
832					 lines * ypadding,buf->vb.width,0,lines,
833					 lines * ypadding + (uoffset >> 1),
834					 lines * ypadding + (voffset >> 1),
835					 buf->fmt->hshift,
836					 buf->fmt->vshift,
837					 0);
838			break;
839		default:
840			BUG();
841		}
842	}
843
844	/* raw data */
845	if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
846		/* build risc code */
847		buf->vb.field = V4L2_FIELD_SEQ_TB;
848		bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
849			      1,tvnorm,&buf->crop);
850		bttv_risc_packed(btv, &buf->top,  dma->sglist,
851				 /* offset */ 0, RAW_BPL, /* padding */ 0,
852				 /* skip_lines */ 0, RAW_LINES);
853		bttv_risc_packed(btv, &buf->bottom, dma->sglist,
854				 buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
855	}
856
857	/* copy format info */
858	buf->btformat = buf->fmt->btformat;
859	buf->btswap   = buf->fmt->btswap;
860	return 0;
861}
862
863/* ---------------------------------------------------------- */
864
865/* calculate geometry, build risc code */
866int
867bttv_overlay_risc(struct bttv *btv,
868		  struct bttv_overlay *ov,
869		  const struct bttv_format *fmt,
870		  struct bttv_buffer *buf)
871{
872	/* check interleave, bottom+top fields */
873	dprintk("%d: overlay fields: %s format: %s  size: %dx%d\n",
874		btv->c.nr, v4l2_field_names[buf->vb.field],
875		fmt->name, ov->w.width, ov->w.height);
876
877	/* calculate geometry */
878	bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
879		      V4L2_FIELD_HAS_BOTH(ov->field),
880		      &bttv_tvnorms[ov->tvnorm],&buf->crop);
881
882	/* build risc code */
883	switch (ov->field) {
884	case V4L2_FIELD_TOP:
885		bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 0);
886		break;
887	case V4L2_FIELD_BOTTOM:
888		bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
889		break;
890	case V4L2_FIELD_INTERLACED:
891		bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 1);
892		bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
893		break;
894	default:
895		BUG();
896	}
897
898	/* copy format info */
899	buf->btformat = fmt->btformat;
900	buf->btswap   = fmt->btswap;
901	buf->vb.field = ov->field;
902	return 0;
903}
904
905/*
906 * Local variables:
907 * c-basic-offset: 8
908 * End:
909 */
910