V4L/DVB (3394): Bttv: correct bttv_risc_packed buffer size
[linux-2.6/linux-loongson.git] / drivers / media / video / bttv-risc.c
bloba60c211c9e31ba4d667494e77e80bdf9b67a0c4b
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/pci.h>
30 #include <linux/vmalloc.h>
31 #include <linux/interrupt.h>
32 #include <asm/page.h>
33 #include <asm/pgtable.h>
35 #include "bttvp.h"
37 #define VCR_HACK_LINES 4
39 /* ---------------------------------------------------------- */
40 /* risc code generators */
42 int
43 bttv_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 lines)
48 u32 instructions,line,todo;
49 struct scatterlist *sg;
50 u32 *rp;
51 int rc;
53 /* estimate risc mem: worst case is one write per page border +
54 one write per scan line + sync + jump (all 2 dwords). padding
55 can cause next bpl to start close to a page border. First DMA
56 region may be smaller than PAGE_SIZE */
57 instructions = 1 + ((bpl + padding) * lines) / PAGE_SIZE + lines;
58 instructions += 2;
59 if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0)
60 return rc;
62 /* sync instruction */
63 rp = risc->cpu;
64 *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
65 *(rp++) = cpu_to_le32(0);
67 /* scan lines */
68 sg = sglist;
69 for (line = 0; line < lines; line++) {
70 if ((btv->opt_vcr_hack) &&
71 (line >= (lines - VCR_HACK_LINES)))
72 continue;
73 while (offset && offset >= sg_dma_len(sg)) {
74 offset -= sg_dma_len(sg);
75 sg++;
77 if (bpl <= sg_dma_len(sg)-offset) {
78 /* fits into current chunk */
79 *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
80 BT848_RISC_EOL|bpl);
81 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
82 offset+=bpl;
83 } else {
84 /* scanline needs to be splitted */
85 todo = bpl;
86 *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
87 (sg_dma_len(sg)-offset));
88 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
89 todo -= (sg_dma_len(sg)-offset);
90 offset = 0;
91 sg++;
92 while (todo > sg_dma_len(sg)) {
93 *(rp++)=cpu_to_le32(BT848_RISC_WRITE|
94 sg_dma_len(sg));
95 *(rp++)=cpu_to_le32(sg_dma_address(sg));
96 todo -= sg_dma_len(sg);
97 sg++;
99 *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
100 todo);
101 *(rp++)=cpu_to_le32(sg_dma_address(sg));
102 offset += todo;
104 offset += padding;
107 /* save pointer to jmp instruction address */
108 risc->jmp = rp;
109 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
110 return 0;
113 static int
114 bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
115 struct scatterlist *sglist,
116 unsigned int yoffset, unsigned int ybpl,
117 unsigned int ypadding, unsigned int ylines,
118 unsigned int uoffset, unsigned int voffset,
119 unsigned int hshift, unsigned int vshift,
120 unsigned int cpadding)
122 unsigned int instructions,line,todo,ylen,chroma;
123 u32 *rp,ri;
124 struct scatterlist *ysg;
125 struct scatterlist *usg;
126 struct scatterlist *vsg;
127 int topfield = (0 == yoffset);
128 int rc;
130 /* estimate risc mem: worst case is one write per page border +
131 one write per scan line (5 dwords)
132 plus sync + jump (2 dwords) */
133 instructions = (ybpl * ylines * 2) / PAGE_SIZE + ylines;
134 instructions += 2;
135 if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
136 return rc;
138 /* sync instruction */
139 rp = risc->cpu;
140 *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
141 *(rp++) = cpu_to_le32(0);
143 /* scan lines */
144 ysg = sglist;
145 usg = sglist;
146 vsg = sglist;
147 for (line = 0; line < ylines; line++) {
148 if ((btv->opt_vcr_hack) &&
149 (line >= (ylines - VCR_HACK_LINES)))
150 continue;
151 switch (vshift) {
152 case 0:
153 chroma = 1;
154 break;
155 case 1:
156 if (topfield)
157 chroma = ((line & 1) == 0);
158 else
159 chroma = ((line & 1) == 1);
160 break;
161 case 2:
162 if (topfield)
163 chroma = ((line & 3) == 0);
164 else
165 chroma = ((line & 3) == 2);
166 break;
167 default:
168 chroma = 0;
169 break;
172 for (todo = ybpl; todo > 0; todo -= ylen) {
173 /* go to next sg entry if needed */
174 while (yoffset && yoffset >= sg_dma_len(ysg)) {
175 yoffset -= sg_dma_len(ysg);
176 ysg++;
178 while (uoffset && uoffset >= sg_dma_len(usg)) {
179 uoffset -= sg_dma_len(usg);
180 usg++;
182 while (voffset && voffset >= sg_dma_len(vsg)) {
183 voffset -= sg_dma_len(vsg);
184 vsg++;
187 /* calculate max number of bytes we can write */
188 ylen = todo;
189 if (yoffset + ylen > sg_dma_len(ysg))
190 ylen = sg_dma_len(ysg) - yoffset;
191 if (chroma) {
192 if (uoffset + (ylen>>hshift) > sg_dma_len(usg))
193 ylen = (sg_dma_len(usg) - uoffset) << hshift;
194 if (voffset + (ylen>>hshift) > sg_dma_len(vsg))
195 ylen = (sg_dma_len(vsg) - voffset) << hshift;
196 ri = BT848_RISC_WRITE123;
197 } else {
198 ri = BT848_RISC_WRITE1S23;
200 if (ybpl == todo)
201 ri |= BT848_RISC_SOL;
202 if (ylen == todo)
203 ri |= BT848_RISC_EOL;
205 /* write risc instruction */
206 *(rp++)=cpu_to_le32(ri | ylen);
207 *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
208 (ylen >> hshift));
209 *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
210 yoffset += ylen;
211 if (chroma) {
212 *(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);
213 uoffset += ylen >> hshift;
214 *(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);
215 voffset += ylen >> hshift;
218 yoffset += ypadding;
219 if (chroma) {
220 uoffset += cpadding;
221 voffset += cpadding;
225 /* save pointer to jmp instruction address */
226 risc->jmp = rp;
227 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
228 return 0;
231 static int
232 bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
233 const struct bttv_format *fmt, struct bttv_overlay *ov,
234 int skip_even, int skip_odd)
236 int instructions,rc,line,maxy,start,end,skip,nskips;
237 struct btcx_skiplist *skips;
238 u32 *rp,ri,ra;
239 u32 addr;
241 /* skip list for window clipping */
242 if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
243 return -ENOMEM;
245 /* estimate risc mem: worst case is (clip+1) * lines instructions
246 + sync + jump (all 2 dwords) */
247 instructions = (ov->nclips + 1) *
248 ((skip_even || skip_odd) ? ov->w.height>>1 : ov->w.height);
249 instructions += 2;
250 if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0) {
251 kfree(skips);
252 return rc;
255 /* sync instruction */
256 rp = risc->cpu;
257 *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
258 *(rp++) = cpu_to_le32(0);
260 addr = (unsigned long)btv->fbuf.base;
261 addr += btv->fbuf.fmt.bytesperline * ov->w.top;
262 addr += (fmt->depth >> 3) * ov->w.left;
264 /* scan lines */
265 for (maxy = -1, line = 0; line < ov->w.height;
266 line++, addr += btv->fbuf.fmt.bytesperline) {
267 if ((btv->opt_vcr_hack) &&
268 (line >= (ov->w.height - VCR_HACK_LINES)))
269 continue;
270 if ((line%2) == 0 && skip_even)
271 continue;
272 if ((line%2) == 1 && skip_odd)
273 continue;
275 /* calculate clipping */
276 if (line > maxy)
277 btcx_calc_skips(line, ov->w.width, &maxy,
278 skips, &nskips, ov->clips, ov->nclips);
280 /* write out risc code */
281 for (start = 0, skip = 0; start < ov->w.width; start = end) {
282 if (skip >= nskips) {
283 ri = BT848_RISC_WRITE;
284 end = ov->w.width;
285 } else if (start < skips[skip].start) {
286 ri = BT848_RISC_WRITE;
287 end = skips[skip].start;
288 } else {
289 ri = BT848_RISC_SKIP;
290 end = skips[skip].end;
291 skip++;
293 if (BT848_RISC_WRITE == ri)
294 ra = addr + (fmt->depth>>3)*start;
295 else
296 ra = 0;
298 if (0 == start)
299 ri |= BT848_RISC_SOL;
300 if (ov->w.width == end)
301 ri |= BT848_RISC_EOL;
302 ri |= (fmt->depth>>3) * (end-start);
304 *(rp++)=cpu_to_le32(ri);
305 if (0 != ra)
306 *(rp++)=cpu_to_le32(ra);
310 /* save pointer to jmp instruction address */
311 risc->jmp = rp;
312 BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
313 kfree(skips);
314 return 0;
317 /* ---------------------------------------------------------- */
319 static void
320 bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo,
321 int width, int height, int interleaved, int norm)
323 const struct bttv_tvnorm *tvnorm = &bttv_tvnorms[norm];
324 u32 xsf, sr;
325 int vdelay;
327 int swidth = tvnorm->swidth;
328 int totalwidth = tvnorm->totalwidth;
329 int scaledtwidth = tvnorm->scaledtwidth;
331 if (bttv_tvcards[btv->c.type].muxsel[btv->input] < 0) {
332 swidth = 720;
333 totalwidth = 858;
334 scaledtwidth = 858;
337 vdelay = tvnorm->vdelay;
339 xsf = (width*scaledtwidth)/swidth;
340 geo->hscale = ((totalwidth*4096UL)/xsf-4096);
341 geo->hdelay = tvnorm->hdelayx1;
342 geo->hdelay = (geo->hdelay*width)/swidth;
343 geo->hdelay &= 0x3fe;
344 sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
345 geo->vscale = (0x10000UL-sr) & 0x1fff;
346 geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
347 ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
348 geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
349 geo->vdelay = vdelay;
350 geo->width = width;
351 geo->sheight = tvnorm->sheight;
352 geo->vtotal = tvnorm->vtotal;
354 if (btv->opt_combfilter) {
355 geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
356 geo->comb = (width < 769) ? 1 : 0;
357 } else {
358 geo->vtc = 0;
359 geo->comb = 0;
363 static void
364 bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
366 int off = odd ? 0x80 : 0x00;
368 if (geo->comb)
369 btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
370 else
371 btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
373 btwrite(geo->vtc, BT848_E_VTC+off);
374 btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off);
375 btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off);
376 btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
377 btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off);
378 btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off);
379 btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off);
380 btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off);
381 btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off);
382 btwrite(geo->crop, BT848_E_CROP+off);
383 btwrite(geo->vtotal>>8, BT848_VTOTAL_HI);
384 btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO);
387 /* ---------------------------------------------------------- */
388 /* risc group / risc main loop / dma management */
390 void
391 bttv_set_dma(struct bttv *btv, int override)
393 unsigned long cmd;
394 int capctl;
396 btv->cap_ctl = 0;
397 if (NULL != btv->curr.top) btv->cap_ctl |= 0x02;
398 if (NULL != btv->curr.bottom) btv->cap_ctl |= 0x01;
399 if (NULL != btv->cvbi) btv->cap_ctl |= 0x0c;
401 capctl = 0;
402 capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00; /* capture */
403 capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00; /* vbi data */
404 capctl |= override;
406 d2printk(KERN_DEBUG
407 "bttv%d: capctl=%x lirq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",
408 btv->c.nr,capctl,btv->loop_irq,
409 btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
410 btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
411 btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0,
412 btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
414 cmd = BT848_RISC_JUMP;
415 if (btv->loop_irq) {
416 cmd |= BT848_RISC_IRQ;
417 cmd |= (btv->loop_irq & 0x0f) << 16;
418 cmd |= (~btv->loop_irq & 0x0f) << 20;
420 if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
421 mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
422 } else {
423 del_timer(&btv->timeout);
425 btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
427 btaor(capctl, ~0x0f, BT848_CAP_CTL);
428 if (capctl) {
429 if (btv->dma_on)
430 return;
431 btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
432 btor(3, BT848_GPIO_DMA_CTL);
433 btv->dma_on = 1;
434 } else {
435 if (!btv->dma_on)
436 return;
437 btand(~3, BT848_GPIO_DMA_CTL);
438 btv->dma_on = 0;
440 return;
444 bttv_risc_init_main(struct bttv *btv)
446 int rc;
448 if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
449 return rc;
450 dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n",
451 btv->c.nr,(unsigned long long)btv->main.dma);
453 btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
454 BT848_FIFO_STATUS_VRE);
455 btv->main.cpu[1] = cpu_to_le32(0);
456 btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
457 btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
459 /* top field */
460 btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
461 btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
462 btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
463 btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
465 btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
466 BT848_FIFO_STATUS_VRO);
467 btv->main.cpu[9] = cpu_to_le32(0);
469 /* bottom field */
470 btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
471 btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
472 btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
473 btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
475 /* jump back to top field */
476 btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
477 btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
479 return 0;
483 bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
484 int irqflags)
486 unsigned long cmd;
487 unsigned long next = btv->main.dma + ((slot+2) << 2);
489 if (NULL == risc) {
490 d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=NULL\n",
491 btv->c.nr,risc,slot);
492 btv->main.cpu[slot+1] = cpu_to_le32(next);
493 } else {
494 d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n",
495 btv->c.nr,risc,slot,(unsigned long long)risc->dma,irqflags);
496 cmd = BT848_RISC_JUMP;
497 if (irqflags) {
498 cmd |= BT848_RISC_IRQ;
499 cmd |= (irqflags & 0x0f) << 16;
500 cmd |= (~irqflags & 0x0f) << 20;
502 risc->jmp[0] = cpu_to_le32(cmd);
503 risc->jmp[1] = cpu_to_le32(next);
504 btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
506 return 0;
509 void
510 bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf)
512 if (in_interrupt())
513 BUG();
514 videobuf_waiton(&buf->vb,0,0);
515 videobuf_dma_pci_unmap(btv->c.pci, &buf->vb.dma);
516 videobuf_dma_free(&buf->vb.dma);
517 btcx_riscmem_free(btv->c.pci,&buf->bottom);
518 btcx_riscmem_free(btv->c.pci,&buf->top);
519 buf->vb.state = STATE_NEEDS_INIT;
523 bttv_buffer_activate_vbi(struct bttv *btv,
524 struct bttv_buffer *vbi)
526 /* vbi capture */
527 if (vbi) {
528 vbi->vb.state = STATE_ACTIVE;
529 list_del(&vbi->vb.queue);
530 bttv_risc_hook(btv, RISC_SLOT_O_VBI, &vbi->top, 0);
531 bttv_risc_hook(btv, RISC_SLOT_E_VBI, &vbi->bottom, 4);
532 } else {
533 bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0);
534 bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0);
536 return 0;
540 bttv_buffer_activate_video(struct bttv *btv,
541 struct bttv_buffer_set *set)
543 /* video capture */
544 if (NULL != set->top && NULL != set->bottom) {
545 if (set->top == set->bottom) {
546 set->top->vb.state = STATE_ACTIVE;
547 if (set->top->vb.queue.next)
548 list_del(&set->top->vb.queue);
549 } else {
550 set->top->vb.state = STATE_ACTIVE;
551 set->bottom->vb.state = STATE_ACTIVE;
552 if (set->top->vb.queue.next)
553 list_del(&set->top->vb.queue);
554 if (set->bottom->vb.queue.next)
555 list_del(&set->bottom->vb.queue);
557 bttv_apply_geo(btv, &set->top->geo, 1);
558 bttv_apply_geo(btv, &set->bottom->geo,0);
559 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
560 set->top_irq);
561 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
562 set->frame_irq);
563 btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
564 ~0xff, BT848_COLOR_FMT);
565 btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
566 ~0x0f, BT848_COLOR_CTL);
567 } else if (NULL != set->top) {
568 set->top->vb.state = STATE_ACTIVE;
569 if (set->top->vb.queue.next)
570 list_del(&set->top->vb.queue);
571 bttv_apply_geo(btv, &set->top->geo,1);
572 bttv_apply_geo(btv, &set->top->geo,0);
573 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
574 set->frame_irq);
575 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
576 btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
577 btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
578 } else if (NULL != set->bottom) {
579 set->bottom->vb.state = STATE_ACTIVE;
580 if (set->bottom->vb.queue.next)
581 list_del(&set->bottom->vb.queue);
582 bttv_apply_geo(btv, &set->bottom->geo,1);
583 bttv_apply_geo(btv, &set->bottom->geo,0);
584 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
585 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
586 set->frame_irq);
587 btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
588 btaor(set->bottom->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
589 } else {
590 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
591 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
593 return 0;
596 /* ---------------------------------------------------------- */
598 /* calculate geometry, build risc code */
600 bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
602 const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
604 dprintk(KERN_DEBUG
605 "bttv%d: buffer field: %s format: %s size: %dx%d\n",
606 btv->c.nr, v4l2_field_names[buf->vb.field],
607 buf->fmt->name, buf->vb.width, buf->vb.height);
609 /* packed pixel modes */
610 if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
611 int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
612 int bpf = bpl * (buf->vb.height >> 1);
614 bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
615 V4L2_FIELD_HAS_BOTH(buf->vb.field),buf->tvnorm);
617 switch (buf->vb.field) {
618 case V4L2_FIELD_TOP:
619 bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
620 0,bpl,0,buf->vb.height);
621 break;
622 case V4L2_FIELD_BOTTOM:
623 bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
624 0,bpl,0,buf->vb.height);
625 break;
626 case V4L2_FIELD_INTERLACED:
627 bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
628 0,bpl,bpl,buf->vb.height >> 1);
629 bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
630 bpl,bpl,bpl,buf->vb.height >> 1);
631 break;
632 case V4L2_FIELD_SEQ_TB:
633 bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
634 0,bpl,0,buf->vb.height >> 1);
635 bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
636 bpf,bpl,0,buf->vb.height >> 1);
637 break;
638 default:
639 BUG();
643 /* planar modes */
644 if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
645 int uoffset, voffset;
646 int ypadding, cpadding, lines;
648 /* calculate chroma offsets */
649 uoffset = buf->vb.width * buf->vb.height;
650 voffset = buf->vb.width * buf->vb.height;
651 if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
652 /* Y-Cr-Cb plane order */
653 uoffset >>= buf->fmt->hshift;
654 uoffset >>= buf->fmt->vshift;
655 uoffset += voffset;
656 } else {
657 /* Y-Cb-Cr plane order */
658 voffset >>= buf->fmt->hshift;
659 voffset >>= buf->fmt->vshift;
660 voffset += uoffset;
663 switch (buf->vb.field) {
664 case V4L2_FIELD_TOP:
665 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
666 buf->vb.height,0,buf->tvnorm);
667 bttv_risc_planar(btv, &buf->top, buf->vb.dma.sglist,
668 0,buf->vb.width,0,buf->vb.height,
669 uoffset,voffset,buf->fmt->hshift,
670 buf->fmt->vshift,0);
671 break;
672 case V4L2_FIELD_BOTTOM:
673 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
674 buf->vb.height,0,buf->tvnorm);
675 bttv_risc_planar(btv, &buf->bottom, buf->vb.dma.sglist,
676 0,buf->vb.width,0,buf->vb.height,
677 uoffset,voffset,buf->fmt->hshift,
678 buf->fmt->vshift,0);
679 break;
680 case V4L2_FIELD_INTERLACED:
681 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
682 buf->vb.height,1,buf->tvnorm);
683 lines = buf->vb.height >> 1;
684 ypadding = buf->vb.width;
685 cpadding = buf->vb.width >> buf->fmt->hshift;
686 bttv_risc_planar(btv,&buf->top,
687 buf->vb.dma.sglist,
688 0,buf->vb.width,ypadding,lines,
689 uoffset,voffset,
690 buf->fmt->hshift,
691 buf->fmt->vshift,
692 cpadding);
693 bttv_risc_planar(btv,&buf->bottom,
694 buf->vb.dma.sglist,
695 ypadding,buf->vb.width,ypadding,lines,
696 uoffset+cpadding,
697 voffset+cpadding,
698 buf->fmt->hshift,
699 buf->fmt->vshift,
700 cpadding);
701 break;
702 case V4L2_FIELD_SEQ_TB:
703 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
704 buf->vb.height,1,buf->tvnorm);
705 lines = buf->vb.height >> 1;
706 ypadding = buf->vb.width;
707 cpadding = buf->vb.width >> buf->fmt->hshift;
708 bttv_risc_planar(btv,&buf->top,
709 buf->vb.dma.sglist,
710 0,buf->vb.width,0,lines,
711 uoffset >> 1,
712 voffset >> 1,
713 buf->fmt->hshift,
714 buf->fmt->vshift,
716 bttv_risc_planar(btv,&buf->bottom,
717 buf->vb.dma.sglist,
718 lines * ypadding,buf->vb.width,0,lines,
719 lines * ypadding + (uoffset >> 1),
720 lines * ypadding + (voffset >> 1),
721 buf->fmt->hshift,
722 buf->fmt->vshift,
724 break;
725 default:
726 BUG();
730 /* raw data */
731 if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
732 /* build risc code */
733 buf->vb.field = V4L2_FIELD_SEQ_TB;
734 bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
735 1,buf->tvnorm);
736 bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist,
737 0, RAW_BPL, 0, RAW_LINES);
738 bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist,
739 buf->vb.size/2 , RAW_BPL, 0, RAW_LINES);
742 /* copy format info */
743 buf->btformat = buf->fmt->btformat;
744 buf->btswap = buf->fmt->btswap;
745 return 0;
748 /* ---------------------------------------------------------- */
750 /* calculate geometry, build risc code */
752 bttv_overlay_risc(struct bttv *btv,
753 struct bttv_overlay *ov,
754 const struct bttv_format *fmt,
755 struct bttv_buffer *buf)
757 /* check interleave, bottom+top fields */
758 dprintk(KERN_DEBUG
759 "bttv%d: overlay fields: %s format: %s size: %dx%d\n",
760 btv->c.nr, v4l2_field_names[buf->vb.field],
761 fmt->name,ov->w.width,ov->w.height);
763 /* calculate geometry */
764 bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
765 V4L2_FIELD_HAS_BOTH(ov->field), ov->tvnorm);
767 /* build risc code */
768 switch (ov->field) {
769 case V4L2_FIELD_TOP:
770 bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 0);
771 break;
772 case V4L2_FIELD_BOTTOM:
773 bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
774 break;
775 case V4L2_FIELD_INTERLACED:
776 bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 1);
777 bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
778 break;
779 default:
780 BUG();
783 /* copy format info */
784 buf->btformat = fmt->btformat;
785 buf->btswap = fmt->btswap;
786 buf->vb.field = ov->field;
787 return 0;
791 * Local variables:
792 * c-basic-offset: 8
793 * End: