linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / media / video / bttv-risc.c
index 769c7e3..b40e973 100644 (file)
@@ -1,4 +1,5 @@
 /*
+
     bttv-risc.c  --  interfaces to other kernel modules
 
     bttv risc code handling
@@ -73,41 +74,41 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
                }
                if (bpl <= sg_dma_len(sg)-offset) {
                        /* fits into current chunk */
-                        *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
+                       *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
                                            BT848_RISC_EOL|bpl);
-                        *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
-                        offset+=bpl;
+                       *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
+                       offset+=bpl;
                } else {
                        /* scanline needs to be splitted */
-                        todo = bpl;
-                        *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
+                       todo = bpl;
+                       *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
                                            (sg_dma_len(sg)-offset));
-                        *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
-                        todo -= (sg_dma_len(sg)-offset);
-                        offset = 0;
-                        sg++;
-                        while (todo > sg_dma_len(sg)) {
-                                *(rp++)=cpu_to_le32(BT848_RISC_WRITE|
+                       *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
+                       todo -= (sg_dma_len(sg)-offset);
+                       offset = 0;
+                       sg++;
+                       while (todo > sg_dma_len(sg)) {
+                               *(rp++)=cpu_to_le32(BT848_RISC_WRITE|
                                                    sg_dma_len(sg));
-                                *(rp++)=cpu_to_le32(sg_dma_address(sg));
+                               *(rp++)=cpu_to_le32(sg_dma_address(sg));
                                todo -= sg_dma_len(sg);
                                sg++;
                        }
-                        *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
+                       *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
                                            todo);
                        *(rp++)=cpu_to_le32(sg_dma_address(sg));
                        offset += todo;
                }
                offset += padding;
        }
-       dprintk("bttv%d: risc planar: %d sglist elems\n", btv->c.nr, (int)(sg-sglist));
 
        /* save pointer to jmp instruction address */
        risc->jmp = rp;
+       BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size);
        return 0;
 }
 
-int
+static int
 bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
                 struct scatterlist *sglist,
                 unsigned int yoffset,  unsigned int ybpl,
@@ -121,6 +122,7 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
        struct scatterlist *ysg;
        struct scatterlist *usg;
        struct scatterlist *vsg;
+       int topfield = (0 == yoffset);
        int rc;
 
        /* estimate risc mem: worst case is one write per page border +
@@ -145,11 +147,26 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
                    (line >= (ylines - VCR_HACK_LINES)))
                        continue;
                switch (vshift) {
-               case 0:  chroma = 1;           break;
-               case 1:  chroma = !(line & 1); break;
-               case 2:  chroma = !(line & 3); break;
-               default: chroma = 0;
+               case 0:
+                       chroma = 1;
+                       break;
+               case 1:
+                       if (topfield)
+                               chroma = ((line & 1) == 0);
+                       else
+                               chroma = ((line & 1) == 1);
+                       break;
+               case 2:
+                       if (topfield)
+                               chroma = ((line & 3) == 0);
+                       else
+                               chroma = ((line & 3) == 2);
+                       break;
+               default:
+                       chroma = 0;
+                       break;
                }
+
                for (todo = ybpl; todo > 0; todo -= ylen) {
                        /* go to next sg entry if needed */
                        while (yoffset && yoffset >= sg_dma_len(ysg)) {
@@ -184,8 +201,8 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
                                ri |= BT848_RISC_EOL;
 
                        /* write risc instruction */
-                        *(rp++)=cpu_to_le32(ri | ylen);
-                        *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
+                       *(rp++)=cpu_to_le32(ri | ylen);
+                       *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
                                            (ylen >> hshift));
                        *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
                        yoffset += ylen;
@@ -205,10 +222,11 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
 
        /* save pointer to jmp instruction address */
        risc->jmp = rp;
+       BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size);
        return 0;
 }
 
-int
+static int
 bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
                  const struct bttv_format *fmt, struct bttv_overlay *ov,
                  int skip_even, int skip_odd)
@@ -221,7 +239,7 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
        /* skip list for window clipping */
        if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
                return -ENOMEM;
-       
+
        /* estimate risc mem: worst case is (clip+1) * lines instructions
           + sync + jump (all 2 dwords) */
        instructions  = (ov->nclips + 1) *
@@ -274,7 +292,7 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
                                ra = addr + (fmt->depth>>3)*start;
                        else
                                ra = 0;
-                               
+
                        if (0 == start)
                                ri |= BT848_RISC_SOL;
                        if (ov->w.width == end)
