diff options
author | Florian Schirmer <devnull@localhost> | 2003-01-25 16:25:48 +0000 |
---|---|---|
committer | Florian Schirmer <devnull@localhost> | 2003-01-25 16:25:48 +0000 |
commit | 20f38ee4089ddef8a057920c8ded5b67fd24bd60 (patch) | |
tree | ae376aa3626c959aa6d64d1d74dfc1a1db366116 | |
parent | 79dbc09e09d48ebb4a087f003789a8bf22d2cc13 (diff) | |
download | mediapointer-dvb-s2-20f38ee4089ddef8a057920c8ded5b67fd24bd60.tar.gz mediapointer-dvb-s2-20f38ee4089ddef8a057920c8ded5b67fd24bd60.tar.bz2 |
- Rewritten RISC programm
- Push sync handling down to DVB API
- Major fixes
-rw-r--r-- | linux/drivers/media/dvb/bt8xx/bt878.c | 390 | ||||
-rw-r--r-- | linux/drivers/media/dvb/bt8xx/bt878.h | 23 | ||||
-rw-r--r-- | linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c | 179 | ||||
-rw-r--r-- | linux/drivers/media/dvb/bt8xx/dvb-bt8xx.h | 1 |
4 files changed, 200 insertions, 393 deletions
diff --git a/linux/drivers/media/dvb/bt8xx/bt878.c b/linux/drivers/media/dvb/bt8xx/bt878.c index 8ade22161..f24eb8705 100644 --- a/linux/drivers/media/dvb/bt8xx/bt878.c +++ b/linux/drivers/media/dvb/bt8xx/bt878.c @@ -84,228 +84,135 @@ extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val) #endif #define dprintk if(bt878_debug) printk -/*******************************/ -/* Memory management functions */ -/*******************************/ +static void bt878_mem_free(struct bt878 *bt) +{ -#define MDEBUG(x) do { } while(0) /* Debug memory management */ + if (bt->buf_cpu) { -/* All taken from [DaveM] from the bttv driver - * I will not pretend that I understand this, but - * it seems to work. - * - * The code used to assume that the kernel vmalloc mappings - * existed in the page tables of every process, this is simply - * not guarenteed. We now use pgd_offset_k which is the - * defined way to get at the kernel page tables. - */ + pci_free_consistent(bt->dev, bt->buf_size, bt->buf_cpu, bt->buf_dma); + bt->buf_cpu = NULL; -/* Given PGD from the address space's page table, return the kernel - * virtual mapping of the physical memory mapped at ADR. - */ -static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) -{ - unsigned long ret = 0UL; - pmd_t *pmd; - pte_t *ptep, pte; - - if (!pgd_none(*pgd)) { - pmd = pmd_offset(pgd, adr); - if (!pmd_none(*pmd)) { - ptep = pte_offset(pmd, adr); - pte = *ptep; - if(pte_present(pte)) { - ret = (unsigned long) page_address(pte_page(pte)); - ret |= (adr & (PAGE_SIZE - 1)); - - } - } - } - MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret)); - return ret; + } + + if (bt->risc_cpu) { + + pci_free_consistent(bt->dev, bt->risc_size, bt->risc_cpu, bt->risc_dma); + bt->risc_cpu = NULL; + + } + } -static inline unsigned long uvirt_to_bus(unsigned long adr) +static int bt878_mem_alloc(struct bt878 *bt) { - unsigned long kva, ret; - kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr); - ret = virt_to_bus((void *)kva); - MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret)); - return ret; + if (!bt->buf_cpu) { + + bt->buf_size = 128 * 1024; + + bt->buf_cpu = pci_alloc_consistent(bt->dev, bt->buf_size, &bt->buf_dma); + + if (!bt->buf_cpu) + return -ENOMEM; + + memset(bt->buf_cpu, 0, bt->buf_size); + + } + + if (!bt->risc_cpu) { + + bt->risc_size = PAGE_SIZE; + bt->risc_cpu = pci_alloc_consistent(bt->dev, bt->risc_size, &bt->risc_dma); + + if (!bt->risc_cpu) { + + bt878_mem_free(bt); + + return -ENOMEM; + + } + + memset(bt->risc_cpu, 0, bt->risc_size); + + } + + return 0; + } -static inline unsigned long kvirt_to_bus(unsigned long adr) -{ - unsigned long va, kva, ret; +/* RISC instructions */ +#define RISC_WRITE (0x01 << 28) +#define RISC_JUMP (0x07 << 28) +#define RISC_SYNC (0x08 << 28) - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); - ret = virt_to_bus((void *)kva); - MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret)); - return ret; -} +/* RISC bits */ +#define RISC_WR_SOL (1 << 27) +#define RISC_WR_EOL (1 << 26) +#define RISC_IRQ (1 << 24) +#define RISC_STATUS(status) ((((~status) & 0x0F) << 20) | ((status & 0x0F) << 16)) +#define RISC_SYNC_RESYNC (1 << 15) +#define RISC_SYNC_FM1 0x06 +#define RISC_SYNC_VRO 0x0C -/* Here we want the physical address of the memory. - * This is used when initializing the contents of the - * area and marking the pages as reserved. - */ -static inline unsigned long kvirt_to_pa(unsigned long adr) +#define RISC_FLUSH() bt->risc_pos = 0 +#define RISC_INSTR(instr) bt->risc_cpu[bt->risc_pos++] = cpu_to_le32(instr) + +static int bt878_make_risc(struct bt878 *bt) { - unsigned long va, kva, ret; - va = VMALLOC_VMADDR(adr); - kva = uvirt_to_kva(pgd_offset_k(va), va); - ret = __pa(kva); - MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret)); - return ret; -} + u32 buf_pos = 0; + u32 line; -static void * rvmalloc(signed long size) -{ - void * mem; - unsigned long adr, page; + bt->block_bytes = bt->buf_size >> 4; + bt->block_count = 1 << 4; + bt->line_bytes = bt->block_bytes; + bt->line_count = bt->block_count; - mem=vmalloc_32(size); - if (mem) - { - memset(mem, 0, size); /* Clear the ram out, no junk to the user */ - adr=(unsigned long) mem; - while (size > 0) - { - page = kvirt_to_pa(adr); - mem_map_reserve(virt_to_page(__va(page))); - adr+=PAGE_SIZE; - size-=PAGE_SIZE; - } - } - return mem; -} + while (bt->line_bytes > 4095) { -static void rvfree(void * mem, signed long size) -{ - unsigned long adr, page; - - if (mem) - { - adr=(unsigned long) mem; - while (size > 0) - { - page = kvirt_to_pa(adr); - mem_map_unreserve(virt_to_page(__va(page))); - adr+=PAGE_SIZE; - size-=PAGE_SIZE; - } - vfree(mem); - } -} + bt->line_bytes >>= 1; + bt->line_count <<= 1; -/*****************************/ -/* Buffer setup function(s) */ -/*****************************/ + } -int bt878_get_buffers(struct bt878 *bt, int bpl, int lpf, int nbufs, int sync) -{ - /* try to allocate nbufs buffers, 2<=nbufs<=16. Each buffer is - a "frame" bpl bytes wide and lpf lines high. - The buffers will be contiguous in kernel virtual space, but - will consist of discontinuous physical pages. - Set up a DMA program to read all these buffers in sequence, - and generate an interrupt at the start of each buffer. - if sync==1, insert a sync RISC op at the start of each buffer, - else don't. - */ - - unsigned long *pc, *pc2; - unsigned char *bp; - int i, j, size, rest; - unsigned long op; - - dprintk("bt878 debug: bt878_get_buffers(%p, bpl=0x%x, lpf=0x%x, n=0x%x\n",bt,bpl,lpf,nbufs); - if(nbufs<2||nbufs>16) return -EINVAL; - if(bpl<0||bpl>4095) return -EINVAL; - if(lpf*nbufs<0||lpf*nbufs>255) return -EINVAL; - if(!bt) return -ENXIO; - - /* stop a possibly running DMA operation */ - btand(~0x0f,BT878_AGPIO_DMA_CTL); - i=btread(BT878_AGPIO_DMA_CTL); - - if(bt->buffer) {rvfree(bt->buffer,bt->allocbufsize); bt->buffer=0; } - if(bt->riscprog) {rvfree(bt->riscprog,PAGE_SIZE); bt->riscprog=0;} - - bt->framesize=bpl*lpf; - bt->buffersize=bt->framesize*nbufs; - bt->allocbufsize=(bpl*lpf*nbufs); - if(bt->allocbufsize&~PAGE_MASK) - bt->allocbufsize=(bt->allocbufsize&PAGE_MASK)+PAGE_SIZE; - dprintk("bt878 debug: allocating 0x%x bytes (min was 0x%x)\n",bt->allocbufsize,(bpl*lpf*nbufs)); - if(!(bt->buffer=rvmalloc(bt->allocbufsize))) { - return -ENOMEM; - } - if(!(bt->riscprog=rvmalloc(PAGE_SIZE))) { - goto fail1; - } - - dprintk("bt878 debug: buffer=%p, riscprog=%p\n",bt->buffer,bt->riscprog); - /* ok. We have the memory for the buffers. Let us set up the DMA prog */ - pc=bt->riscprog; - bp=bt->buffer; - /* sync operation at the beginning of the program */ - *pc++=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC| - BT848_FIFO_STATUS_FM1|(0xf<<20)); - *pc++=0; - for(i=0;i<nbufs;i++) { - for(j=0;j<lpf;j++) { - size=bpl; - rest=PAGE_SIZE-((unsigned int)bp&(~PAGE_MASK)); - if(rest<size) size=rest; - op=BT848_RISC_WRITE|((~i)&0x0f)<<20|(i&0x0f)<<16|size - |BT848_RISC_SOL; - if(j==0) op|=BT848_RISC_IRQ; - if(size==bpl) op|=BT848_RISC_EOL; - *pc++=cpu_to_le32(op); - *pc++=cpu_to_le32(kvirt_to_bus((unsigned long)bp)); - bp+=size; - if(size<bpl) { - size=bpl-size; - op=BT848_RISC_WRITE|((~i)&0x0f)<<20|(i&0x0f)<<16|size - |BT848_RISC_EOL; - *pc++=cpu_to_le32(op); - *pc++=cpu_to_le32(kvirt_to_bus((unsigned long)bp)); - bp+=size; - if((pc-(unsigned long *)bt->riscprog)*sizeof(long)>PAGE_SIZE) goto fail2; - } - } - if(sync) { - *pc++=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC| - BT848_FIFO_STATUS_FM1); - *pc++=0; - } - } - *pc++=cpu_to_le32(BT848_RISC_JUMP); - *pc++=cpu_to_le32(kvirt_to_bus((unsigned long)bt->riscprog)); - - btwrite(cpu_to_le32(bpl|((lpf*nbufs)<<16)),BT878_APACK_LEN); - btwrite(cpu_to_le32(kvirt_to_bus((unsigned long)bt->riscprog)),BT878_ARISC_START); - - if(bt878_debug) { - for(pc2=bt->riscprog;pc2<pc;pc2++) printk("riscprog[%3.3x]=%8.8lx\n", - (pc2-(unsigned long *)(bt->riscprog)),*pc2); - } - - bt->nbuffers=nbufs; - - return 0; - -fail2: - if(bt->riscprog) {rvfree(bt->riscprog,PAGE_SIZE); bt->riscprog=0;} -fail1: - if(bt->buffer) {rvfree(bt->buffer,bt->allocbufsize); bt->buffer=0; bt->allocbufsize=0;} - return -ENOMEM; + if (bt->line_count > 255) { + + printk("bt878: buffer size error!\n"); + + return -EINVAL; + + } + + RISC_FLUSH(); + + RISC_INSTR(RISC_SYNC | RISC_SYNC_FM1); + RISC_INSTR(0); + + for (line = 0; line < bt->line_count; line++) { + + // At the beginning of every block we issue an IRQ with previous (finished) block number set + if (!(buf_pos % bt->block_bytes)) + RISC_INSTR(RISC_WRITE | RISC_WR_SOL | RISC_WR_EOL | RISC_IRQ | RISC_STATUS(((buf_pos / bt->block_bytes) + (bt->block_count - 1)) % bt->block_count) | bt->line_bytes); + else + RISC_INSTR(RISC_WRITE | RISC_WR_SOL | RISC_WR_EOL | bt->line_bytes); + + RISC_INSTR(bt->buf_dma + buf_pos); + + buf_pos += bt->line_bytes; + + } + + RISC_INSTR(RISC_SYNC | RISC_SYNC_VRO); + RISC_INSTR(0); + + RISC_INSTR(RISC_JUMP); + RISC_INSTR(bt->risc_dma); + + btwrite((bt->line_count << 16) | bt->line_bytes, BT878_APACK_LEN); + + return 0; + } - -EXPORT_SYMBOL(bt878_get_buffers); /*****************************/ /* Start/Stop grabbing funcs */ @@ -313,33 +220,49 @@ EXPORT_SYMBOL(bt878_get_buffers); void bt878_start(struct bt878 *bt, u32 controlreg) { - if(!bt->buffer||!bt->riscprog) bt878_get_buffers(bt,0x400,1,4,0); - /* this call to bt878_get_buffers ought to succeed... */ + dprintk("bt878 debug: bt878_start (ctl=%8.8x)\n",controlreg); - controlreg&=~0x1f; - controlreg|=0x1b; - btwrite(cpu_to_le32(kvirt_to_bus((unsigned long)bt->riscprog)), - BT878_ARISC_START); - if(bt->tasklet) tasklet_enable(bt->tasklet); + + controlreg &= ~0x1F; + controlreg |= 0x1B; + + btwrite(cpu_to_le32(bt->risc_dma), BT878_ARISC_START); + + if(bt->tasklet) + tasklet_enable(bt->tasklet); + btwrite(0x000ff800,BT878_AINT_MASK); btwrite(controlreg,BT878_AGPIO_DMA_CTL); + } void bt878_stop(struct bt878 *bt) { + u32 stat; - int i=0; + int i = 0; - btwrite(0,BT878_AINT_MASK); - btand(~0x1f,BT878_AGPIO_DMA_CTL); - dprintk("bt878 debug: bt878_stop\n"); - do { - stat=btread(BT878_AINT_STAT); - if(!(stat&BT878_ARISC_EN)) break; - i++; - } while(i<500); - if(bt->tasklet) tasklet_disable(bt->tasklet); - dprintk("bt878(%d) debug: bt878_stop, i=%d, stat=0x%8.8x\n",bt->nr,i,stat); + dprintk("bt878 debug: bt878_stop\n"); + + btwrite(0, BT878_AINT_MASK); + btand(~0x1F, BT878_AGPIO_DMA_CTL); + + do { + + stat = btread(BT878_AINT_STAT); + + if (!(stat&BT878_ARISC_EN)) + break; + + i++; + + } while (i < 500); + + if(bt->tasklet) + tasklet_disable(bt->tasklet); + + dprintk("bt878(%d) debug: bt878_stop, i=%d, stat=0x%8.8x\n",bt->nr,i,stat); + } EXPORT_SYMBOL(bt878_start); @@ -356,7 +279,7 @@ static void bt878_irq(int irq, void *dev_id, struct pt_regs * regs) struct bt878 *bt; bt=(struct bt878 *)dev_id; - + count=0; while(1) { stat=btread(BT878_AINT_STAT); @@ -397,7 +320,7 @@ static void bt878_irq(int irq, void *dev_id, struct pt_regs * regs) } if(astat&BT878_ARISCI) { spin_lock(&bt->s_lock); - bt->writebuf=(stat&BT878_ARISCS)>>28; + bt->finished_block = (stat & BT878_ARISCS) >> 28; spin_unlock(&bt->s_lock); wake_up_interruptible(&bt->readq); if(bt->tasklet) tasklet_schedule(bt->tasklet); @@ -496,18 +419,26 @@ static int __devinit bt878_probe(struct pci_dev *dev, const struct pci_device_id return -EIO; } */ - bt->nbuffers=bt->allocbufsize=0; - bt->buffer=bt->riscprog=0; + if ((result = bt878_mem_alloc(bt))) { + + printk("bt878: failed to allocate memory!\n"); + + goto fail2; + + } + + bt878_make_risc(bt); + btwrite(0,BT878_AINT_MASK); bt878_num++; return 0; -/* fail2: + fail2: free_irq(bt->irq,bt); -*/ fail1: + fail1: release_mem_region(pci_resource_start(bt->dev,0), pci_resource_len(bt->dev,0)); return result; @@ -520,7 +451,7 @@ static void __devexit bt878_remove(struct pci_dev *pci_dev) if (bt878_verbose) printk("bt878(%d): unloading\n",bt->nr); - + /* turn off all capturing, DMA and IRQs */ btand(~15, BT878_AGPIO_DMA_CTL); @@ -547,8 +478,7 @@ static void __devexit bt878_remove(struct pci_dev *pci_dev) */ bt->shutdown=1; - if(bt->buffer) {rvfree(bt->buffer,bt->allocbufsize); bt->buffer=0;} - if(bt->riscprog) {rvfree(bt->riscprog,PAGE_SIZE); bt->riscprog=0;} + bt878_mem_free(bt); pci_set_drvdata(pci_dev, NULL); return; diff --git a/linux/drivers/media/dvb/bt8xx/bt878.h b/linux/drivers/media/dvb/bt8xx/bt878.h index adbb74145..5676f7708 100644 --- a/linux/drivers/media/dvb/bt8xx/bt878.h +++ b/linux/drivers/media/dvb/bt8xx/bt878.h @@ -87,12 +87,22 @@ struct bt878 { unsigned int irq; unsigned long bt878_adr; unsigned char *bt878_mem; - int nbuffers; - int buffersize; - int framesize; - int allocbufsize; - void *buffer; - void *riscprog; + + u32 finished_block; + u32 last_block; + u32 block_count; + u32 block_bytes; + u32 line_bytes; + u32 line_count; + + u32 buf_size; + u8 *buf_cpu; + dma_addr_t buf_dma; + + u32 risc_size; + u32 *risc_cpu; + dma_addr_t risc_dma; + u32 risc_pos; int writebuf; int readbuf; @@ -103,7 +113,6 @@ struct bt878 { int shutdown; }; -int bt878_get_buffers(struct bt878 *bt, int bpl, int lpf, int nbufs, int sync); void bt878_start(struct bt878 *bt, u32 controlreg); void bt878_stop(struct bt878 *bt); #endif diff --git a/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c index 1f137f3c6..5f09988ac 100644 --- a/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -2,9 +2,6 @@ * Bt8xx based DVB adapter driver * * Copyright (C) 2002,2003 Florian Schirmer <schirmer@taytron.net> - * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de> - * Copyright (C) 1999-2001 Ralph Metzler & Marcus Metzler for convergence integrated media GmbH - * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -45,157 +42,24 @@ extern struct i2c_adapter *bttv_get_i2c_adap(unsigned int card); static LIST_HEAD(card_list); static int debug = 0; -#define TS_SIZE 188 - static void dvb_bt8xx_task(unsigned long data) { - struct bt878 *bt = &bt878[0]; - struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *)data; - int rb; - u8 *rp1=0, *rp2=0; - int count=0, count2=0, tp=0; - int i, ii; - int sync; - u8 tsbuf[TS_SIZE]; /* a buffer to make a single TS packet crossing the wraparound */ - /* point of the circular buffer contiguous in memory again */ - - if (!card->active) - return; - - dprintk("pctv debug: tasklet called, data=0x%8.8lx\n",data); -// bt=dvb->bt; - -// if(!dvb->feeding) return; - - spin_lock_irq(&bt->s_lock); - - /* the dma overtook us, or we overtook the dma? */ - if(bt->readbuf==bt->writebuf|| - bt->readbuf==(bt->writebuf+1)%bt->nbuffers) { - spin_unlock_irq(&bt->s_lock); - dprintk("pctv debug: tasklet: no do r=%d, w=%d\n",bt->readbuf, bt->writebuf); - return; - } - - /* are we frame synced? */ - if(((unsigned char *)bt->buffer)[bt->readbuf*bt->framesize+bt->readptr]!=0x47) { - dprintk("pctv debug: tasklet: searching for sync\n"); - sync=TS_SIZE*2; - do { - if(sync--<=0) break; - if(++bt->readptr>=bt->framesize) { - bt->readptr=0; - if(++bt->readbuf>=bt->nbuffers) bt->readbuf=0; - if(bt->readbuf==bt->writebuf|| - bt->readbuf==(bt->writebuf+1)%bt->nbuffers) { - spin_unlock_irq(&bt->s_lock); - printk("pctv debug: tasklet: dma overtook us. r=%d, w=%d\n",bt->readbuf,bt->writebuf); - return; - } - } - if(((u8 *)bt->buffer)[bt->readbuf*bt->framesize+bt->readptr]!=0x47) continue; - /* ok, we have found a 0x47. See whether at TS_SIZE there is another 0x47 */ - if(bt->readptr+TS_SIZE<bt->framesize&&((u8 *)bt->buffer)[bt->readbuf*bt->framesize+bt->readptr+TS_SIZE]==0x47) { - sync=0; - break; - } - if(bt->readptr+TS_SIZE>=bt->framesize) { - /* the payload area of a TS packet may contain a 0x47. To be sure we - are not looking at such a 0x47, check if there is another one exactly - TS_SIZE further. But if this crosses a frame boundary, check if the - frame is free to access, and handle buffer wraparound. I did not yet - have the patience to do this :-( - */ - printk("pctv: panic, less than 188 Bytes left and no sync. Program me!\n"); - bt->readptr++; - spin_unlock_irq(&bt->s_lock); - return; - } - } while(sync); - dprintk("pctv tasklet: end of sync search @%d[%x]=%x\n", - bt->readbuf,bt->readptr, - ((u8 *)bt->buffer)[bt->readbuf*bt->framesize+bt->readptr]); - } - - /* now find out how many TS frames are available in the buffer */ - rp1=(u8 *)bt->buffer+(bt->readbuf*bt->framesize+bt->readptr); - if(*rp1!=0x47) { - spin_unlock_irq(&bt->s_lock); - return; - } - - count=bt->writebuf-bt->readbuf; - if(count<0) { - count=bt->nbuffers-bt->readbuf; - count2=bt->writebuf; - } - count=count*bt->framesize-bt->readptr; - count/=TS_SIZE; - if(count2) { - rb=bt->readbuf*bt->framesize+bt->readptr+count*TS_SIZE; - while(rb<bt->buffersize&&tp<TS_SIZE) { - tsbuf[tp++]=((u8 *)bt->buffer)[rb++]; - } - rb=0; - while(tp<TS_SIZE) { - tsbuf[tp++]=((u8 *)bt->buffer)[rb++]; - } - count2=count2*bt->framesize-rb; - count2/=TS_SIZE; - rp2=(u8 *)bt->buffer+rb; - } - - i=bt->readbuf*bt->framesize+bt->readptr+TS_SIZE*(count+count2+(tp!=0)); - dprintk("pctv debug: tasklet: i=%d (%d ts frames)\n",i,(i-bt->readbuf*bt->framesize-bt->readptr)/TS_SIZE); - if(i>=bt->buffersize) i-=bt->buffersize; - - /* update the bt878 read pointers, release the lock */ - ii=bt->readbuf; - bt->readbuf=(i/bt->framesize); - if(bt->readbuf>=bt->nbuffers) { - /* this should not happen any more */ - printk("pctv tasklet: i miscomputed bt->readbuf=0x%x>nbuffers=0x%x\n", - bt->readbuf,bt->nbuffers); - printk("pctv tasklet: readbuf %x frsize %x readptr %x count %x count2 %x\n",ii,bt->framesize,bt->readptr,count,count2); - printk("pctv tasklet: TS_SZ %x span %x i %x res readbuf %x\n",TS_SIZE,(tp!=0),i,bt->readbuf); - bt->readbuf-=bt->nbuffers; - } - bt->readptr=(i%bt->framesize); - if(bt->readptr>=bt->framesize) { - /* this should not happen at all... */ - printk("pctv tasklet: i miscomputed bt->readptr=0x%x>framesize=0x%x\n", - bt->readptr,bt->framesize); - bt->readptr-=bt->framesize; - } - - spin_unlock_irq(&bt->s_lock); - - dprintk("pctv tasklet: count1=%d, count2=%d, %sr=%d[%x]\n",count,count2,tp?"span, ":"",bt->readbuf,bt->readptr); - - /* send the first (or only) part of the buffer */ - if(count>0&&count<bt->buffersize/TS_SIZE&&*rp1==0x47) - dvb_dmx_swfilter_packets(&card->demux,rp2,count2); - else { - if(count>0)dprintk("pctv debug: tasklet: error calling demux, c=%d, *buf=0x%x\n",count,*rp1); - } - - /* if the buffer crosses the buffer-wrap, copy the one TS into a local buffer, - then send it. Copy has been done above. */ - if(tp&&tsbuf[0]==0x47) { - dvb_dmx_swfilter_packets(&card->demux,rp2,count2); - tp=0; - } else { - if(tp)dprintk("pctv debug: tasklet: error calling demux1, tsbuf[0]=0x%x\n",tsbuf[0]); - } - - /* send the third and last part of the buffer */ - if(count2>0&&count2<bt->buffersize/TS_SIZE&&*rp2==0x47) - dvb_dmx_swfilter_packets(&card->demux,rp2,count2); - else { - if(count2>0)dprintk("pctv debug: tasklet: error calling demux2, c=%d, *buf=0x%x\n",count2,*rp2); - } + struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *)data; + u8 finished_block = card->bt->finished_block; + + //printk("%d ", finished_block); + + while (card->bt->last_block != finished_block) { + + //printk("dvb_bt8xx: missed irq (%d/%d)\n", card->bt->last_block, finished_block); + + dvb_dmx_swfilter(&card->demux, &card->bt->buf_cpu[card->bt->last_block * card->bt->block_bytes], card->bt->block_bytes); + card->bt->last_block = (card->bt->last_block + 1) % card->bt->block_count; + + } + } static DECLARE_TASKLET_DISABLED(dvb_bt8xx_tasklet, dvb_bt8xx_task, 0); @@ -225,7 +89,7 @@ static int dvb_bt8xx_start_feed(struct dvb_demux_feed *dvbdmxfeed) card->active = 1; - bt878_start(&bt878[0], card->gpio_mode); +// bt878_start(card->bt, card->gpio_mode); return 0; @@ -245,7 +109,7 @@ static int dvb_bt8xx_stop_feed(struct dvb_demux_feed *dvbdmxfeed) if (!card->active) return 0; - bt878_stop(&bt878[0]); +// bt878_stop(card->bt); card->active = 0; @@ -259,11 +123,12 @@ static int __init dvb_bt8xx_load(unsigned int bttv_nr, char *card_name, u32 gpio struct dvb_bt8xx_card *card; int result; - dprintk("dvb_bt8xx: identified card%d as Nebula DigiTV DVB-T card\n", bttv_nr); + dprintk("dvb_bt8xx: identified card%d as %s\n", bttv_nr, card_name); if (!(card = kmalloc(sizeof(struct dvb_bt8xx_card), GFP_KERNEL))) return -ENOMEM; - + + card->bt = &bt878[0]; card->bttv_nr = bttv_nr; card->gpio_mode = gpio_mode; @@ -393,9 +258,9 @@ static int __init dvb_bt8xx_load(unsigned int bttv_nr, char *card_name, u32 gpio } dvb_bt8xx_tasklet.data = (long)card; - bt878[0].tasklet = &dvb_bt8xx_tasklet; + card->bt->tasklet = &dvb_bt8xx_tasklet; - bt878_get_buffers(&bt878[0], 0xC00, 8, 4, 0); + bt878_start(card->bt, card->gpio_mode); list_add_tail(&card->list, &card_list); @@ -415,6 +280,8 @@ static void dvb_bt8xx_close(void) dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr); + bt878_stop(card->bt); + card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem); card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw); dvb_dmxdev_release(&card->dmxdev); diff --git a/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.h index fe776a29c..2401b42d8 100644 --- a/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.h +++ b/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.h @@ -30,6 +30,7 @@ struct dvb_bt8xx_card { struct list_head list; u8 active; struct dvb_adapter *adapter; + struct bt878 *bt; unsigned int bttv_nr; struct dvb_demux demux; dmxdev_t dmxdev; |