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