aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/bt8xx/bttv-risc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/bt8xx/bttv-risc.c')
-rw-r--r--drivers/media/video/bt8xx/bttv-risc.c171
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
43bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, 43bttv_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
319static void 328static void
320bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo, 329bttv_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
363static void 372static void
373bttv_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
428static void
364bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd) 429bttv_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
522bttv_buffer_activate_vbi(struct bttv *btv, 587bttv_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) {