diff options
Diffstat (limited to 'drivers/media/video/bt8xx/bttv-risc.c')
-rw-r--r-- | drivers/media/video/bt8xx/bttv-risc.c | 171 |
1 files changed, 140 insertions, 31 deletions
diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c index afcfe71e3792..e7104d9cb4bd 100644 --- a/drivers/media/video/bt8xx/bttv-risc.c +++ b/drivers/media/video/bt8xx/bttv-risc.c | |||
@@ -43,7 +43,8 @@ int | |||
43 | bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, | 43 | bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, |
44 | struct scatterlist *sglist, | 44 | struct scatterlist *sglist, |
45 | unsigned int offset, unsigned int bpl, | 45 | unsigned int offset, unsigned int bpl, |
46 | unsigned int padding, unsigned int lines) | 46 | unsigned int padding, unsigned int skip_lines, |
47 | unsigned int store_lines) | ||
47 | { | 48 | { |
48 | u32 instructions,line,todo; | 49 | u32 instructions,line,todo; |
49 | struct scatterlist *sg; | 50 | struct scatterlist *sg; |
@@ -54,9 +55,11 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, | |||
54 | one write per scan line + sync + jump (all 2 dwords). padding | 55 | one write per scan line + sync + jump (all 2 dwords). padding |
55 | can cause next bpl to start close to a page border. First DMA | 56 | can cause next bpl to start close to a page border. First DMA |
56 | region may be smaller than PAGE_SIZE */ | 57 | region may be smaller than PAGE_SIZE */ |
57 | instructions = 1 + ((bpl + padding) * lines) / PAGE_SIZE + lines; | 58 | instructions = skip_lines * 4; |
58 | instructions += 2; | 59 | instructions += (1 + ((bpl + padding) * store_lines) |
59 | if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0) | 60 | / PAGE_SIZE + store_lines) * 8; |
61 | instructions += 2 * 8; | ||
62 | if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions)) < 0) | ||
60 | return rc; | 63 | return rc; |
61 | 64 | ||
62 | /* sync instruction */ | 65 | /* sync instruction */ |
@@ -64,11 +67,16 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, | |||
64 | *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); | 67 | *(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); |
65 | *(rp++) = cpu_to_le32(0); | 68 | *(rp++) = cpu_to_le32(0); |
66 | 69 | ||
70 | while (skip_lines-- > 0) { | ||
71 | *(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL | | ||
72 | BT848_RISC_EOL | bpl); | ||
73 | } | ||
74 | |||
67 | /* scan lines */ | 75 | /* scan lines */ |
68 | sg = sglist; | 76 | sg = sglist; |
69 | for (line = 0; line < lines; line++) { | 77 | for (line = 0; line < store_lines; line++) { |
70 | if ((btv->opt_vcr_hack) && | 78 | if ((btv->opt_vcr_hack) && |
71 | (line >= (lines - VCR_HACK_LINES))) | 79 | (line >= (store_lines - VCR_HACK_LINES))) |
72 | continue; | 80 | continue; |
73 | while (offset && offset >= sg_dma_len(sg)) { | 81 | while (offset && offset >= sg_dma_len(sg)) { |
74 | offset -= sg_dma_len(sg); | 82 | offset -= sg_dma_len(sg); |
@@ -130,7 +138,8 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc, | |||
130 | /* estimate risc mem: worst case is one write per page border + | 138 | /* estimate risc mem: worst case is one write per page border + |
131 | one write per scan line (5 dwords) | 139 | one write per scan line (5 dwords) |
132 | plus sync + jump (2 dwords) */ | 140 | plus sync + jump (2 dwords) */ |
133 | instructions = (ybpl * ylines * 2) / PAGE_SIZE + ylines; | 141 | instructions = ((3 + (ybpl + ypadding) * ylines * 2) |
142 | / PAGE_SIZE) + ylines; | ||
134 | instructions += 2; | 143 | instructions += 2; |
135 | if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0) | 144 | if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0) |
136 | return rc; | 145 | return rc; |
@@ -317,10 +326,10 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, | |||
317 | /* ---------------------------------------------------------- */ | 326 | /* ---------------------------------------------------------- */ |
318 | 327 | ||
319 | static void | 328 | static void |
320 | bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo, | 329 | bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo, |
321 | int width, int height, int interleaved, int norm) | 330 | int width, int height, int interleaved, |
331 | const struct bttv_tvnorm *tvnorm) | ||
322 | { | 332 | { |
323 | const struct bttv_tvnorm *tvnorm = &bttv_tvnorms[norm]; | ||
324 | u32 xsf, sr; | 333 | u32 xsf, sr; |
325 | int vdelay; | 334 | int vdelay; |
326 | 335 | ||
@@ -361,6 +370,62 @@ bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo, | |||
361 | } | 370 | } |
362 | 371 | ||
363 | static void | 372 | static void |
373 | bttv_calc_geo (struct bttv * btv, | ||
374 | struct bttv_geometry * geo, | ||
375 | unsigned int width, | ||
376 | unsigned int height, | ||
377 | int both_fields, | ||
378 | const struct bttv_tvnorm * tvnorm, | ||
379 | const struct v4l2_rect * crop) | ||
380 | { | ||
381 | unsigned int c_width; | ||
382 | unsigned int c_height; | ||
383 | u32 sr; | ||
384 | |||
385 | if ((crop->left == tvnorm->cropcap.defrect.left | ||
386 | && crop->top == tvnorm->cropcap.defrect.top | ||
387 | && crop->width == tvnorm->cropcap.defrect.width | ||
388 | && crop->height == tvnorm->cropcap.defrect.height | ||
389 | && width <= tvnorm->swidth /* see PAL-Nc et al */) | ||
390 | || bttv_tvcards[btv->c.type].muxsel[btv->input] < 0) { | ||
391 | bttv_calc_geo_old(btv, geo, width, height, | ||
392 | both_fields, tvnorm); | ||
393 | return; | ||
394 | } | ||
395 | |||
396 | /* For bug compatibility the image size checks permit scale | ||
397 | factors > 16. See bttv_crop_calc_limits(). */ | ||
398 | c_width = min((unsigned int) crop->width, width * 16); | ||
399 | c_height = min((unsigned int) crop->height, height * 16); | ||
400 | |||
401 | geo->width = width; | ||
402 | geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096; | ||
403 | /* Even to store Cb first, odd for Cr. */ | ||
404 | geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1; | ||
405 | |||
406 | geo->sheight = c_height; | ||
407 | geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY; | ||
408 | sr = c_height >> !both_fields; | ||
409 | sr = (sr * 512U + (height >> 1)) / height - 512; | ||
410 | geo->vscale = (0x10000UL - sr) & 0x1fff; | ||
411 | geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0; | ||
412 | geo->vtotal = tvnorm->vtotal; | ||
413 | |||
414 | geo->crop = (((geo->width >> 8) & 0x03) | | ||
415 | ((geo->hdelay >> 6) & 0x0c) | | ||
416 | ((geo->sheight >> 4) & 0x30) | | ||
417 | ((geo->vdelay >> 2) & 0xc0)); | ||
418 | |||
419 | if (btv->opt_combfilter) { | ||
420 | geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); | ||
421 | geo->comb = (width < 769) ? 1 : 0; | ||
422 | } else { | ||
423 | geo->vtc = 0; | ||
424 | geo->comb = 0; | ||
425 | } | ||
426 | } | ||
427 | |||
428 | static void | ||
364 | bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd) | 429 | bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd) |
365 | { | 430 | { |
366 | int off = odd ? 0x80 : 0x00; | 431 | int off = odd ? 0x80 : 0x00; |
@@ -522,16 +587,51 @@ int | |||
522 | bttv_buffer_activate_vbi(struct bttv *btv, | 587 | bttv_buffer_activate_vbi(struct bttv *btv, |
523 | struct bttv_buffer *vbi) | 588 | struct bttv_buffer *vbi) |
524 | { | 589 | { |
525 | /* vbi capture */ | 590 | struct btcx_riscmem *top; |
591 | struct btcx_riscmem *bottom; | ||
592 | int top_irq_flags; | ||
593 | int bottom_irq_flags; | ||
594 | |||
595 | top = NULL; | ||
596 | bottom = NULL; | ||
597 | top_irq_flags = 0; | ||
598 | bottom_irq_flags = 0; | ||
599 | |||
526 | if (vbi) { | 600 | if (vbi) { |
601 | unsigned int crop, vdelay; | ||
602 | |||
527 | vbi->vb.state = STATE_ACTIVE; | 603 | vbi->vb.state = STATE_ACTIVE; |
528 | list_del(&vbi->vb.queue); | 604 | list_del(&vbi->vb.queue); |
529 | bttv_risc_hook(btv, RISC_SLOT_O_VBI, &vbi->top, 0); | 605 | |
530 | bttv_risc_hook(btv, RISC_SLOT_E_VBI, &vbi->bottom, 4); | 606 | /* VDELAY is start of video, end of VBI capturing. */ |
531 | } else { | 607 | crop = btread(BT848_E_CROP); |
532 | bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0); | 608 | vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2); |
533 | bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0); | 609 | |
610 | if (vbi->geo.vdelay > vdelay) { | ||
611 | vdelay = vbi->geo.vdelay & 0xfe; | ||
612 | crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0); | ||
613 | |||
614 | btwrite(vdelay, BT848_E_VDELAY_LO); | ||
615 | btwrite(crop, BT848_E_CROP); | ||
616 | btwrite(vdelay, BT848_O_VDELAY_LO); | ||
617 | btwrite(crop, BT848_O_CROP); | ||
618 | } | ||
619 | |||
620 | if (vbi->vbi_count[0] > 0) { | ||
621 | top = &vbi->top; | ||
622 | top_irq_flags = 4; | ||
623 | } | ||
624 | |||
625 | if (vbi->vbi_count[1] > 0) { | ||
626 | top_irq_flags = 0; | ||
627 | bottom = &vbi->bottom; | ||
628 | bottom_irq_flags = 4; | ||
629 | } | ||
534 | } | 630 | } |
631 | |||
632 | bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags); | ||
633 | bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags); | ||
634 | |||
535 | return 0; | 635 | return 0; |
536 | } | 636 | } |
537 | 637 | ||
@@ -611,28 +711,31 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
611 | int bpf = bpl * (buf->vb.height >> 1); | 711 | int bpf = bpl * (buf->vb.height >> 1); |
612 | 712 | ||
613 | bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height, | 713 | bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height, |
614 | V4L2_FIELD_HAS_BOTH(buf->vb.field),buf->tvnorm); | 714 | V4L2_FIELD_HAS_BOTH(buf->vb.field), |
715 | tvnorm,&buf->crop); | ||
615 | 716 | ||
616 | switch (buf->vb.field) { | 717 | switch (buf->vb.field) { |
617 | case V4L2_FIELD_TOP: | 718 | case V4L2_FIELD_TOP: |
618 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, | 719 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, |
619 | 0,bpl,0,buf->vb.height); | 720 | /* offset */ 0,bpl, |
721 | /* padding */ 0,/* skip_lines */ 0, | ||
722 | buf->vb.height); | ||
620 | break; | 723 | break; |
621 | case V4L2_FIELD_BOTTOM: | 724 | case V4L2_FIELD_BOTTOM: |
622 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, | 725 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, |
623 | 0,bpl,0,buf->vb.height); | 726 | 0,bpl,0,0,buf->vb.height); |
624 | break; | 727 | break; |
625 | case V4L2_FIELD_INTERLACED: | 728 | case V4L2_FIELD_INTERLACED: |
626 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, | 729 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, |
627 | 0,bpl,bpl,buf->vb.height >> 1); | 730 | 0,bpl,bpl,0,buf->vb.height >> 1); |
628 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, | 731 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, |
629 | bpl,bpl,bpl,buf->vb.height >> 1); | 732 | bpl,bpl,bpl,0,buf->vb.height >> 1); |
630 | break; | 733 | break; |
631 | case V4L2_FIELD_SEQ_TB: | 734 | case V4L2_FIELD_SEQ_TB: |
632 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, | 735 | bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist, |
633 | 0,bpl,0,buf->vb.height >> 1); | 736 | 0,bpl,0,0,buf->vb.height >> 1); |
634 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, | 737 | bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist, |
635 | bpf,bpl,0,buf->vb.height >> 1); | 738 | bpf,bpl,0,0,buf->vb.height >> 1); |
636 | break; | 739 | break; |
637 | default: | 740 | default: |
638 | BUG(); | 741 | BUG(); |
@@ -662,7 +765,8 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
662 | switch (buf->vb.field) { | 765 | switch (buf->vb.field) { |
663 | case V4L2_FIELD_TOP: | 766 | case V4L2_FIELD_TOP: |
664 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, | 767 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, |
665 | buf->vb.height,0,buf->tvnorm); | 768 | buf->vb.height,/* both_fields */ 0, |
769 | tvnorm,&buf->crop); | ||
666 | bttv_risc_planar(btv, &buf->top, buf->vb.dma.sglist, | 770 | bttv_risc_planar(btv, &buf->top, buf->vb.dma.sglist, |
667 | 0,buf->vb.width,0,buf->vb.height, | 771 | 0,buf->vb.width,0,buf->vb.height, |
668 | uoffset,voffset,buf->fmt->hshift, | 772 | uoffset,voffset,buf->fmt->hshift, |
@@ -670,7 +774,8 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
670 | break; | 774 | break; |
671 | case V4L2_FIELD_BOTTOM: | 775 | case V4L2_FIELD_BOTTOM: |
672 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, | 776 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, |
673 | buf->vb.height,0,buf->tvnorm); | 777 | buf->vb.height,0, |
778 | tvnorm,&buf->crop); | ||
674 | bttv_risc_planar(btv, &buf->bottom, buf->vb.dma.sglist, | 779 | bttv_risc_planar(btv, &buf->bottom, buf->vb.dma.sglist, |
675 | 0,buf->vb.width,0,buf->vb.height, | 780 | 0,buf->vb.width,0,buf->vb.height, |
676 | uoffset,voffset,buf->fmt->hshift, | 781 | uoffset,voffset,buf->fmt->hshift, |
@@ -678,7 +783,8 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
678 | break; | 783 | break; |
679 | case V4L2_FIELD_INTERLACED: | 784 | case V4L2_FIELD_INTERLACED: |
680 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, | 785 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, |
681 | buf->vb.height,1,buf->tvnorm); | 786 | buf->vb.height,1, |
787 | tvnorm,&buf->crop); | ||
682 | lines = buf->vb.height >> 1; | 788 | lines = buf->vb.height >> 1; |
683 | ypadding = buf->vb.width; | 789 | ypadding = buf->vb.width; |
684 | cpadding = buf->vb.width >> buf->fmt->hshift; | 790 | cpadding = buf->vb.width >> buf->fmt->hshift; |
@@ -700,7 +806,8 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
700 | break; | 806 | break; |
701 | case V4L2_FIELD_SEQ_TB: | 807 | case V4L2_FIELD_SEQ_TB: |
702 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, | 808 | bttv_calc_geo(btv,&buf->geo,buf->vb.width, |
703 | buf->vb.height,1,buf->tvnorm); | 809 | buf->vb.height,1, |
810 | tvnorm,&buf->crop); | ||
704 | lines = buf->vb.height >> 1; | 811 | lines = buf->vb.height >> 1; |
705 | ypadding = buf->vb.width; | 812 | ypadding = buf->vb.width; |
706 | cpadding = buf->vb.width >> buf->fmt->hshift; | 813 | cpadding = buf->vb.width >> buf->fmt->hshift; |
@@ -731,11 +838,12 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf) | |||
731 | /* build risc code */ | 838 | /* build risc code */ |
732 | buf->vb.field = V4L2_FIELD_SEQ_TB; | 839 | buf->vb.field = V4L2_FIELD_SEQ_TB; |
733 | bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight, | 840 | bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight, |
734 | 1,buf->tvnorm); | 841 | 1,tvnorm,&buf->crop); |
735 | bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist, | 842 | bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist, |
736 | 0, RAW_BPL, 0, RAW_LINES); | 843 | /* offset */ 0, RAW_BPL, /* padding */ 0, |
844 | /* skip_lines */ 0, RAW_LINES); | ||
737 | bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist, | 845 | bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist, |
738 | buf->vb.size/2 , RAW_BPL, 0, RAW_LINES); | 846 | buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES); |
739 | } | 847 | } |
740 | 848 | ||
741 | /* copy format info */ | 849 | /* copy format info */ |
@@ -761,7 +869,8 @@ bttv_overlay_risc(struct bttv *btv, | |||
761 | 869 | ||
762 | /* calculate geometry */ | 870 | /* calculate geometry */ |
763 | bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height, | 871 | bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height, |
764 | V4L2_FIELD_HAS_BOTH(ov->field), ov->tvnorm); | 872 | V4L2_FIELD_HAS_BOTH(ov->field), |
873 | &bttv_tvnorms[ov->tvnorm],&buf->crop); | ||
765 | 874 | ||
766 | /* build risc code */ | 875 | /* build risc code */ |
767 | switch (ov->field) { | 876 | switch (ov->field) { |