summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb/bt8xx/bt878.c
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/bt8xx/bt878.c
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/bt8xx/bt878.c')
-rw-r--r--linux/drivers/media/dvb/bt8xx/bt878.c390
1 files changed, 160 insertions, 230 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;