f81232: switch to ->get_serial()
[linux/fpc-iii.git] / drivers / media / pci / bt8xx / bttv-risc.c
blob74aff6877d9cd860b123109a80943c5ea7187d89
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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
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>
39 #include "bttvp.h"
41 #define VCR_HACK_LINES 4
43 /* ---------------------------------------------------------- */
44 /* risc code generators */
46 int
47 bttv_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)
53 u32 instructions,line,todo;
54 struct scatterlist *sg;
55 __le32 *rp;
56 int rc;
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;
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);
74 while (skip_lines-- > 0) {
75 *(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |
76 BT848_RISC_EOL | bpl);
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 = sg_next(sg);
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 = sg_next(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 = sg_next(sg);
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;
116 offset += padding;
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;
125 static int
126 bttv_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)
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;
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;
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);
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;
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 = sg_next(ysg);
193 /* calculate max number of bytes we can write */
194 ylen = todo;
195 if (yoffset + ylen > sg_dma_len(ysg))
196 ylen = sg_dma_len(ysg) - yoffset;
197 if (chroma) {
198 while (uoffset && uoffset >= sg_dma_len(usg)) {
199 uoffset -= sg_dma_len(usg);
200 usg = sg_next(usg);
202 while (voffset && voffset >= sg_dma_len(vsg)) {
203 voffset -= sg_dma_len(vsg);
204 vsg = sg_next(vsg);
207 if (uoffset + (ylen>>hshift) > sg_dma_len(usg))
208 ylen = (sg_dma_len(usg) - uoffset) << hshift;
209 if (voffset + (ylen>>hshift) > sg_dma_len(vsg))
210 ylen = (sg_dma_len(vsg) - voffset) << hshift;
211 ri = BT848_RISC_WRITE123;
212 } else {
213 ri = BT848_RISC_WRITE1S23;
215 if (ybpl == todo)
216 ri |= BT848_RISC_SOL;
217 if (ylen == todo)
218 ri |= BT848_RISC_EOL;
220 /* write risc instruction */
221 *(rp++)=cpu_to_le32(ri | ylen);
222 *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
223 (ylen >> hshift));
224 *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
225 yoffset += ylen;
226 if (chroma) {
227 *(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);
228 uoffset += ylen >> hshift;
229 *(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);
230 voffset += ylen >> hshift;
233 yoffset += ypadding;
234 if (chroma) {
235 uoffset += cpadding;
236 voffset += cpadding;
240 /* save pointer to jmp instruction address */
241 risc->jmp = rp;
242 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
243 return 0;
246 static int
247 bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
248 const struct bttv_format *fmt, struct bttv_overlay *ov,
249 int skip_even, int skip_odd)
251 int dwords, rc, line, maxy, start, end;
252 unsigned skip, nskips;
253 struct btcx_skiplist *skips;
254 __le32 *rp;
255 u32 ri,ra;
256 u32 addr;
258 /* skip list for window clipping */
259 skips = kmalloc_array(ov->nclips, sizeof(*skips),GFP_KERNEL);
260 if (NULL == skips)
261 return -ENOMEM;
263 /* estimate risc mem: worst case is (1.5*clip+1) * lines instructions
264 + sync + jump (all 2 dwords) */
265 dwords = (3 * ov->nclips + 2) *
266 ((skip_even || skip_odd) ? (ov->w.height+1)>>1 : ov->w.height);
267 dwords += 4;
268 if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,dwords*4)) < 0) {
269 kfree(skips);
270 return rc;
273 /* sync instruction */
274 rp = risc->cpu;
275 *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
276 *(rp++) = cpu_to_le32(0);
278 addr = (unsigned long)btv->fbuf.base;
279 addr += btv->fbuf.fmt.bytesperline * ov->w.top;
280 addr += (fmt->depth >> 3) * ov->w.left;
282 /* scan lines */
283 for (maxy = -1, line = 0; line < ov->w.height;
284 line++, addr += btv->fbuf.fmt.bytesperline) {
285 if ((btv->opt_vcr_hack) &&
286 (line >= (ov->w.height - VCR_HACK_LINES)))
287 continue;
288 if ((line%2) == 0 && skip_even)
289 continue;
290 if ((line%2) == 1 && skip_odd)
291 continue;
293 /* calculate clipping */
294 if (line > maxy)
295 btcx_calc_skips(line, ov->w.width, &maxy,
296 skips, &nskips, ov->clips, ov->nclips);
298 /* write out risc code */
299 for (start = 0, skip = 0; start < ov->w.width; start = end) {
300 if (skip >= nskips) {
301 ri = BT848_RISC_WRITE;
302 end = ov->w.width;
303 } else if (start < skips[skip].start) {
304 ri = BT848_RISC_WRITE;
305 end = skips[skip].start;
306 } else {
307 ri = BT848_RISC_SKIP;
308 end = skips[skip].end;
309 skip++;
311 if (BT848_RISC_WRITE == ri)
312 ra = addr + (fmt->depth>>3)*start;
313 else
314 ra = 0;
316 if (0 == start)
317 ri |= BT848_RISC_SOL;
318 if (ov->w.width == end)
319 ri |= BT848_RISC_EOL;
320 ri |= (fmt->depth>>3) * (end-start);
322 *(rp++)=cpu_to_le32(ri);
323 if (0 != ra)
324 *(rp++)=cpu_to_le32(ra);
328 /* save pointer to jmp instruction address */
329 risc->jmp = rp;
330 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
331 kfree(skips);
332 return 0;
335 /* ---------------------------------------------------------- */
337 static void
338 bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
339 int width, int height, int interleaved,
340 const struct bttv_tvnorm *tvnorm)
342 u32 xsf, sr;
343 int vdelay;
345 int swidth = tvnorm->swidth;
346 int totalwidth = tvnorm->totalwidth;
347 int scaledtwidth = tvnorm->scaledtwidth;
349 if (btv->input == btv->dig) {
350 swidth = 720;
351 totalwidth = 858;
352 scaledtwidth = 858;
355 vdelay = tvnorm->vdelay;
357 xsf = (width*scaledtwidth)/swidth;
358 geo->hscale = ((totalwidth*4096UL)/xsf-4096);
359 geo->hdelay = tvnorm->hdelayx1;
360 geo->hdelay = (geo->hdelay*width)/swidth;
361 geo->hdelay &= 0x3fe;
362 sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
363 geo->vscale = (0x10000UL-sr) & 0x1fff;
364 geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
365 ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
366 geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
367 geo->vdelay = vdelay;
368 geo->width = width;
369 geo->sheight = tvnorm->sheight;
370 geo->vtotal = tvnorm->vtotal;
372 if (btv->opt_combfilter) {
373 geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
374 geo->comb = (width < 769) ? 1 : 0;
375 } else {
376 geo->vtc = 0;
377 geo->comb = 0;
381 static void
382 bttv_calc_geo (struct bttv * btv,
383 struct bttv_geometry * geo,
384 unsigned int width,
385 unsigned int height,
386 int both_fields,
387 const struct bttv_tvnorm * tvnorm,
388 const struct v4l2_rect * crop)
390 unsigned int c_width;
391 unsigned int c_height;
392 u32 sr;
394 if ((crop->left == tvnorm->cropcap.defrect.left
395 && crop->top == tvnorm->cropcap.defrect.top
396 && crop->width == tvnorm->cropcap.defrect.width
397 && crop->height == tvnorm->cropcap.defrect.height
398 && width <= tvnorm->swidth /* see PAL-Nc et al */)
399 || btv->input == btv->dig) {
400 bttv_calc_geo_old(btv, geo, width, height,
401 both_fields, tvnorm);
402 return;
405 /* For bug compatibility the image size checks permit scale
406 factors > 16. See bttv_crop_calc_limits(). */
407 c_width = min((unsigned int) crop->width, width * 16);
408 c_height = min((unsigned int) crop->height, height * 16);
410 geo->width = width;
411 geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;
412 /* Even to store Cb first, odd for Cr. */
413 geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;
415 geo->sheight = c_height;
416 geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
417 sr = c_height >> !both_fields;
418 sr = (sr * 512U + (height >> 1)) / height - 512;
419 geo->vscale = (0x10000UL - sr) & 0x1fff;
420 geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;
421 geo->vtotal = tvnorm->vtotal;
423 geo->crop = (((geo->width >> 8) & 0x03) |
424 ((geo->hdelay >> 6) & 0x0c) |
425 ((geo->sheight >> 4) & 0x30) |
426 ((geo->vdelay >> 2) & 0xc0));
428 if (btv->opt_combfilter) {
429 geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
430 geo->comb = (width < 769) ? 1 : 0;
431 } else {
432 geo->vtc = 0;
433 geo->comb = 0;
437 static void
438 bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
440 int off = odd ? 0x80 : 0x00;
442 if (geo->comb)
443 btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
444 else
445 btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
447 btwrite(geo->vtc, BT848_E_VTC+off);
448 btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off);
449 btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off);
450 btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
451 btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off);
452 btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off);
453 btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off);
454 btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off);
455 btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off);
456 btwrite(geo->crop, BT848_E_CROP+off);
457 btwrite(geo->vtotal>>8, BT848_VTOTAL_HI);
458 btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO);
461 /* ---------------------------------------------------------- */
462 /* risc group / risc main loop / dma management */
464 void
465 bttv_set_dma(struct bttv *btv, int override)
467 unsigned long cmd;
468 int capctl;
470 btv->cap_ctl = 0;
471 if (NULL != btv->curr.top) btv->cap_ctl |= 0x02;
472 if (NULL != btv->curr.bottom) btv->cap_ctl |= 0x01;
473 if (NULL != btv->cvbi) btv->cap_ctl |= 0x0c;
475 capctl = 0;
476 capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00; /* capture */
477 capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00; /* vbi data */
478 capctl |= override;
480 d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
481 btv->c.nr,capctl,btv->loop_irq,
482 btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
483 btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
484 btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0,
485 btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
487 cmd = BT848_RISC_JUMP;
488 if (btv->loop_irq) {
489 cmd |= BT848_RISC_IRQ;
490 cmd |= (btv->loop_irq & 0x0f) << 16;
491 cmd |= (~btv->loop_irq & 0x0f) << 20;
493 if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
494 mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
495 } else {
496 del_timer(&btv->timeout);
498 btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
500 btaor(capctl, ~0x0f, BT848_CAP_CTL);
501 if (capctl) {
502 if (btv->dma_on)
503 return;
504 btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
505 btor(3, BT848_GPIO_DMA_CTL);
506 btv->dma_on = 1;
507 } else {
508 if (!btv->dma_on)
509 return;
510 btand(~3, BT848_GPIO_DMA_CTL);
511 btv->dma_on = 0;
513 return;
517 bttv_risc_init_main(struct bttv *btv)
519 int rc;
521 if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
522 return rc;
523 dprintk("%d: risc main @ %08llx\n",
524 btv->c.nr, (unsigned long long)btv->main.dma);
526 btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
527 BT848_FIFO_STATUS_VRE);
528 btv->main.cpu[1] = cpu_to_le32(0);
529 btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
530 btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
532 /* top field */
533 btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
534 btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
535 btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
536 btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
538 btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
539 BT848_FIFO_STATUS_VRO);
540 btv->main.cpu[9] = cpu_to_le32(0);
542 /* bottom field */
543 btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
544 btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
545 btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
546 btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
548 /* jump back to top field */
549 btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
550 btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
552 return 0;
556 bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
557 int irqflags)
559 unsigned long cmd;
560 unsigned long next = btv->main.dma + ((slot+2) << 2);
562 if (NULL == risc) {
563 d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
564 btv->main.cpu[slot+1] = cpu_to_le32(next);
565 } else {
566 d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
567 btv->c.nr, risc, slot,
568 (unsigned long long)risc->dma, irqflags);
569 cmd = BT848_RISC_JUMP;
570 if (irqflags) {
571 cmd |= BT848_RISC_IRQ;
572 cmd |= (irqflags & 0x0f) << 16;
573 cmd |= (~irqflags & 0x0f) << 20;
575 risc->jmp[0] = cpu_to_le32(cmd);
576 risc->jmp[1] = cpu_to_le32(next);
577 btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
579 return 0;
582 void
583 bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
585 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
587 BUG_ON(in_interrupt());
588 videobuf_waiton(q, &buf->vb, 0, 0);
589 videobuf_dma_unmap(q->dev, dma);
590 videobuf_dma_free(dma);
591 btcx_riscmem_free(btv->c.pci,&buf->bottom);
592 btcx_riscmem_free(btv->c.pci,&buf->top);
593 buf->vb.state = VIDEOBUF_NEEDS_INIT;
597 bttv_buffer_activate_vbi(struct bttv *btv,
598 struct bttv_buffer *vbi)
600 struct btcx_riscmem *top;
601 struct btcx_riscmem *bottom;
602 int top_irq_flags;
603 int bottom_irq_flags;
605 top = NULL;
606 bottom = NULL;
607 top_irq_flags = 0;
608 bottom_irq_flags = 0;
610 if (vbi) {
611 unsigned int crop, vdelay;
613 vbi->vb.state = VIDEOBUF_ACTIVE;
614 list_del(&vbi->vb.queue);
616 /* VDELAY is start of video, end of VBI capturing. */
617 crop = btread(BT848_E_CROP);
618 vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
620 if (vbi->geo.vdelay > vdelay) {
621 vdelay = vbi->geo.vdelay & 0xfe;
622 crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
624 btwrite(vdelay, BT848_E_VDELAY_LO);
625 btwrite(crop, BT848_E_CROP);
626 btwrite(vdelay, BT848_O_VDELAY_LO);
627 btwrite(crop, BT848_O_CROP);
630 if (vbi->vbi_count[0] > 0) {
631 top = &vbi->top;
632 top_irq_flags = 4;
635 if (vbi->vbi_count[1] > 0) {
636 top_irq_flags = 0;
637 bottom = &vbi->bottom;
638 bottom_irq_flags = 4;
642 bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
643 bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
645 return 0;
649 bttv_buffer_activate_video(struct bttv *btv,
650 struct bttv_buffer_set *set)
652 /* video capture */
653 if (NULL != set->top && NULL != set->bottom) {
654 if (set->top == set->bottom) {
655 set->top->vb.state = VIDEOBUF_ACTIVE;
656 if (set->top->vb.queue.next)
657 list_del(&set->top->vb.queue);
658 } else {
659 set->top->vb.state = VIDEOBUF_ACTIVE;
660 set->bottom->vb.state = VIDEOBUF_ACTIVE;
661 if (set->top->vb.queue.next)
662 list_del(&set->top->vb.queue);
663 if (set->bottom->vb.queue.next)
664 list_del(&set->bottom->vb.queue);
666 bttv_apply_geo(btv, &set->top->geo, 1);
667 bttv_apply_geo(btv, &set->bottom->geo,0);
668 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
669 set->top_irq);
670 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
671 set->frame_irq);
672 btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
673 ~0xff, BT848_COLOR_FMT);
674 btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
675 ~0x0f, BT848_COLOR_CTL);
676 } else if (NULL != set->top) {
677 set->top->vb.state = VIDEOBUF_ACTIVE;
678 if (set->top->vb.queue.next)
679 list_del(&set->top->vb.queue);
680 bttv_apply_geo(btv, &set->top->geo,1);
681 bttv_apply_geo(btv, &set->top->geo,0);
682 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
683 set->frame_irq);
684 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
685 btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
686 btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
687 } else if (NULL != set->bottom) {
688 set->bottom->vb.state = VIDEOBUF_ACTIVE;
689 if (set->bottom->vb.queue.next)
690 list_del(&set->bottom->vb.queue);
691 bttv_apply_geo(btv, &set->bottom->geo,1);
692 bttv_apply_geo(btv, &set->bottom->geo,0);
693 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
694 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
695 set->frame_irq);
696 btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
697 btaor(set->bottom->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
698 } else {
699 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
700 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
702 return 0;
705 /* ---------------------------------------------------------- */
707 /* calculate geometry, build risc code */
709 bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
711 const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
712 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
714 dprintk("%d: buffer field: %s format: %s size: %dx%d\n",
715 btv->c.nr, v4l2_field_names[buf->vb.field],
716 buf->fmt->name, buf->vb.width, buf->vb.height);
718 /* packed pixel modes */
719 if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
720 int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
721 int bpf = bpl * (buf->vb.height >> 1);
723 bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
724 V4L2_FIELD_HAS_BOTH(buf->vb.field),
725 tvnorm,&buf->crop);
727 switch (buf->vb.field) {
728 case V4L2_FIELD_TOP:
729 bttv_risc_packed(btv,&buf->top,dma->sglist,
730 /* offset */ 0,bpl,
731 /* padding */ 0,/* skip_lines */ 0,
732 buf->vb.height);
733 break;
734 case V4L2_FIELD_BOTTOM:
735 bttv_risc_packed(btv,&buf->bottom,dma->sglist,
736 0,bpl,0,0,buf->vb.height);
737 break;
738 case V4L2_FIELD_INTERLACED:
739 bttv_risc_packed(btv,&buf->top,dma->sglist,
740 0,bpl,bpl,0,buf->vb.height >> 1);
741 bttv_risc_packed(btv,&buf->bottom,dma->sglist,
742 bpl,bpl,bpl,0,buf->vb.height >> 1);
743 break;
744 case V4L2_FIELD_SEQ_TB:
745 bttv_risc_packed(btv,&buf->top,dma->sglist,
746 0,bpl,0,0,buf->vb.height >> 1);
747 bttv_risc_packed(btv,&buf->bottom,dma->sglist,
748 bpf,bpl,0,0,buf->vb.height >> 1);
749 break;
750 default:
751 BUG();
755 /* planar modes */
756 if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
757 int uoffset, voffset;
758 int ypadding, cpadding, lines;
760 /* calculate chroma offsets */
761 uoffset = buf->vb.width * buf->vb.height;
762 voffset = buf->vb.width * buf->vb.height;
763 if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
764 /* Y-Cr-Cb plane order */
765 uoffset >>= buf->fmt->hshift;
766 uoffset >>= buf->fmt->vshift;
767 uoffset += voffset;
768 } else {
769 /* Y-Cb-Cr plane order */
770 voffset >>= buf->fmt->hshift;
771 voffset >>= buf->fmt->vshift;
772 voffset += uoffset;
775 switch (buf->vb.field) {
776 case V4L2_FIELD_TOP:
777 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
778 buf->vb.height,/* both_fields */ 0,
779 tvnorm,&buf->crop);
780 bttv_risc_planar(btv, &buf->top, dma->sglist,
781 0,buf->vb.width,0,buf->vb.height,
782 uoffset,voffset,buf->fmt->hshift,
783 buf->fmt->vshift,0);
784 break;
785 case V4L2_FIELD_BOTTOM:
786 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
787 buf->vb.height,0,
788 tvnorm,&buf->crop);
789 bttv_risc_planar(btv, &buf->bottom, dma->sglist,
790 0,buf->vb.width,0,buf->vb.height,
791 uoffset,voffset,buf->fmt->hshift,
792 buf->fmt->vshift,0);
793 break;
794 case V4L2_FIELD_INTERLACED:
795 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
796 buf->vb.height,1,
797 tvnorm,&buf->crop);
798 lines = buf->vb.height >> 1;
799 ypadding = buf->vb.width;
800 cpadding = buf->vb.width >> buf->fmt->hshift;
801 bttv_risc_planar(btv,&buf->top,
802 dma->sglist,
803 0,buf->vb.width,ypadding,lines,
804 uoffset,voffset,
805 buf->fmt->hshift,
806 buf->fmt->vshift,
807 cpadding);
808 bttv_risc_planar(btv,&buf->bottom,
809 dma->sglist,
810 ypadding,buf->vb.width,ypadding,lines,
811 uoffset+cpadding,
812 voffset+cpadding,
813 buf->fmt->hshift,
814 buf->fmt->vshift,
815 cpadding);
816 break;
817 case V4L2_FIELD_SEQ_TB:
818 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
819 buf->vb.height,1,
820 tvnorm,&buf->crop);
821 lines = buf->vb.height >> 1;
822 ypadding = buf->vb.width;
823 cpadding = buf->vb.width >> buf->fmt->hshift;
824 bttv_risc_planar(btv,&buf->top,
825 dma->sglist,
826 0,buf->vb.width,0,lines,
827 uoffset >> 1,
828 voffset >> 1,
829 buf->fmt->hshift,
830 buf->fmt->vshift,
832 bttv_risc_planar(btv,&buf->bottom,
833 dma->sglist,
834 lines * ypadding,buf->vb.width,0,lines,
835 lines * ypadding + (uoffset >> 1),
836 lines * ypadding + (voffset >> 1),
837 buf->fmt->hshift,
838 buf->fmt->vshift,
840 break;
841 default:
842 BUG();
846 /* raw data */
847 if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
848 /* build risc code */
849 buf->vb.field = V4L2_FIELD_SEQ_TB;
850 bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
851 1,tvnorm,&buf->crop);
852 bttv_risc_packed(btv, &buf->top, dma->sglist,
853 /* offset */ 0, RAW_BPL, /* padding */ 0,
854 /* skip_lines */ 0, RAW_LINES);
855 bttv_risc_packed(btv, &buf->bottom, dma->sglist,
856 buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
859 /* copy format info */
860 buf->btformat = buf->fmt->btformat;
861 buf->btswap = buf->fmt->btswap;
862 return 0;
865 /* ---------------------------------------------------------- */
867 /* calculate geometry, build risc code */
869 bttv_overlay_risc(struct bttv *btv,
870 struct bttv_overlay *ov,
871 const struct bttv_format *fmt,
872 struct bttv_buffer *buf)
874 /* check interleave, bottom+top fields */
875 dprintk("%d: overlay fields: %s format: %s size: %dx%d\n",
876 btv->c.nr, v4l2_field_names[buf->vb.field],
877 fmt->name, ov->w.width, ov->w.height);
879 /* calculate geometry */
880 bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
881 V4L2_FIELD_HAS_BOTH(ov->field),
882 &bttv_tvnorms[ov->tvnorm],&buf->crop);
884 /* build risc code */
885 switch (ov->field) {
886 case V4L2_FIELD_TOP:
887 bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 0);
888 break;
889 case V4L2_FIELD_BOTTOM:
890 bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
891 break;
892 case V4L2_FIELD_INTERLACED:
893 bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 1);
894 bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
895 break;
896 default:
897 BUG();
900 /* copy format info */
901 buf->btformat = fmt->btformat;
902 buf->btswap = fmt->btswap;
903 buf->vb.field = ov->field;
904 return 0;