powerpc/mm: Avoid calling arch_enter/leave_lazy_mmu() in set_ptes
[platform/kernel/linux-starfive.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                     (V4L2_FIELD_HAS_BOTH(btv->field) ||
73                      btv->field == V4L2_FIELD_ALTERNATE)))
74                         continue;
75                 while (offset && offset >= sg_dma_len(sg)) {
76                         offset -= sg_dma_len(sg);
77                         sg = sg_next(sg);
78                 }
79                 if (bpl <= sg_dma_len(sg)-offset) {
80                         /* fits into current chunk */
81                         *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
82                                             BT848_RISC_EOL|bpl);
83                         *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
84                         offset+=bpl;
85                 } else {
86                         /* scanline needs to be split */
87                         todo = bpl;
88                         *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
89                                             (sg_dma_len(sg)-offset));
90                         *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
91                         todo -= (sg_dma_len(sg)-offset);
92                         offset = 0;
93                         sg = sg_next(sg);
94                         while (todo > sg_dma_len(sg)) {
95                                 *(rp++)=cpu_to_le32(BT848_RISC_WRITE|
96                                                     sg_dma_len(sg));
97                                 *(rp++)=cpu_to_le32(sg_dma_address(sg));
98                                 todo -= sg_dma_len(sg);
99                                 sg = sg_next(sg);
100                         }
101                         *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
102                                             todo);
103                         *(rp++)=cpu_to_le32(sg_dma_address(sg));
104                         offset += todo;
105                 }
106                 offset += padding;
107         }
108
109         /* save pointer to jmp instruction address */
110         risc->jmp = rp;
111         WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
112         return 0;
113 }
114
115 static int
116 bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
117                  struct scatterlist *sglist,
118                  unsigned int yoffset,  unsigned int ybpl,
119                  unsigned int ypadding, unsigned int ylines,
120                  unsigned int uoffset,  unsigned int voffset,
121                  unsigned int hshift,   unsigned int vshift,
122                  unsigned int cpadding)
123 {
124         unsigned int instructions,line,todo,ylen,chroma;
125         __le32 *rp;
126         u32 ri;
127         struct scatterlist *ysg;
128         struct scatterlist *usg;
129         struct scatterlist *vsg;
130         int topfield = (0 == yoffset);
131         int rc;
132
133         /* estimate risc mem: worst case is one write per page border +
134            one write per scan line (5 dwords)
135            plus sync + jump (2 dwords) */
136         instructions  = ((3 + (ybpl + ypadding) * ylines * 2)
137                          / PAGE_SIZE) + ylines;
138         instructions += 2;
139         if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
140                 return rc;
141
142         /* sync instruction */
143         rp = risc->cpu;
144         *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
145         *(rp++) = cpu_to_le32(0);
146
147         /* scan lines */
148         ysg = sglist;
149         usg = sglist;
150         vsg = sglist;
151         for (line = 0; line < ylines; line++) {
152                 if ((btv->opt_vcr_hack) &&
153                     (line >= (ylines - VCR_HACK_LINES)))
154                         continue;
155                 switch (vshift) {
156                 case 0:
157                         chroma = 1;
158                         break;
159                 case 1:
160                         if (topfield)
161                                 chroma = ((line & 1) == 0);
162                         else
163                                 chroma = ((line & 1) == 1);
164                         break;
165                 case 2:
166                         if (topfield)
167                                 chroma = ((line & 3) == 0);
168                         else
169                                 chroma = ((line & 3) == 2);
170                         break;
171                 default:
172                         chroma = 0;
173                         break;
174                 }
175
176                 for (todo = ybpl; todo > 0; todo -= ylen) {
177                         /* go to next sg entry if needed */
178                         while (yoffset && yoffset >= sg_dma_len(ysg)) {
179                                 yoffset -= sg_dma_len(ysg);
180                                 ysg = sg_next(ysg);
181                         }
182
183                         /* calculate max number of bytes we can write */
184                         ylen = todo;
185                         if (yoffset + ylen > sg_dma_len(ysg))
186                                 ylen = sg_dma_len(ysg) - yoffset;
187                         if (chroma) {
188                                 while (uoffset && uoffset >= sg_dma_len(usg)) {
189                                         uoffset -= sg_dma_len(usg);
190                                         usg = sg_next(usg);
191                                 }
192                                 while (voffset && voffset >= sg_dma_len(vsg)) {
193                                         voffset -= sg_dma_len(vsg);
194                                         vsg = sg_next(vsg);
195                                 }
196
197                                 if (uoffset + (ylen>>hshift) > sg_dma_len(usg))
198                                         ylen = (sg_dma_len(usg) - uoffset) << hshift;
199                                 if (voffset + (ylen>>hshift) > sg_dma_len(vsg))
200                                         ylen = (sg_dma_len(vsg) - voffset) << hshift;
201                                 ri = BT848_RISC_WRITE123;
202                         } else {
203                                 ri = BT848_RISC_WRITE1S23;
204                         }
205                         if (ybpl == todo)
206                                 ri |= BT848_RISC_SOL;
207                         if (ylen == todo)
208                                 ri |= BT848_RISC_EOL;
209
210                         /* write risc instruction */
211                         *(rp++)=cpu_to_le32(ri | ylen);
212                         *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
213                                             (ylen >> hshift));
214                         *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
215                         yoffset += ylen;
216                         if (chroma) {
217                                 *(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);
218                                 uoffset += ylen >> hshift;
219                                 *(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);
220                                 voffset += ylen >> hshift;
221                         }
222                 }
223                 yoffset += ypadding;
224                 if (chroma) {
225                         uoffset += cpadding;
226                         voffset += cpadding;
227                 }
228         }
229
230         /* save pointer to jmp instruction address */
231         risc->jmp = rp;
232         WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
233         return 0;
234 }
235
236 /* ---------------------------------------------------------- */
237
238 static void
239 bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
240                   int width, int height, int interleaved,
241                   const struct bttv_tvnorm *tvnorm)
242 {
243         u32 xsf, sr;
244         int vdelay;
245
246         int swidth       = tvnorm->swidth;
247         int totalwidth   = tvnorm->totalwidth;
248         int scaledtwidth = tvnorm->scaledtwidth;
249
250         if (btv->input == btv->dig) {
251                 swidth       = 720;
252                 totalwidth   = 858;
253                 scaledtwidth = 858;
254         }
255
256         vdelay = tvnorm->vdelay;
257
258         xsf = (width*scaledtwidth)/swidth;
259         geo->hscale =  ((totalwidth*4096UL)/xsf-4096);
260         geo->hdelay =  tvnorm->hdelayx1;
261         geo->hdelay =  (geo->hdelay*width)/swidth;
262         geo->hdelay &= 0x3fe;
263         sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
264         geo->vscale =  (0x10000UL-sr) & 0x1fff;
265         geo->crop   =  ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
266                 ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
267         geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
268         geo->vdelay  =  vdelay;
269         geo->width   =  width;
270         geo->sheight =  tvnorm->sheight;
271         geo->vtotal  =  tvnorm->vtotal;
272
273         if (btv->opt_combfilter) {
274                 geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
275                 geo->comb = (width < 769) ? 1 : 0;
276         } else {
277                 geo->vtc  = 0;
278                 geo->comb = 0;
279         }
280 }
281
282 static void
283 bttv_calc_geo           (struct bttv *                  btv,
284                          struct bttv_geometry *         geo,
285                          unsigned int                   width,
286                          unsigned int                   height,
287                          int                            both_fields,
288                          const struct bttv_tvnorm *     tvnorm,
289                          const struct v4l2_rect *       crop)
290 {
291         unsigned int c_width;
292         unsigned int c_height;
293         u32 sr;
294
295         if ((crop->left == tvnorm->cropcap.defrect.left
296              && crop->top == tvnorm->cropcap.defrect.top
297              && crop->width == tvnorm->cropcap.defrect.width
298              && crop->height == tvnorm->cropcap.defrect.height
299              && width <= tvnorm->swidth /* see PAL-Nc et al */)
300             || btv->input == btv->dig) {
301                 bttv_calc_geo_old(btv, geo, width, height,
302                                   both_fields, tvnorm);
303                 return;
304         }
305
306         /* For bug compatibility the image size checks permit scale
307            factors > 16. See bttv_crop_calc_limits(). */
308         c_width = min((unsigned int) crop->width, width * 16);
309         c_height = min((unsigned int) crop->height, height * 16);
310
311         geo->width = width;
312         geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;
313         /* Even to store Cb first, odd for Cr. */
314         geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;
315
316         geo->sheight = c_height;
317         geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
318         sr = c_height >> !both_fields;
319         sr = (sr * 512U + (height >> 1)) / height - 512;
320         geo->vscale = (0x10000UL - sr) & 0x1fff;
321         geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;
322         geo->vtotal = tvnorm->vtotal;
323
324         geo->crop = (((geo->width   >> 8) & 0x03) |
325                      ((geo->hdelay  >> 6) & 0x0c) |
326                      ((geo->sheight >> 4) & 0x30) |
327                      ((geo->vdelay  >> 2) & 0xc0));
328
329         if (btv->opt_combfilter) {
330                 geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
331                 geo->comb = (width < 769) ? 1 : 0;
332         } else {
333                 geo->vtc  = 0;
334                 geo->comb = 0;
335         }
336 }
337
338 static void
339 bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
340 {
341         int off = odd ? 0x80 : 0x00;
342
343         if (geo->comb)
344                 btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
345         else
346                 btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
347
348         btwrite(geo->vtc,             BT848_E_VTC+off);
349         btwrite(geo->hscale >> 8,     BT848_E_HSCALE_HI+off);
350         btwrite(geo->hscale & 0xff,   BT848_E_HSCALE_LO+off);
351         btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
352         btwrite(geo->vscale & 0xff,   BT848_E_VSCALE_LO+off);
353         btwrite(geo->width & 0xff,    BT848_E_HACTIVE_LO+off);
354         btwrite(geo->hdelay & 0xff,   BT848_E_HDELAY_LO+off);
355         btwrite(geo->sheight & 0xff,  BT848_E_VACTIVE_LO+off);
356         btwrite(geo->vdelay & 0xff,   BT848_E_VDELAY_LO+off);
357         btwrite(geo->crop,            BT848_E_CROP+off);
358         btwrite(geo->vtotal>>8,       BT848_VTOTAL_HI);
359         btwrite(geo->vtotal & 0xff,   BT848_VTOTAL_LO);
360 }
361
362 /* ---------------------------------------------------------- */
363 /* risc group / risc main loop / dma management               */
364
365 static void bttv_set_risc_status(struct bttv *btv)
366 {
367         unsigned long cmd = BT848_RISC_JUMP;
368         if (btv->loop_irq) {
369                 cmd |= BT848_RISC_IRQ;
370                 cmd |= (btv->loop_irq  & 0x0f) << 16;
371                 cmd |= (~btv->loop_irq & 0x0f) << 20;
372         }
373         btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
374 }
375
376 static void bttv_set_irq_timer(struct bttv *btv)
377 {
378         if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi)
379                 mod_timer(&btv->timeout, jiffies + BTTV_TIMEOUT);
380         else
381                 del_timer(&btv->timeout);
382 }
383
384 static int bttv_set_capture_control(struct bttv *btv, int start_capture)
385 {
386         int capctl = 0;
387
388         if (btv->curr.top || btv->curr.bottom)
389                 capctl = BT848_CAP_CTL_CAPTURE_ODD |
390                          BT848_CAP_CTL_CAPTURE_EVEN;
391
392         if (btv->cvbi)
393                 capctl |= BT848_CAP_CTL_CAPTURE_VBI_ODD |
394                           BT848_CAP_CTL_CAPTURE_VBI_EVEN;
395
396         capctl |= start_capture;
397
398         btaor(capctl, ~0x0f, BT848_CAP_CTL);
399
400         return capctl;
401 }
402
403 static void bttv_start_dma(struct bttv *btv)
404 {
405         if (btv->dma_on)
406                 return;
407         btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
408         btor(BT848_GPIO_DMA_CTL_RISC_ENABLE | BT848_GPIO_DMA_CTL_FIFO_ENABLE,
409              BT848_GPIO_DMA_CTL);
410         btv->dma_on = 1;
411 }
412
413 static void bttv_stop_dma(struct bttv *btv)
414 {
415         if (!btv->dma_on)
416                 return;
417         btand(~(BT848_GPIO_DMA_CTL_RISC_ENABLE |
418                 BT848_GPIO_DMA_CTL_FIFO_ENABLE), BT848_GPIO_DMA_CTL);
419         btv->dma_on = 0;
420 }
421
422 void bttv_set_dma(struct bttv *btv, int start_capture)
423 {
424         int capctl = 0;
425
426         bttv_set_risc_status(btv);
427         bttv_set_irq_timer(btv);
428         capctl = bttv_set_capture_control(btv, start_capture);
429
430         if (capctl)
431                 bttv_start_dma(btv);
432         else
433                 bttv_stop_dma(btv);
434
435         d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
436                  btv->c.nr,capctl,btv->loop_irq,
437                  btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
438                  btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
439                  btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,
440                  btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
441 }
442
443 int
444 bttv_risc_init_main(struct bttv *btv)
445 {
446         int rc;
447
448         if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
449                 return rc;
450         dprintk("%d: risc main @ %08llx\n",
451                 btv->c.nr, (unsigned long long)btv->main.dma);
452
453         btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
454                                        BT848_FIFO_STATUS_VRE);
455         btv->main.cpu[1] = cpu_to_le32(0);
456         btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
457         btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
458
459         /* top field */
460         btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
461         btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
462         btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
463         btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
464
465         btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
466                                        BT848_FIFO_STATUS_VRO);
467         btv->main.cpu[9] = cpu_to_le32(0);
468
469         /* bottom field */
470         btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
471         btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
472         btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
473         btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
474
475         /* jump back to top field */
476         btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
477         btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
478
479         return 0;
480 }
481
482 int
483 bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
484                int irqflags)
485 {
486         unsigned long cmd;
487         unsigned long next = btv->main.dma + ((slot+2) << 2);
488
489         if (NULL == risc) {
490                 d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
491                 btv->main.cpu[slot+1] = cpu_to_le32(next);
492         } else {
493                 d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
494                          btv->c.nr, risc, slot,
495                          (unsigned long long)risc->dma, irqflags);
496                 cmd = BT848_RISC_JUMP;
497                 if (irqflags) {
498                         cmd |= BT848_RISC_IRQ;
499                         cmd |= (irqflags  & 0x0f) << 16;
500                         cmd |= (~irqflags & 0x0f) << 20;
501                 }
502                 risc->jmp[0] = cpu_to_le32(cmd);
503                 risc->jmp[1] = cpu_to_le32(next);
504                 btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
505         }
506         return 0;
507 }
508
509 int bttv_buffer_risc_vbi(struct bttv *btv, struct bttv_buffer *buf)
510 {
511         int r = 0;
512         unsigned int offset;
513         unsigned int bpl = 2044; /* max. vbipack */
514         unsigned int padding = VBI_BPL - bpl;
515         unsigned int skip_lines0 = 0;
516         unsigned int skip_lines1 = 0;
517         unsigned int min_vdelay = MIN_VDELAY;
518
519         const struct bttv_tvnorm *tvnorm = btv->vbi_fmt.tvnorm;
520         struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vbuf.vb2_buf, 0);
521         struct scatterlist *list = sgt->sgl;
522
523         if (btv->vbi_fmt.fmt.count[0] > 0)
524                 skip_lines0 = max(0, (btv->vbi_fmt.fmt.start[0] -
525                                         tvnorm->vbistart[0]));
526         if (btv->vbi_fmt.fmt.count[1] > 0)
527                 skip_lines1 = max(0, (btv->vbi_fmt.fmt.start[1] -
528                                         tvnorm->vbistart[1]));
529
530         if (btv->vbi_fmt.fmt.count[0] > 0) {
531                 r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, padding,
532                                      skip_lines0, btv->vbi_fmt.fmt.count[0]);
533                 if (r)
534                         return r;
535         }
536
537         if (btv->vbi_fmt.fmt.count[1] > 0) {
538                 offset = btv->vbi_fmt.fmt.count[0] * VBI_BPL;
539                 r = bttv_risc_packed(btv, &buf->bottom, list, offset, bpl,
540                                      padding, skip_lines1,
541                                      btv->vbi_fmt.fmt.count[1]);
542                 if (r)
543                         return r;
544         }
545
546         if (btv->vbi_fmt.end >= tvnorm->cropcap.bounds.top)
547                 min_vdelay += btv->vbi_fmt.end - tvnorm->cropcap.bounds.top;
548
549         /* For bttv_buffer_activate_vbi(). */
550         buf->geo.vdelay = min_vdelay;
551
552         return r;
553 }
554
555 int
556 bttv_buffer_activate_vbi(struct bttv *btv,
557                          struct bttv_buffer *vbi)
558 {
559         struct btcx_riscmem *top;
560         struct btcx_riscmem *bottom;
561         int top_irq_flags;
562         int bottom_irq_flags;
563
564         top = NULL;
565         bottom = NULL;
566         top_irq_flags = 0;
567         bottom_irq_flags = 0;
568
569         if (vbi) {
570                 unsigned int crop, vdelay;
571
572                 list_del(&vbi->list);
573
574                 /* VDELAY is start of video, end of VBI capturing. */
575                 crop = btread(BT848_E_CROP);
576                 vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
577
578                 if (vbi->geo.vdelay > vdelay) {
579                         vdelay = vbi->geo.vdelay & 0xfe;
580                         crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
581
582                         btwrite(vdelay, BT848_E_VDELAY_LO);
583                         btwrite(crop,   BT848_E_CROP);
584                         btwrite(vdelay, BT848_O_VDELAY_LO);
585                         btwrite(crop,   BT848_O_CROP);
586                 }
587
588                 if (btv->vbi_count[0] > 0) {
589                         top = &vbi->top;
590                         top_irq_flags = 4;
591                 }
592
593                 if (btv->vbi_count[1] > 0) {
594                         top_irq_flags = 0;
595                         bottom = &vbi->bottom;
596                         bottom_irq_flags = 4;
597                 }
598         }
599
600         bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
601         bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
602
603         return 0;
604 }
605
606 int
607 bttv_buffer_activate_video(struct bttv *btv,
608                            struct bttv_buffer_set *set)
609 {
610         /* video capture */
611         if (NULL != set->top  &&  NULL != set->bottom) {
612                 if (set->top == set->bottom) {
613                         if (set->top->list.next)
614                                 list_del(&set->top->list);
615                 } else {
616                         if (set->top->list.next)
617                                 list_del(&set->top->list);
618                         if (set->bottom->list.next)
619                                 list_del(&set->bottom->list);
620                 }
621                 bttv_apply_geo(btv, &set->top->geo, 1);
622                 bttv_apply_geo(btv, &set->bottom->geo,0);
623                 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
624                                set->top_irq);
625                 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
626                                set->frame_irq);
627                 btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
628                       ~0xff, BT848_COLOR_FMT);
629                 btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
630                       ~0x0f, BT848_COLOR_CTL);
631         } else if (NULL != set->top) {
632                 if (set->top->list.next)
633                         list_del(&set->top->list);
634                 bttv_apply_geo(btv, &set->top->geo,1);
635                 bttv_apply_geo(btv, &set->top->geo,0);
636                 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
637                                set->frame_irq);
638                 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,           0);
639                 btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
640                 btaor(set->top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
641         } else if (NULL != set->bottom) {
642                 if (set->bottom->list.next)
643                         list_del(&set->bottom->list);
644                 bttv_apply_geo(btv, &set->bottom->geo,1);
645                 bttv_apply_geo(btv, &set->bottom->geo,0);
646                 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
647                 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
648                                set->frame_irq);
649                 btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
650                 btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
651         } else {
652                 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
653                 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
654         }
655         return 0;
656 }
657
658 /* ---------------------------------------------------------- */
659
660 /* calculate geometry, build risc code */
661 int
662 bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
663 {
664         int r = 0;
665         const struct bttv_tvnorm *tvnorm = bttv_tvnorms + btv->tvnorm;
666         struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vbuf.vb2_buf, 0);
667         struct scatterlist *list = sgt->sgl;
668         unsigned long size = (btv->fmt->depth * btv->width * btv->height) >> 3;
669
670         /* packed pixel modes */
671         if (btv->fmt->flags & FORMAT_FLAGS_PACKED) {
672                 int bpl = (btv->fmt->depth >> 3) * btv->width;
673                 int bpf = bpl * (btv->height >> 1);
674
675                 bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
676                               V4L2_FIELD_HAS_BOTH(buf->vbuf.field), tvnorm,
677                               &btv->crop[!!btv->do_crop].rect);
678                 switch (buf->vbuf.field) {
679                 case V4L2_FIELD_TOP:
680                         r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,
681                                              0, btv->height);
682                         break;
683                 case V4L2_FIELD_BOTTOM:
684                         r = bttv_risc_packed(btv, &buf->bottom, list, 0, bpl,
685                                              0, 0, btv->height);
686                         break;
687                 case V4L2_FIELD_INTERLACED:
688                         r = bttv_risc_packed(btv, &buf->top, list, 0, bpl,
689                                              bpl, 0, btv->height >> 1);
690                         r = bttv_risc_packed(btv, &buf->bottom, list, bpl,
691                                              bpl, bpl, 0, btv->height >> 1);
692                         break;
693                 case V4L2_FIELD_SEQ_TB:
694                         r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,
695                                              0, btv->height >> 1);
696                         r = bttv_risc_packed(btv, &buf->bottom, list, bpf,
697                                              bpl, 0, 0, btv->height >> 1);
698                         break;
699                 default:
700                         WARN_ON(1);
701                         return -EINVAL;
702                 }
703         }
704         /* planar modes */
705         if (btv->fmt->flags & FORMAT_FLAGS_PLANAR) {
706                 int uoffset, voffset;
707                 int ypadding, cpadding, lines;
708
709                 /* calculate chroma offsets */
710                 uoffset = btv->width * btv->height;
711                 voffset = btv->width * btv->height;
712                 if (btv->fmt->flags & FORMAT_FLAGS_CrCb) {
713                         /* Y-Cr-Cb plane order */
714                         uoffset >>= btv->fmt->hshift;
715                         uoffset >>= btv->fmt->vshift;
716                         uoffset  += voffset;
717                 } else {
718                         /* Y-Cb-Cr plane order */
719                         voffset >>= btv->fmt->hshift;
720                         voffset >>= btv->fmt->vshift;
721                         voffset  += uoffset;
722                 }
723                 switch (buf->vbuf.field) {
724                 case V4L2_FIELD_TOP:
725                         bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
726                                       0, tvnorm,
727                                       &btv->crop[!!btv->do_crop].rect);
728                         r = bttv_risc_planar(btv, &buf->top, list, 0,
729                                              btv->width, 0, btv->height,
730                                              uoffset, voffset,
731                                              btv->fmt->hshift,
732                                              btv->fmt->vshift, 0);
733                         break;
734                 case V4L2_FIELD_BOTTOM:
735                         bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
736                                       0, tvnorm,
737                                       &btv->crop[!!btv->do_crop].rect);
738                         r = bttv_risc_planar(btv, &buf->bottom, list, 0,
739                                              btv->width, 0, btv->height,
740                                              uoffset, voffset,
741                                              btv->fmt->hshift,
742                                              btv->fmt->vshift, 0);
743                         break;
744                 case V4L2_FIELD_INTERLACED:
745                         bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
746                                       1, tvnorm,
747                                       &btv->crop[!!btv->do_crop].rect);
748                         lines = btv->height >> 1;
749                         ypadding = btv->width;
750                         cpadding = btv->width >> btv->fmt->hshift;
751                         r = bttv_risc_planar(btv, &buf->top, list, 0,
752                                              btv->width, ypadding, lines,
753                                              uoffset, voffset,
754                                              btv->fmt->hshift,
755                                              btv->fmt->vshift, cpadding);
756
757                         r = bttv_risc_planar(btv, &buf->bottom, list,
758                                              ypadding, btv->width, ypadding,
759                                              lines,  uoffset + cpadding,
760                                              voffset + cpadding,
761                                              btv->fmt->hshift,
762                                              btv->fmt->vshift, cpadding);
763                         break;
764                 case V4L2_FIELD_SEQ_TB:
765                         bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
766                                       1, tvnorm,
767                                       &btv->crop[!!btv->do_crop].rect);
768                         lines = btv->height >> 1;
769                         ypadding = btv->width;
770                         cpadding = btv->width >> btv->fmt->hshift;
771                         r = bttv_risc_planar(btv, &buf->top, list, 0,
772                                              btv->width, 0, lines,
773                                              uoffset >> 1, voffset >> 1,
774                                              btv->fmt->hshift,
775                                              btv->fmt->vshift, 0);
776                         r = bttv_risc_planar(btv, &buf->bottom, list,
777                                              lines * ypadding,
778                                              btv->width, 0, lines,
779                                              lines * ypadding + (uoffset >> 1),
780                                              lines * ypadding + (voffset >> 1),
781                                              btv->fmt->hshift,
782                                              btv->fmt->vshift, 0);
783                         break;
784                 default:
785                         WARN_ON(1);
786                         return -EINVAL;
787                 }
788         }
789         /* raw data */
790         if (btv->fmt->flags & FORMAT_FLAGS_RAW) {
791                 /* build risc code */
792                 buf->vbuf.field = V4L2_FIELD_SEQ_TB;
793                 bttv_calc_geo(btv, &buf->geo, tvnorm->swidth, tvnorm->sheight,
794                               1, tvnorm, &btv->crop[!!btv->do_crop].rect);
795                 r = bttv_risc_packed(btv, &buf->top, list, 0, RAW_BPL, 0, 0,
796                                      RAW_LINES);
797                 r = bttv_risc_packed(btv, &buf->bottom, list, size / 2,
798                                      RAW_BPL, 0, 0, RAW_LINES);
799         }
800
801         /* copy format info */
802         buf->btformat = btv->fmt->btformat;
803         buf->btswap   = btv->fmt->btswap;
804
805         return r;
806 }