@@ -289,18 +307,19 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
 
        /* save pointer to jmp instruction address */
        risc->jmp = rp;
+       BUG_ON((risc->jmp - risc->cpu + 2) / 4 > risc->size);
        kfree(skips);
        return 0;
 }
 
 /* ---------------------------------------------------------- */
 
-void
+static void
 bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo,
              int width, int height, int interleaved, int norm)
 {
        const struct bttv_tvnorm *tvnorm = &bttv_tvnorms[norm];
-        u32 xsf, sr;
+       u32 xsf, sr;
        int vdelay;
 
        int swidth       = tvnorm->swidth;
@@ -314,64 +333,60 @@ bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo,
        }
 
        vdelay = tvnorm->vdelay;
-#if 0 /* FIXME */
-       if (vdelay < btv->vbi.lines*2)
-               vdelay = btv->vbi.lines*2;
-#endif
-
-        xsf = (width*scaledtwidth)/swidth;
-        geo->hscale =  ((totalwidth*4096UL)/xsf-4096);
-        geo->hdelay =  tvnorm->hdelayx1;
-        geo->hdelay =  (geo->hdelay*width)/swidth;
-        geo->hdelay &= 0x3fe;
-        sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
-        geo->vscale =  (0x10000UL-sr) & 0x1fff;
-        geo->crop   =  ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
-                ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
-        geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
-        geo->vdelay  =  vdelay;
-        geo->width   =  width;
-        geo->sheight =  tvnorm->sheight;
+
+       xsf = (width*scaledtwidth)/swidth;
+       geo->hscale =  ((totalwidth*4096UL)/xsf-4096);
+       geo->hdelay =  tvnorm->hdelayx1;
+       geo->hdelay =  (geo->hdelay*width)/swidth;
+       geo->hdelay &= 0x3fe;
+       sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
+       geo->vscale =  (0x10000UL-sr) & 0x1fff;
+       geo->crop   =  ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
+               ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
+       geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
+       geo->vdelay  =  vdelay;
+       geo->width   =  width;
+       geo->sheight =  tvnorm->sheight;
        geo->vtotal  =  tvnorm->vtotal;
 
-        if (btv->opt_combfilter) {
-                geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
-                geo->comb = (width < 769) ? 1 : 0;
-        } else {
-                geo->vtc  = 0;
-                geo->comb = 0;
-        }
+       if (btv->opt_combfilter) {
+               geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
+               geo->comb = (width < 769) ? 1 : 0;
+       } else {
+               geo->vtc  = 0;
+               geo->comb = 0;
+       }
 }
 
-void
+static void
 bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
 {
-        int off = odd ? 0x80 : 0x00;
+       int off = odd ? 0x80 : 0x00;
 
        if (geo->comb)
                btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
        else
                btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
 
-        btwrite(geo->vtc,             BT848_E_VTC+off);
-        btwrite(geo->hscale >> 8,     BT848_E_HSCALE_HI+off);
-        btwrite(geo->hscale & 0xff,   BT848_E_HSCALE_LO+off);
-        btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
-        btwrite(geo->vscale & 0xff,   BT848_E_VSCALE_LO+off);
-        btwrite(geo->width & 0xff,    BT848_E_HACTIVE_LO+off);
-        btwrite(geo->hdelay & 0xff,   BT848_E_HDELAY_LO+off);
-        btwrite(geo->sheight & 0xff,  BT848_E_VACTIVE_LO+off);
-        btwrite(geo->vdelay & 0xff,   BT848_E_VDELAY_LO+off);
-        btwrite(geo->crop,            BT848_E_CROP+off);
+       btwrite(geo->vtc,             BT848_E_VTC+off);
+       btwrite(geo->hscale >> 8,     BT848_E_HSCALE_HI+off);
+       btwrite(geo->hscale & 0xff,   BT848_E_HSCALE_LO+off);
+       btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
+       btwrite(geo->vscale & 0xff,   BT848_E_VSCALE_LO+off);
+       btwrite(geo->width & 0xff,    BT848_E_HACTIVE_LO+off);
+       btwrite(geo->hdelay & 0xff,   BT848_E_HDELAY_LO+off);
+       btwrite(geo->sheight & 0xff,  BT848_E_VACTIVE_LO+off);
+       btwrite(geo->vdelay & 0xff,   BT848_E_VDELAY_LO+off);
+       btwrite(geo->crop,            BT848_E_CROP+off);
        btwrite(geo->vtotal>>8,       BT848_VTOTAL_HI);
-        btwrite(geo->vtotal & 0xff,   BT848_VTOTAL_LO);
+       btwrite(geo->vtotal & 0xff,   BT848_VTOTAL_LO);
 }
 
 /* ---------------------------------------------------------- */
 /* risc group / risc main loop / dma management               */
 
 void
