1 // SPDX-License-Identifier: GPL-2.0-or-later
4 bttv-risc.c -- interfaces to other kernel modules
6 bttv risc code handling
10 (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org>
15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
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>
25 #include <media/v4l2-ioctl.h>
29 #define VCR_HACK_LINES 4
31 /* ---------------------------------------------------------- */
32 /* risc code generators */
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)
41 u32 instructions,line,todo;
42 struct scatterlist *sg;
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)
57 /* sync instruction */
59 *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
60 *(rp++) = cpu_to_le32(0);
62 while (skip_lines-- > 0) {
63 *(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |
64 BT848_RISC_EOL | bpl);
69 for (line = 0; line < store_lines; line++) {
70 if ((line >= (store_lines - VCR_HACK_LINES)) &&
72 (V4L2_FIELD_HAS_BOTH(btv->field) ||
73 btv->field == V4L2_FIELD_ALTERNATE)))
75 while (offset && offset >= sg_dma_len(sg)) {
76 offset -= sg_dma_len(sg);
79 if (bpl <= sg_dma_len(sg)-offset) {
80 /* fits into current chunk */
81 *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
83 *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
86 /* scanline needs to be split */
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);
94 while (todo > sg_dma_len(sg)) {
95 *(rp++)=cpu_to_le32(BT848_RISC_WRITE|
97 *(rp++)=cpu_to_le32(sg_dma_address(sg));
98 todo -= sg_dma_len(sg);
101 *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
103 *(rp++)=cpu_to_le32(sg_dma_address(sg));
109 /* save pointer to jmp instruction address */
111 WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
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)
124 unsigned int instructions,line,todo,ylen,chroma;
127 struct scatterlist *ysg;
128 struct scatterlist *usg;
129 struct scatterlist *vsg;
130 int topfield = (0 == yoffset);
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;
139 if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
142 /* sync instruction */
144 *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
145 *(rp++) = cpu_to_le32(0);
151 for (line = 0; line < ylines; line++) {
152 if ((btv->opt_vcr_hack) &&
153 (line >= (ylines - VCR_HACK_LINES)))
161 chroma = ((line & 1) == 0);
163 chroma = ((line & 1) == 1);
167 chroma = ((line & 3) == 0);
169 chroma = ((line & 3) == 2);
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);
183 /* calculate max number of bytes we can write */
185 if (yoffset + ylen > sg_dma_len(ysg))
186 ylen = sg_dma_len(ysg) - yoffset;
188 while (uoffset && uoffset >= sg_dma_len(usg)) {
189 uoffset -= sg_dma_len(usg);
192 while (voffset && voffset >= sg_dma_len(vsg)) {
193 voffset -= sg_dma_len(vsg);
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;
203 ri = BT848_RISC_WRITE1S23;
206 ri |= BT848_RISC_SOL;
208 ri |= BT848_RISC_EOL;
210 /* write risc instruction */
211 *(rp++)=cpu_to_le32(ri | ylen);
212 *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
214 *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
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;
230 /* save pointer to jmp instruction address */
232 WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
236 /* ---------------------------------------------------------- */
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)
246 int swidth = tvnorm->swidth;
247 int totalwidth = tvnorm->totalwidth;
248 int scaledtwidth = tvnorm->scaledtwidth;
250 if (btv->input == btv->dig) {
256 vdelay = tvnorm->vdelay;
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;
270 geo->sheight = tvnorm->sheight;
271 geo->vtotal = tvnorm->vtotal;
273 if (btv->opt_combfilter) {
274 geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
275 geo->comb = (width < 769) ? 1 : 0;
283 bttv_calc_geo (struct bttv * btv,
284 struct bttv_geometry * geo,
288 const struct bttv_tvnorm * tvnorm,
289 const struct v4l2_rect * crop)
291 unsigned int c_width;
292 unsigned int c_height;
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);
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);
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;
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;
324 geo->crop = (((geo->width >> 8) & 0x03) |
325 ((geo->hdelay >> 6) & 0x0c) |
326 ((geo->sheight >> 4) & 0x30) |
327 ((geo->vdelay >> 2) & 0xc0));
329 if (btv->opt_combfilter) {
330 geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
331 geo->comb = (width < 769) ? 1 : 0;
339 bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
341 int off = odd ? 0x80 : 0x00;
344 btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
346 btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
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);
362 /* ---------------------------------------------------------- */
363 /* risc group / risc main loop / dma management */
365 static void bttv_set_risc_status(struct bttv *btv)
367 unsigned long cmd = BT848_RISC_JUMP;
369 cmd |= BT848_RISC_IRQ;
370 cmd |= (btv->loop_irq & 0x0f) << 16;
371 cmd |= (~btv->loop_irq & 0x0f) << 20;
373 btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
376 static void bttv_set_irq_timer(struct bttv *btv)
378 if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi)
379 mod_timer(&btv->timeout, jiffies + BTTV_TIMEOUT);
381 del_timer(&btv->timeout);
384 static int bttv_set_capture_control(struct bttv *btv, int start_capture)
388 if (btv->curr.top || btv->curr.bottom)
389 capctl = BT848_CAP_CTL_CAPTURE_ODD |
390 BT848_CAP_CTL_CAPTURE_EVEN;
393 capctl |= BT848_CAP_CTL_CAPTURE_VBI_ODD |
394 BT848_CAP_CTL_CAPTURE_VBI_EVEN;
396 capctl |= start_capture;
398 btaor(capctl, ~0x0f, BT848_CAP_CTL);
403 static void bttv_start_dma(struct bttv *btv)
407 btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
408 btor(BT848_GPIO_DMA_CTL_RISC_ENABLE | BT848_GPIO_DMA_CTL_FIFO_ENABLE,
413 static void bttv_stop_dma(struct bttv *btv)
417 btand(~(BT848_GPIO_DMA_CTL_RISC_ENABLE |
418 BT848_GPIO_DMA_CTL_FIFO_ENABLE), BT848_GPIO_DMA_CTL);
422 void bttv_set_dma(struct bttv *btv, int start_capture)
426 bttv_set_risc_status(btv);
427 bttv_set_irq_timer(btv);
428 capctl = bttv_set_capture_control(btv, start_capture);
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);
444 bttv_risc_init_main(struct bttv *btv)
448 if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
450 dprintk("%d: risc main @ %08llx\n",
451 btv->c.nr, (unsigned long long)btv->main.dma);
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));
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));
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);
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));
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));
483 bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
487 unsigned long next = btv->main.dma + ((slot+2) << 2);
490 d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
491 btv->main.cpu[slot+1] = cpu_to_le32(next);
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;
498 cmd |= BT848_RISC_IRQ;
499 cmd |= (irqflags & 0x0f) << 16;
500 cmd |= (~irqflags & 0x0f) << 20;
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);
509 int bttv_buffer_risc_vbi(struct bttv *btv, struct bttv_buffer *buf)
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;
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;
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]));
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]);
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]);
546 if (btv->vbi_fmt.end >= tvnorm->cropcap.bounds.top)
547 min_vdelay += btv->vbi_fmt.end - tvnorm->cropcap.bounds.top;
549 /* For bttv_buffer_activate_vbi(). */
550 buf->geo.vdelay = min_vdelay;
556 bttv_buffer_activate_vbi(struct bttv *btv,
557 struct bttv_buffer *vbi)
559 struct btcx_riscmem *top;
560 struct btcx_riscmem *bottom;
562 int bottom_irq_flags;
567 bottom_irq_flags = 0;
570 unsigned int crop, vdelay;
572 list_del(&vbi->list);
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);
578 if (vbi->geo.vdelay > vdelay) {
579 vdelay = vbi->geo.vdelay & 0xfe;
580 crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
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);
588 if (btv->vbi_count[0] > 0) {
593 if (btv->vbi_count[1] > 0) {
595 bottom = &vbi->bottom;
596 bottom_irq_flags = 4;
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);
607 bttv_buffer_activate_video(struct bttv *btv,
608 struct bttv_buffer_set *set)
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);
616 if (set->top->list.next)
617 list_del(&set->top->list);
618 if (set->bottom->list.next)
619 list_del(&set->bottom->list);
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,
625 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
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,
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,
649 btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
650 btaor(set->bottom->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
652 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
653 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
658 /* ---------------------------------------------------------- */
660 /* calculate geometry, build risc code */
662 bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
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;
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);
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) {
680 r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,
683 case V4L2_FIELD_BOTTOM:
684 r = bttv_risc_packed(btv, &buf->bottom, list, 0, bpl,
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);
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);
705 if (btv->fmt->flags & FORMAT_FLAGS_PLANAR) {
706 int uoffset, voffset;
707 int ypadding, cpadding, lines;
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;
718 /* Y-Cb-Cr plane order */
719 voffset >>= btv->fmt->hshift;
720 voffset >>= btv->fmt->vshift;
723 switch (buf->vbuf.field) {
725 bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
727 &btv->crop[!!btv->do_crop].rect);
728 r = bttv_risc_planar(btv, &buf->top, list, 0,
729 btv->width, 0, btv->height,
732 btv->fmt->vshift, 0);
734 case V4L2_FIELD_BOTTOM:
735 bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
737 &btv->crop[!!btv->do_crop].rect);
738 r = bttv_risc_planar(btv, &buf->bottom, list, 0,
739 btv->width, 0, btv->height,
742 btv->fmt->vshift, 0);
744 case V4L2_FIELD_INTERLACED:
745 bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
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,
755 btv->fmt->vshift, cpadding);
757 r = bttv_risc_planar(btv, &buf->bottom, list,
758 ypadding, btv->width, ypadding,
759 lines, uoffset + cpadding,
762 btv->fmt->vshift, cpadding);
764 case V4L2_FIELD_SEQ_TB:
765 bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
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,
775 btv->fmt->vshift, 0);
776 r = bttv_risc_planar(btv, &buf->bottom, list,
778 btv->width, 0, lines,
779 lines * ypadding + (uoffset >> 1),
780 lines * ypadding + (voffset >> 1),
782 btv->fmt->vshift, 0);
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,
797 r = bttv_risc_packed(btv, &buf->bottom, list, size / 2,
798 RAW_BPL, 0, 0, RAW_LINES);
801 /* copy format info */
802 buf->btformat = btv->fmt->btformat;
803 buf->btswap = btv->fmt->btswap;