vserver 1.9.3
[linux-2.6.git] / drivers / media / video / bttv-risc.c
1 /*
2     bttv-risc.c  --  interfaces to other kernel modules
3
4     bttv risc code handling
5         - memory management
6         - generation
7
8     (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org>
9
10     This program is free software; you can redistribute it and/or modify
11     it under the terms of the GNU General Public License as published by
12     the Free Software Foundation; either version 2 of the License, or
13     (at your option) any later version.
14
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18     GNU General Public License for more details.
19
20     You should have received a copy of the GNU General Public License
21     along with this program; if not, write to the Free Software
22     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
24 */
25
26 #include <linux/module.h>
27 #include <linux/init.h>
28 #include <linux/pci.h>
29 #include <linux/vmalloc.h>
30 #include <linux/interrupt.h>
31 #include <asm/page.h>
32 #include <asm/pgtable.h>
33
34 #include "bttvp.h"
35
36 #define VCR_HACK_LINES 4
37
38 /* ---------------------------------------------------------- */
39 /* risc code generators                                       */
40
41 int
42 bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
43                  struct scatterlist *sglist,
44                  unsigned int offset, unsigned int bpl,
45                  unsigned int padding, unsigned int lines)
46 {
47         u32 instructions,line,todo;
48         struct scatterlist *sg;
49         u32 *rp;
50         int rc;
51
52         /* estimate risc mem: worst case is one write per page border +
53            one write per scan line + sync + jump (all 2 dwords) */
54         instructions  = (bpl * lines) / PAGE_SIZE + lines;
55         instructions += 2;
56         if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0)
57                 return rc;
58         dprintk("bttv%d: risc packed: bpl %d lines %d instr %d size %d ptr %p\n",
59                 btv->c.nr, bpl, lines, instructions, risc->size, risc->cpu);
60
61         /* sync instruction */
62         rp = risc->cpu;
63         *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
64         *(rp++) = cpu_to_le32(0);
65
66         /* scan lines */
67         sg = sglist;
68         for (line = 0; line < lines; line++) {
69                 if ((btv->opt_vcr_hack) &&
70                     (line >= (lines - VCR_HACK_LINES)))
71                         continue;
72                 while (offset && offset >= sg_dma_len(sg)) {
73                         offset -= sg_dma_len(sg);
74                         sg++;
75                 }
76                 if (bpl <= sg_dma_len(sg)-offset) {
77                         /* fits into current chunk */
78                         *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
79                                             BT848_RISC_EOL|bpl);
80                         *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
81                         offset+=bpl;
82                 } else {
83                         /* scanline needs to be splitted */
84                         todo = bpl;
85                         *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
86                                             (sg_dma_len(sg)-offset));
87                         *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
88                         todo -= (sg_dma_len(sg)-offset);
89                         offset = 0;
90                         sg++;
91                         while (todo > sg_dma_len(sg)) {
92                                 *(rp++)=cpu_to_le32(BT848_RISC_WRITE|
93                                                     sg_dma_len(sg));
94                                 *(rp++)=cpu_to_le32(sg_dma_address(sg));
95                                 todo -= sg_dma_len(sg);
96                                 sg++;
97                         }
98                         *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
99                                             todo);
100                         *(rp++)=cpu_to_le32(sg_dma_address(sg));
101                         offset += todo;
102                 }
103                 offset += padding;
104                 dprintk("bttv%d: risc packed:   line %d ptr %p\n",
105                         btv->c.nr, line, rp);
106         }
107         dprintk("bttv%d: risc packed: %d sglist elems\n", btv->c.nr, (int)(sg-sglist));
108
109         /* save pointer to jmp instruction address */
110         risc->jmp = rp;
111         return 0;
112 }
113
114 int
115 bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
116                  struct scatterlist *sglist,
117                  unsigned int yoffset,  unsigned int ybpl,
118                  unsigned int ypadding, unsigned int ylines,
119                  unsigned int uoffset,  unsigned int voffset,
120                  unsigned int hshift,   unsigned int vshift,
121                  unsigned int cpadding)
122 {
123         unsigned int instructions,line,todo,ylen,chroma;
124         u32 *rp,ri;
125         struct scatterlist *ysg;
126         struct scatterlist *usg;
127         struct scatterlist *vsg;
128         int topfield = (0 == yoffset);
129         int rc;
130
131         /* estimate risc mem: worst case is one write per page border +
132            one write per scan line (5 dwords)
133            plus sync + jump (2 dwords) */
134         instructions  = (ybpl * ylines * 2) / PAGE_SIZE + ylines;
135         instructions += 2;
136         if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
137                 return rc;
138
139         /* sync instruction */
140         rp = risc->cpu;
141         *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
142         *(rp++) = cpu_to_le32(0);
143
144         /* scan lines */
145         ysg = sglist;
146         usg = sglist;
147         vsg = sglist;
148         for (line = 0; line < ylines; line++) {
149                 if ((btv->opt_vcr_hack) &&
150                     (line >= (ylines - VCR_HACK_LINES)))
151                         continue;
152                 switch (vshift) {
153                 case 0:
154                         chroma = 1;
155                         break;
156                 case 1:
157                         if (topfield)
158                                 chroma = (line & 1) == 0;
159                         else
160                                 chroma = (line & 1) == 1;
161                         break;
162                 case 2:
163                         if (topfield)
164                                 chroma = (line & 3) == 0;
165                         else
166                                 chroma = (line & 3) == 2;
167                         break;
168                 default:
169                         chroma = 0;
170                         break;
171                 }
172
173                 for (todo = ybpl; todo > 0; todo -= ylen) {
174                         /* go to next sg entry if needed */
175                         while (yoffset && yoffset >= sg_dma_len(ysg)) {
176                                 yoffset -= sg_dma_len(ysg);
177                                 ysg++;
178                         }
179                         while (uoffset && uoffset >= sg_dma_len(usg)) {
180                                 uoffset -= sg_dma_len(usg);
181                                 usg++;
182                         }
183                         while (voffset && voffset >= sg_dma_len(vsg)) {
184                                 voffset -= sg_dma_len(vsg);
185                                 vsg++;
186                         }
187
188                         /* calculate max number of bytes we can write */
189                         ylen = todo;
190                         if (yoffset + ylen > sg_dma_len(ysg))
191                                 ylen = sg_dma_len(ysg) - yoffset;
192                         if (chroma) {
193                                 if (uoffset + (ylen>>hshift) > sg_dma_len(usg))
194                                         ylen = (sg_dma_len(usg) - uoffset) << hshift;
195                                 if (voffset + (ylen>>hshift) > sg_dma_len(vsg))
196                                         ylen = (sg_dma_len(vsg) - voffset) << hshift;
197                                 ri = BT848_RISC_WRITE123;
198                         } else {
199                                 ri = BT848_RISC_WRITE1S23;
200                         }
201                         if (ybpl == todo)
202                                 ri |= BT848_RISC_SOL;
203                         if (ylen == todo)
204                                 ri |= BT848_RISC_EOL;
205
206                         /* write risc instruction */
207                         *(rp++)=cpu_to_le32(ri | ylen);
208                         *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
209                                             (ylen >> hshift));
210                         *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
211                         yoffset += ylen;
212                         if (chroma) {
213                                 *(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);
214                                 uoffset += ylen >> hshift;
215                                 *(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);
216                                 voffset += ylen >> hshift;
217                         }
218                 }
219                 yoffset += ypadding;
220                 if (chroma) {
221                         uoffset += cpadding;
222                         voffset += cpadding;
223                 }
224         }
225
226         /* save pointer to jmp instruction address */
227         risc->jmp = rp;
228         return 0;
229 }
230
231 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)
235 {
236         int instructions,rc,line,maxy,start,end,skip,nskips;
237         struct btcx_skiplist *skips;
238         u32 *rp,ri,ra;
239         u32 addr;
240
241         /* skip list for window clipping */
242         if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
243                 return -ENOMEM;
244         
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;
253         }
254
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);
259
260         addr  = (unsigned long)btv->fbuf.base;
261         addr += btv->fbuf.fmt.bytesperline * ov->w.top;
262         addr += (fmt->depth >> 3)          * ov->w.left;
263
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;
274
275                 /* calculate clipping */
276                 if (line > maxy)
277                         btcx_calc_skips(line, ov->w.width, &maxy,
278                                         skips, &nskips, ov->clips, ov->nclips);
279
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++;
292                         }
293                         if (BT848_RISC_WRITE == ri)
294                                 ra = addr + (fmt->depth>>3)*start;
295                         else
296                                 ra = 0;
297                                 
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);
303
304                         *(rp++)=cpu_to_le32(ri);
305                         if (0 != ra)
306                                 *(rp++)=cpu_to_le32(ra);
307                 }
308         }
309
310         /* save pointer to jmp instruction address */
311         risc->jmp = rp;
312         kfree(skips);
313         return 0;
314 }
315
316 /* ---------------------------------------------------------- */
317
318 void
319 bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo,
320               int width, int height, int interleaved, int norm)
321 {
322         const struct bttv_tvnorm *tvnorm = &bttv_tvnorms[norm];
323         u32 xsf, sr;
324         int vdelay;
325
326         int swidth       = tvnorm->swidth;
327         int totalwidth   = tvnorm->totalwidth;
328         int scaledtwidth = tvnorm->scaledtwidth;
329
330         if (bttv_tvcards[btv->c.type].muxsel[btv->input] < 0) {
331                 swidth       = 720;
332                 totalwidth   = 858;
333                 scaledtwidth = 858;
334         }
335
336         vdelay = tvnorm->vdelay;
337 #if 0 /* FIXME */
338         if (vdelay < btv->vbi.lines*2)
339                 vdelay = btv->vbi.lines*2;
340 #endif
341
342         xsf = (width*scaledtwidth)/swidth;
343         geo->hscale =  ((totalwidth*4096UL)/xsf-4096);
344         geo->hdelay =  tvnorm->hdelayx1;
345         geo->hdelay =  (geo->hdelay*width)/swidth;
346         geo->hdelay &= 0x3fe;
347         sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
348         geo->vscale =  (0x10000UL-sr) & 0x1fff;
349         geo->crop   =  ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
350                 ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
351         geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
352         geo->vdelay  =  vdelay;
353         geo->width   =  width;
354         geo->sheight =  tvnorm->sheight;
355         geo->vtotal  =  tvnorm->vtotal;
356
357         if (btv->opt_combfilter) {
358                 geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
359                 geo->comb = (width < 769) ? 1 : 0;
360         } else {
361                 geo->vtc  = 0;
362                 geo->comb = 0;
363         }
364 }
365
366 void
367 bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
368 {
369         int off = odd ? 0x80 : 0x00;
370
371         if (geo->comb)
372                 btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
373         else
374                 btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
375
376         btwrite(geo->vtc,             BT848_E_VTC+off);
377         btwrite(geo->hscale >> 8,     BT848_E_HSCALE_HI+off);
378         btwrite(geo->hscale & 0xff,   BT848_E_HSCALE_LO+off);
379         btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
380         btwrite(geo->vscale & 0xff,   BT848_E_VSCALE_LO+off);
381         btwrite(geo->width & 0xff,    BT848_E_HACTIVE_LO+off);
382         btwrite(geo->hdelay & 0xff,   BT848_E_HDELAY_LO+off);
383         btwrite(geo->sheight & 0xff,  BT848_E_VACTIVE_LO+off);
384         btwrite(geo->vdelay & 0xff,   BT848_E_VDELAY_LO+off);
385         btwrite(geo->crop,            BT848_E_CROP+off);
386         btwrite(geo->vtotal>>8,       BT848_VTOTAL_HI);
387         btwrite(geo->vtotal & 0xff,   BT848_VTOTAL_LO);
388 }
389
390 /* ---------------------------------------------------------- */
391 /* risc group / risc main loop / dma management               */
392
393 void
394 bttv_set_dma(struct bttv *btv, int override, int irqflags)
395 {
396         unsigned long cmd;
397         int capctl;
398
399         btv->cap_ctl = 0;
400         if (NULL != btv->curr.top)      btv->cap_ctl |= 0x02;
401         if (NULL != btv->curr.bottom)   btv->cap_ctl |= 0x01;
402         if (NULL != btv->cvbi)          btv->cap_ctl |= 0x0c;
403
404         capctl  = 0;
405         capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00;  /* capture  */
406         capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00;  /* vbi data */
407         capctl |= override;
408
409         d2printk(KERN_DEBUG
410                  "bttv%d: capctl=%x irq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",
411                  btv->c.nr,capctl,irqflags,
412                  btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
413                  btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
414                  btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,
415                  btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
416         
417         cmd = BT848_RISC_JUMP;
418         if (irqflags) {
419                 cmd |= BT848_RISC_IRQ;
420                 cmd |= (irqflags  & 0x0f) << 16;
421                 cmd |= (~irqflags & 0x0f) << 20;
422         }
423         if (irqflags || btv->cvbi) {
424                 mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
425         } else {
426                 del_timer(&btv->timeout);
427         }
428         btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
429         
430         btaor(capctl, ~0x0f, BT848_CAP_CTL);
431         if (capctl) {
432                 if (btv->dma_on)
433                         return;
434                 btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
435                 btor(3, BT848_GPIO_DMA_CTL);
436                 btv->dma_on = 1;
437         } else {
438                 if (!btv->dma_on)
439                         return;
440                 btand(~3, BT848_GPIO_DMA_CTL);
441                 btv->dma_on = 0;
442         }
443         return;
444 }
445
446 int
447 bttv_risc_init_main(struct bttv *btv)
448 {
449         int rc;
450         
451         if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
452                 return rc;
453         dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n",
454                 btv->c.nr,(unsigned long long)btv->main.dma);
455
456         btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
457                                        BT848_FIFO_STATUS_VRE);
458         btv->main.cpu[1] = cpu_to_le32(0);
459         btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
460         btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
461
462         /* top field */
463         btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
464         btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
465         btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
466         btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
467
468         btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
469                                        BT848_FIFO_STATUS_VRO);
470         btv->main.cpu[9] = cpu_to_le32(0);
471
472         /* bottom field */
473         btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
474         btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
475         btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
476         btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
477
478         /* jump back to top field */
479         btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
480         btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
481
482         return 0;
483 }
484
485 int
486 bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
487                int irqflags)
488 {
489         unsigned long cmd;
490         unsigned long next = btv->main.dma + ((slot+2) << 2);
491
492         if (NULL == risc) {
493                 d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=NULL\n",
494                          btv->c.nr,risc,slot);
495                 btv->main.cpu[slot+1] = cpu_to_le32(next);
496         } else {
497                 d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n",
498                          btv->c.nr,risc,slot,(unsigned long long)risc->dma,irqflags);
499                 cmd = BT848_RISC_JUMP;
500                 if (irqflags) {
501                         cmd |= BT848_RISC_IRQ;
502                         cmd |= (irqflags  & 0x0f) << 16;
503                         cmd |= (~irqflags & 0x0f) << 20;
504                 }
505                 risc->jmp[0] = cpu_to_le32(cmd);
506                 risc->jmp[1] = cpu_to_le32(next);
507                 btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
508         }
509         return 0;
510 }
511
512 void
513 bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf)
514 {
515         if (in_interrupt())
516                 BUG();
517         videobuf_waiton(&buf->vb,0,0);
518         videobuf_dma_pci_unmap(btv->c.pci, &buf->vb.dma);
519         videobuf_dma_free(&buf->vb.dma);
520         btcx_riscmem_free(btv->c.pci,&buf->bottom);
521         btcx_riscmem_free(btv->c.pci,&buf->top);
522         buf->vb.state = STATE_NEEDS_INIT;
523 }
524
525 int
526 bttv_buffer_activate_vbi(struct bttv *btv,
527                          struct bttv_buffer *vbi)
528 {
529         /* vbi capture */
530         if (vbi) {
531                 vbi->vb.state = STATE_ACTIVE;
532                 list_del(&vbi->vb.queue);
533                 bttv_risc_hook(btv, RISC_SLOT_O_VBI, &vbi->top,    0);
534                 bttv_risc_hook(btv, RISC_SLOT_E_VBI, &vbi->bottom, 4);
535         } else {
536                 bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0);
537                 bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0);
538         }
539         return 0;
540 }
541
542 int
543 bttv_buffer_activate_video(struct bttv *btv,
544                            struct bttv_buffer_set *set)
545 {
546         /* video capture */
547         if (NULL != set->top  &&  NULL != set->bottom) {
548                 if (set->top == set->bottom) {
549                         set->top->vb.state    = STATE_ACTIVE;
550                         if (set->top->vb.queue.next)
551                                 list_del(&set->top->vb.queue);
552                 } else {
553                         set->top->vb.state    = STATE_ACTIVE;
554                         set->bottom->vb.state = STATE_ACTIVE;
555                         if (set->top->vb.queue.next)
556                                 list_del(&set->top->vb.queue);
557                         if (set->bottom->vb.queue.next)
558                                 list_del(&set->bottom->vb.queue);
559                 }
560                 bttv_apply_geo(btv, &set->top->geo, 1);
561                 bttv_apply_geo(btv, &set->bottom->geo,0);
562                 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top, set->topirq);
563                 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom, 0);
564                 btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
565                       ~0xff, BT848_COLOR_FMT);
566                 btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
567                       ~0x0f, BT848_COLOR_CTL);
568         } else if (NULL != set->top) {
569                 set->top->vb.state  = STATE_ACTIVE;
570                 if (set->top->vb.queue.next)
571                         list_del(&set->top->vb.queue);
572                 bttv_apply_geo(btv, &set->top->geo,1);
573                 bttv_apply_geo(btv, &set->top->geo,0);
574                 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top, 0);
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, 0);
586                 btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
587                 btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
588         } else {
589                 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
590                 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
591         }
592         return 0;
593 }
594
595 /* ---------------------------------------------------------- */
596
597 /* calculate geometry, build risc code */
598 int
599 bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
600 {
601         const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
602
603         dprintk(KERN_DEBUG
604                 "bttv%d: buffer field: %s  format: %s  size: %dx%d\n",
605                 btv->c.nr, v4l2_field_names[buf->vb.field],
606                 buf->fmt->name, buf->vb.width, buf->vb.height);
607
608         /* packed pixel modes */
609         if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
610                 int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
611                 int bpf = bpl * (buf->vb.height >> 1);
612
613                 bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
614                               V4L2_FIELD_HAS_BOTH(buf->vb.field),buf->tvnorm);
615                 
616                 switch (buf->vb.field) {
617                 case V4L2_FIELD_TOP:
618                         bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
619                                          0,bpl,0,buf->vb.height);
620                         break;
621                 case V4L2_FIELD_BOTTOM:
622                         bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
623                                          0,bpl,0,buf->vb.height);
624                         break;
625                 case V4L2_FIELD_INTERLACED:
626                         bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
627                                          0,bpl,bpl,buf->vb.height >> 1);
628                         bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
629                                          bpl,bpl,bpl,buf->vb.height >> 1);
630                         break;
631                 case V4L2_FIELD_SEQ_TB:
632                         bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
633                                          0,bpl,0,buf->vb.height >> 1);
634                         bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
635                                          bpf,bpl,0,buf->vb.height >> 1);
636                         break;
637                 default:
638                         BUG();
639                 }
640         }
641
642         /* planar modes */
643         if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
644                 int uoffset, voffset;
645                 int ypadding, cpadding, lines;
646
647                 /* calculate chroma offsets */
648                 uoffset = buf->vb.width * buf->vb.height;
649                 voffset = buf->vb.width * buf->vb.height;
650                 if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
651                         /* Y-Cr-Cb plane order */
652                         uoffset >>= buf->fmt->hshift;
653                         uoffset >>= buf->fmt->vshift;
654                         uoffset  += voffset;
655                 } else {
656                         /* Y-Cb-Cr plane order */
657                         voffset >>= buf->fmt->hshift;
658                         voffset >>= buf->fmt->vshift;
659                         voffset  += uoffset;
660                 }
661
662                 switch (buf->vb.field) {
663                 case V4L2_FIELD_TOP:
664                         bttv_calc_geo(btv,&buf->geo,buf->vb.width,
665                                       buf->vb.height,0,buf->tvnorm);
666                         bttv_risc_planar(btv, &buf->top, buf->vb.dma.sglist,
667                                          0,buf->vb.width,0,buf->vb.height,
668                                          uoffset,voffset,buf->fmt->hshift,
669                                          buf->fmt->vshift,0);
670                         break;
671                 case V4L2_FIELD_BOTTOM:
672                         bttv_calc_geo(btv,&buf->geo,buf->vb.width,
673                                       buf->vb.height,0,buf->tvnorm);
674                         bttv_risc_planar(btv, &buf->bottom, buf->vb.dma.sglist,
675                                          0,buf->vb.width,0,buf->vb.height,
676                                          uoffset,voffset,buf->fmt->hshift,
677                                          buf->fmt->vshift,0);
678                         break;
679                 case V4L2_FIELD_INTERLACED:
680                         bttv_calc_geo(btv,&buf->geo,buf->vb.width,
681                                       buf->vb.height,1,buf->tvnorm);
682                         lines    = buf->vb.height >> 1;
683                         ypadding = buf->vb.width;
684                         cpadding = buf->vb.width >> buf->fmt->hshift;
685                         bttv_risc_planar(btv,&buf->top,
686                                          buf->vb.dma.sglist,
687                                          0,buf->vb.width,ypadding,lines,
688                                          uoffset,voffset,
689                                          buf->fmt->hshift,
690                                          buf->fmt->vshift,
691                                          cpadding);
692                         bttv_risc_planar(btv,&buf->bottom,
693                                          buf->vb.dma.sglist,
694                                          ypadding,buf->vb.width,ypadding,lines,
695                                          uoffset+cpadding,
696                                          voffset+cpadding,
697                                          buf->fmt->hshift,
698                                          buf->fmt->vshift,
699                                          cpadding);
700                         break;
701                 case V4L2_FIELD_SEQ_TB:
702                         bttv_calc_geo(btv,&buf->geo,buf->vb.width,
703                                       buf->vb.height,1,buf->tvnorm);
704                         lines    = buf->vb.height >> 1;
705                         ypadding = buf->vb.width;
706                         cpadding = buf->vb.width >> buf->fmt->hshift;
707                         bttv_risc_planar(btv,&buf->top,
708                                          buf->vb.dma.sglist,
709                                          0,buf->vb.width,0,lines,
710                                          uoffset >> 1,
711                                          voffset >> 1,
712                                          buf->fmt->hshift,
713                                          buf->fmt->vshift,
714                                          0);
715                         bttv_risc_planar(btv,&buf->bottom,
716                                          buf->vb.dma.sglist,
717                                          lines * ypadding,buf->vb.width,0,lines,
718                                          lines * ypadding + (uoffset >> 1),
719                                          lines * ypadding + (voffset >> 1),
720                                          buf->fmt->hshift,
721                                          buf->fmt->vshift,
722                                          0);
723                         break;
724                 default:
725                         BUG();
726                 }
727         }
728
729         /* raw data */
730         if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
731                 /* build risc code */
732                 buf->vb.field = V4L2_FIELD_SEQ_TB;
733                 bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
734                               1,buf->tvnorm);
735                 bttv_risc_packed(btv, &buf->top,  buf->vb.dma.sglist,
736                                  0, RAW_BPL, 0, RAW_LINES);
737                 bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist,
738                                  buf->vb.size/2 , RAW_BPL, 0, RAW_LINES);
739         }
740
741         /* copy format info */
742         buf->btformat = buf->fmt->btformat;
743         buf->btswap   = buf->fmt->btswap;
744         return 0;
745 }
746
747 /* ---------------------------------------------------------- */
748
749 /* calculate geometry, build risc code */
750 int
751 bttv_overlay_risc(struct bttv *btv,
752                   struct bttv_overlay *ov,
753                   const struct bttv_format *fmt,
754                   struct bttv_buffer *buf)
755 {
756         /* check interleave, bottom+top fields */
757         dprintk(KERN_DEBUG
758                 "bttv%d: overlay fields: %s format: %s  size: %dx%d\n",
759                 btv->c.nr, v4l2_field_names[buf->vb.field],
760                 fmt->name,ov->w.width,ov->w.height);
761
762         /* calculate geometry */
763         bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
764                       V4L2_FIELD_HAS_BOTH(ov->field), ov->tvnorm);
765
766         /* build risc code */
767         switch (ov->field) {
768         case V4L2_FIELD_TOP:
769                 bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 0);
770                 break;
771         case V4L2_FIELD_BOTTOM:
772                 bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
773                 break;
774         case V4L2_FIELD_INTERLACED:
775 #if 0
776                 bttv_risc_overlay(btv, &buf->top,    fmt, ov, 1, 0);
777                 bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 1);
778 #else
779                 bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 1);
780                 bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
781 #endif
782                 break;
783         default:
784                 BUG();
785         }
786
787         /* copy format info */
788         buf->btformat = fmt->btformat;
789         buf->btswap   = fmt->btswap;
790         buf->vb.field = ov->field;
791         return 0;
792 }
793
794 /*
795  * Local variables:
796  * c-basic-offset: 8
797  * End:
798  */