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

📄 cx23885-core.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  Driver for the Conexant CX23885 PCIe bridge * *  Copyright (c) 2006 Steven Toth <stoth@hauppauge.com> * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/init.h>#include <linux/list.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/kmod.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/delay.h>#include <asm/div64.h>#include "cx23885.h"MODULE_DESCRIPTION("Driver for cx23885 based TV cards");MODULE_AUTHOR("Steven Toth <stoth@hauppauge.com>");MODULE_LICENSE("GPL");static unsigned int debug = 0;module_param(debug,int,0644);MODULE_PARM_DESC(debug,"enable debug messages");static unsigned int card[]  = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };module_param_array(card,  int, NULL, 0444);MODULE_PARM_DESC(card,"card type");#define dprintk(level,fmt, arg...)	if (debug >= level) \	printk(KERN_DEBUG "%s/0: " fmt, dev->name , ## arg)static unsigned int cx23885_devcount;static DEFINE_MUTEX(devlist);static LIST_HEAD(cx23885_devlist);#define NO_SYNC_LINE (-1U)/* * CX23885 Assumptions * 1 line = 16 bytes of CDT * cmds size = 80 * cdt size = 16 * linesize * iqsize = 64 * maxlines = 6 * * Address Space: * 0x00000000 0x00008fff FIFO clusters * 0x00010000 0x000104af Channel Management Data Structures * 0x000104b0 0x000104ff Free * 0x00010500 0x000108bf 15 channels * iqsize * 0x000108c0 0x000108ff Free * 0x00010900 0x00010e9f IQ's + Cluster Descriptor Tables *                       15 channels * (iqsize + (maxlines * linesize)) * 0x00010ea0 0x00010xxx Free */struct sram_channel cx23885_sram_channels[] = {	[SRAM_CH01] = {		.name		= "test ch1",		.cmds_start	= 0x10000,		.ctrl_start	= 0x10500,		.cdt		= 0x10900,		.fifo_start	= 0x3000,		.fifo_size	= 0x1000,		.ptr1_reg	= DMA1_PTR1,		.ptr2_reg	= DMA1_PTR2,		.cnt1_reg	= DMA1_CNT1,		.cnt2_reg	= DMA1_CNT2,		.jumponly	= 1,	},	[SRAM_CH02] = {		.name		= "ch2",		.cmds_start	= 0x0,		.ctrl_start	= 0x0,		.cdt		= 0x0,		.fifo_start	= 0x0,		.fifo_size	= 0x0,		.ptr1_reg	= DMA2_PTR1,		.ptr2_reg	= DMA2_PTR2,		.cnt1_reg	= DMA2_CNT1,		.cnt2_reg	= DMA2_CNT2,	},	[SRAM_CH03] = {		.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,		.cnt2_reg	= DMA3_CNT2,	},	[SRAM_CH04] = {		.name		= "ch4",		.cmds_start	= 0x0,		.ctrl_start	= 0x0,		.cdt		= 0x0,		.fifo_start	= 0x0,		.fifo_size	= 0x0,		.ptr1_reg	= DMA4_PTR1,		.ptr2_reg	= DMA4_PTR2,		.cnt1_reg	= DMA4_CNT1,		.cnt2_reg	= DMA4_CNT2,	},	[SRAM_CH05] = {		.name		= "ch5",		.cmds_start	= 0x0,		.ctrl_start	= 0x0,		.cdt		= 0x0,		.fifo_start	= 0x0,		.fifo_size	= 0x0,		.ptr1_reg	= DMA5_PTR1,		.ptr2_reg	= DMA5_PTR2,		.cnt1_reg	= DMA5_CNT1,		.cnt2_reg	= DMA5_CNT2,	},	[SRAM_CH06] = {		.name		= "TS2 C",		.cmds_start	= 0x10140,		.ctrl_start	= 0x10680,		.cdt		= 0x10480,		.fifo_start	= 0x6000,		.fifo_size	= 0x1000,		.ptr1_reg	= DMA5_PTR1,		.ptr2_reg	= DMA5_PTR2,		.cnt1_reg	= DMA5_CNT1,		.cnt2_reg	= DMA5_CNT2,	},	[SRAM_CH07] = {		.name		= "ch7",		.cmds_start	= 0x0,		.ctrl_start	= 0x0,		.cdt		= 0x0,		.fifo_start	= 0x0,		.fifo_size	= 0x0,		.ptr1_reg	= DMA6_PTR1,		.ptr2_reg	= DMA6_PTR2,		.cnt1_reg	= DMA6_CNT1,		.cnt2_reg	= DMA6_CNT2,	},	[SRAM_CH08] = {		.name		= "ch8",		.cmds_start	= 0x0,		.ctrl_start	= 0x0,		.cdt		= 0x0,		.fifo_start	= 0x0,		.fifo_size	= 0x0,		.ptr1_reg	= DMA7_PTR1,		.ptr2_reg	= DMA7_PTR2,		.cnt1_reg	= DMA7_CNT1,		.cnt2_reg	= DMA7_CNT2,	},	[SRAM_CH09] = {		.name		= "ch9",		.cmds_start	= 0x0,		.ctrl_start	= 0x0,		.cdt		= 0x0,		.fifo_start	= 0x0,		.fifo_size	= 0x0,		.ptr1_reg	= DMA8_PTR1,		.ptr2_reg	= DMA8_PTR2,		.cnt1_reg	= DMA8_CNT1,		.cnt2_reg	= DMA8_CNT2,	},};/* FIXME, these allocations will change when * analog arrives. The be reviewed. * CX23887 Assumptions * 1 line = 16 bytes of CDT * cmds size = 80 * cdt size = 16 * linesize * iqsize = 64 * maxlines = 6 * * Address Space: * 0x00000000 0x00008fff FIFO clusters * 0x00010000 0x000104af Channel Management Data Structures * 0x000104b0 0x000104ff Free * 0x00010500 0x000108bf 15 channels * iqsize * 0x000108c0 0x000108ff Free * 0x00010900 0x00010e9f IQ's + Cluster Descriptor Tables *                       15 channels * (iqsize + (maxlines * linesize)) * 0x00010ea0 0x00010xxx Free */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,		.ptr1_reg	= DMA1_PTR1,		.ptr2_reg	= DMA1_PTR2,		.cnt1_reg	= DMA1_CNT1,		.cnt2_reg	= DMA1_CNT2,	},	[SRAM_CH02] = {		.name		= "ch2",		.cmds_start	= 0x0,		.ctrl_start	= 0x0,		.cdt		= 0x0,		.fifo_start	= 0x0,		.fifo_size	= 0x0,		.ptr1_reg	= DMA2_PTR1,		.ptr2_reg	= DMA2_PTR2,		.cnt1_reg	= DMA2_CNT1,		.cnt2_reg	= DMA2_CNT2,	},	[SRAM_CH03] = {		.name		= "ch3",		.cmds_start	= 0x0,		.ctrl_start	= 0x0,		.cdt		= 0x0,		.fifo_start	= 0x0,		.fifo_size	= 0x0,		.ptr1_reg	= DMA3_PTR1,		.ptr2_reg	= DMA3_PTR2,		.cnt1_reg	= DMA3_CNT1,		.cnt2_reg	= DMA3_CNT2,	},	[SRAM_CH04] = {		.name		= "ch4",		.cmds_start	= 0x0,		.ctrl_start	= 0x0,		.cdt		= 0x0,		.fifo_start	= 0x0,		.fifo_size	= 0x0,		.ptr1_reg	= DMA4_PTR1,		.ptr2_reg	= DMA4_PTR2,		.cnt1_reg	= DMA4_CNT1,		.cnt2_reg	= DMA4_CNT2,	},	[SRAM_CH05] = {		.name		= "ch5",		.cmds_start	= 0x0,		.ctrl_start	= 0x0,		.cdt		= 0x0,		.fifo_start	= 0x0,		.fifo_size	= 0x0,		.ptr1_reg	= DMA5_PTR1,		.ptr2_reg	= DMA5_PTR2,		.cnt1_reg	= DMA5_CNT1,		.cnt2_reg	= DMA5_CNT2,	},	[SRAM_CH06] = {		.name		= "TS2 C",		.cmds_start	= 0x10140,		.ctrl_start	= 0x10680,		.cdt		= 0x108d0,		.fifo_start	= 0x6000,		.fifo_size	= 0x1000,		.ptr1_reg	= DMA5_PTR1,		.ptr2_reg	= DMA5_PTR2,		.cnt1_reg	= DMA5_CNT1,		.cnt2_reg	= DMA5_CNT2,	},	[SRAM_CH07] = {		.name		= "ch7",		.cmds_start	= 0x0,		.ctrl_start	= 0x0,		.cdt		= 0x0,		.fifo_start	= 0x0,		.fifo_size	= 0x0,		.ptr1_reg	= DMA6_PTR1,		.ptr2_reg	= DMA6_PTR2,		.cnt1_reg	= DMA6_CNT1,		.cnt2_reg	= DMA6_CNT2,	},	[SRAM_CH08] = {		.name		= "ch8",		.cmds_start	= 0x0,		.ctrl_start	= 0x0,		.cdt		= 0x0,		.fifo_start	= 0x0,		.fifo_size	= 0x0,		.ptr1_reg	= DMA7_PTR1,		.ptr2_reg	= DMA7_PTR2,		.cnt1_reg	= DMA7_CNT1,		.cnt2_reg	= DMA7_CNT2,	},	[SRAM_CH09] = {		.name		= "ch9",		.cmds_start	= 0x0,		.ctrl_start	= 0x0,		.cdt		= 0x0,		.fifo_start	= 0x0,		.fifo_size	= 0x0,		.ptr1_reg	= DMA8_PTR1,		.ptr2_reg	= DMA8_PTR2,		.cnt1_reg	= DMA8_CNT1,		.cnt2_reg	= DMA8_CNT2,	},};static int cx23885_risc_decode(u32 risc){	static char *instr[16] = {		[ RISC_SYNC    >> 28 ] = "sync",		[ RISC_WRITE   >> 28 ] = "write",		[ RISC_WRITEC  >> 28 ] = "writec",		[ RISC_READ    >> 28 ] = "read",		[ RISC_READC   >> 28 ] = "readc",		[ RISC_JUMP    >> 28 ] = "jump",		[ RISC_SKIP    >> 28 ] = "skip",		[ RISC_WRITERM >> 28 ] = "writerm",		[ RISC_WRITECM >> 28 ] = "writecm",		[ RISC_WRITECR >> 28 ] = "writecr",	};	static int incr[16] = {		[ RISC_WRITE   >> 28 ] = 3,		[ RISC_JUMP    >> 28 ] = 3,		[ RISC_SKIP    >> 28 ] = 1,		[ RISC_SYNC    >> 28 ] = 1,		[ RISC_WRITERM >> 28 ] = 3,		[ RISC_WRITECM >> 28 ] = 3,		[ RISC_WRITECR >> 28 ] = 4,	};	static char *bits[] = {		"12",   "13",   "14",   "resync",		"cnt0", "cnt1", "18",   "19",		"20",   "21",   "22",   "23",		"irq1", "irq2", "eol",  "sol",	};	int i;	printk("0x%08x [ %s", risc,	       instr[risc >> 28] ? instr[risc >> 28] : "INVALID");	for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--)		if (risc & (1 << (i + 12)))			printk(" %s", bits[i]);	printk(" count=%d ]\n", risc & 0xfff);	return incr[risc >> 28] ? incr[risc >> 28] : 1;}void cx23885_wakeup(struct cx23885_tsport *port,		    struct cx23885_dmaqueue *q, u32 count){	struct cx23885_dev *dev = port->dev;	struct cx23885_buffer *buf;	int bc;	for (bc = 0;; bc++) {		if (list_empty(&q->active))			break;		buf = list_entry(q->active.next,				 struct cx23885_buffer, vb.queue);		/* count comes from the hw and is is 16bit wide --		 * this trick handles wrap-arounds correctly for		 * up to 32767 buffers in flight... */		if ((s16) (count - buf->count) < 0)			break;		do_gettimeofday(&buf->vb.ts);		dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i,			count, buf->count);		buf->vb.state = STATE_DONE;		list_del(&buf->vb.queue);		wake_up(&buf->vb.done);	}	if (list_empty(&q->active)) {		del_timer(&q->timeout);	} else {		mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);	}	if (bc != 1)		printk("%s: %d buffers handled (should be 1)\n",		       __FUNCTION__, bc);}void cx23885_sram_channel_dump(struct cx23885_dev *dev,			       struct sram_channel *ch);int cx23885_sram_channel_setup(struct cx23885_dev *dev,			       struct sram_channel *ch,			       unsigned int bpl, u32 risc){	unsigned int i, lines;	u32 cdt;	if (ch->cmds_start == 0)	{		dprintk(1, "%s() Erasing channel [%s]\n", __FUNCTION__,			ch->name);		cx_write(ch->ptr1_reg, 0);		cx_write(ch->ptr2_reg, 0);		cx_write(ch->cnt2_reg, 0);		cx_write(ch->cnt1_reg, 0);		return 0;	} else {		dprintk(1, "%s() Configuring channel [%s]\n", __FUNCTION__,			ch->name);	}	bpl   = (bpl + 7) & ~7; /* alignment */	cdt   = ch->cdt;	lines = ch->fifo_size / bpl;	if (lines > 6)		lines = 6;	BUG_ON(lines < 2);	cx_write(8 + 0, cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC) );	cx_write(8 + 4, cpu_to_le32(8) );	cx_write(8 + 8, cpu_to_le32(0) );	/* write CDT */	for (i = 0; i < lines; i++) {		dprintk(2, "%s() 0x%08x <- 0x%08x\n", __FUNCTION__, cdt + 16*i,			ch->fifo_start + bpl*i);		cx_write(cdt + 16*i, ch->fifo_start + bpl*i);		cx_write(cdt + 16*i +  4, 0);		cx_write(cdt + 16*i +  8, 0);		cx_write(cdt + 16*i + 12, 0);	}	/* write CMDS */	if (ch->jumponly)		cx_write(ch->cmds_start +  0, 8);	else		cx_write(ch->cmds_start +  0, risc);	cx_write(ch->cmds_start +  4, 0); /* 64 bits 63-32 */	cx_write(ch->cmds_start +  8, cdt);	cx_write(ch->cmds_start + 12, (lines*16) >> 3);	cx_write(ch->cmds_start + 16, ch->ctrl_start);	if (ch->jumponly)		cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2) );	else		cx_write(ch->cmds_start + 20, 64 >> 2);	for (i = 24; i < 80; i += 4)		cx_write(ch->cmds_start + i, 0);	/* fill registers */	cx_write(ch->ptr1_reg, ch->fifo_start);	cx_write(ch->ptr2_reg, cdt);	cx_write(ch->cnt2_reg, (lines*16) >> 3);	cx_write(ch->cnt1_reg, (bpl >> 3) -1);	dprintk(2,"[bridge %d] sram setup %s: bpl=%d lines=%d\n",		dev->bridge,		ch->name,		bpl,		lines);	return 0;}void cx23885_sram_channel_dump(struct cx23885_dev *dev,			       struct sram_channel *ch){	static char *name[] = {		"init risc lo",		"init risc hi",		"cdt base",		"cdt size",		"iq base",		"iq size",		"risc pc lo",		"risc pc hi",		"iq wr ptr",		"iq rd ptr",		"cdt current",		"pci target lo",		"pci target hi",		"line / byte",	};	u32 risc;	unsigned int i, j, n;	printk("%s: %s - dma channel status dump\n",	       dev->name, ch->name);	for (i = 0; i < ARRAY_SIZE(name); i++)		printk("%s:   cmds: %-15s: 0x%08x\n",		       dev->name, name[i],		       cx_read(ch->cmds_start + 4*i));	for (i = 0; i < 4; i++) {		risc = cx_read(ch->cmds_start + 4 * (i + 14));		printk("%s:   risc%d: ", dev->name, i);		cx23885_risc_decode(risc);	}	for (i = 0; i < (64 >> 2); i += n) {		risc = cx_read(ch->ctrl_start + 4 * i);		/* No consideration for bits 63-32 */		printk("%s:   (0x%08x) iq %x: ", dev->name,		       ch->ctrl_start + 4 * i, i);

⌨️ 快捷键说明

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