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 + -
显示快捷键?