summaryrefslogtreecommitdiff
path: root/linux/drivers/media/video/cx88/cx88-core.c
diff options
context:
space:
mode:
authorGerd Knorr <devnull@localhost>2004-07-29 21:35:48 +0000
committerGerd Knorr <devnull@localhost>2004-07-29 21:35:48 +0000
commit38ea67b839abf0e8f150106314bc4dff33312e18 (patch)
treedbb14a85e437ad4c2eeec5876f24953c0494aaa6 /linux/drivers/media/video/cx88/cx88-core.c
parentcd05362dcbcd4554765bd6d811981202533df047 (diff)
downloadmediapointer-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.c259
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: