Merge git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-fixes-2.6
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / media / video / bttv-risc.c
blobb40e9734bf0885d83724b29b4b5d7683964fe01f
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) */
55 instructions = (bpl * lines) / PAGE_SIZE + lines;
56 instructions += 2;
57 if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0)
58 return rc;
60 /* sync instruction */
61 rp = risc->cpu;
62 *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
63 *(rp++) = cpu_to_le32(0);
65 /* scan lines */
66 sg = sglist;
67 for (line = 0; line < lines; line++) {
68 if ((btv->opt_vcr_hack) &&
69 (line >= (lines - VCR_HACK_LINES)))
70 continue;
71 while (offset && offset >= sg_dma_len(sg)) {
72 offset -= sg_dma_len(sg);
73 sg++;
75 if (bpl <= sg_dma_len(sg)-offset) {
76 /* fits into current chunk */
77 *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
78 BT848_RISC_EOL|bpl);
79 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
80 offset+=bpl;
81 } else {
82 /* scanline needs to be splitted */
83 todo = bpl;
84 *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
85 (sg_dma_len(sg)-offset));
86 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
87 todo -= (sg_dma_len(sg)-offset);
88 offset = 0;
89 sg++;
90 while (todo > sg_dma_len(sg)) {
91 *(rp++)=cpu_to_le32(BT848_RISC_WRITE|
92 sg_dma_len(sg));
93 *(rp++)=cpu_to_le32(sg_dma_address(sg));
94 todo -= sg_dma_len(sg);
95 sg++;
97 *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
98 todo);
99 *(rp++)=cpu_to_le32(sg_dma_address(sg));
100 offset += todo;
102 offset += padding;
105 /* save pointer to jmp instruction address */
106 risc->jmp = rp;
107 BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size);
108 return 0;
111 static int
112 bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
113 struct scatterlist *sglist,
114 unsigned int yoffset, unsigned int ybpl,
115 unsigned int ypadding, unsigned int ylines,
116 unsigned int uoffset, unsigned int voffset,
117 unsigned int hshift, unsigned int vshift,
118 unsigned int cpadding)
120 unsigned int instructions,line,todo,ylen,chroma;
121 u32 *rp,ri;
122 struct scatterlist *ysg;
123 struct scatterlist *usg;
124 struct scatterlist *vsg;
125 int topfield = (0 == yoffset);
126 int rc;
128 /* estimate risc mem: worst case is one write per page border +
129 one write per scan line (5 dwords)
130 plus sync + jump (2 dwords) */
131 instructions = (ybpl * ylines * 2) / PAGE_SIZE + ylines;
132 instructions += 2;
133 if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
134 return rc;
136 /* sync instruction */
137 rp = risc->cpu;
138 *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
139 *(rp++) = cpu_to_le32(0);
141 /* scan lines */
142 ysg = sglist;
143 usg = sglist;
144 vsg = sglist;
145 for (line = 0; line < ylines; line++) {
146 if ((btv->opt_vcr_hack) &&
147 (line >= (ylines - VCR_HACK_LINES)))
148 continue;
149 switch (vshift) {
150 case 0:
151 chroma = 1;
152 break;
153 case 1:
154 if (topfield)
155 chroma = ((line & 1) == 0);
156 else
157 chroma = ((line & 1) == 1);
158 break;
159 case 2:
160 if (topfield)
161 chroma = ((line & 3) == 0);
162 else
163 chroma = ((line & 3) == 2);
164 break;
165 default:
166 chroma = 0;
167 break;
170 for (todo = ybpl; todo > 0; todo -= ylen) {
171 /* go to next sg entry if needed */
172 while (yoffset && yoffset >= sg_dma_len(ysg)) {
173 yoffset -= sg_dma_len(ysg);
174 ysg++;
176 while (uoffset && uoffset >= sg_dma_len(usg)) {
177 uoffset -= sg_dma_len(usg);
178 usg++;
180 while (voffset && voffset >= sg_dma_len(vsg)) {
181 voffset -= sg_dma_len(vsg);
182 vsg++;
185 /* calculate max number of bytes we can write */
186 ylen = todo;
187 if (yoffset + ylen > sg_dma_len(ysg))
188 ylen = sg_dma_len(ysg) - yoffset;
189 if (chroma) {
190 if (uoffset + (ylen>>hshift) > sg_dma_len(usg))
191 ylen = (sg_dma_len(usg) - uoffset) << hshift;
192 if (voffset + (ylen>>hshift) > sg_dma_len(vsg))
193 ylen = (sg_dma_len(vsg) - voffset) << hshift;
194 ri = BT848_RISC_WRITE123;
195 } else {
196 ri = BT848_RISC_WRITE1S23;
198 if (ybpl == todo)
199 ri |= BT848_RISC_SOL;
200 if (ylen == todo)
201 ri |= BT848_RISC_EOL;
203 /* write risc instruction */
204 *(rp++)=cpu_to_le32(ri | ylen);
205 *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
206 (ylen >> hshift));
207 *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
208 yoffset += ylen;
209 if (chroma) {
210 *(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);
211 uoffset += ylen >> hshift;
212 *(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);
213 voffset += ylen >> hshift;
216 yoffset += ypadding;
217 if (chroma) {
218 uoffset += cpadding;
219 voffset += cpadding;
223 /* save pointer to jmp instruction address */
224 risc->jmp = rp;
225 BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size);
226 return 0;
229 static int
230 bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
231 const struct bttv_format *fmt, struct bttv_overlay *ov,
232 int skip_even, int skip_odd)
234 int instructions,rc,line,maxy,start,end,skip,nskips;
235 struct btcx_skiplist *skips;
236 u32 *rp,ri,ra;
237 u32 addr;
239 /* skip list for window clipping */
240 if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
241 return -ENOMEM;
243 /* estimate risc mem: worst case is (clip+1) * lines instructions
244 + sync + jump (all 2 dwords) */
245 instructions = (ov->nclips + 1) *
246 ((skip_even || skip_odd) ? ov->w.height>>1 : ov->w.height);
247 instructions += 2;
248 if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0) {
249 kfree(skips);
250 return rc;
253 /* sync instruction */
254 rp = risc->cpu;
255 *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
256 *(rp++) = cpu_to_le32(0);
258 addr = (unsigned long)btv->fbuf.base;
259 addr += btv->fbuf.fmt.bytesperline * ov->w.top;
260 addr += (fmt->depth >> 3) * ov->w.left;
262 /* scan lines */
263 for (maxy = -1, line = 0; line < ov->w.height;
264 line++, addr += btv->fbuf.fmt.bytesperline) {
265 if ((btv->opt_vcr_hack) &&
266 (line >= (ov->w.height - VCR_HACK_LINES)))
267 continue;
268 if ((line%2) == 0 && skip_even)
269 continue;
270 if ((line%2) == 1 && skip_odd)
271 continue;
273 /* calculate clipping */
274 if (line > maxy)
275 btcx_calc_skips(line, ov->w.width, &maxy,
276 skips, &nskips, ov->clips, ov->nclips);
278 /* write out risc code */
279 for (start = 0, skip = 0; start < ov->w.width; start = end) {
280 if (skip >= nskips) {
281 ri = BT848_RISC_WRITE;
282 end = ov->w.width;
283 } else if (start < skips[skip].start) {
284 ri = BT848_RISC_WRITE;
285 end = skips[skip].start;
286 } else {
287 ri = BT848_RISC_SKIP;
288 end = skips[skip].end;
289 skip++;
291 if (BT848_RISC_WRITE == ri)
292 ra = addr + (fmt->depth>>3)*start;
293 else
294 ra = 0;
296 if (0 == start)
297 ri |= BT848_RISC_SOL;
298 if (ov->w.width == end)
299 ri |= BT848_RISC_EOL;
300 ri |= (fmt->depth>>3) * (end-start);
302 *(rp++)=cpu_to_le32(ri);
303 if (0 != ra)
304 *(rp++)=cpu_to_le32(ra);
308 /* save pointer to jmp instruction address */
309 risc->jmp = rp;
310 BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size);
311 kfree(skips);
312 return 0;
315 /* ---------------------------------------------------------- */
317 static void
318 bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo,
319 int width, int height, int interleaved, int norm)
321 const struct bttv_tvnorm *tvnorm = &bttv_tvnorms[norm];
322 u32 xsf, sr;
323 int vdelay;
325 int swidth = tvnorm->swidth;
326 int totalwidth = tvnorm->totalwidth;
327 int scaledtwidth = tvnorm->scaledtwidth;
329 if (bttv_tvcards[btv->c.type].muxsel[btv->input] < 0) {
330 swidth = 720;
331 totalwidth = 858;
332 scaledtwidth = 858;
335 vdelay = tvnorm->vdelay;
337 xsf = (width*scaledtwidth)/swidth;
338 geo->hscale = ((totalwidth*4096UL)/xsf-4096);
339 geo->hdelay = tvnorm->hdelayx1;
340 geo->hdelay = (geo->hdelay*width)/swidth;
341 geo->hdelay &= 0x3fe;
342 sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
343 geo->vscale = (0x10000UL-sr) & 0x1fff;
344 geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
345 ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
346 geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
347 geo->vdelay = vdelay;
348 geo->width = width;
349 geo->sheight = tvnorm->sheight;
350 geo->vtotal = tvnorm->vtotal;
352 if (btv->opt_combfilter) {
353 geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
354 geo->comb = (width < 769) ? 1 : 0;
355 } else {
356 geo->vtc = 0;
357 geo->comb = 0;
361 static void
362 bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
364 int off = odd ? 0x80 : 0x00;
366 if (geo->comb)
367 btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
368 else
369 btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
371 btwrite(geo->vtc, BT848_E_VTC+off);
372 btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off);
373 btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off);
374 btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
375 btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off);
376 btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off);
377 btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off);
378 btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off);
379 btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off);
380 btwrite(geo->crop, BT848_E_CROP+off);
381 btwrite(geo->vtotal>>8, BT848_VTOTAL_HI);
382 btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO);
385 /* ---------------------------------------------------------- */
386 /* risc group / risc main loop / dma management */
388 void
389 bttv_set_dma(struct bttv *btv, int override)
391 unsigned long cmd;
392 int capctl;
394 btv->cap_ctl = 0;
395 if (NULL != btv->curr.top) btv->cap_ctl |= 0x02;
396 if (NULL != btv->curr.bottom) btv->cap_ctl |= 0x01;
397 if (NULL != btv->cvbi) btv->cap_ctl |= 0x0c;
399 capctl = 0;
400 capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00; /* capture */
401 capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00; /* vbi data */
402 capctl |= override;
404 d2printk(KERN_DEBUG
405 "bttv%d: capctl=%x lirq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",
406 btv->c.nr,capctl,btv->loop_irq,
407 btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
408 btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
409 btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0,
410 btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
412 cmd = BT848_RISC_JUMP;
413 if (btv->loop_irq) {
414 cmd |= BT848_RISC_IRQ;
415 cmd |= (btv->loop_irq & 0x0f) << 16;
416 cmd |= (~btv->loop_irq & 0x0f) << 20;
418 if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
419 mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
420 } else {
421 del_timer(&btv->timeout);
423 btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
425 btaor(capctl, ~0x0f, BT848_CAP_CTL);
426 if (capctl) {
427 if (btv->dma_on)
428 return;
429 btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
430 btor(3, BT848_GPIO_DMA_CTL);
431 btv->dma_on = 1;
432 } else {
433 if (!btv->dma_on)
434 return;
435 btand(~3, BT848_GPIO_DMA_CTL);
436 btv->dma_on = 0;
438 return;
442 bttv_risc_init_main(struct bttv *btv)
444 int rc;
446 if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
447 return rc;
448 dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n",
449 btv->c.nr,(unsigned long long)btv->main.dma);
451 btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
452 BT848_FIFO_STATUS_VRE);
453 btv->main.cpu[1] = cpu_to_le32(0);
454 btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
455 btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
457 /* top field */
458 btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
459 btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
460 btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
461 btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
463 btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
464 BT848_FIFO_STATUS_VRO);
465 btv->main.cpu[9] = cpu_to_le32(0);
467 /* bottom field */
468 btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
469 btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
470 btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
471 btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
473 /* jump back to top field */
474 btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
475 btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
477 return 0;
481 bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
482 int irqflags)
484 unsigned long cmd;
485 unsigned long next = btv->main.dma + ((slot+2) << 2);
487 if (NULL == risc) {
488 d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=NULL\n",
489 btv->c.nr,risc,slot);
490 btv->main.cpu[slot+1] = cpu_to_le32(next);
491 } else {
492 d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n",
493 btv->c.nr,risc,slot,(unsigned long long)risc->dma,irqflags);
494 cmd = BT848_RISC_JUMP;
495 if (irqflags) {
496 cmd |= BT848_RISC_IRQ;
497 cmd |= (irqflags & 0x0f) << 16;
498 cmd |= (~irqflags & 0x0f) << 20;
500 risc->jmp[0] = cpu_to_le32(cmd);
501 risc->jmp[1] = cpu_to_le32(next);
502 btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
504 return 0;
507 void
508 bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf)
510 if (in_interrupt())
511 BUG();
512 videobuf_waiton(&buf->vb,0,0);
513 videobuf_dma_pci_unmap(btv->c.pci, &buf->vb.dma);
514 videobuf_dma_free(&buf->vb.dma);
515 btcx_riscmem_free(btv->c.pci,&buf->bottom);
516 btcx_riscmem_free(btv->c.pci,&buf->top);
517 buf->vb.state = STATE_NEEDS_INIT;
521 bttv_buffer_activate_vbi(struct bttv *btv,
522 struct bttv_buffer *vbi)
524 /* vbi capture */
525 if (vbi) {
526 vbi->vb.state = STATE_ACTIVE;
527 list_del(&vbi->vb.queue);
528 bttv_risc_hook(btv, RISC_SLOT_O_VBI, &vbi->top, 0);
529 bttv_risc_hook(btv, RISC_SLOT_E_VBI, &vbi->bottom, 4);
530 } else {
531 bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0);
532 bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0);
534 return 0;
538 bttv_buffer_activate_video(struct bttv *btv,
539 struct bttv_buffer_set *set)
541 /* video capture */
542 if (NULL != set->top && NULL != set->bottom) {
543 if (set->top == set->bottom) {
544 set->top->vb.state = STATE_ACTIVE;
545 if (set->top->vb.queue.next)
546 list_del(&set->top->vb.queue);
547 } else {
548 set->top->vb.state = STATE_ACTIVE;
549 set->bottom->vb.state = STATE_ACTIVE;
550 if (set->top->vb.queue.next)
551 list_del(&set->top->vb.queue);
552 if (set->bottom->vb.queue.next)
553 list_del(&set->bottom->vb.queue);
555 bttv_apply_geo(btv, &set->top->geo, 1);
556 bttv_apply_geo(btv, &set->bottom->geo,0);
557 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
558 set->top_irq);
559 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
560 set->frame_irq);
561 btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
562 ~0xff, BT848_COLOR_FMT);
563 btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
564 ~0x0f, BT848_COLOR_CTL);
565 } else if (NULL != set->top) {
566 set->top->vb.state = STATE_ACTIVE;
567 if (set->top->vb.queue.next)
568 list_del(&set->top->vb.queue);
569 bttv_apply_geo(btv, &set->top->geo,1);
570 bttv_apply_geo(btv, &set->top->geo,0);
571 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
572 set->frame_irq);
573 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
574 btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
575 btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
576 } else if (NULL != set->bottom) {
577 set->bottom->vb.state = STATE_ACTIVE;
578 if (set->bottom->vb.queue.next)
579 list_del(&set->bottom->vb.queue);
580 bttv_apply_geo(btv, &set->bottom->geo,1);
581 bttv_apply_geo(btv, &set->bottom->geo,0);
582 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
583 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
584 set->frame_irq);
585 btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
586 btaor(set->bottom->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
587 } else {
588 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
589 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
591 return 0;
594 /* ---------------------------------------------------------- */
596 /* calculate geometry, build risc code */
598 bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
600 const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
602 dprintk(KERN_DEBUG
603 "bttv%d: buffer field: %s format: %s size: %dx%d\n",
604 btv->c.nr, v4l2_field_names[buf->vb.field],
605 buf->fmt->name, buf->vb.width, buf->vb.height);
607 /* packed pixel modes */
608 if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
609 int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
610 int bpf = bpl * (buf->vb.height >> 1);
612 bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
613 V4L2_FIELD_HAS_BOTH(buf->vb.field),buf->tvnorm);
615 switch (buf->vb.field) {
616 case V4L2_FIELD_TOP:
617 bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
618 0,bpl,0,buf->vb.height);
619 break;
620 case V4L2_FIELD_BOTTOM:
621 bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
622 0,bpl,0,buf->vb.height);
623 break;
624 case V4L2_FIELD_INTERLACED:
625 bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
626 0,bpl,bpl,buf->vb.height >> 1);
627 bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
628 bpl,bpl,bpl,buf->vb.height >> 1);
629 break;
630 case V4L2_FIELD_SEQ_TB:
631 bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
632 0,bpl,0,buf->vb.height >> 1);
633 bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
634 bpf,bpl,0,buf->vb.height >> 1);
635 break;
636 default:
637 BUG();
641 /* planar modes */
642 if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
643 int uoffset, voffset;
644 int ypadding, cpadding, lines;
646 /* calculate chroma offsets */
647 uoffset = buf->vb.width * buf->vb.height;
648 voffset = buf->vb.width * buf->vb.height;
649 if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
650 /* Y-Cr-Cb plane order */
651 uoffset >>= buf->fmt->hshift;
652 uoffset >>= buf->fmt->vshift;
653 uoffset += voffset;
654 } else {
655 /* Y-Cb-Cr plane order */
656 voffset >>= buf->fmt->hshift;
657 voffset >>= buf->fmt->vshift;
658 voffset += uoffset;
661 switch (buf->vb.field) {
662 case V4L2_FIELD_TOP:
663 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
664 buf->vb.height,0,buf->tvnorm);
665 bttv_risc_planar(btv, &buf->top, buf->vb.dma.sglist,
666 0,buf->vb.width,0,buf->vb.height,
667 uoffset,voffset,buf->fmt->hshift,
668 buf->fmt->vshift,0);
669 break;
670 case V4L2_FIELD_BOTTOM:
671 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
672 buf->vb.height,0,buf->tvnorm);
673 bttv_risc_planar(btv, &buf->bottom, buf->vb.dma.sglist,
674 0,buf->vb.width,0,buf->vb.height,
675 uoffset,voffset,buf->fmt->hshift,
676 buf->fmt->vshift,0);
677 break;
678 case V4L2_FIELD_INTERLACED:
679 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
680 buf->vb.height,1,buf->tvnorm);
681 lines = buf->vb.height >> 1;
682 ypadding = buf->vb.width;
683 cpadding = buf->vb.width >> buf->fmt->hshift;
684 bttv_risc_planar(btv,&buf->top,
685 buf->vb.dma.sglist,
686 0,buf->vb.width,ypadding,lines,
687 uoffset,voffset,
688 buf->fmt->hshift,
689 buf->fmt->vshift,
690 cpadding);
691 bttv_risc_planar(btv,&buf->bottom,
692 buf->vb.dma.sglist,
693 ypadding,buf->vb.width,ypadding,lines,
694 uoffset+cpadding,
695 voffset+cpadding,
696 buf->fmt->hshift,
697 buf->fmt->vshift,
698 cpadding);
699 break;
700 case V4L2_FIELD_SEQ_TB:
701 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
702 buf->vb.height,1,buf->tvnorm);
703 lines = buf->vb.height >> 1;
704 ypadding = buf->vb.width;
705 cpadding = buf->vb.width >> buf->fmt->hshift;
706 bttv_risc_planar(btv,&buf->top,
707 buf->vb.dma.sglist,
708 0,buf->vb.width,0,lines,
709 uoffset >> 1,
710 voffset >> 1,
711 buf->fmt->hshift,
712 buf->fmt->vshift,
714 bttv_risc_planar(btv,&buf->bottom,
715 buf->vb.dma.sglist,
716 lines * ypadding,buf->vb.width,0,lines,
717 lines * ypadding + (uoffset >> 1),
718 lines * ypadding + (voffset >> 1),
719 buf->fmt->hshift,
720 buf->fmt->vshift,
722 break;
723 default:
724 BUG();
728 /* raw data */
729 if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
730 /* build risc code */
731 buf->vb.field = V4L2_FIELD_SEQ_TB;
732 bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
733 1,buf->tvnorm);
734 bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist,
735 0, RAW_BPL, 0, RAW_LINES);
736 bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist,
737 buf->vb.size/2 , RAW_BPL, 0, RAW_LINES);
740 /* copy format info */
741 buf->btformat = buf->fmt->btformat;
742 buf->btswap = buf->fmt->btswap;
743 return 0;
746 /* ---------------------------------------------------------- */
748 /* calculate geometry, build risc code */
750 bttv_overlay_risc(struct bttv *btv,
751 struct bttv_overlay *ov,
752 const struct bttv_format *fmt,
753 struct bttv_buffer *buf)
755 /* check interleave, bottom+top fields */
756 dprintk(KERN_DEBUG
757 "bttv%d: overlay fields: %s format: %s size: %dx%d\n",
758 btv->c.nr, v4l2_field_names[buf->vb.field],
759 fmt->name,ov->w.width,ov->w.height);
761 /* calculate geometry */
762 bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
763 V4L2_FIELD_HAS_BOTH(ov->field), ov->tvnorm);
765 /* build risc code */
766 switch (ov->field) {
767 case V4L2_FIELD_TOP:
768 bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 0);
769 break;
770 case V4L2_FIELD_BOTTOM:
771 bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
772 break;
773 case V4L2_FIELD_INTERLACED:
774 bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 1);
775 bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
776 break;
777 default:
778 BUG();
781 /* copy format info */
782 buf->btformat = fmt->btformat;
783 buf->btswap = fmt->btswap;
784 buf->vb.field = ov->field;
785 return 0;
789 * Local variables:
790 * c-basic-offset: 8
791 * End: