⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cx23885-core.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
		cx23885_video_unregister(dev);	if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)		cx23885_dvb_unregister(&dev->ts1);	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)		cx23885_417_unregister(dev);	if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)		cx23885_dvb_unregister(&dev->ts2);	if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)		cx23885_417_unregister(dev);	cx23885_i2c_unregister(&dev->i2c_bus[2]);	cx23885_i2c_unregister(&dev->i2c_bus[1]);	cx23885_i2c_unregister(&dev->i2c_bus[0]);	iounmap(dev->lmmio);}static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,			       unsigned int offset, u32 sync_line,			       unsigned int bpl, unsigned int padding,			       unsigned int lines){	struct scatterlist *sg;	unsigned int line, todo;	/* sync instruction */	if (sync_line != NO_SYNC_LINE)		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);	/* scan lines */	sg = sglist;	for (line = 0; line < lines; line++) {		while (offset && offset >= sg_dma_len(sg)) {			offset -= sg_dma_len(sg);			sg++;		}		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(sg_dma_address(sg)+offset);			*(rp++) = cpu_to_le32(0); /* bits 63-32 */			offset += bpl;		} else {			/* scanline needs to be split */			todo = bpl;			*(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|					    (sg_dma_len(sg)-offset));			*(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);			*(rp++) = cpu_to_le32(0); /* bits 63-32 */			todo -= (sg_dma_len(sg)-offset);			offset = 0;			sg++;			while (todo > sg_dma_len(sg)) {				*(rp++) = cpu_to_le32(RISC_WRITE|						    sg_dma_len(sg));				*(rp++) = cpu_to_le32(sg_dma_address(sg));				*(rp++) = cpu_to_le32(0); /* bits 63-32 */				todo -= sg_dma_len(sg);				sg++;			}			*(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo);			*(rp++) = cpu_to_le32(sg_dma_address(sg));			*(rp++) = cpu_to_le32(0); /* bits 63-32 */			offset += todo;		}		offset += padding;	}	return rp;}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,			unsigned int padding, unsigned int lines){	u32 instructions, fields;	__le32 *rp;	int rc;	fields = 0;	if (UNSET != top_offset)		fields++;	if (UNSET != bottom_offset)		fields++;	/* estimate risc mem: worst case is one write per page border +	   one write per scan line + syncs + jump (all 2 dwords).  Padding	   can cause next bpl to start close to a page border.  First DMA	   region may be smaller than PAGE_SIZE */	/* write and jump need and extra dword */	instructions  = fields * (1 + ((bpl + padding) * lines)		/ PAGE_SIZE + lines);	instructions += 2;	rc = btcx_riscmem_alloc(pci, risc, instructions*12);	if (rc < 0)		return rc;	/* write risc instructions */	rp = risc->cpu;	if (UNSET != top_offset)		rp = cx23885_risc_field(rp, sglist, top_offset, 0,					bpl, padding, lines);	if (UNSET != bottom_offset)		rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x200,					bpl, padding, lines);	/* save pointer to jmp instruction address */	risc->jmp = rp;	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);	return 0;}static int cx23885_risc_databuffer(struct pci_dev *pci,				   struct btcx_riscmem *risc,				   struct scatterlist *sglist,				   unsigned int bpl,				   unsigned int lines){	u32 instructions;	__le32 *rp;	int rc;	/* estimate risc mem: worst case is one write per page border +	   one write per scan line + syncs + jump (all 2 dwords).  Here	   there is no padding and no sync.  First DMA region may be smaller	   than PAGE_SIZE */	/* Jump and write need an extra dword */	instructions  = 1 + (bpl * lines) / PAGE_SIZE + lines;	instructions += 1;	rc = btcx_riscmem_alloc(pci, risc, instructions*12);	if (rc < 0)		return rc;	/* write risc instructions */	rp = risc->cpu;	rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines);	/* save pointer to jmp instruction address */	risc->jmp = rp;	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);	return 0;}int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,				u32 reg, u32 mask, u32 value){	__le32 *rp;	int rc;	rc = btcx_riscmem_alloc(pci, risc, 4*16);	if (rc < 0)		return rc;	/* write risc instructions */	rp = risc->cpu;	*(rp++) = cpu_to_le32(RISC_WRITECR  | RISC_IRQ2);	*(rp++) = cpu_to_le32(reg);	*(rp++) = cpu_to_le32(value);	*(rp++) = cpu_to_le32(mask);	*(rp++) = cpu_to_le32(RISC_JUMP);	*(rp++) = cpu_to_le32(risc->dma);	*(rp++) = cpu_to_le32(0); /* bits 63-32 */	return 0;}void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_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, dma);	videobuf_dma_free(dma);	btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);	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", __func__);	dprintk(1, "%s() DEV_CNTRL2               0x%08X\n", __func__,		cx_read(DEV_CNTRL2));	dprintk(1, "%s() PCI_INT_MSK              0x%08X\n", __func__,		cx_read(PCI_INT_MSK));	dprintk(1, "%s() AUD_INT_INT_MSK          0x%08X\n", __func__,		cx_read(AUDIO_INT_INT_MSK));	dprintk(1, "%s() AUD_INT_DMA_CTL          0x%08X\n", __func__,		cx_read(AUD_INT_DMA_CTL));	dprintk(1, "%s() AUD_EXT_INT_MSK          0x%08X\n", __func__,		cx_read(AUDIO_EXT_INT_MSK));	dprintk(1, "%s() AUD_EXT_DMA_CTL          0x%08X\n", __func__,		cx_read(AUD_EXT_DMA_CTL));	dprintk(1, "%s() PAD_CTRL                 0x%08X\n", __func__,		cx_read(PAD_CTRL));	dprintk(1, "%s() ALT_PIN_OUT_SEL          0x%08X\n", __func__,		cx_read(ALT_PIN_OUT_SEL));	dprintk(1, "%s() GPIO2                    0x%08X\n", __func__,		cx_read(GPIO2));	dprintk(1, "%s() gpcnt(0x%08X)          0x%08X\n", __func__,		port->reg_gpcnt, cx_read(port->reg_gpcnt));	dprintk(1, "%s() gpcnt_ctl(0x%08X)      0x%08x\n", __func__,		port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl));	dprintk(1, "%s() dma_ctl(0x%08X)        0x%08x\n", __func__,		port->reg_dma_ctl, cx_read(port->reg_dma_ctl));	if (port->reg_src_sel)		dprintk(1, "%s() src_sel(0x%08X)        0x%08x\n", __func__,			port->reg_src_sel, cx_read(port->reg_src_sel));	dprintk(1, "%s() lngth(0x%08X)          0x%08x\n", __func__,		port->reg_lngth, cx_read(port->reg_lngth));	dprintk(1, "%s() hw_sop_ctrl(0x%08X)    0x%08x\n", __func__,		port->reg_hw_sop_ctrl, cx_read(port->reg_hw_sop_ctrl));	dprintk(1, "%s() gen_ctrl(0x%08X)       0x%08x\n", __func__,		port->reg_gen_ctrl, cx_read(port->reg_gen_ctrl));	dprintk(1, "%s() bd_pkt_status(0x%08X)  0x%08x\n", __func__,		port->reg_bd_pkt_status, cx_read(port->reg_bd_pkt_status));	dprintk(1, "%s() sop_status(0x%08X)     0x%08x\n", __func__,		port->reg_sop_status, cx_read(port->reg_sop_status));	dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __func__,		port->reg_fifo_ovfl_stat, cx_read(port->reg_fifo_ovfl_stat));	dprintk(1, "%s() vld_misc(0x%08X)       0x%08x\n", __func__,		port->reg_vld_misc, cx_read(port->reg_vld_misc));	dprintk(1, "%s() ts_clk_en(0x%08X)      0x%08x\n", __func__,		port->reg_ts_clk_en, cx_read(port->reg_ts_clk_en));	dprintk(1, "%s() ts_int_msk(0x%08X)     0x%08x\n", __func__,		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){	struct cx23885_dev *dev = port->dev;	u32 reg;	dprintk(1, "%s() w: %d, h: %d, f: %d\n", __func__,		buf->vb.width, buf->vb.height, buf->vb.field);	/* Stop the fifo and risc engine for this port */	cx_clear(port->reg_dma_ctl, port->dma_ctl_val);	/* setup fifo + format */	cx23885_sram_channel_setup(dev,				   &dev->sram_channels[port->sram_chno],				   port->ts_packet_size, buf->risc.dma);	if (debug > 5) {		cx23885_sram_channel_dump(dev,			&dev->sram_channels[port->sram_chno]);		cx23885_risc_disasm(port, &buf->risc);	}	/* write TS length to chip */	cx_write(port->reg_lngth, buf->vb.width);	if ((!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&		(!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB))) {		printk("%s() Unsupported .portb/c (0x%08x)/(0x%08x)\n",			__func__,			cx23885_boards[dev->board].portb,			cx23885_boards[dev->board].portc);		return -EINVAL;	}	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)		cx23885_av_clk(dev, 0);	udelay(100);	/* If the port supports SRC SELECT, configure it */	if (port->reg_src_sel)		cx_write(port->reg_src_sel, port->src_sel_val);	cx_write(port->reg_hw_sop_ctrl, port->hw_sop_ctrl_val);	cx_write(port->reg_ts_clk_en, port->ts_clk_en_val);	cx_write(port->reg_vld_misc, port->vld_misc_val);	cx_write(port->reg_gen_ctrl, port->gen_ctrl_val);	udelay(100);	/* NOTE: this is 2 (reserved) for portb, does it matter? */	/* reset counter to zero */	cx_write(port->reg_gpcnt_ctl, 3);	q->count = 1;	/* Set VIDB pins to input */	if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {		reg = cx_read(PAD_CTRL);		reg &= ~0x3; /* Clear TS1_OE & TS1_SOP_OE */		cx_write(PAD_CTRL, reg);	}	/* Set VIDC pins to input */	if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {		reg = cx_read(PAD_CTRL);		reg &= ~0x4; /* Clear TS2_SOP_OE */		cx_write(PAD_CTRL, reg);	}	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {		reg = cx_read(PAD_CTRL);		reg = reg & ~0x1;    /* Clear TS1_OE */		/* FIXME, bit 2 writing here is questionable */		/* set TS1_SOP_OE and TS1_OE_HI */		reg = reg | 0xa;		cx_write(PAD_CTRL, reg);		/* FIXME and these two registers should be documented. */		cx_write(CLK_DELAY, cx_read(CLK_DELAY) | 0x80000011);		cx_write(ALT_PIN_OUT_SEL, 0x10100045);	}	switch (dev->bridge) {	case CX23885_BRIDGE_885:	case CX23885_BRIDGE_887:		/* enable irqs */		dprintk(1, "%s() enabling TS int's and DMA\n", __func__);		cx_set(port->reg_ts_int_msk,  port->ts_int_msk_val);		cx_set(port->reg_dma_ctl, port->dma_ctl_val);		cx_set(PCI_INT_MSK, dev->pci_irqmask | port->pci_irqmask);		break;	default:		BUG();	}	cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)		cx23885_av_clk(dev, 1);	if (debug > 4)		cx23885_tsport_reg_dump(port);	return 0;}static int cx23885_stop_dma(struct cx23885_tsport *port){	struct cx23885_dev *dev = port->dev;	u32 reg;	dprintk(1, "%s()\n", __func__);	/* Stop interrupts and DMA */	cx_clear(port->reg_ts_int_msk, port->ts_int_msk_val);	cx_clear(port->reg_dma_ctl, port->dma_ctl_val);	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {		reg = cx_read(PAD_CTRL);		/* Set TS1_OE */		reg = reg | 0x1;		/* clear TS1_SOP_OE and TS1_OE_HI */		reg = reg & ~0xa;		cx_write(PAD_CTRL, reg);#if 0		/*		 * cx_write(CLK_DELAY, cx_read(CLK_DELAY) & ~0x80000011); ????		 * cx_write(ALT_PIN_OUT_SEL, 0x10100045); ?? need to undo this?		 */#endif		cx_write(port->reg_src_sel, 0);		cx_write(port->reg_gen_ctrl, 8);	}	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)		cx23885_av_clk(dev, 0);	return 0;}int cx23885_restart_queue(struct cx23885_tsport *port,				struct cx23885_dmaqueue *q){	struct cx23885_dev *dev = port->dev;	struct cx23885_buffer *buf;	dprintk(5, "%s()\n", __func__);	if (list_empty(&q->active)) {		struct cx23885_buffer *prev;		prev = NULL;		dprintk(5, "%s() queue is empty\n", __func__);		for (;;) {			if (list_empty(&q->queued))				return 0;			buf = list_entry(q->queued.next, struct cx23885_buffer,					 vb.queue);			if (NULL == prev) {				list_del(&buf->vb.queue);				list_add_tail(&buf->vb.queue, &q->active);				cx23885_start_dma(port, q, buf);				buf->vb.state = VIDEOBUF_ACTIVE;				buf->count    = q->count++;				mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);				dprintk(5, "[%p/%d] restart_queue - f/active\n",					buf, buf->vb.i);			} else if (prev->vb.width  == buf->vb.width  &&				   prev->vb.height == buf->vb.height &&				   prev->fmt       == buf->fmt) {				list_del(&buf->vb.queue);				list_add_tail(&buf->vb.queue, &q->active);				buf->vb.state = VIDEOBUF_ACTIVE;				buf->count    = q->count++;				prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);				/* 64 bit bits 63-32 */				prev->risc.jmp[2] = cpu_to_le32(0);				dprintk(5, "[%p/%d] restart_queue - m/active\n",					buf, buf->vb.i);			} else {				return 0;			}			prev = buf;		}		return 0;	}	buf = list_entry(q->active.next, struct cx23885_buffer, vb.queue);	dprintk(2, "restart_queue [%p/%d]: restart dma\n",		buf, buf->vb.i);	cx23885_start_dma(port, q, buf);	list_for_each_entry(buf, &q->active, vb.queue)		buf->count = q->count++;	mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);	return 0;}/* ------------------------------------------------------------------ */int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,			struct cx23885_buffer *buf, enum v4l2_field field){	struct cx23885_dev *dev = port->dev;	int size = port->ts_packet_size * port->ts_packet_count;	int rc;	dprintk(1, "%s: %p\n", __func__, buf);	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)		return -EINVAL;	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {		buf->vb.width  = port->ts_packet_size;		buf->vb.height = port->ts_packet_count;		buf->vb.size   = size;		buf->vb.field  = field /*V4L2_FIELD_TOP*/;		rc = videobuf_iolock(q, &buf->vb, NULL);		if (0 != rc)			goto fail;		cx23885_risc_databuffer(dev->pci, &buf->risc,					videobuf_to_dma(&buf->vb)->sglist,					buf->vb.width, buf->vb.height);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -