Merge tag 'for-6.5-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
[linux-2.6-microblaze.git] / drivers / media / pci / bt8xx / bttv-risc.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3
4     bttv-risc.c  --  interfaces to other kernel modules
5
6     bttv risc code handling
7         - memory management
8         - generation
9
10     (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org>
11
12
13 */
14
15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16
17 #include <linux/module.h>
18 #include <linux/init.h>
19 #include <linux/slab.h>
20 #include <linux/pci.h>
21 #include <linux/vmalloc.h>
22 #include <linux/interrupt.h>
23 #include <linux/pgtable.h>
24 #include <asm/page.h>
25 #include <media/v4l2-ioctl.h>
26
27 #include "bttvp.h"
28
29 #define VCR_HACK_LINES 4
30
31 /* ---------------------------------------------------------- */
32 /* risc code generators                                       */
33
34 int
35 bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
36                  struct scatterlist *sglist,
37                  unsigned int offset, unsigned int bpl,
38                  unsigned int padding, unsigned int skip_lines,
39                  unsigned int store_lines)
40 {
41         u32 instructions,line,todo;
42         struct scatterlist *sg;
43         __le32 *rp;
44         int rc;
45
46         /* estimate risc mem: worst case is one write per page border +
47            one write per scan line + sync + jump (all 2 dwords).  padding
48            can cause next bpl to start close to a page border.  First DMA
49            region may be smaller than PAGE_SIZE */
50         instructions  = skip_lines * 4;
51         instructions += (1 + ((bpl + padding) * store_lines)
52                          / PAGE_SIZE + store_lines) * 8;
53         instructions += 2 * 8;
54         if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions)) < 0)
55                 return rc;
56
57         /* sync instruction */
58         rp = risc->cpu;
59         *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
60         *(rp++) = cpu_to_le32(0);
61
62         while (skip_lines-- > 0) {
63                 *(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |
64                                       BT848_RISC_EOL | bpl);
65         }
66
67         /* scan lines */
68         sg = sglist;
69         for (line = 0; line < store_lines; line++) {
70                 if ((btv->opt_vcr_hack) &&
71                     (line >= (store_lines - VCR_HACK_LINES)))
72                         continue;
73                 while (offset && offset >= sg_dma_len(sg)) {
74                         offset -= sg_dma_len(sg);
75                         sg = sg_next(sg);
76                 }
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 split */
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 = sg_next(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 = sg_next(sg);
98                         }
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;
103                 }
104                 offset += padding;
105         }
106
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;
111 }
112
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)
121 {
122         unsigned int instructions,line,todo,ylen,chroma;
123         __le32 *rp;
124         u32 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  = ((3 + (ybpl + ypadding) * ylines * 2)
135                          / PAGE_SIZE) + ylines;
136         instructions += 2;
137         if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
138                 return rc;
139
140         /* sync instruction */
141         rp = risc->cpu;
142         *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
143         *(rp++) = cpu_to_le32(0);
144
145         /* scan lines */
146         ysg = sglist;
147         usg = sglist;
148         vsg = sglist;
149         for (line = 0; line < ylines; line++) {
150                 if ((btv->opt_vcr_hack) &&
151                     (line >= (ylines - VCR_HACK_LINES)))
152                         continue;
153                 switch (vshift) {
154                 case 0:
155                         chroma = 1;
156                         break;
157                 case 1:
158                         if (topfield)
159                                 chroma = ((line & 1) == 0);
160                         else
161                                 chroma = ((line & 1) == 1);
162                         break;
163                 case 2:
164                         if (topfield)
165                                 chroma = ((line & 3) == 0);
166                         else
167                                 chroma = ((line & 3) == 2);
168                         break;
169                 default:
170                         chroma = 0;
171                         break;
172                 }
173
174                 for (todo = ybpl; todo > 0; todo -= ylen) {
175                         /* go to next sg entry if needed */
176                         while (yoffset && yoffset >= sg_dma_len(ysg)) {
177                                 yoffset -= sg_dma_len(ysg);
178                                 ysg = sg_next(ysg);
179                         }
180
181                         /* calculate max number of bytes we can write */
182                         ylen = todo;
183                         if (yoffset + ylen > sg_dma_len(ysg))
184                                 ylen = sg_dma_len(ysg) - yoffset;
185                         if (chroma) {
186                                 while (uoffset && uoffset >= sg_dma_len(usg)) {
187                                         uoffset -= sg_dma_len(usg);
188                                         usg = sg_next(usg);
189                                 }
190                                 while (voffset && voffset >= sg_dma_len(vsg)) {
191                                         voffset -= sg_dma_len(vsg);
192                                         vsg = sg_next(vsg);
193                                 }
194
195                                 if (uoffset + (ylen>>hshift) > sg_dma_len(usg))
196                                         ylen = (sg_dma_len(usg) - uoffset) << hshift;
197                                 if (voffset + (ylen>>hshift) > sg_dma_len(vsg))
198                                         ylen = (sg_dma_len(vsg) - voffset) << hshift;
199                                 ri = BT848_RISC_WRITE123;
200                         } else {
201                                 ri = BT848_RISC_WRITE1S23;
202                         }
203                         if (ybpl == todo)
204                                 ri |= BT848_RISC_SOL;
205                         if (ylen == todo)
206                                 ri |= BT848_RISC_EOL;
207
208                         /* write risc instruction */
209                         *(rp++)=cpu_to_le32(ri | ylen);
210                         *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
211                                             (ylen >> hshift));
212                         *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
213                         yoffset += ylen;
214                         if (chroma) {
215                                 *(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);
216                                 uoffset += ylen >> hshift;
217                                 *(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);
218                                 voffset += ylen >> hshift;
219                         }
220                 }
221                 yoffset += ypadding;
222                 if (chroma) {
223                         uoffset += cpadding;
224                         voffset += cpadding;
225                 }
226         }
227
228         /* save pointer to jmp instruction address */
229         risc->jmp = rp;
230         BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
231         return 0;
232 }
233
234 /* ---------------------------------------------------------- */
235
236 static void
237 bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
238                   int width, int height, int interleaved,
239                   const struct bttv_tvnorm *tvnorm)
240 {
241         u32 xsf, sr;
242         int vdelay;
243
244         int swidth       = tvnorm->swidth;
245         int totalwidth   = tvnorm->totalwidth;
246         int scaledtwidth = tvnorm->scaledtwidth;
247
248         if (btv->input == btv->dig) {
249                 swidth       = 720;
250                 totalwidth   = 858;
251                 scaledtwidth = 858;
252         }
253
254         vdelay = tvnorm->vdelay;
255
256         xsf = (width*scaledtwidth)/swidth;
257         geo->hscale =  ((totalwidth*4096UL)/xsf-4096);
258         geo->hdelay =  tvnorm->hdelayx1;
259         geo->hdelay =  (geo->hdelay*width)/swidth;
260         geo->hdelay &= 0x3fe;
261         sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
262         geo->vscale =  (0x10000UL-sr) & 0x1fff;
263         geo->crop   =  ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
264                 ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
265         geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
266         geo->vdelay  =  vdelay;
267         geo->width   =  width;
268         geo->sheight =  tvnorm->sheight;
269         geo->vtotal  =  tvnorm->vtotal;
270
271         if (btv->opt_combfilter) {
272                 geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
273                 geo->comb = (width < 769) ? 1 : 0;
274         } else {
275                 geo->vtc  = 0;
276                 geo->comb = 0;
277         }
278 }
279
280 static void
281 bttv_calc_geo           (struct bttv *                  btv,
282                          struct bttv_geometry *         geo,
283                          unsigned int                   width,
284                          unsigned int                   height,
285                          int                            both_fields,
286                          const struct bttv_tvnorm *     tvnorm,
287                          const struct v4l2_rect *       crop)
288 {
289         unsigned int c_width;
290         unsigned int c_height;
291         u32 sr;
292
293         if ((crop->left == tvnorm->cropcap.defrect.left
294              && crop->top == tvnorm->cropcap.defrect.top
295              && crop->width == tvnorm->cropcap.defrect.width
296              && crop->height == tvnorm->cropcap.defrect.height
297              && width <= tvnorm->swidth /* see PAL-Nc et al */)
298             || btv->input == btv->dig) {
299                 bttv_calc_geo_old(btv, geo, width, height,
300                                   both_fields, tvnorm);
301                 return;
302         }
303
304         /* For bug compatibility the image size checks permit scale
305            factors > 16. See bttv_crop_calc_limits(). */
306         c_width = min((unsigned int) crop->width, width * 16);
307         c_height = min((unsigned int) crop->height, height * 16);
308
309         geo->width = width;
310         geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;
311         /* Even to store Cb first, odd for Cr. */
312         geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;
313
314         geo->sheight = c_height;
315         geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
316         sr = c_height >> !both_fields;
317         sr = (sr * 512U + (height >> 1)) / height - 512;
318         geo->vscale = (0x10000UL - sr) & 0x1fff;
319         geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;
320         geo->vtotal = tvnorm->vtotal;
321
322         geo->crop = (((geo->width   >> 8) & 0x03) |
323                      ((geo->hdelay  >> 6) & 0x0c) |
324                      ((geo->sheight >> 4) & 0x30) |
325                      ((geo->vdelay  >> 2) & 0xc0));
326
327         if (btv->opt_combfilter) {
328                 geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
329                 geo->comb = (width < 769) ? 1 : 0;
330         } else {
331                 geo->vtc  = 0;
332                 geo->comb = 0;
333         }
334 }
335
336 static void
337 bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
338 {
339         int off = odd ? 0x80 : 0x00;
340
341         if (geo->comb)
342                 btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
343         else
344                 btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
345
346         btwrite(geo->vtc,             BT848_E_VTC+off);
347         btwrite(geo->hscale >> 8,     BT848_E_HSCALE_HI+off);
348         btwrite(geo->hscale & 0xff,   BT848_E_HSCALE_LO+off);
349         btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
350         btwrite(geo->vscale & 0xff,   BT848_E_VSCALE_LO+off);
351         btwrite(geo->width & 0xff,    BT848_E_HACTIVE_LO+off);
352         btwrite(geo->hdelay & 0xff,   BT848_E_HDELAY_LO+off);
353         btwrite(geo->sheight & 0xff,  BT848_E_VACTIVE_LO+off);
354         btwrite(geo->vdelay & 0xff,   BT848_E_VDELAY_LO+off);
355         btwrite(geo->crop,            BT848_E_CROP+off);
356         btwrite(geo->vtotal>>8,       BT848_VTOTAL_HI);
357         btwrite(geo->vtotal & 0xff,   BT848_VTOTAL_LO);
358 }
359
360 /* ---------------------------------------------------------- */
361 /* risc group / risc main loop / dma management               */
362
363 void
364 bttv_set_dma(struct bttv *btv, int override)
365 {
366         unsigned long cmd;
367         int capctl;
368
369         btv->cap_ctl = 0;
370         if (NULL != btv->curr.top)      btv->cap_ctl |= 0x02;
371         if (NULL != btv->curr.bottom)   btv->cap_ctl |= 0x01;
372         if (NULL != btv->cvbi)          btv->cap_ctl |= 0x0c;
373
374         capctl  = 0;
375         capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00;  /* capture  */
376         capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00;  /* vbi data */
377         capctl |= override;
378
379         d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
380                  btv->c.nr,capctl,btv->loop_irq,
381                  btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
382                  btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
383                  btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,
384                  btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
385
386         cmd = BT848_RISC_JUMP;
387         if (btv->loop_irq) {
388                 cmd |= BT848_RISC_IRQ;
389                 cmd |= (btv->loop_irq  & 0x0f) << 16;
390                 cmd |= (~btv->loop_irq & 0x0f) << 20;
391         }
392         if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
393                 mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
394         } else {
395                 del_timer(&btv->timeout);
396         }
397         btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
398
399         btaor(capctl, ~0x0f, BT848_CAP_CTL);
400         if (capctl) {
401                 if (btv->dma_on)
402                         return;
403                 btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
404                 btor(3, BT848_GPIO_DMA_CTL);
405                 btv->dma_on = 1;
406         } else {
407                 if (!btv->dma_on)
408                         return;
409                 btand(~3, BT848_GPIO_DMA_CTL);
410                 btv->dma_on = 0;
411         }
412         return;
413 }
414
415 int
416 bttv_risc_init_main(struct bttv *btv)
417 {
418         int rc;
419
420         if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
421                 return rc;
422         dprintk("%d: risc main @ %08llx\n",
423                 btv->c.nr, (unsigned long long)btv->main.dma);
424
425         btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
426                                        BT848_FIFO_STATUS_VRE);
427         btv->main.cpu[1] = cpu_to_le32(0);
428         btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
429         btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
430
431         /* top field */
432         btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
433         btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
434         btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
435         btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
436
437         btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
438                                        BT848_FIFO_STATUS_VRO);
439         btv->main.cpu[9] = cpu_to_le32(0);
440
441         /* bottom field */
442         btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
443         btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
444         btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
445         btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
446
447         /* jump back to top field */
448         btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
449         btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
450
451         return 0;
452 }
453
454 int
455 bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
456                int irqflags)
457 {
458         unsigned long cmd;
459         unsigned long next = btv->main.dma + ((slot+2) << 2);
460
461         if (NULL == risc) {
462                 d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
463                 btv->main.cpu[slot+1] = cpu_to_le32(next);
464         } else {
465                 d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
466                          btv->c.nr, risc, slot,
467                          (unsigned long long)risc->dma, irqflags);
468                 cmd = BT848_RISC_JUMP;
469                 if (irqflags) {
470                         cmd |= BT848_RISC_IRQ;
471                         cmd |= (irqflags  & 0x0f) << 16;
472                         cmd |= (~irqflags & 0x0f) << 20;
473                 }
474                 risc->jmp[0] = cpu_to_le32(cmd);
475                 risc->jmp[1] = cpu_to_le32(next);
476                 btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
477         }
478         return 0;
479 }
480
481 void
482 bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
483 {
484         struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
485
486         videobuf_waiton(q, &buf->vb, 0, 0);
487         videobuf_dma_unmap(q->dev, dma);
488         videobuf_dma_free(dma);
489         btcx_riscmem_free(btv->c.pci,&buf->bottom);
490         btcx_riscmem_free(btv->c.pci,&buf->top);
491         buf->vb.state = VIDEOBUF_NEEDS_INIT;
492 }
493
494 int
495 bttv_buffer_activate_vbi(struct bttv *btv,
496                          struct bttv_buffer *vbi)
497 {
498         struct btcx_riscmem *top;
499         struct btcx_riscmem *bottom;
500         int top_irq_flags;
501         int bottom_irq_flags;
502
503         top = NULL;
504         bottom = NULL;
505         top_irq_flags = 0;
506         bottom_irq_flags = 0;
507
508         if (vbi) {
509                 unsigned int crop, vdelay;
510
511                 vbi->vb.state = VIDEOBUF_ACTIVE;
512                 list_del(&vbi->vb.queue);
513
514                 /* VDELAY is start of video, end of VBI capturing. */
515                 crop = btread(BT848_E_CROP);
516                 vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
517
518                 if (vbi->geo.vdelay > vdelay) {
519                         vdelay = vbi->geo.vdelay & 0xfe;
520                         crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
521
522                         btwrite(vdelay, BT848_E_VDELAY_LO);
523                         btwrite(crop,   BT848_E_CROP);
524                         btwrite(vdelay, BT848_O_VDELAY_LO);
525                         btwrite(crop,   BT848_O_CROP);
526                 }
527
528                 if (vbi->vbi_count[0] > 0) {
529                         top = &vbi->top;
530                         top_irq_flags = 4;
531                 }
532
533                 if (vbi->vbi_count[1] > 0) {
534                         top_irq_flags = 0;
535                         bottom = &vbi->bottom;
536                         bottom_irq_flags = 4;
537                 }
538         }
539
540         bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
541         bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
542
543         return 0;
544 }
545
546 int
547 bttv_buffer_activate_video(struct bttv *btv,
548                            struct bttv_buffer_set *set)
549 {
550         /* video capture */
551         if (NULL != set->top  &&  NULL != set->bottom) {
552                 if (set->top == set->bottom) {
553                         set->top->vb.state    = VIDEOBUF_ACTIVE;
554                         if (set->top->vb.queue.next)
555                                 list_del(&set->top->vb.queue);
556                 } else {
557                         set->top->vb.state    = VIDEOBUF_ACTIVE;
558                         set->bottom->vb.state = VIDEOBUF_ACTIVE;
559                         if (set->top->vb.queue.next)
560                                 list_del(&set->top->vb.queue);
561                         if (set->bottom->vb.queue.next)
562                                 list_del(&set->bottom->vb.queue);
563                 }
564                 bttv_apply_geo(btv, &set->top->geo, 1);
565                 bttv_apply_geo(btv, &set->bottom->geo,0);
566                 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
567                                set->top_irq);
568                 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
569                                set->frame_irq);
570                 btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
571                       ~0xff, BT848_COLOR_FMT);
572                 btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
573                       ~0x0f, BT848_COLOR_CTL);
574         } else if (NULL != set->top) {
575                 set->top->vb.state  = VIDEOBUF_ACTIVE;
576                 if (set->top->vb.queue.next)
577                         list_del(&set->top->vb.queue);
578                 bttv_apply_geo(btv, &set->top->geo,1);
579                 bttv_apply_geo(btv, &set->top->geo,0);
580                 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
581                                set->frame_irq);
582                 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,           0);
583                 btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
584                 btaor(set->top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
585         } else if (NULL != set->bottom) {
586                 set->bottom->vb.state = VIDEOBUF_ACTIVE;
587                 if (set->bottom->vb.queue.next)
588                         list_del(&set->bottom->vb.queue);
589                 bttv_apply_geo(btv, &set->bottom->geo,1);
590                 bttv_apply_geo(btv, &set->bottom->geo,0);
591                 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
592                 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
593                                set->frame_irq);
594                 btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
595                 btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
596         } else {
597                 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
598                 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
599         }
600         return 0;
601 }
602
603 /* ---------------------------------------------------------- */
604
605 /* calculate geometry, build risc code */
606 int
607 bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
608 {
609         const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
610         struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
611
612         dprintk("%d: buffer field: %s  format: 0x%08x  size: %dx%d\n",
613                 btv->c.nr, v4l2_field_names[buf->vb.field],
614                 buf->fmt->fourcc, buf->vb.width, buf->vb.height);
615
616         /* packed pixel modes */
617         if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
618                 int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
619                 int bpf = bpl * (buf->vb.height >> 1);
620
621                 bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
622                               V4L2_FIELD_HAS_BOTH(buf->vb.field),
623                               tvnorm,&buf->crop);
624
625                 switch (buf->vb.field) {
626                 case V4L2_FIELD_TOP:
627                         bttv_risc_packed(btv,&buf->top,dma->sglist,
628                                          /* offset */ 0,bpl,
629                                          /* padding */ 0,/* skip_lines */ 0,
630                                          buf->vb.height);
631                         break;
632                 case V4L2_FIELD_BOTTOM:
633                         bttv_risc_packed(btv,&buf->bottom,dma->sglist,
634                                          0,bpl,0,0,buf->vb.height);
635                         break;
636                 case V4L2_FIELD_INTERLACED:
637                         bttv_risc_packed(btv,&buf->top,dma->sglist,
638                                          0,bpl,bpl,0,buf->vb.height >> 1);
639                         bttv_risc_packed(btv,&buf->bottom,dma->sglist,
640                                          bpl,bpl,bpl,0,buf->vb.height >> 1);
641                         break;
642                 case V4L2_FIELD_SEQ_TB:
643                         bttv_risc_packed(btv,&buf->top,dma->sglist,
644                                          0,bpl,0,0,buf->vb.height >> 1);
645                         bttv_risc_packed(btv,&buf->bottom,dma->sglist,
646                                          bpf,bpl,0,0,buf->vb.height >> 1);
647                         break;
648                 default:
649                         BUG();
650                 }
651         }
652
653         /* planar modes */
654         if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
655                 int uoffset, voffset;
656                 int ypadding, cpadding, lines;
657
658                 /* calculate chroma offsets */
659                 uoffset = buf->vb.width * buf->vb.height;
660                 voffset = buf->vb.width * buf->vb.height;
661                 if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
662                         /* Y-Cr-Cb plane order */
663                         uoffset >>= buf->fmt->hshift;
664                         uoffset >>= buf->fmt->vshift;
665                         uoffset  += voffset;
666                 } else {
667                         /* Y-Cb-Cr plane order */
668                         voffset >>= buf->fmt->hshift;
669                         voffset >>= buf->fmt->vshift;
670                         voffset  += uoffset;
671                 }
672
673                 switch (buf->vb.field) {
674                 case V4L2_FIELD_TOP:
675                         bttv_calc_geo(btv,&buf->geo,buf->vb.width,
676                                       buf->vb.height,/* both_fields */ 0,
677                                       tvnorm,&buf->crop);
678                         bttv_risc_planar(btv, &buf->top, dma->sglist,
679                                          0,buf->vb.width,0,buf->vb.height,
680                                          uoffset,voffset,buf->fmt->hshift,
681                                          buf->fmt->vshift,0);
682                         break;
683                 case V4L2_FIELD_BOTTOM:
684                         bttv_calc_geo(btv,&buf->geo,buf->vb.width,
685                                       buf->vb.height,0,
686                                       tvnorm,&buf->crop);
687                         bttv_risc_planar(btv, &buf->bottom, dma->sglist,
688                                          0,buf->vb.width,0,buf->vb.height,
689                                          uoffset,voffset,buf->fmt->hshift,
690                                          buf->fmt->vshift,0);
691                         break;
692                 case V4L2_FIELD_INTERLACED:
693                         bttv_calc_geo(btv,&buf->geo,buf->vb.width,
694                                       buf->vb.height,1,
695                                       tvnorm,&buf->crop);
696                         lines    = buf->vb.height >> 1;
697                         ypadding = buf->vb.width;
698                         cpadding = buf->vb.width >> buf->fmt->hshift;
699                         bttv_risc_planar(btv,&buf->top,
700                                          dma->sglist,
701                                          0,buf->vb.width,ypadding,lines,
702                                          uoffset,voffset,
703                                          buf->fmt->hshift,
704                                          buf->fmt->vshift,
705                                          cpadding);
706                         bttv_risc_planar(btv,&buf->bottom,
707                                          dma->sglist,
708                                          ypadding,buf->vb.width,ypadding,lines,
709                                          uoffset+cpadding,
710                                          voffset+cpadding,
711                                          buf->fmt->hshift,
712                                          buf->fmt->vshift,
713                                          cpadding);
714                         break;
715                 case V4L2_FIELD_SEQ_TB:
716                         bttv_calc_geo(btv,&buf->geo,buf->vb.width,
717                                       buf->vb.height,1,
718                                       tvnorm,&buf->crop);
719                         lines    = buf->vb.height >> 1;
720                         ypadding = buf->vb.width;
721                         cpadding = buf->vb.width >> buf->fmt->hshift;
722                         bttv_risc_planar(btv,&buf->top,
723                                          dma->sglist,
724                                          0,buf->vb.width,0,lines,
725                                          uoffset >> 1,
726                                          voffset >> 1,
727                                          buf->fmt->hshift,
728                                          buf->fmt->vshift,
729                                          0);
730                         bttv_risc_planar(btv,&buf->bottom,
731                                          dma->sglist,
732                                          lines * ypadding,buf->vb.width,0,lines,
733                                          lines * ypadding + (uoffset >> 1),
734                                          lines * ypadding + (voffset >> 1),
735                                          buf->fmt->hshift,
736                                          buf->fmt->vshift,
737                                          0);
738                         break;
739                 default:
740                         BUG();
741                 }
742         }
743
744         /* raw data */
745         if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
746                 /* build risc code */
747                 buf->vb.field = V4L2_FIELD_SEQ_TB;
748                 bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
749                               1,tvnorm,&buf->crop);
750                 bttv_risc_packed(btv, &buf->top,  dma->sglist,
751                                  /* offset */ 0, RAW_BPL, /* padding */ 0,
752                                  /* skip_lines */ 0, RAW_LINES);
753                 bttv_risc_packed(btv, &buf->bottom, dma->sglist,
754                                  buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
755         }
756
757         /* copy format info */
758         buf->btformat = buf->fmt->btformat;
759         buf->btswap   = buf->fmt->btswap;
760         return 0;
761 }