--- linux-2.3.51/drivers/char/bttv.c Sat Mar 11 11:27:13 2000 +++ linux/drivers/char/bttv.c Thu Mar 16 21:19:14 2000 @@ -121,6 +121,7 @@ #define I2C_GET() (btread(BT848_I2C)&1) #define BURSTOFFSET 76 +#define BTTV_ERRORS 5 /* ----------------------------------------------------------------------- */ @@ -719,12 +720,14 @@ /* ----------------------------------------------------------------------- */ +/* for some vendors it is just the PCI ID */ static struct VENDOR { int id; char *name; } vendors[] = { { 0x0001, "ATI Technologies Inc" }, { 0x10b4, "STB Systems Inc" }, + { 0x1118, "Terratec" }, { 0x13eb, "Hauppauge Computer Works Inc" }, { 0x1461, "Avermedia" }, { 0x1850, "Chronos" }, @@ -743,6 +746,7 @@ } cards[] = { { 0x0001, 0x1002, BTTV_HAUPPAUGE878, "TV Wonder" }, { 0x10b4, 0x2636, BTTV_HAUPPAUGE878, "???" }, + { 0x1118, 0x153b, BTTV_TERRATVALUE, "TV Value" }, { 0x13eb, 0x0070, BTTV_HAUPPAUGE878, "WinTV" }, { 0x1461, 0x0002, BTTV_AVERMEDIA98, "TVCapture 98" }, { 0x1850, 0x1851, BTTV_CHRONOS_VS2, "Video Shuttle II" }, @@ -1210,7 +1214,7 @@ unsigned int *pe=(unsigned int *) btv->vbi_even; if (debug) - printk("bttv%d: vbi: po=%08lx pe=%08lx\n", + printk("bttv%d: vbi1: po=%08lx pe=%08lx\n", btv->nr,virt_to_bus(po), virt_to_bus(pe)); *(po++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(po++)=0; @@ -1230,8 +1234,10 @@ } *(pe++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(0x01<<16)); *(pe++)=cpu_to_le32(virt_to_bus(btv->risc_jmp+10)); - DEBUG(printk(KERN_DEBUG "po: 0x%lx\n",(long)po)); - DEBUG(printk(KERN_DEBUG "pe: 0x%lx\n",(long)pe)); + + if (debug) + printk("bttv%d: vbi2: po=%08lx pe=%08lx\n", + btv->nr,virt_to_bus(po), virt_to_bus(pe)); } static int fmtbppx2[16] = { @@ -1307,7 +1313,7 @@ int shift, csize; if (debug) - printk("bttv%d: prisc: ro=%08lx re=%08lx\n", + printk("bttv%d: prisc1: ro=%08lx re=%08lx\n", btv->nr,virt_to_bus(ro), virt_to_bus(re)); switch(fmt) @@ -1403,6 +1409,10 @@ *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); *(re++)=cpu_to_le32(btv->bus_vbi_odd); + if (debug) + printk("bttv%d: prisc2: ro=%08lx re=%08lx\n", + btv->nr,virt_to_bus(ro), virt_to_bus(re)); + return 0; } @@ -1425,7 +1435,7 @@ return make_prisctab(btv, ro, re, vbuf, width, height, palette); if (debug) - printk("bttv%d: vrisc: ro=%08lx re=%08lx\n", + printk("bttv%d: vrisc1: ro=%08lx re=%08lx\n", btv->nr,virt_to_bus(ro), virt_to_bus(re)); inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0; @@ -1475,6 +1485,10 @@ *(ro++)=cpu_to_le32(btv->bus_vbi_even); *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); *(re++)=cpu_to_le32(btv->bus_vbi_odd); + + if (debug) + printk("bttv%d: vrisc2: ro=%08lx re=%08lx\n", + btv->nr,virt_to_bus(ro), virt_to_bus(re)); return 0; } @@ -1552,7 +1566,7 @@ width=btv->win.width; height=btv->win.height; if (debug) - printk("bttv%d: make_clip: pal=%d size=%dx%d, bpl=%d bpp=%d\n", + printk("bttv%d: clip1: pal=%d size=%dx%d, bpl=%d bpp=%d\n", btv->nr,btv->picture.palette,width,height,bpl,bpp); if(width > 1023) width = 1023; /* sanity check */ @@ -1659,6 +1673,10 @@ *(ro++)=cpu_to_le32(btv->bus_vbi_even); *(re++)=cpu_to_le32(BT848_RISC_JUMP); *(re++)=cpu_to_le32(btv->bus_vbi_odd); + + if (debug) + printk("bttv%d: clip2: pal=%d size=%dx%d, bpl=%d bpp=%d\n", + btv->nr,btv->picture.palette,width,height,bpl,bpp); } /* @@ -1992,6 +2010,26 @@ tvnorms[2].hdelayx1 = 186 - (on?BURSTOFFSET :0); } +static void bt848_restart(struct bttv *btv) +{ + if (verbose) + printk("bttv%d: resetting chip\n",btv->nr); + btwrite(0xfffffUL, BT848_INT_STAT); + btand(~15, BT848_GPIO_DMA_CTL); + btwrite(0, BT848_SRESET); + btwrite(virt_to_bus(btv->risc_jmp+2), + BT848_RISC_STRT_ADD); + + /* enforce pll reprogramming */ + btv->pll.pll_current = 0; + set_pll(btv); + + btv->errors = 0; + btv->needs_restart = 0; + bt848_set_geo(btv,0); + bt848_set_risc_jmps(btv,-1); +} + /* * Open a bttv card. Right now the flags stuff is just playing */ @@ -2017,7 +2055,10 @@ for (i = 0; i < gbuffers; i++) btv->gbuf[i].stat = GBUFFER_UNUSED; + if (btv->needs_restart) + bt848_restart(btv); burst(0); + set_pll(btv); btv->user++; up(&btv->lock); MOD_INC_USE_COUNT; @@ -2113,7 +2154,6 @@ btaor(datahi, ~1, BT848_O_CONTROL); } - /* * ioctl routine */ @@ -2235,6 +2275,7 @@ if (btv->win.norm != v.mode) { btv->win.norm = v.mode; down(&btv->lock); + set_pll(btv); make_vbitab(btv); bt848_set_winsize(btv); up(&btv->lock); @@ -2276,7 +2317,7 @@ if(copy_from_user(&vw,arg,sizeof(vw))) return -EFAULT; - + if(vw.flags || vw.width < 16 || vw.height < 16) { down(&btv->lock); @@ -2291,6 +2332,8 @@ vw.width &= ~3; } down(&btv->lock); + if (btv->needs_restart) + bt848_restart(btv); btv->win.x=vw.x; btv->win.y=vw.y; btv->win.width=vw.width; @@ -2564,6 +2607,10 @@ btv->gbuf[i].stat = GBUFFER_UNUSED; return ret; } + down(&btv->lock); + if (btv->needs_restart) + bt848_restart(btv); + up(&btv->lock); return 0; case BTTV_FIELDNR: @@ -2737,6 +2784,10 @@ todo=count; while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) { + down(&btv->lock); + if (btv->needs_restart) + bt848_restart(btv); + up(&btv->lock); if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, q)) return -EFAULT; todo-=q; @@ -2791,6 +2842,8 @@ struct bttv *btv=(struct bttv *)(dev-2); down(&btv->lock); + if (btv->needs_restart) + bt848_restart(btv); btv->vbip=VBIBUF_SIZE; btv->vbi_on = 1; bt848_set_risc_jmps(btv,-1); @@ -2866,6 +2919,7 @@ static int radio_open(struct video_device *dev, int flags) { struct bttv *btv = (struct bttv *)(dev-1); + unsigned long v; down(&btv->lock); if (btv->user) @@ -2873,6 +2927,8 @@ btv->user++; btv->radio = 1; + v = 400*16; + call_i2c_clients(btv,VIDIOCSFREQ,&v); call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type); bt848_muxsel(btv,0); up(&btv->lock); @@ -3092,12 +3148,10 @@ /* print which board we have found */ printk(KERN_INFO "bttv%d: model: ",btv->nr); - sprintf(btv->video_dev.name,"BT%d",btv->id); - if (btv->id==848 && btv->revision==0x12) - strcat(btv->video_dev.name,"A"); - strcat(btv->video_dev.name,"("); - strcat(btv->video_dev.name, tvcards[btv->type].name); - strcat(btv->video_dev.name,")"); + sprintf(btv->video_dev.name,"BT%d%c(%.22s)", + btv->id, + (btv->id==848 && btv->revision==0x12) ? "A" : "", + tvcards[btv->type].name); printk("%s\n",btv->video_dev.name); /* board specific initialisations */ @@ -3349,6 +3403,9 @@ btv->vbibuf=0; btv->field=btv->last_field=0; + btv->errors=0; + btv->needs_restart=0; + /* i2c */ btv->tuner_type=-1; init_bttv_i2c(btv); @@ -3450,7 +3507,7 @@ { u32 stat,astat; u32 dstat; - int count; + int count,i; struct bttv *btv; btv=(struct bttv *)dev_id; @@ -3490,24 +3547,43 @@ btv->field++; } if (astat&(BT848_INT_SCERR|BT848_INT_OCERR)) { - printk("bttv%d: irq:%s%s risc_count=%08x\n",btv->nr, - (astat&BT848_INT_SCERR) ? " SCERR" : "", - (astat&BT848_INT_OCERR) ? " OCERR" : "", - btread(BT848_RISC_COUNT)); - bt848_set_risc_jmps(btv,0); - btwrite(0, BT848_SRESET); - btwrite(virt_to_bus(btv->risc_jmp), - BT848_RISC_STRT_ADD); - bt848_set_geo(btv,0); - bt848_set_risc_jmps(btv,-1); -#if 0 - wake_up_interruptible(&btv->vbiq); - wake_up_interruptible(&btv->capq); -#endif + if (verbose) + printk("bttv%d: irq:%s%s risc_count=%08x\n", + btv->nr, + (astat&BT848_INT_SCERR) ? " SCERR" : "", + (astat&BT848_INT_OCERR) ? " OCERR" : "", + btread(BT848_RISC_COUNT)); + btv->errors++; + if (btv->errors < BTTV_ERRORS) { + btand(~15, BT848_GPIO_DMA_CTL); + btwrite(virt_to_bus(btv->risc_jmp+2), + BT848_RISC_STRT_ADD); + bt848_set_geo(btv,0); + bt848_set_risc_jmps(btv,-1); + } else { + if (verbose) + printk("bttv%d: aiee: error loops\n",btv->nr); + /* cancel all outstanding grab requests */ + btv->gq_in = 0; + btv->gq_out = 0; + btv->gq_grab = -1; + for (i = 0; i < gbuffers; i++) + if (btv->gbuf[i].stat == GBUFFER_GRABBING) + btv->gbuf[i].stat = GBUFFER_ERROR; + /* disable DMA */ + btv->risc_cap_odd = 0; + btv->risc_cap_even = 0; + bt848_set_risc_jmps(btv,0); + + btv->needs_restart = 1; + wake_up_interruptible(&btv->vbiq); + wake_up_interruptible(&btv->capq); + } } if (astat&BT848_INT_RISCI) { - IDEBUG(printk ("bttv%d: IRQ_RISCI\n", btv->nr)); + if (debug > 1) + printk("bttv%d: IRQ_RISCI\n",btv->nr); /* captured VBI frame */ if (stat&(1<<28)) @@ -3519,11 +3595,12 @@ } /* captured full frame */ - if (stat&(2<<28)) + if (stat&(2<<28) && btv->gq_grab != -1) { btv->last_field=btv->field; if (debug) printk("bttv%d: cap irq: done %d\n",btv->nr,btv->gq_grab); + do_gettimeofday(&btv->gbuf[btv->gq_grab].tv); btv->gbuf[btv->gq_grab].stat = GBUFFER_DONE; btv->gq_grab = -1; if (btv->gq_in != btv->gq_out) --- linux-2.3.51/drivers/char/bttv.h Sat Mar 11 13:31:31 2000 +++ linux/drivers/char/bttv.h Thu Mar 16 21:19:14 2000 @@ -21,7 +21,7 @@ #ifndef _BTTV_H_ #define _BTTV_H_ -#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,21) +#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,23) #include #include @@ -112,7 +112,8 @@ #define GBUFFER_GRABBING 1 #define GBUFFER_DONE 2 #define GBUFFER_ERROR 3 - + struct timeval tv; + u16 width; u16 height; u16 fmt; @@ -192,6 +193,9 @@ unsigned int last_field; /* number of last grabbed field */ int i2c_command; int triton1; + + int errors; + int needs_restart; WAIT_QUEUE gpioq; int shutdown; --- linux-2.3.51/Documentation/video4linux/bttv/README Wed Mar 8 23:20:41 2000 +++ linux/Documentation/video4linux/bttv/README Thu Mar 16 21:19:14 2000 @@ -17,7 +17,7 @@ CONFIG_I2C_ALGOBIT=m The latest bttv version is available here: - http://www.in-berlin.de/User/kraxel/v4l/ + http://me.in-berlin.de/~kraxel/bttv.html You'll find Ralphs original (mostly outdated) documentation in the ralphs-doc subdirectory.