📄 hdspm.c
字号:
/* * ALSA driver for RME Hammerfall DSP MADI audio interface(s) * * Copyright (c) 2003 Winfried Ritsch (IEM) * code based on hdsp.c Paul Davis * Marcus Andersson * Thomas Charbonnel * Modified 2006-06-01 for AES32 support by Remy Bruno * <remy.bruno@trinnov.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */#include <sound/driver.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/moduleparam.h>#include <linux/slab.h>#include <linux/pci.h>#include <asm/io.h>#include <sound/core.h>#include <sound/control.h>#include <sound/pcm.h>#include <sound/info.h>#include <sound/asoundef.h>#include <sound/rawmidi.h>#include <sound/hwdep.h>#include <sound/initval.h>#include <sound/hdspm.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 *//* Disable precise pointer at start */static int precise_ptr[SNDRV_CARDS];/* Send all playback to line outs */static int line_outs_monitor[SNDRV_CARDS];/* Enable Analog Outs on Channel 63/64 by default */static int enable_monitor[SNDRV_CARDS];module_param_array(index, int, NULL, 0444);MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");module_param_array(id, charp, NULL, 0444);MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");module_param_array(enable, bool, NULL, 0444);MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");module_param_array(precise_ptr, bool, NULL, 0444);MODULE_PARM_DESC(precise_ptr, "Enable or disable precise pointer.");module_param_array(line_outs_monitor, bool, NULL, 0444);MODULE_PARM_DESC(line_outs_monitor, "Send playback streams to analog outs by default.");module_param_array(enable_monitor, bool, NULL, 0444);MODULE_PARM_DESC(enable_monitor, "Enable Analog Out on Channel 63/64 by default.");MODULE_AUTHOR ("Winfried Ritsch <ritsch_AT_iem.at>, " "Paul Davis <paul@linuxaudiosystems.com>, " "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, " "Remy Bruno <remy.bruno@trinnov.com>");MODULE_DESCRIPTION("RME HDSPM");MODULE_LICENSE("GPL");MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");/* --- Write registers. --- These are defined as byte-offsets from the iobase value. */#define HDSPM_controlRegister 64#define HDSPM_interruptConfirmation 96#define HDSPM_control2Reg 256 /* not in specs ???????? */#define HDSPM_freqReg 256 /* for AES32 */#define HDSPM_midiDataOut0 352 /* just believe in old code */#define HDSPM_midiDataOut1 356#define HDSPM_eeprom_wr 384 /* for AES32 *//* DMA enable for 64 channels, only Bit 0 is relevant */#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */ #define HDSPM_inputEnableBase 768 /* 768-1023 output DMA *//* 16 page addresses for each of the 64 channels DMA buffer in and out (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */#define HDSPM_pageAddressBufferOut 8192#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB *//* --- Read registers. --- These are defined as byte-offsets from the iobase value */#define HDSPM_statusRegister 0/*#define HDSPM_statusRegister2 96 *//* after RME Windows driver sources, status2 is 4-byte word # 48 = word at * offset 192, for AES32 *and* MADI * => need to check that offset 192 is working on MADI */#define HDSPM_statusRegister2 192#define HDSPM_timecodeRegister 128#define HDSPM_midiDataIn0 360#define HDSPM_midiDataIn1 364/* status is data bytes in MIDI-FIFO (0-128) */#define HDSPM_midiStatusOut0 384 #define HDSPM_midiStatusOut1 388 #define HDSPM_midiStatusIn0 392 #define HDSPM_midiStatusIn1 396 /* the meters are regular i/o-mapped registers, but offset considerably from the rest. the peak registers are reset when read; the least-significant 4 bits are full-scale counters; the actual peak value is in the most-significant 24 bits.*/#define HDSPM_MADI_peakrmsbase 4096 /* 4096-8191 2x64x32Bit Meters *//* --- Control Register bits --------- */#define HDSPM_Start (1<<0) /* start engine */#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */#define HDSPM_Latency1 (1<<2) /* where n is defined */#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */#define HDSPM_QuadSpeed (1<<31) /* quad speed bit */#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1, 56channelMODE=0 */ /* MADI ONLY*/#define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode, 0=off, 1=on */ /* MADI ONLY */#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax * -- MADI ONLY */#define HDSPM_InputSelect1 (1<<15) /* should be 0 */#define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */#define HDSPM_SyncRef1 (1<<17) /* for AES32: SyncRefN codes the AES # */#define HDSPM_SyncRef2 (1<<13)#define HDSPM_SyncRef3 (1<<25)#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use AES additional bits in lower 5 Audiodatabits ??? */#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */#define HDSPM_Midi0InterruptEnable (1<<22)#define HDSPM_Midi1InterruptEnable (1<<23)#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */#define HDSPM_wclk_sel (1<<30)/* --- bit helper defines */#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\ HDSPM_DoubleSpeed|HDSPM_QuadSpeed)#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)#define HDSPM_InputOptical 0#define HDSPM_InputCoaxial (HDSPM_InputSelect0)#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\ HDSPM_SyncRef2|HDSPM_SyncRef3)#define HDSPM_SyncRef_Word 0#define HDSPM_SyncRef_MADI (HDSPM_SyncRef0)#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */#define HDSPM_Frequency32KHz HDSPM_Frequency0#define HDSPM_Frequency44_1KHz HDSPM_Frequency1#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\ HDSPM_Frequency0)#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\ HDSPM_Frequency0)/* --- for internal discrimination */#define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */#define HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ 1#define HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ 2#define HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ 3#define HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ 4#define HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ 5#define HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ 6#define HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ 7#define HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ 8#define HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ 9/* Synccheck Status */#define HDSPM_SYNC_CHECK_NO_LOCK 0#define HDSPM_SYNC_CHECK_LOCK 1#define HDSPM_SYNC_CHECK_SYNC 2/* AutoSync References - used by "autosync_ref" control switch */#define HDSPM_AUTOSYNC_FROM_WORD 0#define HDSPM_AUTOSYNC_FROM_MADI 1#define HDSPM_AUTOSYNC_FROM_NONE 2/* Possible sources of MADI input */#define HDSPM_OPTICAL 0 /* optical */#define HDSPM_COAXIAL 1 /* BNC */#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)#define hdspm_decode_latency(x) (((x) & HDSPM_LatencyMask)>>1)#define hdspm_encode_in(x) (((x)&0x3)<<14)#define hdspm_decode_in(x) (((x)>>14)&0x3)/* --- control2 register bits --- */#define HDSPM_TMS (1<<0)#define HDSPM_TCK (1<<1)#define HDSPM_TDI (1<<2)#define HDSPM_JTAG (1<<3)#define HDSPM_PWDN (1<<4)#define HDSPM_PROGRAM (1<<5)#define HDSPM_CONFIG_MODE_0 (1<<6)#define HDSPM_CONFIG_MODE_1 (1<<7)/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/#define HDSPM_BIGENDIAN_MODE (1<<9)#define HDSPM_RD_MULTIPLE (1<<10)/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and that do not conflict with specific bits for AES32 seem to be valid also for the AES32 */#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 * (like inp0) */#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */ /* since 64byte accurate last 6 bits are not used */#define HDSPM_madiSync (1<<18) /* MADI is in sync */#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with * Interrupt */#define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */#define HDSPM_midi1IRQPending (1<<31) /* and aktiv *//* --- status bit helpers */#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\ HDSPM_madiFreq2|HDSPM_madiFreq3)#define HDSPM_madiFreq32 (HDSPM_madiFreq0)#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)#define HDSPM_madiFreq64 (HDSPM_madiFreq2)#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)/* Status2 Register bits */ /* MADI ONLY */#define HDSPM_version0 (1<<0) /* not realy defined but I guess */#define HDSPM_version1 (1<<1) /* in former cards it was ??? */#define HDSPM_version2 (1<<2)#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, *//* missing Bit for 111=128, 1000=176.4, 1001=192 */#define HDSPM_SelSyncRef0 (1<<8) /* Sync Source in slave mode */#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)#define HDSPM_wcFreq32 (HDSPM_wc_freq0)#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)#define HDSPM_wcFreq64 (HDSPM_wc_freq2)#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\ HDSPM_SelSyncRef2)#define HDSPM_SelSyncRef_WORD 0#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\ HDSPM_SelSyncRef2)/* For AES32, bits for status, status2 and timecode are different*//* status */#define HDSPM_AES32_wcLock 0x0200000#define HDSPM_AES32_wcFreq_bit 22/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function HDSPM_bit2freq */#define HDSPM_AES32_syncref_bit 16/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8#define HDSPM_AES32_AUTOSYNC_FROM_NONE 9/* status2 *//* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */#define HDSPM_LockAES 0x80#define HDSPM_LockAES1 0x80#define HDSPM_LockAES2 0x40#define HDSPM_LockAES3 0x20#define HDSPM_LockAES4 0x10#define HDSPM_LockAES5 0x8#define HDSPM_LockAES6 0x4#define HDSPM_LockAES7 0x2#define HDSPM_LockAES8 0x1/* Timecode After windows driver sources, bits 4*i to 4*i+3 give the input frequency on AES i+1 bits 3210 0001 32kHz 0010 44.1kHz 0011 48kHz 0100 64kHz 0101 88.2kHz 0110 96kHz 0111 128kHz 1000 176.4kHz 1001 192kHz NB: Timecode register doesn't seem to work on AES32 card revision 230*//* Mixer Values */#define UNITY_GAIN 32768 /* = 65536/2 */#define MINUS_INFINITY_GAIN 0/* Number of channels for different Speed Modes */#define MADI_SS_CHANNELS 64#define MADI_DS_CHANNELS 32#define MADI_QS_CHANNELS 16/* the size of a substream (1 mono data stream) */#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_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, and also the latency to use. for one direction !!!*/#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)/* revisions >= 230 indicate AES32 card */#define HDSPM_AESREVISION 230/* speed factor modes */#define HDSPM_SPEED_SINGLE 0#define HDSPM_SPEED_DOUBLE 1#define HDSPM_SPEED_QUAD 2/* names for speed modes */static char *hdspm_speed_names[] = { "single", "double", "quad" };struct hdspm_midi { struct hdspm *hdspm; int id; struct snd_rawmidi *rmidi; struct snd_rawmidi_substream *input; struct snd_rawmidi_substream *output; char istimer; /* timer in use */ struct timer_list timer; spinlock_t lock; int pending;};struct hdspm { spinlock_t lock; /* only one playback and/or capture stream */ struct snd_pcm_substream *capture_substream; struct snd_pcm_substream *playback_substream; char *card_name; /* for procinfo */ unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/ unsigned char is_aes32; /* indicates if card is AES32 */ int precise_ptr; /* use precise pointers, to be tested */ int monitor_outs; /* set up monitoring outs init flag */ u32 control_register; /* cached value */ u32 control2_register; /* cached value */ struct hdspm_midi midi[2]; struct tasklet_struct midi_tasklet; size_t period_bytes; unsigned char ss_channels; /* channels of card in single speed */ unsigned char ds_channels; /* Double Speed */ unsigned char qs_channels; /* Quad Speed */ unsigned char *playback_buffer; /* suitably aligned address */ unsigned char *capture_buffer; /* suitably aligned address */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -