diff options
Diffstat (limited to 'linux/drivers/media/video/cx23885/cx23885-core.c')
-rw-r--r-- | linux/drivers/media/video/cx23885/cx23885-core.c | 236 |
1 files changed, 188 insertions, 48 deletions
diff --git a/linux/drivers/media/video/cx23885/cx23885-core.c b/linux/drivers/media/video/cx23885/cx23885-core.c index 205b7b594..70add3d7f 100644 --- a/linux/drivers/media/video/cx23885/cx23885-core.c +++ b/linux/drivers/media/video/cx23885/cx23885-core.c @@ -51,7 +51,7 @@ MODULE_PARM_DESC(card,"card type"); static unsigned int cx23885_devcount; static DEFINE_MUTEX(devlist); -static LIST_HEAD(cx23885_devlist); +LIST_HEAD(cx23885_devlist); #define NO_SYNC_LINE (-1U) @@ -76,12 +76,12 @@ static LIST_HEAD(cx23885_devlist); static struct sram_channel cx23885_sram_channels[] = { [SRAM_CH01] = { - .name = "test ch1", + .name = "VID A", .cmds_start = 0x10000, - .ctrl_start = 0x10500, - .cdt = 0x10900, - .fifo_start = 0x3000, - .fifo_size = 0x1000, + .ctrl_start = 0x105b0, + .cdt = 0x107b0, + .fifo_start = 0x40, + .fifo_size = 0x2800, .ptr1_reg = DMA1_PTR1, .ptr2_reg = DMA1_PTR2, .cnt1_reg = DMA1_CNT1, @@ -103,8 +103,8 @@ static struct sram_channel cx23885_sram_channels[] = { [SRAM_CH03] = { .name = "TS1 B", .cmds_start = 0x100A0, - .ctrl_start = 0x10780, - .cdt = 0x10400, + .ctrl_start = 0x10630, + .cdt = 0x10870, .fifo_start = 0x5000, .fifo_size = 0x1000, .ptr1_reg = DMA3_PTR1, @@ -140,7 +140,7 @@ static struct sram_channel cx23885_sram_channels[] = { .name = "TS2 C", .cmds_start = 0x10140, .ctrl_start = 0x10680, - .cdt = 0x10480, + .cdt = 0x108d0, .fifo_start = 0x6000, .fifo_size = 0x1000, .ptr1_reg = DMA5_PTR1, @@ -208,12 +208,12 @@ static struct sram_channel cx23885_sram_channels[] = { static struct sram_channel cx23887_sram_channels[] = { [SRAM_CH01] = { - .name = "test ch1", - .cmds_start = 0x0, - .ctrl_start = 0x0, - .cdt = 0x0, - .fifo_start = 0x0, - .fifo_size = 0x0, + .name = "VID A", + .cmds_start = 0x10000, + .ctrl_start = 0x105b0, + .cdt = 0x107b0, + .fifo_start = 0x40, + .fifo_size = 0x2800, .ptr1_reg = DMA1_PTR1, .ptr2_reg = DMA1_PTR2, .cnt1_reg = DMA1_CNT1, @@ -232,12 +232,12 @@ static struct sram_channel cx23887_sram_channels[] = { .cnt2_reg = DMA2_CNT2, }, [SRAM_CH03] = { - .name = "ch3", - .cmds_start = 0x0, - .ctrl_start = 0x0, - .cdt = 0x0, - .fifo_start = 0x0, - .fifo_size = 0x0, + .name = "TS1 B", + .cmds_start = 0x100A0, + .ctrl_start = 0x10780, + .cdt = 0x10400, + .fifo_start = 0x5000, + .fifo_size = 0x1000, .ptr1_reg = DMA3_PTR1, .ptr2_reg = DMA3_PTR2, .cnt1_reg = DMA3_CNT1, @@ -357,7 +357,7 @@ static int cx23885_risc_decode(u32 risc) return incr[risc >> 28] ? incr[risc >> 28] : 1; } -static void cx23885_wakeup(struct cx23885_tsport *port, +void cx23885_wakeup(struct cx23885_tsport *port, struct cx23885_dmaqueue *q, u32 count) { struct cx23885_dev *dev = port->dev; @@ -393,7 +393,7 @@ static void cx23885_wakeup(struct cx23885_tsport *port, __FUNCTION__, bc); } -static int cx23885_sram_channel_setup(struct cx23885_dev *dev, +int cx23885_sram_channel_setup(struct cx23885_dev *dev, struct sram_channel *ch, unsigned int bpl, u32 risc) { @@ -466,7 +466,7 @@ static int cx23885_sram_channel_setup(struct cx23885_dev *dev, return 0; } -static void cx23885_sram_channel_dump(struct cx23885_dev *dev, +void cx23885_sram_channel_dump(struct cx23885_dev *dev, struct sram_channel *ch) { static char *name[] = { @@ -593,15 +593,18 @@ static void cx23885_reset(struct cx23885_dev *dev) mdelay(100); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH01 ], 188*4, 0); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH02 ], 128, 0); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH03 ], 188*4, 0); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH04 ], 128, 0); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH05 ], 128, 0); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH06 ], 188*4, 0); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH07 ], 128, 0); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH08 ], 128, 0); - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH09 ], 128, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01], + 720*4, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02], 128, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH03], + 188*4, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH04], 128, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH05], 128, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH06], + 188*4, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH07], 128, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH08], 128, 0); + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH09], 128, 0); cx23885_gpio_setup(dev); } @@ -635,7 +638,7 @@ static int get_resources(struct cx23885_dev *dev) } static void cx23885_timeout(unsigned long data); -static int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, +int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, u32 reg, u32 mask, u32 value); static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *port, int portno) @@ -703,6 +706,44 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p return 0; } +static void cx23885_dev_checkrevision(struct cx23885_dev *dev) +{ + switch (cx_read(RDR_CFG2) & 0xff) { + case 0x00: + /* cx23885 */ + dev->hwrevision = 0xa0; + break; + case 0x01: + /* CX23885-12Z */ + dev->hwrevision = 0xa1; + break; + case 0x02: + /* CX23885-13Z */ + dev->hwrevision = 0xb0; + break; + case 0x03: + /* CX23888-22Z */ + dev->hwrevision = 0xc0; + break; + case 0x0e: + /* CX23887-15Z */ + dev->hwrevision = 0xc0; + case 0x0f: + /* CX23887-14Z */ + dev->hwrevision = 0xb1; + break; + default: + printk(KERN_ERR "%s() New hardware revision found 0x%x\n", + __FUNCTION__, dev->hwrevision); + } + if (dev->hwrevision) + printk(KERN_INFO "%s() Hardware revision = 0x%02x\n", + __FUNCTION__, dev->hwrevision); + else + printk(KERN_ERR "%s() Hardware revision unknown 0x%x\n", + __FUNCTION__, dev->hwrevision); +} + static int cx23885_dev_setup(struct cx23885_dev *dev) { int i; @@ -722,10 +763,14 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) if(dev->pci->device == 0x8880) { dev->bridge = CX23885_BRIDGE_887; dev->sram_channels = cx23887_sram_channels; + /* Apply a sensible clock frequency for the PCIe bridge */ + dev->clk_freq = 25000000; } else if(dev->pci->device == 0x8852) { dev->bridge = CX23885_BRIDGE_885; dev->sram_channels = cx23885_sram_channels; + /* Apply a sensible clock frequency for the PCIe bridge */ + dev->clk_freq = 28000000; } else BUG(); @@ -745,6 +790,10 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) cx23885_card_list(dev); } + /* If the user specific a clk freq override, apply it */ + if (cx23885_boards[dev->board].clk_freq > 0) + dev->clk_freq = cx23885_boards[dev->board].clk_freq; + dev->pci_bus = dev->pci->bus->number; dev->pci_slot = PCI_SLOT(dev->pci->devfn); dev->pci_irqmask = 0x001f00; @@ -809,6 +858,17 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) cx23885_pci_quirks(dev); + /* Assume some sensible defaults */ + dev->tuner_type = cx23885_boards[dev->board].tuner_type; + dev->tuner_addr = cx23885_boards[dev->board].tuner_addr; + dev->radio_type = cx23885_boards[dev->board].radio_type; + dev->radio_addr = cx23885_boards[dev->board].radio_addr; + + dprintk(1, "%s() tuner_type = 0x%x tuner_addr = 0x%x\n", + __FUNCTION__, dev->tuner_type, dev->tuner_addr); + dprintk(1, "%s() radio_type = 0x%x radio_addr = 0x%x\n", + __FUNCTION__, dev->radio_type, dev->radio_addr); + /* init hardware */ cx23885_reset(dev); @@ -819,20 +879,29 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) cx23885_card_setup(dev); cx23885_ir_init(dev); - if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) { + if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) { + if (cx23885_video_register(dev) < 0) { + printk(KERN_ERR "%s() Failed to register analog " + "video adapters on VID_A\n", __FUNCTION__); + } + } + + if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) { if (cx23885_dvb_register(&dev->ts1) < 0) { printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n", __FUNCTION__); } } - if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) { + if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) { if (cx23885_dvb_register(&dev->ts2) < 0) { printk(KERN_ERR "%s() Failed to register dvb adapters on VID_C\n", __FUNCTION__); } } + cx23885_dev_checkrevision(dev); + return 0; } @@ -844,6 +913,9 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev) if (!atomic_dec_and_test(&dev->refcount)) return; + if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) + cx23885_video_unregister(dev); + if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) cx23885_dvb_unregister(&dev->ts1); @@ -911,7 +983,6 @@ static u32* cx23885_risc_field(u32 *rp, struct scatterlist *sglist, return rp; } -#if 0 int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, struct scatterlist *sglist, unsigned int top_offset, unsigned int bottom_offset, unsigned int bpl, @@ -951,7 +1022,6 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size); return 0; } -#endif /* 0 */ static int cx23885_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, @@ -984,7 +1054,7 @@ static int cx23885_risc_databuffer(struct pci_dev *pci, return 0; } -static int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, +int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, u32 reg, u32 mask, u32 value) { u32 *rp; @@ -1017,6 +1087,57 @@ void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf) buf->vb.state = VIDEOBUF_NEEDS_INIT; } +static void cx23885_tsport_reg_dump(struct cx23885_tsport *port) +{ + struct cx23885_dev *dev = port->dev; + + dprintk(1, "%s() Register Dump\n", __FUNCTION__); + dprintk(1, "%s() DEV_CNTRL2 0x%08X\n", __FUNCTION__, + cx_read(DEV_CNTRL2)); + dprintk(1, "%s() PCI_INT_MSK 0x%08X\n", __FUNCTION__, + cx_read(PCI_INT_MSK)); + dprintk(1, "%s() AUD_INT_INT_MSK 0x%08X\n", __FUNCTION__, + cx_read(AUDIO_INT_INT_MSK)); + dprintk(1, "%s() AUD_INT_DMA_CTL 0x%08X\n", __FUNCTION__, + cx_read(AUD_INT_DMA_CTL)); + dprintk(1, "%s() AUD_EXT_INT_MSK 0x%08X\n", __FUNCTION__, + cx_read(AUDIO_EXT_INT_MSK)); + dprintk(1, "%s() AUD_EXT_DMA_CTL 0x%08X\n", __FUNCTION__, + cx_read(AUD_EXT_DMA_CTL)); + dprintk(1, "%s() PAD_CTRL 0x%08X\n", __FUNCTION__, + cx_read(PAD_CTRL)); + dprintk(1, "%s() ALT_PIN_OUT_SEL 0x%08X\n", __FUNCTION__, + cx_read(ALT_PIN_OUT_SEL)); + dprintk(1, "%s() GPIO2 0x%08X\n", __FUNCTION__, + cx_read(GPIO2)); + dprintk(1, "%s() gpcnt(0x%08X) 0x%08X\n", __FUNCTION__, + port->reg_gpcnt, cx_read(port->reg_gpcnt)); + dprintk(1, "%s() gpcnt_ctl(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl)); + dprintk(1, "%s() dma_ctl(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_dma_ctl, cx_read(port->reg_dma_ctl)); + dprintk(1, "%s() src_sel(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_src_sel, cx_read(port->reg_src_sel)); + dprintk(1, "%s() lngth(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_lngth, cx_read(port->reg_lngth)); + dprintk(1, "%s() hw_sop_ctrl(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_hw_sop_ctrl, cx_read(port->reg_hw_sop_ctrl)); + dprintk(1, "%s() gen_ctrl(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_gen_ctrl, cx_read(port->reg_gen_ctrl)); + dprintk(1, "%s() bd_pkt_status(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_bd_pkt_status, cx_read(port->reg_bd_pkt_status)); + dprintk(1, "%s() sop_status(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_sop_status, cx_read(port->reg_sop_status)); + dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_fifo_ovfl_stat, cx_read(port->reg_fifo_ovfl_stat)); + dprintk(1, "%s() vld_misc(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_vld_misc, cx_read(port->reg_vld_misc)); + dprintk(1, "%s() ts_clk_en(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_ts_clk_en, cx_read(port->reg_ts_clk_en)); + dprintk(1, "%s() ts_int_msk(0x%08X) 0x%08x\n", __FUNCTION__, + port->reg_ts_int_msk, cx_read(port->reg_ts_int_msk)); +} + static int cx23885_start_dma(struct cx23885_tsport *port, struct cx23885_dmaqueue *q, struct cx23885_buffer *buf) @@ -1079,6 +1200,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port, cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */ + if (debug > 4) + cx23885_tsport_reg_dump(port); + return 0; } @@ -1094,7 +1218,7 @@ static int cx23885_stop_dma(struct cx23885_tsport *port) return 0; } -static int cx23885_restart_queue(struct cx23885_tsport *port, +int cx23885_restart_queue(struct cx23885_tsport *port, struct cx23885_dmaqueue *q) { struct cx23885_dev *dev = port->dev; @@ -1334,12 +1458,15 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) struct cx23885_tsport *ts1 = &dev->ts1; struct cx23885_tsport *ts2 = &dev->ts2; u32 pci_status, pci_mask; + u32 vida_status, vida_mask; u32 ts1_status, ts1_mask; u32 ts2_status, ts2_mask; - int ts1_count = 0, ts2_count = 0, handled = 0; + int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0; pci_status = cx_read(PCI_INT_STAT); pci_mask = cx_read(PCI_INT_MSK); + vida_status = cx_read(VID_A_INT_STAT); + vida_mask = cx_read(VID_A_INT_MSK); ts1_status = cx_read(VID_B_INT_STAT); ts1_mask = cx_read(VID_B_INT_MSK); ts2_status = cx_read(VID_C_INT_STAT); @@ -1348,11 +1475,17 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) if ( (pci_status == 0) && (ts2_status == 0) && (ts1_status == 0) ) goto out; + vida_count = cx_read(VID_A_GPCNT); ts1_count = cx_read(ts1->reg_gpcnt); ts2_count = cx_read(ts2->reg_gpcnt); - dprintk(7, "pci_status: 0x%08x pci_mask: 0x%08x\n", pci_status, pci_mask ); - dprintk(7, "ts1_status: 0x%08x ts1_mask: 0x%08x count: 0x%x\n", ts1_status, ts1_mask, ts1_count ); - dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n", ts2_status, ts2_mask, ts2_count ); + dprintk(7, "pci_status: 0x%08x pci_mask: 0x%08x\n", + pci_status, pci_mask); + dprintk(7, "vida_status: 0x%08x vida_mask: 0x%08x count: 0x%x\n", + vida_status, vida_mask, vida_count); + dprintk(7, "ts1_status: 0x%08x ts1_mask: 0x%08x count: 0x%x\n", + ts1_status, ts1_mask, ts1_count); + dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n", + ts2_status, ts2_mask, ts2_count); if ( (pci_status & PCI_MSK_RISC_RD) || (pci_status & PCI_MSK_RISC_WR) || @@ -1389,11 +1522,18 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) } - if (ts1_status) - handled += cx23885_irq_ts(ts1, ts1_status); + if (ts1_status) { + if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) + handled += cx23885_irq_ts(ts1, ts1_status); + } + + if (ts2_status) { + if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) + handled += cx23885_irq_ts(ts2, ts2_status); + } - if (ts2_status) - handled += cx23885_irq_ts(ts2, ts2_status); + if (vida_status) + handled += cx23885_video_irq(dev, vida_status); if (handled) cx_write(PCI_INT_STAT, pci_status); |