-bttv_set_dma(struct bttv *btv, int override, int irqflags)
+bttv_set_dma(struct bttv *btv, int override)
 {
        unsigned long cmd;
        int capctl;
@@ -387,26 +402,26 @@ bttv_set_dma(struct bttv *btv, int override, int irqflags)
        capctl |= override;
 
        d2printk(KERN_DEBUG
-                "bttv%d: capctl=%x irq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",
-                btv->c.nr,capctl,irqflags,
+                "bttv%d: capctl=%x lirq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",
+                btv->c.nr,capctl,btv->loop_irq,
                 btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
                 btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
                 btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,
                 btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
-       
+
        cmd = BT848_RISC_JUMP;
-       if (irqflags) {
+       if (btv->loop_irq) {
                cmd |= BT848_RISC_IRQ;
-               cmd |= (irqflags  & 0x0f) << 16;
-               cmd |= (~irqflags & 0x0f) << 20;
+               cmd |= (btv->loop_irq  & 0x0f) << 16;
+               cmd |= (~btv->loop_irq & 0x0f) << 20;
        }
-       if (irqflags || btv->cvbi) {
+       if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
                mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
        } else {
                del_timer(&btv->timeout);
        }
-        btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
-       
+       btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
+
        btaor(capctl, ~0x0f, BT848_CAP_CTL);
        if (capctl) {
                if (btv->dma_on)
@@ -417,7 +432,7 @@ bttv_set_dma(struct bttv *btv, int override, int irqflags)
        } else {
                if (!btv->dma_on)
                        return;
-                btand(~3, BT848_GPIO_DMA_CTL);
+               btand(~3, BT848_GPIO_DMA_CTL);
                btv->dma_on = 0;
        }
        return;
@@ -427,7 +442,7 @@ int
 bttv_risc_init_main(struct bttv *btv)
 {
        int rc;
-       
+
        if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
                return rc;
        dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n",
@@ -445,19 +460,19 @@ bttv_risc_init_main(struct bttv *btv)
        btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
        btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
 
-        btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
+       btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
                                       BT848_FIFO_STATUS_VRO);
-        btv->main.cpu[9] = cpu_to_le32(0);
+       btv->main.cpu[9] = cpu_to_le32(0);
 
        /* bottom field */
-        btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
+       btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
        btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
-        btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
+       btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
        btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
 
        /* jump back to top field */
        btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
-        btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
+       btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
 
        return 0;
 }
@@ -539,8 +554,10 @@ bttv_buffer_activate_video(struct bttv *btv,
                }
                bttv_apply_geo(btv, &set->top->geo, 1);
                bttv_apply_geo(btv, &set->bottom->geo,0);
-               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top, set->topirq);
-               bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom, 0);
+               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
+                              set->top_irq);
+               bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
+                              set->frame_irq);
                btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
                      ~0xff, BT848_COLOR_FMT);
                btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
@@ -551,7 +568,8 @@ bttv_buffer_activate_video(struct bttv *btv,
                        list_del(&set->top->vb.queue);
                bttv_apply_geo(btv, &set->top->geo,1);
                bttv_apply_geo(btv, &set->top->geo,0);
-               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top, 0);
+               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
+                              set->frame_irq);
                bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,           0);
                btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
                btaor(set->top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
@@ -561,8 +579,9 @@ bttv_buffer_activate_video(struct bttv *btv,
                        list_del(&set->bottom->vb.queue);
                bttv_apply_geo(btv, &set->bottom->geo,1);
                bttv_apply_geo(btv, &set->bottom->geo,0);
-               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL,                 0);
-               bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom, 0);
+               bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
+               bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
+                              set->frame_irq);
                btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
                btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
        } else {
@@ -592,7 +611,7 @@ bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
 
                bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
                              V4L2_FIELD_HAS_BOTH(buf->vb.field),buf->tvnorm);
-               
+
                switch (buf->vb.field) {
                case V4L2_FIELD_TOP:
                        bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
@@ -752,13 +771,8 @@ bttv_overlay_risc(struct bttv *btv,
                bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
                break;
        case V4L2_FIELD_INTERLACED:
-#if 0
-               bttv_risc_overlay(btv, &buf->top,    fmt, ov, 1, 0);
-               bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 1);
-#else
                bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 1);
                bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
-#endif
                break;
        default:
                BUG();