27 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
29 #include <linux/module.h>
31 #include <linux/slab.h>
32 #include <linux/pci.h>
36 #include <asm/pgtable.h>
41 #define VCR_HACK_LINES 4
49 unsigned int offset,
unsigned int bpl,
50 unsigned int padding,
unsigned int skip_lines,
51 unsigned int store_lines)
62 instructions = skip_lines * 4;
63 instructions += (1 + ((bpl +
padding) * store_lines)
65 instructions += 2 * 8;
74 while (skip_lines-- > 0) {
81 for (line = 0; line < store_lines; line++) {
82 if ((btv->opt_vcr_hack) &&
126 bttv_risc_planar(
struct bttv *btv,
struct btcx_riscmem *risc,
128 unsigned int yoffset,
unsigned int ybpl,
129 unsigned int ypadding,
unsigned int ylines,
130 unsigned int uoffset,
unsigned int voffset,
131 unsigned int hshift,
unsigned int vshift,
132 unsigned int cpadding)
134 unsigned int instructions,
line,
todo,ylen,chroma;
140 int topfield = (0 == yoffset);
146 instructions = ((3 + (ybpl + ypadding) * ylines * 2)
161 for (line = 0; line < ylines; line++) {
162 if ((btv->opt_vcr_hack) &&
171 chroma = ((line & 1) == 0);
173 chroma = ((line & 1) == 1);
177 chroma = ((line & 3) == 0);
179 chroma = ((line & 3) == 2);
186 for (todo = ybpl; todo > 0; todo -= ylen) {
188 while (yoffset && yoffset >=
sg_dma_len(ysg)) {
192 while (uoffset && uoffset >=
sg_dma_len(usg)) {
196 while (voffset && voffset >=
sg_dma_len(vsg)) {
206 if (uoffset + (ylen>>hshift) >
sg_dma_len(usg))
208 if (voffset + (ylen>>hshift) >
sg_dma_len(vsg))
227 uoffset += ylen >> hshift;
229 voffset += ylen >> hshift;
246 bttv_risc_overlay(
struct bttv *btv,
struct btcx_riscmem *risc,
247 const struct bttv_format *
fmt,
struct bttv_overlay *ov,
248 int skip_even,
int skip_odd)
251 unsigned skip, nskips;
263 dwords = (3 * ov->nclips + 2) *
264 ((skip_even || skip_odd) ? (ov->w.height+1)>>1 : ov->w.height);
276 addr = (
unsigned long)btv->fbuf.base;
277 addr += btv->fbuf.fmt.bytesperline * ov->w.top;
278 addr += (fmt->depth >> 3) * ov->w.left;
281 for (maxy = -1, line = 0; line < ov->w.height;
282 line++, addr += btv->fbuf.fmt.bytesperline) {
283 if ((btv->opt_vcr_hack) &&
286 if ((line%2) == 0 && skip_even)
288 if ((line%2) == 1 && skip_odd)
294 skips, &nskips, ov->clips, ov->nclips);
297 for (start = 0, skip = 0; start < ov->w.width; start =
end) {
298 if (skip >= nskips) {
301 }
else if (start < skips[skip].start) {
310 ra = addr + (fmt->depth>>3)*start;
316 if (ov->w.width == end)
318 ri |= (fmt->depth>>3) * (end-start);
336 bttv_calc_geo_old(
struct bttv *btv,
struct bttv_geometry *geo,
338 const struct bttv_tvnorm *
tvnorm)
343 int swidth = tvnorm->swidth;
344 int totalwidth = tvnorm->totalwidth;
345 int scaledtwidth = tvnorm->scaledtwidth;
347 if (btv->input == btv->dig) {
353 vdelay = tvnorm->vdelay;
355 xsf = (width*scaledtwidth)/swidth;
356 geo->hscale = ((totalwidth*4096
UL)/xsf-4096);
357 geo->hdelay = tvnorm->hdelayx1;
358 geo->hdelay = (geo->hdelay*
width)/swidth;
359 geo->hdelay &= 0x3fe;
360 sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
361 geo->vscale = (0x10000
UL-
sr) & 0x1fff;
362 geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
363 ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
365 geo->vdelay = vdelay;
367 geo->sheight = tvnorm->sheight;
368 geo->vtotal = tvnorm->vtotal;
370 if (btv->opt_combfilter) {
371 geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
372 geo->comb = (width < 769) ? 1 : 0;
380 bttv_calc_geo (
struct bttv * btv,
381 struct bttv_geometry * geo,
385 const struct bttv_tvnorm * tvnorm,
388 unsigned int c_width;
389 unsigned int c_height;
392 if ((crop->
left == tvnorm->cropcap.defrect.left
393 && crop->
top == tvnorm->cropcap.defrect.top
394 && crop->
width == tvnorm->cropcap.defrect.width
395 && crop->
height == tvnorm->cropcap.defrect.height
396 && width <= tvnorm->swidth )
397 || btv->input == btv->dig) {
398 bttv_calc_geo_old(btv, geo, width, height,
399 both_fields, tvnorm);
405 c_width =
min((
unsigned int) crop->
width, width * 16);
406 c_height =
min((
unsigned int) crop->
height, height * 16);
409 geo->hscale = (c_width * 4096
U + (width >> 1)) / width - 4096;
411 geo->hdelay = ((crop->
left * width + c_width) / c_width) & ~1;
413 geo->sheight = c_height;
414 geo->vdelay = crop->
top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
415 sr = c_height >> !both_fields;
416 sr = (sr * 512
U + (height >> 1)) / height - 512;
417 geo->vscale = (0x10000
UL -
sr) & 0x1fff;
419 geo->vtotal = tvnorm->vtotal;
421 geo->crop = (((geo->width >> 8) & 0x03) |
422 ((geo->hdelay >> 6) & 0x0c) |
423 ((geo->sheight >> 4) & 0x30) |
424 ((geo->vdelay >> 2) & 0xc0));
426 if (btv->opt_combfilter) {
427 geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
428 geo->comb = (width < 769) ? 1 : 0;
436 bttv_apply_geo(
struct bttv *btv,
struct bttv_geometry *geo,
int odd)
438 int off = odd ? 0x80 : 0x00;
469 if (
NULL != btv->curr.top) btv->cap_ctl |= 0x02;
470 if (
NULL != btv->curr.bottom) btv->cap_ctl |= 0x01;
471 if (
NULL != btv->cvbi) btv->cap_ctl |= 0x0c;
474 capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00;
475 capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00;
478 d2printk(
"%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
479 btv->c.nr,capctl,btv->loop_irq,
480 btv->cvbi ? (
unsigned long long)btv->cvbi->top.dma : 0,
481 btv->curr.top ? (
unsigned long long)btv->curr.top->top.dma : 0,
482 btv->cvbi ? (
unsigned long long)btv->cvbi->bottom.dma : 0,
483 btv->curr.bottom ? (
unsigned long long)btv->curr.bottom->bottom.dma : 0);
488 cmd |= (btv->loop_irq & 0x0f) << 16;
489 cmd |= (~btv->loop_irq & 0x0f) << 20;
491 if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
521 dprintk(
"%d: risc main @ %08llx\n",
522 btv->c.nr, (
unsigned long long)btv->main.dma);
528 btv->main.cpu[3] =
cpu_to_le32(btv->main.dma + (4<<2));
532 btv->main.cpu[5] =
cpu_to_le32(btv->main.dma + (6<<2));
534 btv->main.cpu[7] =
cpu_to_le32(btv->main.dma + (8<<2));
542 btv->main.cpu[11] =
cpu_to_le32(btv->main.dma + (12<<2));
544 btv->main.cpu[13] =
cpu_to_le32(btv->main.dma + (14<<2));
548 btv->main.cpu[15] =
cpu_to_le32(btv->main.dma + (0<<2));
558 unsigned long next = btv->main.dma + ((slot+2) << 2);
561 d2printk(
"%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
564 d2printk(
"%d: risc=%p slot[%d]=%08llx irq=%d\n",
565 btv->c.nr, risc, slot,
566 (
unsigned long long)risc->
dma, irqflags);
570 cmd |= (irqflags & 0x0f) << 16;
571 cmd |= (~irqflags & 0x0f) << 20;
596 struct bttv_buffer *vbi)
601 int bottom_irq_flags;
606 bottom_irq_flags = 0;
609 unsigned int crop, vdelay;
618 if (vbi->geo.vdelay > vdelay) {
619 vdelay = vbi->geo.vdelay & 0xfe;
620 crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
628 if (vbi->vbi_count[0] > 0) {
633 if (vbi->vbi_count[1] > 0) {
635 bottom = &vbi->bottom;
636 bottom_irq_flags = 4;
648 struct bttv_buffer_set *
set)
652 if (
set->top ==
set->bottom) {
654 if (
set->top->vb.queue.next)
659 if (
set->top->vb.queue.next)
661 if (
set->bottom->vb.queue.next)
664 bttv_apply_geo(btv, &
set->top->geo, 1);
665 bttv_apply_geo(btv, &
set->bottom->geo,0);
670 btaor((
set->top->btformat & 0xf0) | (
set->bottom->btformat & 0x0f),
672 btaor((
set->top->btswap & 0x0a) | (
set->bottom->btswap & 0x05),
676 if (
set->top->vb.queue.next)
678 bttv_apply_geo(btv, &
set->top->geo,1);
679 bttv_apply_geo(btv, &
set->top->geo,0);
685 }
else if (
NULL !=
set->bottom) {
687 if (
set->bottom->vb.queue.next)
689 bttv_apply_geo(btv, &
set->bottom->geo,1);
690 bttv_apply_geo(btv, &
set->bottom->geo,0);
709 const struct bttv_tvnorm *tvnorm =
bttv_tvnorms + buf->tvnorm;
712 dprintk(
"%d: buffer field: %s format: %s size: %dx%d\n",
714 buf->fmt->name, buf->vb.width, buf->vb.height);
718 int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
719 int bpf = bpl * (buf->vb.height >> 1);
721 bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
725 switch (buf->vb.field) {
734 0,bpl,0,0,buf->vb.height);
738 0,bpl,bpl,0,buf->vb.height >> 1);
740 bpl,bpl,bpl,0,buf->vb.height >> 1);
744 0,bpl,0,0,buf->vb.height >> 1);
746 bpf,bpl,0,0,buf->vb.height >> 1);
755 int uoffset, voffset;
756 int ypadding, cpadding, lines;
759 uoffset = buf->vb.width * buf->vb.height;
760 voffset = buf->vb.width * buf->vb.height;
761 if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
763 uoffset >>= buf->fmt->hshift;
764 uoffset >>= buf->fmt->vshift;
768 voffset >>= buf->fmt->hshift;
769 voffset >>= buf->fmt->vshift;
773 switch (buf->vb.field) {
775 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
778 bttv_risc_planar(btv, &buf->top, dma->
sglist,
779 0,buf->vb.width,0,buf->vb.height,
780 uoffset,voffset,buf->fmt->hshift,
784 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
787 bttv_risc_planar(btv, &buf->bottom, dma->
sglist,
788 0,buf->vb.width,0,buf->vb.height,
789 uoffset,voffset,buf->fmt->hshift,
793 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
796 lines = buf->vb.height >> 1;
797 ypadding = buf->vb.width;
798 cpadding = buf->vb.width >> buf->fmt->hshift;
799 bttv_risc_planar(btv,&buf->top,
801 0,buf->vb.width,ypadding,lines,
806 bttv_risc_planar(btv,&buf->bottom,
808 ypadding,buf->vb.width,ypadding,lines,
816 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
819 lines = buf->vb.height >> 1;
820 ypadding = buf->vb.width;
821 cpadding = buf->vb.width >> buf->fmt->hshift;
822 bttv_risc_planar(btv,&buf->top,
824 0,buf->vb.width,0,lines,
830 bttv_risc_planar(btv,&buf->bottom,
832 lines * ypadding,buf->vb.width,0,lines,
833 lines * ypadding + (uoffset >> 1),
834 lines * ypadding + (voffset >> 1),
845 if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
848 bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
849 1,tvnorm,&buf->crop);
854 buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
858 buf->btformat = buf->fmt->btformat;
859 buf->btswap = buf->fmt->btswap;
868 struct bttv_overlay *ov,
869 const struct bttv_format *fmt,
870 struct bttv_buffer *
buf)
873 dprintk(
"%d: overlay fields: %s format: %s size: %dx%d\n",
875 fmt->name, ov->w.width, ov->w.height);
878 bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
885 bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 0);
888 bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
891 bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 1);
892 bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
899 buf->btformat = fmt->btformat;
900 buf->btswap = fmt->btswap;
901 buf->vb.field = ov->field;