diff options
author | Gerd Knorr <devnull@localhost> | 2004-07-29 21:35:48 +0000 |
---|---|---|
committer | Gerd Knorr <devnull@localhost> | 2004-07-29 21:35:48 +0000 |
commit | 38ea67b839abf0e8f150106314bc4dff33312e18 (patch) | |
tree | dbb14a85e437ad4c2eeec5876f24953c0494aaa6 /linux/drivers/media/video/cx88/cx88-core.c | |
parent | cd05362dcbcd4554765bd6d811981202533df047 (diff) | |
download | mediapointer-dvb-s2-38ea67b839abf0e8f150106314bc4dff33312e18.tar.gz mediapointer-dvb-s2-38ea67b839abf0e8f150106314bc4dff33312e18.tar.bz2 |
- cx88: big code reorganization.
- cx88: started merging blackbird patches, not working yet.
Diffstat (limited to 'linux/drivers/media/video/cx88/cx88-core.c')
-rw-r--r-- | linux/drivers/media/video/cx88/cx88-core.c | 259 |
1 files changed, 202 insertions, 57 deletions
diff --git a/linux/drivers/media/video/cx88/cx88-core.c b/linux/drivers/media/video/cx88/cx88-core.c index 800556791..31ad10653 100644 --- a/linux/drivers/media/video/cx88/cx88-core.c +++ b/linux/drivers/media/video/cx88/cx88-core.c @@ -1,3 +1,4 @@ + /* * device driver for Conexant 2388x based TV cards * driver core @@ -38,42 +39,28 @@ MODULE_LICENSE("GPL"); /* ------------------------------------------------------------------ */ -#if 0 -static unsigned int gpio_tracking = 0; -MODULE_PARM(gpio_tracking,"i"); -MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]"); - -static unsigned int ts_nr = -1; -MODULE_PARM(ts_nr,"i"); -MODULE_PARM_DESC(ts_nr,"ts device number"); - -static unsigned int vbi_nr = -1; -MODULE_PARM(vbi_nr,"i"); -MODULE_PARM_DESC(vbi_nr,"vbi device number"); - -static unsigned int radio_nr = -1; -MODULE_PARM(radio_nr,"i"); -MODULE_PARM_DESC(radio_nr,"radio device number"); - -static unsigned int oss = 0; -MODULE_PARM(oss,"i"); -MODULE_PARM_DESC(oss,"register oss devices (default: no)"); - -static unsigned int dsp_nr = -1; -MODULE_PARM(dsp_nr,"i"); -MODULE_PARM_DESC(dsp_nr,"oss dsp device number"); - -static unsigned int mixer_nr = -1; -MODULE_PARM(mixer_nr,"i"); -MODULE_PARM_DESC(mixer_nr,"oss mixer device number"); -#endif - static unsigned int core_debug = 0; MODULE_PARM(core_debug,"i"); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); +static unsigned int latency = UNSET; +MODULE_PARM(latency,"i"); +MODULE_PARM_DESC(latency,"pci latency timer"); + +static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; +MODULE_PARM(tuner,"1-" __stringify(CX88_MAXBOARDS) "i"); +MODULE_PARM_DESC(tuner,"tuner type"); + +static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; +MODULE_PARM(card,"1-" __stringify(CX88_MAXBOARDS) "i"); +MODULE_PARM_DESC(card,"card type"); + #define dprintk(fmt, arg...) if (core_debug) \ - printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg) + printk(KERN_DEBUG "%s: " fmt, core->name , ## arg) + +static unsigned int cx88_devcount; +static LIST_HEAD(cx88_devlist); +static DECLARE_MUTEX(devlist); /* ------------------------------------------------------------------ */ /* debug help functions */ @@ -259,10 +246,12 @@ cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf) * * FIFO space allocations: * channel 21 (y video) - 10.0k + * channel 22 (u video) - 2.0k + * channel 23 (v video) - 2.0k * channel 24 (vbi) - 4.0k * channels 25+26 (audio) - 0.5k - * everything else - 2.0k - * TOTAL = 29.0k + * channel 28 (mpeg) - 4.0k + * TOTAL = 25.5k * * Every channel has 160 bytes control data (64 bytes instruction * queue and 6 CDT entries), which is close to 2k total. @@ -346,9 +335,21 @@ struct sram_channel cx88_sram_channels[] = { .cnt1_reg = MO_DMA26_CNT1, .cnt2_reg = MO_DMA26_CNT2, }, + [SRAM_CH28] = { + .name = "mpeg", + .cmds_start = 0x180200, + .ctrl_start = 0x1807C0, + .cdt = 0x1807C0 + 64, + .fifo_start = 0x185600, + .fifo_size = 0x001000, + .ptr1_reg = MO_DMA28_PTR1, + .ptr2_reg = MO_DMA28_PTR2, + .cnt1_reg = MO_DMA28_CNT1, + .cnt2_reg = MO_DMA28_CNT2, + }, }; -int cx88_sram_channel_setup(struct cx8800_dev *dev, +int cx88_sram_channel_setup(struct cx88_core *core, struct sram_channel *ch, unsigned int bpl, u32 risc) { @@ -378,7 +379,7 @@ int cx88_sram_channel_setup(struct cx8800_dev *dev, /* fill registers */ cx_write(ch->ptr1_reg, ch->fifo_start); cx_write(ch->ptr2_reg, cdt); - cx_write(ch->cnt1_reg, bpl >> 3); + cx_write(ch->cnt1_reg, (bpl >> 3) -1); cx_write(ch->cnt2_reg, (lines*16) >> 3); dprintk("sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines); @@ -426,25 +427,25 @@ int cx88_risc_decode(u32 risc) return incr[risc >> 28] ? incr[risc >> 28] : 1; } -void cx88_risc_disasm(struct cx8800_dev *dev, +void cx88_risc_disasm(struct cx88_core *core, struct btcx_riscmem *risc) { unsigned int i,j,n; printk("%s: risc disasm: %p [dma=0x%08lx]\n", - dev->name, risc->cpu, (unsigned long)risc->dma); + core->name, risc->cpu, (unsigned long)risc->dma); for (i = 0; i < (risc->size >> 2); i += n) { - printk("%s: %04d: ", dev->name, i); + printk("%s: %04d: ", core->name, i); n = cx88_risc_decode(risc->cpu[i]); for (j = 1; j < n; j++) printk("%s: %04d: 0x%08x [ arg #%d ]\n", - dev->name, i+j, risc->cpu[i+j], j); + core->name, i+j, risc->cpu[i+j], j); if (risc->cpu[i] == RISC_JUMP) break; } } -void cx88_sram_channel_dump(struct cx8800_dev *dev, +void cx88_sram_channel_dump(struct cx88_core *core, struct sram_channel *ch) { static char *name[] = { @@ -463,39 +464,40 @@ void cx88_sram_channel_dump(struct cx8800_dev *dev, u32 risc; unsigned int i,j,n; - printk("%s: %s - dma channel status dump\n",dev->name,ch->name); + printk("%s: %s - dma channel status dump\n", + core->name,ch->name); for (i = 0; i < ARRAY_SIZE(name); i++) printk("%s: cmds: %-12s: 0x%08x\n", - dev->name,name[i], + core->name,name[i], cx_read(ch->cmds_start + 4*i)); for (i = 0; i < 4; i++) { risc = cx_read(ch->cmds_start + 4 * (i+11)); - printk("%s: risc%d: ", dev->name, i); + printk("%s: risc%d: ", core->name, i); cx88_risc_decode(risc); } for (i = 0; i < 16; i += n) { risc = cx_read(ch->ctrl_start + 4 * i); - printk("%s: iq %x: ", dev->name, i); + printk("%s: iq %x: ", core->name, i); n = cx88_risc_decode(risc); for (j = 1; j < n; j++) { risc = cx_read(ch->ctrl_start + 4 * (i+j)); printk("%s: iq %x: 0x%08x [ arg #%d ]\n", - dev->name, i+j, risc, j); + core->name, i+j, risc, j); } } printk("%s: fifo: 0x%08x -> 0x%x\n", - dev->name, ch->fifo_start, ch->fifo_start+ch->fifo_size); + core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size); printk("%s: ctrl: 0x%08x -> 0x%x\n", - dev->name, ch->ctrl_start, ch->ctrl_start+6*16); + core->name, ch->ctrl_start, ch->ctrl_start+6*16); printk("%s: ptr1_reg: 0x%08x\n", - dev->name,cx_read(ch->ptr1_reg)); + core->name,cx_read(ch->ptr1_reg)); printk("%s: ptr2_reg: 0x%08x\n", - dev->name,cx_read(ch->ptr2_reg)); + core->name,cx_read(ch->ptr2_reg)); printk("%s: cnt1_reg: 0x%08x\n", - dev->name,cx_read(ch->cnt1_reg)); + core->name,cx_read(ch->cnt1_reg)); printk("%s: cnt2_reg: 0x%08x\n", - dev->name,cx_read(ch->cnt2_reg)); + core->name,cx_read(ch->cnt2_reg)); } char *cx88_pci_irqs[32] = { @@ -531,14 +533,13 @@ void cx88_print_irqbits(char *name, char *tag, char **strings, /* ------------------------------------------------------------------ */ -int cx88_pci_quirks(char *name, struct pci_dev *pci, unsigned int *latency) +static int cx88_pci_quirks(char *name, struct pci_dev *pci) { + unsigned int lat = UNSET; u8 ctrl = 0; u8 value; - if (0 == pci_pci_problems) - return 0; - + /* check pci quirks */ if (pci_pci_problems & PCIPCI_TRITON) { printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n", name); @@ -563,19 +564,161 @@ int cx88_pci_quirks(char *name, struct pci_dev *pci, unsigned int *latency) if (pci_pci_problems & PCIPCI_ALIMAGIK) { printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n", name); - *latency = 0x0A; + lat = 0x0A; } #endif + + /* check insmod options */ + if (UNSET != latency) + lat = latency; + + /* apply stuff */ if (ctrl) { pci_read_config_byte(pci, CX88X_DEVCTRL, &value); value |= ctrl; pci_write_config_byte(pci, CX88X_DEVCTRL, value); } + if (UNSET != lat) { + printk(KERN_INFO "%s: setting pci latency timer to %d\n", + name, latency); + pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency); + } return 0; } /* ------------------------------------------------------------------ */ +struct video_device *cx88_vdev_init(struct cx88_core *core, + struct pci_dev *pci, + struct video_device *template, + char *type) +{ + struct video_device *vfd; + + vfd = video_device_alloc(); + if (NULL == vfd) + return NULL; + *vfd = *template; + vfd->minor = -1; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + vfd->dev = &pci->dev; + vfd->release = video_device_release; +#endif + snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", + core->name, type, cx88_boards[core->board].name); + return vfd; +} + +static int get_ressources(struct cx88_core *core, struct pci_dev *pci) +{ + if (request_mem_region(pci_resource_start(pci,0), + pci_resource_len(pci,0), + core->name)) + return 0; + printk(KERN_ERR "%s: can't get MMIO memory @ 0x%lx\n", + core->name,pci_resource_start(pci,0)); + return -EBUSY; +} + +struct cx88_core* cx88_core_get(struct pci_dev *pci) +{ + struct cx88_core *core; + struct list_head *item; + int i; + + down(&devlist); + list_for_each(item,&cx88_devlist) { + core = list_entry(item, struct cx88_core, devlist); + if (pci->bus->number != core->pci_bus) + continue; + if (PCI_SLOT(pci->devfn) != core->pci_slot) + continue; + + if (0 != get_ressources(core,pci)) + goto fail_unlock; + atomic_inc(&core->refcount); + up(&devlist); + return core; + } + core = kmalloc(sizeof(*core),GFP_KERNEL); + if (NULL == core) + goto fail_unlock; + + memset(core,0,sizeof(*core)); + core->pci_bus = pci->bus->number; + core->pci_slot = PCI_SLOT(pci->devfn); + atomic_inc(&core->refcount); + + core->nr = cx88_devcount++; + sprintf(core->name,"cx88[%d]",core->nr); + if (0 != get_ressources(core,pci)) { + cx88_devcount--; + goto fail_free; + } + list_add_tail(&core->devlist,&cx88_devlist); + + /* PCI stuff */ + cx88_pci_quirks(core->name, pci); + core->lmmio = ioremap(pci_resource_start(pci,0), + pci_resource_len(pci,0)); + core->bmmio = (u8*)core->lmmio; + + /* board config */ + core->board = UNSET; + if (card[core->nr] < cx88_bcount) + core->board = card[core->nr]; + for (i = 0; UNSET == core->board && i < cx88_idcount; i++) + if (pci->subsystem_vendor == cx88_subids[i].subvendor && + pci->subsystem_device == cx88_subids[i].subdevice) + core->board = cx88_subids[i].card; + if (UNSET == core->board) { + core->board = CX88_BOARD_UNKNOWN; + cx88_card_list(core,pci); + } + printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", + core->name,pci->subsystem_vendor, + pci->subsystem_device,cx88_boards[core->board].name, + core->board, card[core->nr] == core->board ? + "insmod option" : "autodetected"); + + core->tuner_type = tuner[core->nr]; + if (UNSET == core->tuner_type) + core->tuner_type = cx88_boards[core->board].tuner_type; + core->tda9887_conf = cx88_boards[core->board].tda9887_conf; + + /* init hardware */ + cx88_i2c_init(core,pci); + + up(&devlist); + return core; + +fail_free: + kfree(core); +fail_unlock: + up(&devlist); + return NULL; +} + +void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) +{ + release_mem_region(pci_resource_start(pci,0), + pci_resource_len(pci,0)); + + if (!atomic_dec_and_test(&core->refcount)) + return; + + down(&devlist); + if (0 == core->i2c_rc) + i2c_bit_del_bus(&core->i2c_adap); + list_del(&core->devlist); + iounmap(core->lmmio); + cx88_devcount--; + up(&devlist); + kfree(core); +} + +/* ------------------------------------------------------------------ */ + EXPORT_SYMBOL(cx88_print_ioctl); EXPORT_SYMBOL(cx88_pci_irqs); EXPORT_SYMBOL(cx88_vid_irqs); @@ -591,7 +734,9 @@ EXPORT_SYMBOL(cx88_sram_channels); EXPORT_SYMBOL(cx88_sram_channel_setup); EXPORT_SYMBOL(cx88_sram_channel_dump); -EXPORT_SYMBOL(cx88_pci_quirks); +EXPORT_SYMBOL(cx88_vdev_init); +EXPORT_SYMBOL(cx88_core_get); +EXPORT_SYMBOL(cx88_core_put); /* * Local variables: |