ASoC: Merge up v6.6-rc7
[linux-block.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 ((line >= (store_lines - VCR_HACK_LINES)) &&
71                     btv->opt_vcr_hack)
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         WARN_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         WARN_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 static void bttv_set_risc_status(struct bttv *btv)
364 {
365         unsigned long cmd = BT848_RISC_JUMP;
366         if (btv->loop_irq) {
367                 cmd |= BT848_RISC_IRQ;
368                 cmd |= (btv->loop_irq  & 0x0f) << 16;
369                 cmd |= (~btv->loop_irq & 0x0f) << 20;
370         }
371         btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
372 }
373
374 static void bttv_set_irq_timer(struct bttv *btv)
375 {
376         if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi)
377                 mod_timer(&btv->timeout, jiffies + BTTV_TIMEOUT);
378         else
379                 del_timer(&btv->timeout);
380 }
381
382 static int bttv_set_capture_control(struct bttv *btv, int start_capture)
383 {
384         int capctl = 0;
385
386         if (btv->curr.top || btv->curr.bottom)
387                 capctl = BT848_CAP_CTL_CAPTURE_ODD |
388                          BT848_CAP_CTL_CAPTURE_EVEN;
389
390         if (btv->cvbi)
391                 capctl |= BT848_CAP_CTL_CAPTURE_VBI_ODD |
392                           BT848_CAP_CTL_CAPTURE_VBI_EVEN;
393
394         capctl |= start_capture;
395
396         btaor(capctl, ~0x0f, BT848_CAP_CTL);
397
398         return capctl;
399 }
400
401 static void bttv_start_dma(struct bttv *btv)
402 {
403         if (btv->dma_on)
404                 return;
405         btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
406         btor(BT848_GPIO_DMA_CTL_RISC_ENABLE | BT848_GPIO_DMA_CTL_FIFO_ENABLE,
407              BT848_GPIO_DMA_CTL);
408         btv->dma_on = 1;
409 }
410
411 static void bttv_stop_dma(struct bttv *btv)
412 {
413         if (!btv->dma_on)
414                 return;
415         btand(~(BT848_GPIO_DMA_CTL_RISC_ENABLE |
416                 BT848_GPIO_DMA_CTL_FIFO_ENABLE), BT848_GPIO_DMA_CTL);
417         btv->dma_on = 0;
418 }
419
420 void bttv_set_dma(struct bttv *btv, int start_capture)
421 {
422         int capctl = 0;
423
424         bttv_set_risc_status(btv);
425         bttv_set_irq_timer(btv);
426         capctl = bttv_set_capture_control(btv, start_capture);
427
428         if (capctl)
429                 bttv_start_dma(btv);
430         else
431                 bttv_stop_dma(btv);
432
433         d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
434                  btv->c.nr,capctl,btv->loop_irq,
435                  btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
436                  btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
437                  btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,
438                  btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
439 }
440
441 int
442 bttv_risc_init_main(struct bttv *btv)
443 {
444         int rc;
445
446         if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
447                 return rc;
448         dprintk("%d: risc main @ %08llx\n",
449                 btv->c.nr, (unsigned long long)btv->main.dma);
450
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));
456
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));
462
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);
466
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));
472
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));
476
477         return 0;
478 }
479
480 int
481 bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
482                int irqflags)
483 {
484         unsigned long cmd;
485         unsigned long next = btv->main.dma + ((slot+2) << 2);
486
487         if (NULL == risc) {
488                 d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
489                 btv->main.cpu[slot+1] = cpu_to_le32(next);
490         } else {
491                 d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
492                          btv->c.nr, risc, slot,
493                          (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;
499                 }
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);
503         }
504         return 0;
505 }
506
507 int bttv_buffer_risc_vbi(struct bttv *btv, struct bttv_buffer *buf)
508 {
509         int r = 0;
510         unsigned int offset;
511         unsigned int bpl = 2044; /* max. vbipack */
512         unsigned int padding = VBI_BPL - bpl;
513         unsigned int skip_lines0 = 0;
514         unsigned int skip_lines1 = 0;
515         unsigned int min_vdelay = MIN_VDELAY;
516
517         const struct bttv_tvnorm *tvnorm = btv->vbi_fmt.tvnorm;
518         struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vbuf.vb2_buf, 0);
519         struct scatterlist *list = sgt->sgl;
520
521         if (btv->vbi_fmt.fmt.count[0] > 0)
522                 skip_lines0 = max(0, (btv->vbi_fmt.fmt.start[0] -
523                                         tvnorm->vbistart[0]));
524         if (btv->vbi_fmt.fmt.count[1] > 0)
525                 skip_lines1 = max(0, (btv->vbi_fmt.fmt.start[1] -
526                                         tvnorm->vbistart[1]));
527
528         if (btv->vbi_fmt.fmt.count[0] > 0) {
529                 r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, padding,
530                                      skip_lines0, btv->vbi_fmt.fmt.count[0]);
531                 if (r)
532                         return r;
533         }
534
535         if (btv->vbi_fmt.fmt.count[1] > 0) {
536                 offset = btv->vbi_fmt.fmt.count[0] * VBI_BPL;
537                 r = bttv_risc_packed(btv, &buf->bottom, list, offset, bpl,
538                                      padding, skip_lines1,
539                                      btv->vbi_fmt.fmt.count[1]);
540                 if (r)
541                         return r;
542         }
543
544         if (btv->vbi_fmt.end >= tvnorm->cropcap.bounds.top)
545                 min_vdelay += btv->vbi_fmt.end - tvnorm->cropcap.bounds.top;
546
547         /* For bttv_buffer_activate_vbi(). */
548         buf->geo.vdelay = min_vdelay;
549
550         return r;
551 }
552
553 int
554 bttv_buffer_activate_vbi(struct bttv *btv,
555                          struct bttv_buffer *vbi)
556 {
557         struct btcx_riscmem *top;
558         struct btcx_riscmem *bottom;
559         int top_irq_flags;
560         int bottom_irq_flags;
561
562         top = NULL;
563         bottom = NULL;
564         top_irq_flags = 0;
565         bottom_irq_flags = 0;
566
567         if (vbi) {
568                 unsigned int crop, vdelay;
569
570                 list_del(&vbi->list);
571
572                 /* VDELAY is start of video, end of VBI capturing. */
573                 crop = btread(BT848_E_CROP);
574                 vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
575
576                 if (vbi->geo.vdelay > vdelay) {
577                         vdelay = vbi->geo.vdelay & 0xfe;
578                         crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
579
580                         btwrite(vdelay, BT848_E_VDELAY_LO);
581                         btwrite(crop,   BT848_E_CROP);
582                         btwrite(vdelay, BT848_O_VDELAY_LO);
583                         btwrite(crop,   BT848_O_CROP);
584                 }
585
586                 if (btv->vbi_count[0] > 0) {
587                         top = &vbi->top;
588                         top_irq_flags = 4;
589                 }
590
591                 if (btv->vbi_count[1] > 0) {
592                         top_irq_flags = 0;
593                         bottom = &vbi->bottom;
594                         bottom_irq_flags = 4;
595                 }
596         }
597
598         bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
599         bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
600
601         return 0;
602 }
603
604 int
605 bttv_buffer_activate_video(struct bttv *btv,
606                            struct bttv_buffer_set *set)
607 {
608         /* video capture */
609         if (NULL != set->top  &&  NULL != set->bottom) {
610                 if (set->top == set->bottom) {
611                         if (set->top->list.next)
612                                 list_del(&set->top->list);
613                 } else {
614                         if (set->top->list.next)
615                                 list_del(&set->top->list);
616                         if (set->bottom->list.next)
617                                 list_del(&set->bottom->list);
618                 }
619                 bttv_apply_geo(btv, &set->top->geo, 1);
620                 bttv_apply_geo(btv, &set->bottom->geo,0);
621                 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
622                                set->top_irq);
623                 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
624                                set->frame_irq);
625                 btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
626                       ~0xff, BT848_COLOR_FMT);
627                 btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
628                       ~0x0f, BT848_COLOR_CTL);
629         } else if (NULL != set->top) {
630                 if (set->top->list.next)
631                         list_del(&set->top->list);
632                 bttv_apply_geo(btv, &set->top->geo,1);
633                 bttv_apply_geo(btv, &set->top->geo,0);
634                 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
635                                set->frame_irq);
636                 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,           0);
637                 btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
638                 btaor(set->top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
639         } else if (NULL != set->bottom) {
640                 if (set->bottom->list.next)
641                         list_del(&set->bottom->list);
642                 bttv_apply_geo(btv, &set->bottom->geo,1);
643                 bttv_apply_geo(btv, &set->bottom->geo,0);
644                 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
645                 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
646                                set->frame_irq);
647                 btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
648                 btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
649         } else {
650                 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
651                 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
652         }
653         return 0;
654 }
655
656 /* ---------------------------------------------------------- */
657
658 /* calculate geometry, build risc code */
659 int
660 bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
661 {
662         int r = 0;
663         const struct bttv_tvnorm *tvnorm = bttv_tvnorms + btv->tvnorm;
664         struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vbuf.vb2_buf, 0);
665         struct scatterlist *list = sgt->sgl;
666         unsigned long size = (btv->fmt->depth * btv->width * btv->height) >> 3;
667
668         /* packed pixel modes */
669         if (btv->fmt->flags & FORMAT_FLAGS_PACKED) {
670                 int bpl = (btv->fmt->depth >> 3) * btv->width;
671                 int bpf = bpl * (btv->height >> 1);
672
673                 bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
674                               V4L2_FIELD_HAS_BOTH(buf->vbuf.field), tvnorm,
675                               &btv->crop[!!btv->do_crop].rect);
676                 switch (buf->vbuf.field) {
677                 case V4L2_FIELD_TOP:
678                         r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,
679                                              0, btv->height);
680                         break;
681                 case V4L2_FIELD_BOTTOM:
682                         r = bttv_risc_packed(btv, &buf->bottom, list, 0, bpl,
683                                              0, 0, btv->height);
684                         break;
685                 case V4L2_FIELD_INTERLACED:
686                         r = bttv_risc_packed(btv, &buf->top, list, 0, bpl,
687                                              bpl, 0, btv->height >> 1);
688                         r = bttv_risc_packed(btv, &buf->bottom, list, bpl,
689                                              bpl, bpl, 0, btv->height >> 1);
690                         break;
691                 case V4L2_FIELD_SEQ_TB:
692                         r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,
693                                              0, btv->height >> 1);
694                         r = bttv_risc_packed(btv, &buf->bottom, list, bpf,
695                                              bpl, 0, 0, btv->height >> 1);
696                         break;
697                 default:
698                         WARN_ON(1);
699                         return -EINVAL;
700                 }
701         }
702         /* planar modes */
703         if (btv->fmt->flags & FORMAT_FLAGS_PLANAR) {
704                 int uoffset, voffset;
705                 int ypadding, cpadding, lines;
706
707                 /* calculate chroma offsets */
708                 uoffset = btv->width * btv->height;
709                 voffset = btv->width * btv->height;
710                 if (btv->fmt->flags & FORMAT_FLAGS_CrCb) {
711                         /* Y-Cr-Cb plane order */
712                         uoffset >>= btv->fmt->hshift;
713                         uoffset >>= btv->fmt->vshift;
714                         uoffset  += voffset;
715                 } else {
716                         /* Y-Cb-Cr plane order */
717                         voffset >>= btv->fmt->hshift;
718                         voffset >>= btv->fmt->vshift;
719                         voffset  += uoffset;
720                 }
721                 switch (buf->vbuf.field) {
722                 case V4L2_FIELD_TOP:
723                         bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
724                                       0, tvnorm,
725                                       &btv->crop[!!btv->do_crop].rect);
726                         r = bttv_risc_planar(btv, &buf->top, list, 0,
727                                              btv->width, 0, btv->height,
728                                              uoffset, voffset,
729                                              btv->fmt->hshift,
730                                              btv->fmt->vshift, 0);
731                         break;
732                 case V4L2_FIELD_BOTTOM:
733                         bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
734                                       0, tvnorm,
735                                       &btv->crop[!!btv->do_crop].rect);
736                         r = bttv_risc_planar(btv, &buf->bottom, list, 0,
737                                              btv->width, 0, btv->height,
738                                              uoffset, voffset,
739                                              btv->fmt->hshift,
740                                              btv->fmt->vshift, 0);
741                         break;
742                 case V4L2_FIELD_INTERLACED:
743                         bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
744                                       1, tvnorm,
745                                       &btv->crop[!!btv->do_crop].rect);
746                         lines = btv->height >> 1;
747                         ypadding = btv->width;
748                         cpadding = btv->width >> btv->fmt->hshift;
749                         r = bttv_risc_planar(btv, &buf->top, list, 0,
750                                              btv->width, ypadding, lines,
751                                              uoffset, voffset,
752                                              btv->fmt->hshift,
753                                              btv->fmt->vshift, cpadding);
754
755                         r = bttv_risc_planar(btv, &buf->bottom, list,
756                                              ypadding, btv->width, ypadding,
757                                              lines,  uoffset + cpadding,
758                                              voffset + cpadding,
759                                              btv->fmt->hshift,
760                                              btv->fmt->vshift, cpadding);
761                         break;
762                 case V4L2_FIELD_SEQ_TB:
763                         bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
764                                       1, tvnorm,
765                                       &btv->crop[!!btv->do_crop].rect);
766                         lines = btv->height >> 1;
767                         ypadding = btv->width;
768                         cpadding = btv->width >> btv->fmt->hshift;
769                         r = bttv_risc_planar(btv, &buf->top, list, 0,
770                                              btv->width, 0, lines,
771                                              uoffset >> 1, voffset >> 1,
772                                              btv->fmt->hshift,
773                                              btv->fmt->vshift, 0);
774                         r = bttv_risc_planar(btv, &buf->bottom, list,
775                                              lines * ypadding,
776                                              btv->width, 0, lines,
777                                              lines * ypadding + (uoffset >> 1),
778                                              lines * ypadding + (voffset >> 1),
779                                              btv->fmt->hshift,
780                                              btv->fmt->vshift, 0);
781                         break;
782                 default:
783                         WARN_ON(1);
784                         return -EINVAL;
785                 }
786         }
787         /* raw data */
788         if (btv->fmt->flags & FORMAT_FLAGS_RAW) {
789                 /* build risc code */
790                 buf->vbuf.field = V4L2_FIELD_SEQ_TB;
791                 bttv_calc_geo(btv, &buf->geo, tvnorm->swidth, tvnorm->sheight,
792                               1, tvnorm, &btv->crop[!!btv->do_crop].rect);
793                 r = bttv_risc_packed(btv, &buf->top, list, 0, RAW_BPL, 0, 0,
794                                      RAW_LINES);
795                 r = bttv_risc_packed(btv, &buf->bottom, list, size / 2,
796                                      RAW_BPL, 0, 0, RAW_LINES);
797         }
798
799         /* copy format info */
800         buf->btformat = btv->fmt->btformat;
801         buf->btswap   = btv->fmt->btswap;
802
803         return r;
804 }