summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb
diff options
context:
space:
mode:
authorFlorian Schirmer <devnull@localhost>2003-01-25 16:25:48 +0000
committerFlorian Schirmer <devnull@localhost>2003-01-25 16:25:48 +0000
commit20f38ee4089ddef8a057920c8ded5b67fd24bd60 (patch)
treeae376aa3626c959aa6d64d1d74dfc1a1db366116 /linux/drivers/media/dvb
parent79dbc09e09d48ebb4a087f003789a8bf22d2cc13 (diff)
downloadmediapointer-dvb-s2-20f38ee4089ddef8a057920c8ded5b67fd24bd60.tar.gz
mediapointer-dvb-s2-20f38ee4089ddef8a057920c8ded5b67fd24bd60.tar.bz2
- Rewritten RISC programm
- Push sync handling down to DVB API - Major fixes
Diffstat (limited to 'linux/drivers/media/dvb')
-rw-r--r--linux/drivers/media/dvb/bt8xx/bt878.c390
-rw-r--r--linux/drivers/media/dvb/bt8xx/bt878.h23
-rw-r--r--linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c179
-rw-r--r--linux/drivers/media/dvb/bt8xx/dvb-bt8xx.h1
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;