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

📄 dbri.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Driver for DBRI sound chip found on Sparcs. * Copyright (C) 2004, 2005 Martin Habets (mhabets@users.sourceforge.net) * * Converted to ring buffered version by Krzysztof Helt (krzysztof.h1@wp.pl) * * Based entirely upon drivers/sbus/audio/dbri.c which is: * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de) * Copyright (C) 1998, 1999 Brent Baccala (baccala@freesoft.org) * * This is the low level driver for the DBRI & MMCODEC duo used for ISDN & AUDIO * on Sun SPARCStation 10, 20, LX and Voyager models. * * - DBRI: AT&T T5900FX Dual Basic Rates ISDN Interface. It is a 32 channel *   data time multiplexer with ISDN support (aka T7259) *   Interfaces: SBus,ISDN NT & TE, CHI, 4 bits parallel. *   CHI: (spelled ki) Concentration Highway Interface (AT&T or Intel bus ?). *   Documentation: *   - "STP 4000SBus Dual Basic Rate ISDN (DBRI) Transceiver" from *     Sparc Technology Business (courtesy of Sun Support) *   - Data sheet of the T7903, a newer but very similar ISA bus equivalent *     available from the Lucent (formerly AT&T microelectronics) home *     page. *   - http://www.freesoft.org/Linux/DBRI/ * - MMCODEC: Crystal Semiconductor CS4215 16 bit Multimedia Audio Codec *   Interfaces: CHI, Audio In & Out, 2 bits parallel *   Documentation: from the Crystal Semiconductor home page. * * The DBRI is a 32 pipe machine, each pipe can transfer some bits between * memory and a serial device (long pipes, no. 0-15) or between two serial * devices (short pipes, no. 16-31), or simply send a fixed data to a serial * device (short pipes). * A timeslot defines the bit-offset and no. of bits read from a serial device. * The timeslots are linked to 6 circular lists, one for each direction for * each serial device (NT,TE,CHI). A timeslot is associated to 1 or 2 pipes * (the second one is a monitor/tee pipe, valid only for serial input). * * The mmcodec is connected via the CHI bus and needs the data & some * parameters (volume, output selection) time multiplexed in 8 byte * chunks. It also has a control mode, which serves for audio format setting. * * Looking at the CS4215 data sheet it is easy to set up 2 or 4 codecs on * the same CHI bus, so I thought perhaps it is possible to use the on-board * & the speakerbox codec simultaneously, giving 2 (not very independent :-) * audio devices. But the SUN HW group decided against it, at least on my * LX the speakerbox connector has at least 1 pin missing and 1 wrongly * connected. * * I've tried to stick to the following function naming conventions: * snd_*	ALSA stuff * cs4215_*	CS4215 codec specific stuff * dbri_*	DBRI high-level stuff * other	DBRI low-level stuff */#include <sound/driver.h>#include <linux/interrupt.h>#include <linux/delay.h>#include <linux/irq.h>#include <linux/io.h>#include <sound/core.h>#include <sound/pcm.h>#include <sound/pcm_params.h>#include <sound/info.h>#include <sound/control.h>#include <sound/initval.h>#include <linux/of.h>#include <asm/sbus.h>#include <asm/atomic.h>MODULE_AUTHOR("Rudolf Koenig, Brent Baccala and Martin Habets");MODULE_DESCRIPTION("Sun DBRI");MODULE_LICENSE("GPL");MODULE_SUPPORTED_DEVICE("{{Sun,DBRI}}");static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card *//* Enable this card */static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;module_param_array(index, int, NULL, 0444);MODULE_PARM_DESC(index, "Index value for Sun DBRI soundcard.");module_param_array(id, charp, NULL, 0444);MODULE_PARM_DESC(id, "ID string for Sun DBRI soundcard.");module_param_array(enable, bool, NULL, 0444);MODULE_PARM_DESC(enable, "Enable Sun DBRI soundcard.");#undef DBRI_DEBUG#define D_INT	(1<<0)#define D_GEN	(1<<1)#define D_CMD	(1<<2)#define D_MM	(1<<3)#define D_USR	(1<<4)#define D_DESC	(1<<5)static int dbri_debug;module_param(dbri_debug, int, 0644);MODULE_PARM_DESC(dbri_debug, "Debug value for Sun DBRI soundcard.");#ifdef DBRI_DEBUGstatic char *cmds[] = {	"WAIT", "PAUSE", "JUMP", "IIQ", "REX", "SDP", "CDP", "DTS",	"SSP", "CHI", "NT", "TE", "CDEC", "TEST", "CDM", "RESRV"};#define dprintk(a, x...) if (dbri_debug & a) printk(KERN_DEBUG x)#else#define dprintk(a, x...) do { } while (0)#endif				/* DBRI_DEBUG */#define DBRI_CMD(cmd, intr, value) ((cmd << 28) |	\				    (intr << 27) |	\				    value)/***************************************************************************	CS4215 specific definitions and structures****************************************************************************/struct cs4215 {	__u8 data[4];		/* Data mode: Time slots 5-8 */	__u8 ctrl[4];		/* Ctrl mode: Time slots 1-4 */	__u8 onboard;	__u8 offset;		/* Bit offset from frame sync to time slot 1 */	volatile __u32 status;	volatile __u32 version;	__u8 precision;		/* In bits, either 8 or 16 */	__u8 channels;		/* 1 or 2 */};/* * Control mode first *//* Time Slot 1, Status register */#define CS4215_CLB	(1<<2)	/* Control Latch Bit */#define CS4215_OLB	(1<<3)	/* 1: line: 2.0V, speaker 4V */				/* 0: line: 2.8V, speaker 8V */#define CS4215_MLB	(1<<4)	/* 1: Microphone: 20dB gain disabled */#define CS4215_RSRVD_1  (1<<5)/* Time Slot 2, Data Format Register */#define CS4215_DFR_LINEAR16	0#define CS4215_DFR_ULAW		1#define CS4215_DFR_ALAW		2#define CS4215_DFR_LINEAR8	3#define CS4215_DFR_STEREO	(1<<2)static struct {	unsigned short freq;	unsigned char xtal;	unsigned char csval;} CS4215_FREQ[] = {	{  8000, (1 << 4), (0 << 3) },	{ 16000, (1 << 4), (1 << 3) },	{ 27429, (1 << 4), (2 << 3) },	/* Actually 24428.57 */	{ 32000, (1 << 4), (3 << 3) },     /* {    NA, (1 << 4), (4 << 3) }, */     /* {    NA, (1 << 4), (5 << 3) }, */	{ 48000, (1 << 4), (6 << 3) },	{  9600, (1 << 4), (7 << 3) },	{  5512, (2 << 4), (0 << 3) },	/* Actually 5512.5 */	{ 11025, (2 << 4), (1 << 3) },	{ 18900, (2 << 4), (2 << 3) },	{ 22050, (2 << 4), (3 << 3) },	{ 37800, (2 << 4), (4 << 3) },	{ 44100, (2 << 4), (5 << 3) },	{ 33075, (2 << 4), (6 << 3) },	{  6615, (2 << 4), (7 << 3) },	{ 0, 0, 0}};#define CS4215_HPF	(1<<7)	/* High Pass Filter, 1: Enabled */#define CS4215_12_MASK	0xfcbf	/* Mask off reserved bits in slot 1 & 2 *//* Time Slot 3, Serial Port Control register */#define CS4215_XEN	(1<<0)	/* 0: Enable serial output */#define CS4215_XCLK	(1<<1)	/* 1: Master mode: Generate SCLK */#define CS4215_BSEL_64	(0<<2)	/* Bitrate: 64 bits per frame */#define CS4215_BSEL_128	(1<<2)#define CS4215_BSEL_256	(2<<2)#define CS4215_MCK_MAST (0<<4)	/* Master clock */#define CS4215_MCK_XTL1 (1<<4)	/* 24.576 MHz clock source */#define CS4215_MCK_XTL2 (2<<4)	/* 16.9344 MHz clock source */#define CS4215_MCK_CLK1 (3<<4)	/* Clockin, 256 x Fs */#define CS4215_MCK_CLK2 (4<<4)	/* Clockin, see DFR *//* Time Slot 4, Test Register */#define CS4215_DAD	(1<<0)	/* 0:Digital-Dig loop, 1:Dig-Analog-Dig loop */#define CS4215_ENL	(1<<1)	/* Enable Loopback Testing *//* Time Slot 5, Parallel Port Register *//* Read only here and the same as the in data mode *//* Time Slot 6, Reserved  *//* Time Slot 7, Version Register  */#define CS4215_VERSION_MASK 0xf	/* Known versions 0/C, 1/D, 2/E *//* Time Slot 8, Reserved  *//* * Data mode *//* Time Slot 1-2: Left Channel Data, 2-3: Right Channel Data  *//* Time Slot 5, Output Setting  */#define CS4215_LO(v)	v	/* Left Output Attenuation 0x3f: -94.5 dB */#define CS4215_LE	(1<<6)	/* Line Out Enable */#define CS4215_HE	(1<<7)	/* Headphone Enable *//* Time Slot 6, Output Setting  */#define CS4215_RO(v)	v	/* Right Output Attenuation 0x3f: -94.5 dB */#define CS4215_SE	(1<<6)	/* Speaker Enable */#define CS4215_ADI	(1<<7)	/* A/D Data Invalid: Busy in calibration *//* Time Slot 7, Input Setting */#define CS4215_LG(v)	v	/* Left Gain Setting 0xf: 22.5 dB */#define CS4215_IS	(1<<4)	/* Input Select: 1=Microphone, 0=Line */#define CS4215_OVR	(1<<5)	/* 1: Over range condition occurred */#define CS4215_PIO0	(1<<6)	/* Parallel I/O 0 */#define CS4215_PIO1	(1<<7)/* Time Slot 8, Input Setting */#define CS4215_RG(v)	v	/* Right Gain Setting 0xf: 22.5 dB */#define CS4215_MA(v)	(v<<4)	/* Monitor Path Attenuation 0xf: mute *//***************************************************************************		DBRI specific definitions and structures****************************************************************************//* DBRI main registers */#define REG0	0x00		/* Status and Control */#define REG1	0x04		/* Mode and Interrupt */#define REG2	0x08		/* Parallel IO */#define REG3	0x0c		/* Test */#define REG8	0x20		/* Command Queue Pointer */#define REG9	0x24		/* Interrupt Queue Pointer */#define DBRI_NO_CMDS	64#define DBRI_INT_BLK	64#define DBRI_NO_DESCS	64#define DBRI_NO_PIPES	32#define DBRI_MAX_PIPE	(DBRI_NO_PIPES - 1)#define DBRI_REC	0#define DBRI_PLAY	1#define DBRI_NO_STREAMS	2/* One transmit/receive descriptor *//* When ba != 0 descriptor is used */struct dbri_mem {	volatile __u32 word1;	__u32 ba;	/* Transmit/Receive Buffer Address */	__u32 nda;	/* Next Descriptor Address */	volatile __u32 word4;};/* This structure is in a DMA region where it can accessed by both * the CPU and the DBRI */struct dbri_dma {	s32 cmd[DBRI_NO_CMDS];			/* Place for commands */	volatile s32 intr[DBRI_INT_BLK];	/* Interrupt field  */	struct dbri_mem desc[DBRI_NO_DESCS];	/* Xmit/receive descriptors */};#define dbri_dma_off(member, elem)	\	((u32)(unsigned long)		\	 (&(((struct dbri_dma *)0)->member[elem])))enum in_or_out { PIPEinput, PIPEoutput };struct dbri_pipe {	u32 sdp;		/* SDP command word */	int nextpipe;		/* Next pipe in linked list */	int length;		/* Length of timeslot (bits) */	int first_desc;		/* Index of first descriptor */	int desc;		/* Index of active descriptor */	volatile __u32 *recv_fixed_ptr;	/* Ptr to receive fixed data */};/* Per stream (playback or record) information */struct dbri_streaminfo {	struct snd_pcm_substream *substream;	u32 dvma_buffer;	/* Device view of ALSA DMA buffer */	int size;		/* Size of DMA buffer             */	size_t offset;		/* offset in user buffer          */	int pipe;		/* Data pipe used                 */	int left_gain;		/* mixer elements                 */	int right_gain;};/* This structure holds the information for both chips (DBRI & CS4215) */struct snd_dbri {	int regs_size, irq;	/* Needed for unload */	struct sbus_dev *sdev;	/* SBUS device info */	spinlock_t lock;	struct dbri_dma *dma;	/* Pointer to our DMA block */	u32 dma_dvma;		/* DBRI visible DMA address */	void __iomem *regs;	/* dbri HW regs */	int dbri_irqp;		/* intr queue pointer */	struct dbri_pipe pipes[DBRI_NO_PIPES];	/* DBRI's 32 data pipes */	int next_desc[DBRI_NO_DESCS];		/* Index of next desc, or -1 */	spinlock_t cmdlock;	/* Protects cmd queue accesses */	s32 *cmdptr;		/* Pointer to the last queued cmd */	int chi_bpf;	struct cs4215 mm;	/* mmcodec special info */				/* per stream (playback/record) info */	struct dbri_streaminfo stream_info[DBRI_NO_STREAMS];};#define DBRI_MAX_VOLUME		63	/* Output volume */#define DBRI_MAX_GAIN		15	/* Input gain *//* DBRI Reg0 - Status Control Register - defines. (Page 17) */#define D_P		(1<<15)	/* Program command & queue pointer valid */#define D_G		(1<<14)	/* Allow 4-Word SBus Burst */#define D_S		(1<<13)	/* Allow 16-Word SBus Burst */#define D_E		(1<<12)	/* Allow 8-Word SBus Burst */#define D_X		(1<<7)	/* Sanity Timer Disable */#define D_T		(1<<6)	/* Permit activation of the TE interface */#define D_N		(1<<5)	/* Permit activation of the NT interface */#define D_C		(1<<4)	/* Permit activation of the CHI interface */#define D_F		(1<<3)	/* Force Sanity Timer Time-Out */#define D_D		(1<<2)	/* Disable Master Mode */#define D_H		(1<<1)	/* Halt for Analysis */#define D_R		(1<<0)	/* Soft Reset *//* DBRI Reg1 - Mode and Interrupt Register - defines. (Page 18) */#define D_LITTLE_END	(1<<8)	/* Byte Order */#define D_BIG_END	(0<<8)	/* Byte Order */#define D_MRR		(1<<4)	/* Multiple Error Ack on SBus (read only) */#define D_MLE		(1<<3)	/* Multiple Late Error on SBus (read only) */#define D_LBG		(1<<2)	/* Lost Bus Grant on SBus (read only) */#define D_MBE		(1<<1)	/* Burst Error on SBus (read only) */#define D_IR		(1<<0)	/* Interrupt Indicator (read only) *//* DBRI Reg2 - Parallel IO Register - defines. (Page 18) */#define D_ENPIO3	(1<<7)	/* Enable Pin 3 */#define D_ENPIO2	(1<<6)	/* Enable Pin 2 */#define D_ENPIO1	(1<<5)	/* Enable Pin 1 */#define D_ENPIO0	(1<<4)	/* Enable Pin 0 */#define D_ENPIO		(0xf0)	/* Enable all the pins */#define D_PIO3		(1<<3)	/* Pin 3: 1: Data mode, 0: Ctrl mode */#define D_PIO2		(1<<2)	/* Pin 2: 1: Onboard PDN */#define D_PIO1		(1<<1)	/* Pin 1: 0: Reset */#define D_PIO0		(1<<0)	/* Pin 0: 1: Speakerbox PDN *//* DBRI Commands (Page 20) */#define D_WAIT		0x0	/* Stop execution */#define D_PAUSE		0x1	/* Flush long pipes */#define D_JUMP		0x2	/* New command queue */#define D_IIQ		0x3	/* Initialize Interrupt Queue */#define D_REX		0x4	/* Report command execution via interrupt */#define D_SDP		0x5	/* Setup Data Pipe */#define D_CDP		0x6	/* Continue Data Pipe (reread NULL Pointer) */#define D_DTS		0x7	/* Define Time Slot */#define D_SSP		0x8	/* Set short Data Pipe */#define D_CHI		0x9	/* Set CHI Global Mode */#define D_NT		0xa	/* NT Command */#define D_TE		0xb	/* TE Command */#define D_CDEC		0xc	/* Codec setup */#define D_TEST		0xd	/* No comment */#define D_CDM		0xe	/* CHI Data mode command *//* Special bits for some commands */#define D_PIPE(v)      ((v)<<0)	/* Pipe No.: 0-15 long, 16-21 short *//* Setup Data Pipe *//* IRM */#define D_SDP_2SAME	(1<<18)	/* Report 2nd time in a row value received */#define D_SDP_CHANGE	(2<<18)	/* Report any changes */#define D_SDP_EVERY	(3<<18)	/* Report any changes */#define D_SDP_EOL	(1<<17)	/* EOL interrupt enable */#define D_SDP_IDLE	(1<<16)	/* HDLC idle interrupt enable *//* Pipe data MODE */#define D_SDP_MEM	(0<<13)	/* To/from memory */#define D_SDP_HDLC	(2<<13)#define D_SDP_HDLC_D	(3<<13)	/* D Channel (prio control) */#define D_SDP_SER	(4<<13)	/* Serial to serial */#define D_SDP_FIXED	(6<<13)	/* Short only */#define D_SDP_MODE(v)	((v)&(7<<13))#define D_SDP_TO_SER	(1<<12)	/* Direction */#define D_SDP_FROM_SER	(0<<12)	/* Direction */#define D_SDP_MSB	(1<<11)	/* Bit order within Byte */#define D_SDP_LSB	(0<<11)	/* Bit order within Byte */#define D_SDP_P		(1<<10)	/* Pointer Valid */#define D_SDP_A		(1<<8)	/* Abort */#define D_SDP_C		(1<<7)	/* Clear *//* Define Time Slot */#define D_DTS_VI	(1<<17)	/* Valid Input Time-Slot Descriptor */#define D_DTS_VO	(1<<16)	/* Valid Output Time-Slot Descriptor */#define D_DTS_INS	(1<<15)	/* Insert Time Slot */#define D_DTS_DEL	(0<<15)	/* Delete Time Slot */#define D_DTS_PRVIN(v) ((v)<<10)	/* Previous In Pipe */#define D_DTS_PRVOUT(v)        ((v)<<5)	/* Previous Out Pipe *//* Time Slot defines */#define D_TS_LEN(v)	((v)<<24)	/* Number of bits in this time slot */#define D_TS_CYCLE(v)	((v)<<14)	/* Bit Count at start of TS */#define D_TS_DI		(1<<13)	/* Data Invert */#define D_TS_1CHANNEL	(0<<10)	/* Single Channel / Normal mode */#define D_TS_MONITOR	(2<<10)	/* Monitor pipe */#define D_TS_NONCONTIG	(3<<10)	/* Non contiguous mode */#define D_TS_ANCHOR	(7<<10)	/* Starting short pipes */#define D_TS_MON(v)    ((v)<<5)	/* Monitor Pipe */#define D_TS_NEXT(v)   ((v)<<0)	/* Pipe no.: 0-15 long, 16-21 short *//* Concentration Highway Interface Modes */#define D_CHI_CHICM(v)	((v)<<16)	/* Clock mode */#define D_CHI_IR	(1<<15)	/* Immediate Interrupt Report */#define D_CHI_EN	(1<<14)	/* CHIL Interrupt enabled */#define D_CHI_OD	(1<<13)	/* Open Drain Enable */#define D_CHI_FE	(1<<12)	/* Sample CHIFS on Rising Frame Edge */#define D_CHI_FD	(1<<11)	/* Frame Drive */

⌨️ 快捷键说明

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