aboutsummaryrefslogtreecommitdiff
path: root/sound/pci/rme9652/hdsp.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /sound/pci/rme9652/hdsp.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'sound/pci/rme9652/hdsp.c')
-rw-r--r--sound/pci/rme9652/hdsp.c5206
1 files changed, 5206 insertions, 0 deletions
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
new file mode 100644
index 00000000000..12efbf0fab5
--- /dev/null
+++ b/sound/pci/rme9652/hdsp.c
@@ -0,0 +1,5206 @@
+/*
+ * ALSA driver for RME Hammerfall DSP audio interface(s)
+ *
+ * Copyright (c) 2002 Paul Davis
+ * Marcus Andersson
+ * Thomas Charbonnel
+ *
+ * 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/slab.h>
+#include <linux/pci.h>
+#include <linux/firmware.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/rawmidi.h>
+#include <sound/hwdep.h>
+#include <sound/initval.h>
+#include <sound/hdsp.h>
+
+#include <asm/byteorder.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 */
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards.");
+MODULE_AUTHOR("Paul Davis <paul@linuxaudiosystems.com>, Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
+MODULE_DESCRIPTION("RME Hammerfall DSP");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
+ "{RME HDSP-9652},"
+ "{RME HDSP-9632}}");
+
+#define HDSP_MAX_CHANNELS 26
+#define HDSP_MAX_DS_CHANNELS 14
+#define HDSP_MAX_QS_CHANNELS 8
+#define DIGIFACE_SS_CHANNELS 26
+#define DIGIFACE_DS_CHANNELS 14
+#define MULTIFACE_SS_CHANNELS 18
+#define MULTIFACE_DS_CHANNELS 14
+#define H9652_SS_CHANNELS 26
+#define H9652_DS_CHANNELS 14
+/* This does not include possible Analog Extension Boards
+ AEBs are detected at card initialization
+*/
+#define H9632_SS_CHANNELS 12
+#define H9632_DS_CHANNELS 8
+#define H9632_QS_CHANNELS 4
+
+/* Write registers. These are defined as byte-offsets from the iobase value.
+ */
+#define HDSP_resetPointer 0
+#define HDSP_outputBufferAddress 32
+#define HDSP_inputBufferAddress 36
+#define HDSP_controlRegister 64
+#define HDSP_interruptConfirmation 96
+#define HDSP_outputEnable 128
+#define HDSP_control2Reg 256
+#define HDSP_midiDataOut0 352
+#define HDSP_midiDataOut1 356
+#define HDSP_fifoData 368
+#define HDSP_inputEnable 384
+
+/* Read registers. These are defined as byte-offsets from the iobase value
+ */
+
+#define HDSP_statusRegister 0
+#define HDSP_timecode 128
+#define HDSP_status2Register 192
+#define HDSP_midiDataOut0 352
+#define HDSP_midiDataOut1 356
+#define HDSP_midiDataIn0 360
+#define HDSP_midiDataIn1 364
+#define HDSP_midiStatusOut0 384
+#define HDSP_midiStatusOut1 388
+#define HDSP_midiStatusIn0 392
+#define HDSP_midiStatusIn1 396
+#define HDSP_fifoStatus 400
+
+/* 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 HDSP_playbackPeakLevel 4096 /* 26 * 32 bit values */
+#define HDSP_inputPeakLevel 4224 /* 26 * 32 bit values */
+#define HDSP_outputPeakLevel 4352 /* (26+2) * 32 bit values */
+#define HDSP_playbackRmsLevel 4612 /* 26 * 64 bit values */
+#define HDSP_inputRmsLevel 4868 /* 26 * 64 bit values */
+
+
+/* This is for H9652 cards
+ Peak values are read downward from the base
+ Rms values are read upward
+ There are rms values for the outputs too
+ 26*3 values are read in ss mode
+ 14*3 in ds mode, with no gap between values
+*/
+#define HDSP_9652_peakBase 7164
+#define HDSP_9652_rmsBase 4096
+
+/* c.f. the hdsp_9632_meters_t struct */
+#define HDSP_9632_metersBase 4096
+
+#define HDSP_IO_EXTENT 7168
+
+/* control2 register bits */
+
+#define HDSP_TMS 0x01
+#define HDSP_TCK 0x02
+#define HDSP_TDI 0x04
+#define HDSP_JTAG 0x08
+#define HDSP_PWDN 0x10
+#define HDSP_PROGRAM 0x020
+#define HDSP_CONFIG_MODE_0 0x040
+#define HDSP_CONFIG_MODE_1 0x080
+#define HDSP_VERSION_BIT 0x100
+#define HDSP_BIGENDIAN_MODE 0x200
+#define HDSP_RD_MULTIPLE 0x400
+#define HDSP_9652_ENABLE_MIXER 0x800
+#define HDSP_TDO 0x10000000
+
+#define HDSP_S_PROGRAM (HDSP_PROGRAM|HDSP_CONFIG_MODE_0)
+#define HDSP_S_LOAD (HDSP_PROGRAM|HDSP_CONFIG_MODE_1)
+
+/* Control Register bits */
+
+#define HDSP_Start (1<<0) /* start engine */
+#define HDSP_Latency0 (1<<1) /* buffer size = 2^n where n is defined by Latency{2,1,0} */
+#define HDSP_Latency1 (1<<2) /* [ see above ] */
+#define HDSP_Latency2 (1<<3) /* [ see above ] */
+#define HDSP_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */
+#define HDSP_AudioInterruptEnable (1<<5) /* what do you think ? */
+#define HDSP_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz/176.4kHz 1=48kHz/96kHz/192kHz */
+#define HDSP_Frequency1 (1<<7) /* 0=32kHz/64kHz/128kHz */
+#define HDSP_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
+#define HDSP_SPDIFProfessional (1<<9) /* 0=consumer, 1=professional */
+#define HDSP_SPDIFEmphasis (1<<10) /* 0=none, 1=on */
+#define HDSP_SPDIFNonAudio (1<<11) /* 0=off, 1=on */
+#define HDSP_SPDIFOpticalOut (1<<12) /* 1=use 1st ADAT connector for SPDIF, 0=do not */
+#define HDSP_SyncRef2 (1<<13)
+#define HDSP_SPDIFInputSelect0 (1<<14)
+#define HDSP_SPDIFInputSelect1 (1<<15)
+#define HDSP_SyncRef0 (1<<16)
+#define HDSP_SyncRef1 (1<<17)
+#define HDSP_AnalogExtensionBoard (1<<18) /* For H9632 cards */
+#define HDSP_XLRBreakoutCable (1<<20) /* For H9632 cards */
+#define HDSP_Midi0InterruptEnable (1<<22)
+#define HDSP_Midi1InterruptEnable (1<<23)
+#define HDSP_LineOut (1<<24)
+#define HDSP_ADGain0 (1<<25) /* From here : H9632 specific */
+#define HDSP_ADGain1 (1<<26)
+#define HDSP_DAGain0 (1<<27)
+#define HDSP_DAGain1 (1<<28)
+#define HDSP_PhoneGain0 (1<<29)
+#define HDSP_PhoneGain1 (1<<30)
+#define HDSP_QuadSpeed (1<<31)
+
+#define HDSP_ADGainMask (HDSP_ADGain0|HDSP_ADGain1)
+#define HDSP_ADGainMinus10dBV HDSP_ADGainMask
+#define HDSP_ADGainPlus4dBu (HDSP_ADGain0)
+#define HDSP_ADGainLowGain 0
+
+#define HDSP_DAGainMask (HDSP_DAGain0|HDSP_DAGain1)
+#define HDSP_DAGainHighGain HDSP_DAGainMask
+#define HDSP_DAGainPlus4dBu (HDSP_DAGain0)
+#define HDSP_DAGainMinus10dBV 0
+
+#define HDSP_PhoneGainMask (HDSP_PhoneGain0|HDSP_PhoneGain1)
+#define HDSP_PhoneGain0dB HDSP_PhoneGainMask
+#define HDSP_PhoneGainMinus6dB (HDSP_PhoneGain0)
+#define HDSP_PhoneGainMinus12dB 0
+
+#define HDSP_LatencyMask (HDSP_Latency0|HDSP_Latency1|HDSP_Latency2)
+#define HDSP_FrequencyMask (HDSP_Frequency0|HDSP_Frequency1|HDSP_DoubleSpeed|HDSP_QuadSpeed)
+
+#define HDSP_SPDIFInputMask (HDSP_SPDIFInputSelect0|HDSP_SPDIFInputSelect1)
+#define HDSP_SPDIFInputADAT1 0
+#define HDSP_SPDIFInputCoaxial (HDSP_SPDIFInputSelect0)
+#define HDSP_SPDIFInputCdrom (HDSP_SPDIFInputSelect1)
+#define HDSP_SPDIFInputAES (HDSP_SPDIFInputSelect0|HDSP_SPDIFInputSelect1)
+
+#define HDSP_SyncRefMask (HDSP_SyncRef0|HDSP_SyncRef1|HDSP_SyncRef2)
+#define HDSP_SyncRef_ADAT1 0
+#define HDSP_SyncRef_ADAT2 (HDSP_SyncRef0)
+#define HDSP_SyncRef_ADAT3 (HDSP_SyncRef1)
+#define HDSP_SyncRef_SPDIF (HDSP_SyncRef0|HDSP_SyncRef1)
+#define HDSP_SyncRef_WORD (HDSP_SyncRef2)
+#define HDSP_SyncRef_ADAT_SYNC (HDSP_SyncRef0|HDSP_SyncRef2)
+
+/* Sample Clock Sources */
+
+#define HDSP_CLOCK_SOURCE_AUTOSYNC 0
+#define HDSP_CLOCK_SOURCE_INTERNAL_32KHZ 1
+#define HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ 2
+#define HDSP_CLOCK_SOURCE_INTERNAL_48KHZ 3
+#define HDSP_CLOCK_SOURCE_INTERNAL_64KHZ 4
+#define HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ 5
+#define HDSP_CLOCK_SOURCE_INTERNAL_96KHZ 6
+#define HDSP_CLOCK_SOURCE_INTERNAL_128KHZ 7
+#define HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ 8
+#define HDSP_CLOCK_SOURCE_INTERNAL_192KHZ 9
+
+/* Preferred sync reference choices - used by "pref_sync_ref" control switch */
+
+#define HDSP_SYNC_FROM_WORD 0
+#define HDSP_SYNC_FROM_SPDIF 1
+#define HDSP_SYNC_FROM_ADAT1 2
+#define HDSP_SYNC_FROM_ADAT_SYNC 3
+#define HDSP_SYNC_FROM_ADAT2 4
+#define HDSP_SYNC_FROM_ADAT3 5
+
+/* SyncCheck status */
+
+#define HDSP_SYNC_CHECK_NO_LOCK 0
+#define HDSP_SYNC_CHECK_LOCK 1
+#define HDSP_SYNC_CHECK_SYNC 2
+
+/* AutoSync references - used by "autosync_ref" control switch */
+
+#define HDSP_AUTOSYNC_FROM_WORD 0
+#define HDSP_AUTOSYNC_FROM_ADAT_SYNC 1
+#define HDSP_AUTOSYNC_FROM_SPDIF 2
+#define HDSP_AUTOSYNC_FROM_NONE 3
+#define HDSP_AUTOSYNC_FROM_ADAT1 4
+#define HDSP_AUTOSYNC_FROM_ADAT2 5
+#define HDSP_AUTOSYNC_FROM_ADAT3 6
+
+/* Possible sources of S/PDIF input */
+
+#define HDSP_SPDIFIN_OPTICAL 0 /* optical (ADAT1) */
+#define HDSP_SPDIFIN_COAXIAL 1 /* coaxial (RCA) */
+#define HDSP_SPDIFIN_INTERNAL 2 /* internal (CDROM) */
+#define HDSP_SPDIFIN_AES 3 /* xlr for H9632 (AES)*/
+
+#define HDSP_Frequency32KHz HDSP_Frequency0
+#define HDSP_Frequency44_1KHz HDSP_Frequency1
+#define HDSP_Frequency48KHz (HDSP_Frequency1|HDSP_Frequency0)
+#define HDSP_Frequency64KHz (HDSP_DoubleSpeed|HDSP_Frequency0)
+#define HDSP_Frequency88_2KHz (HDSP_DoubleSpeed|HDSP_Frequency1)
+#define HDSP_Frequency96KHz (HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0)
+/* For H9632 cards */
+#define HDSP_Frequency128KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency0)
+#define HDSP_Frequency176_4KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1)
+#define HDSP_Frequency192KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0)
+
+#define hdsp_encode_latency(x) (((x)<<1) & HDSP_LatencyMask)
+#define hdsp_decode_latency(x) (((x) & HDSP_LatencyMask)>>1)
+
+#define hdsp_encode_spdif_in(x) (((x)&0x3)<<14)
+#define hdsp_decode_spdif_in(x) (((x)>>14)&0x3)
+
+/* Status Register bits */
+
+#define HDSP_audioIRQPending (1<<0)
+#define HDSP_Lock2 (1<<1) /* this is for Digiface and H9652 */
+#define HDSP_spdifFrequency3 HDSP_Lock2 /* this is for H9632 only */
+#define HDSP_Lock1 (1<<2)
+#define HDSP_Lock0 (1<<3)
+#define HDSP_SPDIFSync (1<<4)
+#define HDSP_TimecodeLock (1<<5)
+#define HDSP_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
+#define HDSP_Sync2 (1<<16)
+#define HDSP_Sync1 (1<<17)
+#define HDSP_Sync0 (1<<18)
+#define HDSP_DoubleSpeedStatus (1<<19)
+#define HDSP_ConfigError (1<<20)
+#define HDSP_DllError (1<<21)
+#define HDSP_spdifFrequency0 (1<<22)
+#define HDSP_spdifFrequency1 (1<<23)
+#define HDSP_spdifFrequency2 (1<<24)
+#define HDSP_SPDIFErrorFlag (1<<25)
+#define HDSP_BufferID (1<<26)
+#define HDSP_TimecodeSync (1<<27)
+#define HDSP_AEBO (1<<28) /* H9632 specific Analog Extension Boards */
+#define HDSP_AEBI (1<<29) /* 0 = present, 1 = absent */
+#define HDSP_midi0IRQPending (1<<30)
+#define HDSP_midi1IRQPending (1<<31)
+
+#define HDSP_spdifFrequencyMask (HDSP_spdifFrequency0|HDSP_spdifFrequency1|HDSP_spdifFrequency2)
+
+#define HDSP_spdifFrequency32KHz (HDSP_spdifFrequency0)
+#define HDSP_spdifFrequency44_1KHz (HDSP_spdifFrequency1)
+#define HDSP_spdifFrequency48KHz (HDSP_spdifFrequency0|HDSP_spdifFrequency1)
+
+#define HDSP_spdifFrequency64KHz (HDSP_spdifFrequency2)
+#define HDSP_spdifFrequency88_2KHz (HDSP_spdifFrequency0|HDSP_spdifFrequency2)
+#define HDSP_spdifFrequency96KHz (HDSP_spdifFrequency2|HDSP_spdifFrequency1)
+
+/* This is for H9632 cards */
+#define HDSP_spdifFrequency128KHz HDSP_spdifFrequencyMask
+#define HDSP_spdifFrequency176_4KHz HDSP_spdifFrequency3
+#define HDSP_spdifFrequency192KHz (HDSP_spdifFrequency3|HDSP_spdifFrequency0)
+
+/* Status2 Register bits */
+
+#define HDSP_version0 (1<<0)
+#define HDSP_version1 (1<<1)
+#define HDSP_version2 (1<<2)
+#define HDSP_wc_lock (1<<3)
+#define HDSP_wc_sync (1<<4)
+#define HDSP_inp_freq0 (1<<5)
+#define HDSP_inp_freq1 (1<<6)
+#define HDSP_inp_freq2 (1<<7)
+#define HDSP_SelSyncRef0 (1<<8)
+#define HDSP_SelSyncRef1 (1<<9)
+#define HDSP_SelSyncRef2 (1<<10)
+
+#define HDSP_wc_valid (HDSP_wc_lock|HDSP_wc_sync)
+
+#define HDSP_systemFrequencyMask (HDSP_inp_freq0|HDSP_inp_freq1|HDSP_inp_freq2)
+#define HDSP_systemFrequency32 (HDSP_inp_freq0)
+#define HDSP_systemFrequency44_1 (HDSP_inp_freq1)
+#define HDSP_systemFrequency48 (HDSP_inp_freq0|HDSP_inp_freq1)
+#define HDSP_systemFrequency64 (HDSP_inp_freq2)
+#define HDSP_systemFrequency88_2 (HDSP_inp_freq0|HDSP_inp_freq2)
+#define HDSP_systemFrequency96 (HDSP_inp_freq1|HDSP_inp_freq2)
+/* FIXME : more values for 9632 cards ? */
+
+#define HDSP_SelSyncRefMask (HDSP_SelSyncRef0|HDSP_SelSyncRef1|HDSP_SelSyncRef2)
+#define HDSP_SelSyncRef_ADAT1 0
+#define HDSP_SelSyncRef_ADAT2 (HDSP_SelSyncRef0)
+#define HDSP_SelSyncRef_ADAT3 (HDSP_SelSyncRef1)
+#define HDSP_SelSyncRef_SPDIF (HDSP_SelSyncRef0|HDSP_SelSyncRef1)
+#define HDSP_SelSyncRef_WORD (HDSP_SelSyncRef2)
+#define HDSP_SelSyncRef_ADAT_SYNC (HDSP_SelSyncRef0|HDSP_SelSyncRef2)
+
+/* Card state flags */
+
+#define HDSP_InitializationComplete (1<<0)
+#define HDSP_FirmwareLoaded (1<<1)
+#define HDSP_FirmwareCached (1<<2)
+
+/* FIFO wait times, defined in terms of 1/10ths of msecs */
+
+#define HDSP_LONG_WAIT 5000
+#define HDSP_SHORT_WAIT 30
+
+#define UNITY_GAIN 32768
+#define MINUS_INFINITY_GAIN 0
+
+#ifndef PCI_VENDOR_ID_XILINX
+#define PCI_VENDOR_ID_XILINX 0x10ee
+#endif
+#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
+#endif
+
+/* the size of a substream (1 mono data stream) */
+
+#define HDSP_CHANNEL_BUFFER_SAMPLES (16*1024)
+#define HDSP_CHANNEL_BUFFER_BYTES (4*HDSP_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
+ Multiface 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 HDSP_DMA_AREA_BYTES ((HDSP_MAX_CHANNELS+1) * HDSP_CHANNEL_BUFFER_BYTES)
+#define HDSP_DMA_AREA_KILOBYTES (HDSP_DMA_AREA_BYTES/1024)
+
+/* use hotplug firmeare loader? */
+#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
+#ifndef HDSP_USE_HWDEP_LOADER
+#define HDSP_FW_LOADER
+#endif
+#endif
+
+typedef struct _hdsp hdsp_t;
+typedef struct _hdsp_midi hdsp_midi_t;
+typedef struct _hdsp_9632_meters hdsp_9632_meters_t;
+
+struct _hdsp_9632_meters {
+ u32 input_peak[16];
+ u32 playback_peak[16];
+ u32 output_peak[16];
+ u32 xxx_peak[16];
+ u32 padding[64];
+ u32 input_rms_low[16];
+ u32 playback_rms_low[16];
+ u32 output_rms_low[16];
+ u32 xxx_rms_low[16];
+ u32 input_rms_high[16];
+ u32 playback_rms_high[16];
+ u32 output_rms_high[16];
+ u32 xxx_rms_high[16];
+};
+
+struct _hdsp_midi {
+ hdsp_t *hdsp;
+ int id;
+ snd_rawmidi_t *rmidi;
+ snd_rawmidi_substream_t *input;
+ snd_rawmidi_substream_t *output;
+ char istimer; /* timer in use */
+ struct timer_list timer;
+ spinlock_t lock;
+ int pending;
+};
+
+struct _hdsp {
+ spinlock_t lock;
+ snd_pcm_substream_t *capture_substream;
+ snd_pcm_substream_t *playback_substream;
+ hdsp_midi_t midi[2];
+ struct tasklet_struct midi_tasklet;
+ int use_midi_tasklet;
+ int precise_ptr;
+ u32 control_register; /* cached value */
+ u32 control2_register; /* cached value */
+ u32 creg_spdif;
+ u32 creg_spdif_stream;
+ char *card_name; /* digiface/multiface */
+ HDSP_IO_Type io_type; /* ditto, but for code use */
+ unsigned short firmware_rev;
+ unsigned short state; /* stores state bits */
+ u32 firmware_cache[24413]; /* this helps recover from accidental iobox power failure */
+ size_t period_bytes; /* guess what this is */
+ unsigned char max_channels;
+ unsigned char qs_in_channels; /* quad speed mode for H9632 */
+ unsigned char ds_in_channels;
+ unsigned char ss_in_channels; /* different for multiface/digiface */
+ unsigned char qs_out_channels;
+ unsigned char ds_out_channels;
+ unsigned char ss_out_channels;
+
+ struct snd_dma_buffer capture_dma_buf;
+ struct snd_dma_buffer playback_dma_buf;
+ unsigned char *capture_buffer; /* suitably aligned address */
+ unsigned char *playback_buffer; /* suitably aligned address */
+
+ pid_t capture_pid;
+ pid_t playback_pid;
+ int running;
+ int system_sample_rate;
+ char *channel_map;
+ int dev;
+ int irq;
+ unsigned long port;
+ void __iomem *iobase;
+ snd_card_t *card;
+ snd_pcm_t *pcm;
+ snd_hwdep_t *hwdep;
+ struct pci_dev *pci;
+ snd_kcontrol_t *spdif_ctl;
+ unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE];
+};
+
+/* 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_df_ss[HDSP_MAX_CHANNELS] = {
+ 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_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */
+ /* Analog */
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ /* ADAT 2 */
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ /* SPDIF */
+ 24, 25,
+ -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+static char channel_map_ds[HDSP_MAX_CHANNELS] = {
+ /* 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, -1
+};
+
+static char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = {
+ /* ADAT channels */
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ /* SPDIF */
+ 8, 9,
+ /* Analog */
+ 10, 11,
+ /* AO4S-192 and AI4S-192 extension boards */
+ 12, 13, 14, 15,
+ /* others don't exist */
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1
+};
+
+static char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = {
+ /* ADAT */
+ 1, 3, 5, 7,
+ /* SPDIF */
+ 8, 9,
+ /* Analog */
+ 10, 11,
+ /* AO4S-192 and AI4S-192 extension boards */
+ 12, 13, 14, 15,
+ /* others don't exist */
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1
+};
+
+static char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = {
+ /* ADAT is disabled in this mode */
+ /* SPDIF */
+ 8, 9,
+ /* Analog */
+ 10, 11,
+ /* AO4S-192 and AI4S-192 extension boards */
+ 12, 13, 14, 15,
+ /* others don't exist */
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1
+};
+
+static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
+{
+ dmab->dev.type = SNDRV_DMA_TYPE_DEV;
+ dmab->dev.dev = snd_dma_pci_data(pci);
+ if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
+ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+ size, dmab) < 0)
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
+{
+ if (dmab->area)
+ snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
+}
+
+
+static struct pci_device_id snd_hdsp_ids[] = {
+ {
+ .vendor = PCI_VENDOR_ID_XILINX,
+ .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ }, /* RME Hammerfall-DSP */
+ { 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, snd_hdsp_ids);
+
+/* prototypes */
+static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp);
+static int snd_hdsp_create_pcm(snd_card_t *card, hdsp_t *hdsp);
+static int snd_hdsp_enable_io (hdsp_t *hdsp);
+static void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp);
+static void snd_hdsp_initialize_channels (hdsp_t *hdsp);
+static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout);
+static int hdsp_autosync_ref(hdsp_t *hdsp);
+static int snd_hdsp_set_defaults(hdsp_t *hdsp);
+static void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp);
+
+static int hdsp_playback_to_output_key (hdsp_t *hdsp, int in, int out)
+{
+ switch (hdsp->firmware_rev) {
+ case 0xa:
+ return (64 * out) + (32 + (in));
+ case 0x96:
+ case 0x97:
+ return (32 * out) + (16 + (in));
+ default:
+ return (52 * out) + (26 + (in));
+ }
+}
+
+static int hdsp_input_to_output_key (hdsp_t *hdsp, int in, int out)
+{
+ switch (hdsp->firmware_rev) {
+ case 0xa:
+ return (64 * out) + in;
+ case 0x96:
+ case 0x97:
+ return (32 * out) + in;
+ default:
+ return (52 * out) + in;
+ }
+}
+
+static void hdsp_write(hdsp_t *hdsp, int reg, int val)
+{
+ writel(val, hdsp->iobase + reg);
+}
+
+static unsigned int hdsp_read(hdsp_t *hdsp, int reg)
+{
+ return readl (hdsp->iobase + reg);
+}
+
+static int hdsp_check_for_iobox (hdsp_t *hdsp)
+{
+
+ if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
+ if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_ConfigError) {
+ snd_printk ("Hammerfall-DSP: no Digiface or Multiface connected!\n");
+ hdsp->state &= ~HDSP_FirmwareLoaded;
+ return -EIO;
+ }
+ return 0;
+
+}
+
+static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) {
+
+ int i;
+ unsigned long flags;
+
+ if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
+
+ snd_printk ("Hammerfall-DSP: loading firmware\n");
+
+ hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM);
+ hdsp_write (hdsp, HDSP_fifoData, 0);
+
+ if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
+ snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n");
+ return -EIO;
+ }
+
+ hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
+
+ for (i = 0; i < 24413; ++i) {
+ hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]);
+ if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) {
+ snd_printk ("Hammerfall-DSP: timeout during firmware loading\n");
+ return -EIO;
+ }
+ }
+
+ if ((1000 / HZ) < 3000) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout((3000 * HZ + 999) / 1000);
+ } else {
+ mdelay(3000);
+ }
+
+ if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
+ snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n");
+ return -EIO;
+ }
+
+#ifdef SNDRV_BIG_ENDIAN
+ hdsp->control2_register = HDSP_BIGENDIAN_MODE;
+#else
+ hdsp->control2_register = 0;
+#endif
+ hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
+ snd_printk ("Hammerfall-DSP: finished firmware loading\n");
+
+ }
+ if (hdsp->state & HDSP_InitializationComplete) {
+ snd_printk("Hammerfall-DSP: firmware loaded from cache, restoring defaults\n");
+ spin_lock_irqsave(&hdsp->lock, flags);
+ snd_hdsp_set_defaults(hdsp);
+ spin_unlock_irqrestore(&hdsp->lock, flags);
+ }
+
+ hdsp->state |= HDSP_FirmwareLoaded;
+
+ return 0;
+}
+
+static int hdsp_get_iobox_version (hdsp_t *hdsp)
+{
+ if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
+
+ hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM);
+ hdsp_write (hdsp, HDSP_fifoData, 0);
+ if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0) {
+ return -EIO;
+ }
+
+ hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
+ hdsp_write (hdsp, HDSP_fifoData, 0);
+
+ if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT)) {
+ hdsp->io_type = Multiface;
+ hdsp_write (hdsp, HDSP_control2Reg, HDSP_VERSION_BIT);
+ hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
+ hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT);
+ } else {
+ hdsp->io_type = Digiface;
+ }
+ } else {
+ /* firmware was already loaded, get iobox type */
+ if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) {
+ hdsp->io_type = Multiface;
+ } else {
+ hdsp->io_type = Digiface;
+ }
+ }
+ return 0;
+}
+
+
+static int hdsp_check_for_firmware (hdsp_t *hdsp)
+{
+ if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
+ if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
+ snd_printk("Hammerfall-DSP: firmware not present.\n");
+ hdsp->state &= ~HDSP_FirmwareLoaded;
+ return -EIO;
+ }
+ return 0;
+}
+
+
+static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout)
+{
+ int i;
+
+ /* the fifoStatus registers reports on how many words
+ are available in the command FIFO.
+ */
+
+ for (i = 0; i < timeout; i++) {
+
+ if ((int)(hdsp_read (hdsp, HDSP_fifoStatus) & 0xff) <= count)
+ return 0;
+
+ /* not very friendly, but we only do this during a firmware
+ load and changing the mixer, so we just put up with it.
+ */
+
+ udelay (100);
+ }
+
+ snd_printk ("Hammerfall-DSP: wait for FIFO status <= %d failed after %d iterations\n",
+ count, timeout);
+ return -1;
+}
+
+static int hdsp_read_gain (hdsp_t *hdsp, unsigned int addr)
+{
+ if (addr >= HDSP_MATRIX_MIXER_SIZE) {
+ return 0;
+ }
+ return hdsp->mixer_matrix[addr];
+}
+
+static int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned short data)
+{
+ unsigned int ad;
+
+ if (addr >= HDSP_MATRIX_MIXER_SIZE)
+ return -1;
+
+ if (hdsp->io_type == H9652 || hdsp->io_type == H9632) {
+
+ /* from martin bjornsen:
+
+ "You can only write dwords to the
+ mixer memory which contain two
+ mixer values in the low and high
+ word. So if you want to change
+ value 0 you have to read value 1
+ from the cache and write both to
+ the first dword in the mixer
+ memory."
+ */
+
+ if (hdsp->io_type == H9632 && addr >= 512) {
+ return 0;
+ }
+
+ if (hdsp->io_type == H9652 && addr >= 1352) {
+ return 0;
+ }
+
+ hdsp->mixer_matrix[addr] = data;
+
+
+ /* `addr' addresses a 16-bit wide address, but
+ the address space accessed via hdsp_write
+ uses byte offsets. put another way, addr
+ varies from 0 to 1351, but to access the
+ corresponding memory location, we need
+ to access 0 to 2703 ...
+ */
+ ad = addr/2;
+
+ hdsp_write (hdsp, 4096 + (ad*4),
+ (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) +
+ hdsp->mixer_matrix[addr&0x7fe]);
+
+ return 0;
+
+ } else {
+
+ ad = (addr << 16) + data;
+
+ if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT)) {
+ return -1;
+ }
+
+ hdsp_write (hdsp, HDSP_fifoData, ad);
+ hdsp->mixer_matrix[addr] = data;
+
+ }
+
+ return 0;
+}
+
+static int snd_hdsp_use_is_exclusive(hdsp_t *hdsp)
+{
+ unsigned long flags;
+ int ret = 1;
+
+ spin_lock_irqsave(&hdsp->lock, flags);
+ if ((hdsp->playback_pid != hdsp->capture_pid) &&
+ (hdsp->playback_pid >= 0) && (hdsp->capture_pid >= 0)) {
+ ret = 0;
+ }
+ spin_unlock_irqrestore(&hdsp->lock, flags);
+ return ret;
+}
+
+static int hdsp_external_sample_rate (hdsp_t *hdsp)
+{
+ unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
+ unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
+
+ switch (rate_bits) {
+ case HDSP_systemFrequency32: return 32000;
+ case HDSP_systemFrequency44_1: return 44100;
+ case HDSP_systemFrequency48: return 48000;
+ case HDSP_systemFrequency64: return 64000;
+ case HDSP_systemFrequency88_2: return 88200;
+ case HDSP_systemFrequency96: return 96000;
+ default:
+ return 0;
+ }
+}
+
+static int hdsp_spdif_sample_rate(hdsp_t *hdsp)
+{
+ unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);
+ unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);
+
+ if (status & HDSP_SPDIFErrorFlag) {
+ return 0;
+ }
+
+ switch (rate_bits) {
+ case HDSP_spdifFrequency32KHz: return 32000;
+ case HDSP_spdifFrequency44_1KHz: return 44100;
+ case HDSP_spdifFrequency48KHz: return 48000;
+ case HDSP_spdifFrequency64KHz: return 64000;
+ case HDSP_spdifFrequency88_2KHz: return 88200;
+ case HDSP_spdifFrequency96KHz: return 96000;
+ case HDSP_spdifFrequency128KHz:
+ if (hdsp->io_type == H9632) return 128000;
+ break;
+ case HDSP_spdifFrequency176_4KHz:
+ if (hdsp->io_type == H9632) return 176400;
+ break;
+ case HDSP_spdifFrequency192KHz:
+ if (hdsp->io_type == H9632) return 192000;
+ break;
+ default:
+ break;
+ }
+ snd_printk ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status);
+ return 0;
+}
+
+static void hdsp_compute_period_size(hdsp_t *hdsp)
+{
+ hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));
+}
+
+static snd_pcm_uframes_t hdsp_hw_pointer(hdsp_t *hdsp)
+{
+ int position;
+
+ position = hdsp_read(hdsp, HDSP_statusRegister);
+
+ if (!hdsp->precise_ptr) {
+ return (position & HDSP_BufferID) ? (hdsp->period_bytes / 4) : 0;
+ }
+
+ position &= HDSP_BufferPositionMask;
+ position /= 4;
+ position &= (hdsp->period_bytes/2) - 1;
+ return position;
+}
+
+static void hdsp_reset_hw_pointer(hdsp_t *hdsp)
+{
+ hdsp_write (hdsp, HDSP_resetPointer, 0);
+}
+
+static void hdsp_start_audio(hdsp_t *s)
+{
+ s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start);
+ hdsp_write(s, HDSP_controlRegister, s->control_register);
+}
+
+static void hdsp_stop_audio(hdsp_t *s)
+{
+ s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable);
+ hdsp_write(s, HDSP_controlRegister, s->control_register);
+}
+
+static void hdsp_silence_playback(hdsp_t *hdsp)
+{
+ memset(hdsp->playback_buffer, 0, HDSP_DMA_AREA_BYTES);
+}
+
+static int hdsp_set_interrupt_interval(hdsp_t *s, unsigned int frames)
+{
+ int n;
+
+ spin_lock_irq(&s->lock);
+
+ frames >>= 7;
+ n = 0;
+ while (frames) {
+ n++;
+ frames >>= 1;
+ }
+
+ s->control_register &= ~HDSP_LatencyMask;
+ s->control_register |= hdsp_encode_latency(n);
+
+ hdsp_write(s, HDSP_controlRegister, s->control_register);
+
+ hdsp_compute_period_size(s);
+
+ spin_unlock_irq(&s->lock);
+
+ return 0;
+}
+
+static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally)
+{
+ int reject_if_open = 0;
+ int current_rate;
+ int rate_bits;
+
+ /* ASSUMPTION: hdsp->lock is either held, or
+ there is no need for it (e.g. during module
+ initialization).
+ */
+
+ if (!(hdsp->control_register & HDSP_ClockModeMaster)) {
+ if (called_internally) {
+ /* request from ctl or card initialization */
+ snd_printk("Hammerfall-DSP: device is not running as a clock master: cannot set sample rate.\n");
+ return -1;
+ } else {
+ /* hw_param request while in AutoSync mode */
+ int external_freq = hdsp_external_sample_rate(hdsp);
+ int spdif_freq = hdsp_spdif_sample_rate(hdsp);
+
+ if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) {
+ snd_printk("Hammerfall-DSP: Detected ADAT in double speed mode\n");
+ } else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) {
+ snd_printk("Hammerfall-DSP: Detected ADAT in quad speed mode\n");
+ } else if (rate != external_freq) {
+ snd_printk("Hammerfall-DSP: No AutoSync source for requested rate\n");
+ return -1;
+ }
+ }
+ }
+
+ current_rate = hdsp->system_sample_rate;
+
+ /* Changing from a "single speed" to a "double speed" rate is
+ not allowed if any substreams are open. This is because
+ such a change causes a shift in the location of
+ the DMA buffers and a reduction in the number of available
+ buffers.
+
+ Note that a similar but essentially insoluble problem
+ exists for externally-driven rate changes. All we can do
+ is to flag rate changes in the read/write routines. */
+
+ if (rate > 96000 && hdsp->io_type != H9632) {
+ return -EINVAL;
+ }
+
+ switch (rate) {
+ case 32000:
+ if (current_rate > 48000) {
+ reject_if_open = 1;
+ }
+ rate_bits = HDSP_Frequency32KHz;
+ break;
+ case 44100:
+ if (current_rate > 48000) {
+ reject_if_open = 1;
+ }
+ rate_bits = HDSP_Frequency44_1KHz;
+ break;
+ case 48000:
+ if (current_rate > 48000) {
+ reject_if_open = 1;
+ }
+ rate_bits = HDSP_Frequency48KHz;
+ break;
+ case 64000:
+ if (current_rate <= 48000 || current_rate > 96000) {
+ reject_if_open = 1;
+ }
+ rate_bits = HDSP_Frequency64KHz;
+ break;
+ case 88200:
+ if (current_rate <= 48000 || current_rate > 96000) {
+ reject_if_open = 1;
+ }
+ rate_bits = HDS