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

📄 cx23885-core.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
			     struct cx23885_buffer   *buf){	struct cx23885_dev *dev = port->dev;	dprintk(1, "%s() w: %d, h: %d, f: %d\n", __FUNCTION__,		buf->vb.width, buf->vb.height, buf->vb.field);	/* 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() Failed. Unsupported value in .portb/c (0x%08x)/(0x%08x)\n",			__FUNCTION__,			cx23885_boards[dev->board].portb,			cx23885_boards[dev->board].portc );		return -EINVAL;	}	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, 0x47 << 16 | 188 << 4);	cx_write(port->reg_ts_clk_en, port->ts_clk_en_val);	cx_write(port->reg_vld_misc, 0x00);	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;	switch(dev->bridge) {	case CX23885_BRIDGE_885:	case CX23885_BRIDGE_887:		/* enable irqs */		dprintk(1, "%s() enabling TS int's and DMA\n", __FUNCTION__ );		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 */	return 0;}static int cx23885_stop_dma(struct cx23885_tsport *port){	struct cx23885_dev *dev = port->dev;	dprintk(1, "%s()\n", __FUNCTION__);	/* 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);	return 0;}static 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", __FUNCTION__);	if (list_empty(&q->active))	{		struct cx23885_buffer *prev;		prev = NULL;		dprintk(5, "%s() queue is empty\n", __FUNCTION__);		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 = STATE_ACTIVE;				buf->count    = q->count++;				mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);				dprintk(5, "[%p/%d] restart_queue - first 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 = STATE_ACTIVE;				buf->count    = q->count++;				prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);				prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */				dprintk(5,"[%p/%d] restart_queue - move to 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", __FUNCTION__, buf);	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)		return -EINVAL;	if (STATE_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*/;		if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))			goto fail;		cx23885_risc_databuffer(dev->pci, &buf->risc,					videobuf_to_dma(&buf->vb)->sglist,					buf->vb.width, buf->vb.height);	}	buf->vb.state = STATE_PREPARED;	return 0; fail:	cx23885_free_buffer(q, buf);	return rc;}void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf){	struct cx23885_buffer    *prev;	struct cx23885_dev *dev = port->dev;	struct cx23885_dmaqueue  *cx88q = &port->mpegq;	/* add jump to stopper */	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);	buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);	buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */	if (list_empty(&cx88q->active)) {		dprintk( 1, "queue is empty - first active\n" );		list_add_tail(&buf->vb.queue, &cx88q->active);		cx23885_start_dma(port, cx88q, buf);		buf->vb.state = STATE_ACTIVE;		buf->count    = cx88q->count++;		mod_timer(&cx88q->timeout, jiffies + BUFFER_TIMEOUT);		dprintk(1, "[%p/%d] %s - first active\n",			buf, buf->vb.i, __FUNCTION__);	} else {		dprintk( 1, "queue is not empty - append to active\n" );		prev = list_entry(cx88q->active.prev, struct cx23885_buffer,				  vb.queue);		list_add_tail(&buf->vb.queue, &cx88q->active);		buf->vb.state = STATE_ACTIVE;		buf->count    = cx88q->count++;		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);		prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */		dprintk( 1, "[%p/%d] %s - append to active\n",			 buf, buf->vb.i, __FUNCTION__);	}}/* ----------------------------------------------------------- */static void do_cancel_buffers(struct cx23885_tsport *port, char *reason,			      int restart){	struct cx23885_dev *dev = port->dev;	struct cx23885_dmaqueue *q = &port->mpegq;	struct cx23885_buffer *buf;	unsigned long flags;	spin_lock_irqsave(&port->slock, flags);	while (!list_empty(&q->active)) {		buf = list_entry(q->active.next, struct cx23885_buffer,				 vb.queue);		list_del(&buf->vb.queue);		buf->vb.state = STATE_ERROR;		wake_up(&buf->vb.done);		dprintk(1, "[%p/%d] %s - dma=0x%08lx\n",			buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);	}	if (restart) {		dprintk(1, "restarting queue\n" );		cx23885_restart_queue(port, q);	}	spin_unlock_irqrestore(&port->slock, flags);}void cx23885_cancel_buffers(struct cx23885_tsport *port){	struct cx23885_dev *dev = port->dev;	struct cx23885_dmaqueue *q = &port->mpegq;	dprintk(1, "%s()\n", __FUNCTION__);	del_timer_sync(&q->timeout);	cx23885_stop_dma(port);	do_cancel_buffers(port, "cancel", 0);}static void cx23885_timeout(unsigned long data){	struct cx23885_tsport *port = (struct cx23885_tsport *)data;	struct cx23885_dev *dev = port->dev;	dprintk(1, "%s()\n",__FUNCTION__);	if (debug > 5)		cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);	cx23885_stop_dma(port);	do_cancel_buffers(port, "timeout", 1);}static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status){	struct cx23885_dev *dev = port->dev;	int handled = 0;	u32 count;	if ( (status & VID_BC_MSK_OPC_ERR) ||	     (status & VID_BC_MSK_BAD_PKT) ||	     (status & VID_BC_MSK_SYNC) ||	     (status & VID_BC_MSK_OF))	{		if (status & VID_BC_MSK_OPC_ERR)			dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n", VID_BC_MSK_OPC_ERR);		if (status & VID_BC_MSK_BAD_PKT)			dprintk(7, " (VID_BC_MSK_BAD_PKT 0x%08x)\n", VID_BC_MSK_BAD_PKT);		if (status & VID_BC_MSK_SYNC)			dprintk(7, " (VID_BC_MSK_SYNC    0x%08x)\n", VID_BC_MSK_SYNC);		if (status & VID_BC_MSK_OF)			dprintk(7, " (VID_BC_MSK_OF      0x%08x)\n", VID_BC_MSK_OF);		printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name);		cx_clear(port->reg_dma_ctl, port->dma_ctl_val);		cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);	} else if (status & VID_BC_MSK_RISCI1) {		dprintk(7, " (RISCI1            0x%08x)\n", VID_BC_MSK_RISCI1);		spin_lock(&port->slock);		count = cx_read(port->reg_gpcnt);		cx23885_wakeup(port, &port->mpegq, count);		spin_unlock(&port->slock);	} else if (status & VID_BC_MSK_RISCI2) {		dprintk(7, " (RISCI2            0x%08x)\n", VID_BC_MSK_RISCI2);		spin_lock(&port->slock);		cx23885_restart_queue(port, &port->mpegq);		spin_unlock(&port->slock);	}	if (status) {		cx_write(port->reg_ts_int_stat, status);		handled = 1;	}	return handled;}static irqreturn_t cx23885_irq(int irq, void *dev_id){	struct cx23885_dev *dev = dev_id;	struct cx23885_tsport *ts1 = &dev->ts1;	struct cx23885_tsport *ts2 = &dev->ts2;	u32 pci_status, pci_mask;	u32 ts1_status, ts1_mask;	u32 ts2_status, ts2_mask;	int ts1_count = 0, ts2_count = 0, handled = 0;	pci_status = cx_read(PCI_INT_STAT);	pci_mask = cx_read(PCI_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);	ts2_mask = cx_read(VID_C_INT_MSK);	if ( (pci_status == 0) && (ts2_status == 0) && (ts1_status == 0) )		goto out;	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 );	if ( (pci_status & PCI_MSK_RISC_RD) ||	     (pci_status & PCI_MSK_RISC_WR) ||	     (pci_status & PCI_MSK_AL_RD) ||	     (pci_status & PCI_MSK_AL_WR) ||	     (pci_status & PCI_MSK_APB_DMA) ||	     (pci_status & PCI_MSK_VID_C) ||	     (pci_status & PCI_MSK_VID_B) ||	     (pci_status & PCI_MSK_VID_A) ||	     (pci_status & PCI_MSK_AUD_INT) ||	     (pci_status & PCI_MSK_AUD_EXT) )	{		if (pci_status & PCI_MSK_RISC_RD)			dprintk(7, " (PCI_MSK_RISC_RD   0x%08x)\n", PCI_MSK_RISC_RD);		if (pci_status & PCI_MSK_RISC_WR)			dprintk(7, " (PCI_MSK_RISC_WR   0x%08x)\n", PCI_MSK_RISC_WR);		if (pci_status & PCI_MSK_AL_RD)			dprintk(7, " (PCI_MSK_AL_RD     0x%08x)\n", PCI_MSK_AL_RD);		if (pci_status & PCI_MSK_AL_WR)			dprintk(7, " (PCI_MSK_AL_WR     0x%08x)\n", PCI_MSK_AL_WR);		if (pci_status & PCI_MSK_APB_DMA)			dprintk(7, " (PCI_MSK_APB_DMA   0x%08x)\n", PCI_MSK_APB_DMA);		if (pci_status & PCI_MSK_VID_C)			dprintk(7, " (PCI_MSK_VID_C     0x%08x)\n", PCI_MSK_VID_C);		if (pci_status & PCI_MSK_VID_B)			dprintk(7, " (PCI_MSK_VID_B     0x%08x)\n", PCI_MSK_VID_B);		if (pci_status & PCI_MSK_VID_A)			dprintk(7, " (PCI_MSK_VID_A     0x%08x)\n", PCI_MSK_VID_A);		if (pci_status & PCI_MSK_AUD_INT)			dprintk(7, " (PCI_MSK_AUD_INT   0x%08x)\n", PCI_MSK_AUD_INT);		if (pci_status & PCI_MSK_AUD_EXT)			dprintk(7, " (PCI_MSK_AUD_EXT   0x%08x)\n", PCI_MSK_AUD_EXT);	}	if (ts1_status)		handled += cx23885_irq_ts(ts1, ts1_status);	if (ts2_status)		handled += cx23885_irq_ts(ts2, ts2_status);	if (handled)		cx_write(PCI_INT_STAT, pci_status);out:	return IRQ_RETVAL(handled);}static int __devinit cx23885_initdev(struct pci_dev *pci_dev,				     const struct pci_device_id *pci_id){	struct cx23885_dev *dev;	int err;	dev = kzalloc(sizeof(*dev), GFP_KERNEL);	if (NULL == dev)		return -ENOMEM;	/* pci init */	dev->pci = pci_dev;	if (pci_enable_device(pci_dev)) {		err = -EIO;		goto fail_free;	}	if (cx23885_dev_setup(dev) < 0) {		err = -EINVAL;		goto fail_free;	}	/* print pci info */	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);	pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);	printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "	       "latency: %d, mmio: 0x%llx\n", dev->name,	       pci_name(pci_dev), dev->pci_rev, pci_dev->irq,	       dev->pci_lat, (unsigned long long)pci_resource_start(pci_dev,0));	pci_set_master(pci_dev);	if (!pci_dma_supported(pci_dev, 0xffffffff)) {		printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);		err = -EIO;		goto fail_irq;	}	err = request_irq(pci_dev->irq, cx23885_irq,			  IRQF_SHARED | IRQF_DISABLED, dev->name, dev);	if (err < 0) {		printk(KERN_ERR "%s: can't get IRQ %d\n",		       dev->name, pci_dev->irq);		goto fail_irq;	}	pci_set_drvdata(pci_dev, dev);	return 0;fail_irq:	cx23885_dev_unregister(dev);fail_free:	kfree(dev);	return err;}static void __devexit cx23885_finidev(struct pci_dev *pci_dev){	struct cx23885_dev *dev = pci_get_drvdata(pci_dev);	cx23885_shutdown(dev);	pci_disable_device(pci_dev);	/* unregister stuff */	free_irq(pci_dev->irq, dev);	pci_set_drvdata(pci_dev, NULL);	mutex_lock(&devlist);	list_del(&dev->devlist);	mutex_unlock(&devlist);	cx23885_dev_unregister(dev);	kfree(dev);}static struct pci_device_id cx23885_pci_tbl[] = {	{		/* CX23885 */		.vendor       = 0x14f1,		.device       = 0x8852,		.subvendor    = PCI_ANY_ID,		.subdevice    = PCI_ANY_ID,	},{		/* CX23887 Rev 2 */		.vendor       = 0x14f1,		.device       = 0x8880,		.subvendor    = PCI_ANY_ID,		.subdevice    = PCI_ANY_ID,	},{		/* --- end of list --- */	}};MODULE_DEVICE_TABLE(pci, cx23885_pci_tbl);static struct pci_driver cx23885_pci_driver = {	.name     = "cx23885",	.id_table = cx23885_pci_tbl,	.probe    = cx23885_initdev,	.remove   = __devexit_p(cx23885_finidev),	/* TODO */	.suspend  = NULL,	.resume   = NULL,};static int cx23885_init(void){	printk(KERN_INFO "cx23885 driver version %d.%d.%d loaded\n",	       (CX23885_VERSION_CODE >> 16) & 0xff,	       (CX23885_VERSION_CODE >>  8) & 0xff,	       CX23885_VERSION_CODE & 0xff);#ifdef SNAPSHOT	printk(KERN_INFO "cx23885: snapshot date %04d-%02d-%02d\n",	       SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);#endif	return pci_register_driver(&cx23885_pci_driver);}static void cx23885_fini(void){	pci_unregister_driver(&cx23885_pci_driver);}module_init(cx23885_init);module_exit(cx23885_fini);/* ----------------------------------------------------------- *//* * Local variables: * c-basic-offset: 8 * End: * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off */

⌨️ 快捷键说明

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