📄 rme9652.c
字号:
/* * ALSA driver for RME Digi9652 audio interfaces * * Copyright (c) 1999 IEM - Winfried Ritsch * Copyright (c) 1999-2001 Paul Davis * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */#include <sound/driver.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/pci.h>#include <linux/slab.h>#include <linux/moduleparam.h>#include <sound/core.h>#include <sound/control.h>#include <sound/pcm.h>#include <sound/info.h>#include <sound/asoundef.h>#include <sound/initval.h>#include <asm/current.h>#include <asm/io.h>static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */static int precise_ptr[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* Enable precise pointer */static int boot_devs;module_param_array(index, int, boot_devs, 0444);MODULE_PARM_DESC(index, "Index value for RME Digi9652 (Hammerfall) soundcard.");MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);module_param_array(id, charp, boot_devs, 0444);MODULE_PARM_DESC(id, "ID string for RME Digi9652 (Hammerfall) soundcard.");MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);module_param_array(enable, bool, boot_devs, 0444);MODULE_PARM_DESC(enable, "Enable/disable specific RME96{52,36} soundcards.");MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);module_param_array(precise_ptr, bool, boot_devs, 0444);MODULE_PARM_DESC(precise_ptr, "Enable precise pointer (doesn't work reliably).");MODULE_PARM_SYNTAX(precise_ptr, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);MODULE_AUTHOR("Paul Davis <pbd@op.net>, Winfried Ritsch");MODULE_DESCRIPTION("RME Digi9652/Digi9636");MODULE_LICENSE("GPL");MODULE_CLASSES("{sound}");MODULE_DEVICES("{{RME,Hammerfall}," "{RME,Hammerfall-Light}}");/* The Hammerfall has two sets of 24 ADAT + 2 S/PDIF channels, one for capture, one for playback. Both the ADAT and S/PDIF channels appear to the host CPU in the same block of memory. There is no functional difference between them in terms of access. The Hammerfall Light is identical to the Hammerfall, except that it has 2 sets 18 channels (16 ADAT + 2 S/PDIF) for capture and playback.*/#define RME9652_NCHANNELS 26#define RME9636_NCHANNELS 18/* Preferred sync source choices - used by "sync_pref" control switch */#define RME9652_SYNC_FROM_SPDIF 0#define RME9652_SYNC_FROM_ADAT1 1#define RME9652_SYNC_FROM_ADAT2 2#define RME9652_SYNC_FROM_ADAT3 3/* Possible sources of S/PDIF input */#define RME9652_SPDIFIN_OPTICAL 0 /* optical (ADAT1) */#define RME9652_SPDIFIN_COAXIAL 1 /* coaxial (RCA) */#define RME9652_SPDIFIN_INTERN 2 /* internal (CDROM) *//* ------------- Status-Register bits --------------------- */#define RME9652_IRQ (1<<0) /* IRQ is High if not reset by irq_clear */#define RME9652_lock_2 (1<<1) /* ADAT 3-PLL: 1=locked, 0=unlocked */#define RME9652_lock_1 (1<<2) /* ADAT 2-PLL: 1=locked, 0=unlocked */#define RME9652_lock_0 (1<<3) /* ADAT 1-PLL: 1=locked, 0=unlocked */#define RME9652_fs48 (1<<4) /* sample rate is 0=44.1/88.2,1=48/96 Khz */#define RME9652_wsel_rd (1<<5) /* if Word-Clock is used and valid then 1 */ /* bits 6-15 encode h/w buffer pointer position */#define RME9652_sync_2 (1<<16) /* if ADAT-IN 3 in sync to system clock */#define RME9652_sync_1 (1<<17) /* if ADAT-IN 2 in sync to system clock */#define RME9652_sync_0 (1<<18) /* if ADAT-IN 1 in sync to system clock */#define RME9652_DS_rd (1<<19) /* 1=Double Speed Mode, 0=Normal Speed */#define RME9652_tc_busy (1<<20) /* 1=time-code copy in progress (960ms) */#define RME9652_tc_out (1<<21) /* time-code out bit */#define RME9652_F_0 (1<<22) /* 000=64kHz, 100=88.2kHz, 011=96kHz */#define RME9652_F_1 (1<<23) /* 111=32kHz, 110=44.1kHz, 101=48kHz, */#define RME9652_F_2 (1<<24) /* external Crystal Chip if ERF=1 */#define RME9652_ERF (1<<25) /* Error-Flag of SDPIF Receiver (1=No Lock) */#define RME9652_buffer_id (1<<26) /* toggles by each interrupt on rec/play */#define RME9652_tc_valid (1<<27) /* 1 = a signal is detected on time-code input */#define RME9652_SPDIF_READ (1<<28) /* byte available from Rev 1.5+ S/PDIF interface */#define RME9652_sync (RME9652_sync_0|RME9652_sync_1|RME9652_sync_2)#define RME9652_lock (RME9652_lock_0|RME9652_lock_1|RME9652_lock_2)#define RME9652_F (RME9652_F_0|RME9652_F_1|RME9652_F_2)#define rme9652_decode_spdif_rate(x) ((x)>>22)/* Bit 6..15 : h/w buffer pointer */#define RME9652_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 RME9652_REV15_buf_pos(x) ((((x)&0xE0000000)>>26)|((x)&RME9652_buf_pos))#ifndef PCI_VENDOR_ID_XILINX#define PCI_VENDOR_ID_XILINX 0x10ee#endif#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL#define PCI_DEVICE_ID_XILINX_HAMMERFALL 0x3fc4#endif/* amount of io space we remap for register access. i'm not sure we even need this much, but 1K is nice round number :)*/#define RME9652_IO_EXTENT 1024#define RME9652_init_buffer 0#define RME9652_play_buffer 32 /* holds ptr to 26x64kBit host RAM */#define RME9652_rec_buffer 36 /* holds ptr to 26x64kBit host RAM */#define RME9652_control_register 64#define RME9652_irq_clear 96#define RME9652_time_code 100 /* useful if used with alesis adat */#define RME9652_thru_base 128 /* 132...228 Thru for 26 channels *//* Read-only registers *//* Writing to any of the register locations writes to the status register. We'll use the first location as our point of access.*/#define RME9652_status_register 0/* --------- Control-Register Bits ---------------- */#define RME9652_start_bit (1<<0) /* start record/play */ /* bits 1-3 encode buffersize/latency */#define RME9652_Master (1<<4) /* Clock Mode Master=1,Slave/Auto=0 */#define RME9652_IE (1<<5) /* Interupt Enable */#define RME9652_freq (1<<6) /* samplerate 0=44.1/88.2, 1=48/96 kHz */#define RME9652_freq1 (1<<7) /* if 0, 32kHz, else always 1 */#define RME9652_DS (1<<8) /* Doule Speed 0=44.1/48, 1=88.2/96 Khz */#define RME9652_PRO (1<<9) /* S/PDIF out: 0=consumer, 1=professional */#define RME9652_EMP (1<<10) /* Emphasis 0=None, 1=ON */#define RME9652_Dolby (1<<11) /* Non-audio bit 1=set, 0=unset */#define RME9652_opt_out (1<<12) /* Use 1st optical OUT as SPDIF: 1=yes,0=no */#define RME9652_wsel (1<<13) /* use Wordclock as sync (overwrites master) */#define RME9652_inp_0 (1<<14) /* SPDIF-IN: 00=optical (ADAT1), */#define RME9652_inp_1 (1<<15) /* 01=koaxial (Cinch), 10=Internal CDROM */#define RME9652_SyncPref_ADAT2 (1<<16)#define RME9652_SyncPref_ADAT3 (1<<17)#define RME9652_SPDIF_RESET (1<<18) /* Rev 1.5+: h/w S/PDIF receiver */#define RME9652_SPDIF_SELECT (1<<19)#define RME9652_SPDIF_CLOCK (1<<20)#define RME9652_SPDIF_WRITE (1<<21)#define RME9652_ADAT1_INTERNAL (1<<22) /* Rev 1.5+: if set, internal CD connector carries ADAT *//* buffersize = 512Bytes * 2^n, where n is made from Bit2 ... Bit0 */#define RME9652_latency 0x0e#define rme9652_encode_latency(x) (((x)&0x7)<<1)#define rme9652_decode_latency(x) (((x)>>1)&0x7)#define rme9652_running_double_speed(s) ((s)->control_register & RME9652_DS)#define RME9652_inp (RME9652_inp_0|RME9652_inp_1)#define rme9652_encode_spdif_in(x) (((x)&0x3)<<14)#define rme9652_decode_spdif_in(x) (((x)>>14)&0x3)#define RME9652_SyncPref_Mask (RME9652_SyncPref_ADAT2|RME9652_SyncPref_ADAT3)#define RME9652_SyncPref_ADAT1 0#define RME9652_SyncPref_SPDIF (RME9652_SyncPref_ADAT2|RME9652_SyncPref_ADAT3)/* the size of a substream (1 mono data stream) */#define RME9652_CHANNEL_BUFFER_SAMPLES (16*1024)#define RME9652_CHANNEL_BUFFER_BYTES (4*RME9652_CHANNEL_BUFFER_SAMPLES)/* the size of the area we need to allocate for DMA transfers. the size is the same regardless of the number of channels - the 9636 still uses the same memory area. Note that we allocate 1 more channel than is apparently needed because the h/w seems to write 1 byte beyond the end of the last page. Sigh.*/#define RME9652_DMA_AREA_BYTES ((RME9652_NCHANNELS+1) * RME9652_CHANNEL_BUFFER_BYTES)#define RME9652_DMA_AREA_KILOBYTES (RME9652_DMA_AREA_BYTES/1024)typedef struct snd_rme9652 { int dev; spinlock_t lock; int irq; unsigned long port; struct resource *res_port; unsigned long iobase; int precise_ptr; u32 control_register; /* cached value */ u32 thru_bits; /* thru 1=on, 0=off channel 1=Bit1... channel 26= Bit26 */ u32 creg_spdif; u32 creg_spdif_stream; char *card_name; /* hammerfall or hammerfall light names */ size_t hw_offsetmask; /* &-with status register to get real hw_offset */ size_t prev_hw_offset; /* previous hw offset */ size_t max_jitter; /* maximum jitter in frames for hw pointer */ size_t period_bytes; /* guess what this is */ unsigned char ds_channels; unsigned char ss_channels; /* different for hammerfall/hammerfall-light */ void *capture_buffer_unaligned; /* original buffer addresses */ void *playback_buffer_unaligned; /* original buffer addresses */ unsigned char *capture_buffer; /* suitably aligned address */ unsigned char *playback_buffer; /* suitably aligned address */ dma_addr_t capture_buffer_addr; dma_addr_t playback_buffer_addr; pid_t capture_pid; pid_t playback_pid; snd_pcm_substream_t *capture_substream; snd_pcm_substream_t *playback_substream; int running; int passthru; /* non-zero if doing pass-thru */ int hw_rev; /* h/w rev * 10 (i.e. 1.5 has hw_rev = 15) */ int last_spdif_sample_rate; /* so that we can catch externally ... */ int last_adat_sample_rate; /* ... induced rate changes */ char *channel_map; snd_card_t *card; snd_pcm_t *pcm; struct pci_dev *pci; snd_kcontrol_t *spdif_ctl;} rme9652_t;/* These tables map the ALSA channels 1..N to the channels that we need to use in order to find the relevant channel buffer. RME refer to this kind of mapping as between "the ADAT channel and the DMA channel." We index it using the logical audio channel, and the value is the DMA channel (i.e. channel buffer number) where the data for that channel can be read/written from/to.*/static char channel_map_9652_ss[26] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25};static char channel_map_9636_ss[26] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* channels 16 and 17 are S/PDIF */ 24, 25, /* channels 18-25 don't exist */ -1, -1, -1, -1, -1, -1, -1, -1};static char channel_map_9652_ds[26] = { /* ADAT channels are remapped */ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, /* channels 12 and 13 are S/PDIF */ 24, 25, /* others don't exist */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};static char channel_map_9636_ds[26] = { /* ADAT channels are remapped */ 1, 3, 5, 7, 9, 11, 13, 15, /* channels 8 and 9 are S/PDIF */ 24, 25 /* others don't exist */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};#define RME9652_PREALLOCATE_MEMORY /* via module snd-hammerfall-mem */#ifdef RME9652_PREALLOCATE_MEMORYstatic void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture){ struct snd_dma_device pdev; struct snd_dma_buffer dmbuf; memset(&pdev, 0, sizeof(pdev)); pdev.type = SNDRV_DMA_TYPE_DEV; pdev.dev = snd_dma_pci_data(pci); pdev.id = capture; dmbuf.bytes = 0; if (! snd_dma_get_reserved(&pdev, &dmbuf)) { if (snd_dma_alloc_pages(&pdev, size, &dmbuf) < 0) return NULL; snd_dma_set_reserved(&pdev, &dmbuf); } *addrp = dmbuf.addr; return dmbuf.area;}static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture){ struct snd_dma_device pdev; memset(&pdev, 0, sizeof(pdev)); pdev.type = SNDRV_DMA_TYPE_DEV; pdev.dev = snd_dma_pci_data(pci); pdev.id = capture; snd_dma_free_reserved(&pdev);}#elsestatic void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture){ return snd_malloc_pci_pages(pci, size, addrp);}static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture){ snd_free_pci_pages(pci, size, ptr, addr);}#endifstatic struct pci_device_id snd_rme9652_ids[] = { { .vendor = 0x10ee, .device = 0x3fc4, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, /* RME Digi9652 */ { 0, },};MODULE_DEVICE_TABLE(pci, snd_rme9652_ids);static inline void rme9652_write(rme9652_t *rme9652, int reg, int val){ writel(val, rme9652->iobase + reg);}static inline unsigned int rme9652_read(rme9652_t *rme9652, int reg){ return readl(rme9652->iobase + reg);}static inline int snd_rme9652_use_is_exclusive(rme9652_t *rme9652){ unsigned long flags; int ret = 1; spin_lock_irqsave(&rme9652->lock, flags); if ((rme9652->playback_pid != rme9652->capture_pid) && (rme9652->playback_pid >= 0) && (rme9652->capture_pid >= 0)) { ret = 0; } spin_unlock_irqrestore(&rme9652->lock, flags); return ret;}static inline int rme9652_adat_sample_rate(rme9652_t *rme9652){ if (rme9652_running_double_speed(rme9652)) { return (rme9652_read(rme9652, RME9652_status_register) & RME9652_fs48) ? 96000 : 88200; } else { return (rme9652_read(rme9652, RME9652_status_register) & RME9652_fs48) ? 48000 : 44100; }}static inline void rme9652_compute_period_size(rme9652_t *rme9652){ unsigned int i; i = rme9652->control_register & RME9652_latency; rme9652->period_bytes = 1 << ((rme9652_decode_latency(i) + 8)); rme9652->hw_offsetmask = (rme9652->period_bytes * 2 - 1) & RME9652_buf_pos; rme9652->max_jitter = 80;}static snd_pcm_uframes_t rme9652_hw_pointer(rme9652_t *rme9652){ int status; unsigned int offset, frag; snd_pcm_uframes_t period_size = rme9652->period_bytes / 4; snd_pcm_sframes_t delta; status = rme9652_read(rme9652, RME9652_status_register); if (!rme9652->precise_ptr) return (status & RME9652_buffer_id) ? period_size : 0; offset = status & RME9652_buf_pos; /* The hardware may give a backward movement for up to 80 frames Martin Kirst <martin.kirst@freenet.de> knows the details. */ delta = rme9652->prev_hw_offset - offset; delta &= 0xffff; if (delta <= (snd_pcm_sframes_t)rme9652->max_jitter * 4) offset = rme9652->prev_hw_offset; else rme9652->prev_hw_offset = offset; offset &= rme9652->hw_offsetmask; offset /= 4; frag = status & RME9652_buffer_id; if (offset < period_size) { if (offset > rme9652->max_jitter) { if (frag) printk(KERN_ERR "Unexpected hw_pointer position (bufid == 0): status: %x offset: %d\n", status, offset); } else if (!frag) return 0; offset -= rme9652->max_jitter; if (offset < 0) offset += period_size * 2; } else { if (offset > period_size + rme9652->max_jitter) { if (!frag) printk(KERN_ERR "Unexpected hw_pointer position (bufid == 1): status: %x offset: %d\n", status, offset); } else if (frag) return period_size; offset -= rme9652->max_jitter; } return offset;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -