diff options
Diffstat (limited to 'linux/drivers/media/dvb/bt8xx/bt878.c')
-rw-r--r-- | linux/drivers/media/dvb/bt8xx/bt878.c | 466 |
1 files changed, 224 insertions, 242 deletions
diff --git a/linux/drivers/media/dvb/bt8xx/bt878.c b/linux/drivers/media/dvb/bt8xx/bt878.c index de4906222..09c5dd38f 100644 --- a/linux/drivers/media/dvb/bt8xx/bt878.c +++ b/linux/drivers/media/dvb/bt8xx/bt878.c @@ -50,10 +50,11 @@ unsigned int bt878_verbose = 1; unsigned int bt878_debug = 0; -MODULE_PARM(bt878_verbose,"i"); -MODULE_PARM_DESC(bt878_verbose,"verbose startup messages, default is 1 (yes)"); -MODULE_PARM(bt878_debug,"i"); -MODULE_PARM_DESC(bt878_debug,"debug messages, default is 0 (no)"); +MODULE_PARM(bt878_verbose, "i"); +MODULE_PARM_DESC(bt878_verbose, + "verbose startup messages, default is 1 (yes)"); +MODULE_PARM(bt878_debug, "i"); +MODULE_PARM_DESC(bt878_debug, "debug messages, default is 0 (no)"); MODULE_LICENSE("GPL"); int bt878_num; @@ -62,13 +63,14 @@ struct bt878 bt878[BT878_MAX]; EXPORT_SYMBOL(bt878_num); EXPORT_SYMBOL(bt878); -#if defined(__powerpc__) /* big-endian */ +#if defined(__powerpc__) /* big-endian */ extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val) { - __asm__ __volatile__ ("stwbrx %1,0,%2" : \ - "=m" (*addr) : "r" (val), "r" (addr)); - __asm__ __volatile__ ("eieio" : : : "memory"); + __asm__ __volatile__("stwbrx %1,0,%2":"=m"(*addr):"r"(val), + "r"(addr)); + __asm__ __volatile__("eieio":::"memory"); } + #define btwrite(dat,adr) io_st_le32((unsigned *)(bt->bt878_mem+(adr)),(dat)) #define btread(adr) ld_le32((unsigned *)(bt->bt878_mem+(adr))) #else @@ -87,58 +89,49 @@ extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val) static void bt878_mem_free(struct bt878 *bt) { - if (bt->buf_cpu) { - - pci_free_consistent(bt->dev, bt->buf_size, bt->buf_cpu, bt->buf_dma); + pci_free_consistent(bt->dev, bt->buf_size, bt->buf_cpu, + bt->buf_dma); bt->buf_cpu = NULL; - } - + if (bt->risc_cpu) { - - pci_free_consistent(bt->dev, bt->risc_size, bt->risc_cpu, bt->risc_dma); + pci_free_consistent(bt->dev, bt->risc_size, bt->risc_cpu, + bt->risc_dma); bt->risc_cpu = NULL; - } - } static int bt878_mem_alloc(struct bt878 *bt) { - if (!bt->buf_cpu) { - bt->buf_size = 128 * 1024; - bt->buf_cpu = pci_alloc_consistent(bt->dev, bt->buf_size, &bt->buf_dma); - + 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); - + 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; - } /* RISC instructions */ @@ -160,59 +153,54 @@ static int bt878_mem_alloc(struct bt878 *bt) static int bt878_make_risc(struct bt878 *bt) { - u32 buf_pos = 0; u32 line; bt->block_bytes = bt->buf_size >> 4; bt->block_count = 1 << 4; - bt->line_bytes = bt->block_bytes; - bt->line_count = bt->block_count; + bt->line_bytes = bt->block_bytes; + bt->line_count = bt->block_count; while (bt->line_bytes > 4095) { - bt->line_bytes >>= 1; bt->line_count <<= 1; - } 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); + 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(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(RISC_JUMP); RISC_INSTR(bt->risc_dma); btwrite((bt->line_count << 16) | bt->line_bytes, BT878_APACK_LEN); - - return 0; - + return 0; } /*****************************/ @@ -221,43 +209,36 @@ static int bt878_make_risc(struct bt878 *bt) void bt878_start(struct bt878 *bt, u32 controlreg) { + dprintk("bt878 debug: bt878_start (ctl=%8.8x)\n", controlreg); - dprintk("bt878 debug: bt878_start (ctl=%8.8x)\n",controlreg); - controlreg &= ~0x1F; controlreg |= 0x1B; - + btwrite(cpu_to_le32(bt->risc_dma), BT878_ARISC_START); - - btwrite(0x000ff800,BT878_AINT_MASK); - btwrite(controlreg,BT878_AGPIO_DMA_CTL); - + + btwrite(0x000ff800, BT878_AINT_MASK); + btwrite(controlreg, BT878_AGPIO_DMA_CTL); } void bt878_stop(struct bt878 *bt) { - u32 stat; int i = 0; - + 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)) + if (!(stat & BT878_ARISC_EN)) break; - - i++; - + i++; } while (i < 500); - dprintk("bt878(%d) debug: bt878_stop, i=%d, stat=0x%8.8x\n",bt->nr,i,stat); - + dprintk("bt878(%d) debug: bt878_stop, i=%d, stat=0x%8.8x\n", + bt->nr, i, stat); } EXPORT_SYMBOL(bt878_start); @@ -266,69 +247,74 @@ EXPORT_SYMBOL(bt878_stop); /*****************************/ /* Interrupt service routine */ /*****************************/ - -static -irqreturn_t bt878_irq(int irq, void *dev_id, struct pt_regs * regs) + +static irqreturn_t bt878_irq(int irq, void *dev_id, struct pt_regs *regs) { - u32 stat,astat,mask; - int count; - struct bt878 *bt; - - bt=(struct bt878 *)dev_id; - - count=0; - while(1) { - stat=btread(BT878_AINT_STAT); - mask=btread(BT878_AINT_MASK); - if(!(astat=(stat&mask))) - return IRQ_NONE; /* this interrupt is not for me */ + u32 stat, astat, mask; + int count; + struct bt878 *bt; + + bt = (struct bt878 *) dev_id; + + count = 0; + while (1) { + stat = btread(BT878_AINT_STAT); + mask = btread(BT878_AINT_MASK); + if (!(astat = (stat & mask))) + return IRQ_NONE; /* this interrupt is not for me */ /* dprintk("bt878(%d) debug: irq count %d, stat 0x%8.8x, mask 0x%8.8x\n",bt->nr,count,stat,mask); */ - btwrite(astat,BT878_AINT_STAT); /* try to clear interupt condition */ - - - if(astat&(BT878_ASCERR|BT878_AOCERR)) { - if(bt878_verbose) { + btwrite(astat, BT878_AINT_STAT); /* try to clear interupt condition */ + + + if (astat & (BT878_ASCERR | BT878_AOCERR)) { + if (bt878_verbose) { printk("bt878(%d): irq%s%s risc_pc=%08x\n", - bt->nr, - (astat&BT878_ASCERR)?" SCERR":"", - (astat&BT878_AOCERR)?" OCERR":"", - btread(BT878_ARISC_PC)); + bt->nr, + (astat & BT878_ASCERR) ? " SCERR" : + "", + (astat & BT878_AOCERR) ? " OCERR" : + "", btread(BT878_ARISC_PC)); } } - if(astat&(BT878_APABORT|BT878_ARIPERR|BT878_APPERR)) { - if(bt878_verbose) { - printk("bt878(%d): irq%s%s%s risc_pc=%08x\n", - bt->nr, - (astat&BT878_APABORT)?" PABORT":"", - (astat&BT878_ARIPERR)?" RIPERR":"", - (astat&BT878_APPERR)?" PPERR":"", - btread(BT878_ARISC_PC)); + if (astat & (BT878_APABORT | BT878_ARIPERR | BT878_APPERR)) { + if (bt878_verbose) { + printk + ("bt878(%d): irq%s%s%s risc_pc=%08x\n", + bt->nr, + (astat & BT878_APABORT) ? " PABORT" : + "", + (astat & BT878_ARIPERR) ? " RIPERR" : + "", + (astat & BT878_APPERR) ? " PPERR" : + "", btread(BT878_ARISC_PC)); } } - if(astat&(BT878_AFDSR|BT878_AFTRGT|BT878_AFBUS)) { - if(bt878_verbose) { - printk("bt878(%d): irq%s%s%s risc_pc=%08x\n", - bt->nr, - (astat&BT878_AFDSR)?" FDSR":"", - (astat&BT878_AFTRGT)?" FTRGT":"", - (astat&BT878_AFBUS)?" FBUS":"", - btread(BT878_ARISC_PC)); + if (astat & (BT878_AFDSR | BT878_AFTRGT | BT878_AFBUS)) { + if (bt878_verbose) { + printk + ("bt878(%d): irq%s%s%s risc_pc=%08x\n", + bt->nr, + (astat & BT878_AFDSR) ? " FDSR" : "", + (astat & BT878_AFTRGT) ? " FTRGT" : + "", + (astat & BT878_AFBUS) ? " FBUS" : "", + btread(BT878_ARISC_PC)); } } - if(astat&BT878_ARISCI) { + if (astat & BT878_ARISCI) { bt->finished_block = (stat & BT878_ARISCS) >> 28; tasklet_schedule(&bt->tasklet); break; } count++; - if(count>20) { - btwrite(0,BT878_AINT_MASK); - printk(KERN_ERR - "bt878(%d): IRQ lockup, cleared int mask\n", bt->nr); + if (count > 20) { + btwrite(0, BT878_AINT_MASK); + printk(KERN_ERR + "bt878(%d): IRQ lockup, cleared int mask\n", + bt->nr); break; } } - return IRQ_HANDLED; } @@ -336,77 +322,79 @@ irqreturn_t bt878_irq(int irq, void *dev_id, struct pt_regs * regs) /* PCI device handling */ /***********************/ -static int __devinit bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) +static int __devinit bt878_probe(struct pci_dev *dev, + const struct pci_device_id *pci_id) { - int result; - unsigned char lat; - struct bt878 *bt; + int result; + unsigned char lat; + struct bt878 *bt; #if defined(__powerpc__) - unsigned int cmd; + unsigned int cmd; #endif - printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n", bt878_num); - - bt=&bt878[bt878_num]; - bt->dev=dev; - bt->nr = bt878_num; - bt->shutdown=0; - - bt->id=dev->device; - bt->irq=dev->irq; - bt->bt878_adr=pci_resource_start(dev,0); - if (pci_enable_device(dev)) - return -EIO; - if (!request_mem_region(pci_resource_start(dev,0), - pci_resource_len(dev,0), - "bt878")) { - return -EBUSY; - } + printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n", + bt878_num); + + bt = &bt878[bt878_num]; + bt->dev = dev; + bt->nr = bt878_num; + bt->shutdown = 0; + + bt->id = dev->device; + bt->irq = dev->irq; + bt->bt878_adr = pci_resource_start(dev, 0); + if (pci_enable_device(dev)) + return -EIO; + if (!request_mem_region(pci_resource_start(dev, 0), + pci_resource_len(dev, 0), "bt878")) { + return -EBUSY; + } + + pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision); + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + printk(KERN_INFO "bt878(%d): Bt%x (rev %d) at %02x:%02x.%x, ", + bt878_num, bt->id, bt->revision, dev->bus->number, + PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + printk("irq: %d, latency: %d, memory: 0x%lx\n", + bt->irq, lat, bt->bt878_adr); - pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision); - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); - printk(KERN_INFO "bt878(%d): Bt%x (rev %d) at %02x:%02x.%x, ", - bt878_num,bt->id, bt->revision, dev->bus->number, - PCI_SLOT(dev->devfn),PCI_FUNC(dev->devfn)); - printk("irq: %d, latency: %d, memory: 0x%lx\n", - bt->irq, lat, bt->bt878_adr); - #if defined(__powerpc__) - /* on OpenFirmware machines (PowerMac at least), PCI memory cycle */ - /* response on cards with no firmware is not enabled by OF */ - pci_read_config_dword(dev, PCI_COMMAND, &cmd); - cmd = (cmd | PCI_COMMAND_MEMORY ); - pci_write_config_dword(dev, PCI_COMMAND, cmd); + /* on OpenFirmware machines (PowerMac at least), PCI memory cycle */ + /* response on cards with no firmware is not enabled by OF */ + pci_read_config_dword(dev, PCI_COMMAND, &cmd); + cmd = (cmd | PCI_COMMAND_MEMORY); + pci_write_config_dword(dev, PCI_COMMAND, cmd); #endif #ifdef __sparc__ - bt->bt878_mem=(unsigned char *)bt->bt878_adr; + bt->bt878_mem = (unsigned char *) bt->bt878_adr; #else - bt->bt878_mem=ioremap(bt->bt878_adr, 0x1000); + bt->bt878_mem = ioremap(bt->bt878_adr, 0x1000); #endif - - /* clear interrupt mask */ - btwrite(0, BT848_INT_MASK); - - result = request_irq(bt->irq, bt878_irq, - SA_SHIRQ | SA_INTERRUPT,"bt878",(void *)bt); - if (result==-EINVAL) - { - printk(KERN_ERR "bt878(%d): Bad irq number or handler\n", - bt878_num); - goto fail1; - } - if (result==-EBUSY) - { - printk(KERN_ERR "bt878(%d): IRQ %d busy, change your PnP config in BIOS\n",bt878_num,bt->irq); - goto fail1; - } - if (result < 0) - goto fail1; - - pci_set_master(dev); - pci_set_drvdata(dev,bt); + + /* clear interrupt mask */ + btwrite(0, BT848_INT_MASK); + + result = request_irq(bt->irq, bt878_irq, + SA_SHIRQ | SA_INTERRUPT, "bt878", + (void *) bt); + if (result == -EINVAL) { + printk(KERN_ERR "bt878(%d): Bad irq number or handler\n", + bt878_num); + goto fail1; + } + if (result == -EBUSY) { + printk(KERN_ERR + "bt878(%d): IRQ %d busy, change your PnP config in BIOS\n", + bt878_num, bt->irq); + goto fail1; + } + if (result < 0) + goto fail1; + + pci_set_master(dev); + pci_set_drvdata(dev, bt); /* if(init_bt878(btv) < 0) { bt878_remove(dev); @@ -415,82 +403,76 @@ static int __devinit bt878_probe(struct pci_dev *dev, const struct pci_device_id */ 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: - free_irq(bt->irq,bt); - fail1: - release_mem_region(pci_resource_start(bt->dev,0), - pci_resource_len(bt->dev,0)); - return result; + btwrite(0, BT878_AINT_MASK); + bt878_num++; + + return 0; + + fail2: + free_irq(bt->irq, bt); + fail1: + release_mem_region(pci_resource_start(bt->dev, 0), + pci_resource_len(bt->dev, 0)); + return result; } static void __devexit bt878_remove(struct pci_dev *pci_dev) { - u8 command; - struct bt878 *bt = pci_get_drvdata(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); - - /* first disable interrupts before unmapping the memory! */ - btwrite(0, BT878_AINT_MASK); - btwrite(~0x0UL,BT878_AINT_STAT); - - /* disable PCI bus-mastering */ - pci_read_config_byte(bt->dev, PCI_COMMAND, &command); - /* Should this be &=~ ?? */ - command&=~PCI_COMMAND_MASTER; - pci_write_config_byte(bt->dev, PCI_COMMAND, command); - - free_irq(bt->irq,bt); - printk(KERN_DEBUG "bt878_mem: 0x%p.\n", bt->bt878_mem); - if (bt->bt878_mem) - iounmap(bt->bt878_mem); - - release_mem_region(pci_resource_start(bt->dev,0), - pci_resource_len(bt->dev,0)); - /* wake up any waiting processes - because shutdown flag is set, no new processes (in this queue) - are expected - */ - bt->shutdown=1; - - bt878_mem_free(bt); - - pci_set_drvdata(pci_dev, NULL); - return; + u8 command; + struct bt878 *bt = pci_get_drvdata(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); + + /* first disable interrupts before unmapping the memory! */ + btwrite(0, BT878_AINT_MASK); + btwrite(~0x0UL, BT878_AINT_STAT); + + /* disable PCI bus-mastering */ + pci_read_config_byte(bt->dev, PCI_COMMAND, &command); + /* Should this be &=~ ?? */ + command &= ~PCI_COMMAND_MASTER; + pci_write_config_byte(bt->dev, PCI_COMMAND, command); + + free_irq(bt->irq, bt); + printk(KERN_DEBUG "bt878_mem: 0x%p.\n", bt->bt878_mem); + if (bt->bt878_mem) + iounmap(bt->bt878_mem); + + release_mem_region(pci_resource_start(bt->dev, 0), + pci_resource_len(bt->dev, 0)); + /* wake up any waiting processes + because shutdown flag is set, no new processes (in this queue) + are expected + */ + bt->shutdown = 1; + bt878_mem_free(bt); + + pci_set_drvdata(pci_dev, NULL); + return; } static struct pci_device_id bt878_pci_tbl[] __devinitdata = { - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BROOKTREE_878, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0,} + {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BROOKTREE_878, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0,} }; MODULE_DEVICE_TABLE(pci, bt878_pci_tbl); static struct pci_driver bt878_pci_driver = { - name: "bt878", - id_table: bt878_pci_tbl, - probe: bt878_probe, - remove: bt878_remove, + .name = "bt878", + .id_table = bt878_pci_tbl, + .probe = bt878_probe, + .remove = bt878_remove, }; /*******************************/ @@ -499,22 +481,22 @@ static struct pci_driver bt878_pci_driver = { int bt878_init_module(void) { - bt878_num = 0; + bt878_num = 0; - printk(KERN_INFO "bt878: AUDIO driver version %d.%d.%d loaded\n", - (BT878_VERSION_CODE >> 16) & 0xff, - (BT878_VERSION_CODE >> 8) & 0xff, - BT878_VERSION_CODE & 0xff); + printk(KERN_INFO "bt878: AUDIO driver version %d.%d.%d loaded\n", + (BT878_VERSION_CODE >> 16) & 0xff, + (BT878_VERSION_CODE >> 8) & 0xff, + BT878_VERSION_CODE & 0xff); /* bt878_check_chipset(); */ - return pci_module_init(&bt878_pci_driver); + return pci_module_init(&bt878_pci_driver); } void bt878_cleanup_module(void) { - pci_unregister_driver(&bt878_pci_driver); - return; + pci_unregister_driver(&bt878_pci_driver); + return; } module_init(bt878_init_module); |