rme96xx.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,862 行 · 第 1/4 页

C
1,862
字号
/* (C) 2000 Guenter Geiger <geiger@debian.org>   with copy/pastes from the driver of Winfried Ritsch <ritsch@iem.kug.ac.at>   based on es1370.c   *  10 Jan 2001: 0.1 initial version   *  19 Jan 2001: 0.2 fixed bug in select()   *  27 Apr 2001: 0.3 more than one card usable   *  11 May 2001: 0.4 fixed for SMP, included into kernel source tree   *  17 May 2001: 0.5 draining code didn't work on new cards   *  18 May 2001: 0.6 remove synchronize_irq() call    *  17 Jul 2001: 0.7 updated xrmectrl to make it work for newer cards   *   2 feb 2002: 0.8 fixed pci device handling, see below for patches from Heiko (Thanks!)                       Marcus Meissner <Marcus.Meissner@caldera.de>		       Modifications - Heiko Purnhagen <purnhage@tnt.uni-hannover.de>		       HP20020108 fixed handling of "large" read()		       HP20020116 towards REV 1.5 support, based on ALSA's card-rme9652.c		       HP20020118 made mixer ioctl and handling of devices>1 more safe		       HP20020201 fixed handling of "large" read() properly		       added REV 1.5 S/P-DIF receiver support		       SNDCTL_DSP_SPEED now returns the actual speed   *  10 Aug 2002: added synchronize_irq() againTODO:   - test more than one card --- done   - check for pci IOREGION (see es1370) in rme96xx_probe ??   - error detection   - mmap interface   - mixer mmap interface   - mixer ioctl   - get rid of noise upon first open (why ??)   - allow multiple open (at least for read)   - allow multiple open for non overlapping regions   - recheck the multiple devices part (offsets of different devices, etc)   - do decent draining in _release --- done   - SMP support   - what about using fragstotal>2 for small fragsize? (HP20020118)   - add support for AFMT_S32_LE*/#ifndef RMEVERSION#define RMEVERSION "0.8"#endif#include <linux/version.h>#include <linux/module.h>#include <linux/string.h>#include <linux/sched.h>#include <linux/sound.h>#include <linux/soundcard.h>#include <linux/pci.h>#include <linux/smp_lock.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/poll.h>#include <linux/wait.h>#include <asm/dma.h>#include <asm/page.h>#include "rme96xx.h"#define NR_DEVICE 2static int devices = 1;MODULE_PARM(devices, "1-" __MODULE_STRING(NR_DEVICE) "i");MODULE_PARM_DESC(devices, "number of dsp devices allocated by the driver");MODULE_AUTHOR("Guenter Geiger, geiger@debian.org");MODULE_DESCRIPTION("RME9652/36 \"Hammerfall\" Driver");MODULE_LICENSE("GPL");#ifdef DEBUG#define DBG(x) printk("RME_DEBUG:");x#define COMM(x) printk("RME_COMM: " x "\n");#else#define DBG(x) while (0) {}#define COMM(x)#endif/*--------------------------------------------------------------------------                         Preporcessor Macros and Definitions --------------------------------------------------------------------------*/#define RME96xx_MAGIC 0x6473/* Registers-Space in offsets from base address with 16MByte size */#define RME96xx_IO_EXTENT     16l*1024l*1024l#define RME96xx_CHANNELS_PER_CARD 26/*                  Write - Register *//* 0,4,8,12,16,20,24,28 ... hardware init (erasing fifo-pointer intern) */#define RME96xx_num_of_init_regs   8#define RME96xx_init_buffer       (0/4)#define RME96xx_play_buffer       (32/4)  /* pointer to 26x64kBit RAM from mainboard */#define RME96xx_rec_buffer        (36/4)  /* pointer to 26x64kBit RAM from mainboard */#define RME96xx_control_register  (64/4)  /* exact meaning see below */#define RME96xx_irq_clear         (96/4)  /* irq acknowledge */#define RME96xx_time_code         (100/4) /* if used with alesis adat */#define RME96xx_thru_base         (128/4) /* 132...228 Thru for 26 channels */#define RME96xx_thru_channels     RME96xx_CHANNELS_PER_CARD/*                     Read Register */#define RME96xx_status_register    0     /* meaning see below *//* Status Register: *//* ------------------------------------------------------------------------ */#define RME96xx_IRQ          0x0000001 /* IRQ is High if not reset by RMExx_irq_clear */#define RME96xx_lock_2       0x0000002 /* ADAT 3-PLL: 1=locked, 0=unlocked */#define RME96xx_lock_1       0x0000004 /* ADAT 2-PLL: 1=locked, 0=unlocked */#define RME96xx_lock_0       0x0000008 /* ADAT 1-PLL: 1=locked, 0=unlocked */#define RME96xx_fs48         0x0000010 /* sample rate 0 ...44.1/88.2,  1 ... 48/96 Khz */#define RME96xx_wsel_rd      0x0000020 /* if Word-Clock is used and valid then 1 */#define RME96xx_buf_pos1     0x0000040 /* Bit 6..15 : Position of buffer-pointer in 64Bytes-blocks */#define RME96xx_buf_pos2     0x0000080 /* resolution +/- 1 64Byte/block (since 64Bytes bursts) */ #define RME96xx_buf_pos3     0x0000100 /* 10 bits = 1024 values */#define RME96xx_buf_pos4     0x0000200 /* if we mask off the first 6 bits, we can take the status */#define RME96xx_buf_pos5     0x0000400 /* register as sample counter in the hardware buffer */#define RME96xx_buf_pos6     0x0000800 #define RME96xx_buf_pos7     0x0001000 #define RME96xx_buf_pos8     0x0002000 #define RME96xx_buf_pos9     0x0004000#define RME96xx_buf_pos10    0x0008000 #define RME96xx_sync_2       0x0010000 /* if ADAT-IN3 synced to system clock */#define RME96xx_sync_1       0x0020000 /* if ADAT-IN2 synced to system clock */#define RME96xx_sync_0       0x0040000 /* if ADAT-IN1 synced to system clock */#define RME96xx_DS_rd        0x0080000 /* 1=Double Speed, 0=Normal Speed */#define RME96xx_tc_busy      0x0100000 /* 1=time-code copy in progress (960ms) */#define RME96xx_tc_out       0x0200000 /* time-code out bit */#define RME96xx_F_0          0x0400000 /*  000=64kHz, 100=88.2kHz, 011=96kHz  */#define RME96xx_F_1          0x0800000 /*  111=32kHz, 110=44.1kHz, 101=48kHz, */#define RME96xx_F_2          0x1000000 /*  001=Rev 1.5+ external Crystal Chip */#define RME96xx_ERF          0x2000000 /* Error-Flag of SDPIF Receiver (1=No Lock)*/#define RME96xx_buffer_id    0x4000000 /* toggles by each interrupt on rec/play */#define RME96xx_tc_valid     0x8000000 /* 1 = a signal is detected on time-code input */#define RME96xx_SPDIF_READ  0x10000000 /* byte available from Rev 1.5+ SPDIF interface *//* Status Register Fields */#define RME96xx_lock            (RME96xx_lock_0|RME96xx_lock_1|RME96xx_lock_2)#define RME96xx_sync            (RME96xx_sync_0|RME96xx_sync_1|RME96xx_sync_2)#define RME96xx_F               (RME96xx_F_0|RME96xx_F_1|RME96xx_F_2)#define rme96xx_decode_spdif_rate(x) ((x)>>22)/* Bit 6..15 : h/w buffer pointer */#define RME96xx_buf_pos          0x000FFC0 /* Bits 31,30,29 are bits 5,4,3 of h/w pointer position on later   Rev G EEPROMS and Rev 1.5 cards or later.*/ #define RME96xx_REV15_buf_pos(x) ((((x)&0xE0000000)>>26)|((x)&RME96xx_buf_pos))/* Control-Register: */			    /*--------------------------------------------------------------------------------*/#define RME96xx_start_bit	0x0001 /* start record/play */#define RME96xx_latency0	0x0002 /* Buffer size / latency */#define RME96xx_latency1	0x0004 /*   buffersize = 512Bytes * 2^n */#define RME96xx_latency2	0x0008 /*   0=64samples ... 7=8192samples */#define RME96xx_Master		0x0010 /* Clock Mode 1=Master, 0=Slave/Auto */#define RME96xx_IE		0x0020 /* Interupt Enable */#define RME96xx_freq		0x0040 /* samplerate 0=44.1/88.2, 1=48/96 kHz*/#define RME96xx_freq1		0x0080 /* samplerate 0=32 kHz, 1=other rates ??? (from ALSA, but may be wrong) */#define RME96xx_DS              0x0100 /* double speed 0=44.1/48, 1=88.2/96 Khz */#define RME96xx_PRO		0x0200 /* SPDIF-OUT 0=consumer, 1=professional */#define RME96xx_EMP		0x0400 /* SPDIF-OUT emphasis 0=off, 1=on */#define RME96xx_Dolby		0x0800 /* SPDIF-OUT non-audio bit 1=set, 0=unset */#define RME96xx_opt_out	        0x1000 /* use 1st optical OUT as SPDIF: 1=yes, 0=no */#define RME96xx_wsel            0x2000 /* use Wordclock as sync (overwrites master) */#define RME96xx_inp_0           0x4000 /* SPDIF-IN 00=optical (ADAT1), */#define RME96xx_inp_1           0x8000 /* 01=coaxial (Cinch), 10=internal CDROM */#define RME96xx_SyncRef0       0x10000 /* preferred sync-source in autosync */#define RME96xx_SyncRef1       0x20000 /* 00=ADAT1, 01=ADAT2, 10=ADAT3, 11=SPDIF */#define RME96xx_SPDIF_RESET    (1<<18) /* Rev 1.5+: h/w SPDIF receiver */#define RME96xx_SPDIF_SELECT   (1<<19)#define RME96xx_SPDIF_CLOCK    (1<<20)#define RME96xx_SPDIF_WRITE    (1<<21)#define RME96xx_ADAT1_INTERNAL (1<<22) /* Rev 1.5+: if set, internal CD connector carries ADAT */#define RME96xx_ctrl_init            (RME96xx_latency0 |\                                     RME96xx_Master |\                                     RME96xx_inp_1)                              /* Control register fields and shortcuts */#define RME96xx_latency (RME96xx_latency0|RME96xx_latency1|RME96xx_latency2)#define RME96xx_inp         (RME96xx_inp_0|RME96xx_inp_1)#define RME96xx_SyncRef    (RME96xx_SyncRef0|RME96xx_SyncRef1)#define RME96xx_mixer_allowed (RME96xx_Master|RME96xx_PRO|RME96xx_EMP|RME96xx_Dolby|RME96xx_opt_out|RME96xx_wsel|RME96xx_inp|RME96xx_SyncRef|RME96xx_ADAT1_INTERNAL)/* latency = 512Bytes * 2^n, where n is made from Bit3 ... Bit1  (??? HP20020201) */#define RME96xx_SET_LATENCY(x)   (((x)&0x7)<<1)#define RME96xx_GET_LATENCY(x)   (((x)>>1)&0x7)#define RME96xx_SET_inp(x) (((x)&0x3)<<14)#define RME96xx_GET_inp(x)   (((x)>>14)&0x3)#define RME96xx_SET_SyncRef(x) (((x)&0x3)<<17)#define RME96xx_GET_SyncRef(x)   (((x)>>17)&0x3)/* buffer sizes */#define RME96xx_BYTES_PER_SAMPLE  4 /* sizeof(u32) */#define RME_16K 16*1024#define RME96xx_DMA_MAX_SAMPLES  (RME_16K)#define RME96xx_DMA_MAX_SIZE     (RME_16K * RME96xx_BYTES_PER_SAMPLE)#define RME96xx_DMA_MAX_SIZE_ALL (RME96xx_DMA_MAX_SIZE * RME96xx_CHANNELS_PER_CARD)#define RME96xx_NUM_OF_FRAGMENTS     2#define RME96xx_FRAGMENT_MAX_SIZE    (RME96xx_DMA_MAX_SIZE/2)#define RME96xx_FRAGMENT_MAX_SAMPLES (RME96xx_DMA_MAX_SAMPLES/2)#define RME96xx_MAX_LATENCY       7   /* 16k samples */#define RME96xx_MAX_DEVS 4 /* we provide some OSS stereodevs */#define RME96xx_MASK_DEVS 0x3 /* RME96xx_MAX_DEVS-1 */#define RME_MESS "rme96xx:"/*------------------------------------------------------------------------                   Types, struct and function declarations  ------------------------------------------------------------------------*//* --------------------------------------------------------------------- */static const char invalid_magic[] = KERN_CRIT RME_MESS" invalid magic value\n";#define VALIDATE_STATE(s)                         \({                                                \	if (!(s) || (s)->magic != RME96xx_MAGIC) { \		printk(invalid_magic);            \		return -ENXIO;                    \	}                                         \})/* --------------------------------------------------------------------- */static struct file_operations rme96xx_audio_fops;static struct file_operations rme96xx_mixer_fops;static int numcards;typedef int32_t raw_sample_t;typedef struct _rme96xx_info {	/* hardware settings */	int magic;	struct pci_dev * pcidev; /* pci_dev structure */	unsigned long *iobase;		unsigned int irq;	/* list of rme96xx devices */	struct list_head devs;	spinlock_t lock;	u32 *recbuf;             /* memory for rec buffer */	u32 *playbuf;            /* memory for play buffer */	u32 control_register;	u32 thru_bits; /* thru 1=on, 0=off channel 1=Bit1... channel 26= Bit26 */	int hw_rev;             /* h/w rev * 10 (i.e. 1.5 has hw_rev = 15) */	char *card_name;	/* hammerfall or hammerfall light names */	int open_count;         /* unused ???   HP20020201 */	int rate;	int latency;	unsigned int fragsize;	int started;	int hwptr; /* can be negativ because of pci burst offset  */	unsigned int hwbufid;  /* set by interrupt, buffer which is written/read now */		struct dmabuf {		unsigned int format;		int formatshift;		int inchannels;       /* number of channels for device */		int outchannels;       /* number of channels for device */		int mono; /* if true, we play mono on 2 channels */		int inoffset; /* which channel is considered the first one */         	int outoffset;				/* state */		int opened;               /* open() made */		int started;              /* first write/read */		int mmapped;              /* mmap */		int open_mode;		struct _rme96xx_info *s;  		/* pointer to read/write position in buffer */		unsigned readptr;          		unsigned writeptr;          		unsigned error; /* over/underruns cleared on sync again */		/* waiting and locking */		wait_queue_head_t wait;		struct semaphore  open_sem;		wait_queue_head_t open_wait;	} dma[RME96xx_MAX_DEVS]; 	int dspnum[RME96xx_MAX_DEVS];  /* register with sound subsystem */ 	int mixer;  /* register with sound subsystem */ } rme96xx_info;/* fiddling with the card (first level hardware control) */inline void rme96xx_set_ctrl(rme96xx_info* s,int mask){	s->control_register|=mask;	writel(s->control_register,s->iobase + RME96xx_control_register);}inline void rme96xx_unset_ctrl(rme96xx_info* s,int mask){	s->control_register&=(~mask);	writel(s->control_register,s->iobase + RME96xx_control_register);}inline int rme96xx_get_sample_rate_status(rme96xx_info* s){	int val;	u32 status;	status = readl(s->iobase + RME96xx_status_register);	val = (status & RME96xx_fs48) ? 48000 : 44100;	if (status & RME96xx_DS_rd)		val *= 2;	return val;}inline int rme96xx_get_sample_rate_ctrl(rme96xx_info* s){	int val;	val = (s->control_register & RME96xx_freq) ? 48000 : 44100;	if (s->control_register & RME96xx_DS)		val *= 2;	return val;}/* code from ALSA card-rme9652.c for rev 1.5 SPDIF receiver   HP 20020201 */static void rme96xx_spdif_set_bit (rme96xx_info* s, int mask, int onoff){	if (onoff) 		s->control_register |= mask;	else 		s->control_register &= ~mask;			writel(s->control_register,s->iobase + RME96xx_control_register);}static void rme96xx_spdif_write_byte (rme96xx_info* s, const int val){	long mask;	long i;	for (i = 0, mask = 0x80; i < 8; i++, mask >>= 1) {		if (val & mask)			rme96xx_spdif_set_bit (s, RME96xx_SPDIF_WRITE, 1);		else 			rme96xx_spdif_set_bit (s, RME96xx_SPDIF_WRITE, 0);		rme96xx_spdif_set_bit (s, RME96xx_SPDIF_CLOCK, 1);		rme96xx_spdif_set_bit (s, RME96xx_SPDIF_CLOCK, 0);	}}static int rme96xx_spdif_read_byte (rme96xx_info* s){	long mask;	long val;	long i;	val = 0;	for (i = 0, mask = 0x80;  i < 8; i++, mask >>= 1) {		rme96xx_spdif_set_bit (s, RME96xx_SPDIF_CLOCK, 1);		if (readl(s->iobase + RME96xx_status_register) & RME96xx_SPDIF_READ)			val |= mask;		rme96xx_spdif_set_bit (s, RME96xx_SPDIF_CLOCK, 0);	}	return val;}static void rme96xx_write_spdif_codec (rme96xx_info* s, const int address, const int data){	rme96xx_spdif_set_bit (s, RME96xx_SPDIF_SELECT, 1);	rme96xx_spdif_write_byte (s, 0x20);	rme96xx_spdif_write_byte (s, address);	rme96xx_spdif_write_byte (s, data);	rme96xx_spdif_set_bit (s, RME96xx_SPDIF_SELECT, 0);}static int rme96xx_spdif_read_codec (rme96xx_info* s, const int address){	int ret;	rme96xx_spdif_set_bit (s, RME96xx_SPDIF_SELECT, 1);	rme96xx_spdif_write_byte (s, 0x20);	rme96xx_spdif_write_byte (s, address);	rme96xx_spdif_set_bit (s, RME96xx_SPDIF_SELECT, 0);	rme96xx_spdif_set_bit (s, RME96xx_SPDIF_SELECT, 1);	rme96xx_spdif_write_byte (s, 0x21);	ret = rme96xx_spdif_read_byte (s);	rme96xx_spdif_set_bit (s, RME96xx_SPDIF_SELECT, 0);	return ret;}static void rme96xx_initialize_spdif_receiver (rme96xx_info* s){	/* XXX what unsets this ? */	/* no idea ???   HP 20020201 */	s->control_register |= RME96xx_SPDIF_RESET;	rme96xx_write_spdif_codec (s, 4, 0x40);	rme96xx_write_spdif_codec (s, 17, 0x13);	rme96xx_write_spdif_codec (s, 6, 0x02);}static inline int rme96xx_spdif_sample_rate (rme96xx_info *s, int *spdifrate){	unsigned int rate_bits;

⌨️ 快捷键说明

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