diff options
Diffstat (limited to 'drivers/media/video/cx88/cx88-core.c')
-rw-r--r-- | drivers/media/video/cx88/cx88-core.c | 222 |
1 files changed, 40 insertions, 182 deletions
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index f31ec96..62e8dd2 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -28,7 +28,6 @@ #include <linux/init.h> #include <linux/list.h> #include <linux/module.h> -#include <linux/moduleparam.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/kmod.h> @@ -52,22 +51,6 @@ static unsigned int core_debug = 0; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); -static unsigned int latency = UNSET; -module_param(latency,int,0444); -MODULE_PARM_DESC(latency,"pci latency timer"); - -static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; -static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; -static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; - -module_param_array(tuner, int, NULL, 0444); -module_param_array(radio, int, NULL, 0444); -module_param_array(card, int, NULL, 0444); - -MODULE_PARM_DESC(tuner,"tuner type"); -MODULE_PARM_DESC(radio,"radio tuner type"); -MODULE_PARM_DESC(card,"card type"); - static unsigned int nicam = 0; module_param(nicam,int,0644); MODULE_PARM_DESC(nicam,"tv audio is nicam"); @@ -85,13 +68,15 @@ static DEFINE_MUTEX(devlist); #define NO_SYNC_LINE (-1U) +/* @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be + generated _after_ lpi lines are transferred. */ static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, unsigned int offset, u32 sync_line, unsigned int bpl, unsigned int padding, - unsigned int lines) + unsigned int lines, unsigned int lpi) { struct scatterlist *sg; - unsigned int line,todo; + unsigned int line,todo,sol; /* sync instruction */ if (sync_line != NO_SYNC_LINE) @@ -104,15 +89,19 @@ static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, offset -= sg_dma_len(sg); sg++; } + if (lpi && line>0 && !(line % lpi)) + sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC; + else + sol = RISC_SOL; if (bpl <= sg_dma_len(sg)-offset) { /* fits into current chunk */ - *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); + *(rp++)=cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl); *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); offset+=bpl; } else { /* scanline needs to be split */ todo = bpl; - *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL| + *(rp++)=cpu_to_le32(RISC_WRITE|sol| (sg_dma_len(sg)-offset)); *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); todo -= (sg_dma_len(sg)-offset); @@ -163,10 +152,10 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, rp = risc->cpu; if (UNSET != top_offset) rp = cx88_risc_field(rp, sglist, top_offset, 0, - bpl, padding, lines); + bpl, padding, lines, 0); if (UNSET != bottom_offset) rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200, - bpl, padding, lines); + bpl, padding, lines, 0); /* save pointer to jmp instruction address */ risc->jmp = rp; @@ -176,7 +165,7 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, struct scatterlist *sglist, unsigned int bpl, - unsigned int lines) + unsigned int lines, unsigned int lpi) { u32 instructions; u32 *rp; @@ -193,7 +182,7 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, /* write risc instructions */ rp = risc->cpu; - rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines); + rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi); /* save pointer to jmp instruction address */ risc->jmp = rp; @@ -224,10 +213,12 @@ int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, void cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf) { + struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); + BUG_ON(in_interrupt()); videobuf_waiton(&buf->vb,0,0); - videobuf_dma_unmap(q, &buf->vb.dma); - videobuf_dma_free(&buf->vb.dma); + videobuf_dma_unmap(q, dma); + videobuf_dma_free(dma); btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc); buf->vb.state = STATE_NEEDS_INIT; } @@ -451,10 +442,13 @@ void cx88_sram_channel_dump(struct cx88_core *core, printk("%s: cmds: %-12s: 0x%08x\n", core->name,name[i], cx_read(ch->cmds_start + 4*i)); - for (i = 0; i < 4; i++) { + for (n = 1, i = 0; i < 4; i++) { risc = cx_read(ch->cmds_start + 4 * (i+11)); printk("%s: risc%d: ", core->name, i); - cx88_risc_decode(risc); + if (--n) + printk("0x%08x [ arg #%d ]\n", risc, n); + else + n = cx88_risc_decode(risc); } for (i = 0; i < 16; i += n) { risc = cx_read(ch->ctrl_start + 4 * i); @@ -514,7 +508,7 @@ int cx88_core_irq(struct cx88_core *core, u32 status) { int handled = 0; - if (status & (1<<18)) { + if (status & PCI_INT_IR_SMPINT) { cx88_ir_irq(core); handled++; } @@ -738,7 +732,7 @@ int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int heig value |= (1 << 15); value |= (1 << 16); } - if (INPUT(core->input)->type == CX88_VMUX_SVIDEO) + if (INPUT(core->input).type == CX88_VMUX_SVIDEO) value |= (1 << 13) | (1 << 5); if (V4L2_FIELD_INTERLACED == field) value |= (1 << 3); // VINT (interlaced vertical scaling) @@ -833,7 +827,7 @@ static int set_tvaudio(struct cx88_core *core) { v4l2_std_id norm = core->tvnorm; - if (CX88_VMUX_TELEVISION != INPUT(core->input)->type) + if (CX88_VMUX_TELEVISION != INPUT(core->input).type) return 0; if (V4L2_STD_PAL_BG & norm) { @@ -997,61 +991,6 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm) /* ------------------------------------------------------------------ */ -static int cx88_pci_quirks(char *name, struct pci_dev *pci) -{ - unsigned int lat = UNSET; - u8 ctrl = 0; - u8 value; - - /* check pci quirks */ - if (pci_pci_problems & PCIPCI_TRITON) { - printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n", - name); - ctrl |= CX88X_EN_TBFX; - } - if (pci_pci_problems & PCIPCI_NATOMA) { - printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n", - name); - ctrl |= CX88X_EN_TBFX; - } - if (pci_pci_problems & PCIPCI_VIAETBF) { - printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n", - name); - ctrl |= CX88X_EN_TBFX; - } - if (pci_pci_problems & PCIPCI_VSFX) { - printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n", - name); - ctrl |= CX88X_EN_VSFX; - } -#ifdef PCIPCI_ALIMAGIK - if (pci_pci_problems & PCIPCI_ALIMAGIK) { - printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n", - name); - 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, @@ -1067,122 +1006,38 @@ struct video_device *cx88_vdev_init(struct cx88_core *core, vfd->dev = &pci->dev; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", - core->name, type, cx88_boards[core->board].name); + core->name, type, 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%llx\n", - core->name,(unsigned long long)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; mutex_lock(&devlist); - list_for_each(item,&cx88_devlist) { - core = list_entry(item, struct cx88_core, devlist); + list_for_each_entry(core, &cx88_devlist, 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; + if (0 != cx88_get_resources(core, pci)) { + mutex_unlock(&devlist); + return NULL; + } atomic_inc(&core->refcount); mutex_unlock(&devlist); return core; } - core = kzalloc(sizeof(*core),GFP_KERNEL); - if (NULL == core) - goto fail_unlock; - - atomic_inc(&core->refcount); - core->pci_bus = pci->bus->number; - core->pci_slot = PCI_SLOT(pci->devfn); - core->pci_irqmask = 0x00fc00; - mutex_init(&core->lock); - - core->nr = cx88_devcount++; - sprintf(core->name,"cx88[%d]",core->nr); - if (0 != get_ressources(core,pci)) { - printk(KERN_ERR "CORE %s No more PCI ressources for " - "subsystem: %04x:%04x, board: %s\n", - core->name,pci->subsystem_vendor, - pci->subsystem_device, - cx88_boards[core->board].name); - - 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 __iomem *)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); + + core = cx88_core_create(pci, cx88_devcount); + if (NULL != core) { + cx88_devcount++; + list_add_tail(&core->devlist, &cx88_devlist); } - printk(KERN_INFO "CORE %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]; - core->radio_type = radio[core->nr]; - if (UNSET == core->tuner_type) - core->tuner_type = cx88_boards[core->board].tuner_type; - if (UNSET == core->radio_type) - core->radio_type = cx88_boards[core->board].radio_type; - if (!core->tuner_addr) - core->tuner_addr = cx88_boards[core->board].tuner_addr; - if (!core->radio_addr) - core->radio_addr = cx88_boards[core->board].radio_addr; - - printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n", - core->tuner_type, core->tuner_addr<<1, - core->radio_type, core->radio_addr<<1); - - core->tda9887_conf = cx88_boards[core->board].tda9887_conf; - - /* init hardware */ - cx88_reset(core); - cx88_card_setup_pre_i2c(core); - cx88_i2c_init(core,pci); - cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL); - cx88_card_setup(core); - cx88_ir_init(core,pci); mutex_unlock(&devlist); return core; - -fail_free: - kfree(core); -fail_unlock: - mutex_unlock(&devlist); - return NULL; } void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) @@ -1229,6 +1084,9 @@ EXPORT_SYMBOL(cx88_vdev_init); EXPORT_SYMBOL(cx88_core_get); EXPORT_SYMBOL(cx88_core_put); +EXPORT_SYMBOL(cx88_ir_start); +EXPORT_SYMBOL(cx88_ir_stop); + /* * Local variables: * c-basic-offset: 8 |