Merge remote-tracking branch 'moduleh/module.h-split'
[linux-2.6/next.git] / drivers / media / video / bt8xx / bttv-risc.c
blob9b57d091da48cede48cf7eca3e1976a96521a854
1 /*
3 bttv-risc.c -- interfaces to other kernel modules
5 bttv risc code handling
6 - memory management
7 - generation
9 (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org>
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.
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.
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.
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>
37 #include "bttvp.h"
39 #define VCR_HACK_LINES 4
41 /* ---------------------------------------------------------- */
42 /* risc code generators */
44 int
45 bttv_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)
51 u32 instructions,line,todo;
52 struct scatterlist *sg;
53 __le32 *rp;
54 int rc;
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;
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);
72 while (skip_lines-- > 0) {
73 *(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |
74 BT848_RISC_EOL | bpl);
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++;
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++;
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;
114 offset += padding;
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;
123 static int
124 bttv_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)
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;
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;
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);
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;
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++;
190 while (uoffset && uoffset >= sg_dma_len(usg)) {
191 uoffset -= sg_dma_len(usg);
192 usg++;
194 while (voffset && voffset >= sg_dma_len(vsg)) {
195 voffset -= sg_dma_len(vsg);
196 vsg++;
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;
212 if (ybpl == todo)
213 ri |= BT848_RISC_SOL;
214 if (ylen == todo)
215 ri |= BT848_RISC_EOL;
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;
230 yoffset += ypadding;
231 if (chroma) {
232 uoffset += cpadding;
233 voffset += cpadding;
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;
243 static int
244 bttv_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)
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;
255 /* skip list for window clipping */
256 if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
257 return -ENOMEM;
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;
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);
274 addr = (unsigned long)btv->fbuf.base;
275 addr += btv->fbuf.fmt.bytesperline * ov->w.top;
276 addr += (fmt->depth >> 3) * ov->w.left;
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;
289 /* calculate clipping */
290 if (line > maxy)
291 btcx_calc_skips(line, ov->w.width, &maxy,
292 skips, &nskips, ov->clips, ov->nclips);
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++;
307 if (BT848_RISC_WRITE == ri)
308 ra = addr + (fmt->depth>>3)*start;
309 else
310 ra = 0;
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);
318 *(rp++)=cpu_to_le32(ri);
319 if (0 != ra)
320 *(rp++)=cpu_to_le32(ra);
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;
331 /* ---------------------------------------------------------- */
333 static void
334 bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
335 int width, int height, int interleaved,
336 const struct bttv_tvnorm *tvnorm)
338 u32 xsf, sr;
339 int vdelay;
341 int swidth = tvnorm->swidth;
342 int totalwidth = tvnorm->totalwidth;
343 int scaledtwidth = tvnorm->scaledtwidth;
345 if (btv->input == btv->dig) {
346 swidth = 720;
347 totalwidth = 858;
348 scaledtwidth = 858;
351 vdelay = tvnorm->vdelay;
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;
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;
377 static void
378 bttv_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)
386 unsigned int c_width;
387 unsigned int c_height;
388 u32 sr;
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;
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);
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;
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;
419 geo->crop = (((geo->width >> 8) & 0x03) |
420 ((geo->hdelay >> 6) & 0x0c) |
421 ((geo->sheight >> 4) & 0x30) |
422 ((geo->vdelay >> 2) & 0xc0));
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;
433 static void
434 bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
436 int off = odd ? 0x80 : 0x00;
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);
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);
457 /* ---------------------------------------------------------- */
458 /* risc group / risc main loop / dma management */
460 void
461 bttv_set_dma(struct bttv *btv, int override)
463 unsigned long cmd;
464 int capctl;
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;
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;
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);
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;
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);
495 btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
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;
510 return;
514 bttv_risc_init_main(struct bttv *btv)
516 int rc;
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);
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));
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));
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);
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));
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));
549 return 0;
553 bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
554 int irqflags)
556 unsigned long cmd;
557 unsigned long next = btv->main.dma + ((slot+2) << 2);
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;
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);
576 return 0;
579 void
580 bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
582 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
584 BUG_ON(in_interrupt());
585 videobuf_waiton(q, &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;
594 bttv_buffer_activate_vbi(struct bttv *btv,
595 struct bttv_buffer *vbi)
597 struct btcx_riscmem *top;
598 struct btcx_riscmem *bottom;
599 int top_irq_flags;
600 int bottom_irq_flags;
602 top = NULL;
603 bottom = NULL;
604 top_irq_flags = 0;
605 bottom_irq_flags = 0;
607 if (vbi) {
608 unsigned int crop, vdelay;
610 vbi->vb.state = VIDEOBUF_ACTIVE;
611 list_del(&vbi->vb.queue);
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);
617 if (vbi->geo.vdelay > vdelay) {
618 vdelay = vbi->geo.vdelay & 0xfe;
619 crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
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);
627 if (vbi->vbi_count[0] > 0) {
628 top = &vbi->top;
629 top_irq_flags = 4;
632 if (vbi->vbi_count[1] > 0) {
633 top_irq_flags = 0;
634 bottom = &vbi->bottom;
635 bottom_irq_flags = 4;
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);
642 return 0;
646 bttv_buffer_activate_video(struct bttv *btv,
647 struct bttv_buffer_set *set)
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);
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);
699 return 0;
702 /* ---------------------------------------------------------- */
704 /* calculate geometry, build risc code */
706 bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
708 const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
709 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
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);
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);
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);
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();
753 /* planar modes */
754 if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
755 int uoffset, voffset;
756 int ypadding, cpadding, lines;
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;
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,
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,
838 break;
839 default:
840 BUG();
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);
857 /* copy format info */
858 buf->btformat = buf->fmt->btformat;
859 buf->btswap = buf->fmt->btswap;
860 return 0;
863 /* ---------------------------------------------------------- */
865 /* calculate geometry, build risc code */
867 bttv_overlay_risc(struct bttv *btv,
868 struct bttv_overlay *ov,
869 const struct bttv_format *fmt,
870 struct bttv_buffer *buf)
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);
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);
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();
899 /* copy format info */
900 buf->btformat = fmt->btformat;
901 buf->btswap = fmt->btswap;
902 buf->vb.field = ov->field;
903 return 0;
907 * Local variables:
908 * c-basic-offset: 8
909 * End: