• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/media/video/bt8xx/
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#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/slab.h>
30#include <linux/pci.h>
31#include <linux/vmalloc.h>
32#include <linux/interrupt.h>
33#include <asm/page.h>
34#include <asm/pgtable.h>
35#include <media/v4l2-ioctl.h>
36
37#include "bttvp.h"
38
39#define VCR_HACK_LINES 4
40
41/* ---------------------------------------------------------- */
42/* risc code generators                                       */
43
44int
45bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
46		 struct scatterlist *sglist,
47		 unsigned int offset, unsigned int bpl,
48		 unsigned int padding, unsigned int skip_lines,
49		 unsigned int store_lines)
50{
51	u32 instructions,line,todo;
52	struct scatterlist *sg;
53	__le32 *rp;
54	int rc;
55
56	/* estimate risc mem: worst case is one write per page border +
57	   one write per scan line + sync + jump (all 2 dwords).  padding
58	   can cause next bpl to start close to a page border.  First DMA
59	   region may be smaller than PAGE_SIZE */
60	instructions  = skip_lines * 4;
61	instructions += (1 + ((bpl + padding) * store_lines)
62			 / PAGE_SIZE + store_lines) * 8;
63	instructions += 2 * 8;
64	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions)) < 0)
65		return rc;
66
67	/* sync instruction */
68	rp = risc->cpu;
69	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
70	*(rp++) = cpu_to_le32(0);
71
72	while (skip_lines-- > 0) {
73		*(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |
74				      BT848_RISC_EOL | bpl);
75	}
76
77	/* scan lines */
78	sg = sglist;
79	for (line = 0; line < store_lines; line++) {
80		if ((btv->opt_vcr_hack) &&
81		    (line >= (store_lines - VCR_HACK_LINES)))
82			continue;
83		while (offset && offset >= sg_dma_len(sg)) {
84			offset -= sg_dma_len(sg);
85			sg++;
86		}
87		if (bpl <= sg_dma_len(sg)-offset) {
88			/* fits into current chunk */
89			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
90					    BT848_RISC_EOL|bpl);
91			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
92			offset+=bpl;
93		} else {
94			/* scanline needs to be splitted */
95			todo = bpl;
96			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
97					    (sg_dma_len(sg)-offset));
98			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
99			todo -= (sg_dma_len(sg)-offset);
100			offset = 0;
101			sg++;
102			while (todo > sg_dma_len(sg)) {
103				*(rp++)=cpu_to_le32(BT848_RISC_WRITE|
104						    sg_dma_len(sg));
105				*(rp++)=cpu_to_le32(sg_dma_address(sg));
106				todo -= sg_dma_len(sg);
107				sg++;
108			}
109			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
110					    todo);
111			*(rp++)=cpu_to_le32(sg_dma_address(sg));
112			offset += todo;
113		}
114		offset += padding;
115	}
116
117	/* save pointer to jmp instruction address */
118	risc->jmp = rp;
119	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
120	return 0;
121}
122
123static int
124bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
125		 struct scatterlist *sglist,
126		 unsigned int yoffset,  unsigned int ybpl,
127		 unsigned int ypadding, unsigned int ylines,
128		 unsigned int uoffset,  unsigned int voffset,
129		 unsigned int hshift,   unsigned int vshift,
130		 unsigned int cpadding)
131{
132	unsigned int instructions,line,todo,ylen,chroma;
133	__le32 *rp;
134	u32 ri;
135	struct scatterlist *ysg;
136	struct scatterlist *usg;
137	struct scatterlist *vsg;
138	int topfield = (0 == yoffset);
139	int rc;
140
141	/* estimate risc mem: worst case is one write per page border +
142	   one write per scan line (5 dwords)
143	   plus sync + jump (2 dwords) */
144	instructions  = ((3 + (ybpl + ypadding) * ylines * 2)
145			 / PAGE_SIZE) + ylines;
146	instructions += 2;
147	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
148		return rc;
149
150	/* sync instruction */
151	rp = risc->cpu;
152	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
153	*(rp++) = cpu_to_le32(0);
154
155	/* scan lines */
156	ysg = sglist;
157	usg = sglist;
158	vsg = sglist;
159	for (line = 0; line < ylines; line++) {
160		if ((btv->opt_vcr_hack) &&
161		    (line >= (ylines - VCR_HACK_LINES)))
162			continue;
163		switch (vshift) {
164		case 0:
165			chroma = 1;
166			break;
167		case 1:
168			if (topfield)
169				chroma = ((line & 1) == 0);
170			else
171				chroma = ((line & 1) == 1);
172			break;
173		case 2:
174			if (topfield)
175				chroma = ((line & 3) == 0);
176			else
177				chroma = ((line & 3) == 2);
178			break;
179		default:
180			chroma = 0;
181			break;
182		}
183
184		for (todo = ybpl; todo > 0; todo -= ylen) {
185			/* go to next sg entry if needed */
186			while (yoffset && yoffset >= sg_dma_len(ysg)) {
187				yoffset -= sg_dma_len(ysg);
188				ysg++;
189			}
190			while (uoffset && uoffset >= sg_dma_len(usg)) {
191				uoffset -= sg_dma_len(usg);
192				usg++;
193			}
194			while (voffset && voffset >= sg_dma_len(vsg)) {
195				voffset -= sg_dma_len(vsg);
196				vsg++;
197			}
198
199			/* calculate max number of bytes we can write */
200			ylen = todo;
201			if (yoffset + ylen > sg_dma_len(ysg))
202				ylen = sg_dma_len(ysg) - yoffset;
203			if (chroma) {
204				if (uoffset + (ylen>>hshift) > sg_dma_len(usg))
205					ylen = (sg_dma_len(usg) - uoffset) << hshift;
206				if (voffset + (ylen>>hshift) > sg_dma_len(vsg))
207					ylen = (sg_dma_len(vsg) - voffset) << hshift;
208				ri = BT848_RISC_WRITE123;
209			} else {
210				ri = BT848_RISC_WRITE1S23;
211			}
212			if (ybpl == todo)
213				ri |= BT848_RISC_SOL;
214			if (ylen == todo)
215				ri |= BT848_RISC_EOL;
216
217			/* write risc instruction */
218			*(rp++)=cpu_to_le32(ri | ylen);
219			*(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
220					    (ylen >> hshift));
221			*(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
222			yoffset += ylen;
223			if (chroma) {
224				*(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);
225				uoffset += ylen >> hshift;
226				*(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);
227				voffset += ylen >> hshift;
228			}
229		}
230		yoffset += ypadding;
231		if (chroma) {
232			uoffset += cpadding;
233			voffset += cpadding;
234		}
235	}
236
237	/* save pointer to jmp instruction address */
238	risc->jmp = rp;
239	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
240	return 0;
241}
242
243static int
244bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
245		  const struct bttv_format *fmt, struct bttv_overlay *ov,
246		  int skip_even, int skip_odd)
247{
248	int dwords, rc, line, maxy, start, end;
249	unsigned skip, nskips;
250	struct btcx_skiplist *skips;
251	__le32 *rp;
252	u32 ri,ra;
253	u32 addr;
254
255	/* skip list for window clipping */
256	if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
257		return -ENOMEM;
258
259	/* estimate risc mem: worst case is (1.5*clip+1) * lines instructions
260	   + sync + jump (all 2 dwords) */
261	dwords  = (3 * ov->nclips + 2) *
262		((skip_even || skip_odd) ? (ov->w.height+1)>>1 :  ov->w.height);
263	dwords += 4;
264	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,dwords*4)) < 0) {
265		kfree(skips);
266		return rc;
267	}
268
269	/* sync instruction */
270	rp = risc->cpu;
271	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
272	*(rp++) = cpu_to_le32(0);
273
274	addr  = (unsigned long)btv->fbuf.base;
275	addr += btv->fbuf.fmt.bytesperline * ov->w.top;
276	addr += (fmt->depth >> 3)          * ov->w.left;
277
278	/* scan lines */
279	for (maxy = -1, line = 0; line < ov->w.height;
280	     line++, addr += btv->fbuf.fmt.bytesperline) {
281		if ((btv->opt_vcr_hack) &&
282		     (line >= (ov->w.height - VCR_HACK_LINES)))
283			continue;
284		if ((line%2) == 0  &&  skip_even)
285			continue;
286		if ((line%2) == 1  &&  skip_odd)
287			continue;
288
289		/* calculate clipping */
290		if (line > maxy)
291			btcx_calc_skips(line, ov->w.width, &maxy,
292					skips, &nskips, ov->clips, ov->nclips);
293
294		/* write out risc code */
295		for (start = 0, skip = 0; start < ov->w.width; start = end) {
296			if (skip >= nskips) {
297				ri  = BT848_RISC_WRITE;
298				end = ov->w.width;
299			} else if (start < skips[skip].start) {
300				ri  = BT848_RISC_WRITE;
301				end = skips[skip].start;
302			} else {
303				ri  = BT848_RISC_SKIP;
304				end = skips[skip].end;
305				skip++;
306			}
307			if (BT848_RISC_WRITE == ri)
308				ra = addr + (fmt->depth>>3)*start;
309			else
310				ra = 0;
311
312			if (0 == start)
313				ri |= BT848_RISC_SOL;
314			if (ov->w.width == end)
315				ri |= BT848_RISC_EOL;
316			ri |= (fmt->depth>>3) * (end-start);
317
318			*(rp++)=cpu_to_le32(ri);
319			if (0 != ra)
320				*(rp++)=cpu_to_le32(ra);
321		}
322	}
323
324	/* save pointer to jmp instruction address */
325	risc->jmp = rp;
326	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
327	kfree(skips);
328	return 0;
329}
330
331/* ---------------------------------------------------------- */
332
333static void
334bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
335		  int width, int height, int interleaved,
336		  const struct bttv_tvnorm *tvnorm)
337{
338	u32 xsf, sr;
339	int vdelay;
340
341	int swidth       = tvnorm->swidth;
342	int totalwidth   = tvnorm->totalwidth;
343	int scaledtwidth = tvnorm->scaledtwidth;
344
345	if (btv->input == btv->dig) {
346		swidth       = 720;
347		totalwidth   = 858;
348		scaledtwidth = 858;
349	}
350
351	vdelay = tvnorm->vdelay;
352
353	xsf = (width*scaledtwidth)/swidth;
354	geo->hscale =  ((totalwidth*4096UL)/xsf-4096);
355	geo->hdelay =  tvnorm->hdelayx1;
356	geo->hdelay =  (geo->hdelay*width)/swidth;
357	geo->hdelay &= 0x3fe;
358	sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
359	geo->vscale =  (0x10000UL-sr) & 0x1fff;
360	geo->crop   =  ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
361		((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
362	geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
363	geo->vdelay  =  vdelay;
364	geo->width   =  width;
365	geo->sheight =  tvnorm->sheight;
366	geo->vtotal  =  tvnorm->vtotal;
367
368	if (btv->opt_combfilter) {
369		geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
370		geo->comb = (width < 769) ? 1 : 0;
371	} else {
372		geo->vtc  = 0;
373		geo->comb = 0;
374	}
375}
376
377static void
378bttv_calc_geo		(struct bttv *                  btv,
379			 struct bttv_geometry *         geo,
380			 unsigned int                   width,
381			 unsigned int                   height,
382			 int                            both_fields,
383			 const struct bttv_tvnorm *     tvnorm,
384			 const struct v4l2_rect *       crop)
385{
386	unsigned int c_width;
387	unsigned int c_height;
388	u32 sr;
389
390	if ((crop->left == tvnorm->cropcap.defrect.left
391	     && crop->top == tvnorm->cropcap.defrect.top
392	     && crop->width == tvnorm->cropcap.defrect.width
393	     && crop->height == tvnorm->cropcap.defrect.height
394	     && width <= tvnorm->swidth /* see PAL-Nc et al */)
395	    || btv->input == btv->dig) {
396		bttv_calc_geo_old(btv, geo, width, height,
397				  both_fields, tvnorm);
398		return;
399	}
400
401	/* For bug compatibility the image size checks permit scale
402	   factors > 16. See bttv_crop_calc_limits(). */
403	c_width = min((unsigned int) crop->width, width * 16);
404	c_height = min((unsigned int) crop->height, height * 16);
405
406	geo->width = width;
407	geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;
408	/* Even to store Cb first, odd for Cr. */
409	geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;
410
411	geo->sheight = c_height;
412	geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
413	sr = c_height >> !both_fields;
414	sr = (sr * 512U + (height >> 1)) / height - 512;
415	geo->vscale = (0x10000UL - sr) & 0x1fff;
416	geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;
417	geo->vtotal = tvnorm->vtotal;
418
419	geo->crop = (((geo->width   >> 8) & 0x03) |
420		     ((geo->hdelay  >> 6) & 0x0c) |
421		     ((geo->sheight >> 4) & 0x30) |
422		     ((geo->vdelay  >> 2) & 0xc0));
423
424	if (btv->opt_combfilter) {
425		geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
426		geo->comb = (width < 769) ? 1 : 0;
427	} else {
428		geo->vtc  = 0;
429		geo->comb = 0;
430	}
431}
432
433static void
434bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
435{
436	int off = odd ? 0x80 : 0x00;
437
438	if (geo->comb)
439		btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
440	else
441		btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
442
443	btwrite(geo->vtc,             BT848_E_VTC+off);
444	btwrite(geo->hscale >> 8,     BT848_E_HSCALE_HI+off);
445	btwrite(geo->hscale & 0xff,   BT848_E_HSCALE_LO+off);
446	btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
447	btwrite(geo->vscale & 0xff,   BT848_E_VSCALE_LO+off);
448	btwrite(geo->width & 0xff,    BT848_E_HACTIVE_LO+off);
449	btwrite(geo->hdelay & 0xff,   BT848_E_HDELAY_LO+off);
450	btwrite(geo->sheight & 0xff,  BT848_E_VACTIVE_LO+off);
451	btwrite(geo->vdelay & 0xff,   BT848_E_VDELAY_LO+off);
452	btwrite(geo->crop,            BT848_E_CROP+off);
453	btwrite(geo->vtotal>>8,       BT848_VTOTAL_HI);
454	btwrite(geo->vtotal & 0xff,   BT848_VTOTAL_LO);
455}
456
457/* ---------------------------------------------------------- */
458/* risc group / risc main loop / dma management               */
459
460void
461bttv_set_dma(struct bttv *btv, int override)
462{
463	unsigned long cmd;
464	int capctl;
465
466	btv->cap_ctl = 0;
467	if (NULL != btv->curr.top)      btv->cap_ctl |= 0x02;
468	if (NULL != btv->curr.bottom)   btv->cap_ctl |= 0x01;
469	if (NULL != btv->cvbi)          btv->cap_ctl |= 0x0c;
470
471	capctl  = 0;
472	capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00;  /* capture  */
473	capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00;  /* vbi data */
474	capctl |= override;
475
476	d2printk(KERN_DEBUG
477		 "bttv%d: capctl=%x lirq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",
478		 btv->c.nr,capctl,btv->loop_irq,
479		 btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
480		 btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
481		 btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,
482		 btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
483
484	cmd = BT848_RISC_JUMP;
485	if (btv->loop_irq) {
486		cmd |= BT848_RISC_IRQ;
487		cmd |= (btv->loop_irq  & 0x0f) << 16;
488		cmd |= (~btv->loop_irq & 0x0f) << 20;
489	}
490	if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
491		mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
492	} else {
493		del_timer(&btv->timeout);
494	}
495	btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
496
497	btaor(capctl, ~0x0f, BT848_CAP_CTL);
498	if (capctl) {
499		if (btv->dma_on)
500			return;
501		btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
502		btor(3, BT848_GPIO_DMA_CTL);
503		btv->dma_on = 1;
504	} else {
505		if (!btv->dma_on)
506			return;
507		btand(~3, BT848_GPIO_DMA_CTL);
508		btv->dma_on = 0;
509	}
510	return;
511}
512
513int
514bttv_risc_init_main(struct bttv *btv)
515{
516	int rc;
517
518	if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
519		return rc;
520	dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n",
521		btv->c.nr,(unsigned long long)btv->main.dma);
522
523	btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
524				       BT848_FIFO_STATUS_VRE);
525	btv->main.cpu[1] = cpu_to_le32(0);
526	btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
527	btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
528
529	/* top field */
530	btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
531	btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
532	btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
533	btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
534
535	btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
536				       BT848_FIFO_STATUS_VRO);
537	btv->main.cpu[9] = cpu_to_le32(0);
538
539	/* bottom field */
540	btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
541	btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
542	btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
543	btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
544
545	/* jump back to top field */
546	btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
547	btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
548
549	return 0;
550}
551
552int
553bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
554	       int irqflags)
555{
556	unsigned long cmd;
557	unsigned long next = btv->main.dma + ((slot+2) << 2);
558
559	if (NULL == risc) {
560		d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=NULL\n",
561			 btv->c.nr,risc,slot);
562		btv->main.cpu[slot+1] = cpu_to_le32(next);
563	} else {
564		d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n",
565			 btv->c.nr,risc,slot,(unsigned long long)risc->dma,irqflags);
566		cmd = BT848_RISC_JUMP;
567		if (irqflags) {
568			cmd |= BT848_RISC_IRQ;
569			cmd |= (irqflags  & 0x0f) << 16;
570			cmd |= (~irqflags & 0x0f) << 20;
571		}
572		risc->jmp[0] = cpu_to_le32(cmd);
573		risc->jmp[1] = cpu_to_le32(next);
574		btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
575	}
576	return 0;
577}
578
579void
580bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
581{
582	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
583
584	BUG_ON(in_interrupt());
585	videobuf_waiton(&buf->vb,0,0);
586	videobuf_dma_unmap(q->dev, dma);
587	videobuf_dma_free(dma);
588	btcx_riscmem_free(btv->c.pci,&buf->bottom);
589	btcx_riscmem_free(btv->c.pci,&buf->top);
590	buf->vb.state = VIDEOBUF_NEEDS_INIT;
591}
592
593int
594bttv_buffer_activate_vbi(struct bttv *btv,
595			 struct bttv_buffer *vbi)
596{
597	struct btcx_riscmem *top;
598	struct btcx_riscmem *bottom;
599	int top_irq_flags;
600	int bottom_irq_flags;
601
602	top = NULL;
603	bottom = NULL;
604	top_irq_flags = 0;
605	bottom_irq_flags = 0;
606
607	if (vbi) {
608		unsigned int crop, vdelay;
609
610		vbi->vb.state = VIDEOBUF_ACTIVE;
611		list_del(&vbi->vb.queue);
612
613		/* VDELAY is start of video, end of VBI capturing. */
614		crop = btread(BT848_E_CROP);
615		vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
616
617		if (vbi->geo.vdelay > vdelay) {
618			vdelay = vbi->geo.vdelay & 0xfe;
619			crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
620
621			btwrite(vdelay, BT848_E_VDELAY_LO);
622			btwrite(crop,	BT848_E_CROP);
623			btwrite(vdelay, BT848_O_VDELAY_LO);
624			btwrite(crop,	BT848_O_CROP);
625		}
626
627		if (vbi->vbi_count[0] > 0) {
628			top = &vbi->top;
629			top_irq_flags = 4;
630		}
631
632		if (vbi->vbi_count[1] > 0) {
633			top_irq_flags = 0;
634			bottom = &vbi->bottom;
635			bottom_irq_flags = 4;
636		}
637	}
638
639	bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
640	bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
641
642	return 0;
643}
644
645int
646bttv_buffer_activate_video(struct bttv *btv,
647			   struct bttv_buffer_set *set)
648{
649	/* video capture */
650	if (NULL != set->top  &&  NULL != set->bottom) {
651		if (set->top == set->bottom) {
652			set->top->vb.state    = VIDEOBUF_ACTIVE;
653			if (set->top->vb.queue.next)
654				list_del(&set->top->vb.queue);
655		} else {
656			set->top->vb.state    = VIDEOBUF_ACTIVE;
657			set->bottom->vb.state = VIDEOBUF_ACTIVE;
658			if (set->top->vb.queue.next)
659				list_del(&set->top->vb.queue);
660			if (set->bottom->vb.queue.next)
661				list_del(&set->bottom->vb.queue);
662		}
663		bttv_apply_geo(btv, &set->top->geo, 1);
664		bttv_apply_geo(btv, &set->bottom->geo,0);
665		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
666			       set->top_irq);
667		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
668			       set->frame_irq);
669		btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
670		      ~0xff, BT848_COLOR_FMT);
671		btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
672		      ~0x0f, BT848_COLOR_CTL);
673	} else if (NULL != set->top) {
674		set->top->vb.state  = VIDEOBUF_ACTIVE;
675		if (set->top->vb.queue.next)
676			list_del(&set->top->vb.queue);
677		bttv_apply_geo(btv, &set->top->geo,1);
678		bttv_apply_geo(btv, &set->top->geo,0);
679		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
680			       set->frame_irq);
681		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,           0);
682		btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
683		btaor(set->top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
684	} else if (NULL != set->bottom) {
685		set->bottom->vb.state = VIDEOBUF_ACTIVE;
686		if (set->bottom->vb.queue.next)
687			list_del(&set->bottom->vb.queue);
688		bttv_apply_geo(btv, &set->bottom->geo,1);
689		bttv_apply_geo(btv, &set->bottom->geo,0);
690		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
691		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
692			       set->frame_irq);
693		btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
694		btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
695	} else {
696		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
697		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
698	}
699	return 0;
700}
701
702/* ---------------------------------------------------------- */
703
704/* calculate geometry, build risc code */
705int
706bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
707{
708	const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
709	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
710
711	dprintk(KERN_DEBUG
712		"bttv%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(KERN_DEBUG
874		"bttv%d: overlay fields: %s format: %s  size: %dx%d\n",
875		btv->c.nr, v4l2_field_names[buf->vb.field],
876		fmt->name,ov->w.width,ov->w.height);
877
878	/* calculate geometry */
879	bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
880		      V4L2_FIELD_HAS_BOTH(ov->field),
881		      &bttv_tvnorms[ov->tvnorm],&buf->crop);
882
883	/* build risc code */
884	switch (ov->field) {
885	case V4L2_FIELD_TOP:
886		bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 0);
887		break;
888	case V4L2_FIELD_BOTTOM:
889		bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
890		break;
891	case V4L2_FIELD_INTERLACED:
892		bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 1);
893		bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
894		break;
895	default:
896		BUG();
897	}
898
899	/* copy format info */
900	buf->btformat = fmt->btformat;
901	buf->btswap   = fmt->btswap;
902	buf->vb.field = ov->field;
903	return 0;
904}
905
906/*
907 * Local variables:
908 * c-basic-offset: 8
909 * End:
910 */
911