1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * ALSA driver for RME Hammerfall DSP audio interface(s) 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * Copyright (c) 2002 Paul Davis 5*1da177e4SLinus Torvalds * Marcus Andersson 6*1da177e4SLinus Torvalds * Thomas Charbonnel 7*1da177e4SLinus Torvalds * 8*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 9*1da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 10*1da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 11*1da177e4SLinus Torvalds * (at your option) any later version. 12*1da177e4SLinus Torvalds * 13*1da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, 14*1da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*1da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*1da177e4SLinus Torvalds * GNU General Public License for more details. 17*1da177e4SLinus Torvalds * 18*1da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 19*1da177e4SLinus Torvalds * along with this program; if not, write to the Free Software 20*1da177e4SLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21*1da177e4SLinus Torvalds * 22*1da177e4SLinus Torvalds */ 23*1da177e4SLinus Torvalds 24*1da177e4SLinus Torvalds #include <sound/driver.h> 25*1da177e4SLinus Torvalds #include <linux/init.h> 26*1da177e4SLinus Torvalds #include <linux/delay.h> 27*1da177e4SLinus Torvalds #include <linux/interrupt.h> 28*1da177e4SLinus Torvalds #include <linux/slab.h> 29*1da177e4SLinus Torvalds #include <linux/pci.h> 30*1da177e4SLinus Torvalds #include <linux/firmware.h> 31*1da177e4SLinus Torvalds #include <linux/moduleparam.h> 32*1da177e4SLinus Torvalds 33*1da177e4SLinus Torvalds #include <sound/core.h> 34*1da177e4SLinus Torvalds #include <sound/control.h> 35*1da177e4SLinus Torvalds #include <sound/pcm.h> 36*1da177e4SLinus Torvalds #include <sound/info.h> 37*1da177e4SLinus Torvalds #include <sound/asoundef.h> 38*1da177e4SLinus Torvalds #include <sound/rawmidi.h> 39*1da177e4SLinus Torvalds #include <sound/hwdep.h> 40*1da177e4SLinus Torvalds #include <sound/initval.h> 41*1da177e4SLinus Torvalds #include <sound/hdsp.h> 42*1da177e4SLinus Torvalds 43*1da177e4SLinus Torvalds #include <asm/byteorder.h> 44*1da177e4SLinus Torvalds #include <asm/current.h> 45*1da177e4SLinus Torvalds #include <asm/io.h> 46*1da177e4SLinus Torvalds 47*1da177e4SLinus Torvalds static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 48*1da177e4SLinus Torvalds static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 49*1da177e4SLinus Torvalds static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ 50*1da177e4SLinus Torvalds 51*1da177e4SLinus Torvalds module_param_array(index, int, NULL, 0444); 52*1da177e4SLinus Torvalds MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface."); 53*1da177e4SLinus Torvalds module_param_array(id, charp, NULL, 0444); 54*1da177e4SLinus Torvalds MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface."); 55*1da177e4SLinus Torvalds module_param_array(enable, bool, NULL, 0444); 56*1da177e4SLinus Torvalds MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards."); 57*1da177e4SLinus Torvalds MODULE_AUTHOR("Paul Davis <paul@linuxaudiosystems.com>, Marcus Andersson, Thomas Charbonnel <thomas@undata.org>"); 58*1da177e4SLinus Torvalds MODULE_DESCRIPTION("RME Hammerfall DSP"); 59*1da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 60*1da177e4SLinus Torvalds MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," 61*1da177e4SLinus Torvalds "{RME HDSP-9652}," 62*1da177e4SLinus Torvalds "{RME HDSP-9632}}"); 63*1da177e4SLinus Torvalds 64*1da177e4SLinus Torvalds #define HDSP_MAX_CHANNELS 26 65*1da177e4SLinus Torvalds #define HDSP_MAX_DS_CHANNELS 14 66*1da177e4SLinus Torvalds #define HDSP_MAX_QS_CHANNELS 8 67*1da177e4SLinus Torvalds #define DIGIFACE_SS_CHANNELS 26 68*1da177e4SLinus Torvalds #define DIGIFACE_DS_CHANNELS 14 69*1da177e4SLinus Torvalds #define MULTIFACE_SS_CHANNELS 18 70*1da177e4SLinus Torvalds #define MULTIFACE_DS_CHANNELS 14 71*1da177e4SLinus Torvalds #define H9652_SS_CHANNELS 26 72*1da177e4SLinus Torvalds #define H9652_DS_CHANNELS 14 73*1da177e4SLinus Torvalds /* This does not include possible Analog Extension Boards 74*1da177e4SLinus Torvalds AEBs are detected at card initialization 75*1da177e4SLinus Torvalds */ 76*1da177e4SLinus Torvalds #define H9632_SS_CHANNELS 12 77*1da177e4SLinus Torvalds #define H9632_DS_CHANNELS 8 78*1da177e4SLinus Torvalds #define H9632_QS_CHANNELS 4 79*1da177e4SLinus Torvalds 80*1da177e4SLinus Torvalds /* Write registers. These are defined as byte-offsets from the iobase value. 81*1da177e4SLinus Torvalds */ 82*1da177e4SLinus Torvalds #define HDSP_resetPointer 0 83*1da177e4SLinus Torvalds #define HDSP_outputBufferAddress 32 84*1da177e4SLinus Torvalds #define HDSP_inputBufferAddress 36 85*1da177e4SLinus Torvalds #define HDSP_controlRegister 64 86*1da177e4SLinus Torvalds #define HDSP_interruptConfirmation 96 87*1da177e4SLinus Torvalds #define HDSP_outputEnable 128 88*1da177e4SLinus Torvalds #define HDSP_control2Reg 256 89*1da177e4SLinus Torvalds #define HDSP_midiDataOut0 352 90*1da177e4SLinus Torvalds #define HDSP_midiDataOut1 356 91*1da177e4SLinus Torvalds #define HDSP_fifoData 368 92*1da177e4SLinus Torvalds #define HDSP_inputEnable 384 93*1da177e4SLinus Torvalds 94*1da177e4SLinus Torvalds /* Read registers. These are defined as byte-offsets from the iobase value 95*1da177e4SLinus Torvalds */ 96*1da177e4SLinus Torvalds 97*1da177e4SLinus Torvalds #define HDSP_statusRegister 0 98*1da177e4SLinus Torvalds #define HDSP_timecode 128 99*1da177e4SLinus Torvalds #define HDSP_status2Register 192 100*1da177e4SLinus Torvalds #define HDSP_midiDataOut0 352 101*1da177e4SLinus Torvalds #define HDSP_midiDataOut1 356 102*1da177e4SLinus Torvalds #define HDSP_midiDataIn0 360 103*1da177e4SLinus Torvalds #define HDSP_midiDataIn1 364 104*1da177e4SLinus Torvalds #define HDSP_midiStatusOut0 384 105*1da177e4SLinus Torvalds #define HDSP_midiStatusOut1 388 106*1da177e4SLinus Torvalds #define HDSP_midiStatusIn0 392 107*1da177e4SLinus Torvalds #define HDSP_midiStatusIn1 396 108*1da177e4SLinus Torvalds #define HDSP_fifoStatus 400 109*1da177e4SLinus Torvalds 110*1da177e4SLinus Torvalds /* the meters are regular i/o-mapped registers, but offset 111*1da177e4SLinus Torvalds considerably from the rest. the peak registers are reset 112*1da177e4SLinus Torvalds when read; the least-significant 4 bits are full-scale counters; 113*1da177e4SLinus Torvalds the actual peak value is in the most-significant 24 bits. 114*1da177e4SLinus Torvalds */ 115*1da177e4SLinus Torvalds 116*1da177e4SLinus Torvalds #define HDSP_playbackPeakLevel 4096 /* 26 * 32 bit values */ 117*1da177e4SLinus Torvalds #define HDSP_inputPeakLevel 4224 /* 26 * 32 bit values */ 118*1da177e4SLinus Torvalds #define HDSP_outputPeakLevel 4352 /* (26+2) * 32 bit values */ 119*1da177e4SLinus Torvalds #define HDSP_playbackRmsLevel 4612 /* 26 * 64 bit values */ 120*1da177e4SLinus Torvalds #define HDSP_inputRmsLevel 4868 /* 26 * 64 bit values */ 121*1da177e4SLinus Torvalds 122*1da177e4SLinus Torvalds 123*1da177e4SLinus Torvalds /* This is for H9652 cards 124*1da177e4SLinus Torvalds Peak values are read downward from the base 125*1da177e4SLinus Torvalds Rms values are read upward 126*1da177e4SLinus Torvalds There are rms values for the outputs too 127*1da177e4SLinus Torvalds 26*3 values are read in ss mode 128*1da177e4SLinus Torvalds 14*3 in ds mode, with no gap between values 129*1da177e4SLinus Torvalds */ 130*1da177e4SLinus Torvalds #define HDSP_9652_peakBase 7164 131*1da177e4SLinus Torvalds #define HDSP_9652_rmsBase 4096 132*1da177e4SLinus Torvalds 133*1da177e4SLinus Torvalds /* c.f. the hdsp_9632_meters_t struct */ 134*1da177e4SLinus Torvalds #define HDSP_9632_metersBase 4096 135*1da177e4SLinus Torvalds 136*1da177e4SLinus Torvalds #define HDSP_IO_EXTENT 7168 137*1da177e4SLinus Torvalds 138*1da177e4SLinus Torvalds /* control2 register bits */ 139*1da177e4SLinus Torvalds 140*1da177e4SLinus Torvalds #define HDSP_TMS 0x01 141*1da177e4SLinus Torvalds #define HDSP_TCK 0x02 142*1da177e4SLinus Torvalds #define HDSP_TDI 0x04 143*1da177e4SLinus Torvalds #define HDSP_JTAG 0x08 144*1da177e4SLinus Torvalds #define HDSP_PWDN 0x10 145*1da177e4SLinus Torvalds #define HDSP_PROGRAM 0x020 146*1da177e4SLinus Torvalds #define HDSP_CONFIG_MODE_0 0x040 147*1da177e4SLinus Torvalds #define HDSP_CONFIG_MODE_1 0x080 148*1da177e4SLinus Torvalds #define HDSP_VERSION_BIT 0x100 149*1da177e4SLinus Torvalds #define HDSP_BIGENDIAN_MODE 0x200 150*1da177e4SLinus Torvalds #define HDSP_RD_MULTIPLE 0x400 151*1da177e4SLinus Torvalds #define HDSP_9652_ENABLE_MIXER 0x800 152*1da177e4SLinus Torvalds #define HDSP_TDO 0x10000000 153*1da177e4SLinus Torvalds 154*1da177e4SLinus Torvalds #define HDSP_S_PROGRAM (HDSP_PROGRAM|HDSP_CONFIG_MODE_0) 155*1da177e4SLinus Torvalds #define HDSP_S_LOAD (HDSP_PROGRAM|HDSP_CONFIG_MODE_1) 156*1da177e4SLinus Torvalds 157*1da177e4SLinus Torvalds /* Control Register bits */ 158*1da177e4SLinus Torvalds 159*1da177e4SLinus Torvalds #define HDSP_Start (1<<0) /* start engine */ 160*1da177e4SLinus Torvalds #define HDSP_Latency0 (1<<1) /* buffer size = 2^n where n is defined by Latency{2,1,0} */ 161*1da177e4SLinus Torvalds #define HDSP_Latency1 (1<<2) /* [ see above ] */ 162*1da177e4SLinus Torvalds #define HDSP_Latency2 (1<<3) /* [ see above ] */ 163*1da177e4SLinus Torvalds #define HDSP_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */ 164*1da177e4SLinus Torvalds #define HDSP_AudioInterruptEnable (1<<5) /* what do you think ? */ 165*1da177e4SLinus Torvalds #define HDSP_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz/176.4kHz 1=48kHz/96kHz/192kHz */ 166*1da177e4SLinus Torvalds #define HDSP_Frequency1 (1<<7) /* 0=32kHz/64kHz/128kHz */ 167*1da177e4SLinus Torvalds #define HDSP_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */ 168*1da177e4SLinus Torvalds #define HDSP_SPDIFProfessional (1<<9) /* 0=consumer, 1=professional */ 169*1da177e4SLinus Torvalds #define HDSP_SPDIFEmphasis (1<<10) /* 0=none, 1=on */ 170*1da177e4SLinus Torvalds #define HDSP_SPDIFNonAudio (1<<11) /* 0=off, 1=on */ 171*1da177e4SLinus Torvalds #define HDSP_SPDIFOpticalOut (1<<12) /* 1=use 1st ADAT connector for SPDIF, 0=do not */ 172*1da177e4SLinus Torvalds #define HDSP_SyncRef2 (1<<13) 173*1da177e4SLinus Torvalds #define HDSP_SPDIFInputSelect0 (1<<14) 174*1da177e4SLinus Torvalds #define HDSP_SPDIFInputSelect1 (1<<15) 175*1da177e4SLinus Torvalds #define HDSP_SyncRef0 (1<<16) 176*1da177e4SLinus Torvalds #define HDSP_SyncRef1 (1<<17) 177*1da177e4SLinus Torvalds #define HDSP_AnalogExtensionBoard (1<<18) /* For H9632 cards */ 178*1da177e4SLinus Torvalds #define HDSP_XLRBreakoutCable (1<<20) /* For H9632 cards */ 179*1da177e4SLinus Torvalds #define HDSP_Midi0InterruptEnable (1<<22) 180*1da177e4SLinus Torvalds #define HDSP_Midi1InterruptEnable (1<<23) 181*1da177e4SLinus Torvalds #define HDSP_LineOut (1<<24) 182*1da177e4SLinus Torvalds #define HDSP_ADGain0 (1<<25) /* From here : H9632 specific */ 183*1da177e4SLinus Torvalds #define HDSP_ADGain1 (1<<26) 184*1da177e4SLinus Torvalds #define HDSP_DAGain0 (1<<27) 185*1da177e4SLinus Torvalds #define HDSP_DAGain1 (1<<28) 186*1da177e4SLinus Torvalds #define HDSP_PhoneGain0 (1<<29) 187*1da177e4SLinus Torvalds #define HDSP_PhoneGain1 (1<<30) 188*1da177e4SLinus Torvalds #define HDSP_QuadSpeed (1<<31) 189*1da177e4SLinus Torvalds 190*1da177e4SLinus Torvalds #define HDSP_ADGainMask (HDSP_ADGain0|HDSP_ADGain1) 191*1da177e4SLinus Torvalds #define HDSP_ADGainMinus10dBV HDSP_ADGainMask 192*1da177e4SLinus Torvalds #define HDSP_ADGainPlus4dBu (HDSP_ADGain0) 193*1da177e4SLinus Torvalds #define HDSP_ADGainLowGain 0 194*1da177e4SLinus Torvalds 195*1da177e4SLinus Torvalds #define HDSP_DAGainMask (HDSP_DAGain0|HDSP_DAGain1) 196*1da177e4SLinus Torvalds #define HDSP_DAGainHighGain HDSP_DAGainMask 197*1da177e4SLinus Torvalds #define HDSP_DAGainPlus4dBu (HDSP_DAGain0) 198*1da177e4SLinus Torvalds #define HDSP_DAGainMinus10dBV 0 199*1da177e4SLinus Torvalds 200*1da177e4SLinus Torvalds #define HDSP_PhoneGainMask (HDSP_PhoneGain0|HDSP_PhoneGain1) 201*1da177e4SLinus Torvalds #define HDSP_PhoneGain0dB HDSP_PhoneGainMask 202*1da177e4SLinus Torvalds #define HDSP_PhoneGainMinus6dB (HDSP_PhoneGain0) 203*1da177e4SLinus Torvalds #define HDSP_PhoneGainMinus12dB 0 204*1da177e4SLinus Torvalds 205*1da177e4SLinus Torvalds #define HDSP_LatencyMask (HDSP_Latency0|HDSP_Latency1|HDSP_Latency2) 206*1da177e4SLinus Torvalds #define HDSP_FrequencyMask (HDSP_Frequency0|HDSP_Frequency1|HDSP_DoubleSpeed|HDSP_QuadSpeed) 207*1da177e4SLinus Torvalds 208*1da177e4SLinus Torvalds #define HDSP_SPDIFInputMask (HDSP_SPDIFInputSelect0|HDSP_SPDIFInputSelect1) 209*1da177e4SLinus Torvalds #define HDSP_SPDIFInputADAT1 0 210*1da177e4SLinus Torvalds #define HDSP_SPDIFInputCoaxial (HDSP_SPDIFInputSelect0) 211*1da177e4SLinus Torvalds #define HDSP_SPDIFInputCdrom (HDSP_SPDIFInputSelect1) 212*1da177e4SLinus Torvalds #define HDSP_SPDIFInputAES (HDSP_SPDIFInputSelect0|HDSP_SPDIFInputSelect1) 213*1da177e4SLinus Torvalds 214*1da177e4SLinus Torvalds #define HDSP_SyncRefMask (HDSP_SyncRef0|HDSP_SyncRef1|HDSP_SyncRef2) 215*1da177e4SLinus Torvalds #define HDSP_SyncRef_ADAT1 0 216*1da177e4SLinus Torvalds #define HDSP_SyncRef_ADAT2 (HDSP_SyncRef0) 217*1da177e4SLinus Torvalds #define HDSP_SyncRef_ADAT3 (HDSP_SyncRef1) 218*1da177e4SLinus Torvalds #define HDSP_SyncRef_SPDIF (HDSP_SyncRef0|HDSP_SyncRef1) 219*1da177e4SLinus Torvalds #define HDSP_SyncRef_WORD (HDSP_SyncRef2) 220*1da177e4SLinus Torvalds #define HDSP_SyncRef_ADAT_SYNC (HDSP_SyncRef0|HDSP_SyncRef2) 221*1da177e4SLinus Torvalds 222*1da177e4SLinus Torvalds /* Sample Clock Sources */ 223*1da177e4SLinus Torvalds 224*1da177e4SLinus Torvalds #define HDSP_CLOCK_SOURCE_AUTOSYNC 0 225*1da177e4SLinus Torvalds #define HDSP_CLOCK_SOURCE_INTERNAL_32KHZ 1 226*1da177e4SLinus Torvalds #define HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ 2 227*1da177e4SLinus Torvalds #define HDSP_CLOCK_SOURCE_INTERNAL_48KHZ 3 228*1da177e4SLinus Torvalds #define HDSP_CLOCK_SOURCE_INTERNAL_64KHZ 4 229*1da177e4SLinus Torvalds #define HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ 5 230*1da177e4SLinus Torvalds #define HDSP_CLOCK_SOURCE_INTERNAL_96KHZ 6 231*1da177e4SLinus Torvalds #define HDSP_CLOCK_SOURCE_INTERNAL_128KHZ 7 232*1da177e4SLinus Torvalds #define HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ 8 233*1da177e4SLinus Torvalds #define HDSP_CLOCK_SOURCE_INTERNAL_192KHZ 9 234*1da177e4SLinus Torvalds 235*1da177e4SLinus Torvalds /* Preferred sync reference choices - used by "pref_sync_ref" control switch */ 236*1da177e4SLinus Torvalds 237*1da177e4SLinus Torvalds #define HDSP_SYNC_FROM_WORD 0 238*1da177e4SLinus Torvalds #define HDSP_SYNC_FROM_SPDIF 1 239*1da177e4SLinus Torvalds #define HDSP_SYNC_FROM_ADAT1 2 240*1da177e4SLinus Torvalds #define HDSP_SYNC_FROM_ADAT_SYNC 3 241*1da177e4SLinus Torvalds #define HDSP_SYNC_FROM_ADAT2 4 242*1da177e4SLinus Torvalds #define HDSP_SYNC_FROM_ADAT3 5 243*1da177e4SLinus Torvalds 244*1da177e4SLinus Torvalds /* SyncCheck status */ 245*1da177e4SLinus Torvalds 246*1da177e4SLinus Torvalds #define HDSP_SYNC_CHECK_NO_LOCK 0 247*1da177e4SLinus Torvalds #define HDSP_SYNC_CHECK_LOCK 1 248*1da177e4SLinus Torvalds #define HDSP_SYNC_CHECK_SYNC 2 249*1da177e4SLinus Torvalds 250*1da177e4SLinus Torvalds /* AutoSync references - used by "autosync_ref" control switch */ 251*1da177e4SLinus Torvalds 252*1da177e4SLinus Torvalds #define HDSP_AUTOSYNC_FROM_WORD 0 253*1da177e4SLinus Torvalds #define HDSP_AUTOSYNC_FROM_ADAT_SYNC 1 254*1da177e4SLinus Torvalds #define HDSP_AUTOSYNC_FROM_SPDIF 2 255*1da177e4SLinus Torvalds #define HDSP_AUTOSYNC_FROM_NONE 3 256*1da177e4SLinus Torvalds #define HDSP_AUTOSYNC_FROM_ADAT1 4 257*1da177e4SLinus Torvalds #define HDSP_AUTOSYNC_FROM_ADAT2 5 258*1da177e4SLinus Torvalds #define HDSP_AUTOSYNC_FROM_ADAT3 6 259*1da177e4SLinus Torvalds 260*1da177e4SLinus Torvalds /* Possible sources of S/PDIF input */ 261*1da177e4SLinus Torvalds 262*1da177e4SLinus Torvalds #define HDSP_SPDIFIN_OPTICAL 0 /* optical (ADAT1) */ 263*1da177e4SLinus Torvalds #define HDSP_SPDIFIN_COAXIAL 1 /* coaxial (RCA) */ 264*1da177e4SLinus Torvalds #define HDSP_SPDIFIN_INTERNAL 2 /* internal (CDROM) */ 265*1da177e4SLinus Torvalds #define HDSP_SPDIFIN_AES 3 /* xlr for H9632 (AES)*/ 266*1da177e4SLinus Torvalds 267*1da177e4SLinus Torvalds #define HDSP_Frequency32KHz HDSP_Frequency0 268*1da177e4SLinus Torvalds #define HDSP_Frequency44_1KHz HDSP_Frequency1 269*1da177e4SLinus Torvalds #define HDSP_Frequency48KHz (HDSP_Frequency1|HDSP_Frequency0) 270*1da177e4SLinus Torvalds #define HDSP_Frequency64KHz (HDSP_DoubleSpeed|HDSP_Frequency0) 271*1da177e4SLinus Torvalds #define HDSP_Frequency88_2KHz (HDSP_DoubleSpeed|HDSP_Frequency1) 272*1da177e4SLinus Torvalds #define HDSP_Frequency96KHz (HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0) 273*1da177e4SLinus Torvalds /* For H9632 cards */ 274*1da177e4SLinus Torvalds #define HDSP_Frequency128KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency0) 275*1da177e4SLinus Torvalds #define HDSP_Frequency176_4KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1) 276*1da177e4SLinus Torvalds #define HDSP_Frequency192KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0) 277*1da177e4SLinus Torvalds 278*1da177e4SLinus Torvalds #define hdsp_encode_latency(x) (((x)<<1) & HDSP_LatencyMask) 279*1da177e4SLinus Torvalds #define hdsp_decode_latency(x) (((x) & HDSP_LatencyMask)>>1) 280*1da177e4SLinus Torvalds 281*1da177e4SLinus Torvalds #define hdsp_encode_spdif_in(x) (((x)&0x3)<<14) 282*1da177e4SLinus Torvalds #define hdsp_decode_spdif_in(x) (((x)>>14)&0x3) 283*1da177e4SLinus Torvalds 284*1da177e4SLinus Torvalds /* Status Register bits */ 285*1da177e4SLinus Torvalds 286*1da177e4SLinus Torvalds #define HDSP_audioIRQPending (1<<0) 287*1da177e4SLinus Torvalds #define HDSP_Lock2 (1<<1) /* this is for Digiface and H9652 */ 288*1da177e4SLinus Torvalds #define HDSP_spdifFrequency3 HDSP_Lock2 /* this is for H9632 only */ 289*1da177e4SLinus Torvalds #define HDSP_Lock1 (1<<2) 290*1da177e4SLinus Torvalds #define HDSP_Lock0 (1<<3) 291*1da177e4SLinus Torvalds #define HDSP_SPDIFSync (1<<4) 292*1da177e4SLinus Torvalds #define HDSP_TimecodeLock (1<<5) 293*1da177e4SLinus Torvalds #define HDSP_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */ 294*1da177e4SLinus Torvalds #define HDSP_Sync2 (1<<16) 295*1da177e4SLinus Torvalds #define HDSP_Sync1 (1<<17) 296*1da177e4SLinus Torvalds #define HDSP_Sync0 (1<<18) 297*1da177e4SLinus Torvalds #define HDSP_DoubleSpeedStatus (1<<19) 298*1da177e4SLinus Torvalds #define HDSP_ConfigError (1<<20) 299*1da177e4SLinus Torvalds #define HDSP_DllError (1<<21) 300*1da177e4SLinus Torvalds #define HDSP_spdifFrequency0 (1<<22) 301*1da177e4SLinus Torvalds #define HDSP_spdifFrequency1 (1<<23) 302*1da177e4SLinus Torvalds #define HDSP_spdifFrequency2 (1<<24) 303*1da177e4SLinus Torvalds #define HDSP_SPDIFErrorFlag (1<<25) 304*1da177e4SLinus Torvalds #define HDSP_BufferID (1<<26) 305*1da177e4SLinus Torvalds #define HDSP_TimecodeSync (1<<27) 306*1da177e4SLinus Torvalds #define HDSP_AEBO (1<<28) /* H9632 specific Analog Extension Boards */ 307*1da177e4SLinus Torvalds #define HDSP_AEBI (1<<29) /* 0 = present, 1 = absent */ 308*1da177e4SLinus Torvalds #define HDSP_midi0IRQPending (1<<30) 309*1da177e4SLinus Torvalds #define HDSP_midi1IRQPending (1<<31) 310*1da177e4SLinus Torvalds 311*1da177e4SLinus Torvalds #define HDSP_spdifFrequencyMask (HDSP_spdifFrequency0|HDSP_spdifFrequency1|HDSP_spdifFrequency2) 312*1da177e4SLinus Torvalds 313*1da177e4SLinus Torvalds #define HDSP_spdifFrequency32KHz (HDSP_spdifFrequency0) 314*1da177e4SLinus Torvalds #define HDSP_spdifFrequency44_1KHz (HDSP_spdifFrequency1) 315*1da177e4SLinus Torvalds #define HDSP_spdifFrequency48KHz (HDSP_spdifFrequency0|HDSP_spdifFrequency1) 316*1da177e4SLinus Torvalds 317*1da177e4SLinus Torvalds #define HDSP_spdifFrequency64KHz (HDSP_spdifFrequency2) 318*1da177e4SLinus Torvalds #define HDSP_spdifFrequency88_2KHz (HDSP_spdifFrequency0|HDSP_spdifFrequency2) 319*1da177e4SLinus Torvalds #define HDSP_spdifFrequency96KHz (HDSP_spdifFrequency2|HDSP_spdifFrequency1) 320*1da177e4SLinus Torvalds 321*1da177e4SLinus Torvalds /* This is for H9632 cards */ 322*1da177e4SLinus Torvalds #define HDSP_spdifFrequency128KHz HDSP_spdifFrequencyMask 323*1da177e4SLinus Torvalds #define HDSP_spdifFrequency176_4KHz HDSP_spdifFrequency3 324*1da177e4SLinus Torvalds #define HDSP_spdifFrequency192KHz (HDSP_spdifFrequency3|HDSP_spdifFrequency0) 325*1da177e4SLinus Torvalds 326*1da177e4SLinus Torvalds /* Status2 Register bits */ 327*1da177e4SLinus Torvalds 328*1da177e4SLinus Torvalds #define HDSP_version0 (1<<0) 329*1da177e4SLinus Torvalds #define HDSP_version1 (1<<1) 330*1da177e4SLinus Torvalds #define HDSP_version2 (1<<2) 331*1da177e4SLinus Torvalds #define HDSP_wc_lock (1<<3) 332*1da177e4SLinus Torvalds #define HDSP_wc_sync (1<<4) 333*1da177e4SLinus Torvalds #define HDSP_inp_freq0 (1<<5) 334*1da177e4SLinus Torvalds #define HDSP_inp_freq1 (1<<6) 335*1da177e4SLinus Torvalds #define HDSP_inp_freq2 (1<<7) 336*1da177e4SLinus Torvalds #define HDSP_SelSyncRef0 (1<<8) 337*1da177e4SLinus Torvalds #define HDSP_SelSyncRef1 (1<<9) 338*1da177e4SLinus Torvalds #define HDSP_SelSyncRef2 (1<<10) 339*1da177e4SLinus Torvalds 340*1da177e4SLinus Torvalds #define HDSP_wc_valid (HDSP_wc_lock|HDSP_wc_sync) 341*1da177e4SLinus Torvalds 342*1da177e4SLinus Torvalds #define HDSP_systemFrequencyMask (HDSP_inp_freq0|HDSP_inp_freq1|HDSP_inp_freq2) 343*1da177e4SLinus Torvalds #define HDSP_systemFrequency32 (HDSP_inp_freq0) 344*1da177e4SLinus Torvalds #define HDSP_systemFrequency44_1 (HDSP_inp_freq1) 345*1da177e4SLinus Torvalds #define HDSP_systemFrequency48 (HDSP_inp_freq0|HDSP_inp_freq1) 346*1da177e4SLinus Torvalds #define HDSP_systemFrequency64 (HDSP_inp_freq2) 347*1da177e4SLinus Torvalds #define HDSP_systemFrequency88_2 (HDSP_inp_freq0|HDSP_inp_freq2) 348*1da177e4SLinus Torvalds #define HDSP_systemFrequency96 (HDSP_inp_freq1|HDSP_inp_freq2) 349*1da177e4SLinus Torvalds /* FIXME : more values for 9632 cards ? */ 350*1da177e4SLinus Torvalds 351*1da177e4SLinus Torvalds #define HDSP_SelSyncRefMask (HDSP_SelSyncRef0|HDSP_SelSyncRef1|HDSP_SelSyncRef2) 352*1da177e4SLinus Torvalds #define HDSP_SelSyncRef_ADAT1 0 353*1da177e4SLinus Torvalds #define HDSP_SelSyncRef_ADAT2 (HDSP_SelSyncRef0) 354*1da177e4SLinus Torvalds #define HDSP_SelSyncRef_ADAT3 (HDSP_SelSyncRef1) 355*1da177e4SLinus Torvalds #define HDSP_SelSyncRef_SPDIF (HDSP_SelSyncRef0|HDSP_SelSyncRef1) 356*1da177e4SLinus Torvalds #define HDSP_SelSyncRef_WORD (HDSP_SelSyncRef2) 357*1da177e4SLinus Torvalds #define HDSP_SelSyncRef_ADAT_SYNC (HDSP_SelSyncRef0|HDSP_SelSyncRef2) 358*1da177e4SLinus Torvalds 359*1da177e4SLinus Torvalds /* Card state flags */ 360*1da177e4SLinus Torvalds 361*1da177e4SLinus Torvalds #define HDSP_InitializationComplete (1<<0) 362*1da177e4SLinus Torvalds #define HDSP_FirmwareLoaded (1<<1) 363*1da177e4SLinus Torvalds #define HDSP_FirmwareCached (1<<2) 364*1da177e4SLinus Torvalds 365*1da177e4SLinus Torvalds /* FIFO wait times, defined in terms of 1/10ths of msecs */ 366*1da177e4SLinus Torvalds 367*1da177e4SLinus Torvalds #define HDSP_LONG_WAIT 5000 368*1da177e4SLinus Torvalds #define HDSP_SHORT_WAIT 30 369*1da177e4SLinus Torvalds 370*1da177e4SLinus Torvalds #define UNITY_GAIN 32768 371*1da177e4SLinus Torvalds #define MINUS_INFINITY_GAIN 0 372*1da177e4SLinus Torvalds 373*1da177e4SLinus Torvalds #ifndef PCI_VENDOR_ID_XILINX 374*1da177e4SLinus Torvalds #define PCI_VENDOR_ID_XILINX 0x10ee 375*1da177e4SLinus Torvalds #endif 376*1da177e4SLinus Torvalds #ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 377*1da177e4SLinus Torvalds #define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5 378*1da177e4SLinus Torvalds #endif 379*1da177e4SLinus Torvalds 380*1da177e4SLinus Torvalds /* the size of a substream (1 mono data stream) */ 381*1da177e4SLinus Torvalds 382*1da177e4SLinus Torvalds #define HDSP_CHANNEL_BUFFER_SAMPLES (16*1024) 383*1da177e4SLinus Torvalds #define HDSP_CHANNEL_BUFFER_BYTES (4*HDSP_CHANNEL_BUFFER_SAMPLES) 384*1da177e4SLinus Torvalds 385*1da177e4SLinus Torvalds /* the size of the area we need to allocate for DMA transfers. the 386*1da177e4SLinus Torvalds size is the same regardless of the number of channels - the 387*1da177e4SLinus Torvalds Multiface still uses the same memory area. 388*1da177e4SLinus Torvalds 389*1da177e4SLinus Torvalds Note that we allocate 1 more channel than is apparently needed 390*1da177e4SLinus Torvalds because the h/w seems to write 1 byte beyond the end of the last 391*1da177e4SLinus Torvalds page. Sigh. 392*1da177e4SLinus Torvalds */ 393*1da177e4SLinus Torvalds 394*1da177e4SLinus Torvalds #define HDSP_DMA_AREA_BYTES ((HDSP_MAX_CHANNELS+1) * HDSP_CHANNEL_BUFFER_BYTES) 395*1da177e4SLinus Torvalds #define HDSP_DMA_AREA_KILOBYTES (HDSP_DMA_AREA_BYTES/1024) 396*1da177e4SLinus Torvalds 397*1da177e4SLinus Torvalds /* use hotplug firmeare loader? */ 398*1da177e4SLinus Torvalds #if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) 399*1da177e4SLinus Torvalds #ifndef HDSP_USE_HWDEP_LOADER 400*1da177e4SLinus Torvalds #define HDSP_FW_LOADER 401*1da177e4SLinus Torvalds #endif 402*1da177e4SLinus Torvalds #endif 403*1da177e4SLinus Torvalds 404*1da177e4SLinus Torvalds typedef struct _hdsp hdsp_t; 405*1da177e4SLinus Torvalds typedef struct _hdsp_midi hdsp_midi_t; 406*1da177e4SLinus Torvalds typedef struct _hdsp_9632_meters hdsp_9632_meters_t; 407*1da177e4SLinus Torvalds 408*1da177e4SLinus Torvalds struct _hdsp_9632_meters { 409*1da177e4SLinus Torvalds u32 input_peak[16]; 410*1da177e4SLinus Torvalds u32 playback_peak[16]; 411*1da177e4SLinus Torvalds u32 output_peak[16]; 412*1da177e4SLinus Torvalds u32 xxx_peak[16]; 413*1da177e4SLinus Torvalds u32 padding[64]; 414*1da177e4SLinus Torvalds u32 input_rms_low[16]; 415*1da177e4SLinus Torvalds u32 playback_rms_low[16]; 416*1da177e4SLinus Torvalds u32 output_rms_low[16]; 417*1da177e4SLinus Torvalds u32 xxx_rms_low[16]; 418*1da177e4SLinus Torvalds u32 input_rms_high[16]; 419*1da177e4SLinus Torvalds u32 playback_rms_high[16]; 420*1da177e4SLinus Torvalds u32 output_rms_high[16]; 421*1da177e4SLinus Torvalds u32 xxx_rms_high[16]; 422*1da177e4SLinus Torvalds }; 423*1da177e4SLinus Torvalds 424*1da177e4SLinus Torvalds struct _hdsp_midi { 425*1da177e4SLinus Torvalds hdsp_t *hdsp; 426*1da177e4SLinus Torvalds int id; 427*1da177e4SLinus Torvalds snd_rawmidi_t *rmidi; 428*1da177e4SLinus Torvalds snd_rawmidi_substream_t *input; 429*1da177e4SLinus Torvalds snd_rawmidi_substream_t *output; 430*1da177e4SLinus Torvalds char istimer; /* timer in use */ 431*1da177e4SLinus Torvalds struct timer_list timer; 432*1da177e4SLinus Torvalds spinlock_t lock; 433*1da177e4SLinus Torvalds int pending; 434*1da177e4SLinus Torvalds }; 435*1da177e4SLinus Torvalds 436*1da177e4SLinus Torvalds struct _hdsp { 437*1da177e4SLinus Torvalds spinlock_t lock; 438*1da177e4SLinus Torvalds snd_pcm_substream_t *capture_substream; 439*1da177e4SLinus Torvalds snd_pcm_substream_t *playback_substream; 440*1da177e4SLinus Torvalds hdsp_midi_t midi[2]; 441*1da177e4SLinus Torvalds struct tasklet_struct midi_tasklet; 442*1da177e4SLinus Torvalds int use_midi_tasklet; 443*1da177e4SLinus Torvalds int precise_ptr; 444*1da177e4SLinus Torvalds u32 control_register; /* cached value */ 445*1da177e4SLinus Torvalds u32 control2_register; /* cached value */ 446*1da177e4SLinus Torvalds u32 creg_spdif; 447*1da177e4SLinus Torvalds u32 creg_spdif_stream; 448*1da177e4SLinus Torvalds char *card_name; /* digiface/multiface */ 449*1da177e4SLinus Torvalds HDSP_IO_Type io_type; /* ditto, but for code use */ 450*1da177e4SLinus Torvalds unsigned short firmware_rev; 451*1da177e4SLinus Torvalds unsigned short state; /* stores state bits */ 452*1da177e4SLinus Torvalds u32 firmware_cache[24413]; /* this helps recover from accidental iobox power failure */ 453*1da177e4SLinus Torvalds size_t period_bytes; /* guess what this is */ 454*1da177e4SLinus Torvalds unsigned char max_channels; 455*1da177e4SLinus Torvalds unsigned char qs_in_channels; /* quad speed mode for H9632 */ 456*1da177e4SLinus Torvalds unsigned char ds_in_channels; 457*1da177e4SLinus Torvalds unsigned char ss_in_channels; /* different for multiface/digiface */ 458*1da177e4SLinus Torvalds unsigned char qs_out_channels; 459*1da177e4SLinus Torvalds unsigned char ds_out_channels; 460*1da177e4SLinus Torvalds unsigned char ss_out_channels; 461*1da177e4SLinus Torvalds 462*1da177e4SLinus Torvalds struct snd_dma_buffer capture_dma_buf; 463*1da177e4SLinus Torvalds struct snd_dma_buffer playback_dma_buf; 464*1da177e4SLinus Torvalds unsigned char *capture_buffer; /* suitably aligned address */ 465*1da177e4SLinus Torvalds unsigned char *playback_buffer; /* suitably aligned address */ 466*1da177e4SLinus Torvalds 467*1da177e4SLinus Torvalds pid_t capture_pid; 468*1da177e4SLinus Torvalds pid_t playback_pid; 469*1da177e4SLinus Torvalds int running; 470*1da177e4SLinus Torvalds int system_sample_rate; 471*1da177e4SLinus Torvalds char *channel_map; 472*1da177e4SLinus Torvalds int dev; 473*1da177e4SLinus Torvalds int irq; 474*1da177e4SLinus Torvalds unsigned long port; 475*1da177e4SLinus Torvalds void __iomem *iobase; 476*1da177e4SLinus Torvalds snd_card_t *card; 477*1da177e4SLinus Torvalds snd_pcm_t *pcm; 478*1da177e4SLinus Torvalds snd_hwdep_t *hwdep; 479*1da177e4SLinus Torvalds struct pci_dev *pci; 480*1da177e4SLinus Torvalds snd_kcontrol_t *spdif_ctl; 481*1da177e4SLinus Torvalds unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE]; 482*1da177e4SLinus Torvalds }; 483*1da177e4SLinus Torvalds 484*1da177e4SLinus Torvalds /* These tables map the ALSA channels 1..N to the channels that we 485*1da177e4SLinus Torvalds need to use in order to find the relevant channel buffer. RME 486*1da177e4SLinus Torvalds refer to this kind of mapping as between "the ADAT channel and 487*1da177e4SLinus Torvalds the DMA channel." We index it using the logical audio channel, 488*1da177e4SLinus Torvalds and the value is the DMA channel (i.e. channel buffer number) 489*1da177e4SLinus Torvalds where the data for that channel can be read/written from/to. 490*1da177e4SLinus Torvalds */ 491*1da177e4SLinus Torvalds 492*1da177e4SLinus Torvalds static char channel_map_df_ss[HDSP_MAX_CHANNELS] = { 493*1da177e4SLinus Torvalds 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 494*1da177e4SLinus Torvalds 18, 19, 20, 21, 22, 23, 24, 25 495*1da177e4SLinus Torvalds }; 496*1da177e4SLinus Torvalds 497*1da177e4SLinus Torvalds static char channel_map_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */ 498*1da177e4SLinus Torvalds /* Analog */ 499*1da177e4SLinus Torvalds 0, 1, 2, 3, 4, 5, 6, 7, 500*1da177e4SLinus Torvalds /* ADAT 2 */ 501*1da177e4SLinus Torvalds 16, 17, 18, 19, 20, 21, 22, 23, 502*1da177e4SLinus Torvalds /* SPDIF */ 503*1da177e4SLinus Torvalds 24, 25, 504*1da177e4SLinus Torvalds -1, -1, -1, -1, -1, -1, -1, -1 505*1da177e4SLinus Torvalds }; 506*1da177e4SLinus Torvalds 507*1da177e4SLinus Torvalds static char channel_map_ds[HDSP_MAX_CHANNELS] = { 508*1da177e4SLinus Torvalds /* ADAT channels are remapped */ 509*1da177e4SLinus Torvalds 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 510*1da177e4SLinus Torvalds /* channels 12 and 13 are S/PDIF */ 511*1da177e4SLinus Torvalds 24, 25, 512*1da177e4SLinus Torvalds /* others don't exist */ 513*1da177e4SLinus Torvalds -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 514*1da177e4SLinus Torvalds }; 515*1da177e4SLinus Torvalds 516*1da177e4SLinus Torvalds static char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = { 517*1da177e4SLinus Torvalds /* ADAT channels */ 518*1da177e4SLinus Torvalds 0, 1, 2, 3, 4, 5, 6, 7, 519*1da177e4SLinus Torvalds /* SPDIF */ 520*1da177e4SLinus Torvalds 8, 9, 521*1da177e4SLinus Torvalds /* Analog */ 522*1da177e4SLinus Torvalds 10, 11, 523*1da177e4SLinus Torvalds /* AO4S-192 and AI4S-192 extension boards */ 524*1da177e4SLinus Torvalds 12, 13, 14, 15, 525*1da177e4SLinus Torvalds /* others don't exist */ 526*1da177e4SLinus Torvalds -1, -1, -1, -1, -1, -1, -1, -1, 527*1da177e4SLinus Torvalds -1, -1 528*1da177e4SLinus Torvalds }; 529*1da177e4SLinus Torvalds 530*1da177e4SLinus Torvalds static char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = { 531*1da177e4SLinus Torvalds /* ADAT */ 532*1da177e4SLinus Torvalds 1, 3, 5, 7, 533*1da177e4SLinus Torvalds /* SPDIF */ 534*1da177e4SLinus Torvalds 8, 9, 535*1da177e4SLinus Torvalds /* Analog */ 536*1da177e4SLinus Torvalds 10, 11, 537*1da177e4SLinus Torvalds /* AO4S-192 and AI4S-192 extension boards */ 538*1da177e4SLinus Torvalds 12, 13, 14, 15, 539*1da177e4SLinus Torvalds /* others don't exist */ 540*1da177e4SLinus Torvalds -1, -1, -1, -1, -1, -1, -1, -1, 541*1da177e4SLinus Torvalds -1, -1, -1, -1, -1, -1 542*1da177e4SLinus Torvalds }; 543*1da177e4SLinus Torvalds 544*1da177e4SLinus Torvalds static char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = { 545*1da177e4SLinus Torvalds /* ADAT is disabled in this mode */ 546*1da177e4SLinus Torvalds /* SPDIF */ 547*1da177e4SLinus Torvalds 8, 9, 548*1da177e4SLinus Torvalds /* Analog */ 549*1da177e4SLinus Torvalds 10, 11, 550*1da177e4SLinus Torvalds /* AO4S-192 and AI4S-192 extension boards */ 551*1da177e4SLinus Torvalds 12, 13, 14, 15, 552*1da177e4SLinus Torvalds /* others don't exist */ 553*1da177e4SLinus Torvalds -1, -1, -1, -1, -1, -1, -1, -1, 554*1da177e4SLinus Torvalds -1, -1, -1, -1, -1, -1, -1, -1, 555*1da177e4SLinus Torvalds -1, -1 556*1da177e4SLinus Torvalds }; 557*1da177e4SLinus Torvalds 558*1da177e4SLinus Torvalds static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size) 559*1da177e4SLinus Torvalds { 560*1da177e4SLinus Torvalds dmab->dev.type = SNDRV_DMA_TYPE_DEV; 561*1da177e4SLinus Torvalds dmab->dev.dev = snd_dma_pci_data(pci); 562*1da177e4SLinus Torvalds if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) { 563*1da177e4SLinus Torvalds if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 564*1da177e4SLinus Torvalds size, dmab) < 0) 565*1da177e4SLinus Torvalds return -ENOMEM; 566*1da177e4SLinus Torvalds } 567*1da177e4SLinus Torvalds return 0; 568*1da177e4SLinus Torvalds } 569*1da177e4SLinus Torvalds 570*1da177e4SLinus Torvalds static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci) 571*1da177e4SLinus Torvalds { 572*1da177e4SLinus Torvalds if (dmab->area) 573*1da177e4SLinus Torvalds snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci)); 574*1da177e4SLinus Torvalds } 575*1da177e4SLinus Torvalds 576*1da177e4SLinus Torvalds 577*1da177e4SLinus Torvalds static struct pci_device_id snd_hdsp_ids[] = { 578*1da177e4SLinus Torvalds { 579*1da177e4SLinus Torvalds .vendor = PCI_VENDOR_ID_XILINX, 580*1da177e4SLinus Torvalds .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP, 581*1da177e4SLinus Torvalds .subvendor = PCI_ANY_ID, 582*1da177e4SLinus Torvalds .subdevice = PCI_ANY_ID, 583*1da177e4SLinus Torvalds }, /* RME Hammerfall-DSP */ 584*1da177e4SLinus Torvalds { 0, }, 585*1da177e4SLinus Torvalds }; 586*1da177e4SLinus Torvalds 587*1da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, snd_hdsp_ids); 588*1da177e4SLinus Torvalds 589*1da177e4SLinus Torvalds /* prototypes */ 590*1da177e4SLinus Torvalds static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp); 591*1da177e4SLinus Torvalds static int snd_hdsp_create_pcm(snd_card_t *card, hdsp_t *hdsp); 592*1da177e4SLinus Torvalds static int snd_hdsp_enable_io (hdsp_t *hdsp); 593*1da177e4SLinus Torvalds static void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp); 594*1da177e4SLinus Torvalds static void snd_hdsp_initialize_channels (hdsp_t *hdsp); 595*1da177e4SLinus Torvalds static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout); 596*1da177e4SLinus Torvalds static int hdsp_autosync_ref(hdsp_t *hdsp); 597*1da177e4SLinus Torvalds static int snd_hdsp_set_defaults(hdsp_t *hdsp); 598*1da177e4SLinus Torvalds static void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp); 599*1da177e4SLinus Torvalds 600*1da177e4SLinus Torvalds static int hdsp_playback_to_output_key (hdsp_t *hdsp, int in, int out) 601*1da177e4SLinus Torvalds { 602*1da177e4SLinus Torvalds switch (hdsp->firmware_rev) { 603*1da177e4SLinus Torvalds case 0xa: 604*1da177e4SLinus Torvalds return (64 * out) + (32 + (in)); 605*1da177e4SLinus Torvalds case 0x96: 606*1da177e4SLinus Torvalds case 0x97: 607*1da177e4SLinus Torvalds return (32 * out) + (16 + (in)); 608*1da177e4SLinus Torvalds default: 609*1da177e4SLinus Torvalds return (52 * out) + (26 + (in)); 610*1da177e4SLinus Torvalds } 611*1da177e4SLinus Torvalds } 612*1da177e4SLinus Torvalds 613*1da177e4SLinus Torvalds static int hdsp_input_to_output_key (hdsp_t *hdsp, int in, int out) 614*1da177e4SLinus Torvalds { 615*1da177e4SLinus Torvalds switch (hdsp->firmware_rev) { 616*1da177e4SLinus Torvalds case 0xa: 617*1da177e4SLinus Torvalds return (64 * out) + in; 618*1da177e4SLinus Torvalds case 0x96: 619*1da177e4SLinus Torvalds case 0x97: 620*1da177e4SLinus Torvalds return (32 * out) + in; 621*1da177e4SLinus Torvalds default: 622*1da177e4SLinus Torvalds return (52 * out) + in; 623*1da177e4SLinus Torvalds } 624*1da177e4SLinus Torvalds } 625*1da177e4SLinus Torvalds 626*1da177e4SLinus Torvalds static void hdsp_write(hdsp_t *hdsp, int reg, int val) 627*1da177e4SLinus Torvalds { 628*1da177e4SLinus Torvalds writel(val, hdsp->iobase + reg); 629*1da177e4SLinus Torvalds } 630*1da177e4SLinus Torvalds 631*1da177e4SLinus Torvalds static unsigned int hdsp_read(hdsp_t *hdsp, int reg) 632*1da177e4SLinus Torvalds { 633*1da177e4SLinus Torvalds return readl (hdsp->iobase + reg); 634*1da177e4SLinus Torvalds } 635*1da177e4SLinus Torvalds 636*1da177e4SLinus Torvalds static int hdsp_check_for_iobox (hdsp_t *hdsp) 637*1da177e4SLinus Torvalds { 638*1da177e4SLinus Torvalds 639*1da177e4SLinus Torvalds if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; 640*1da177e4SLinus Torvalds if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_ConfigError) { 641*1da177e4SLinus Torvalds snd_printk ("Hammerfall-DSP: no Digiface or Multiface connected!\n"); 642*1da177e4SLinus Torvalds hdsp->state &= ~HDSP_FirmwareLoaded; 643*1da177e4SLinus Torvalds return -EIO; 644*1da177e4SLinus Torvalds } 645*1da177e4SLinus Torvalds return 0; 646*1da177e4SLinus Torvalds 647*1da177e4SLinus Torvalds } 648*1da177e4SLinus Torvalds 649*1da177e4SLinus Torvalds static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) { 650*1da177e4SLinus Torvalds 651*1da177e4SLinus Torvalds int i; 652*1da177e4SLinus Torvalds unsigned long flags; 653*1da177e4SLinus Torvalds 654*1da177e4SLinus Torvalds if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { 655*1da177e4SLinus Torvalds 656*1da177e4SLinus Torvalds snd_printk ("Hammerfall-DSP: loading firmware\n"); 657*1da177e4SLinus Torvalds 658*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM); 659*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_fifoData, 0); 660*1da177e4SLinus Torvalds 661*1da177e4SLinus Torvalds if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) { 662*1da177e4SLinus Torvalds snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n"); 663*1da177e4SLinus Torvalds return -EIO; 664*1da177e4SLinus Torvalds } 665*1da177e4SLinus Torvalds 666*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); 667*1da177e4SLinus Torvalds 668*1da177e4SLinus Torvalds for (i = 0; i < 24413; ++i) { 669*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]); 670*1da177e4SLinus Torvalds if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) { 671*1da177e4SLinus Torvalds snd_printk ("Hammerfall-DSP: timeout during firmware loading\n"); 672*1da177e4SLinus Torvalds return -EIO; 673*1da177e4SLinus Torvalds } 674*1da177e4SLinus Torvalds } 675*1da177e4SLinus Torvalds 676*1da177e4SLinus Torvalds if ((1000 / HZ) < 3000) { 677*1da177e4SLinus Torvalds set_current_state(TASK_UNINTERRUPTIBLE); 678*1da177e4SLinus Torvalds schedule_timeout((3000 * HZ + 999) / 1000); 679*1da177e4SLinus Torvalds } else { 680*1da177e4SLinus Torvalds mdelay(3000); 681*1da177e4SLinus Torvalds } 682*1da177e4SLinus Torvalds 683*1da177e4SLinus Torvalds if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) { 684*1da177e4SLinus Torvalds snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n"); 685*1da177e4SLinus Torvalds return -EIO; 686*1da177e4SLinus Torvalds } 687*1da177e4SLinus Torvalds 688*1da177e4SLinus Torvalds #ifdef SNDRV_BIG_ENDIAN 689*1da177e4SLinus Torvalds hdsp->control2_register = HDSP_BIGENDIAN_MODE; 690*1da177e4SLinus Torvalds #else 691*1da177e4SLinus Torvalds hdsp->control2_register = 0; 692*1da177e4SLinus Torvalds #endif 693*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register); 694*1da177e4SLinus Torvalds snd_printk ("Hammerfall-DSP: finished firmware loading\n"); 695*1da177e4SLinus Torvalds 696*1da177e4SLinus Torvalds } 697*1da177e4SLinus Torvalds if (hdsp->state & HDSP_InitializationComplete) { 698*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: firmware loaded from cache, restoring defaults\n"); 699*1da177e4SLinus Torvalds spin_lock_irqsave(&hdsp->lock, flags); 700*1da177e4SLinus Torvalds snd_hdsp_set_defaults(hdsp); 701*1da177e4SLinus Torvalds spin_unlock_irqrestore(&hdsp->lock, flags); 702*1da177e4SLinus Torvalds } 703*1da177e4SLinus Torvalds 704*1da177e4SLinus Torvalds hdsp->state |= HDSP_FirmwareLoaded; 705*1da177e4SLinus Torvalds 706*1da177e4SLinus Torvalds return 0; 707*1da177e4SLinus Torvalds } 708*1da177e4SLinus Torvalds 709*1da177e4SLinus Torvalds static int hdsp_get_iobox_version (hdsp_t *hdsp) 710*1da177e4SLinus Torvalds { 711*1da177e4SLinus Torvalds if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { 712*1da177e4SLinus Torvalds 713*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM); 714*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_fifoData, 0); 715*1da177e4SLinus Torvalds if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0) { 716*1da177e4SLinus Torvalds return -EIO; 717*1da177e4SLinus Torvalds } 718*1da177e4SLinus Torvalds 719*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); 720*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_fifoData, 0); 721*1da177e4SLinus Torvalds 722*1da177e4SLinus Torvalds if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT)) { 723*1da177e4SLinus Torvalds hdsp->io_type = Multiface; 724*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_control2Reg, HDSP_VERSION_BIT); 725*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD); 726*1da177e4SLinus Torvalds hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT); 727*1da177e4SLinus Torvalds } else { 728*1da177e4SLinus Torvalds hdsp->io_type = Digiface; 729*1da177e4SLinus Torvalds } 730*1da177e4SLinus Torvalds } else { 731*1da177e4SLinus Torvalds /* firmware was already loaded, get iobox type */ 732*1da177e4SLinus Torvalds if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) { 733*1da177e4SLinus Torvalds hdsp->io_type = Multiface; 734*1da177e4SLinus Torvalds } else { 735*1da177e4SLinus Torvalds hdsp->io_type = Digiface; 736*1da177e4SLinus Torvalds } 737*1da177e4SLinus Torvalds } 738*1da177e4SLinus Torvalds return 0; 739*1da177e4SLinus Torvalds } 740*1da177e4SLinus Torvalds 741*1da177e4SLinus Torvalds 742*1da177e4SLinus Torvalds static int hdsp_check_for_firmware (hdsp_t *hdsp) 743*1da177e4SLinus Torvalds { 744*1da177e4SLinus Torvalds if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; 745*1da177e4SLinus Torvalds if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { 746*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: firmware not present.\n"); 747*1da177e4SLinus Torvalds hdsp->state &= ~HDSP_FirmwareLoaded; 748*1da177e4SLinus Torvalds return -EIO; 749*1da177e4SLinus Torvalds } 750*1da177e4SLinus Torvalds return 0; 751*1da177e4SLinus Torvalds } 752*1da177e4SLinus Torvalds 753*1da177e4SLinus Torvalds 754*1da177e4SLinus Torvalds static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout) 755*1da177e4SLinus Torvalds { 756*1da177e4SLinus Torvalds int i; 757*1da177e4SLinus Torvalds 758*1da177e4SLinus Torvalds /* the fifoStatus registers reports on how many words 759*1da177e4SLinus Torvalds are available in the command FIFO. 760*1da177e4SLinus Torvalds */ 761*1da177e4SLinus Torvalds 762*1da177e4SLinus Torvalds for (i = 0; i < timeout; i++) { 763*1da177e4SLinus Torvalds 764*1da177e4SLinus Torvalds if ((int)(hdsp_read (hdsp, HDSP_fifoStatus) & 0xff) <= count) 765*1da177e4SLinus Torvalds return 0; 766*1da177e4SLinus Torvalds 767*1da177e4SLinus Torvalds /* not very friendly, but we only do this during a firmware 768*1da177e4SLinus Torvalds load and changing the mixer, so we just put up with it. 769*1da177e4SLinus Torvalds */ 770*1da177e4SLinus Torvalds 771*1da177e4SLinus Torvalds udelay (100); 772*1da177e4SLinus Torvalds } 773*1da177e4SLinus Torvalds 774*1da177e4SLinus Torvalds snd_printk ("Hammerfall-DSP: wait for FIFO status <= %d failed after %d iterations\n", 775*1da177e4SLinus Torvalds count, timeout); 776*1da177e4SLinus Torvalds return -1; 777*1da177e4SLinus Torvalds } 778*1da177e4SLinus Torvalds 779*1da177e4SLinus Torvalds static int hdsp_read_gain (hdsp_t *hdsp, unsigned int addr) 780*1da177e4SLinus Torvalds { 781*1da177e4SLinus Torvalds if (addr >= HDSP_MATRIX_MIXER_SIZE) { 782*1da177e4SLinus Torvalds return 0; 783*1da177e4SLinus Torvalds } 784*1da177e4SLinus Torvalds return hdsp->mixer_matrix[addr]; 785*1da177e4SLinus Torvalds } 786*1da177e4SLinus Torvalds 787*1da177e4SLinus Torvalds static int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned short data) 788*1da177e4SLinus Torvalds { 789*1da177e4SLinus Torvalds unsigned int ad; 790*1da177e4SLinus Torvalds 791*1da177e4SLinus Torvalds if (addr >= HDSP_MATRIX_MIXER_SIZE) 792*1da177e4SLinus Torvalds return -1; 793*1da177e4SLinus Torvalds 794*1da177e4SLinus Torvalds if (hdsp->io_type == H9652 || hdsp->io_type == H9632) { 795*1da177e4SLinus Torvalds 796*1da177e4SLinus Torvalds /* from martin bjornsen: 797*1da177e4SLinus Torvalds 798*1da177e4SLinus Torvalds "You can only write dwords to the 799*1da177e4SLinus Torvalds mixer memory which contain two 800*1da177e4SLinus Torvalds mixer values in the low and high 801*1da177e4SLinus Torvalds word. So if you want to change 802*1da177e4SLinus Torvalds value 0 you have to read value 1 803*1da177e4SLinus Torvalds from the cache and write both to 804*1da177e4SLinus Torvalds the first dword in the mixer 805*1da177e4SLinus Torvalds memory." 806*1da177e4SLinus Torvalds */ 807*1da177e4SLinus Torvalds 808*1da177e4SLinus Torvalds if (hdsp->io_type == H9632 && addr >= 512) { 809*1da177e4SLinus Torvalds return 0; 810*1da177e4SLinus Torvalds } 811*1da177e4SLinus Torvalds 812*1da177e4SLinus Torvalds if (hdsp->io_type == H9652 && addr >= 1352) { 813*1da177e4SLinus Torvalds return 0; 814*1da177e4SLinus Torvalds } 815*1da177e4SLinus Torvalds 816*1da177e4SLinus Torvalds hdsp->mixer_matrix[addr] = data; 817*1da177e4SLinus Torvalds 818*1da177e4SLinus Torvalds 819*1da177e4SLinus Torvalds /* `addr' addresses a 16-bit wide address, but 820*1da177e4SLinus Torvalds the address space accessed via hdsp_write 821*1da177e4SLinus Torvalds uses byte offsets. put another way, addr 822*1da177e4SLinus Torvalds varies from 0 to 1351, but to access the 823*1da177e4SLinus Torvalds corresponding memory location, we need 824*1da177e4SLinus Torvalds to access 0 to 2703 ... 825*1da177e4SLinus Torvalds */ 826*1da177e4SLinus Torvalds ad = addr/2; 827*1da177e4SLinus Torvalds 828*1da177e4SLinus Torvalds hdsp_write (hdsp, 4096 + (ad*4), 829*1da177e4SLinus Torvalds (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) + 830*1da177e4SLinus Torvalds hdsp->mixer_matrix[addr&0x7fe]); 831*1da177e4SLinus Torvalds 832*1da177e4SLinus Torvalds return 0; 833*1da177e4SLinus Torvalds 834*1da177e4SLinus Torvalds } else { 835*1da177e4SLinus Torvalds 836*1da177e4SLinus Torvalds ad = (addr << 16) + data; 837*1da177e4SLinus Torvalds 838*1da177e4SLinus Torvalds if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT)) { 839*1da177e4SLinus Torvalds return -1; 840*1da177e4SLinus Torvalds } 841*1da177e4SLinus Torvalds 842*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_fifoData, ad); 843*1da177e4SLinus Torvalds hdsp->mixer_matrix[addr] = data; 844*1da177e4SLinus Torvalds 845*1da177e4SLinus Torvalds } 846*1da177e4SLinus Torvalds 847*1da177e4SLinus Torvalds return 0; 848*1da177e4SLinus Torvalds } 849*1da177e4SLinus Torvalds 850*1da177e4SLinus Torvalds static int snd_hdsp_use_is_exclusive(hdsp_t *hdsp) 851*1da177e4SLinus Torvalds { 852*1da177e4SLinus Torvalds unsigned long flags; 853*1da177e4SLinus Torvalds int ret = 1; 854*1da177e4SLinus Torvalds 855*1da177e4SLinus Torvalds spin_lock_irqsave(&hdsp->lock, flags); 856*1da177e4SLinus Torvalds if ((hdsp->playback_pid != hdsp->capture_pid) && 857*1da177e4SLinus Torvalds (hdsp->playback_pid >= 0) && (hdsp->capture_pid >= 0)) { 858*1da177e4SLinus Torvalds ret = 0; 859*1da177e4SLinus Torvalds } 860*1da177e4SLinus Torvalds spin_unlock_irqrestore(&hdsp->lock, flags); 861*1da177e4SLinus Torvalds return ret; 862*1da177e4SLinus Torvalds } 863*1da177e4SLinus Torvalds 864*1da177e4SLinus Torvalds static int hdsp_external_sample_rate (hdsp_t *hdsp) 865*1da177e4SLinus Torvalds { 866*1da177e4SLinus Torvalds unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register); 867*1da177e4SLinus Torvalds unsigned int rate_bits = status2 & HDSP_systemFrequencyMask; 868*1da177e4SLinus Torvalds 869*1da177e4SLinus Torvalds switch (rate_bits) { 870*1da177e4SLinus Torvalds case HDSP_systemFrequency32: return 32000; 871*1da177e4SLinus Torvalds case HDSP_systemFrequency44_1: return 44100; 872*1da177e4SLinus Torvalds case HDSP_systemFrequency48: return 48000; 873*1da177e4SLinus Torvalds case HDSP_systemFrequency64: return 64000; 874*1da177e4SLinus Torvalds case HDSP_systemFrequency88_2: return 88200; 875*1da177e4SLinus Torvalds case HDSP_systemFrequency96: return 96000; 876*1da177e4SLinus Torvalds default: 877*1da177e4SLinus Torvalds return 0; 878*1da177e4SLinus Torvalds } 879*1da177e4SLinus Torvalds } 880*1da177e4SLinus Torvalds 881*1da177e4SLinus Torvalds static int hdsp_spdif_sample_rate(hdsp_t *hdsp) 882*1da177e4SLinus Torvalds { 883*1da177e4SLinus Torvalds unsigned int status = hdsp_read(hdsp, HDSP_statusRegister); 884*1da177e4SLinus Torvalds unsigned int rate_bits = (status & HDSP_spdifFrequencyMask); 885*1da177e4SLinus Torvalds 886*1da177e4SLinus Torvalds if (status & HDSP_SPDIFErrorFlag) { 887*1da177e4SLinus Torvalds return 0; 888*1da177e4SLinus Torvalds } 889*1da177e4SLinus Torvalds 890*1da177e4SLinus Torvalds switch (rate_bits) { 891*1da177e4SLinus Torvalds case HDSP_spdifFrequency32KHz: return 32000; 892*1da177e4SLinus Torvalds case HDSP_spdifFrequency44_1KHz: return 44100; 893*1da177e4SLinus Torvalds case HDSP_spdifFrequency48KHz: return 48000; 894*1da177e4SLinus Torvalds case HDSP_spdifFrequency64KHz: return 64000; 895*1da177e4SLinus Torvalds case HDSP_spdifFrequency88_2KHz: return 88200; 896*1da177e4SLinus Torvalds case HDSP_spdifFrequency96KHz: return 96000; 897*1da177e4SLinus Torvalds case HDSP_spdifFrequency128KHz: 898*1da177e4SLinus Torvalds if (hdsp->io_type == H9632) return 128000; 899*1da177e4SLinus Torvalds break; 900*1da177e4SLinus Torvalds case HDSP_spdifFrequency176_4KHz: 901*1da177e4SLinus Torvalds if (hdsp->io_type == H9632) return 176400; 902*1da177e4SLinus Torvalds break; 903*1da177e4SLinus Torvalds case HDSP_spdifFrequency192KHz: 904*1da177e4SLinus Torvalds if (hdsp->io_type == H9632) return 192000; 905*1da177e4SLinus Torvalds break; 906*1da177e4SLinus Torvalds default: 907*1da177e4SLinus Torvalds break; 908*1da177e4SLinus Torvalds } 909*1da177e4SLinus Torvalds snd_printk ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status); 910*1da177e4SLinus Torvalds return 0; 911*1da177e4SLinus Torvalds } 912*1da177e4SLinus Torvalds 913*1da177e4SLinus Torvalds static void hdsp_compute_period_size(hdsp_t *hdsp) 914*1da177e4SLinus Torvalds { 915*1da177e4SLinus Torvalds hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8)); 916*1da177e4SLinus Torvalds } 917*1da177e4SLinus Torvalds 918*1da177e4SLinus Torvalds static snd_pcm_uframes_t hdsp_hw_pointer(hdsp_t *hdsp) 919*1da177e4SLinus Torvalds { 920*1da177e4SLinus Torvalds int position; 921*1da177e4SLinus Torvalds 922*1da177e4SLinus Torvalds position = hdsp_read(hdsp, HDSP_statusRegister); 923*1da177e4SLinus Torvalds 924*1da177e4SLinus Torvalds if (!hdsp->precise_ptr) { 925*1da177e4SLinus Torvalds return (position & HDSP_BufferID) ? (hdsp->period_bytes / 4) : 0; 926*1da177e4SLinus Torvalds } 927*1da177e4SLinus Torvalds 928*1da177e4SLinus Torvalds position &= HDSP_BufferPositionMask; 929*1da177e4SLinus Torvalds position /= 4; 930*1da177e4SLinus Torvalds position &= (hdsp->period_bytes/2) - 1; 931*1da177e4SLinus Torvalds return position; 932*1da177e4SLinus Torvalds } 933*1da177e4SLinus Torvalds 934*1da177e4SLinus Torvalds static void hdsp_reset_hw_pointer(hdsp_t *hdsp) 935*1da177e4SLinus Torvalds { 936*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_resetPointer, 0); 937*1da177e4SLinus Torvalds } 938*1da177e4SLinus Torvalds 939*1da177e4SLinus Torvalds static void hdsp_start_audio(hdsp_t *s) 940*1da177e4SLinus Torvalds { 941*1da177e4SLinus Torvalds s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start); 942*1da177e4SLinus Torvalds hdsp_write(s, HDSP_controlRegister, s->control_register); 943*1da177e4SLinus Torvalds } 944*1da177e4SLinus Torvalds 945*1da177e4SLinus Torvalds static void hdsp_stop_audio(hdsp_t *s) 946*1da177e4SLinus Torvalds { 947*1da177e4SLinus Torvalds s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable); 948*1da177e4SLinus Torvalds hdsp_write(s, HDSP_controlRegister, s->control_register); 949*1da177e4SLinus Torvalds } 950*1da177e4SLinus Torvalds 951*1da177e4SLinus Torvalds static void hdsp_silence_playback(hdsp_t *hdsp) 952*1da177e4SLinus Torvalds { 953*1da177e4SLinus Torvalds memset(hdsp->playback_buffer, 0, HDSP_DMA_AREA_BYTES); 954*1da177e4SLinus Torvalds } 955*1da177e4SLinus Torvalds 956*1da177e4SLinus Torvalds static int hdsp_set_interrupt_interval(hdsp_t *s, unsigned int frames) 957*1da177e4SLinus Torvalds { 958*1da177e4SLinus Torvalds int n; 959*1da177e4SLinus Torvalds 960*1da177e4SLinus Torvalds spin_lock_irq(&s->lock); 961*1da177e4SLinus Torvalds 962*1da177e4SLinus Torvalds frames >>= 7; 963*1da177e4SLinus Torvalds n = 0; 964*1da177e4SLinus Torvalds while (frames) { 965*1da177e4SLinus Torvalds n++; 966*1da177e4SLinus Torvalds frames >>= 1; 967*1da177e4SLinus Torvalds } 968*1da177e4SLinus Torvalds 969*1da177e4SLinus Torvalds s->control_register &= ~HDSP_LatencyMask; 970*1da177e4SLinus Torvalds s->control_register |= hdsp_encode_latency(n); 971*1da177e4SLinus Torvalds 972*1da177e4SLinus Torvalds hdsp_write(s, HDSP_controlRegister, s->control_register); 973*1da177e4SLinus Torvalds 974*1da177e4SLinus Torvalds hdsp_compute_period_size(s); 975*1da177e4SLinus Torvalds 976*1da177e4SLinus Torvalds spin_unlock_irq(&s->lock); 977*1da177e4SLinus Torvalds 978*1da177e4SLinus Torvalds return 0; 979*1da177e4SLinus Torvalds } 980*1da177e4SLinus Torvalds 981*1da177e4SLinus Torvalds static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally) 982*1da177e4SLinus Torvalds { 983*1da177e4SLinus Torvalds int reject_if_open = 0; 984*1da177e4SLinus Torvalds int current_rate; 985*1da177e4SLinus Torvalds int rate_bits; 986*1da177e4SLinus Torvalds 987*1da177e4SLinus Torvalds /* ASSUMPTION: hdsp->lock is either held, or 988*1da177e4SLinus Torvalds there is no need for it (e.g. during module 989*1da177e4SLinus Torvalds initialization). 990*1da177e4SLinus Torvalds */ 991*1da177e4SLinus Torvalds 992*1da177e4SLinus Torvalds if (!(hdsp->control_register & HDSP_ClockModeMaster)) { 993*1da177e4SLinus Torvalds if (called_internally) { 994*1da177e4SLinus Torvalds /* request from ctl or card initialization */ 995*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: device is not running as a clock master: cannot set sample rate.\n"); 996*1da177e4SLinus Torvalds return -1; 997*1da177e4SLinus Torvalds } else { 998*1da177e4SLinus Torvalds /* hw_param request while in AutoSync mode */ 999*1da177e4SLinus Torvalds int external_freq = hdsp_external_sample_rate(hdsp); 1000*1da177e4SLinus Torvalds int spdif_freq = hdsp_spdif_sample_rate(hdsp); 1001*1da177e4SLinus Torvalds 1002*1da177e4SLinus Torvalds if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) { 1003*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: Detected ADAT in double speed mode\n"); 1004*1da177e4SLinus Torvalds } else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) { 1005*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: Detected ADAT in quad speed mode\n"); 1006*1da177e4SLinus Torvalds } else if (rate != external_freq) { 1007*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: No AutoSync source for requested rate\n"); 1008*1da177e4SLinus Torvalds return -1; 1009*1da177e4SLinus Torvalds } 1010*1da177e4SLinus Torvalds } 1011*1da177e4SLinus Torvalds } 1012*1da177e4SLinus Torvalds 1013*1da177e4SLinus Torvalds current_rate = hdsp->system_sample_rate; 1014*1da177e4SLinus Torvalds 1015*1da177e4SLinus Torvalds /* Changing from a "single speed" to a "double speed" rate is 1016*1da177e4SLinus Torvalds not allowed if any substreams are open. This is because 1017*1da177e4SLinus Torvalds such a change causes a shift in the location of 1018*1da177e4SLinus Torvalds the DMA buffers and a reduction in the number of available 1019*1da177e4SLinus Torvalds buffers. 1020*1da177e4SLinus Torvalds 1021*1da177e4SLinus Torvalds Note that a similar but essentially insoluble problem 1022*1da177e4SLinus Torvalds exists for externally-driven rate changes. All we can do 1023*1da177e4SLinus Torvalds is to flag rate changes in the read/write routines. */ 1024*1da177e4SLinus Torvalds 1025*1da177e4SLinus Torvalds if (rate > 96000 && hdsp->io_type != H9632) { 1026*1da177e4SLinus Torvalds return -EINVAL; 1027*1da177e4SLinus Torvalds } 1028*1da177e4SLinus Torvalds 1029*1da177e4SLinus Torvalds switch (rate) { 1030*1da177e4SLinus Torvalds case 32000: 1031*1da177e4SLinus Torvalds if (current_rate > 48000) { 1032*1da177e4SLinus Torvalds reject_if_open = 1; 1033*1da177e4SLinus Torvalds } 1034*1da177e4SLinus Torvalds rate_bits = HDSP_Frequency32KHz; 1035*1da177e4SLinus Torvalds break; 1036*1da177e4SLinus Torvalds case 44100: 1037*1da177e4SLinus Torvalds if (current_rate > 48000) { 1038*1da177e4SLinus Torvalds reject_if_open = 1; 1039*1da177e4SLinus Torvalds } 1040*1da177e4SLinus Torvalds rate_bits = HDSP_Frequency44_1KHz; 1041*1da177e4SLinus Torvalds break; 1042*1da177e4SLinus Torvalds case 48000: 1043*1da177e4SLinus Torvalds if (current_rate > 48000) { 1044*1da177e4SLinus Torvalds reject_if_open = 1; 1045*1da177e4SLinus Torvalds } 1046*1da177e4SLinus Torvalds rate_bits = HDSP_Frequency48KHz; 1047*1da177e4SLinus Torvalds break; 1048*1da177e4SLinus Torvalds case 64000: 1049*1da177e4SLinus Torvalds if (current_rate <= 48000 || current_rate > 96000) { 1050*1da177e4SLinus Torvalds reject_if_open = 1; 1051*1da177e4SLinus Torvalds } 1052*1da177e4SLinus Torvalds rate_bits = HDSP_Frequency64KHz; 1053*1da177e4SLinus Torvalds break; 1054*1da177e4SLinus Torvalds case 88200: 1055*1da177e4SLinus Torvalds if (current_rate <= 48000 || current_rate > 96000) { 1056*1da177e4SLinus Torvalds reject_if_open = 1; 1057*1da177e4SLinus Torvalds } 1058*1da177e4SLinus Torvalds rate_bits = HDSP_Frequency88_2KHz; 1059*1da177e4SLinus Torvalds break; 1060*1da177e4SLinus Torvalds case 96000: 1061*1da177e4SLinus Torvalds if (current_rate <= 48000 || current_rate > 96000) { 1062*1da177e4SLinus Torvalds reject_if_open = 1; 1063*1da177e4SLinus Torvalds } 1064*1da177e4SLinus Torvalds rate_bits = HDSP_Frequency96KHz; 1065*1da177e4SLinus Torvalds break; 1066*1da177e4SLinus Torvalds case 128000: 1067*1da177e4SLinus Torvalds if (current_rate < 128000) { 1068*1da177e4SLinus Torvalds reject_if_open = 1; 1069*1da177e4SLinus Torvalds } 1070*1da177e4SLinus Torvalds rate_bits = HDSP_Frequency128KHz; 1071*1da177e4SLinus Torvalds break; 1072*1da177e4SLinus Torvalds case 176400: 1073*1da177e4SLinus Torvalds if (current_rate < 128000) { 1074*1da177e4SLinus Torvalds reject_if_open = 1; 1075*1da177e4SLinus Torvalds } 1076*1da177e4SLinus Torvalds rate_bits = HDSP_Frequency176_4KHz; 1077*1da177e4SLinus Torvalds break; 1078*1da177e4SLinus Torvalds case 192000: 1079*1da177e4SLinus Torvalds if (current_rate < 128000) { 1080*1da177e4SLinus Torvalds reject_if_open = 1; 1081*1da177e4SLinus Torvalds } 1082*1da177e4SLinus Torvalds rate_bits = HDSP_Frequency192KHz; 1083*1da177e4SLinus Torvalds break; 1084*1da177e4SLinus Torvalds default: 1085*1da177e4SLinus Torvalds return -EINVAL; 1086*1da177e4SLinus Torvalds } 1087*1da177e4SLinus Torvalds 1088*1da177e4SLinus Torvalds if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) { 1089*1da177e4SLinus Torvalds snd_printk ("Hammerfall-DSP: cannot change speed mode (capture PID = %d, playback PID = %d)\n", 1090*1da177e4SLinus Torvalds hdsp->capture_pid, 1091*1da177e4SLinus Torvalds hdsp->playback_pid); 1092*1da177e4SLinus Torvalds return -EBUSY; 1093*1da177e4SLinus Torvalds } 1094*1da177e4SLinus Torvalds 1095*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_FrequencyMask; 1096*1da177e4SLinus Torvalds hdsp->control_register |= rate_bits; 1097*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 1098*1da177e4SLinus Torvalds 1099*1da177e4SLinus Torvalds if (rate >= 128000) { 1100*1da177e4SLinus Torvalds hdsp->channel_map = channel_map_H9632_qs; 1101*1da177e4SLinus Torvalds } else if (rate > 48000) { 1102*1da177e4SLinus Torvalds if (hdsp->io_type == H9632) { 1103*1da177e4SLinus Torvalds hdsp->channel_map = channel_map_H9632_ds; 1104*1da177e4SLinus Torvalds } else { 1105*1da177e4SLinus Torvalds hdsp->channel_map = channel_map_ds; 1106*1da177e4SLinus Torvalds } 1107*1da177e4SLinus Torvalds } else { 1108*1da177e4SLinus Torvalds switch (hdsp->io_type) { 1109*1da177e4SLinus Torvalds case Multiface: 1110*1da177e4SLinus Torvalds hdsp->channel_map = channel_map_mf_ss; 1111*1da177e4SLinus Torvalds break; 1112*1da177e4SLinus Torvalds case Digiface: 1113*1da177e4SLinus Torvalds case H9652: 1114*1da177e4SLinus Torvalds hdsp->channel_map = channel_map_df_ss; 1115*1da177e4SLinus Torvalds break; 1116*1da177e4SLinus Torvalds case H9632: 1117*1da177e4SLinus Torvalds hdsp->channel_map = channel_map_H9632_ss; 1118*1da177e4SLinus Torvalds break; 1119*1da177e4SLinus Torvalds default: 1120*1da177e4SLinus Torvalds /* should never happen */ 1121*1da177e4SLinus Torvalds break; 1122*1da177e4SLinus Torvalds } 1123*1da177e4SLinus Torvalds } 1124*1da177e4SLinus Torvalds 1125*1da177e4SLinus Torvalds hdsp->system_sample_rate = rate; 1126*1da177e4SLinus Torvalds 1127*1da177e4SLinus Torvalds return 0; 1128*1da177e4SLinus Torvalds } 1129*1da177e4SLinus Torvalds 1130*1da177e4SLinus Torvalds /*---------------------------------------------------------------------------- 1131*1da177e4SLinus Torvalds MIDI 1132*1da177e4SLinus Torvalds ----------------------------------------------------------------------------*/ 1133*1da177e4SLinus Torvalds 1134*1da177e4SLinus Torvalds static unsigned char snd_hdsp_midi_read_byte (hdsp_t *hdsp, int id) 1135*1da177e4SLinus Torvalds { 1136*1da177e4SLinus Torvalds /* the hardware already does the relevant bit-mask with 0xff */ 1137*1da177e4SLinus Torvalds if (id) { 1138*1da177e4SLinus Torvalds return hdsp_read(hdsp, HDSP_midiDataIn1); 1139*1da177e4SLinus Torvalds } else { 1140*1da177e4SLinus Torvalds return hdsp_read(hdsp, HDSP_midiDataIn0); 1141*1da177e4SLinus Torvalds } 1142*1da177e4SLinus Torvalds } 1143*1da177e4SLinus Torvalds 1144*1da177e4SLinus Torvalds static void snd_hdsp_midi_write_byte (hdsp_t *hdsp, int id, int val) 1145*1da177e4SLinus Torvalds { 1146*1da177e4SLinus Torvalds /* the hardware already does the relevant bit-mask with 0xff */ 1147*1da177e4SLinus Torvalds if (id) { 1148*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_midiDataOut1, val); 1149*1da177e4SLinus Torvalds } else { 1150*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_midiDataOut0, val); 1151*1da177e4SLinus Torvalds } 1152*1da177e4SLinus Torvalds } 1153*1da177e4SLinus Torvalds 1154*1da177e4SLinus Torvalds static int snd_hdsp_midi_input_available (hdsp_t *hdsp, int id) 1155*1da177e4SLinus Torvalds { 1156*1da177e4SLinus Torvalds if (id) { 1157*1da177e4SLinus Torvalds return (hdsp_read(hdsp, HDSP_midiStatusIn1) & 0xff); 1158*1da177e4SLinus Torvalds } else { 1159*1da177e4SLinus Torvalds return (hdsp_read(hdsp, HDSP_midiStatusIn0) & 0xff); 1160*1da177e4SLinus Torvalds } 1161*1da177e4SLinus Torvalds } 1162*1da177e4SLinus Torvalds 1163*1da177e4SLinus Torvalds static int snd_hdsp_midi_output_possible (hdsp_t *hdsp, int id) 1164*1da177e4SLinus Torvalds { 1165*1da177e4SLinus Torvalds int fifo_bytes_used; 1166*1da177e4SLinus Torvalds 1167*1da177e4SLinus Torvalds if (id) { 1168*1da177e4SLinus Torvalds fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut1) & 0xff; 1169*1da177e4SLinus Torvalds } else { 1170*1da177e4SLinus Torvalds fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut0) & 0xff; 1171*1da177e4SLinus Torvalds } 1172*1da177e4SLinus Torvalds 1173*1da177e4SLinus Torvalds if (fifo_bytes_used < 128) { 1174*1da177e4SLinus Torvalds return 128 - fifo_bytes_used; 1175*1da177e4SLinus Torvalds } else { 1176*1da177e4SLinus Torvalds return 0; 1177*1da177e4SLinus Torvalds } 1178*1da177e4SLinus Torvalds } 1179*1da177e4SLinus Torvalds 1180*1da177e4SLinus Torvalds static void snd_hdsp_flush_midi_input (hdsp_t *hdsp, int id) 1181*1da177e4SLinus Torvalds { 1182*1da177e4SLinus Torvalds while (snd_hdsp_midi_input_available (hdsp, id)) { 1183*1da177e4SLinus Torvalds snd_hdsp_midi_read_byte (hdsp, id); 1184*1da177e4SLinus Torvalds } 1185*1da177e4SLinus Torvalds } 1186*1da177e4SLinus Torvalds 1187*1da177e4SLinus Torvalds static int snd_hdsp_midi_output_write (hdsp_midi_t *hmidi) 1188*1da177e4SLinus Torvalds { 1189*1da177e4SLinus Torvalds unsigned long flags; 1190*1da177e4SLinus Torvalds int n_pending; 1191*1da177e4SLinus Torvalds int to_write; 1192*1da177e4SLinus Torvalds int i; 1193*1da177e4SLinus Torvalds unsigned char buf[128]; 1194*1da177e4SLinus Torvalds 1195*1da177e4SLinus Torvalds /* Output is not interrupt driven */ 1196*1da177e4SLinus Torvalds 1197*1da177e4SLinus Torvalds spin_lock_irqsave (&hmidi->lock, flags); 1198*1da177e4SLinus Torvalds if (hmidi->output) { 1199*1da177e4SLinus Torvalds if (!snd_rawmidi_transmit_empty (hmidi->output)) { 1200*1da177e4SLinus Torvalds if ((n_pending = snd_hdsp_midi_output_possible (hmidi->hdsp, hmidi->id)) > 0) { 1201*1da177e4SLinus Torvalds if (n_pending > (int)sizeof (buf)) 1202*1da177e4SLinus Torvalds n_pending = sizeof (buf); 1203*1da177e4SLinus Torvalds 1204*1da177e4SLinus Torvalds if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) { 1205*1da177e4SLinus Torvalds for (i = 0; i < to_write; ++i) 1206*1da177e4SLinus Torvalds snd_hdsp_midi_write_byte (hmidi->hdsp, hmidi->id, buf[i]); 1207*1da177e4SLinus Torvalds } 1208*1da177e4SLinus Torvalds } 1209*1da177e4SLinus Torvalds } 1210*1da177e4SLinus Torvalds } 1211*1da177e4SLinus Torvalds spin_unlock_irqrestore (&hmidi->lock, flags); 1212*1da177e4SLinus Torvalds return 0; 1213*1da177e4SLinus Torvalds } 1214*1da177e4SLinus Torvalds 1215*1da177e4SLinus Torvalds static int snd_hdsp_midi_input_read (hdsp_midi_t *hmidi) 1216*1da177e4SLinus Torvalds { 1217*1da177e4SLinus Torvalds unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */ 1218*1da177e4SLinus Torvalds unsigned long flags; 1219*1da177e4SLinus Torvalds int n_pending; 1220*1da177e4SLinus Torvalds int i; 1221*1da177e4SLinus Torvalds 1222*1da177e4SLinus Torvalds spin_lock_irqsave (&hmidi->lock, flags); 1223*1da177e4SLinus Torvalds if ((n_pending = snd_hdsp_midi_input_available (hmidi->hdsp, hmidi->id)) > 0) { 1224*1da177e4SLinus Torvalds if (hmidi->input) { 1225*1da177e4SLinus Torvalds if (n_pending > (int)sizeof (buf)) { 1226*1da177e4SLinus Torvalds n_pending = sizeof (buf); 1227*1da177e4SLinus Torvalds } 1228*1da177e4SLinus Torvalds for (i = 0; i < n_pending; ++i) { 1229*1da177e4SLinus Torvalds buf[i] = snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id); 1230*1da177e4SLinus Torvalds } 1231*1da177e4SLinus Torvalds if (n_pending) { 1232*1da177e4SLinus Torvalds snd_rawmidi_receive (hmidi->input, buf, n_pending); 1233*1da177e4SLinus Torvalds } 1234*1da177e4SLinus Torvalds } else { 1235*1da177e4SLinus Torvalds /* flush the MIDI input FIFO */ 1236*1da177e4SLinus Torvalds while (--n_pending) { 1237*1da177e4SLinus Torvalds snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id); 1238*1da177e4SLinus Torvalds } 1239*1da177e4SLinus Torvalds } 1240*1da177e4SLinus Torvalds } 1241*1da177e4SLinus Torvalds hmidi->pending = 0; 1242*1da177e4SLinus Torvalds if (hmidi->id) { 1243*1da177e4SLinus Torvalds hmidi->hdsp->control_register |= HDSP_Midi1InterruptEnable; 1244*1da177e4SLinus Torvalds } else { 1245*1da177e4SLinus Torvalds hmidi->hdsp->control_register |= HDSP_Midi0InterruptEnable; 1246*1da177e4SLinus Torvalds } 1247*1da177e4SLinus Torvalds hdsp_write(hmidi->hdsp, HDSP_controlRegister, hmidi->hdsp->control_register); 1248*1da177e4SLinus Torvalds spin_unlock_irqrestore (&hmidi->lock, flags); 1249*1da177e4SLinus Torvalds return snd_hdsp_midi_output_write (hmidi); 1250*1da177e4SLinus Torvalds } 1251*1da177e4SLinus Torvalds 1252*1da177e4SLinus Torvalds static void snd_hdsp_midi_input_trigger(snd_rawmidi_substream_t * substream, int up) 1253*1da177e4SLinus Torvalds { 1254*1da177e4SLinus Torvalds hdsp_t *hdsp; 1255*1da177e4SLinus Torvalds hdsp_midi_t *hmidi; 1256*1da177e4SLinus Torvalds unsigned long flags; 1257*1da177e4SLinus Torvalds u32 ie; 1258*1da177e4SLinus Torvalds 1259*1da177e4SLinus Torvalds hmidi = (hdsp_midi_t *) substream->rmidi->private_data; 1260*1da177e4SLinus Torvalds hdsp = hmidi->hdsp; 1261*1da177e4SLinus Torvalds ie = hmidi->id ? HDSP_Midi1InterruptEnable : HDSP_Midi0InterruptEnable; 1262*1da177e4SLinus Torvalds spin_lock_irqsave (&hdsp->lock, flags); 1263*1da177e4SLinus Torvalds if (up) { 1264*1da177e4SLinus Torvalds if (!(hdsp->control_register & ie)) { 1265*1da177e4SLinus Torvalds snd_hdsp_flush_midi_input (hdsp, hmidi->id); 1266*1da177e4SLinus Torvalds hdsp->control_register |= ie; 1267*1da177e4SLinus Torvalds } 1268*1da177e4SLinus Torvalds } else { 1269*1da177e4SLinus Torvalds hdsp->control_register &= ~ie; 1270*1da177e4SLinus Torvalds tasklet_kill(&hdsp->midi_tasklet); 1271*1da177e4SLinus Torvalds } 1272*1da177e4SLinus Torvalds 1273*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 1274*1da177e4SLinus Torvalds spin_unlock_irqrestore (&hdsp->lock, flags); 1275*1da177e4SLinus Torvalds } 1276*1da177e4SLinus Torvalds 1277*1da177e4SLinus Torvalds static void snd_hdsp_midi_output_timer(unsigned long data) 1278*1da177e4SLinus Torvalds { 1279*1da177e4SLinus Torvalds hdsp_midi_t *hmidi = (hdsp_midi_t *) data; 1280*1da177e4SLinus Torvalds unsigned long flags; 1281*1da177e4SLinus Torvalds 1282*1da177e4SLinus Torvalds snd_hdsp_midi_output_write(hmidi); 1283*1da177e4SLinus Torvalds spin_lock_irqsave (&hmidi->lock, flags); 1284*1da177e4SLinus Torvalds 1285*1da177e4SLinus Torvalds /* this does not bump hmidi->istimer, because the 1286*1da177e4SLinus Torvalds kernel automatically removed the timer when it 1287*1da177e4SLinus Torvalds expired, and we are now adding it back, thus 1288*1da177e4SLinus Torvalds leaving istimer wherever it was set before. 1289*1da177e4SLinus Torvalds */ 1290*1da177e4SLinus Torvalds 1291*1da177e4SLinus Torvalds if (hmidi->istimer) { 1292*1da177e4SLinus Torvalds hmidi->timer.expires = 1 + jiffies; 1293*1da177e4SLinus Torvalds add_timer(&hmidi->timer); 1294*1da177e4SLinus Torvalds } 1295*1da177e4SLinus Torvalds 1296*1da177e4SLinus Torvalds spin_unlock_irqrestore (&hmidi->lock, flags); 1297*1da177e4SLinus Torvalds } 1298*1da177e4SLinus Torvalds 1299*1da177e4SLinus Torvalds static void snd_hdsp_midi_output_trigger(snd_rawmidi_substream_t * substream, int up) 1300*1da177e4SLinus Torvalds { 1301*1da177e4SLinus Torvalds hdsp_midi_t *hmidi; 1302*1da177e4SLinus Torvalds unsigned long flags; 1303*1da177e4SLinus Torvalds 1304*1da177e4SLinus Torvalds hmidi = (hdsp_midi_t *) substream->rmidi->private_data; 1305*1da177e4SLinus Torvalds spin_lock_irqsave (&hmidi->lock, flags); 1306*1da177e4SLinus Torvalds if (up) { 1307*1da177e4SLinus Torvalds if (!hmidi->istimer) { 1308*1da177e4SLinus Torvalds init_timer(&hmidi->timer); 1309*1da177e4SLinus Torvalds hmidi->timer.function = snd_hdsp_midi_output_timer; 1310*1da177e4SLinus Torvalds hmidi->timer.data = (unsigned long) hmidi; 1311*1da177e4SLinus Torvalds hmidi->timer.expires = 1 + jiffies; 1312*1da177e4SLinus Torvalds add_timer(&hmidi->timer); 1313*1da177e4SLinus Torvalds hmidi->istimer++; 1314*1da177e4SLinus Torvalds } 1315*1da177e4SLinus Torvalds } else { 1316*1da177e4SLinus Torvalds if (hmidi->istimer && --hmidi->istimer <= 0) { 1317*1da177e4SLinus Torvalds del_timer (&hmidi->timer); 1318*1da177e4SLinus Torvalds } 1319*1da177e4SLinus Torvalds } 1320*1da177e4SLinus Torvalds spin_unlock_irqrestore (&hmidi->lock, flags); 1321*1da177e4SLinus Torvalds if (up) 1322*1da177e4SLinus Torvalds snd_hdsp_midi_output_write(hmidi); 1323*1da177e4SLinus Torvalds } 1324*1da177e4SLinus Torvalds 1325*1da177e4SLinus Torvalds static int snd_hdsp_midi_input_open(snd_rawmidi_substream_t * substream) 1326*1da177e4SLinus Torvalds { 1327*1da177e4SLinus Torvalds hdsp_midi_t *hmidi; 1328*1da177e4SLinus Torvalds 1329*1da177e4SLinus Torvalds hmidi = (hdsp_midi_t *) substream->rmidi->private_data; 1330*1da177e4SLinus Torvalds spin_lock_irq (&hmidi->lock); 1331*1da177e4SLinus Torvalds snd_hdsp_flush_midi_input (hmidi->hdsp, hmidi->id); 1332*1da177e4SLinus Torvalds hmidi->input = substream; 1333*1da177e4SLinus Torvalds spin_unlock_irq (&hmidi->lock); 1334*1da177e4SLinus Torvalds 1335*1da177e4SLinus Torvalds return 0; 1336*1da177e4SLinus Torvalds } 1337*1da177e4SLinus Torvalds 1338*1da177e4SLinus Torvalds static int snd_hdsp_midi_output_open(snd_rawmidi_substream_t * substream) 1339*1da177e4SLinus Torvalds { 1340*1da177e4SLinus Torvalds hdsp_midi_t *hmidi; 1341*1da177e4SLinus Torvalds 1342*1da177e4SLinus Torvalds hmidi = (hdsp_midi_t *) substream->rmidi->private_data; 1343*1da177e4SLinus Torvalds spin_lock_irq (&hmidi->lock); 1344*1da177e4SLinus Torvalds hmidi->output = substream; 1345*1da177e4SLinus Torvalds spin_unlock_irq (&hmidi->lock); 1346*1da177e4SLinus Torvalds 1347*1da177e4SLinus Torvalds return 0; 1348*1da177e4SLinus Torvalds } 1349*1da177e4SLinus Torvalds 1350*1da177e4SLinus Torvalds static int snd_hdsp_midi_input_close(snd_rawmidi_substream_t * substream) 1351*1da177e4SLinus Torvalds { 1352*1da177e4SLinus Torvalds hdsp_midi_t *hmidi; 1353*1da177e4SLinus Torvalds 1354*1da177e4SLinus Torvalds snd_hdsp_midi_input_trigger (substream, 0); 1355*1da177e4SLinus Torvalds 1356*1da177e4SLinus Torvalds hmidi = (hdsp_midi_t *) substream->rmidi->private_data; 1357*1da177e4SLinus Torvalds spin_lock_irq (&hmidi->lock); 1358*1da177e4SLinus Torvalds hmidi->input = NULL; 1359*1da177e4SLinus Torvalds spin_unlock_irq (&hmidi->lock); 1360*1da177e4SLinus Torvalds 1361*1da177e4SLinus Torvalds return 0; 1362*1da177e4SLinus Torvalds } 1363*1da177e4SLinus Torvalds 1364*1da177e4SLinus Torvalds static int snd_hdsp_midi_output_close(snd_rawmidi_substream_t * substream) 1365*1da177e4SLinus Torvalds { 1366*1da177e4SLinus Torvalds hdsp_midi_t *hmidi; 1367*1da177e4SLinus Torvalds 1368*1da177e4SLinus Torvalds snd_hdsp_midi_output_trigger (substream, 0); 1369*1da177e4SLinus Torvalds 1370*1da177e4SLinus Torvalds hmidi = (hdsp_midi_t *) substream->rmidi->private_data; 1371*1da177e4SLinus Torvalds spin_lock_irq (&hmidi->lock); 1372*1da177e4SLinus Torvalds hmidi->output = NULL; 1373*1da177e4SLinus Torvalds spin_unlock_irq (&hmidi->lock); 1374*1da177e4SLinus Torvalds 1375*1da177e4SLinus Torvalds return 0; 1376*1da177e4SLinus Torvalds } 1377*1da177e4SLinus Torvalds 1378*1da177e4SLinus Torvalds static snd_rawmidi_ops_t snd_hdsp_midi_output = 1379*1da177e4SLinus Torvalds { 1380*1da177e4SLinus Torvalds .open = snd_hdsp_midi_output_open, 1381*1da177e4SLinus Torvalds .close = snd_hdsp_midi_output_close, 1382*1da177e4SLinus Torvalds .trigger = snd_hdsp_midi_output_trigger, 1383*1da177e4SLinus Torvalds }; 1384*1da177e4SLinus Torvalds 1385*1da177e4SLinus Torvalds static snd_rawmidi_ops_t snd_hdsp_midi_input = 1386*1da177e4SLinus Torvalds { 1387*1da177e4SLinus Torvalds .open = snd_hdsp_midi_input_open, 1388*1da177e4SLinus Torvalds .close = snd_hdsp_midi_input_close, 1389*1da177e4SLinus Torvalds .trigger = snd_hdsp_midi_input_trigger, 1390*1da177e4SLinus Torvalds }; 1391*1da177e4SLinus Torvalds 1392*1da177e4SLinus Torvalds static int __devinit snd_hdsp_create_midi (snd_card_t *card, hdsp_t *hdsp, int id) 1393*1da177e4SLinus Torvalds { 1394*1da177e4SLinus Torvalds char buf[32]; 1395*1da177e4SLinus Torvalds 1396*1da177e4SLinus Torvalds hdsp->midi[id].id = id; 1397*1da177e4SLinus Torvalds hdsp->midi[id].rmidi = NULL; 1398*1da177e4SLinus Torvalds hdsp->midi[id].input = NULL; 1399*1da177e4SLinus Torvalds hdsp->midi[id].output = NULL; 1400*1da177e4SLinus Torvalds hdsp->midi[id].hdsp = hdsp; 1401*1da177e4SLinus Torvalds hdsp->midi[id].istimer = 0; 1402*1da177e4SLinus Torvalds hdsp->midi[id].pending = 0; 1403*1da177e4SLinus Torvalds spin_lock_init (&hdsp->midi[id].lock); 1404*1da177e4SLinus Torvalds 1405*1da177e4SLinus Torvalds sprintf (buf, "%s MIDI %d", card->shortname, id+1); 1406*1da177e4SLinus Torvalds if (snd_rawmidi_new (card, buf, id, 1, 1, &hdsp->midi[id].rmidi) < 0) { 1407*1da177e4SLinus Torvalds return -1; 1408*1da177e4SLinus Torvalds } 1409*1da177e4SLinus Torvalds 1410*1da177e4SLinus Torvalds sprintf (hdsp->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1); 1411*1da177e4SLinus Torvalds hdsp->midi[id].rmidi->private_data = &hdsp->midi[id]; 1412*1da177e4SLinus Torvalds 1413*1da177e4SLinus Torvalds snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdsp_midi_output); 1414*1da177e4SLinus Torvalds snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdsp_midi_input); 1415*1da177e4SLinus Torvalds 1416*1da177e4SLinus Torvalds hdsp->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | 1417*1da177e4SLinus Torvalds SNDRV_RAWMIDI_INFO_INPUT | 1418*1da177e4SLinus Torvalds SNDRV_RAWMIDI_INFO_DUPLEX; 1419*1da177e4SLinus Torvalds 1420*1da177e4SLinus Torvalds return 0; 1421*1da177e4SLinus Torvalds } 1422*1da177e4SLinus Torvalds 1423*1da177e4SLinus Torvalds /*----------------------------------------------------------------------------- 1424*1da177e4SLinus Torvalds Control Interface 1425*1da177e4SLinus Torvalds ----------------------------------------------------------------------------*/ 1426*1da177e4SLinus Torvalds 1427*1da177e4SLinus Torvalds static u32 snd_hdsp_convert_from_aes(snd_aes_iec958_t *aes) 1428*1da177e4SLinus Torvalds { 1429*1da177e4SLinus Torvalds u32 val = 0; 1430*1da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? HDSP_SPDIFProfessional : 0; 1431*1da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? HDSP_SPDIFNonAudio : 0; 1432*1da177e4SLinus Torvalds if (val & HDSP_SPDIFProfessional) 1433*1da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0; 1434*1da177e4SLinus Torvalds else 1435*1da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0; 1436*1da177e4SLinus Torvalds return val; 1437*1da177e4SLinus Torvalds } 1438*1da177e4SLinus Torvalds 1439*1da177e4SLinus Torvalds static void snd_hdsp_convert_to_aes(snd_aes_iec958_t *aes, u32 val) 1440*1da177e4SLinus Torvalds { 1441*1da177e4SLinus Torvalds aes->status[0] = ((val & HDSP_SPDIFProfessional) ? IEC958_AES0_PROFESSIONAL : 0) | 1442*1da177e4SLinus Torvalds ((val & HDSP_SPDIFNonAudio) ? IEC958_AES0_NONAUDIO : 0); 1443*1da177e4SLinus Torvalds if (val & HDSP_SPDIFProfessional) 1444*1da177e4SLinus Torvalds aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0; 1445*1da177e4SLinus Torvalds else 1446*1da177e4SLinus Torvalds aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_CON_EMPHASIS_5015 : 0; 1447*1da177e4SLinus Torvalds } 1448*1da177e4SLinus Torvalds 1449*1da177e4SLinus Torvalds static int snd_hdsp_control_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 1450*1da177e4SLinus Torvalds { 1451*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 1452*1da177e4SLinus Torvalds uinfo->count = 1; 1453*1da177e4SLinus Torvalds return 0; 1454*1da177e4SLinus Torvalds } 1455*1da177e4SLinus Torvalds 1456*1da177e4SLinus Torvalds static int snd_hdsp_control_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1457*1da177e4SLinus Torvalds { 1458*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1459*1da177e4SLinus Torvalds 1460*1da177e4SLinus Torvalds snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif); 1461*1da177e4SLinus Torvalds return 0; 1462*1da177e4SLinus Torvalds } 1463*1da177e4SLinus Torvalds 1464*1da177e4SLinus Torvalds static int snd_hdsp_control_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1465*1da177e4SLinus Torvalds { 1466*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1467*1da177e4SLinus Torvalds int change; 1468*1da177e4SLinus Torvalds u32 val; 1469*1da177e4SLinus Torvalds 1470*1da177e4SLinus Torvalds val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958); 1471*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 1472*1da177e4SLinus Torvalds change = val != hdsp->creg_spdif; 1473*1da177e4SLinus Torvalds hdsp->creg_spdif = val; 1474*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 1475*1da177e4SLinus Torvalds return change; 1476*1da177e4SLinus Torvalds } 1477*1da177e4SLinus Torvalds 1478*1da177e4SLinus Torvalds static int snd_hdsp_control_spdif_stream_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 1479*1da177e4SLinus Torvalds { 1480*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 1481*1da177e4SLinus Torvalds uinfo->count = 1; 1482*1da177e4SLinus Torvalds return 0; 1483*1da177e4SLinus Torvalds } 1484*1da177e4SLinus Torvalds 1485*1da177e4SLinus Torvalds static int snd_hdsp_control_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1486*1da177e4SLinus Torvalds { 1487*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1488*1da177e4SLinus Torvalds 1489*1da177e4SLinus Torvalds snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream); 1490*1da177e4SLinus Torvalds return 0; 1491*1da177e4SLinus Torvalds } 1492*1da177e4SLinus Torvalds 1493*1da177e4SLinus Torvalds static int snd_hdsp_control_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1494*1da177e4SLinus Torvalds { 1495*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1496*1da177e4SLinus Torvalds int change; 1497*1da177e4SLinus Torvalds u32 val; 1498*1da177e4SLinus Torvalds 1499*1da177e4SLinus Torvalds val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958); 1500*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 1501*1da177e4SLinus Torvalds change = val != hdsp->creg_spdif_stream; 1502*1da177e4SLinus Torvalds hdsp->creg_spdif_stream = val; 1503*1da177e4SLinus Torvalds hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis); 1504*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= val); 1505*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 1506*1da177e4SLinus Torvalds return change; 1507*1da177e4SLinus Torvalds } 1508*1da177e4SLinus Torvalds 1509*1da177e4SLinus Torvalds static int snd_hdsp_control_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 1510*1da177e4SLinus Torvalds { 1511*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 1512*1da177e4SLinus Torvalds uinfo->count = 1; 1513*1da177e4SLinus Torvalds return 0; 1514*1da177e4SLinus Torvalds } 1515*1da177e4SLinus Torvalds 1516*1da177e4SLinus Torvalds static int snd_hdsp_control_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1517*1da177e4SLinus Torvalds { 1518*1da177e4SLinus Torvalds ucontrol->value.iec958.status[0] = kcontrol->private_value; 1519*1da177e4SLinus Torvalds return 0; 1520*1da177e4SLinus Torvalds } 1521*1da177e4SLinus Torvalds 1522*1da177e4SLinus Torvalds #define HDSP_SPDIF_IN(xname, xindex) \ 1523*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_PCM, \ 1524*1da177e4SLinus Torvalds .name = xname, \ 1525*1da177e4SLinus Torvalds .index = xindex, \ 1526*1da177e4SLinus Torvalds .info = snd_hdsp_info_spdif_in, \ 1527*1da177e4SLinus Torvalds .get = snd_hdsp_get_spdif_in, \ 1528*1da177e4SLinus Torvalds .put = snd_hdsp_put_spdif_in } 1529*1da177e4SLinus Torvalds 1530*1da177e4SLinus Torvalds static unsigned int hdsp_spdif_in(hdsp_t *hdsp) 1531*1da177e4SLinus Torvalds { 1532*1da177e4SLinus Torvalds return hdsp_decode_spdif_in(hdsp->control_register & HDSP_SPDIFInputMask); 1533*1da177e4SLinus Torvalds } 1534*1da177e4SLinus Torvalds 1535*1da177e4SLinus Torvalds static int hdsp_set_spdif_input(hdsp_t *hdsp, int in) 1536*1da177e4SLinus Torvalds { 1537*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_SPDIFInputMask; 1538*1da177e4SLinus Torvalds hdsp->control_register |= hdsp_encode_spdif_in(in); 1539*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 1540*1da177e4SLinus Torvalds return 0; 1541*1da177e4SLinus Torvalds } 1542*1da177e4SLinus Torvalds 1543*1da177e4SLinus Torvalds static int snd_hdsp_info_spdif_in(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 1544*1da177e4SLinus Torvalds { 1545*1da177e4SLinus Torvalds static char *texts[4] = {"Optical", "Coaxial", "Internal", "AES"}; 1546*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1547*1da177e4SLinus Torvalds 1548*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1549*1da177e4SLinus Torvalds uinfo->count = 1; 1550*1da177e4SLinus Torvalds uinfo->value.enumerated.items = ((hdsp->io_type == H9632) ? 4 : 3); 1551*1da177e4SLinus Torvalds if (uinfo->value.enumerated.item > ((hdsp->io_type == H9632) ? 3 : 2)) 1552*1da177e4SLinus Torvalds uinfo->value.enumerated.item = ((hdsp->io_type == H9632) ? 3 : 2); 1553*1da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 1554*1da177e4SLinus Torvalds return 0; 1555*1da177e4SLinus Torvalds } 1556*1da177e4SLinus Torvalds 1557*1da177e4SLinus Torvalds static int snd_hdsp_get_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1558*1da177e4SLinus Torvalds { 1559*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1560*1da177e4SLinus Torvalds 1561*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp); 1562*1da177e4SLinus Torvalds return 0; 1563*1da177e4SLinus Torvalds } 1564*1da177e4SLinus Torvalds 1565*1da177e4SLinus Torvalds static int snd_hdsp_put_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1566*1da177e4SLinus Torvalds { 1567*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1568*1da177e4SLinus Torvalds int change; 1569*1da177e4SLinus Torvalds unsigned int val; 1570*1da177e4SLinus Torvalds 1571*1da177e4SLinus Torvalds if (!snd_hdsp_use_is_exclusive(hdsp)) 1572*1da177e4SLinus Torvalds return -EBUSY; 1573*1da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3); 1574*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 1575*1da177e4SLinus Torvalds change = val != hdsp_spdif_in(hdsp); 1576*1da177e4SLinus Torvalds if (change) 1577*1da177e4SLinus Torvalds hdsp_set_spdif_input(hdsp, val); 1578*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 1579*1da177e4SLinus Torvalds return change; 1580*1da177e4SLinus Torvalds } 1581*1da177e4SLinus Torvalds 1582*1da177e4SLinus Torvalds #define HDSP_SPDIF_OUT(xname, xindex) \ 1583*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, .name = xname, .index = xindex, \ 1584*1da177e4SLinus Torvalds .info = snd_hdsp_info_spdif_bits, \ 1585*1da177e4SLinus Torvalds .get = snd_hdsp_get_spdif_out, .put = snd_hdsp_put_spdif_out } 1586*1da177e4SLinus Torvalds 1587*1da177e4SLinus Torvalds static int hdsp_spdif_out(hdsp_t *hdsp) 1588*1da177e4SLinus Torvalds { 1589*1da177e4SLinus Torvalds return (hdsp->control_register & HDSP_SPDIFOpticalOut) ? 1 : 0; 1590*1da177e4SLinus Torvalds } 1591*1da177e4SLinus Torvalds 1592*1da177e4SLinus Torvalds static int hdsp_set_spdif_output(hdsp_t *hdsp, int out) 1593*1da177e4SLinus Torvalds { 1594*1da177e4SLinus Torvalds if (out) { 1595*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_SPDIFOpticalOut; 1596*1da177e4SLinus Torvalds } else { 1597*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_SPDIFOpticalOut; 1598*1da177e4SLinus Torvalds } 1599*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 1600*1da177e4SLinus Torvalds return 0; 1601*1da177e4SLinus Torvalds } 1602*1da177e4SLinus Torvalds 1603*1da177e4SLinus Torvalds static int snd_hdsp_info_spdif_bits(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 1604*1da177e4SLinus Torvalds { 1605*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1606*1da177e4SLinus Torvalds uinfo->count = 1; 1607*1da177e4SLinus Torvalds uinfo->value.integer.min = 0; 1608*1da177e4SLinus Torvalds uinfo->value.integer.max = 1; 1609*1da177e4SLinus Torvalds return 0; 1610*1da177e4SLinus Torvalds } 1611*1da177e4SLinus Torvalds 1612*1da177e4SLinus Torvalds static int snd_hdsp_get_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1613*1da177e4SLinus Torvalds { 1614*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1615*1da177e4SLinus Torvalds 1616*1da177e4SLinus Torvalds ucontrol->value.integer.value[0] = hdsp_spdif_out(hdsp); 1617*1da177e4SLinus Torvalds return 0; 1618*1da177e4SLinus Torvalds } 1619*1da177e4SLinus Torvalds 1620*1da177e4SLinus Torvalds static int snd_hdsp_put_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1621*1da177e4SLinus Torvalds { 1622*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1623*1da177e4SLinus Torvalds int change; 1624*1da177e4SLinus Torvalds unsigned int val; 1625*1da177e4SLinus Torvalds 1626*1da177e4SLinus Torvalds if (!snd_hdsp_use_is_exclusive(hdsp)) 1627*1da177e4SLinus Torvalds return -EBUSY; 1628*1da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] & 1; 1629*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 1630*1da177e4SLinus Torvalds change = (int)val != hdsp_spdif_out(hdsp); 1631*1da177e4SLinus Torvalds hdsp_set_spdif_output(hdsp, val); 1632*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 1633*1da177e4SLinus Torvalds return change; 1634*1da177e4SLinus Torvalds } 1635*1da177e4SLinus Torvalds 1636*1da177e4SLinus Torvalds #define HDSP_SPDIF_PROFESSIONAL(xname, xindex) \ 1637*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, .name = xname, .index = xindex, \ 1638*1da177e4SLinus Torvalds .info = snd_hdsp_info_spdif_bits, \ 1639*1da177e4SLinus Torvalds .get = snd_hdsp_get_spdif_professional, .put = snd_hdsp_put_spdif_professional } 1640*1da177e4SLinus Torvalds 1641*1da177e4SLinus Torvalds static int hdsp_spdif_professional(hdsp_t *hdsp) 1642*1da177e4SLinus Torvalds { 1643*1da177e4SLinus Torvalds return (hdsp->control_register & HDSP_SPDIFProfessional) ? 1 : 0; 1644*1da177e4SLinus Torvalds } 1645*1da177e4SLinus Torvalds 1646*1da177e4SLinus Torvalds static int hdsp_set_spdif_professional(hdsp_t *hdsp, int val) 1647*1da177e4SLinus Torvalds { 1648*1da177e4SLinus Torvalds if (val) { 1649*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_SPDIFProfessional; 1650*1da177e4SLinus Torvalds } else { 1651*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_SPDIFProfessional; 1652*1da177e4SLinus Torvalds } 1653*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 1654*1da177e4SLinus Torvalds return 0; 1655*1da177e4SLinus Torvalds } 1656*1da177e4SLinus Torvalds 1657*1da177e4SLinus Torvalds static int snd_hdsp_get_spdif_professional(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1658*1da177e4SLinus Torvalds { 1659*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1660*1da177e4SLinus Torvalds 1661*1da177e4SLinus Torvalds ucontrol->value.integer.value[0] = hdsp_spdif_professional(hdsp); 1662*1da177e4SLinus Torvalds return 0; 1663*1da177e4SLinus Torvalds } 1664*1da177e4SLinus Torvalds 1665*1da177e4SLinus Torvalds static int snd_hdsp_put_spdif_professional(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1666*1da177e4SLinus Torvalds { 1667*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1668*1da177e4SLinus Torvalds int change; 1669*1da177e4SLinus Torvalds unsigned int val; 1670*1da177e4SLinus Torvalds 1671*1da177e4SLinus Torvalds if (!snd_hdsp_use_is_exclusive(hdsp)) 1672*1da177e4SLinus Torvalds return -EBUSY; 1673*1da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] & 1; 1674*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 1675*1da177e4SLinus Torvalds change = (int)val != hdsp_spdif_professional(hdsp); 1676*1da177e4SLinus Torvalds hdsp_set_spdif_professional(hdsp, val); 1677*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 1678*1da177e4SLinus Torvalds return change; 1679*1da177e4SLinus Torvalds } 1680*1da177e4SLinus Torvalds 1681*1da177e4SLinus Torvalds #define HDSP_SPDIF_EMPHASIS(xname, xindex) \ 1682*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, .name = xname, .index = xindex, \ 1683*1da177e4SLinus Torvalds .info = snd_hdsp_info_spdif_bits, \ 1684*1da177e4SLinus Torvalds .get = snd_hdsp_get_spdif_emphasis, .put = snd_hdsp_put_spdif_emphasis } 1685*1da177e4SLinus Torvalds 1686*1da177e4SLinus Torvalds static int hdsp_spdif_emphasis(hdsp_t *hdsp) 1687*1da177e4SLinus Torvalds { 1688*1da177e4SLinus Torvalds return (hdsp->control_register & HDSP_SPDIFEmphasis) ? 1 : 0; 1689*1da177e4SLinus Torvalds } 1690*1da177e4SLinus Torvalds 1691*1da177e4SLinus Torvalds static int hdsp_set_spdif_emphasis(hdsp_t *hdsp, int val) 1692*1da177e4SLinus Torvalds { 1693*1da177e4SLinus Torvalds if (val) { 1694*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_SPDIFEmphasis; 1695*1da177e4SLinus Torvalds } else { 1696*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_SPDIFEmphasis; 1697*1da177e4SLinus Torvalds } 1698*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 1699*1da177e4SLinus Torvalds return 0; 1700*1da177e4SLinus Torvalds } 1701*1da177e4SLinus Torvalds 1702*1da177e4SLinus Torvalds static int snd_hdsp_get_spdif_emphasis(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1703*1da177e4SLinus Torvalds { 1704*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1705*1da177e4SLinus Torvalds 1706*1da177e4SLinus Torvalds ucontrol->value.integer.value[0] = hdsp_spdif_emphasis(hdsp); 1707*1da177e4SLinus Torvalds return 0; 1708*1da177e4SLinus Torvalds } 1709*1da177e4SLinus Torvalds 1710*1da177e4SLinus Torvalds static int snd_hdsp_put_spdif_emphasis(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1711*1da177e4SLinus Torvalds { 1712*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1713*1da177e4SLinus Torvalds int change; 1714*1da177e4SLinus Torvalds unsigned int val; 1715*1da177e4SLinus Torvalds 1716*1da177e4SLinus Torvalds if (!snd_hdsp_use_is_exclusive(hdsp)) 1717*1da177e4SLinus Torvalds return -EBUSY; 1718*1da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] & 1; 1719*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 1720*1da177e4SLinus Torvalds change = (int)val != hdsp_spdif_emphasis(hdsp); 1721*1da177e4SLinus Torvalds hdsp_set_spdif_emphasis(hdsp, val); 1722*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 1723*1da177e4SLinus Torvalds return change; 1724*1da177e4SLinus Torvalds } 1725*1da177e4SLinus Torvalds 1726*1da177e4SLinus Torvalds #define HDSP_SPDIF_NON_AUDIO(xname, xindex) \ 1727*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, .name = xname, .index = xindex, \ 1728*1da177e4SLinus Torvalds .info = snd_hdsp_info_spdif_bits, \ 1729*1da177e4SLinus Torvalds .get = snd_hdsp_get_spdif_nonaudio, .put = snd_hdsp_put_spdif_nonaudio } 1730*1da177e4SLinus Torvalds 1731*1da177e4SLinus Torvalds static int hdsp_spdif_nonaudio(hdsp_t *hdsp) 1732*1da177e4SLinus Torvalds { 1733*1da177e4SLinus Torvalds return (hdsp->control_register & HDSP_SPDIFNonAudio) ? 1 : 0; 1734*1da177e4SLinus Torvalds } 1735*1da177e4SLinus Torvalds 1736*1da177e4SLinus Torvalds static int hdsp_set_spdif_nonaudio(hdsp_t *hdsp, int val) 1737*1da177e4SLinus Torvalds { 1738*1da177e4SLinus Torvalds if (val) { 1739*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_SPDIFNonAudio; 1740*1da177e4SLinus Torvalds } else { 1741*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_SPDIFNonAudio; 1742*1da177e4SLinus Torvalds } 1743*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 1744*1da177e4SLinus Torvalds return 0; 1745*1da177e4SLinus Torvalds } 1746*1da177e4SLinus Torvalds 1747*1da177e4SLinus Torvalds static int snd_hdsp_get_spdif_nonaudio(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1748*1da177e4SLinus Torvalds { 1749*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1750*1da177e4SLinus Torvalds 1751*1da177e4SLinus Torvalds ucontrol->value.integer.value[0] = hdsp_spdif_nonaudio(hdsp); 1752*1da177e4SLinus Torvalds return 0; 1753*1da177e4SLinus Torvalds } 1754*1da177e4SLinus Torvalds 1755*1da177e4SLinus Torvalds static int snd_hdsp_put_spdif_nonaudio(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1756*1da177e4SLinus Torvalds { 1757*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1758*1da177e4SLinus Torvalds int change; 1759*1da177e4SLinus Torvalds unsigned int val; 1760*1da177e4SLinus Torvalds 1761*1da177e4SLinus Torvalds if (!snd_hdsp_use_is_exclusive(hdsp)) 1762*1da177e4SLinus Torvalds return -EBUSY; 1763*1da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] & 1; 1764*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 1765*1da177e4SLinus Torvalds change = (int)val != hdsp_spdif_nonaudio(hdsp); 1766*1da177e4SLinus Torvalds hdsp_set_spdif_nonaudio(hdsp, val); 1767*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 1768*1da177e4SLinus Torvalds return change; 1769*1da177e4SLinus Torvalds } 1770*1da177e4SLinus Torvalds 1771*1da177e4SLinus Torvalds #define HDSP_SPDIF_SAMPLE_RATE(xname, xindex) \ 1772*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 1773*1da177e4SLinus Torvalds .name = xname, \ 1774*1da177e4SLinus Torvalds .index = xindex, \ 1775*1da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ, \ 1776*1da177e4SLinus Torvalds .info = snd_hdsp_info_spdif_sample_rate, \ 1777*1da177e4SLinus Torvalds .get = snd_hdsp_get_spdif_sample_rate \ 1778*1da177e4SLinus Torvalds } 1779*1da177e4SLinus Torvalds 1780*1da177e4SLinus Torvalds static int snd_hdsp_info_spdif_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 1781*1da177e4SLinus Torvalds { 1782*1da177e4SLinus Torvalds static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"}; 1783*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1784*1da177e4SLinus Torvalds 1785*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1786*1da177e4SLinus Torvalds uinfo->count = 1; 1787*1da177e4SLinus Torvalds uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7; 1788*1da177e4SLinus Torvalds if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 1789*1da177e4SLinus Torvalds uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 1790*1da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 1791*1da177e4SLinus Torvalds return 0; 1792*1da177e4SLinus Torvalds } 1793*1da177e4SLinus Torvalds 1794*1da177e4SLinus Torvalds static int snd_hdsp_get_spdif_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1795*1da177e4SLinus Torvalds { 1796*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1797*1da177e4SLinus Torvalds 1798*1da177e4SLinus Torvalds switch (hdsp_spdif_sample_rate(hdsp)) { 1799*1da177e4SLinus Torvalds case 32000: 1800*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 0; 1801*1da177e4SLinus Torvalds break; 1802*1da177e4SLinus Torvalds case 44100: 1803*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 1; 1804*1da177e4SLinus Torvalds break; 1805*1da177e4SLinus Torvalds case 48000: 1806*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 2; 1807*1da177e4SLinus Torvalds break; 1808*1da177e4SLinus Torvalds case 64000: 1809*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 3; 1810*1da177e4SLinus Torvalds break; 1811*1da177e4SLinus Torvalds case 88200: 1812*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 4; 1813*1da177e4SLinus Torvalds break; 1814*1da177e4SLinus Torvalds case 96000: 1815*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 5; 1816*1da177e4SLinus Torvalds break; 1817*1da177e4SLinus Torvalds case 128000: 1818*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 7; 1819*1da177e4SLinus Torvalds break; 1820*1da177e4SLinus Torvalds case 176400: 1821*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 8; 1822*1da177e4SLinus Torvalds break; 1823*1da177e4SLinus Torvalds case 192000: 1824*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 9; 1825*1da177e4SLinus Torvalds break; 1826*1da177e4SLinus Torvalds default: 1827*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 6; 1828*1da177e4SLinus Torvalds } 1829*1da177e4SLinus Torvalds return 0; 1830*1da177e4SLinus Torvalds } 1831*1da177e4SLinus Torvalds 1832*1da177e4SLinus Torvalds #define HDSP_SYSTEM_SAMPLE_RATE(xname, xindex) \ 1833*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 1834*1da177e4SLinus Torvalds .name = xname, \ 1835*1da177e4SLinus Torvalds .index = xindex, \ 1836*1da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ, \ 1837*1da177e4SLinus Torvalds .info = snd_hdsp_info_system_sample_rate, \ 1838*1da177e4SLinus Torvalds .get = snd_hdsp_get_system_sample_rate \ 1839*1da177e4SLinus Torvalds } 1840*1da177e4SLinus Torvalds 1841*1da177e4SLinus Torvalds static int snd_hdsp_info_system_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 1842*1da177e4SLinus Torvalds { 1843*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1844*1da177e4SLinus Torvalds uinfo->count = 1; 1845*1da177e4SLinus Torvalds return 0; 1846*1da177e4SLinus Torvalds } 1847*1da177e4SLinus Torvalds 1848*1da177e4SLinus Torvalds static int snd_hdsp_get_system_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1849*1da177e4SLinus Torvalds { 1850*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1851*1da177e4SLinus Torvalds 1852*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate; 1853*1da177e4SLinus Torvalds return 0; 1854*1da177e4SLinus Torvalds } 1855*1da177e4SLinus Torvalds 1856*1da177e4SLinus Torvalds #define HDSP_AUTOSYNC_SAMPLE_RATE(xname, xindex) \ 1857*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_PCM, \ 1858*1da177e4SLinus Torvalds .name = xname, \ 1859*1da177e4SLinus Torvalds .index = xindex, \ 1860*1da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ, \ 1861*1da177e4SLinus Torvalds .info = snd_hdsp_info_autosync_sample_rate, \ 1862*1da177e4SLinus Torvalds .get = snd_hdsp_get_autosync_sample_rate \ 1863*1da177e4SLinus Torvalds } 1864*1da177e4SLinus Torvalds 1865*1da177e4SLinus Torvalds static int snd_hdsp_info_autosync_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 1866*1da177e4SLinus Torvalds { 1867*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1868*1da177e4SLinus Torvalds static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"}; 1869*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1870*1da177e4SLinus Torvalds uinfo->count = 1; 1871*1da177e4SLinus Torvalds uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7 ; 1872*1da177e4SLinus Torvalds if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 1873*1da177e4SLinus Torvalds uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 1874*1da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 1875*1da177e4SLinus Torvalds return 0; 1876*1da177e4SLinus Torvalds } 1877*1da177e4SLinus Torvalds 1878*1da177e4SLinus Torvalds static int snd_hdsp_get_autosync_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1879*1da177e4SLinus Torvalds { 1880*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1881*1da177e4SLinus Torvalds 1882*1da177e4SLinus Torvalds switch (hdsp_external_sample_rate(hdsp)) { 1883*1da177e4SLinus Torvalds case 32000: 1884*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 0; 1885*1da177e4SLinus Torvalds break; 1886*1da177e4SLinus Torvalds case 44100: 1887*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 1; 1888*1da177e4SLinus Torvalds break; 1889*1da177e4SLinus Torvalds case 48000: 1890*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 2; 1891*1da177e4SLinus Torvalds break; 1892*1da177e4SLinus Torvalds case 64000: 1893*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 3; 1894*1da177e4SLinus Torvalds break; 1895*1da177e4SLinus Torvalds case 88200: 1896*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 4; 1897*1da177e4SLinus Torvalds break; 1898*1da177e4SLinus Torvalds case 96000: 1899*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 5; 1900*1da177e4SLinus Torvalds break; 1901*1da177e4SLinus Torvalds case 128000: 1902*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 7; 1903*1da177e4SLinus Torvalds break; 1904*1da177e4SLinus Torvalds case 176400: 1905*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 8; 1906*1da177e4SLinus Torvalds break; 1907*1da177e4SLinus Torvalds case 192000: 1908*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 9; 1909*1da177e4SLinus Torvalds break; 1910*1da177e4SLinus Torvalds default: 1911*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 6; 1912*1da177e4SLinus Torvalds } 1913*1da177e4SLinus Torvalds return 0; 1914*1da177e4SLinus Torvalds } 1915*1da177e4SLinus Torvalds 1916*1da177e4SLinus Torvalds #define HDSP_SYSTEM_CLOCK_MODE(xname, xindex) \ 1917*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 1918*1da177e4SLinus Torvalds .name = xname, \ 1919*1da177e4SLinus Torvalds .index = xindex, \ 1920*1da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ, \ 1921*1da177e4SLinus Torvalds .info = snd_hdsp_info_system_clock_mode, \ 1922*1da177e4SLinus Torvalds .get = snd_hdsp_get_system_clock_mode \ 1923*1da177e4SLinus Torvalds } 1924*1da177e4SLinus Torvalds 1925*1da177e4SLinus Torvalds static int hdsp_system_clock_mode(hdsp_t *hdsp) 1926*1da177e4SLinus Torvalds { 1927*1da177e4SLinus Torvalds if (hdsp->control_register & HDSP_ClockModeMaster) { 1928*1da177e4SLinus Torvalds return 0; 1929*1da177e4SLinus Torvalds } else if (hdsp_external_sample_rate(hdsp) != hdsp->system_sample_rate) { 1930*1da177e4SLinus Torvalds return 0; 1931*1da177e4SLinus Torvalds } 1932*1da177e4SLinus Torvalds return 1; 1933*1da177e4SLinus Torvalds } 1934*1da177e4SLinus Torvalds 1935*1da177e4SLinus Torvalds static int snd_hdsp_info_system_clock_mode(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 1936*1da177e4SLinus Torvalds { 1937*1da177e4SLinus Torvalds static char *texts[] = {"Master", "Slave" }; 1938*1da177e4SLinus Torvalds 1939*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1940*1da177e4SLinus Torvalds uinfo->count = 1; 1941*1da177e4SLinus Torvalds uinfo->value.enumerated.items = 2; 1942*1da177e4SLinus Torvalds if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 1943*1da177e4SLinus Torvalds uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 1944*1da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 1945*1da177e4SLinus Torvalds return 0; 1946*1da177e4SLinus Torvalds } 1947*1da177e4SLinus Torvalds 1948*1da177e4SLinus Torvalds static int snd_hdsp_get_system_clock_mode(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 1949*1da177e4SLinus Torvalds { 1950*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 1951*1da177e4SLinus Torvalds 1952*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp); 1953*1da177e4SLinus Torvalds return 0; 1954*1da177e4SLinus Torvalds } 1955*1da177e4SLinus Torvalds 1956*1da177e4SLinus Torvalds #define HDSP_CLOCK_SOURCE(xname, xindex) \ 1957*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_PCM, \ 1958*1da177e4SLinus Torvalds .name = xname, \ 1959*1da177e4SLinus Torvalds .index = xindex, \ 1960*1da177e4SLinus Torvalds .info = snd_hdsp_info_clock_source, \ 1961*1da177e4SLinus Torvalds .get = snd_hdsp_get_clock_source, \ 1962*1da177e4SLinus Torvalds .put = snd_hdsp_put_clock_source \ 1963*1da177e4SLinus Torvalds } 1964*1da177e4SLinus Torvalds 1965*1da177e4SLinus Torvalds static int hdsp_clock_source(hdsp_t *hdsp) 1966*1da177e4SLinus Torvalds { 1967*1da177e4SLinus Torvalds if (hdsp->control_register & HDSP_ClockModeMaster) { 1968*1da177e4SLinus Torvalds switch (hdsp->system_sample_rate) { 1969*1da177e4SLinus Torvalds case 32000: 1970*1da177e4SLinus Torvalds return 1; 1971*1da177e4SLinus Torvalds case 44100: 1972*1da177e4SLinus Torvalds return 2; 1973*1da177e4SLinus Torvalds case 48000: 1974*1da177e4SLinus Torvalds return 3; 1975*1da177e4SLinus Torvalds case 64000: 1976*1da177e4SLinus Torvalds return 4; 1977*1da177e4SLinus Torvalds case 88200: 1978*1da177e4SLinus Torvalds return 5; 1979*1da177e4SLinus Torvalds case 96000: 1980*1da177e4SLinus Torvalds return 6; 1981*1da177e4SLinus Torvalds case 128000: 1982*1da177e4SLinus Torvalds return 7; 1983*1da177e4SLinus Torvalds case 176400: 1984*1da177e4SLinus Torvalds return 8; 1985*1da177e4SLinus Torvalds case 192000: 1986*1da177e4SLinus Torvalds return 9; 1987*1da177e4SLinus Torvalds default: 1988*1da177e4SLinus Torvalds return 3; 1989*1da177e4SLinus Torvalds } 1990*1da177e4SLinus Torvalds } else { 1991*1da177e4SLinus Torvalds return 0; 1992*1da177e4SLinus Torvalds } 1993*1da177e4SLinus Torvalds } 1994*1da177e4SLinus Torvalds 1995*1da177e4SLinus Torvalds static int hdsp_set_clock_source(hdsp_t *hdsp, int mode) 1996*1da177e4SLinus Torvalds { 1997*1da177e4SLinus Torvalds int rate; 1998*1da177e4SLinus Torvalds switch (mode) { 1999*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_AUTOSYNC: 2000*1da177e4SLinus Torvalds if (hdsp_external_sample_rate(hdsp) != 0) { 2001*1da177e4SLinus Torvalds if (!hdsp_set_rate(hdsp, hdsp_external_sample_rate(hdsp), 1)) { 2002*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_ClockModeMaster; 2003*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 2004*1da177e4SLinus Torvalds return 0; 2005*1da177e4SLinus Torvalds } 2006*1da177e4SLinus Torvalds } 2007*1da177e4SLinus Torvalds return -1; 2008*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ: 2009*1da177e4SLinus Torvalds rate = 32000; 2010*1da177e4SLinus Torvalds break; 2011*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ: 2012*1da177e4SLinus Torvalds rate = 44100; 2013*1da177e4SLinus Torvalds break; 2014*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ: 2015*1da177e4SLinus Torvalds rate = 48000; 2016*1da177e4SLinus Torvalds break; 2017*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ: 2018*1da177e4SLinus Torvalds rate = 64000; 2019*1da177e4SLinus Torvalds break; 2020*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ: 2021*1da177e4SLinus Torvalds rate = 88200; 2022*1da177e4SLinus Torvalds break; 2023*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ: 2024*1da177e4SLinus Torvalds rate = 96000; 2025*1da177e4SLinus Torvalds break; 2026*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ: 2027*1da177e4SLinus Torvalds rate = 128000; 2028*1da177e4SLinus Torvalds break; 2029*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ: 2030*1da177e4SLinus Torvalds rate = 176400; 2031*1da177e4SLinus Torvalds break; 2032*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ: 2033*1da177e4SLinus Torvalds rate = 192000; 2034*1da177e4SLinus Torvalds break; 2035*1da177e4SLinus Torvalds default: 2036*1da177e4SLinus Torvalds rate = 48000; 2037*1da177e4SLinus Torvalds } 2038*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_ClockModeMaster; 2039*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 2040*1da177e4SLinus Torvalds hdsp_set_rate(hdsp, rate, 1); 2041*1da177e4SLinus Torvalds return 0; 2042*1da177e4SLinus Torvalds } 2043*1da177e4SLinus Torvalds 2044*1da177e4SLinus Torvalds static int snd_hdsp_info_clock_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 2045*1da177e4SLinus Torvalds { 2046*1da177e4SLinus Torvalds static char *texts[] = {"AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz", "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz", "Internal 96.0 kHz", "Internal 128 kHz", "Internal 176.4 kHz", "Internal 192.0 KHz" }; 2047*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2048*1da177e4SLinus Torvalds 2049*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2050*1da177e4SLinus Torvalds uinfo->count = 1; 2051*1da177e4SLinus Torvalds if (hdsp->io_type == H9632) 2052*1da177e4SLinus Torvalds uinfo->value.enumerated.items = 10; 2053*1da177e4SLinus Torvalds else 2054*1da177e4SLinus Torvalds uinfo->value.enumerated.items = 7; 2055*1da177e4SLinus Torvalds if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 2056*1da177e4SLinus Torvalds uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 2057*1da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 2058*1da177e4SLinus Torvalds return 0; 2059*1da177e4SLinus Torvalds } 2060*1da177e4SLinus Torvalds 2061*1da177e4SLinus Torvalds static int snd_hdsp_get_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2062*1da177e4SLinus Torvalds { 2063*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2064*1da177e4SLinus Torvalds 2065*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp); 2066*1da177e4SLinus Torvalds return 0; 2067*1da177e4SLinus Torvalds } 2068*1da177e4SLinus Torvalds 2069*1da177e4SLinus Torvalds static int snd_hdsp_put_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2070*1da177e4SLinus Torvalds { 2071*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2072*1da177e4SLinus Torvalds int change; 2073*1da177e4SLinus Torvalds int val; 2074*1da177e4SLinus Torvalds 2075*1da177e4SLinus Torvalds if (!snd_hdsp_use_is_exclusive(hdsp)) 2076*1da177e4SLinus Torvalds return -EBUSY; 2077*1da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0]; 2078*1da177e4SLinus Torvalds if (val < 0) val = 0; 2079*1da177e4SLinus Torvalds if (hdsp->io_type == H9632) { 2080*1da177e4SLinus Torvalds if (val > 9) val = 9; 2081*1da177e4SLinus Torvalds } else { 2082*1da177e4SLinus Torvalds if (val > 6) val = 6; 2083*1da177e4SLinus Torvalds } 2084*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 2085*1da177e4SLinus Torvalds if (val != hdsp_clock_source(hdsp)) { 2086*1da177e4SLinus Torvalds change = (hdsp_set_clock_source(hdsp, val) == 0) ? 1 : 0; 2087*1da177e4SLinus Torvalds } else { 2088*1da177e4SLinus Torvalds change = 0; 2089*1da177e4SLinus Torvalds } 2090*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 2091*1da177e4SLinus Torvalds return change; 2092*1da177e4SLinus Torvalds } 2093*1da177e4SLinus Torvalds 2094*1da177e4SLinus Torvalds #define HDSP_DA_GAIN(xname, xindex) \ 2095*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 2096*1da177e4SLinus Torvalds .name = xname, \ 2097*1da177e4SLinus Torvalds .index = xindex, \ 2098*1da177e4SLinus Torvalds .info = snd_hdsp_info_da_gain, \ 2099*1da177e4SLinus Torvalds .get = snd_hdsp_get_da_gain, \ 2100*1da177e4SLinus Torvalds .put = snd_hdsp_put_da_gain \ 2101*1da177e4SLinus Torvalds } 2102*1da177e4SLinus Torvalds 2103*1da177e4SLinus Torvalds static int hdsp_da_gain(hdsp_t *hdsp) 2104*1da177e4SLinus Torvalds { 2105*1da177e4SLinus Torvalds switch (hdsp->control_register & HDSP_DAGainMask) { 2106*1da177e4SLinus Torvalds case HDSP_DAGainHighGain: 2107*1da177e4SLinus Torvalds return 0; 2108*1da177e4SLinus Torvalds case HDSP_DAGainPlus4dBu: 2109*1da177e4SLinus Torvalds return 1; 2110*1da177e4SLinus Torvalds case HDSP_DAGainMinus10dBV: 2111*1da177e4SLinus Torvalds return 2; 2112*1da177e4SLinus Torvalds default: 2113*1da177e4SLinus Torvalds return 1; 2114*1da177e4SLinus Torvalds } 2115*1da177e4SLinus Torvalds } 2116*1da177e4SLinus Torvalds 2117*1da177e4SLinus Torvalds static int hdsp_set_da_gain(hdsp_t *hdsp, int mode) 2118*1da177e4SLinus Torvalds { 2119*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_DAGainMask; 2120*1da177e4SLinus Torvalds switch (mode) { 2121*1da177e4SLinus Torvalds case 0: 2122*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_DAGainHighGain; 2123*1da177e4SLinus Torvalds break; 2124*1da177e4SLinus Torvalds case 1: 2125*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_DAGainPlus4dBu; 2126*1da177e4SLinus Torvalds break; 2127*1da177e4SLinus Torvalds case 2: 2128*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_DAGainMinus10dBV; 2129*1da177e4SLinus Torvalds break; 2130*1da177e4SLinus Torvalds default: 2131*1da177e4SLinus Torvalds return -1; 2132*1da177e4SLinus Torvalds 2133*1da177e4SLinus Torvalds } 2134*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 2135*1da177e4SLinus Torvalds return 0; 2136*1da177e4SLinus Torvalds } 2137*1da177e4SLinus Torvalds 2138*1da177e4SLinus Torvalds static int snd_hdsp_info_da_gain(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 2139*1da177e4SLinus Torvalds { 2140*1da177e4SLinus Torvalds static char *texts[] = {"Hi Gain", "+4 dBu", "-10 dbV"}; 2141*1da177e4SLinus Torvalds 2142*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2143*1da177e4SLinus Torvalds uinfo->count = 1; 2144*1da177e4SLinus Torvalds uinfo->value.enumerated.items = 3; 2145*1da177e4SLinus Torvalds if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 2146*1da177e4SLinus Torvalds uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 2147*1da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 2148*1da177e4SLinus Torvalds return 0; 2149*1da177e4SLinus Torvalds } 2150*1da177e4SLinus Torvalds 2151*1da177e4SLinus Torvalds static int snd_hdsp_get_da_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2152*1da177e4SLinus Torvalds { 2153*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2154*1da177e4SLinus Torvalds 2155*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp); 2156*1da177e4SLinus Torvalds return 0; 2157*1da177e4SLinus Torvalds } 2158*1da177e4SLinus Torvalds 2159*1da177e4SLinus Torvalds static int snd_hdsp_put_da_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2160*1da177e4SLinus Torvalds { 2161*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2162*1da177e4SLinus Torvalds int change; 2163*1da177e4SLinus Torvalds int val; 2164*1da177e4SLinus Torvalds 2165*1da177e4SLinus Torvalds if (!snd_hdsp_use_is_exclusive(hdsp)) 2166*1da177e4SLinus Torvalds return -EBUSY; 2167*1da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0]; 2168*1da177e4SLinus Torvalds if (val < 0) val = 0; 2169*1da177e4SLinus Torvalds if (val > 2) val = 2; 2170*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 2171*1da177e4SLinus Torvalds if (val != hdsp_da_gain(hdsp)) { 2172*1da177e4SLinus Torvalds change = (hdsp_set_da_gain(hdsp, val) == 0) ? 1 : 0; 2173*1da177e4SLinus Torvalds } else { 2174*1da177e4SLinus Torvalds change = 0; 2175*1da177e4SLinus Torvalds } 2176*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 2177*1da177e4SLinus Torvalds return change; 2178*1da177e4SLinus Torvalds } 2179*1da177e4SLinus Torvalds 2180*1da177e4SLinus Torvalds #define HDSP_AD_GAIN(xname, xindex) \ 2181*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 2182*1da177e4SLinus Torvalds .name = xname, \ 2183*1da177e4SLinus Torvalds .index = xindex, \ 2184*1da177e4SLinus Torvalds .info = snd_hdsp_info_ad_gain, \ 2185*1da177e4SLinus Torvalds .get = snd_hdsp_get_ad_gain, \ 2186*1da177e4SLinus Torvalds .put = snd_hdsp_put_ad_gain \ 2187*1da177e4SLinus Torvalds } 2188*1da177e4SLinus Torvalds 2189*1da177e4SLinus Torvalds static int hdsp_ad_gain(hdsp_t *hdsp) 2190*1da177e4SLinus Torvalds { 2191*1da177e4SLinus Torvalds switch (hdsp->control_register & HDSP_ADGainMask) { 2192*1da177e4SLinus Torvalds case HDSP_ADGainMinus10dBV: 2193*1da177e4SLinus Torvalds return 0; 2194*1da177e4SLinus Torvalds case HDSP_ADGainPlus4dBu: 2195*1da177e4SLinus Torvalds return 1; 2196*1da177e4SLinus Torvalds case HDSP_ADGainLowGain: 2197*1da177e4SLinus Torvalds return 2; 2198*1da177e4SLinus Torvalds default: 2199*1da177e4SLinus Torvalds return 1; 2200*1da177e4SLinus Torvalds } 2201*1da177e4SLinus Torvalds } 2202*1da177e4SLinus Torvalds 2203*1da177e4SLinus Torvalds static int hdsp_set_ad_gain(hdsp_t *hdsp, int mode) 2204*1da177e4SLinus Torvalds { 2205*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_ADGainMask; 2206*1da177e4SLinus Torvalds switch (mode) { 2207*1da177e4SLinus Torvalds case 0: 2208*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_ADGainMinus10dBV; 2209*1da177e4SLinus Torvalds break; 2210*1da177e4SLinus Torvalds case 1: 2211*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_ADGainPlus4dBu; 2212*1da177e4SLinus Torvalds break; 2213*1da177e4SLinus Torvalds case 2: 2214*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_ADGainLowGain; 2215*1da177e4SLinus Torvalds break; 2216*1da177e4SLinus Torvalds default: 2217*1da177e4SLinus Torvalds return -1; 2218*1da177e4SLinus Torvalds 2219*1da177e4SLinus Torvalds } 2220*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 2221*1da177e4SLinus Torvalds return 0; 2222*1da177e4SLinus Torvalds } 2223*1da177e4SLinus Torvalds 2224*1da177e4SLinus Torvalds static int snd_hdsp_info_ad_gain(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 2225*1da177e4SLinus Torvalds { 2226*1da177e4SLinus Torvalds static char *texts[] = {"-10 dBV", "+4 dBu", "Lo Gain"}; 2227*1da177e4SLinus Torvalds 2228*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2229*1da177e4SLinus Torvalds uinfo->count = 1; 2230*1da177e4SLinus Torvalds uinfo->value.enumerated.items = 3; 2231*1da177e4SLinus Torvalds if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 2232*1da177e4SLinus Torvalds uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 2233*1da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 2234*1da177e4SLinus Torvalds return 0; 2235*1da177e4SLinus Torvalds } 2236*1da177e4SLinus Torvalds 2237*1da177e4SLinus Torvalds static int snd_hdsp_get_ad_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2238*1da177e4SLinus Torvalds { 2239*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2240*1da177e4SLinus Torvalds 2241*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp); 2242*1da177e4SLinus Torvalds return 0; 2243*1da177e4SLinus Torvalds } 2244*1da177e4SLinus Torvalds 2245*1da177e4SLinus Torvalds static int snd_hdsp_put_ad_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2246*1da177e4SLinus Torvalds { 2247*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2248*1da177e4SLinus Torvalds int change; 2249*1da177e4SLinus Torvalds int val; 2250*1da177e4SLinus Torvalds 2251*1da177e4SLinus Torvalds if (!snd_hdsp_use_is_exclusive(hdsp)) 2252*1da177e4SLinus Torvalds return -EBUSY; 2253*1da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0]; 2254*1da177e4SLinus Torvalds if (val < 0) val = 0; 2255*1da177e4SLinus Torvalds if (val > 2) val = 2; 2256*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 2257*1da177e4SLinus Torvalds if (val != hdsp_ad_gain(hdsp)) { 2258*1da177e4SLinus Torvalds change = (hdsp_set_ad_gain(hdsp, val) == 0) ? 1 : 0; 2259*1da177e4SLinus Torvalds } else { 2260*1da177e4SLinus Torvalds change = 0; 2261*1da177e4SLinus Torvalds } 2262*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 2263*1da177e4SLinus Torvalds return change; 2264*1da177e4SLinus Torvalds } 2265*1da177e4SLinus Torvalds 2266*1da177e4SLinus Torvalds #define HDSP_PHONE_GAIN(xname, xindex) \ 2267*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 2268*1da177e4SLinus Torvalds .name = xname, \ 2269*1da177e4SLinus Torvalds .index = xindex, \ 2270*1da177e4SLinus Torvalds .info = snd_hdsp_info_phone_gain, \ 2271*1da177e4SLinus Torvalds .get = snd_hdsp_get_phone_gain, \ 2272*1da177e4SLinus Torvalds .put = snd_hdsp_put_phone_gain \ 2273*1da177e4SLinus Torvalds } 2274*1da177e4SLinus Torvalds 2275*1da177e4SLinus Torvalds static int hdsp_phone_gain(hdsp_t *hdsp) 2276*1da177e4SLinus Torvalds { 2277*1da177e4SLinus Torvalds switch (hdsp->control_register & HDSP_PhoneGainMask) { 2278*1da177e4SLinus Torvalds case HDSP_PhoneGain0dB: 2279*1da177e4SLinus Torvalds return 0; 2280*1da177e4SLinus Torvalds case HDSP_PhoneGainMinus6dB: 2281*1da177e4SLinus Torvalds return 1; 2282*1da177e4SLinus Torvalds case HDSP_PhoneGainMinus12dB: 2283*1da177e4SLinus Torvalds return 2; 2284*1da177e4SLinus Torvalds default: 2285*1da177e4SLinus Torvalds return 0; 2286*1da177e4SLinus Torvalds } 2287*1da177e4SLinus Torvalds } 2288*1da177e4SLinus Torvalds 2289*1da177e4SLinus Torvalds static int hdsp_set_phone_gain(hdsp_t *hdsp, int mode) 2290*1da177e4SLinus Torvalds { 2291*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_PhoneGainMask; 2292*1da177e4SLinus Torvalds switch (mode) { 2293*1da177e4SLinus Torvalds case 0: 2294*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_PhoneGain0dB; 2295*1da177e4SLinus Torvalds break; 2296*1da177e4SLinus Torvalds case 1: 2297*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_PhoneGainMinus6dB; 2298*1da177e4SLinus Torvalds break; 2299*1da177e4SLinus Torvalds case 2: 2300*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_PhoneGainMinus12dB; 2301*1da177e4SLinus Torvalds break; 2302*1da177e4SLinus Torvalds default: 2303*1da177e4SLinus Torvalds return -1; 2304*1da177e4SLinus Torvalds 2305*1da177e4SLinus Torvalds } 2306*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 2307*1da177e4SLinus Torvalds return 0; 2308*1da177e4SLinus Torvalds } 2309*1da177e4SLinus Torvalds 2310*1da177e4SLinus Torvalds static int snd_hdsp_info_phone_gain(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 2311*1da177e4SLinus Torvalds { 2312*1da177e4SLinus Torvalds static char *texts[] = {"0 dB", "-6 dB", "-12 dB"}; 2313*1da177e4SLinus Torvalds 2314*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2315*1da177e4SLinus Torvalds uinfo->count = 1; 2316*1da177e4SLinus Torvalds uinfo->value.enumerated.items = 3; 2317*1da177e4SLinus Torvalds if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 2318*1da177e4SLinus Torvalds uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 2319*1da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 2320*1da177e4SLinus Torvalds return 0; 2321*1da177e4SLinus Torvalds } 2322*1da177e4SLinus Torvalds 2323*1da177e4SLinus Torvalds static int snd_hdsp_get_phone_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2324*1da177e4SLinus Torvalds { 2325*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2326*1da177e4SLinus Torvalds 2327*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp); 2328*1da177e4SLinus Torvalds return 0; 2329*1da177e4SLinus Torvalds } 2330*1da177e4SLinus Torvalds 2331*1da177e4SLinus Torvalds static int snd_hdsp_put_phone_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2332*1da177e4SLinus Torvalds { 2333*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2334*1da177e4SLinus Torvalds int change; 2335*1da177e4SLinus Torvalds int val; 2336*1da177e4SLinus Torvalds 2337*1da177e4SLinus Torvalds if (!snd_hdsp_use_is_exclusive(hdsp)) 2338*1da177e4SLinus Torvalds return -EBUSY; 2339*1da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0]; 2340*1da177e4SLinus Torvalds if (val < 0) val = 0; 2341*1da177e4SLinus Torvalds if (val > 2) val = 2; 2342*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 2343*1da177e4SLinus Torvalds if (val != hdsp_phone_gain(hdsp)) { 2344*1da177e4SLinus Torvalds change = (hdsp_set_phone_gain(hdsp, val) == 0) ? 1 : 0; 2345*1da177e4SLinus Torvalds } else { 2346*1da177e4SLinus Torvalds change = 0; 2347*1da177e4SLinus Torvalds } 2348*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 2349*1da177e4SLinus Torvalds return change; 2350*1da177e4SLinus Torvalds } 2351*1da177e4SLinus Torvalds 2352*1da177e4SLinus Torvalds #define HDSP_XLR_BREAKOUT_CABLE(xname, xindex) \ 2353*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 2354*1da177e4SLinus Torvalds .name = xname, \ 2355*1da177e4SLinus Torvalds .index = xindex, \ 2356*1da177e4SLinus Torvalds .info = snd_hdsp_info_xlr_breakout_cable, \ 2357*1da177e4SLinus Torvalds .get = snd_hdsp_get_xlr_breakout_cable, \ 2358*1da177e4SLinus Torvalds .put = snd_hdsp_put_xlr_breakout_cable \ 2359*1da177e4SLinus Torvalds } 2360*1da177e4SLinus Torvalds 2361*1da177e4SLinus Torvalds static int hdsp_xlr_breakout_cable(hdsp_t *hdsp) 2362*1da177e4SLinus Torvalds { 2363*1da177e4SLinus Torvalds if (hdsp->control_register & HDSP_XLRBreakoutCable) { 2364*1da177e4SLinus Torvalds return 1; 2365*1da177e4SLinus Torvalds } 2366*1da177e4SLinus Torvalds return 0; 2367*1da177e4SLinus Torvalds } 2368*1da177e4SLinus Torvalds 2369*1da177e4SLinus Torvalds static int hdsp_set_xlr_breakout_cable(hdsp_t *hdsp, int mode) 2370*1da177e4SLinus Torvalds { 2371*1da177e4SLinus Torvalds if (mode) { 2372*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_XLRBreakoutCable; 2373*1da177e4SLinus Torvalds } else { 2374*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_XLRBreakoutCable; 2375*1da177e4SLinus Torvalds } 2376*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 2377*1da177e4SLinus Torvalds return 0; 2378*1da177e4SLinus Torvalds } 2379*1da177e4SLinus Torvalds 2380*1da177e4SLinus Torvalds static int snd_hdsp_info_xlr_breakout_cable(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 2381*1da177e4SLinus Torvalds { 2382*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 2383*1da177e4SLinus Torvalds uinfo->count = 1; 2384*1da177e4SLinus Torvalds uinfo->value.integer.min = 0; 2385*1da177e4SLinus Torvalds uinfo->value.integer.max = 1; 2386*1da177e4SLinus Torvalds return 0; 2387*1da177e4SLinus Torvalds } 2388*1da177e4SLinus Torvalds 2389*1da177e4SLinus Torvalds static int snd_hdsp_get_xlr_breakout_cable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2390*1da177e4SLinus Torvalds { 2391*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2392*1da177e4SLinus Torvalds 2393*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = hdsp_xlr_breakout_cable(hdsp); 2394*1da177e4SLinus Torvalds return 0; 2395*1da177e4SLinus Torvalds } 2396*1da177e4SLinus Torvalds 2397*1da177e4SLinus Torvalds static int snd_hdsp_put_xlr_breakout_cable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2398*1da177e4SLinus Torvalds { 2399*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2400*1da177e4SLinus Torvalds int change; 2401*1da177e4SLinus Torvalds int val; 2402*1da177e4SLinus Torvalds 2403*1da177e4SLinus Torvalds if (!snd_hdsp_use_is_exclusive(hdsp)) 2404*1da177e4SLinus Torvalds return -EBUSY; 2405*1da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] & 1; 2406*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 2407*1da177e4SLinus Torvalds change = (int)val != hdsp_xlr_breakout_cable(hdsp); 2408*1da177e4SLinus Torvalds hdsp_set_xlr_breakout_cable(hdsp, val); 2409*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 2410*1da177e4SLinus Torvalds return change; 2411*1da177e4SLinus Torvalds } 2412*1da177e4SLinus Torvalds 2413*1da177e4SLinus Torvalds /* (De)activates old RME Analog Extension Board 2414*1da177e4SLinus Torvalds These are connected to the internal ADAT connector 2415*1da177e4SLinus Torvalds Switching this on desactivates external ADAT 2416*1da177e4SLinus Torvalds */ 2417*1da177e4SLinus Torvalds #define HDSP_AEB(xname, xindex) \ 2418*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 2419*1da177e4SLinus Torvalds .name = xname, \ 2420*1da177e4SLinus Torvalds .index = xindex, \ 2421*1da177e4SLinus Torvalds .info = snd_hdsp_info_aeb, \ 2422*1da177e4SLinus Torvalds .get = snd_hdsp_get_aeb, \ 2423*1da177e4SLinus Torvalds .put = snd_hdsp_put_aeb \ 2424*1da177e4SLinus Torvalds } 2425*1da177e4SLinus Torvalds 2426*1da177e4SLinus Torvalds static int hdsp_aeb(hdsp_t *hdsp) 2427*1da177e4SLinus Torvalds { 2428*1da177e4SLinus Torvalds if (hdsp->control_register & HDSP_AnalogExtensionBoard) { 2429*1da177e4SLinus Torvalds return 1; 2430*1da177e4SLinus Torvalds } 2431*1da177e4SLinus Torvalds return 0; 2432*1da177e4SLinus Torvalds } 2433*1da177e4SLinus Torvalds 2434*1da177e4SLinus Torvalds static int hdsp_set_aeb(hdsp_t *hdsp, int mode) 2435*1da177e4SLinus Torvalds { 2436*1da177e4SLinus Torvalds if (mode) { 2437*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_AnalogExtensionBoard; 2438*1da177e4SLinus Torvalds } else { 2439*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_AnalogExtensionBoard; 2440*1da177e4SLinus Torvalds } 2441*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 2442*1da177e4SLinus Torvalds return 0; 2443*1da177e4SLinus Torvalds } 2444*1da177e4SLinus Torvalds 2445*1da177e4SLinus Torvalds static int snd_hdsp_info_aeb(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 2446*1da177e4SLinus Torvalds { 2447*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 2448*1da177e4SLinus Torvalds uinfo->count = 1; 2449*1da177e4SLinus Torvalds uinfo->value.integer.min = 0; 2450*1da177e4SLinus Torvalds uinfo->value.integer.max = 1; 2451*1da177e4SLinus Torvalds return 0; 2452*1da177e4SLinus Torvalds } 2453*1da177e4SLinus Torvalds 2454*1da177e4SLinus Torvalds static int snd_hdsp_get_aeb(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2455*1da177e4SLinus Torvalds { 2456*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2457*1da177e4SLinus Torvalds 2458*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = hdsp_aeb(hdsp); 2459*1da177e4SLinus Torvalds return 0; 2460*1da177e4SLinus Torvalds } 2461*1da177e4SLinus Torvalds 2462*1da177e4SLinus Torvalds static int snd_hdsp_put_aeb(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2463*1da177e4SLinus Torvalds { 2464*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2465*1da177e4SLinus Torvalds int change; 2466*1da177e4SLinus Torvalds int val; 2467*1da177e4SLinus Torvalds 2468*1da177e4SLinus Torvalds if (!snd_hdsp_use_is_exclusive(hdsp)) 2469*1da177e4SLinus Torvalds return -EBUSY; 2470*1da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] & 1; 2471*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 2472*1da177e4SLinus Torvalds change = (int)val != hdsp_aeb(hdsp); 2473*1da177e4SLinus Torvalds hdsp_set_aeb(hdsp, val); 2474*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 2475*1da177e4SLinus Torvalds return change; 2476*1da177e4SLinus Torvalds } 2477*1da177e4SLinus Torvalds 2478*1da177e4SLinus Torvalds #define HDSP_PREF_SYNC_REF(xname, xindex) \ 2479*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 2480*1da177e4SLinus Torvalds .name = xname, \ 2481*1da177e4SLinus Torvalds .index = xindex, \ 2482*1da177e4SLinus Torvalds .info = snd_hdsp_info_pref_sync_ref, \ 2483*1da177e4SLinus Torvalds .get = snd_hdsp_get_pref_sync_ref, \ 2484*1da177e4SLinus Torvalds .put = snd_hdsp_put_pref_sync_ref \ 2485*1da177e4SLinus Torvalds } 2486*1da177e4SLinus Torvalds 2487*1da177e4SLinus Torvalds static int hdsp_pref_sync_ref(hdsp_t *hdsp) 2488*1da177e4SLinus Torvalds { 2489*1da177e4SLinus Torvalds /* Notice that this looks at the requested sync source, 2490*1da177e4SLinus Torvalds not the one actually in use. 2491*1da177e4SLinus Torvalds */ 2492*1da177e4SLinus Torvalds 2493*1da177e4SLinus Torvalds switch (hdsp->control_register & HDSP_SyncRefMask) { 2494*1da177e4SLinus Torvalds case HDSP_SyncRef_ADAT1: 2495*1da177e4SLinus Torvalds return HDSP_SYNC_FROM_ADAT1; 2496*1da177e4SLinus Torvalds case HDSP_SyncRef_ADAT2: 2497*1da177e4SLinus Torvalds return HDSP_SYNC_FROM_ADAT2; 2498*1da177e4SLinus Torvalds case HDSP_SyncRef_ADAT3: 2499*1da177e4SLinus Torvalds return HDSP_SYNC_FROM_ADAT3; 2500*1da177e4SLinus Torvalds case HDSP_SyncRef_SPDIF: 2501*1da177e4SLinus Torvalds return HDSP_SYNC_FROM_SPDIF; 2502*1da177e4SLinus Torvalds case HDSP_SyncRef_WORD: 2503*1da177e4SLinus Torvalds return HDSP_SYNC_FROM_WORD; 2504*1da177e4SLinus Torvalds case HDSP_SyncRef_ADAT_SYNC: 2505*1da177e4SLinus Torvalds return HDSP_SYNC_FROM_ADAT_SYNC; 2506*1da177e4SLinus Torvalds default: 2507*1da177e4SLinus Torvalds return HDSP_SYNC_FROM_WORD; 2508*1da177e4SLinus Torvalds } 2509*1da177e4SLinus Torvalds return 0; 2510*1da177e4SLinus Torvalds } 2511*1da177e4SLinus Torvalds 2512*1da177e4SLinus Torvalds static int hdsp_set_pref_sync_ref(hdsp_t *hdsp, int pref) 2513*1da177e4SLinus Torvalds { 2514*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_SyncRefMask; 2515*1da177e4SLinus Torvalds switch (pref) { 2516*1da177e4SLinus Torvalds case HDSP_SYNC_FROM_ADAT1: 2517*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_SyncRefMask; /* clear SyncRef bits */ 2518*1da177e4SLinus Torvalds break; 2519*1da177e4SLinus Torvalds case HDSP_SYNC_FROM_ADAT2: 2520*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_SyncRef_ADAT2; 2521*1da177e4SLinus Torvalds break; 2522*1da177e4SLinus Torvalds case HDSP_SYNC_FROM_ADAT3: 2523*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_SyncRef_ADAT3; 2524*1da177e4SLinus Torvalds break; 2525*1da177e4SLinus Torvalds case HDSP_SYNC_FROM_SPDIF: 2526*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_SyncRef_SPDIF; 2527*1da177e4SLinus Torvalds break; 2528*1da177e4SLinus Torvalds case HDSP_SYNC_FROM_WORD: 2529*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_SyncRef_WORD; 2530*1da177e4SLinus Torvalds break; 2531*1da177e4SLinus Torvalds case HDSP_SYNC_FROM_ADAT_SYNC: 2532*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_SyncRef_ADAT_SYNC; 2533*1da177e4SLinus Torvalds break; 2534*1da177e4SLinus Torvalds default: 2535*1da177e4SLinus Torvalds return -1; 2536*1da177e4SLinus Torvalds } 2537*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 2538*1da177e4SLinus Torvalds return 0; 2539*1da177e4SLinus Torvalds } 2540*1da177e4SLinus Torvalds 2541*1da177e4SLinus Torvalds static int snd_hdsp_info_pref_sync_ref(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 2542*1da177e4SLinus Torvalds { 2543*1da177e4SLinus Torvalds static char *texts[] = {"Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3" }; 2544*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2545*1da177e4SLinus Torvalds 2546*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2547*1da177e4SLinus Torvalds uinfo->count = 1; 2548*1da177e4SLinus Torvalds 2549*1da177e4SLinus Torvalds switch (hdsp->io_type) { 2550*1da177e4SLinus Torvalds case Digiface: 2551*1da177e4SLinus Torvalds case H9652: 2552*1da177e4SLinus Torvalds uinfo->value.enumerated.items = 6; 2553*1da177e4SLinus Torvalds break; 2554*1da177e4SLinus Torvalds case Multiface: 2555*1da177e4SLinus Torvalds uinfo->value.enumerated.items = 4; 2556*1da177e4SLinus Torvalds break; 2557*1da177e4SLinus Torvalds case H9632: 2558*1da177e4SLinus Torvalds uinfo->value.enumerated.items = 3; 2559*1da177e4SLinus Torvalds break; 2560*1da177e4SLinus Torvalds default: 2561*1da177e4SLinus Torvalds uinfo->value.enumerated.items = 0; 2562*1da177e4SLinus Torvalds break; 2563*1da177e4SLinus Torvalds } 2564*1da177e4SLinus Torvalds 2565*1da177e4SLinus Torvalds if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 2566*1da177e4SLinus Torvalds uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 2567*1da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 2568*1da177e4SLinus Torvalds return 0; 2569*1da177e4SLinus Torvalds } 2570*1da177e4SLinus Torvalds 2571*1da177e4SLinus Torvalds static int snd_hdsp_get_pref_sync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2572*1da177e4SLinus Torvalds { 2573*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2574*1da177e4SLinus Torvalds 2575*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp); 2576*1da177e4SLinus Torvalds return 0; 2577*1da177e4SLinus Torvalds } 2578*1da177e4SLinus Torvalds 2579*1da177e4SLinus Torvalds static int snd_hdsp_put_pref_sync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2580*1da177e4SLinus Torvalds { 2581*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2582*1da177e4SLinus Torvalds int change, max; 2583*1da177e4SLinus Torvalds unsigned int val; 2584*1da177e4SLinus Torvalds 2585*1da177e4SLinus Torvalds if (!snd_hdsp_use_is_exclusive(hdsp)) 2586*1da177e4SLinus Torvalds return -EBUSY; 2587*1da177e4SLinus Torvalds 2588*1da177e4SLinus Torvalds switch (hdsp->io_type) { 2589*1da177e4SLinus Torvalds case Digiface: 2590*1da177e4SLinus Torvalds case H9652: 2591*1da177e4SLinus Torvalds max = 6; 2592*1da177e4SLinus Torvalds break; 2593*1da177e4SLinus Torvalds case Multiface: 2594*1da177e4SLinus Torvalds max = 4; 2595*1da177e4SLinus Torvalds break; 2596*1da177e4SLinus Torvalds case H9632: 2597*1da177e4SLinus Torvalds max = 3; 2598*1da177e4SLinus Torvalds break; 2599*1da177e4SLinus Torvalds default: 2600*1da177e4SLinus Torvalds return -EIO; 2601*1da177e4SLinus Torvalds } 2602*1da177e4SLinus Torvalds 2603*1da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0] % max; 2604*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 2605*1da177e4SLinus Torvalds change = (int)val != hdsp_pref_sync_ref(hdsp); 2606*1da177e4SLinus Torvalds hdsp_set_pref_sync_ref(hdsp, val); 2607*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 2608*1da177e4SLinus Torvalds return change; 2609*1da177e4SLinus Torvalds } 2610*1da177e4SLinus Torvalds 2611*1da177e4SLinus Torvalds #define HDSP_AUTOSYNC_REF(xname, xindex) \ 2612*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 2613*1da177e4SLinus Torvalds .name = xname, \ 2614*1da177e4SLinus Torvalds .index = xindex, \ 2615*1da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ, \ 2616*1da177e4SLinus Torvalds .info = snd_hdsp_info_autosync_ref, \ 2617*1da177e4SLinus Torvalds .get = snd_hdsp_get_autosync_ref, \ 2618*1da177e4SLinus Torvalds } 2619*1da177e4SLinus Torvalds 2620*1da177e4SLinus Torvalds static int hdsp_autosync_ref(hdsp_t *hdsp) 2621*1da177e4SLinus Torvalds { 2622*1da177e4SLinus Torvalds /* This looks at the autosync selected sync reference */ 2623*1da177e4SLinus Torvalds unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register); 2624*1da177e4SLinus Torvalds 2625*1da177e4SLinus Torvalds switch (status2 & HDSP_SelSyncRefMask) { 2626*1da177e4SLinus Torvalds case HDSP_SelSyncRef_WORD: 2627*1da177e4SLinus Torvalds return HDSP_AUTOSYNC_FROM_WORD; 2628*1da177e4SLinus Torvalds case HDSP_SelSyncRef_ADAT_SYNC: 2629*1da177e4SLinus Torvalds return HDSP_AUTOSYNC_FROM_ADAT_SYNC; 2630*1da177e4SLinus Torvalds case HDSP_SelSyncRef_SPDIF: 2631*1da177e4SLinus Torvalds return HDSP_AUTOSYNC_FROM_SPDIF; 2632*1da177e4SLinus Torvalds case HDSP_SelSyncRefMask: 2633*1da177e4SLinus Torvalds return HDSP_AUTOSYNC_FROM_NONE; 2634*1da177e4SLinus Torvalds case HDSP_SelSyncRef_ADAT1: 2635*1da177e4SLinus Torvalds return HDSP_AUTOSYNC_FROM_ADAT1; 2636*1da177e4SLinus Torvalds case HDSP_SelSyncRef_ADAT2: 2637*1da177e4SLinus Torvalds return HDSP_AUTOSYNC_FROM_ADAT2; 2638*1da177e4SLinus Torvalds case HDSP_SelSyncRef_ADAT3: 2639*1da177e4SLinus Torvalds return HDSP_AUTOSYNC_FROM_ADAT3; 2640*1da177e4SLinus Torvalds default: 2641*1da177e4SLinus Torvalds return HDSP_AUTOSYNC_FROM_WORD; 2642*1da177e4SLinus Torvalds } 2643*1da177e4SLinus Torvalds return 0; 2644*1da177e4SLinus Torvalds } 2645*1da177e4SLinus Torvalds 2646*1da177e4SLinus Torvalds static int snd_hdsp_info_autosync_ref(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 2647*1da177e4SLinus Torvalds { 2648*1da177e4SLinus Torvalds static char *texts[] = {"Word", "ADAT Sync", "IEC958", "None", "ADAT1", "ADAT2", "ADAT3" }; 2649*1da177e4SLinus Torvalds 2650*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2651*1da177e4SLinus Torvalds uinfo->count = 1; 2652*1da177e4SLinus Torvalds uinfo->value.enumerated.items = 7; 2653*1da177e4SLinus Torvalds if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 2654*1da177e4SLinus Torvalds uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 2655*1da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 2656*1da177e4SLinus Torvalds return 0; 2657*1da177e4SLinus Torvalds } 2658*1da177e4SLinus Torvalds 2659*1da177e4SLinus Torvalds static int snd_hdsp_get_autosync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2660*1da177e4SLinus Torvalds { 2661*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2662*1da177e4SLinus Torvalds 2663*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp); 2664*1da177e4SLinus Torvalds return 0; 2665*1da177e4SLinus Torvalds } 2666*1da177e4SLinus Torvalds 2667*1da177e4SLinus Torvalds #define HDSP_LINE_OUT(xname, xindex) \ 2668*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 2669*1da177e4SLinus Torvalds .name = xname, \ 2670*1da177e4SLinus Torvalds .index = xindex, \ 2671*1da177e4SLinus Torvalds .info = snd_hdsp_info_line_out, \ 2672*1da177e4SLinus Torvalds .get = snd_hdsp_get_line_out, \ 2673*1da177e4SLinus Torvalds .put = snd_hdsp_put_line_out \ 2674*1da177e4SLinus Torvalds } 2675*1da177e4SLinus Torvalds 2676*1da177e4SLinus Torvalds static int hdsp_line_out(hdsp_t *hdsp) 2677*1da177e4SLinus Torvalds { 2678*1da177e4SLinus Torvalds return (hdsp->control_register & HDSP_LineOut) ? 1 : 0; 2679*1da177e4SLinus Torvalds } 2680*1da177e4SLinus Torvalds 2681*1da177e4SLinus Torvalds static int hdsp_set_line_output(hdsp_t *hdsp, int out) 2682*1da177e4SLinus Torvalds { 2683*1da177e4SLinus Torvalds if (out) { 2684*1da177e4SLinus Torvalds hdsp->control_register |= HDSP_LineOut; 2685*1da177e4SLinus Torvalds } else { 2686*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_LineOut; 2687*1da177e4SLinus Torvalds } 2688*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 2689*1da177e4SLinus Torvalds return 0; 2690*1da177e4SLinus Torvalds } 2691*1da177e4SLinus Torvalds 2692*1da177e4SLinus Torvalds static int snd_hdsp_info_line_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 2693*1da177e4SLinus Torvalds { 2694*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 2695*1da177e4SLinus Torvalds uinfo->count = 1; 2696*1da177e4SLinus Torvalds uinfo->value.integer.min = 0; 2697*1da177e4SLinus Torvalds uinfo->value.integer.max = 1; 2698*1da177e4SLinus Torvalds return 0; 2699*1da177e4SLinus Torvalds } 2700*1da177e4SLinus Torvalds 2701*1da177e4SLinus Torvalds static int snd_hdsp_get_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2702*1da177e4SLinus Torvalds { 2703*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2704*1da177e4SLinus Torvalds 2705*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 2706*1da177e4SLinus Torvalds ucontrol->value.integer.value[0] = hdsp_line_out(hdsp); 2707*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 2708*1da177e4SLinus Torvalds return 0; 2709*1da177e4SLinus Torvalds } 2710*1da177e4SLinus Torvalds 2711*1da177e4SLinus Torvalds static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2712*1da177e4SLinus Torvalds { 2713*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2714*1da177e4SLinus Torvalds int change; 2715*1da177e4SLinus Torvalds unsigned int val; 2716*1da177e4SLinus Torvalds 2717*1da177e4SLinus Torvalds if (!snd_hdsp_use_is_exclusive(hdsp)) 2718*1da177e4SLinus Torvalds return -EBUSY; 2719*1da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] & 1; 2720*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 2721*1da177e4SLinus Torvalds change = (int)val != hdsp_line_out(hdsp); 2722*1da177e4SLinus Torvalds hdsp_set_line_output(hdsp, val); 2723*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 2724*1da177e4SLinus Torvalds return change; 2725*1da177e4SLinus Torvalds } 2726*1da177e4SLinus Torvalds 2727*1da177e4SLinus Torvalds #define HDSP_PRECISE_POINTER(xname, xindex) \ 2728*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 2729*1da177e4SLinus Torvalds .name = xname, \ 2730*1da177e4SLinus Torvalds .index = xindex, \ 2731*1da177e4SLinus Torvalds .info = snd_hdsp_info_precise_pointer, \ 2732*1da177e4SLinus Torvalds .get = snd_hdsp_get_precise_pointer, \ 2733*1da177e4SLinus Torvalds .put = snd_hdsp_put_precise_pointer \ 2734*1da177e4SLinus Torvalds } 2735*1da177e4SLinus Torvalds 2736*1da177e4SLinus Torvalds static int hdsp_set_precise_pointer(hdsp_t *hdsp, int precise) 2737*1da177e4SLinus Torvalds { 2738*1da177e4SLinus Torvalds if (precise) { 2739*1da177e4SLinus Torvalds hdsp->precise_ptr = 1; 2740*1da177e4SLinus Torvalds } else { 2741*1da177e4SLinus Torvalds hdsp->precise_ptr = 0; 2742*1da177e4SLinus Torvalds } 2743*1da177e4SLinus Torvalds return 0; 2744*1da177e4SLinus Torvalds } 2745*1da177e4SLinus Torvalds 2746*1da177e4SLinus Torvalds static int snd_hdsp_info_precise_pointer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 2747*1da177e4SLinus Torvalds { 2748*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 2749*1da177e4SLinus Torvalds uinfo->count = 1; 2750*1da177e4SLinus Torvalds uinfo->value.integer.min = 0; 2751*1da177e4SLinus Torvalds uinfo->value.integer.max = 1; 2752*1da177e4SLinus Torvalds return 0; 2753*1da177e4SLinus Torvalds } 2754*1da177e4SLinus Torvalds 2755*1da177e4SLinus Torvalds static int snd_hdsp_get_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2756*1da177e4SLinus Torvalds { 2757*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2758*1da177e4SLinus Torvalds 2759*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 2760*1da177e4SLinus Torvalds ucontrol->value.integer.value[0] = hdsp->precise_ptr; 2761*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 2762*1da177e4SLinus Torvalds return 0; 2763*1da177e4SLinus Torvalds } 2764*1da177e4SLinus Torvalds 2765*1da177e4SLinus Torvalds static int snd_hdsp_put_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2766*1da177e4SLinus Torvalds { 2767*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2768*1da177e4SLinus Torvalds int change; 2769*1da177e4SLinus Torvalds unsigned int val; 2770*1da177e4SLinus Torvalds 2771*1da177e4SLinus Torvalds if (!snd_hdsp_use_is_exclusive(hdsp)) 2772*1da177e4SLinus Torvalds return -EBUSY; 2773*1da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] & 1; 2774*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 2775*1da177e4SLinus Torvalds change = (int)val != hdsp->precise_ptr; 2776*1da177e4SLinus Torvalds hdsp_set_precise_pointer(hdsp, val); 2777*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 2778*1da177e4SLinus Torvalds return change; 2779*1da177e4SLinus Torvalds } 2780*1da177e4SLinus Torvalds 2781*1da177e4SLinus Torvalds #define HDSP_USE_MIDI_TASKLET(xname, xindex) \ 2782*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 2783*1da177e4SLinus Torvalds .name = xname, \ 2784*1da177e4SLinus Torvalds .index = xindex, \ 2785*1da177e4SLinus Torvalds .info = snd_hdsp_info_use_midi_tasklet, \ 2786*1da177e4SLinus Torvalds .get = snd_hdsp_get_use_midi_tasklet, \ 2787*1da177e4SLinus Torvalds .put = snd_hdsp_put_use_midi_tasklet \ 2788*1da177e4SLinus Torvalds } 2789*1da177e4SLinus Torvalds 2790*1da177e4SLinus Torvalds static int hdsp_set_use_midi_tasklet(hdsp_t *hdsp, int use_tasklet) 2791*1da177e4SLinus Torvalds { 2792*1da177e4SLinus Torvalds if (use_tasklet) { 2793*1da177e4SLinus Torvalds hdsp->use_midi_tasklet = 1; 2794*1da177e4SLinus Torvalds } else { 2795*1da177e4SLinus Torvalds hdsp->use_midi_tasklet = 0; 2796*1da177e4SLinus Torvalds } 2797*1da177e4SLinus Torvalds return 0; 2798*1da177e4SLinus Torvalds } 2799*1da177e4SLinus Torvalds 2800*1da177e4SLinus Torvalds static int snd_hdsp_info_use_midi_tasklet(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 2801*1da177e4SLinus Torvalds { 2802*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 2803*1da177e4SLinus Torvalds uinfo->count = 1; 2804*1da177e4SLinus Torvalds uinfo->value.integer.min = 0; 2805*1da177e4SLinus Torvalds uinfo->value.integer.max = 1; 2806*1da177e4SLinus Torvalds return 0; 2807*1da177e4SLinus Torvalds } 2808*1da177e4SLinus Torvalds 2809*1da177e4SLinus Torvalds static int snd_hdsp_get_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2810*1da177e4SLinus Torvalds { 2811*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2812*1da177e4SLinus Torvalds 2813*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 2814*1da177e4SLinus Torvalds ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet; 2815*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 2816*1da177e4SLinus Torvalds return 0; 2817*1da177e4SLinus Torvalds } 2818*1da177e4SLinus Torvalds 2819*1da177e4SLinus Torvalds static int snd_hdsp_put_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2820*1da177e4SLinus Torvalds { 2821*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2822*1da177e4SLinus Torvalds int change; 2823*1da177e4SLinus Torvalds unsigned int val; 2824*1da177e4SLinus Torvalds 2825*1da177e4SLinus Torvalds if (!snd_hdsp_use_is_exclusive(hdsp)) 2826*1da177e4SLinus Torvalds return -EBUSY; 2827*1da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] & 1; 2828*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 2829*1da177e4SLinus Torvalds change = (int)val != hdsp->use_midi_tasklet; 2830*1da177e4SLinus Torvalds hdsp_set_use_midi_tasklet(hdsp, val); 2831*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 2832*1da177e4SLinus Torvalds return change; 2833*1da177e4SLinus Torvalds } 2834*1da177e4SLinus Torvalds 2835*1da177e4SLinus Torvalds #define HDSP_MIXER(xname, xindex) \ 2836*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 2837*1da177e4SLinus Torvalds .name = xname, \ 2838*1da177e4SLinus Torvalds .index = xindex, \ 2839*1da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ 2840*1da177e4SLinus Torvalds SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ 2841*1da177e4SLinus Torvalds .info = snd_hdsp_info_mixer, \ 2842*1da177e4SLinus Torvalds .get = snd_hdsp_get_mixer, \ 2843*1da177e4SLinus Torvalds .put = snd_hdsp_put_mixer \ 2844*1da177e4SLinus Torvalds } 2845*1da177e4SLinus Torvalds 2846*1da177e4SLinus Torvalds static int snd_hdsp_info_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 2847*1da177e4SLinus Torvalds { 2848*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 2849*1da177e4SLinus Torvalds uinfo->count = 3; 2850*1da177e4SLinus Torvalds uinfo->value.integer.min = 0; 2851*1da177e4SLinus Torvalds uinfo->value.integer.max = 65536; 2852*1da177e4SLinus Torvalds uinfo->value.integer.step = 1; 2853*1da177e4SLinus Torvalds return 0; 2854*1da177e4SLinus Torvalds } 2855*1da177e4SLinus Torvalds 2856*1da177e4SLinus Torvalds static int snd_hdsp_get_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2857*1da177e4SLinus Torvalds { 2858*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2859*1da177e4SLinus Torvalds int source; 2860*1da177e4SLinus Torvalds int destination; 2861*1da177e4SLinus Torvalds int addr; 2862*1da177e4SLinus Torvalds 2863*1da177e4SLinus Torvalds source = ucontrol->value.integer.value[0]; 2864*1da177e4SLinus Torvalds destination = ucontrol->value.integer.value[1]; 2865*1da177e4SLinus Torvalds 2866*1da177e4SLinus Torvalds if (source >= hdsp->max_channels) { 2867*1da177e4SLinus Torvalds addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels,destination); 2868*1da177e4SLinus Torvalds } else { 2869*1da177e4SLinus Torvalds addr = hdsp_input_to_output_key(hdsp,source, destination); 2870*1da177e4SLinus Torvalds } 2871*1da177e4SLinus Torvalds 2872*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 2873*1da177e4SLinus Torvalds ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr); 2874*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 2875*1da177e4SLinus Torvalds return 0; 2876*1da177e4SLinus Torvalds } 2877*1da177e4SLinus Torvalds 2878*1da177e4SLinus Torvalds static int snd_hdsp_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2879*1da177e4SLinus Torvalds { 2880*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2881*1da177e4SLinus Torvalds int change; 2882*1da177e4SLinus Torvalds int source; 2883*1da177e4SLinus Torvalds int destination; 2884*1da177e4SLinus Torvalds int gain; 2885*1da177e4SLinus Torvalds int addr; 2886*1da177e4SLinus Torvalds 2887*1da177e4SLinus Torvalds if (!snd_hdsp_use_is_exclusive(hdsp)) 2888*1da177e4SLinus Torvalds return -EBUSY; 2889*1da177e4SLinus Torvalds 2890*1da177e4SLinus Torvalds source = ucontrol->value.integer.value[0]; 2891*1da177e4SLinus Torvalds destination = ucontrol->value.integer.value[1]; 2892*1da177e4SLinus Torvalds 2893*1da177e4SLinus Torvalds if (source >= hdsp->max_channels) { 2894*1da177e4SLinus Torvalds addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels, destination); 2895*1da177e4SLinus Torvalds } else { 2896*1da177e4SLinus Torvalds addr = hdsp_input_to_output_key(hdsp,source, destination); 2897*1da177e4SLinus Torvalds } 2898*1da177e4SLinus Torvalds 2899*1da177e4SLinus Torvalds gain = ucontrol->value.integer.value[2]; 2900*1da177e4SLinus Torvalds 2901*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 2902*1da177e4SLinus Torvalds change = gain != hdsp_read_gain(hdsp, addr); 2903*1da177e4SLinus Torvalds if (change) 2904*1da177e4SLinus Torvalds hdsp_write_gain(hdsp, addr, gain); 2905*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 2906*1da177e4SLinus Torvalds return change; 2907*1da177e4SLinus Torvalds } 2908*1da177e4SLinus Torvalds 2909*1da177e4SLinus Torvalds #define HDSP_WC_SYNC_CHECK(xname, xindex) \ 2910*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 2911*1da177e4SLinus Torvalds .name = xname, \ 2912*1da177e4SLinus Torvalds .index = xindex, \ 2913*1da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ 2914*1da177e4SLinus Torvalds .info = snd_hdsp_info_sync_check, \ 2915*1da177e4SLinus Torvalds .get = snd_hdsp_get_wc_sync_check \ 2916*1da177e4SLinus Torvalds } 2917*1da177e4SLinus Torvalds 2918*1da177e4SLinus Torvalds static int snd_hdsp_info_sync_check(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) 2919*1da177e4SLinus Torvalds { 2920*1da177e4SLinus Torvalds static char *texts[] = {"No Lock", "Lock", "Sync" }; 2921*1da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2922*1da177e4SLinus Torvalds uinfo->count = 1; 2923*1da177e4SLinus Torvalds uinfo->value.enumerated.items = 3; 2924*1da177e4SLinus Torvalds if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 2925*1da177e4SLinus Torvalds uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 2926*1da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 2927*1da177e4SLinus Torvalds return 0; 2928*1da177e4SLinus Torvalds } 2929*1da177e4SLinus Torvalds 2930*1da177e4SLinus Torvalds static int hdsp_wc_sync_check(hdsp_t *hdsp) 2931*1da177e4SLinus Torvalds { 2932*1da177e4SLinus Torvalds int status2 = hdsp_read(hdsp, HDSP_status2Register); 2933*1da177e4SLinus Torvalds if (status2 & HDSP_wc_lock) { 2934*1da177e4SLinus Torvalds if (status2 & HDSP_wc_sync) { 2935*1da177e4SLinus Torvalds return 2; 2936*1da177e4SLinus Torvalds } else { 2937*1da177e4SLinus Torvalds return 1; 2938*1da177e4SLinus Torvalds } 2939*1da177e4SLinus Torvalds } else { 2940*1da177e4SLinus Torvalds return 0; 2941*1da177e4SLinus Torvalds } 2942*1da177e4SLinus Torvalds return 0; 2943*1da177e4SLinus Torvalds } 2944*1da177e4SLinus Torvalds 2945*1da177e4SLinus Torvalds static int snd_hdsp_get_wc_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2946*1da177e4SLinus Torvalds { 2947*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2948*1da177e4SLinus Torvalds 2949*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = hdsp_wc_sync_check(hdsp); 2950*1da177e4SLinus Torvalds return 0; 2951*1da177e4SLinus Torvalds } 2952*1da177e4SLinus Torvalds 2953*1da177e4SLinus Torvalds #define HDSP_SPDIF_SYNC_CHECK(xname, xindex) \ 2954*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 2955*1da177e4SLinus Torvalds .name = xname, \ 2956*1da177e4SLinus Torvalds .index = xindex, \ 2957*1da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ 2958*1da177e4SLinus Torvalds .info = snd_hdsp_info_sync_check, \ 2959*1da177e4SLinus Torvalds .get = snd_hdsp_get_spdif_sync_check \ 2960*1da177e4SLinus Torvalds } 2961*1da177e4SLinus Torvalds 2962*1da177e4SLinus Torvalds static int hdsp_spdif_sync_check(hdsp_t *hdsp) 2963*1da177e4SLinus Torvalds { 2964*1da177e4SLinus Torvalds int status = hdsp_read(hdsp, HDSP_statusRegister); 2965*1da177e4SLinus Torvalds if (status & HDSP_SPDIFErrorFlag) { 2966*1da177e4SLinus Torvalds return 0; 2967*1da177e4SLinus Torvalds } else { 2968*1da177e4SLinus Torvalds if (status & HDSP_SPDIFSync) { 2969*1da177e4SLinus Torvalds return 2; 2970*1da177e4SLinus Torvalds } else { 2971*1da177e4SLinus Torvalds return 1; 2972*1da177e4SLinus Torvalds } 2973*1da177e4SLinus Torvalds } 2974*1da177e4SLinus Torvalds return 0; 2975*1da177e4SLinus Torvalds } 2976*1da177e4SLinus Torvalds 2977*1da177e4SLinus Torvalds static int snd_hdsp_get_spdif_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 2978*1da177e4SLinus Torvalds { 2979*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 2980*1da177e4SLinus Torvalds 2981*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = hdsp_spdif_sync_check(hdsp); 2982*1da177e4SLinus Torvalds return 0; 2983*1da177e4SLinus Torvalds } 2984*1da177e4SLinus Torvalds 2985*1da177e4SLinus Torvalds #define HDSP_ADATSYNC_SYNC_CHECK(xname, xindex) \ 2986*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 2987*1da177e4SLinus Torvalds .name = xname, \ 2988*1da177e4SLinus Torvalds .index = xindex, \ 2989*1da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ 2990*1da177e4SLinus Torvalds .info = snd_hdsp_info_sync_check, \ 2991*1da177e4SLinus Torvalds .get = snd_hdsp_get_adatsync_sync_check \ 2992*1da177e4SLinus Torvalds } 2993*1da177e4SLinus Torvalds 2994*1da177e4SLinus Torvalds static int hdsp_adatsync_sync_check(hdsp_t *hdsp) 2995*1da177e4SLinus Torvalds { 2996*1da177e4SLinus Torvalds int status = hdsp_read(hdsp, HDSP_statusRegister); 2997*1da177e4SLinus Torvalds if (status & HDSP_TimecodeLock) { 2998*1da177e4SLinus Torvalds if (status & HDSP_TimecodeSync) { 2999*1da177e4SLinus Torvalds return 2; 3000*1da177e4SLinus Torvalds } else { 3001*1da177e4SLinus Torvalds return 1; 3002*1da177e4SLinus Torvalds } 3003*1da177e4SLinus Torvalds } else { 3004*1da177e4SLinus Torvalds return 0; 3005*1da177e4SLinus Torvalds } 3006*1da177e4SLinus Torvalds } 3007*1da177e4SLinus Torvalds 3008*1da177e4SLinus Torvalds static int snd_hdsp_get_adatsync_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 3009*1da177e4SLinus Torvalds { 3010*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 3011*1da177e4SLinus Torvalds 3012*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = hdsp_adatsync_sync_check(hdsp); 3013*1da177e4SLinus Torvalds return 0; 3014*1da177e4SLinus Torvalds } 3015*1da177e4SLinus Torvalds 3016*1da177e4SLinus Torvalds #define HDSP_ADAT_SYNC_CHECK \ 3017*1da177e4SLinus Torvalds { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ 3018*1da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ 3019*1da177e4SLinus Torvalds .info = snd_hdsp_info_sync_check, \ 3020*1da177e4SLinus Torvalds .get = snd_hdsp_get_adat_sync_check \ 3021*1da177e4SLinus Torvalds } 3022*1da177e4SLinus Torvalds 3023*1da177e4SLinus Torvalds static int hdsp_adat_sync_check(hdsp_t *hdsp, int idx) 3024*1da177e4SLinus Torvalds { 3025*1da177e4SLinus Torvalds int status = hdsp_read(hdsp, HDSP_statusRegister); 3026*1da177e4SLinus Torvalds 3027*1da177e4SLinus Torvalds if (status & (HDSP_Lock0>>idx)) { 3028*1da177e4SLinus Torvalds if (status & (HDSP_Sync0>>idx)) { 3029*1da177e4SLinus Torvalds return 2; 3030*1da177e4SLinus Torvalds } else { 3031*1da177e4SLinus Torvalds return 1; 3032*1da177e4SLinus Torvalds } 3033*1da177e4SLinus Torvalds } else { 3034*1da177e4SLinus Torvalds return 0; 3035*1da177e4SLinus Torvalds } 3036*1da177e4SLinus Torvalds } 3037*1da177e4SLinus Torvalds 3038*1da177e4SLinus Torvalds static int snd_hdsp_get_adat_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) 3039*1da177e4SLinus Torvalds { 3040*1da177e4SLinus Torvalds int offset; 3041*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); 3042*1da177e4SLinus Torvalds 3043*1da177e4SLinus Torvalds offset = ucontrol->id.index - 1; 3044*1da177e4SLinus Torvalds snd_assert(offset >= 0); 3045*1da177e4SLinus Torvalds 3046*1da177e4SLinus Torvalds switch (hdsp->io_type) { 3047*1da177e4SLinus Torvalds case Digiface: 3048*1da177e4SLinus Torvalds case H9652: 3049*1da177e4SLinus Torvalds if (offset >= 3) 3050*1da177e4SLinus Torvalds return -EINVAL; 3051*1da177e4SLinus Torvalds break; 3052*1da177e4SLinus Torvalds case Multiface: 3053*1da177e4SLinus Torvalds case H9632: 3054*1da177e4SLinus Torvalds if (offset >= 1) 3055*1da177e4SLinus Torvalds return -EINVAL; 3056*1da177e4SLinus Torvalds break; 3057*1da177e4SLinus Torvalds default: 3058*1da177e4SLinus Torvalds return -EIO; 3059*1da177e4SLinus Torvalds } 3060*1da177e4SLinus Torvalds 3061*1da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = hdsp_adat_sync_check(hdsp, offset); 3062*1da177e4SLinus Torvalds return 0; 3063*1da177e4SLinus Torvalds } 3064*1da177e4SLinus Torvalds 3065*1da177e4SLinus Torvalds static snd_kcontrol_new_t snd_hdsp_9632_controls[] = { 3066*1da177e4SLinus Torvalds HDSP_DA_GAIN("DA Gain", 0), 3067*1da177e4SLinus Torvalds HDSP_AD_GAIN("AD Gain", 0), 3068*1da177e4SLinus Torvalds HDSP_PHONE_GAIN("Phones Gain", 0), 3069*1da177e4SLinus Torvalds HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0) 3070*1da177e4SLinus Torvalds }; 3071*1da177e4SLinus Torvalds 3072*1da177e4SLinus Torvalds static snd_kcontrol_new_t snd_hdsp_controls[] = { 3073*1da177e4SLinus Torvalds { 3074*1da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM, 3075*1da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), 3076*1da177e4SLinus Torvalds .info = snd_hdsp_control_spdif_info, 3077*1da177e4SLinus Torvalds .get = snd_hdsp_control_spdif_get, 3078*1da177e4SLinus Torvalds .put = snd_hdsp_control_spdif_put, 3079*1da177e4SLinus Torvalds }, 3080*1da177e4SLinus Torvalds { 3081*1da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, 3082*1da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM, 3083*1da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), 3084*1da177e4SLinus Torvalds .info = snd_hdsp_control_spdif_stream_info, 3085*1da177e4SLinus Torvalds .get = snd_hdsp_control_spdif_stream_get, 3086*1da177e4SLinus Torvalds .put = snd_hdsp_control_spdif_stream_put, 3087*1da177e4SLinus Torvalds }, 3088*1da177e4SLinus Torvalds { 3089*1da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ, 3090*1da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3091*1da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), 3092*1da177e4SLinus Torvalds .info = snd_hdsp_control_spdif_mask_info, 3093*1da177e4SLinus Torvalds .get = snd_hdsp_control_spdif_mask_get, 3094*1da177e4SLinus Torvalds .private_value = IEC958_AES0_NONAUDIO | 3095*1da177e4SLinus Torvalds IEC958_AES0_PROFESSIONAL | 3096*1da177e4SLinus Torvalds IEC958_AES0_CON_EMPHASIS, 3097*1da177e4SLinus Torvalds }, 3098*1da177e4SLinus Torvalds { 3099*1da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ, 3100*1da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 3101*1da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), 3102*1da177e4SLinus Torvalds .info = snd_hdsp_control_spdif_mask_info, 3103*1da177e4SLinus Torvalds .get = snd_hdsp_control_spdif_mask_get, 3104*1da177e4SLinus Torvalds .private_value = IEC958_AES0_NONAUDIO | 3105*1da177e4SLinus Torvalds IEC958_AES0_PROFESSIONAL | 3106*1da177e4SLinus Torvalds IEC958_AES0_PRO_EMPHASIS, 3107*1da177e4SLinus Torvalds }, 3108*1da177e4SLinus Torvalds HDSP_MIXER("Mixer", 0), 3109*1da177e4SLinus Torvalds HDSP_SPDIF_IN("IEC958 Input Connector", 0), 3110*1da177e4SLinus Torvalds HDSP_SPDIF_OUT("IEC958 Output also on ADAT1", 0), 3111*1da177e4SLinus Torvalds HDSP_SPDIF_PROFESSIONAL("IEC958 Professional Bit", 0), 3112*1da177e4SLinus Torvalds HDSP_SPDIF_EMPHASIS("IEC958 Emphasis Bit", 0), 3113*1da177e4SLinus Torvalds HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0), 3114*1da177e4SLinus Torvalds /* 'Sample Clock Source' complies with the alsa control naming scheme */ 3115*1da177e4SLinus Torvalds HDSP_CLOCK_SOURCE("Sample Clock Source", 0), 3116*1da177e4SLinus Torvalds HDSP_SYSTEM_CLOCK_MODE("System Clock Mode", 0), 3117*1da177e4SLinus Torvalds HDSP_PREF_SYNC_REF("Preferred Sync Reference", 0), 3118*1da177e4SLinus Torvalds HDSP_AUTOSYNC_REF("AutoSync Reference", 0), 3119*1da177e4SLinus Torvalds HDSP_SPDIF_SAMPLE_RATE("SPDIF Sample Rate", 0), 3120*1da177e4SLinus Torvalds HDSP_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), 3121*1da177e4SLinus Torvalds /* 'External Rate' complies with the alsa control naming scheme */ 3122*1da177e4SLinus Torvalds HDSP_AUTOSYNC_SAMPLE_RATE("External Rate", 0), 3123*1da177e4SLinus Torvalds HDSP_WC_SYNC_CHECK("Word Clock Lock Status", 0), 3124*1da177e4SLinus Torvalds HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0), 3125*1da177e4SLinus Torvalds HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0), 3126*1da177e4SLinus Torvalds HDSP_LINE_OUT("Line Out", 0), 3127*1da177e4SLinus Torvalds HDSP_PRECISE_POINTER("Precise Pointer", 0), 3128*1da177e4SLinus Torvalds HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0), 3129*1da177e4SLinus Torvalds }; 3130*1da177e4SLinus Torvalds 3131*1da177e4SLinus Torvalds static snd_kcontrol_new_t snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0); 3132*1da177e4SLinus Torvalds static snd_kcontrol_new_t snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK; 3133*1da177e4SLinus Torvalds 3134*1da177e4SLinus Torvalds static int snd_hdsp_create_controls(snd_card_t *card, hdsp_t *hdsp) 3135*1da177e4SLinus Torvalds { 3136*1da177e4SLinus Torvalds unsigned int idx; 3137*1da177e4SLinus Torvalds int err; 3138*1da177e4SLinus Torvalds snd_kcontrol_t *kctl; 3139*1da177e4SLinus Torvalds 3140*1da177e4SLinus Torvalds for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) { 3141*1da177e4SLinus Torvalds if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0) { 3142*1da177e4SLinus Torvalds return err; 3143*1da177e4SLinus Torvalds } 3144*1da177e4SLinus Torvalds if (idx == 1) /* IEC958 (S/PDIF) Stream */ 3145*1da177e4SLinus Torvalds hdsp->spdif_ctl = kctl; 3146*1da177e4SLinus Torvalds } 3147*1da177e4SLinus Torvalds 3148*1da177e4SLinus Torvalds /* ADAT SyncCheck status */ 3149*1da177e4SLinus Torvalds snd_hdsp_adat_sync_check.name = "ADAT Lock Status"; 3150*1da177e4SLinus Torvalds snd_hdsp_adat_sync_check.index = 1; 3151*1da177e4SLinus Torvalds if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp)))) { 3152*1da177e4SLinus Torvalds return err; 3153*1da177e4SLinus Torvalds } 3154*1da177e4SLinus Torvalds if (hdsp->io_type == Digiface || hdsp->io_type == H9652) { 3155*1da177e4SLinus Torvalds for (idx = 1; idx < 3; ++idx) { 3156*1da177e4SLinus Torvalds snd_hdsp_adat_sync_check.index = idx+1; 3157*1da177e4SLinus Torvalds if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp)))) { 3158*1da177e4SLinus Torvalds return err; 3159*1da177e4SLinus Torvalds } 3160*1da177e4SLinus Torvalds } 3161*1da177e4SLinus Torvalds } 3162*1da177e4SLinus Torvalds 3163*1da177e4SLinus Torvalds /* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */ 3164*1da177e4SLinus Torvalds if (hdsp->io_type == H9632) { 3165*1da177e4SLinus Torvalds for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) { 3166*1da177e4SLinus Torvalds if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp))) < 0) { 3167*1da177e4SLinus Torvalds return err; 3168*1da177e4SLinus Torvalds } 3169*1da177e4SLinus Torvalds } 3170*1da177e4SLinus Torvalds } 3171*1da177e4SLinus Torvalds 3172*1da177e4SLinus Torvalds /* AEB control for H96xx card */ 3173*1da177e4SLinus Torvalds if (hdsp->io_type == H9632 || hdsp->io_type == H9652) { 3174*1da177e4SLinus Torvalds if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp))) < 0) { 3175*1da177e4SLinus Torvalds return err; 3176*1da177e4SLinus Torvalds } 3177*1da177e4SLinus Torvalds } 3178*1da177e4SLinus Torvalds 3179*1da177e4SLinus Torvalds return 0; 3180*1da177e4SLinus Torvalds } 3181*1da177e4SLinus Torvalds 3182*1da177e4SLinus Torvalds /*------------------------------------------------------------ 3183*1da177e4SLinus Torvalds /proc interface 3184*1da177e4SLinus Torvalds ------------------------------------------------------------*/ 3185*1da177e4SLinus Torvalds 3186*1da177e4SLinus Torvalds static void 3187*1da177e4SLinus Torvalds snd_hdsp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer) 3188*1da177e4SLinus Torvalds { 3189*1da177e4SLinus Torvalds hdsp_t *hdsp = (hdsp_t *) entry->private_data; 3190*1da177e4SLinus Torvalds unsigned int status; 3191*1da177e4SLinus Torvalds unsigned int status2; 3192*1da177e4SLinus Torvalds char *pref_sync_ref; 3193*1da177e4SLinus Torvalds char *autosync_ref; 3194*1da177e4SLinus Torvalds char *system_clock_mode; 3195*1da177e4SLinus Torvalds char *clock_source; 3196*1da177e4SLinus Torvalds int x; 3197*1da177e4SLinus Torvalds 3198*1da177e4SLinus Torvalds if (hdsp_check_for_iobox (hdsp)) { 3199*1da177e4SLinus Torvalds snd_iprintf(buffer, "No I/O box connected.\nPlease connect one and upload firmware.\n"); 3200*1da177e4SLinus Torvalds return; 3201*1da177e4SLinus Torvalds } 3202*1da177e4SLinus Torvalds 3203*1da177e4SLinus Torvalds if (hdsp_check_for_firmware(hdsp)) { 3204*1da177e4SLinus Torvalds if (hdsp->state & HDSP_FirmwareCached) { 3205*1da177e4SLinus Torvalds if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { 3206*1da177e4SLinus Torvalds snd_iprintf(buffer, "Firmware loading from cache failed, please upload manually.\n"); 3207*1da177e4SLinus Torvalds return; 3208*1da177e4SLinus Torvalds } 3209*1da177e4SLinus Torvalds } else { 3210*1da177e4SLinus Torvalds snd_iprintf(buffer, "No firmware loaded nor cached, please upload firmware.\n"); 3211*1da177e4SLinus Torvalds return; 3212*1da177e4SLinus Torvalds } 3213*1da177e4SLinus Torvalds } 3214*1da177e4SLinus Torvalds 3215*1da177e4SLinus Torvalds status = hdsp_read(hdsp, HDSP_statusRegister); 3216*1da177e4SLinus Torvalds status2 = hdsp_read(hdsp, HDSP_status2Register); 3217*1da177e4SLinus Torvalds 3218*1da177e4SLinus Torvalds snd_iprintf(buffer, "%s (Card #%d)\n", hdsp->card_name, hdsp->card->number + 1); 3219*1da177e4SLinus Torvalds snd_iprintf(buffer, "Buffers: capture %p playback %p\n", 3220*1da177e4SLinus Torvalds hdsp->capture_buffer, hdsp->playback_buffer); 3221*1da177e4SLinus Torvalds snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n", 3222*1da177e4SLinus Torvalds hdsp->irq, hdsp->port, (unsigned long)hdsp->iobase); 3223*1da177e4SLinus Torvalds snd_iprintf(buffer, "Control register: 0x%x\n", hdsp->control_register); 3224*1da177e4SLinus Torvalds snd_iprintf(buffer, "Control2 register: 0x%x\n", hdsp->control2_register); 3225*1da177e4SLinus Torvalds snd_iprintf(buffer, "Status register: 0x%x\n", status); 3226*1da177e4SLinus Torvalds snd_iprintf(buffer, "Status2 register: 0x%x\n", status2); 3227*1da177e4SLinus Torvalds snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff); 3228*1da177e4SLinus Torvalds snd_iprintf(buffer, "MIDI1 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut0)); 3229*1da177e4SLinus Torvalds snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0)); 3230*1da177e4SLinus Torvalds snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1)); 3231*1da177e4SLinus Torvalds snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1)); 3232*1da177e4SLinus Torvalds snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off"); 3233*1da177e4SLinus Torvalds 3234*1da177e4SLinus Torvalds snd_iprintf(buffer, "\n"); 3235*1da177e4SLinus Torvalds 3236*1da177e4SLinus Torvalds x = 1 << (6 + hdsp_decode_latency(hdsp->control_register & HDSP_LatencyMask)); 3237*1da177e4SLinus Torvalds 3238*1da177e4SLinus Torvalds snd_iprintf(buffer, "Buffer Size (Latency): %d samples (2 periods of %lu bytes)\n", x, (unsigned long) hdsp->period_bytes); 3239*1da177e4SLinus Torvalds snd_iprintf(buffer, "Hardware pointer (frames): %ld\n", hdsp_hw_pointer(hdsp)); 3240*1da177e4SLinus Torvalds snd_iprintf(buffer, "Precise pointer: %s\n", hdsp->precise_ptr ? "on" : "off"); 3241*1da177e4SLinus Torvalds snd_iprintf(buffer, "Line out: %s\n", (hdsp->control_register & HDSP_LineOut) ? "on" : "off"); 3242*1da177e4SLinus Torvalds 3243*1da177e4SLinus Torvalds snd_iprintf(buffer, "Firmware version: %d\n", (status2&HDSP_version0)|(status2&HDSP_version1)<<1|(status2&HDSP_version2)<<2); 3244*1da177e4SLinus Torvalds 3245*1da177e4SLinus Torvalds snd_iprintf(buffer, "\n"); 3246*1da177e4SLinus Torvalds 3247*1da177e4SLinus Torvalds 3248*1da177e4SLinus Torvalds switch (hdsp_clock_source(hdsp)) { 3249*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_AUTOSYNC: 3250*1da177e4SLinus Torvalds clock_source = "AutoSync"; 3251*1da177e4SLinus Torvalds break; 3252*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ: 3253*1da177e4SLinus Torvalds clock_source = "Internal 32 kHz"; 3254*1da177e4SLinus Torvalds break; 3255*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ: 3256*1da177e4SLinus Torvalds clock_source = "Internal 44.1 kHz"; 3257*1da177e4SLinus Torvalds break; 3258*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ: 3259*1da177e4SLinus Torvalds clock_source = "Internal 48 kHz"; 3260*1da177e4SLinus Torvalds break; 3261*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ: 3262*1da177e4SLinus Torvalds clock_source = "Internal 64 kHz"; 3263*1da177e4SLinus Torvalds break; 3264*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ: 3265*1da177e4SLinus Torvalds clock_source = "Internal 88.2 kHz"; 3266*1da177e4SLinus Torvalds break; 3267*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ: 3268*1da177e4SLinus Torvalds clock_source = "Internal 96 kHz"; 3269*1da177e4SLinus Torvalds break; 3270*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ: 3271*1da177e4SLinus Torvalds clock_source = "Internal 128 kHz"; 3272*1da177e4SLinus Torvalds break; 3273*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ: 3274*1da177e4SLinus Torvalds clock_source = "Internal 176.4 kHz"; 3275*1da177e4SLinus Torvalds break; 3276*1da177e4SLinus Torvalds case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ: 3277*1da177e4SLinus Torvalds clock_source = "Internal 192 kHz"; 3278*1da177e4SLinus Torvalds break; 3279*1da177e4SLinus Torvalds default: 3280*1da177e4SLinus Torvalds clock_source = "Error"; 3281*1da177e4SLinus Torvalds } 3282*1da177e4SLinus Torvalds snd_iprintf (buffer, "Sample Clock Source: %s\n", clock_source); 3283*1da177e4SLinus Torvalds 3284*1da177e4SLinus Torvalds if (hdsp_system_clock_mode(hdsp)) { 3285*1da177e4SLinus Torvalds system_clock_mode = "Slave"; 3286*1da177e4SLinus Torvalds } else { 3287*1da177e4SLinus Torvalds system_clock_mode = "Master"; 3288*1da177e4SLinus Torvalds } 3289*1da177e4SLinus Torvalds 3290*1da177e4SLinus Torvalds switch (hdsp_pref_sync_ref (hdsp)) { 3291*1da177e4SLinus Torvalds case HDSP_SYNC_FROM_WORD: 3292*1da177e4SLinus Torvalds pref_sync_ref = "Word Clock"; 3293*1da177e4SLinus Torvalds break; 3294*1da177e4SLinus Torvalds case HDSP_SYNC_FROM_ADAT_SYNC: 3295*1da177e4SLinus Torvalds pref_sync_ref = "ADAT Sync"; 3296*1da177e4SLinus Torvalds break; 3297*1da177e4SLinus Torvalds case HDSP_SYNC_FROM_SPDIF: 3298*1da177e4SLinus Torvalds pref_sync_ref = "SPDIF"; 3299*1da177e4SLinus Torvalds break; 3300*1da177e4SLinus Torvalds case HDSP_SYNC_FROM_ADAT1: 3301*1da177e4SLinus Torvalds pref_sync_ref = "ADAT1"; 3302*1da177e4SLinus Torvalds break; 3303*1da177e4SLinus Torvalds case HDSP_SYNC_FROM_ADAT2: 3304*1da177e4SLinus Torvalds pref_sync_ref = "ADAT2"; 3305*1da177e4SLinus Torvalds break; 3306*1da177e4SLinus Torvalds case HDSP_SYNC_FROM_ADAT3: 3307*1da177e4SLinus Torvalds pref_sync_ref = "ADAT3"; 3308*1da177e4SLinus Torvalds break; 3309*1da177e4SLinus Torvalds default: 3310*1da177e4SLinus Torvalds pref_sync_ref = "Word Clock"; 3311*1da177e4SLinus Torvalds break; 3312*1da177e4SLinus Torvalds } 3313*1da177e4SLinus Torvalds snd_iprintf (buffer, "Preferred Sync Reference: %s\n", pref_sync_ref); 3314*1da177e4SLinus Torvalds 3315*1da177e4SLinus Torvalds switch (hdsp_autosync_ref (hdsp)) { 3316*1da177e4SLinus Torvalds case HDSP_AUTOSYNC_FROM_WORD: 3317*1da177e4SLinus Torvalds autosync_ref = "Word Clock"; 3318*1da177e4SLinus Torvalds break; 3319*1da177e4SLinus Torvalds case HDSP_AUTOSYNC_FROM_ADAT_SYNC: 3320*1da177e4SLinus Torvalds autosync_ref = "ADAT Sync"; 3321*1da177e4SLinus Torvalds break; 3322*1da177e4SLinus Torvalds case HDSP_AUTOSYNC_FROM_SPDIF: 3323*1da177e4SLinus Torvalds autosync_ref = "SPDIF"; 3324*1da177e4SLinus Torvalds break; 3325*1da177e4SLinus Torvalds case HDSP_AUTOSYNC_FROM_NONE: 3326*1da177e4SLinus Torvalds autosync_ref = "None"; 3327*1da177e4SLinus Torvalds break; 3328*1da177e4SLinus Torvalds case HDSP_AUTOSYNC_FROM_ADAT1: 3329*1da177e4SLinus Torvalds autosync_ref = "ADAT1"; 3330*1da177e4SLinus Torvalds break; 3331*1da177e4SLinus Torvalds case HDSP_AUTOSYNC_FROM_ADAT2: 3332*1da177e4SLinus Torvalds autosync_ref = "ADAT2"; 3333*1da177e4SLinus Torvalds break; 3334*1da177e4SLinus Torvalds case HDSP_AUTOSYNC_FROM_ADAT3: 3335*1da177e4SLinus Torvalds autosync_ref = "ADAT3"; 3336*1da177e4SLinus Torvalds break; 3337*1da177e4SLinus Torvalds default: 3338*1da177e4SLinus Torvalds autosync_ref = "---"; 3339*1da177e4SLinus Torvalds break; 3340*1da177e4SLinus Torvalds } 3341*1da177e4SLinus Torvalds snd_iprintf (buffer, "AutoSync Reference: %s\n", autosync_ref); 3342*1da177e4SLinus Torvalds 3343*1da177e4SLinus Torvalds snd_iprintf (buffer, "AutoSync Frequency: %d\n", hdsp_external_sample_rate(hdsp)); 3344*1da177e4SLinus Torvalds 3345*1da177e4SLinus Torvalds snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode); 3346*1da177e4SLinus Torvalds 3347*1da177e4SLinus Torvalds snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate); 3348*1da177e4SLinus Torvalds 3349*1da177e4SLinus Torvalds snd_iprintf(buffer, "\n"); 3350*1da177e4SLinus Torvalds 3351*1da177e4SLinus Torvalds switch (hdsp_spdif_in(hdsp)) { 3352*1da177e4SLinus Torvalds case HDSP_SPDIFIN_OPTICAL: 3353*1da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 input: Optical\n"); 3354*1da177e4SLinus Torvalds break; 3355*1da177e4SLinus Torvalds case HDSP_SPDIFIN_COAXIAL: 3356*1da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 input: Coaxial\n"); 3357*1da177e4SLinus Torvalds break; 3358*1da177e4SLinus Torvalds case HDSP_SPDIFIN_INTERNAL: 3359*1da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 input: Internal\n"); 3360*1da177e4SLinus Torvalds break; 3361*1da177e4SLinus Torvalds case HDSP_SPDIFIN_AES: 3362*1da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 input: AES\n"); 3363*1da177e4SLinus Torvalds break; 3364*1da177e4SLinus Torvalds default: 3365*1da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 input: ???\n"); 3366*1da177e4SLinus Torvalds break; 3367*1da177e4SLinus Torvalds } 3368*1da177e4SLinus Torvalds 3369*1da177e4SLinus Torvalds if (hdsp->control_register & HDSP_SPDIFOpticalOut) { 3370*1da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n"); 3371*1da177e4SLinus Torvalds } else { 3372*1da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 output: Coaxial only\n"); 3373*1da177e4SLinus Torvalds } 3374*1da177e4SLinus Torvalds 3375*1da177e4SLinus Torvalds if (hdsp->control_register & HDSP_SPDIFProfessional) { 3376*1da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 quality: Professional\n"); 3377*1da177e4SLinus Torvalds } else { 3378*1da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 quality: Consumer\n"); 3379*1da177e4SLinus Torvalds } 3380*1da177e4SLinus Torvalds 3381*1da177e4SLinus Torvalds if (hdsp->control_register & HDSP_SPDIFEmphasis) { 3382*1da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 emphasis: on\n"); 3383*1da177e4SLinus Torvalds } else { 3384*1da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 emphasis: off\n"); 3385*1da177e4SLinus Torvalds } 3386*1da177e4SLinus Torvalds 3387*1da177e4SLinus Torvalds if (hdsp->control_register & HDSP_SPDIFNonAudio) { 3388*1da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 NonAudio: on\n"); 3389*1da177e4SLinus Torvalds } else { 3390*1da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 NonAudio: off\n"); 3391*1da177e4SLinus Torvalds } 3392*1da177e4SLinus Torvalds if ((x = hdsp_spdif_sample_rate (hdsp)) != 0) { 3393*1da177e4SLinus Torvalds snd_iprintf (buffer, "IEC958 sample rate: %d\n", x); 3394*1da177e4SLinus Torvalds } else { 3395*1da177e4SLinus Torvalds snd_iprintf (buffer, "IEC958 sample rate: Error flag set\n"); 3396*1da177e4SLinus Torvalds } 3397*1da177e4SLinus Torvalds 3398*1da177e4SLinus Torvalds snd_iprintf(buffer, "\n"); 3399*1da177e4SLinus Torvalds 3400*1da177e4SLinus Torvalds /* Sync Check */ 3401*1da177e4SLinus Torvalds x = status & HDSP_Sync0; 3402*1da177e4SLinus Torvalds if (status & HDSP_Lock0) { 3403*1da177e4SLinus Torvalds snd_iprintf(buffer, "ADAT1: %s\n", x ? "Sync" : "Lock"); 3404*1da177e4SLinus Torvalds } else { 3405*1da177e4SLinus Torvalds snd_iprintf(buffer, "ADAT1: No Lock\n"); 3406*1da177e4SLinus Torvalds } 3407*1da177e4SLinus Torvalds 3408*1da177e4SLinus Torvalds switch (hdsp->io_type) { 3409*1da177e4SLinus Torvalds case Digiface: 3410*1da177e4SLinus Torvalds case H9652: 3411*1da177e4SLinus Torvalds x = status & HDSP_Sync1; 3412*1da177e4SLinus Torvalds if (status & HDSP_Lock1) { 3413*1da177e4SLinus Torvalds snd_iprintf(buffer, "ADAT2: %s\n", x ? "Sync" : "Lock"); 3414*1da177e4SLinus Torvalds } else { 3415*1da177e4SLinus Torvalds snd_iprintf(buffer, "ADAT2: No Lock\n"); 3416*1da177e4SLinus Torvalds } 3417*1da177e4SLinus Torvalds x = status & HDSP_Sync2; 3418*1da177e4SLinus Torvalds if (status & HDSP_Lock2) { 3419*1da177e4SLinus Torvalds snd_iprintf(buffer, "ADAT3: %s\n", x ? "Sync" : "Lock"); 3420*1da177e4SLinus Torvalds } else { 3421*1da177e4SLinus Torvalds snd_iprintf(buffer, "ADAT3: No Lock\n"); 3422*1da177e4SLinus Torvalds } 3423*1da177e4SLinus Torvalds default: 3424*1da177e4SLinus Torvalds /* relax */ 3425*1da177e4SLinus Torvalds break; 3426*1da177e4SLinus Torvalds } 3427*1da177e4SLinus Torvalds 3428*1da177e4SLinus Torvalds x = status & HDSP_SPDIFSync; 3429*1da177e4SLinus Torvalds if (status & HDSP_SPDIFErrorFlag) { 3430*1da177e4SLinus Torvalds snd_iprintf (buffer, "SPDIF: No Lock\n"); 3431*1da177e4SLinus Torvalds } else { 3432*1da177e4SLinus Torvalds snd_iprintf (buffer, "SPDIF: %s\n", x ? "Sync" : "Lock"); 3433*1da177e4SLinus Torvalds } 3434*1da177e4SLinus Torvalds 3435*1da177e4SLinus Torvalds x = status2 & HDSP_wc_sync; 3436*1da177e4SLinus Torvalds if (status2 & HDSP_wc_lock) { 3437*1da177e4SLinus Torvalds snd_iprintf (buffer, "Word Clock: %s\n", x ? "Sync" : "Lock"); 3438*1da177e4SLinus Torvalds } else { 3439*1da177e4SLinus Torvalds snd_iprintf (buffer, "Word Clock: No Lock\n"); 3440*1da177e4SLinus Torvalds } 3441*1da177e4SLinus Torvalds 3442*1da177e4SLinus Torvalds x = status & HDSP_TimecodeSync; 3443*1da177e4SLinus Torvalds if (status & HDSP_TimecodeLock) { 3444*1da177e4SLinus Torvalds snd_iprintf(buffer, "ADAT Sync: %s\n", x ? "Sync" : "Lock"); 3445*1da177e4SLinus Torvalds } else { 3446*1da177e4SLinus Torvalds snd_iprintf(buffer, "ADAT Sync: No Lock\n"); 3447*1da177e4SLinus Torvalds } 3448*1da177e4SLinus Torvalds 3449*1da177e4SLinus Torvalds snd_iprintf(buffer, "\n"); 3450*1da177e4SLinus Torvalds 3451*1da177e4SLinus Torvalds /* Informations about H9632 specific controls */ 3452*1da177e4SLinus Torvalds if (hdsp->io_type == H9632) { 3453*1da177e4SLinus Torvalds char *tmp; 3454*1da177e4SLinus Torvalds 3455*1da177e4SLinus Torvalds switch (hdsp_ad_gain(hdsp)) { 3456*1da177e4SLinus Torvalds case 0: 3457*1da177e4SLinus Torvalds tmp = "-10 dBV"; 3458*1da177e4SLinus Torvalds break; 3459*1da177e4SLinus Torvalds case 1: 3460*1da177e4SLinus Torvalds tmp = "+4 dBu"; 3461*1da177e4SLinus Torvalds break; 3462*1da177e4SLinus Torvalds default: 3463*1da177e4SLinus Torvalds tmp = "Lo Gain"; 3464*1da177e4SLinus Torvalds break; 3465*1da177e4SLinus Torvalds } 3466*1da177e4SLinus Torvalds snd_iprintf(buffer, "AD Gain : %s\n", tmp); 3467*1da177e4SLinus Torvalds 3468*1da177e4SLinus Torvalds switch (hdsp_da_gain(hdsp)) { 3469*1da177e4SLinus Torvalds case 0: 3470*1da177e4SLinus Torvalds tmp = "Hi Gain"; 3471*1da177e4SLinus Torvalds break; 3472*1da177e4SLinus Torvalds case 1: 3473*1da177e4SLinus Torvalds tmp = "+4 dBu"; 3474*1da177e4SLinus Torvalds break; 3475*1da177e4SLinus Torvalds default: 3476*1da177e4SLinus Torvalds tmp = "-10 dBV"; 3477*1da177e4SLinus Torvalds break; 3478*1da177e4SLinus Torvalds } 3479*1da177e4SLinus Torvalds snd_iprintf(buffer, "DA Gain : %s\n", tmp); 3480*1da177e4SLinus Torvalds 3481*1da177e4SLinus Torvalds switch (hdsp_phone_gain(hdsp)) { 3482*1da177e4SLinus Torvalds case 0: 3483*1da177e4SLinus Torvalds tmp = "0 dB"; 3484*1da177e4SLinus Torvalds break; 3485*1da177e4SLinus Torvalds case 1: 3486*1da177e4SLinus Torvalds tmp = "-6 dB"; 3487*1da177e4SLinus Torvalds break; 3488*1da177e4SLinus Torvalds default: 3489*1da177e4SLinus Torvalds tmp = "-12 dB"; 3490*1da177e4SLinus Torvalds break; 3491*1da177e4SLinus Torvalds } 3492*1da177e4SLinus Torvalds snd_iprintf(buffer, "Phones Gain : %s\n", tmp); 3493*1da177e4SLinus Torvalds 3494*1da177e4SLinus Torvalds snd_iprintf(buffer, "XLR Breakout Cable : %s\n", hdsp_xlr_breakout_cable(hdsp) ? "yes" : "no"); 3495*1da177e4SLinus Torvalds 3496*1da177e4SLinus Torvalds if (hdsp->control_register & HDSP_AnalogExtensionBoard) { 3497*1da177e4SLinus Torvalds snd_iprintf(buffer, "AEB : on (ADAT1 internal)\n"); 3498*1da177e4SLinus Torvalds } else { 3499*1da177e4SLinus Torvalds snd_iprintf(buffer, "AEB : off (ADAT1 external)\n"); 3500*1da177e4SLinus Torvalds } 3501*1da177e4SLinus Torvalds snd_iprintf(buffer, "\n"); 3502*1da177e4SLinus Torvalds } 3503*1da177e4SLinus Torvalds 3504*1da177e4SLinus Torvalds } 3505*1da177e4SLinus Torvalds 3506*1da177e4SLinus Torvalds static void __devinit snd_hdsp_proc_init(hdsp_t *hdsp) 3507*1da177e4SLinus Torvalds { 3508*1da177e4SLinus Torvalds snd_info_entry_t *entry; 3509*1da177e4SLinus Torvalds 3510*1da177e4SLinus Torvalds if (! snd_card_proc_new(hdsp->card, "hdsp", &entry)) 3511*1da177e4SLinus Torvalds snd_info_set_text_ops(entry, hdsp, 1024, snd_hdsp_proc_read); 3512*1da177e4SLinus Torvalds } 3513*1da177e4SLinus Torvalds 3514*1da177e4SLinus Torvalds static void snd_hdsp_free_buffers(hdsp_t *hdsp) 3515*1da177e4SLinus Torvalds { 3516*1da177e4SLinus Torvalds snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci); 3517*1da177e4SLinus Torvalds snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci); 3518*1da177e4SLinus Torvalds } 3519*1da177e4SLinus Torvalds 3520*1da177e4SLinus Torvalds static int __devinit snd_hdsp_initialize_memory(hdsp_t *hdsp) 3521*1da177e4SLinus Torvalds { 3522*1da177e4SLinus Torvalds unsigned long pb_bus, cb_bus; 3523*1da177e4SLinus Torvalds 3524*1da177e4SLinus Torvalds if (snd_hammerfall_get_buffer(hdsp->pci, &hdsp->capture_dma_buf, HDSP_DMA_AREA_BYTES) < 0 || 3525*1da177e4SLinus Torvalds snd_hammerfall_get_buffer(hdsp->pci, &hdsp->playback_dma_buf, HDSP_DMA_AREA_BYTES) < 0) { 3526*1da177e4SLinus Torvalds if (hdsp->capture_dma_buf.area) 3527*1da177e4SLinus Torvalds snd_dma_free_pages(&hdsp->capture_dma_buf); 3528*1da177e4SLinus Torvalds printk(KERN_ERR "%s: no buffers available\n", hdsp->card_name); 3529*1da177e4SLinus Torvalds return -ENOMEM; 3530*1da177e4SLinus Torvalds } 3531*1da177e4SLinus Torvalds 3532*1da177e4SLinus Torvalds /* Align to bus-space 64K boundary */ 3533*1da177e4SLinus Torvalds 3534*1da177e4SLinus Torvalds cb_bus = (hdsp->capture_dma_buf.addr + 0xFFFF) & ~0xFFFFl; 3535*1da177e4SLinus Torvalds pb_bus = (hdsp->playback_dma_buf.addr + 0xFFFF) & ~0xFFFFl; 3536*1da177e4SLinus Torvalds 3537*1da177e4SLinus Torvalds /* Tell the card where it is */ 3538*1da177e4SLinus Torvalds 3539*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus); 3540*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus); 3541*1da177e4SLinus Torvalds 3542*1da177e4SLinus Torvalds hdsp->capture_buffer = hdsp->capture_dma_buf.area + (cb_bus - hdsp->capture_dma_buf.addr); 3543*1da177e4SLinus Torvalds hdsp->playback_buffer = hdsp->playback_dma_buf.area + (pb_bus - hdsp->playback_dma_buf.addr); 3544*1da177e4SLinus Torvalds 3545*1da177e4SLinus Torvalds return 0; 3546*1da177e4SLinus Torvalds } 3547*1da177e4SLinus Torvalds 3548*1da177e4SLinus Torvalds static int snd_hdsp_set_defaults(hdsp_t *hdsp) 3549*1da177e4SLinus Torvalds { 3550*1da177e4SLinus Torvalds unsigned int i; 3551*1da177e4SLinus Torvalds 3552*1da177e4SLinus Torvalds /* ASSUMPTION: hdsp->lock is either held, or 3553*1da177e4SLinus Torvalds there is no need to hold it (e.g. during module 3554*1da177e4SLinus Torvalds initalization). 3555*1da177e4SLinus Torvalds */ 3556*1da177e4SLinus Torvalds 3557*1da177e4SLinus Torvalds /* set defaults: 3558*1da177e4SLinus Torvalds 3559*1da177e4SLinus Torvalds SPDIF Input via Coax 3560*1da177e4SLinus Torvalds Master clock mode 3561*1da177e4SLinus Torvalds maximum latency (7 => 2^7 = 8192 samples, 64Kbyte buffer, 3562*1da177e4SLinus Torvalds which implies 2 4096 sample, 32Kbyte periods). 3563*1da177e4SLinus Torvalds Enable line out. 3564*1da177e4SLinus Torvalds */ 3565*1da177e4SLinus Torvalds 3566*1da177e4SLinus Torvalds hdsp->control_register = HDSP_ClockModeMaster | 3567*1da177e4SLinus Torvalds HDSP_SPDIFInputCoaxial | 3568*1da177e4SLinus Torvalds hdsp_encode_latency(7) | 3569*1da177e4SLinus Torvalds HDSP_LineOut; 3570*1da177e4SLinus Torvalds 3571*1da177e4SLinus Torvalds 3572*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 3573*1da177e4SLinus Torvalds 3574*1da177e4SLinus Torvalds #ifdef SNDRV_BIG_ENDIAN 3575*1da177e4SLinus Torvalds hdsp->control2_register = HDSP_BIGENDIAN_MODE; 3576*1da177e4SLinus Torvalds #else 3577*1da177e4SLinus Torvalds hdsp->control2_register = 0; 3578*1da177e4SLinus Torvalds #endif 3579*1da177e4SLinus Torvalds if (hdsp->io_type == H9652) { 3580*1da177e4SLinus Torvalds snd_hdsp_9652_enable_mixer (hdsp); 3581*1da177e4SLinus Torvalds } else { 3582*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register); 3583*1da177e4SLinus Torvalds } 3584*1da177e4SLinus Torvalds 3585*1da177e4SLinus Torvalds hdsp_reset_hw_pointer(hdsp); 3586*1da177e4SLinus Torvalds hdsp_compute_period_size(hdsp); 3587*1da177e4SLinus Torvalds 3588*1da177e4SLinus Torvalds /* silence everything */ 3589*1da177e4SLinus Torvalds 3590*1da177e4SLinus Torvalds for (i = 0; i < HDSP_MATRIX_MIXER_SIZE; ++i) { 3591*1da177e4SLinus Torvalds hdsp->mixer_matrix[i] = MINUS_INFINITY_GAIN; 3592*1da177e4SLinus Torvalds } 3593*1da177e4SLinus Torvalds 3594*1da177e4SLinus Torvalds for (i = 0; i < ((hdsp->io_type == H9652 || hdsp->io_type == H9632) ? 1352 : HDSP_MATRIX_MIXER_SIZE); ++i) { 3595*1da177e4SLinus Torvalds if (hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN)) { 3596*1da177e4SLinus Torvalds return -EIO; 3597*1da177e4SLinus Torvalds } 3598*1da177e4SLinus Torvalds } 3599*1da177e4SLinus Torvalds 3600*1da177e4SLinus Torvalds /* H9632 specific defaults */ 3601*1da177e4SLinus Torvalds if (hdsp->io_type == H9632) { 3602*1da177e4SLinus Torvalds hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB); 3603*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 3604*1da177e4SLinus Torvalds } 3605*1da177e4SLinus Torvalds 3606*1da177e4SLinus Torvalds /* set a default rate so that the channel map is set up. 3607*1da177e4SLinus Torvalds */ 3608*1da177e4SLinus Torvalds 3609*1da177e4SLinus Torvalds hdsp_set_rate(hdsp, 48000, 1); 3610*1da177e4SLinus Torvalds 3611*1da177e4SLinus Torvalds return 0; 3612*1da177e4SLinus Torvalds } 3613*1da177e4SLinus Torvalds 3614*1da177e4SLinus Torvalds static void hdsp_midi_tasklet(unsigned long arg) 3615*1da177e4SLinus Torvalds { 3616*1da177e4SLinus Torvalds hdsp_t *hdsp = (hdsp_t *)arg; 3617*1da177e4SLinus Torvalds 3618*1da177e4SLinus Torvalds if (hdsp->midi[0].pending) { 3619*1da177e4SLinus Torvalds snd_hdsp_midi_input_read (&hdsp->midi[0]); 3620*1da177e4SLinus Torvalds } 3621*1da177e4SLinus Torvalds if (hdsp->midi[1].pending) { 3622*1da177e4SLinus Torvalds snd_hdsp_midi_input_read (&hdsp->midi[1]); 3623*1da177e4SLinus Torvalds } 3624*1da177e4SLinus Torvalds } 3625*1da177e4SLinus Torvalds 3626*1da177e4SLinus Torvalds static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *regs) 3627*1da177e4SLinus Torvalds { 3628*1da177e4SLinus Torvalds hdsp_t *hdsp = (hdsp_t *) dev_id; 3629*1da177e4SLinus Torvalds unsigned int status; 3630*1da177e4SLinus Torvalds int audio; 3631*1da177e4SLinus Torvalds int midi0; 3632*1da177e4SLinus Torvalds int midi1; 3633*1da177e4SLinus Torvalds unsigned int midi0status; 3634*1da177e4SLinus Torvalds unsigned int midi1status; 3635*1da177e4SLinus Torvalds int schedule = 0; 3636*1da177e4SLinus Torvalds 3637*1da177e4SLinus Torvalds status = hdsp_read(hdsp, HDSP_statusRegister); 3638*1da177e4SLinus Torvalds 3639*1da177e4SLinus Torvalds audio = status & HDSP_audioIRQPending; 3640*1da177e4SLinus Torvalds midi0 = status & HDSP_midi0IRQPending; 3641*1da177e4SLinus Torvalds midi1 = status & HDSP_midi1IRQPending; 3642*1da177e4SLinus Torvalds 3643*1da177e4SLinus Torvalds if (!audio && !midi0 && !midi1) { 3644*1da177e4SLinus Torvalds return IRQ_NONE; 3645*1da177e4SLinus Torvalds } 3646*1da177e4SLinus Torvalds 3647*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_interruptConfirmation, 0); 3648*1da177e4SLinus Torvalds 3649*1da177e4SLinus Torvalds midi0status = hdsp_read (hdsp, HDSP_midiStatusIn0) & 0xff; 3650*1da177e4SLinus Torvalds midi1status = hdsp_read (hdsp, HDSP_midiStatusIn1) & 0xff; 3651*1da177e4SLinus Torvalds 3652*1da177e4SLinus Torvalds if (audio) { 3653*1da177e4SLinus Torvalds if (hdsp->capture_substream) { 3654*1da177e4SLinus Torvalds snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); 3655*1da177e4SLinus Torvalds } 3656*1da177e4SLinus Torvalds 3657*1da177e4SLinus Torvalds if (hdsp->playback_substream) { 3658*1da177e4SLinus Torvalds snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream); 3659*1da177e4SLinus Torvalds } 3660*1da177e4SLinus Torvalds } 3661*1da177e4SLinus Torvalds 3662*1da177e4SLinus Torvalds if (midi0 && midi0status) { 3663*1da177e4SLinus Torvalds if (hdsp->use_midi_tasklet) { 3664*1da177e4SLinus Torvalds /* we disable interrupts for this input until processing is done */ 3665*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_Midi0InterruptEnable; 3666*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 3667*1da177e4SLinus Torvalds hdsp->midi[0].pending = 1; 3668*1da177e4SLinus Torvalds schedule = 1; 3669*1da177e4SLinus Torvalds } else { 3670*1da177e4SLinus Torvalds snd_hdsp_midi_input_read (&hdsp->midi[0]); 3671*1da177e4SLinus Torvalds } 3672*1da177e4SLinus Torvalds } 3673*1da177e4SLinus Torvalds if (hdsp->io_type != Multiface && hdsp->io_type != H9632 && midi1 && midi1status) { 3674*1da177e4SLinus Torvalds if (hdsp->use_midi_tasklet) { 3675*1da177e4SLinus Torvalds /* we disable interrupts for this input until processing is done */ 3676*1da177e4SLinus Torvalds hdsp->control_register &= ~HDSP_Midi1InterruptEnable; 3677*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 3678*1da177e4SLinus Torvalds hdsp->midi[1].pending = 1; 3679*1da177e4SLinus Torvalds schedule = 1; 3680*1da177e4SLinus Torvalds } else { 3681*1da177e4SLinus Torvalds snd_hdsp_midi_input_read (&hdsp->midi[1]); 3682*1da177e4SLinus Torvalds } 3683*1da177e4SLinus Torvalds } 3684*1da177e4SLinus Torvalds if (hdsp->use_midi_tasklet && schedule) 3685*1da177e4SLinus Torvalds tasklet_hi_schedule(&hdsp->midi_tasklet); 3686*1da177e4SLinus Torvalds return IRQ_HANDLED; 3687*1da177e4SLinus Torvalds } 3688*1da177e4SLinus Torvalds 3689*1da177e4SLinus Torvalds static snd_pcm_uframes_t snd_hdsp_hw_pointer(snd_pcm_substream_t *substream) 3690*1da177e4SLinus Torvalds { 3691*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_pcm_substream_chip(substream); 3692*1da177e4SLinus Torvalds return hdsp_hw_pointer(hdsp); 3693*1da177e4SLinus Torvalds } 3694*1da177e4SLinus Torvalds 3695*1da177e4SLinus Torvalds static char *hdsp_channel_buffer_location(hdsp_t *hdsp, 3696*1da177e4SLinus Torvalds int stream, 3697*1da177e4SLinus Torvalds int channel) 3698*1da177e4SLinus Torvalds 3699*1da177e4SLinus Torvalds { 3700*1da177e4SLinus Torvalds int mapped_channel; 3701*1da177e4SLinus Torvalds 3702*1da177e4SLinus Torvalds snd_assert(channel >= 0 && channel < hdsp->max_channels, return NULL); 3703*1da177e4SLinus Torvalds 3704*1da177e4SLinus Torvalds if ((mapped_channel = hdsp->channel_map[channel]) < 0) { 3705*1da177e4SLinus Torvalds return NULL; 3706*1da177e4SLinus Torvalds } 3707*1da177e4SLinus Torvalds 3708*1da177e4SLinus Torvalds if (stream == SNDRV_PCM_STREAM_CAPTURE) { 3709*1da177e4SLinus Torvalds return hdsp->capture_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES); 3710*1da177e4SLinus Torvalds } else { 3711*1da177e4SLinus Torvalds return hdsp->playback_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES); 3712*1da177e4SLinus Torvalds } 3713*1da177e4SLinus Torvalds } 3714*1da177e4SLinus Torvalds 3715*1da177e4SLinus Torvalds static int snd_hdsp_playback_copy(snd_pcm_substream_t *substream, int channel, 3716*1da177e4SLinus Torvalds snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count) 3717*1da177e4SLinus Torvalds { 3718*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_pcm_substream_chip(substream); 3719*1da177e4SLinus Torvalds char *channel_buf; 3720*1da177e4SLinus Torvalds 3721*1da177e4SLinus Torvalds snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL); 3722*1da177e4SLinus Torvalds 3723*1da177e4SLinus Torvalds channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); 3724*1da177e4SLinus Torvalds snd_assert(channel_buf != NULL, return -EIO); 3725*1da177e4SLinus Torvalds if (copy_from_user(channel_buf + pos * 4, src, count * 4)) 3726*1da177e4SLinus Torvalds return -EFAULT; 3727*1da177e4SLinus Torvalds return count; 3728*1da177e4SLinus Torvalds } 3729*1da177e4SLinus Torvalds 3730*1da177e4SLinus Torvalds static int snd_hdsp_capture_copy(snd_pcm_substream_t *substream, int channel, 3731*1da177e4SLinus Torvalds snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count) 3732*1da177e4SLinus Torvalds { 3733*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_pcm_substream_chip(substream); 3734*1da177e4SLinus Torvalds char *channel_buf; 3735*1da177e4SLinus Torvalds 3736*1da177e4SLinus Torvalds snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL); 3737*1da177e4SLinus Torvalds 3738*1da177e4SLinus Torvalds channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); 3739*1da177e4SLinus Torvalds snd_assert(channel_buf != NULL, return -EIO); 3740*1da177e4SLinus Torvalds if (copy_to_user(dst, channel_buf + pos * 4, count * 4)) 3741*1da177e4SLinus Torvalds return -EFAULT; 3742*1da177e4SLinus Torvalds return count; 3743*1da177e4SLinus Torvalds } 3744*1da177e4SLinus Torvalds 3745*1da177e4SLinus Torvalds static int snd_hdsp_hw_silence(snd_pcm_substream_t *substream, int channel, 3746*1da177e4SLinus Torvalds snd_pcm_uframes_t pos, snd_pcm_uframes_t count) 3747*1da177e4SLinus Torvalds { 3748*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_pcm_substream_chip(substream); 3749*1da177e4SLinus Torvalds char *channel_buf; 3750*1da177e4SLinus Torvalds 3751*1da177e4SLinus Torvalds channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); 3752*1da177e4SLinus Torvalds snd_assert(channel_buf != NULL, return -EIO); 3753*1da177e4SLinus Torvalds memset(channel_buf + pos * 4, 0, count * 4); 3754*1da177e4SLinus Torvalds return count; 3755*1da177e4SLinus Torvalds } 3756*1da177e4SLinus Torvalds 3757*1da177e4SLinus Torvalds static int snd_hdsp_reset(snd_pcm_substream_t *substream) 3758*1da177e4SLinus Torvalds { 3759*1da177e4SLinus Torvalds snd_pcm_runtime_t *runtime = substream->runtime; 3760*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_pcm_substream_chip(substream); 3761*1da177e4SLinus Torvalds snd_pcm_substream_t *other; 3762*1da177e4SLinus Torvalds if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 3763*1da177e4SLinus Torvalds other = hdsp->capture_substream; 3764*1da177e4SLinus Torvalds else 3765*1da177e4SLinus Torvalds other = hdsp->playback_substream; 3766*1da177e4SLinus Torvalds if (hdsp->running) 3767*1da177e4SLinus Torvalds runtime->status->hw_ptr = hdsp_hw_pointer(hdsp); 3768*1da177e4SLinus Torvalds else 3769*1da177e4SLinus Torvalds runtime->status->hw_ptr = 0; 3770*1da177e4SLinus Torvalds if (other) { 3771*1da177e4SLinus Torvalds struct list_head *pos; 3772*1da177e4SLinus Torvalds snd_pcm_substream_t *s; 3773*1da177e4SLinus Torvalds snd_pcm_runtime_t *oruntime = other->runtime; 3774*1da177e4SLinus Torvalds snd_pcm_group_for_each(pos, substream) { 3775*1da177e4SLinus Torvalds s = snd_pcm_group_substream_entry(pos); 3776*1da177e4SLinus Torvalds if (s == other) { 3777*1da177e4SLinus Torvalds oruntime->status->hw_ptr = runtime->status->hw_ptr; 3778*1da177e4SLinus Torvalds break; 3779*1da177e4SLinus Torvalds } 3780*1da177e4SLinus Torvalds } 3781*1da177e4SLinus Torvalds } 3782*1da177e4SLinus Torvalds return 0; 3783*1da177e4SLinus Torvalds } 3784*1da177e4SLinus Torvalds 3785*1da177e4SLinus Torvalds static int snd_hdsp_hw_params(snd_pcm_substream_t *substream, 3786*1da177e4SLinus Torvalds snd_pcm_hw_params_t *params) 3787*1da177e4SLinus Torvalds { 3788*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_pcm_substream_chip(substream); 3789*1da177e4SLinus Torvalds int err; 3790*1da177e4SLinus Torvalds pid_t this_pid; 3791*1da177e4SLinus Torvalds pid_t other_pid; 3792*1da177e4SLinus Torvalds 3793*1da177e4SLinus Torvalds if (hdsp_check_for_iobox (hdsp)) { 3794*1da177e4SLinus Torvalds return -EIO; 3795*1da177e4SLinus Torvalds } 3796*1da177e4SLinus Torvalds 3797*1da177e4SLinus Torvalds if (hdsp_check_for_firmware(hdsp)) { 3798*1da177e4SLinus Torvalds if (hdsp->state & HDSP_FirmwareCached) { 3799*1da177e4SLinus Torvalds if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { 3800*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); 3801*1da177e4SLinus Torvalds } 3802*1da177e4SLinus Torvalds } else { 3803*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); 3804*1da177e4SLinus Torvalds } 3805*1da177e4SLinus Torvalds return -EIO; 3806*1da177e4SLinus Torvalds } 3807*1da177e4SLinus Torvalds 3808*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 3809*1da177e4SLinus Torvalds 3810*1da177e4SLinus Torvalds if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { 3811*1da177e4SLinus Torvalds hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis); 3812*1da177e4SLinus Torvalds hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= hdsp->creg_spdif_stream); 3813*1da177e4SLinus Torvalds this_pid = hdsp->playback_pid; 3814*1da177e4SLinus Torvalds other_pid = hdsp->capture_pid; 3815*1da177e4SLinus Torvalds } else { 3816*1da177e4SLinus Torvalds this_pid = hdsp->capture_pid; 3817*1da177e4SLinus Torvalds other_pid = hdsp->playback_pid; 3818*1da177e4SLinus Torvalds } 3819*1da177e4SLinus Torvalds 3820*1da177e4SLinus Torvalds if ((other_pid > 0) && (this_pid != other_pid)) { 3821*1da177e4SLinus Torvalds 3822*1da177e4SLinus Torvalds /* The other stream is open, and not by the same 3823*1da177e4SLinus Torvalds task as this one. Make sure that the parameters 3824*1da177e4SLinus Torvalds that matter are the same. 3825*1da177e4SLinus Torvalds */ 3826*1da177e4SLinus Torvalds 3827*1da177e4SLinus Torvalds if (params_rate(params) != hdsp->system_sample_rate) { 3828*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 3829*1da177e4SLinus Torvalds _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); 3830*1da177e4SLinus Torvalds return -EBUSY; 3831*1da177e4SLinus Torvalds } 3832*1da177e4SLinus Torvalds 3833*1da177e4SLinus Torvalds if (params_period_size(params) != hdsp->period_bytes / 4) { 3834*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 3835*1da177e4SLinus Torvalds _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); 3836*1da177e4SLinus Torvalds return -EBUSY; 3837*1da177e4SLinus Torvalds } 3838*1da177e4SLinus Torvalds 3839*1da177e4SLinus Torvalds /* We're fine. */ 3840*1da177e4SLinus Torvalds 3841*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 3842*1da177e4SLinus Torvalds return 0; 3843*1da177e4SLinus Torvalds 3844*1da177e4SLinus Torvalds } else { 3845*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 3846*1da177e4SLinus Torvalds } 3847*1da177e4SLinus Torvalds 3848*1da177e4SLinus Torvalds /* how to make sure that the rate matches an externally-set one ? 3849*1da177e4SLinus Torvalds */ 3850*1da177e4SLinus Torvalds 3851*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 3852*1da177e4SLinus Torvalds if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) { 3853*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 3854*1da177e4SLinus Torvalds _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); 3855*1da177e4SLinus Torvalds return err; 3856*1da177e4SLinus Torvalds } else { 3857*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 3858*1da177e4SLinus Torvalds } 3859*1da177e4SLinus Torvalds 3860*1da177e4SLinus Torvalds if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) { 3861*1da177e4SLinus Torvalds _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); 3862*1da177e4SLinus Torvalds return err; 3863*1da177e4SLinus Torvalds } 3864*1da177e4SLinus Torvalds 3865*1da177e4SLinus Torvalds return 0; 3866*1da177e4SLinus Torvalds } 3867*1da177e4SLinus Torvalds 3868*1da177e4SLinus Torvalds static int snd_hdsp_channel_info(snd_pcm_substream_t *substream, 3869*1da177e4SLinus Torvalds snd_pcm_channel_info_t *info) 3870*1da177e4SLinus Torvalds { 3871*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_pcm_substream_chip(substream); 3872*1da177e4SLinus Torvalds int mapped_channel; 3873*1da177e4SLinus Torvalds 3874*1da177e4SLinus Torvalds snd_assert(info->channel < hdsp->max_channels, return -EINVAL); 3875*1da177e4SLinus Torvalds 3876*1da177e4SLinus Torvalds if ((mapped_channel = hdsp->channel_map[info->channel]) < 0) { 3877*1da177e4SLinus Torvalds return -EINVAL; 3878*1da177e4SLinus Torvalds } 3879*1da177e4SLinus Torvalds 3880*1da177e4SLinus Torvalds info->offset = mapped_channel * HDSP_CHANNEL_BUFFER_BYTES; 3881*1da177e4SLinus Torvalds info->first = 0; 3882*1da177e4SLinus Torvalds info->step = 32; 3883*1da177e4SLinus Torvalds return 0; 3884*1da177e4SLinus Torvalds } 3885*1da177e4SLinus Torvalds 3886*1da177e4SLinus Torvalds static int snd_hdsp_ioctl(snd_pcm_substream_t *substream, 3887*1da177e4SLinus Torvalds unsigned int cmd, void *arg) 3888*1da177e4SLinus Torvalds { 3889*1da177e4SLinus Torvalds switch (cmd) { 3890*1da177e4SLinus Torvalds case SNDRV_PCM_IOCTL1_RESET: 3891*1da177e4SLinus Torvalds { 3892*1da177e4SLinus Torvalds return snd_hdsp_reset(substream); 3893*1da177e4SLinus Torvalds } 3894*1da177e4SLinus Torvalds case SNDRV_PCM_IOCTL1_CHANNEL_INFO: 3895*1da177e4SLinus Torvalds { 3896*1da177e4SLinus Torvalds snd_pcm_channel_info_t *info = arg; 3897*1da177e4SLinus Torvalds return snd_hdsp_channel_info(substream, info); 3898*1da177e4SLinus Torvalds } 3899*1da177e4SLinus Torvalds default: 3900*1da177e4SLinus Torvalds break; 3901*1da177e4SLinus Torvalds } 3902*1da177e4SLinus Torvalds 3903*1da177e4SLinus Torvalds return snd_pcm_lib_ioctl(substream, cmd, arg); 3904*1da177e4SLinus Torvalds } 3905*1da177e4SLinus Torvalds 3906*1da177e4SLinus Torvalds static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd) 3907*1da177e4SLinus Torvalds { 3908*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_pcm_substream_chip(substream); 3909*1da177e4SLinus Torvalds snd_pcm_substream_t *other; 3910*1da177e4SLinus Torvalds int running; 3911*1da177e4SLinus Torvalds 3912*1da177e4SLinus Torvalds if (hdsp_check_for_iobox (hdsp)) { 3913*1da177e4SLinus Torvalds return -EIO; 3914*1da177e4SLinus Torvalds } 3915*1da177e4SLinus Torvalds 3916*1da177e4SLinus Torvalds if (hdsp_check_for_firmware(hdsp)) { 3917*1da177e4SLinus Torvalds if (hdsp->state & HDSP_FirmwareCached) { 3918*1da177e4SLinus Torvalds if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { 3919*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); 3920*1da177e4SLinus Torvalds } 3921*1da177e4SLinus Torvalds } else { 3922*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); 3923*1da177e4SLinus Torvalds } 3924*1da177e4SLinus Torvalds return -EIO; 3925*1da177e4SLinus Torvalds } 3926*1da177e4SLinus Torvalds 3927*1da177e4SLinus Torvalds spin_lock(&hdsp->lock); 3928*1da177e4SLinus Torvalds running = hdsp->running; 3929*1da177e4SLinus Torvalds switch (cmd) { 3930*1da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_START: 3931*1da177e4SLinus Torvalds running |= 1 << substream->stream; 3932*1da177e4SLinus Torvalds break; 3933*1da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_STOP: 3934*1da177e4SLinus Torvalds running &= ~(1 << substream->stream); 3935*1da177e4SLinus Torvalds break; 3936*1da177e4SLinus Torvalds default: 3937*1da177e4SLinus Torvalds snd_BUG(); 3938*1da177e4SLinus Torvalds spin_unlock(&hdsp->lock); 3939*1da177e4SLinus Torvalds return -EINVAL; 3940*1da177e4SLinus Torvalds } 3941*1da177e4SLinus Torvalds if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 3942*1da177e4SLinus Torvalds other = hdsp->capture_substream; 3943*1da177e4SLinus Torvalds else 3944*1da177e4SLinus Torvalds other = hdsp->playback_substream; 3945*1da177e4SLinus Torvalds 3946*1da177e4SLinus Torvalds if (other) { 3947*1da177e4SLinus Torvalds struct list_head *pos; 3948*1da177e4SLinus Torvalds snd_pcm_substream_t *s; 3949*1da177e4SLinus Torvalds snd_pcm_group_for_each(pos, substream) { 3950*1da177e4SLinus Torvalds s = snd_pcm_group_substream_entry(pos); 3951*1da177e4SLinus Torvalds if (s == other) { 3952*1da177e4SLinus Torvalds snd_pcm_trigger_done(s, substream); 3953*1da177e4SLinus Torvalds if (cmd == SNDRV_PCM_TRIGGER_START) 3954*1da177e4SLinus Torvalds running |= 1 << s->stream; 3955*1da177e4SLinus Torvalds else 3956*1da177e4SLinus Torvalds running &= ~(1 << s->stream); 3957*1da177e4SLinus Torvalds goto _ok; 3958*1da177e4SLinus Torvalds } 3959*1da177e4SLinus Torvalds } 3960*1da177e4SLinus Torvalds if (cmd == SNDRV_PCM_TRIGGER_START) { 3961*1da177e4SLinus Torvalds if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) && 3962*1da177e4SLinus Torvalds substream->stream == SNDRV_PCM_STREAM_CAPTURE) 3963*1da177e4SLinus Torvalds hdsp_silence_playback(hdsp); 3964*1da177e4SLinus Torvalds } else { 3965*1da177e4SLinus Torvalds if (running && 3966*1da177e4SLinus Torvalds substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 3967*1da177e4SLinus Torvalds hdsp_silence_playback(hdsp); 3968*1da177e4SLinus Torvalds } 3969*1da177e4SLinus Torvalds } else { 3970*1da177e4SLinus Torvalds if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 3971*1da177e4SLinus Torvalds hdsp_silence_playback(hdsp); 3972*1da177e4SLinus Torvalds } 3973*1da177e4SLinus Torvalds _ok: 3974*1da177e4SLinus Torvalds snd_pcm_trigger_done(substream, substream); 3975*1da177e4SLinus Torvalds if (!hdsp->running && running) 3976*1da177e4SLinus Torvalds hdsp_start_audio(hdsp); 3977*1da177e4SLinus Torvalds else if (hdsp->running && !running) 3978*1da177e4SLinus Torvalds hdsp_stop_audio(hdsp); 3979*1da177e4SLinus Torvalds hdsp->running = running; 3980*1da177e4SLinus Torvalds spin_unlock(&hdsp->lock); 3981*1da177e4SLinus Torvalds 3982*1da177e4SLinus Torvalds return 0; 3983*1da177e4SLinus Torvalds } 3984*1da177e4SLinus Torvalds 3985*1da177e4SLinus Torvalds static int snd_hdsp_prepare(snd_pcm_substream_t *substream) 3986*1da177e4SLinus Torvalds { 3987*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_pcm_substream_chip(substream); 3988*1da177e4SLinus Torvalds int result = 0; 3989*1da177e4SLinus Torvalds 3990*1da177e4SLinus Torvalds if (hdsp_check_for_iobox (hdsp)) { 3991*1da177e4SLinus Torvalds return -EIO; 3992*1da177e4SLinus Torvalds } 3993*1da177e4SLinus Torvalds 3994*1da177e4SLinus Torvalds if (hdsp_check_for_firmware(hdsp)) { 3995*1da177e4SLinus Torvalds if (hdsp->state & HDSP_FirmwareCached) { 3996*1da177e4SLinus Torvalds if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { 3997*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); 3998*1da177e4SLinus Torvalds } 3999*1da177e4SLinus Torvalds } else { 4000*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); 4001*1da177e4SLinus Torvalds } 4002*1da177e4SLinus Torvalds return -EIO; 4003*1da177e4SLinus Torvalds } 4004*1da177e4SLinus Torvalds 4005*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 4006*1da177e4SLinus Torvalds if (!hdsp->running) 4007*1da177e4SLinus Torvalds hdsp_reset_hw_pointer(hdsp); 4008*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 4009*1da177e4SLinus Torvalds return result; 4010*1da177e4SLinus Torvalds } 4011*1da177e4SLinus Torvalds 4012*1da177e4SLinus Torvalds static snd_pcm_hardware_t snd_hdsp_playback_subinfo = 4013*1da177e4SLinus Torvalds { 4014*1da177e4SLinus Torvalds .info = (SNDRV_PCM_INFO_MMAP | 4015*1da177e4SLinus Torvalds SNDRV_PCM_INFO_MMAP_VALID | 4016*1da177e4SLinus Torvalds SNDRV_PCM_INFO_NONINTERLEAVED | 4017*1da177e4SLinus Torvalds SNDRV_PCM_INFO_SYNC_START | 4018*1da177e4SLinus Torvalds SNDRV_PCM_INFO_DOUBLE), 4019*1da177e4SLinus Torvalds #ifdef SNDRV_BIG_ENDIAN 4020*1da177e4SLinus Torvalds .formats = SNDRV_PCM_FMTBIT_S32_BE, 4021*1da177e4SLinus Torvalds #else 4022*1da177e4SLinus Torvalds .formats = SNDRV_PCM_FMTBIT_S32_LE, 4023*1da177e4SLinus Torvalds #endif 4024*1da177e4SLinus Torvalds .rates = (SNDRV_PCM_RATE_32000 | 4025*1da177e4SLinus Torvalds SNDRV_PCM_RATE_44100 | 4026*1da177e4SLinus Torvalds SNDRV_PCM_RATE_48000 | 4027*1da177e4SLinus Torvalds SNDRV_PCM_RATE_64000 | 4028*1da177e4SLinus Torvalds SNDRV_PCM_RATE_88200 | 4029*1da177e4SLinus Torvalds SNDRV_PCM_RATE_96000), 4030*1da177e4SLinus Torvalds .rate_min = 32000, 4031*1da177e4SLinus Torvalds .rate_max = 96000, 4032*1da177e4SLinus Torvalds .channels_min = 14, 4033*1da177e4SLinus Torvalds .channels_max = HDSP_MAX_CHANNELS, 4034*1da177e4SLinus Torvalds .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS, 4035*1da177e4SLinus Torvalds .period_bytes_min = (64 * 4) * 10, 4036*1da177e4SLinus Torvalds .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS, 4037*1da177e4SLinus Torvalds .periods_min = 2, 4038*1da177e4SLinus Torvalds .periods_max = 2, 4039*1da177e4SLinus Torvalds .fifo_size = 0 4040*1da177e4SLinus Torvalds }; 4041*1da177e4SLinus Torvalds 4042*1da177e4SLinus Torvalds static snd_pcm_hardware_t snd_hdsp_capture_subinfo = 4043*1da177e4SLinus Torvalds { 4044*1da177e4SLinus Torvalds .info = (SNDRV_PCM_INFO_MMAP | 4045*1da177e4SLinus Torvalds SNDRV_PCM_INFO_MMAP_VALID | 4046*1da177e4SLinus Torvalds SNDRV_PCM_INFO_NONINTERLEAVED | 4047*1da177e4SLinus Torvalds SNDRV_PCM_INFO_SYNC_START), 4048*1da177e4SLinus Torvalds #ifdef SNDRV_BIG_ENDIAN 4049*1da177e4SLinus Torvalds .formats = SNDRV_PCM_FMTBIT_S32_BE, 4050*1da177e4SLinus Torvalds #else 4051*1da177e4SLinus Torvalds .formats = SNDRV_PCM_FMTBIT_S32_LE, 4052*1da177e4SLinus Torvalds #endif 4053*1da177e4SLinus Torvalds .rates = (SNDRV_PCM_RATE_32000 | 4054*1da177e4SLinus Torvalds SNDRV_PCM_RATE_44100 | 4055*1da177e4SLinus Torvalds SNDRV_PCM_RATE_48000 | 4056*1da177e4SLinus Torvalds SNDRV_PCM_RATE_64000 | 4057*1da177e4SLinus Torvalds SNDRV_PCM_RATE_88200 | 4058*1da177e4SLinus Torvalds SNDRV_PCM_RATE_96000), 4059*1da177e4SLinus Torvalds .rate_min = 32000, 4060*1da177e4SLinus Torvalds .rate_max = 96000, 4061*1da177e4SLinus Torvalds .channels_min = 14, 4062*1da177e4SLinus Torvalds .channels_max = HDSP_MAX_CHANNELS, 4063*1da177e4SLinus Torvalds .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS, 4064*1da177e4SLinus Torvalds .period_bytes_min = (64 * 4) * 10, 4065*1da177e4SLinus Torvalds .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS, 4066*1da177e4SLinus Torvalds .periods_min = 2, 4067*1da177e4SLinus Torvalds .periods_max = 2, 4068*1da177e4SLinus Torvalds .fifo_size = 0 4069*1da177e4SLinus Torvalds }; 4070*1da177e4SLinus Torvalds 4071*1da177e4SLinus Torvalds static unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; 4072*1da177e4SLinus Torvalds 4073*1da177e4SLinus Torvalds static snd_pcm_hw_constraint_list_t hdsp_hw_constraints_period_sizes = { 4074*1da177e4SLinus Torvalds .count = ARRAY_SIZE(hdsp_period_sizes), 4075*1da177e4SLinus Torvalds .list = hdsp_period_sizes, 4076*1da177e4SLinus Torvalds .mask = 0 4077*1da177e4SLinus Torvalds }; 4078*1da177e4SLinus Torvalds 4079*1da177e4SLinus Torvalds static unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 }; 4080*1da177e4SLinus Torvalds 4081*1da177e4SLinus Torvalds static snd_pcm_hw_constraint_list_t hdsp_hw_constraints_9632_sample_rates = { 4082*1da177e4SLinus Torvalds .count = ARRAY_SIZE(hdsp_9632_sample_rates), 4083*1da177e4SLinus Torvalds .list = hdsp_9632_sample_rates, 4084*1da177e4SLinus Torvalds .mask = 0 4085*1da177e4SLinus Torvalds }; 4086*1da177e4SLinus Torvalds 4087*1da177e4SLinus Torvalds static int snd_hdsp_hw_rule_in_channels(snd_pcm_hw_params_t *params, 4088*1da177e4SLinus Torvalds snd_pcm_hw_rule_t *rule) 4089*1da177e4SLinus Torvalds { 4090*1da177e4SLinus Torvalds hdsp_t *hdsp = rule->private; 4091*1da177e4SLinus Torvalds snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 4092*1da177e4SLinus Torvalds if (hdsp->io_type == H9632) { 4093*1da177e4SLinus Torvalds unsigned int list[3]; 4094*1da177e4SLinus Torvalds list[0] = hdsp->qs_in_channels; 4095*1da177e4SLinus Torvalds list[1] = hdsp->ds_in_channels; 4096*1da177e4SLinus Torvalds list[2] = hdsp->ss_in_channels; 4097*1da177e4SLinus Torvalds return snd_interval_list(c, 3, list, 0); 4098*1da177e4SLinus Torvalds } else { 4099*1da177e4SLinus Torvalds unsigned int list[2]; 4100*1da177e4SLinus Torvalds list[0] = hdsp->ds_in_channels; 4101*1da177e4SLinus Torvalds list[1] = hdsp->ss_in_channels; 4102*1da177e4SLinus Torvalds return snd_interval_list(c, 2, list, 0); 4103*1da177e4SLinus Torvalds } 4104*1da177e4SLinus Torvalds } 4105*1da177e4SLinus Torvalds 4106*1da177e4SLinus Torvalds static int snd_hdsp_hw_rule_out_channels(snd_pcm_hw_params_t *params, 4107*1da177e4SLinus Torvalds snd_pcm_hw_rule_t *rule) 4108*1da177e4SLinus Torvalds { 4109*1da177e4SLinus Torvalds unsigned int list[3]; 4110*1da177e4SLinus Torvalds hdsp_t *hdsp = rule->private; 4111*1da177e4SLinus Torvalds snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 4112*1da177e4SLinus Torvalds if (hdsp->io_type == H9632) { 4113*1da177e4SLinus Torvalds list[0] = hdsp->qs_out_channels; 4114*1da177e4SLinus Torvalds list[1] = hdsp->ds_out_channels; 4115*1da177e4SLinus Torvalds list[2] = hdsp->ss_out_channels; 4116*1da177e4SLinus Torvalds return snd_interval_list(c, 3, list, 0); 4117*1da177e4SLinus Torvalds } else { 4118*1da177e4SLinus Torvalds list[0] = hdsp->ds_out_channels; 4119*1da177e4SLinus Torvalds list[1] = hdsp->ss_out_channels; 4120*1da177e4SLinus Torvalds } 4121*1da177e4SLinus Torvalds return snd_interval_list(c, 2, list, 0); 4122*1da177e4SLinus Torvalds } 4123*1da177e4SLinus Torvalds 4124*1da177e4SLinus Torvalds static int snd_hdsp_hw_rule_in_channels_rate(snd_pcm_hw_params_t *params, 4125*1da177e4SLinus Torvalds snd_pcm_hw_rule_t *rule) 4126*1da177e4SLinus Torvalds { 4127*1da177e4SLinus Torvalds hdsp_t *hdsp = rule->private; 4128*1da177e4SLinus Torvalds snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 4129*1da177e4SLinus Torvalds snd_interval_t *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 4130*1da177e4SLinus Torvalds if (r->min > 96000 && hdsp->io_type == H9632) { 4131*1da177e4SLinus Torvalds snd_interval_t t = { 4132*1da177e4SLinus Torvalds .min = hdsp->qs_in_channels, 4133*1da177e4SLinus Torvalds .max = hdsp->qs_in_channels, 4134*1da177e4SLinus Torvalds .integer = 1, 4135*1da177e4SLinus Torvalds }; 4136*1da177e4SLinus Torvalds return snd_interval_refine(c, &t); 4137*1da177e4SLinus Torvalds } else if (r->min > 48000 && r->max <= 96000) { 4138*1da177e4SLinus Torvalds snd_interval_t t = { 4139*1da177e4SLinus Torvalds .min = hdsp->ds_in_channels, 4140*1da177e4SLinus Torvalds .max = hdsp->ds_in_channels, 4141*1da177e4SLinus Torvalds .integer = 1, 4142*1da177e4SLinus Torvalds }; 4143*1da177e4SLinus Torvalds return snd_interval_refine(c, &t); 4144*1da177e4SLinus Torvalds } else if (r->max < 64000) { 4145*1da177e4SLinus Torvalds snd_interval_t t = { 4146*1da177e4SLinus Torvalds .min = hdsp->ss_in_channels, 4147*1da177e4SLinus Torvalds .max = hdsp->ss_in_channels, 4148*1da177e4SLinus Torvalds .integer = 1, 4149*1da177e4SLinus Torvalds }; 4150*1da177e4SLinus Torvalds return snd_interval_refine(c, &t); 4151*1da177e4SLinus Torvalds } 4152*1da177e4SLinus Torvalds return 0; 4153*1da177e4SLinus Torvalds } 4154*1da177e4SLinus Torvalds 4155*1da177e4SLinus Torvalds static int snd_hdsp_hw_rule_out_channels_rate(snd_pcm_hw_params_t *params, 4156*1da177e4SLinus Torvalds snd_pcm_hw_rule_t *rule) 4157*1da177e4SLinus Torvalds { 4158*1da177e4SLinus Torvalds hdsp_t *hdsp = rule->private; 4159*1da177e4SLinus Torvalds snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 4160*1da177e4SLinus Torvalds snd_interval_t *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 4161*1da177e4SLinus Torvalds if (r->min > 96000 && hdsp->io_type == H9632) { 4162*1da177e4SLinus Torvalds snd_interval_t t = { 4163*1da177e4SLinus Torvalds .min = hdsp->qs_out_channels, 4164*1da177e4SLinus Torvalds .max = hdsp->qs_out_channels, 4165*1da177e4SLinus Torvalds .integer = 1, 4166*1da177e4SLinus Torvalds }; 4167*1da177e4SLinus Torvalds return snd_interval_refine(c, &t); 4168*1da177e4SLinus Torvalds } else if (r->min > 48000 && r->max <= 96000) { 4169*1da177e4SLinus Torvalds snd_interval_t t = { 4170*1da177e4SLinus Torvalds .min = hdsp->ds_out_channels, 4171*1da177e4SLinus Torvalds .max = hdsp->ds_out_channels, 4172*1da177e4SLinus Torvalds .integer = 1, 4173*1da177e4SLinus Torvalds }; 4174*1da177e4SLinus Torvalds return snd_interval_refine(c, &t); 4175*1da177e4SLinus Torvalds } else if (r->max < 64000) { 4176*1da177e4SLinus Torvalds snd_interval_t t = { 4177*1da177e4SLinus Torvalds .min = hdsp->ss_out_channels, 4178*1da177e4SLinus Torvalds .max = hdsp->ss_out_channels, 4179*1da177e4SLinus Torvalds .integer = 1, 4180*1da177e4SLinus Torvalds }; 4181*1da177e4SLinus Torvalds return snd_interval_refine(c, &t); 4182*1da177e4SLinus Torvalds } 4183*1da177e4SLinus Torvalds return 0; 4184*1da177e4SLinus Torvalds } 4185*1da177e4SLinus Torvalds 4186*1da177e4SLinus Torvalds static int snd_hdsp_hw_rule_rate_out_channels(snd_pcm_hw_params_t *params, 4187*1da177e4SLinus Torvalds snd_pcm_hw_rule_t *rule) 4188*1da177e4SLinus Torvalds { 4189*1da177e4SLinus Torvalds hdsp_t *hdsp = rule->private; 4190*1da177e4SLinus Torvalds snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 4191*1da177e4SLinus Torvalds snd_interval_t *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 4192*1da177e4SLinus Torvalds if (c->min >= hdsp->ss_out_channels) { 4193*1da177e4SLinus Torvalds snd_interval_t t = { 4194*1da177e4SLinus Torvalds .min = 32000, 4195*1da177e4SLinus Torvalds .max = 48000, 4196*1da177e4SLinus Torvalds .integer = 1, 4197*1da177e4SLinus Torvalds }; 4198*1da177e4SLinus Torvalds return snd_interval_refine(r, &t); 4199*1da177e4SLinus Torvalds } else if (c->max <= hdsp->qs_out_channels && hdsp->io_type == H9632) { 4200*1da177e4SLinus Torvalds snd_interval_t t = { 4201*1da177e4SLinus Torvalds .min = 128000, 4202*1da177e4SLinus Torvalds .max = 192000, 4203*1da177e4SLinus Torvalds .integer = 1, 4204*1da177e4SLinus Torvalds }; 4205*1da177e4SLinus Torvalds return snd_interval_refine(r, &t); 4206*1da177e4SLinus Torvalds } else if (c->max <= hdsp->ds_out_channels) { 4207*1da177e4SLinus Torvalds snd_interval_t t = { 4208*1da177e4SLinus Torvalds .min = 64000, 4209*1da177e4SLinus Torvalds .max = 96000, 4210*1da177e4SLinus Torvalds .integer = 1, 4211*1da177e4SLinus Torvalds }; 4212*1da177e4SLinus Torvalds return snd_interval_refine(r, &t); 4213*1da177e4SLinus Torvalds } 4214*1da177e4SLinus Torvalds return 0; 4215*1da177e4SLinus Torvalds } 4216*1da177e4SLinus Torvalds 4217*1da177e4SLinus Torvalds static int snd_hdsp_hw_rule_rate_in_channels(snd_pcm_hw_params_t *params, 4218*1da177e4SLinus Torvalds snd_pcm_hw_rule_t *rule) 4219*1da177e4SLinus Torvalds { 4220*1da177e4SLinus Torvalds hdsp_t *hdsp = rule->private; 4221*1da177e4SLinus Torvalds snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 4222*1da177e4SLinus Torvalds snd_interval_t *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 4223*1da177e4SLinus Torvalds if (c->min >= hdsp->ss_in_channels) { 4224*1da177e4SLinus Torvalds snd_interval_t t = { 4225*1da177e4SLinus Torvalds .min = 32000, 4226*1da177e4SLinus Torvalds .max = 48000, 4227*1da177e4SLinus Torvalds .integer = 1, 4228*1da177e4SLinus Torvalds }; 4229*1da177e4SLinus Torvalds return snd_interval_refine(r, &t); 4230*1da177e4SLinus Torvalds } else if (c->max <= hdsp->qs_in_channels && hdsp->io_type == H9632) { 4231*1da177e4SLinus Torvalds snd_interval_t t = { 4232*1da177e4SLinus Torvalds .min = 128000, 4233*1da177e4SLinus Torvalds .max = 192000, 4234*1da177e4SLinus Torvalds .integer = 1, 4235*1da177e4SLinus Torvalds }; 4236*1da177e4SLinus Torvalds return snd_interval_refine(r, &t); 4237*1da177e4SLinus Torvalds } else if (c->max <= hdsp->ds_in_channels) { 4238*1da177e4SLinus Torvalds snd_interval_t t = { 4239*1da177e4SLinus Torvalds .min = 64000, 4240*1da177e4SLinus Torvalds .max = 96000, 4241*1da177e4SLinus Torvalds .integer = 1, 4242*1da177e4SLinus Torvalds }; 4243*1da177e4SLinus Torvalds return snd_interval_refine(r, &t); 4244*1da177e4SLinus Torvalds } 4245*1da177e4SLinus Torvalds return 0; 4246*1da177e4SLinus Torvalds } 4247*1da177e4SLinus Torvalds 4248*1da177e4SLinus Torvalds static int snd_hdsp_playback_open(snd_pcm_substream_t *substream) 4249*1da177e4SLinus Torvalds { 4250*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_pcm_substream_chip(substream); 4251*1da177e4SLinus Torvalds snd_pcm_runtime_t *runtime = substream->runtime; 4252*1da177e4SLinus Torvalds 4253*1da177e4SLinus Torvalds if (hdsp_check_for_iobox (hdsp)) { 4254*1da177e4SLinus Torvalds return -EIO; 4255*1da177e4SLinus Torvalds } 4256*1da177e4SLinus Torvalds 4257*1da177e4SLinus Torvalds if (hdsp_check_for_firmware(hdsp)) { 4258*1da177e4SLinus Torvalds if (hdsp->state & HDSP_FirmwareCached) { 4259*1da177e4SLinus Torvalds if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { 4260*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); 4261*1da177e4SLinus Torvalds } 4262*1da177e4SLinus Torvalds } else { 4263*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); 4264*1da177e4SLinus Torvalds } 4265*1da177e4SLinus Torvalds return -EIO; 4266*1da177e4SLinus Torvalds } 4267*1da177e4SLinus Torvalds 4268*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 4269*1da177e4SLinus Torvalds 4270*1da177e4SLinus Torvalds snd_pcm_set_sync(substream); 4271*1da177e4SLinus Torvalds 4272*1da177e4SLinus Torvalds runtime->hw = snd_hdsp_playback_subinfo; 4273*1da177e4SLinus Torvalds runtime->dma_area = hdsp->playback_buffer; 4274*1da177e4SLinus Torvalds runtime->dma_bytes = HDSP_DMA_AREA_BYTES; 4275*1da177e4SLinus Torvalds 4276*1da177e4SLinus Torvalds hdsp->playback_pid = current->pid; 4277*1da177e4SLinus Torvalds hdsp->playback_substream = substream; 4278*1da177e4SLinus Torvalds 4279*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 4280*1da177e4SLinus Torvalds 4281*1da177e4SLinus Torvalds snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); 4282*1da177e4SLinus Torvalds snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes); 4283*1da177e4SLinus Torvalds if (hdsp->io_type == H9632) { 4284*1da177e4SLinus Torvalds runtime->hw.channels_min = hdsp->qs_out_channels; 4285*1da177e4SLinus Torvalds runtime->hw.channels_max = hdsp->ss_out_channels; 4286*1da177e4SLinus Torvalds runtime->hw.rate_max = 192000; 4287*1da177e4SLinus Torvalds runtime->hw.rates = SNDRV_PCM_RATE_KNOT; 4288*1da177e4SLinus Torvalds snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates); 4289*1da177e4SLinus Torvalds } 4290*1da177e4SLinus Torvalds 4291*1da177e4SLinus Torvalds snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 4292*1da177e4SLinus Torvalds snd_hdsp_hw_rule_out_channels, hdsp, 4293*1da177e4SLinus Torvalds SNDRV_PCM_HW_PARAM_CHANNELS, -1); 4294*1da177e4SLinus Torvalds snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 4295*1da177e4SLinus Torvalds snd_hdsp_hw_rule_out_channels_rate, hdsp, 4296*1da177e4SLinus Torvalds SNDRV_PCM_HW_PARAM_RATE, -1); 4297*1da177e4SLinus Torvalds snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 4298*1da177e4SLinus Torvalds snd_hdsp_hw_rule_rate_out_channels, hdsp, 4299*1da177e4SLinus Torvalds SNDRV_PCM_HW_PARAM_CHANNELS, -1); 4300*1da177e4SLinus Torvalds 4301*1da177e4SLinus Torvalds hdsp->creg_spdif_stream = hdsp->creg_spdif; 4302*1da177e4SLinus Torvalds hdsp->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; 4303*1da177e4SLinus Torvalds snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE | 4304*1da177e4SLinus Torvalds SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id); 4305*1da177e4SLinus Torvalds return 0; 4306*1da177e4SLinus Torvalds } 4307*1da177e4SLinus Torvalds 4308*1da177e4SLinus Torvalds static int snd_hdsp_playback_release(snd_pcm_substream_t *substream) 4309*1da177e4SLinus Torvalds { 4310*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_pcm_substream_chip(substream); 4311*1da177e4SLinus Torvalds 4312*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 4313*1da177e4SLinus Torvalds 4314*1da177e4SLinus Torvalds hdsp->playback_pid = -1; 4315*1da177e4SLinus Torvalds hdsp->playback_substream = NULL; 4316*1da177e4SLinus Torvalds 4317*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 4318*1da177e4SLinus Torvalds 4319*1da177e4SLinus Torvalds hdsp->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; 4320*1da177e4SLinus Torvalds snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE | 4321*1da177e4SLinus Torvalds SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id); 4322*1da177e4SLinus Torvalds return 0; 4323*1da177e4SLinus Torvalds } 4324*1da177e4SLinus Torvalds 4325*1da177e4SLinus Torvalds 4326*1da177e4SLinus Torvalds static int snd_hdsp_capture_open(snd_pcm_substream_t *substream) 4327*1da177e4SLinus Torvalds { 4328*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_pcm_substream_chip(substream); 4329*1da177e4SLinus Torvalds snd_pcm_runtime_t *runtime = substream->runtime; 4330*1da177e4SLinus Torvalds 4331*1da177e4SLinus Torvalds if (hdsp_check_for_iobox (hdsp)) { 4332*1da177e4SLinus Torvalds return -EIO; 4333*1da177e4SLinus Torvalds } 4334*1da177e4SLinus Torvalds 4335*1da177e4SLinus Torvalds if (hdsp_check_for_firmware(hdsp)) { 4336*1da177e4SLinus Torvalds if (hdsp->state & HDSP_FirmwareCached) { 4337*1da177e4SLinus Torvalds if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { 4338*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); 4339*1da177e4SLinus Torvalds } 4340*1da177e4SLinus Torvalds } else { 4341*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); 4342*1da177e4SLinus Torvalds } 4343*1da177e4SLinus Torvalds return -EIO; 4344*1da177e4SLinus Torvalds } 4345*1da177e4SLinus Torvalds 4346*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 4347*1da177e4SLinus Torvalds 4348*1da177e4SLinus Torvalds snd_pcm_set_sync(substream); 4349*1da177e4SLinus Torvalds 4350*1da177e4SLinus Torvalds runtime->hw = snd_hdsp_capture_subinfo; 4351*1da177e4SLinus Torvalds runtime->dma_area = hdsp->capture_buffer; 4352*1da177e4SLinus Torvalds runtime->dma_bytes = HDSP_DMA_AREA_BYTES; 4353*1da177e4SLinus Torvalds 4354*1da177e4SLinus Torvalds hdsp->capture_pid = current->pid; 4355*1da177e4SLinus Torvalds hdsp->capture_substream = substream; 4356*1da177e4SLinus Torvalds 4357*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 4358*1da177e4SLinus Torvalds 4359*1da177e4SLinus Torvalds snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); 4360*1da177e4SLinus Torvalds snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes); 4361*1da177e4SLinus Torvalds if (hdsp->io_type == H9632) { 4362*1da177e4SLinus Torvalds runtime->hw.channels_min = hdsp->qs_in_channels; 4363*1da177e4SLinus Torvalds runtime->hw.channels_max = hdsp->ss_in_channels; 4364*1da177e4SLinus Torvalds runtime->hw.rate_max = 192000; 4365*1da177e4SLinus Torvalds runtime->hw.rates = SNDRV_PCM_RATE_KNOT; 4366*1da177e4SLinus Torvalds snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates); 4367*1da177e4SLinus Torvalds } 4368*1da177e4SLinus Torvalds snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 4369*1da177e4SLinus Torvalds snd_hdsp_hw_rule_in_channels, hdsp, 4370*1da177e4SLinus Torvalds SNDRV_PCM_HW_PARAM_CHANNELS, -1); 4371*1da177e4SLinus Torvalds snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 4372*1da177e4SLinus Torvalds snd_hdsp_hw_rule_in_channels_rate, hdsp, 4373*1da177e4SLinus Torvalds SNDRV_PCM_HW_PARAM_RATE, -1); 4374*1da177e4SLinus Torvalds snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 4375*1da177e4SLinus Torvalds snd_hdsp_hw_rule_rate_in_channels, hdsp, 4376*1da177e4SLinus Torvalds SNDRV_PCM_HW_PARAM_CHANNELS, -1); 4377*1da177e4SLinus Torvalds return 0; 4378*1da177e4SLinus Torvalds } 4379*1da177e4SLinus Torvalds 4380*1da177e4SLinus Torvalds static int snd_hdsp_capture_release(snd_pcm_substream_t *substream) 4381*1da177e4SLinus Torvalds { 4382*1da177e4SLinus Torvalds hdsp_t *hdsp = snd_pcm_substream_chip(substream); 4383*1da177e4SLinus Torvalds 4384*1da177e4SLinus Torvalds spin_lock_irq(&hdsp->lock); 4385*1da177e4SLinus Torvalds 4386*1da177e4SLinus Torvalds hdsp->capture_pid = -1; 4387*1da177e4SLinus Torvalds hdsp->capture_substream = NULL; 4388*1da177e4SLinus Torvalds 4389*1da177e4SLinus Torvalds spin_unlock_irq(&hdsp->lock); 4390*1da177e4SLinus Torvalds return 0; 4391*1da177e4SLinus Torvalds } 4392*1da177e4SLinus Torvalds 4393*1da177e4SLinus Torvalds static int snd_hdsp_hwdep_dummy_op(snd_hwdep_t *hw, struct file *file) 4394*1da177e4SLinus Torvalds { 4395*1da177e4SLinus Torvalds /* we have nothing to initialize but the call is required */ 4396*1da177e4SLinus Torvalds return 0; 4397*1da177e4SLinus Torvalds } 4398*1da177e4SLinus Torvalds 4399*1da177e4SLinus Torvalds 4400*1da177e4SLinus Torvalds /* helper functions for copying meter values */ 4401*1da177e4SLinus Torvalds static inline int copy_u32_le(void __user *dest, void __iomem *src) 4402*1da177e4SLinus Torvalds { 4403*1da177e4SLinus Torvalds u32 val = readl(src); 4404*1da177e4SLinus Torvalds return copy_to_user(dest, &val, 4); 4405*1da177e4SLinus Torvalds } 4406*1da177e4SLinus Torvalds 4407*1da177e4SLinus Torvalds static inline int copy_u64_le(void __user *dest, void __iomem *src_low, void __iomem *src_high) 4408*1da177e4SLinus Torvalds { 4409*1da177e4SLinus Torvalds u32 rms_low, rms_high; 4410*1da177e4SLinus Torvalds u64 rms; 4411*1da177e4SLinus Torvalds rms_low = readl(src_low); 4412*1da177e4SLinus Torvalds rms_high = readl(src_high); 4413*1da177e4SLinus Torvalds rms = ((u64)rms_high << 32) | rms_low; 4414*1da177e4SLinus Torvalds return copy_to_user(dest, &rms, 8); 4415*1da177e4SLinus Torvalds } 4416*1da177e4SLinus Torvalds 4417*1da177e4SLinus Torvalds static inline int copy_u48_le(void __user *dest, void __iomem *src_low, void __iomem *src_high) 4418*1da177e4SLinus Torvalds { 4419*1da177e4SLinus Torvalds u32 rms_low, rms_high; 4420*1da177e4SLinus Torvalds u64 rms; 4421*1da177e4SLinus Torvalds rms_low = readl(src_low) & 0xffffff00; 4422*1da177e4SLinus Torvalds rms_high = readl(src_high) & 0xffffff00; 4423*1da177e4SLinus Torvalds rms = ((u64)rms_high << 32) | rms_low; 4424*1da177e4SLinus Torvalds return copy_to_user(dest, &rms, 8); 4425*1da177e4SLinus Torvalds } 4426*1da177e4SLinus Torvalds 4427*1da177e4SLinus Torvalds static int hdsp_9652_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms) 4428*1da177e4SLinus Torvalds { 4429*1da177e4SLinus Torvalds int doublespeed = 0; 4430*1da177e4SLinus Torvalds int i, j, channels, ofs; 4431*1da177e4SLinus Torvalds 4432*1da177e4SLinus Torvalds if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus) 4433*1da177e4SLinus Torvalds doublespeed = 1; 4434*1da177e4SLinus Torvalds channels = doublespeed ? 14 : 26; 4435*1da177e4SLinus Torvalds for (i = 0, j = 0; i < 26; ++i) { 4436*1da177e4SLinus Torvalds if (doublespeed && (i & 4)) 4437*1da177e4SLinus Torvalds continue; 4438*1da177e4SLinus Torvalds ofs = HDSP_9652_peakBase - j * 4; 4439*1da177e4SLinus Torvalds if (copy_u32_le(&peak_rms->input_peaks[i], hdsp->iobase + ofs)) 4440*1da177e4SLinus Torvalds return -EFAULT; 4441*1da177e4SLinus Torvalds ofs -= channels * 4; 4442*1da177e4SLinus Torvalds if (copy_u32_le(&peak_rms->playback_peaks[i], hdsp->iobase + ofs)) 4443*1da177e4SLinus Torvalds return -EFAULT; 4444*1da177e4SLinus Torvalds ofs -= channels * 4; 4445*1da177e4SLinus Torvalds if (copy_u32_le(&peak_rms->output_peaks[i], hdsp->iobase + ofs)) 4446*1da177e4SLinus Torvalds return -EFAULT; 4447*1da177e4SLinus Torvalds ofs = HDSP_9652_rmsBase + j * 8; 4448*1da177e4SLinus Torvalds if (copy_u48_le(&peak_rms->input_rms[i], hdsp->iobase + ofs, 4449*1da177e4SLinus Torvalds hdsp->iobase + ofs + 4)) 4450*1da177e4SLinus Torvalds return -EFAULT; 4451*1da177e4SLinus Torvalds ofs += channels * 8; 4452*1da177e4SLinus Torvalds if (copy_u48_le(&peak_rms->playback_rms[i], hdsp->iobase + ofs, 4453*1da177e4SLinus Torvalds hdsp->iobase + ofs + 4)) 4454*1da177e4SLinus Torvalds return -EFAULT; 4455*1da177e4SLinus Torvalds ofs += channels * 8; 4456*1da177e4SLinus Torvalds if (copy_u48_le(&peak_rms->output_rms[i], hdsp->iobase + ofs, 4457*1da177e4SLinus Torvalds hdsp->iobase + ofs + 4)) 4458*1da177e4SLinus Torvalds return -EFAULT; 4459*1da177e4SLinus Torvalds j++; 4460*1da177e4SLinus Torvalds } 4461*1da177e4SLinus Torvalds return 0; 4462*1da177e4SLinus Torvalds } 4463*1da177e4SLinus Torvalds 4464*1da177e4SLinus Torvalds static int hdsp_9632_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms) 4465*1da177e4SLinus Torvalds { 4466*1da177e4SLinus Torvalds int i, j; 4467*1da177e4SLinus Torvalds hdsp_9632_meters_t __iomem *m; 4468*1da177e4SLinus Torvalds int doublespeed = 0; 4469*1da177e4SLinus Torvalds 4470*1da177e4SLinus Torvalds if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus) 4471*1da177e4SLinus Torvalds doublespeed = 1; 4472*1da177e4SLinus Torvalds m = (hdsp_9632_meters_t __iomem *)(hdsp->iobase+HDSP_9632_metersBase); 4473*1da177e4SLinus Torvalds for (i = 0, j = 0; i < 16; ++i, ++j) { 4474*1da177e4SLinus Torvalds if (copy_u32_le(&peak_rms->input_peaks[i], &m->input_peak[j])) 4475*1da177e4SLinus Torvalds return -EFAULT; 4476*1da177e4SLinus Torvalds if (copy_u32_le(&peak_rms->playback_peaks[i], &m->playback_peak[j])) 4477*1da177e4SLinus Torvalds return -EFAULT; 4478*1da177e4SLinus Torvalds if (copy_u32_le(&peak_rms->output_peaks[i], &m->output_peak[j])) 4479*1da177e4SLinus Torvalds return -EFAULT; 4480*1da177e4SLinus Torvalds if (copy_u64_le(&peak_rms->input_rms[i], &m->input_rms_low[j], 4481*1da177e4SLinus Torvalds &m->input_rms_high[j])) 4482*1da177e4SLinus Torvalds return -EFAULT; 4483*1da177e4SLinus Torvalds if (copy_u64_le(&peak_rms->playback_rms[i], &m->playback_rms_low[j], 4484*1da177e4SLinus Torvalds &m->playback_rms_high[j])) 4485*1da177e4SLinus Torvalds return -EFAULT; 4486*1da177e4SLinus Torvalds if (copy_u64_le(&peak_rms->output_rms[i], &m->output_rms_low[j], 4487*1da177e4SLinus Torvalds &m->output_rms_high[j])) 4488*1da177e4SLinus Torvalds return -EFAULT; 4489*1da177e4SLinus Torvalds if (doublespeed && i == 3) i += 4; 4490*1da177e4SLinus Torvalds } 4491*1da177e4SLinus Torvalds return 0; 4492*1da177e4SLinus Torvalds } 4493*1da177e4SLinus Torvalds 4494*1da177e4SLinus Torvalds static int hdsp_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms) 4495*1da177e4SLinus Torvalds { 4496*1da177e4SLinus Torvalds int i; 4497*1da177e4SLinus Torvalds 4498*1da177e4SLinus Torvalds for (i = 0; i < 26; i++) { 4499*1da177e4SLinus Torvalds if (copy_u32_le(&peak_rms->playback_peaks[i], 4500*1da177e4SLinus Torvalds hdsp->iobase + HDSP_playbackPeakLevel + i * 4)) 4501*1da177e4SLinus Torvalds return -EFAULT; 4502*1da177e4SLinus Torvalds if (copy_u32_le(&peak_rms->input_peaks[i], 4503*1da177e4SLinus Torvalds hdsp->iobase + HDSP_inputPeakLevel + i * 4)) 4504*1da177e4SLinus Torvalds return -EFAULT; 4505*1da177e4SLinus Torvalds } 4506*1da177e4SLinus Torvalds for (i = 0; i < 28; i++) { 4507*1da177e4SLinus Torvalds if (copy_u32_le(&peak_rms->output_peaks[i], 4508*1da177e4SLinus Torvalds hdsp->iobase + HDSP_outputPeakLevel + i * 4)) 4509*1da177e4SLinus Torvalds return -EFAULT; 4510*1da177e4SLinus Torvalds } 4511*1da177e4SLinus Torvalds for (i = 0; i < 26; ++i) { 4512*1da177e4SLinus Torvalds if (copy_u64_le(&peak_rms->playback_rms[i], 4513*1da177e4SLinus Torvalds hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4, 4514*1da177e4SLinus Torvalds hdsp->iobase + HDSP_playbackRmsLevel + i * 8)) 4515*1da177e4SLinus Torvalds return -EFAULT; 4516*1da177e4SLinus Torvalds if (copy_u64_le(&peak_rms->input_rms[i], 4517*1da177e4SLinus Torvalds hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4, 4518*1da177e4SLinus Torvalds hdsp->iobase + HDSP_inputRmsLevel + i * 8)) 4519*1da177e4SLinus Torvalds return -EFAULT; 4520*1da177e4SLinus Torvalds } 4521*1da177e4SLinus Torvalds return 0; 4522*1da177e4SLinus Torvalds } 4523*1da177e4SLinus Torvalds 4524*1da177e4SLinus Torvalds static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int cmd, unsigned long arg) 4525*1da177e4SLinus Torvalds { 4526*1da177e4SLinus Torvalds hdsp_t *hdsp = (hdsp_t *)hw->private_data; 4527*1da177e4SLinus Torvalds void __user *argp = (void __user *)arg; 4528*1da177e4SLinus Torvalds 4529*1da177e4SLinus Torvalds switch (cmd) { 4530*1da177e4SLinus Torvalds case SNDRV_HDSP_IOCTL_GET_PEAK_RMS: { 4531*1da177e4SLinus Torvalds hdsp_peak_rms_t __user *peak_rms = (hdsp_peak_rms_t __user *)arg; 4532*1da177e4SLinus Torvalds 4533*1da177e4SLinus Torvalds if (!(hdsp->state & HDSP_FirmwareLoaded)) { 4534*1da177e4SLinus Torvalds snd_printk(KERN_ERR "Hammerfall-DSP: firmware needs to be uploaded to the card.\n"); 4535*1da177e4SLinus Torvalds return -EINVAL; 4536*1da177e4SLinus Torvalds } 4537*1da177e4SLinus Torvalds 4538*1da177e4SLinus Torvalds switch (hdsp->io_type) { 4539*1da177e4SLinus Torvalds case H9652: 4540*1da177e4SLinus Torvalds return hdsp_9652_get_peak(hdsp, peak_rms); 4541*1da177e4SLinus Torvalds case H9632: 4542*1da177e4SLinus Torvalds return hdsp_9632_get_peak(hdsp, peak_rms); 4543*1da177e4SLinus Torvalds default: 4544*1da177e4SLinus Torvalds return hdsp_get_peak(hdsp, peak_rms); 4545*1da177e4SLinus Torvalds } 4546*1da177e4SLinus Torvalds } 4547*1da177e4SLinus Torvalds case SNDRV_HDSP_IOCTL_GET_CONFIG_INFO: { 4548*1da177e4SLinus Torvalds hdsp_config_info_t info; 4549*1da177e4SLinus Torvalds unsigned long flags; 4550*1da177e4SLinus Torvalds int i; 4551*1da177e4SLinus Torvalds 4552*1da177e4SLinus Torvalds if (!(hdsp->state & HDSP_FirmwareLoaded)) { 4553*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: Firmware needs to be uploaded to the card.\n"); 4554*1da177e4SLinus Torvalds return -EINVAL; 4555*1da177e4SLinus Torvalds } 4556*1da177e4SLinus Torvalds spin_lock_irqsave(&hdsp->lock, flags); 4557*1da177e4SLinus Torvalds info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp); 4558*1da177e4SLinus Torvalds info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp); 4559*1da177e4SLinus Torvalds if (hdsp->io_type != H9632) { 4560*1da177e4SLinus Torvalds info.adatsync_sync_check = (unsigned char)hdsp_adatsync_sync_check(hdsp); 4561*1da177e4SLinus Torvalds } 4562*1da177e4SLinus Torvalds info.spdif_sync_check = (unsigned char)hdsp_spdif_sync_check(hdsp); 4563*1da177e4SLinus Torvalds for (i = 0; i < ((hdsp->io_type != Multiface && hdsp->io_type != H9632) ? 3 : 1); ++i) { 4564*1da177e4SLinus Torvalds info.adat_sync_check[i] = (unsigned char)hdsp_adat_sync_check(hdsp, i); 4565*1da177e4SLinus Torvalds } 4566*1da177e4SLinus Torvalds info.spdif_in = (unsigned char)hdsp_spdif_in(hdsp); 4567*1da177e4SLinus Torvalds info.spdif_out = (unsigned char)hdsp_spdif_out(hdsp); 4568*1da177e4SLinus Torvalds info.spdif_professional = (unsigned char)hdsp_spdif_professional(hdsp); 4569*1da177e4SLinus Torvalds info.spdif_emphasis = (unsigned char)hdsp_spdif_emphasis(hdsp); 4570*1da177e4SLinus Torvalds info.spdif_nonaudio = (unsigned char)hdsp_spdif_nonaudio(hdsp); 4571*1da177e4SLinus Torvalds info.spdif_sample_rate = hdsp_spdif_sample_rate(hdsp); 4572*1da177e4SLinus Torvalds info.system_sample_rate = hdsp->system_sample_rate; 4573*1da177e4SLinus Torvalds info.autosync_sample_rate = hdsp_external_sample_rate(hdsp); 4574*1da177e4SLinus Torvalds info.system_clock_mode = (unsigned char)hdsp_system_clock_mode(hdsp); 4575*1da177e4SLinus Torvalds info.clock_source = (unsigned char)hdsp_clock_source(hdsp); 4576*1da177e4SLinus Torvalds info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp); 4577*1da177e4SLinus Torvalds info.line_out = (unsigned char)hdsp_line_out(hdsp); 4578*1da177e4SLinus Torvalds if (hdsp->io_type == H9632) { 4579*1da177e4SLinus Torvalds info.da_gain = (unsigned char)hdsp_da_gain(hdsp); 4580*1da177e4SLinus Torvalds info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp); 4581*1da177e4SLinus Torvalds info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp); 4582*1da177e4SLinus Torvalds info.xlr_breakout_cable = (unsigned char)hdsp_xlr_breakout_cable(hdsp); 4583*1da177e4SLinus Torvalds 4584*1da177e4SLinus Torvalds } 4585*1da177e4SLinus Torvalds if (hdsp->io_type == H9632 || hdsp->io_type == H9652) { 4586*1da177e4SLinus Torvalds info.analog_extension_board = (unsigned char)hdsp_aeb(hdsp); 4587*1da177e4SLinus Torvalds } 4588*1da177e4SLinus Torvalds spin_unlock_irqrestore(&hdsp->lock, flags); 4589*1da177e4SLinus Torvalds if (copy_to_user(argp, &info, sizeof(info))) 4590*1da177e4SLinus Torvalds return -EFAULT; 4591*1da177e4SLinus Torvalds break; 4592*1da177e4SLinus Torvalds } 4593*1da177e4SLinus Torvalds case SNDRV_HDSP_IOCTL_GET_9632_AEB: { 4594*1da177e4SLinus Torvalds hdsp_9632_aeb_t h9632_aeb; 4595*1da177e4SLinus Torvalds 4596*1da177e4SLinus Torvalds if (hdsp->io_type != H9632) return -EINVAL; 4597*1da177e4SLinus Torvalds h9632_aeb.aebi = hdsp->ss_in_channels - H9632_SS_CHANNELS; 4598*1da177e4SLinus Torvalds h9632_aeb.aebo = hdsp->ss_out_channels - H9632_SS_CHANNELS; 4599*1da177e4SLinus Torvalds if (copy_to_user(argp, &h9632_aeb, sizeof(h9632_aeb))) 4600*1da177e4SLinus Torvalds return -EFAULT; 4601*1da177e4SLinus Torvalds break; 4602*1da177e4SLinus Torvalds } 4603*1da177e4SLinus Torvalds case SNDRV_HDSP_IOCTL_GET_VERSION: { 4604*1da177e4SLinus Torvalds hdsp_version_t hdsp_version; 4605*1da177e4SLinus Torvalds int err; 4606*1da177e4SLinus Torvalds 4607*1da177e4SLinus Torvalds if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL; 4608*1da177e4SLinus Torvalds if (hdsp->io_type == Undefined) { 4609*1da177e4SLinus Torvalds if ((err = hdsp_get_iobox_version(hdsp)) < 0) { 4610*1da177e4SLinus Torvalds return err; 4611*1da177e4SLinus Torvalds } 4612*1da177e4SLinus Torvalds } 4613*1da177e4SLinus Torvalds hdsp_version.io_type = hdsp->io_type; 4614*1da177e4SLinus Torvalds hdsp_version.firmware_rev = hdsp->firmware_rev; 4615*1da177e4SLinus Torvalds if ((err = copy_to_user(argp, &hdsp_version, sizeof(hdsp_version)))) { 4616*1da177e4SLinus Torvalds return -EFAULT; 4617*1da177e4SLinus Torvalds } 4618*1da177e4SLinus Torvalds break; 4619*1da177e4SLinus Torvalds } 4620*1da177e4SLinus Torvalds case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: { 4621*1da177e4SLinus Torvalds hdsp_firmware_t __user *firmware; 4622*1da177e4SLinus Torvalds u32 __user *firmware_data; 4623*1da177e4SLinus Torvalds int err; 4624*1da177e4SLinus Torvalds 4625*1da177e4SLinus Torvalds if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL; 4626*1da177e4SLinus Torvalds /* SNDRV_HDSP_IOCTL_GET_VERSION must have been called */ 4627*1da177e4SLinus Torvalds if (hdsp->io_type == Undefined) return -EINVAL; 4628*1da177e4SLinus Torvalds 4629*1da177e4SLinus Torvalds if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded)) 4630*1da177e4SLinus Torvalds return -EBUSY; 4631*1da177e4SLinus Torvalds 4632*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: initializing firmware upload\n"); 4633*1da177e4SLinus Torvalds firmware = (hdsp_firmware_t __user *)argp; 4634*1da177e4SLinus Torvalds 4635*1da177e4SLinus Torvalds if (get_user(firmware_data, &firmware->firmware_data)) { 4636*1da177e4SLinus Torvalds return -EFAULT; 4637*1da177e4SLinus Torvalds } 4638*1da177e4SLinus Torvalds 4639*1da177e4SLinus Torvalds if (hdsp_check_for_iobox (hdsp)) { 4640*1da177e4SLinus Torvalds return -EIO; 4641*1da177e4SLinus Torvalds } 4642*1da177e4SLinus Torvalds 4643*1da177e4SLinus Torvalds if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0) { 4644*1da177e4SLinus Torvalds return -EFAULT; 4645*1da177e4SLinus Torvalds } 4646*1da177e4SLinus Torvalds 4647*1da177e4SLinus Torvalds hdsp->state |= HDSP_FirmwareCached; 4648*1da177e4SLinus Torvalds 4649*1da177e4SLinus Torvalds if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) { 4650*1da177e4SLinus Torvalds return err; 4651*1da177e4SLinus Torvalds } 4652*1da177e4SLinus Torvalds 4653*1da177e4SLinus Torvalds if (!(hdsp->state & HDSP_InitializationComplete)) { 4654*1da177e4SLinus Torvalds if ((err = snd_hdsp_enable_io(hdsp)) < 0) { 4655*1da177e4SLinus Torvalds return err; 4656*1da177e4SLinus Torvalds } 4657*1da177e4SLinus Torvalds 4658*1da177e4SLinus Torvalds snd_hdsp_initialize_channels(hdsp); 4659*1da177e4SLinus Torvalds snd_hdsp_initialize_midi_flush(hdsp); 4660*1da177e4SLinus Torvalds 4661*1da177e4SLinus Torvalds if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { 4662*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: error creating alsa devices\n"); 4663*1da177e4SLinus Torvalds return err; 4664*1da177e4SLinus Torvalds } 4665*1da177e4SLinus Torvalds } 4666*1da177e4SLinus Torvalds break; 4667*1da177e4SLinus Torvalds } 4668*1da177e4SLinus Torvalds case SNDRV_HDSP_IOCTL_GET_MIXER: { 4669*1da177e4SLinus Torvalds hdsp_mixer_t __user *mixer = (hdsp_mixer_t __user *)argp; 4670*1da177e4SLinus Torvalds if (copy_to_user(mixer->matrix, hdsp->mixer_matrix, sizeof(unsigned short)*HDSP_MATRIX_MIXER_SIZE)) 4671*1da177e4SLinus Torvalds return -EFAULT; 4672*1da177e4SLinus Torvalds break; 4673*1da177e4SLinus Torvalds } 4674*1da177e4SLinus Torvalds default: 4675*1da177e4SLinus Torvalds return -EINVAL; 4676*1da177e4SLinus Torvalds } 4677*1da177e4SLinus Torvalds return 0; 4678*1da177e4SLinus Torvalds } 4679*1da177e4SLinus Torvalds 4680*1da177e4SLinus Torvalds static snd_pcm_ops_t snd_hdsp_playback_ops = { 4681*1da177e4SLinus Torvalds .open = snd_hdsp_playback_open, 4682*1da177e4SLinus Torvalds .close = snd_hdsp_playback_release, 4683*1da177e4SLinus Torvalds .ioctl = snd_hdsp_ioctl, 4684*1da177e4SLinus Torvalds .hw_params = snd_hdsp_hw_params, 4685*1da177e4SLinus Torvalds .prepare = snd_hdsp_prepare, 4686*1da177e4SLinus Torvalds .trigger = snd_hdsp_trigger, 4687*1da177e4SLinus Torvalds .pointer = snd_hdsp_hw_pointer, 4688*1da177e4SLinus Torvalds .copy = snd_hdsp_playback_copy, 4689*1da177e4SLinus Torvalds .silence = snd_hdsp_hw_silence, 4690*1da177e4SLinus Torvalds }; 4691*1da177e4SLinus Torvalds 4692*1da177e4SLinus Torvalds static snd_pcm_ops_t snd_hdsp_capture_ops = { 4693*1da177e4SLinus Torvalds .open = snd_hdsp_capture_open, 4694*1da177e4SLinus Torvalds .close = snd_hdsp_capture_release, 4695*1da177e4SLinus Torvalds .ioctl = snd_hdsp_ioctl, 4696*1da177e4SLinus Torvalds .hw_params = snd_hdsp_hw_params, 4697*1da177e4SLinus Torvalds .prepare = snd_hdsp_prepare, 4698*1da177e4SLinus Torvalds .trigger = snd_hdsp_trigger, 4699*1da177e4SLinus Torvalds .pointer = snd_hdsp_hw_pointer, 4700*1da177e4SLinus Torvalds .copy = snd_hdsp_capture_copy, 4701*1da177e4SLinus Torvalds }; 4702*1da177e4SLinus Torvalds 4703*1da177e4SLinus Torvalds static int __devinit snd_hdsp_create_hwdep(snd_card_t *card, 4704*1da177e4SLinus Torvalds hdsp_t *hdsp) 4705*1da177e4SLinus Torvalds { 4706*1da177e4SLinus Torvalds snd_hwdep_t *hw; 4707*1da177e4SLinus Torvalds int err; 4708*1da177e4SLinus Torvalds 4709*1da177e4SLinus Torvalds if ((err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw)) < 0) 4710*1da177e4SLinus Torvalds return err; 4711*1da177e4SLinus Torvalds 4712*1da177e4SLinus Torvalds hdsp->hwdep = hw; 4713*1da177e4SLinus Torvalds hw->private_data = hdsp; 4714*1da177e4SLinus Torvalds strcpy(hw->name, "HDSP hwdep interface"); 4715*1da177e4SLinus Torvalds 4716*1da177e4SLinus Torvalds hw->ops.open = snd_hdsp_hwdep_dummy_op; 4717*1da177e4SLinus Torvalds hw->ops.ioctl = snd_hdsp_hwdep_ioctl; 4718*1da177e4SLinus Torvalds hw->ops.release = snd_hdsp_hwdep_dummy_op; 4719*1da177e4SLinus Torvalds 4720*1da177e4SLinus Torvalds return 0; 4721*1da177e4SLinus Torvalds } 4722*1da177e4SLinus Torvalds 4723*1da177e4SLinus Torvalds static int snd_hdsp_create_pcm(snd_card_t *card, hdsp_t *hdsp) 4724*1da177e4SLinus Torvalds { 4725*1da177e4SLinus Torvalds snd_pcm_t *pcm; 4726*1da177e4SLinus Torvalds int err; 4727*1da177e4SLinus Torvalds 4728*1da177e4SLinus Torvalds if ((err = snd_pcm_new(card, hdsp->card_name, 0, 1, 1, &pcm)) < 0) 4729*1da177e4SLinus Torvalds return err; 4730*1da177e4SLinus Torvalds 4731*1da177e4SLinus Torvalds hdsp->pcm = pcm; 4732*1da177e4SLinus Torvalds pcm->private_data = hdsp; 4733*1da177e4SLinus Torvalds strcpy(pcm->name, hdsp->card_name); 4734*1da177e4SLinus Torvalds 4735*1da177e4SLinus Torvalds snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_hdsp_playback_ops); 4736*1da177e4SLinus Torvalds snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_hdsp_capture_ops); 4737*1da177e4SLinus Torvalds 4738*1da177e4SLinus Torvalds pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; 4739*1da177e4SLinus Torvalds 4740*1da177e4SLinus Torvalds return 0; 4741*1da177e4SLinus Torvalds } 4742*1da177e4SLinus Torvalds 4743*1da177e4SLinus Torvalds static void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp) 4744*1da177e4SLinus Torvalds { 4745*1da177e4SLinus Torvalds hdsp->control2_register |= HDSP_9652_ENABLE_MIXER; 4746*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register); 4747*1da177e4SLinus Torvalds } 4748*1da177e4SLinus Torvalds 4749*1da177e4SLinus Torvalds static int snd_hdsp_enable_io (hdsp_t *hdsp) 4750*1da177e4SLinus Torvalds { 4751*1da177e4SLinus Torvalds int i; 4752*1da177e4SLinus Torvalds 4753*1da177e4SLinus Torvalds if (hdsp_fifo_wait (hdsp, 0, 100)) { 4754*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: enable_io fifo_wait failed\n"); 4755*1da177e4SLinus Torvalds return -EIO; 4756*1da177e4SLinus Torvalds } 4757*1da177e4SLinus Torvalds 4758*1da177e4SLinus Torvalds for (i = 0; i < hdsp->max_channels; ++i) { 4759*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_inputEnable + (4 * i), 1); 4760*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_outputEnable + (4 * i), 1); 4761*1da177e4SLinus Torvalds } 4762*1da177e4SLinus Torvalds 4763*1da177e4SLinus Torvalds return 0; 4764*1da177e4SLinus Torvalds } 4765*1da177e4SLinus Torvalds 4766*1da177e4SLinus Torvalds static void snd_hdsp_initialize_channels(hdsp_t *hdsp) 4767*1da177e4SLinus Torvalds { 4768*1da177e4SLinus Torvalds int status, aebi_channels, aebo_channels; 4769*1da177e4SLinus Torvalds 4770*1da177e4SLinus Torvalds switch (hdsp->io_type) { 4771*1da177e4SLinus Torvalds case Digiface: 4772*1da177e4SLinus Torvalds hdsp->card_name = "RME Hammerfall DSP + Digiface"; 4773*1da177e4SLinus Torvalds hdsp->ss_in_channels = hdsp->ss_out_channels = DIGIFACE_SS_CHANNELS; 4774*1da177e4SLinus Torvalds hdsp->ds_in_channels = hdsp->ds_out_channels = DIGIFACE_DS_CHANNELS; 4775*1da177e4SLinus Torvalds break; 4776*1da177e4SLinus Torvalds 4777*1da177e4SLinus Torvalds case H9652: 4778*1da177e4SLinus Torvalds hdsp->card_name = "RME Hammerfall HDSP 9652"; 4779*1da177e4SLinus Torvalds hdsp->ss_in_channels = hdsp->ss_out_channels = H9652_SS_CHANNELS; 4780*1da177e4SLinus Torvalds hdsp->ds_in_channels = hdsp->ds_out_channels = H9652_DS_CHANNELS; 4781*1da177e4SLinus Torvalds break; 4782*1da177e4SLinus Torvalds 4783*1da177e4SLinus Torvalds case H9632: 4784*1da177e4SLinus Torvalds status = hdsp_read(hdsp, HDSP_statusRegister); 4785*1da177e4SLinus Torvalds /* HDSP_AEBx bits are low when AEB are connected */ 4786*1da177e4SLinus Torvalds aebi_channels = (status & HDSP_AEBI) ? 0 : 4; 4787*1da177e4SLinus Torvalds aebo_channels = (status & HDSP_AEBO) ? 0 : 4; 4788*1da177e4SLinus Torvalds hdsp->card_name = "RME Hammerfall HDSP 9632"; 4789*1da177e4SLinus Torvalds hdsp->ss_in_channels = H9632_SS_CHANNELS+aebi_channels; 4790*1da177e4SLinus Torvalds hdsp->ds_in_channels = H9632_DS_CHANNELS+aebi_channels; 4791*1da177e4SLinus Torvalds hdsp->qs_in_channels = H9632_QS_CHANNELS+aebi_channels; 4792*1da177e4SLinus Torvalds hdsp->ss_out_channels = H9632_SS_CHANNELS+aebo_channels; 4793*1da177e4SLinus Torvalds hdsp->ds_out_channels = H9632_DS_CHANNELS+aebo_channels; 4794*1da177e4SLinus Torvalds hdsp->qs_out_channels = H9632_QS_CHANNELS+aebo_channels; 4795*1da177e4SLinus Torvalds break; 4796*1da177e4SLinus Torvalds 4797*1da177e4SLinus Torvalds case Multiface: 4798*1da177e4SLinus Torvalds hdsp->card_name = "RME Hammerfall DSP + Multiface"; 4799*1da177e4SLinus Torvalds hdsp->ss_in_channels = hdsp->ss_out_channels = MULTIFACE_SS_CHANNELS; 4800*1da177e4SLinus Torvalds hdsp->ds_in_channels = hdsp->ds_out_channels = MULTIFACE_DS_CHANNELS; 4801*1da177e4SLinus Torvalds break; 4802*1da177e4SLinus Torvalds 4803*1da177e4SLinus Torvalds default: 4804*1da177e4SLinus Torvalds /* should never get here */ 4805*1da177e4SLinus Torvalds break; 4806*1da177e4SLinus Torvalds } 4807*1da177e4SLinus Torvalds } 4808*1da177e4SLinus Torvalds 4809*1da177e4SLinus Torvalds static void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp) 4810*1da177e4SLinus Torvalds { 4811*1da177e4SLinus Torvalds snd_hdsp_flush_midi_input (hdsp, 0); 4812*1da177e4SLinus Torvalds snd_hdsp_flush_midi_input (hdsp, 1); 4813*1da177e4SLinus Torvalds } 4814*1da177e4SLinus Torvalds 4815*1da177e4SLinus Torvalds static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp) 4816*1da177e4SLinus Torvalds { 4817*1da177e4SLinus Torvalds int err; 4818*1da177e4SLinus Torvalds 4819*1da177e4SLinus Torvalds if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) { 4820*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: Error creating pcm interface\n"); 4821*1da177e4SLinus Torvalds return err; 4822*1da177e4SLinus Torvalds } 4823*1da177e4SLinus Torvalds 4824*1da177e4SLinus Torvalds 4825*1da177e4SLinus Torvalds if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) { 4826*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: Error creating first midi interface\n"); 4827*1da177e4SLinus Torvalds return err; 4828*1da177e4SLinus Torvalds } 4829*1da177e4SLinus Torvalds 4830*1da177e4SLinus Torvalds if (hdsp->io_type == Digiface || hdsp->io_type == H9652) { 4831*1da177e4SLinus Torvalds if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) { 4832*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: Error creating second midi interface\n"); 4833*1da177e4SLinus Torvalds return err; 4834*1da177e4SLinus Torvalds } 4835*1da177e4SLinus Torvalds } 4836*1da177e4SLinus Torvalds 4837*1da177e4SLinus Torvalds if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) { 4838*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: Error creating ctl interface\n"); 4839*1da177e4SLinus Torvalds return err; 4840*1da177e4SLinus Torvalds } 4841*1da177e4SLinus Torvalds 4842*1da177e4SLinus Torvalds snd_hdsp_proc_init(hdsp); 4843*1da177e4SLinus Torvalds 4844*1da177e4SLinus Torvalds hdsp->system_sample_rate = -1; 4845*1da177e4SLinus Torvalds hdsp->playback_pid = -1; 4846*1da177e4SLinus Torvalds hdsp->capture_pid = -1; 4847*1da177e4SLinus Torvalds hdsp->capture_substream = NULL; 4848*1da177e4SLinus Torvalds hdsp->playback_substream = NULL; 4849*1da177e4SLinus Torvalds 4850*1da177e4SLinus Torvalds if ((err = snd_hdsp_set_defaults(hdsp)) < 0) { 4851*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: Error setting default values\n"); 4852*1da177e4SLinus Torvalds return err; 4853*1da177e4SLinus Torvalds } 4854*1da177e4SLinus Torvalds 4855*1da177e4SLinus Torvalds if (!(hdsp->state & HDSP_InitializationComplete)) { 4856*1da177e4SLinus Torvalds sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, 4857*1da177e4SLinus Torvalds hdsp->port, hdsp->irq); 4858*1da177e4SLinus Torvalds 4859*1da177e4SLinus Torvalds if ((err = snd_card_register(card)) < 0) { 4860*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: error registering card\n"); 4861*1da177e4SLinus Torvalds return err; 4862*1da177e4SLinus Torvalds } 4863*1da177e4SLinus Torvalds hdsp->state |= HDSP_InitializationComplete; 4864*1da177e4SLinus Torvalds } 4865*1da177e4SLinus Torvalds 4866*1da177e4SLinus Torvalds return 0; 4867*1da177e4SLinus Torvalds } 4868*1da177e4SLinus Torvalds 4869*1da177e4SLinus Torvalds #ifdef HDSP_FW_LOADER 4870*1da177e4SLinus Torvalds /* load firmware via hotplug fw loader */ 4871*1da177e4SLinus Torvalds static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp) 4872*1da177e4SLinus Torvalds { 4873*1da177e4SLinus Torvalds const char *fwfile; 4874*1da177e4SLinus Torvalds const struct firmware *fw; 4875*1da177e4SLinus Torvalds int err; 4876*1da177e4SLinus Torvalds 4877*1da177e4SLinus Torvalds if (hdsp->io_type == H9652 || hdsp->io_type == H9632) 4878*1da177e4SLinus Torvalds return 0; 4879*1da177e4SLinus Torvalds if (hdsp->io_type == Undefined) { 4880*1da177e4SLinus Torvalds if ((err = hdsp_get_iobox_version(hdsp)) < 0) 4881*1da177e4SLinus Torvalds return err; 4882*1da177e4SLinus Torvalds if (hdsp->io_type == H9652 || hdsp->io_type == H9632) 4883*1da177e4SLinus Torvalds return 0; 4884*1da177e4SLinus Torvalds } 4885*1da177e4SLinus Torvalds 4886*1da177e4SLinus Torvalds /* caution: max length of firmware filename is 30! */ 4887*1da177e4SLinus Torvalds switch (hdsp->io_type) { 4888*1da177e4SLinus Torvalds case Multiface: 4889*1da177e4SLinus Torvalds if (hdsp->firmware_rev == 0xa) 4890*1da177e4SLinus Torvalds fwfile = "multiface_firmware.bin"; 4891*1da177e4SLinus Torvalds else 4892*1da177e4SLinus Torvalds fwfile = "multiface_firmware_rev11.bin"; 4893*1da177e4SLinus Torvalds break; 4894*1da177e4SLinus Torvalds case Digiface: 4895*1da177e4SLinus Torvalds if (hdsp->firmware_rev == 0xa) 4896*1da177e4SLinus Torvalds fwfile = "digiface_firmware.bin"; 4897*1da177e4SLinus Torvalds else 4898*1da177e4SLinus Torvalds fwfile = "digiface_firmware_rev11.bin"; 4899*1da177e4SLinus Torvalds break; 4900*1da177e4SLinus Torvalds default: 4901*1da177e4SLinus Torvalds snd_printk(KERN_ERR "Hammerfall-DSP: invalid io_type %d\n", hdsp->io_type); 4902*1da177e4SLinus Torvalds return -EINVAL; 4903*1da177e4SLinus Torvalds } 4904*1da177e4SLinus Torvalds 4905*1da177e4SLinus Torvalds if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) { 4906*1da177e4SLinus Torvalds snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile); 4907*1da177e4SLinus Torvalds return -ENOENT; 4908*1da177e4SLinus Torvalds } 4909*1da177e4SLinus Torvalds if (fw->size < sizeof(hdsp->firmware_cache)) { 4910*1da177e4SLinus Torvalds snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n", 4911*1da177e4SLinus Torvalds (int)fw->size, (int)sizeof(hdsp->firmware_cache)); 4912*1da177e4SLinus Torvalds release_firmware(fw); 4913*1da177e4SLinus Torvalds return -EINVAL; 4914*1da177e4SLinus Torvalds } 4915*1da177e4SLinus Torvalds #ifdef SNDRV_BIG_ENDIAN 4916*1da177e4SLinus Torvalds { 4917*1da177e4SLinus Torvalds int i; 4918*1da177e4SLinus Torvalds u32 *src = (u32*)fw->data; 4919*1da177e4SLinus Torvalds for (i = 0; i < ARRAY_SIZE(hdsp->firmware_cache); i++, src++) 4920*1da177e4SLinus Torvalds hdsp->firmware_cache[i] = ((*src & 0x000000ff) << 16) | 4921*1da177e4SLinus Torvalds ((*src & 0x0000ff00) << 8) | 4922*1da177e4SLinus Torvalds ((*src & 0x00ff0000) >> 8) | 4923*1da177e4SLinus Torvalds ((*src & 0xff000000) >> 16); 4924*1da177e4SLinus Torvalds } 4925*1da177e4SLinus Torvalds #else 4926*1da177e4SLinus Torvalds memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache)); 4927*1da177e4SLinus Torvalds #endif 4928*1da177e4SLinus Torvalds release_firmware(fw); 4929*1da177e4SLinus Torvalds 4930*1da177e4SLinus Torvalds hdsp->state |= HDSP_FirmwareCached; 4931*1da177e4SLinus Torvalds 4932*1da177e4SLinus Torvalds if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0) 4933*1da177e4SLinus Torvalds return err; 4934*1da177e4SLinus Torvalds 4935*1da177e4SLinus Torvalds if (!(hdsp->state & HDSP_InitializationComplete)) { 4936*1da177e4SLinus Torvalds if ((err = snd_hdsp_enable_io(hdsp)) < 0) { 4937*1da177e4SLinus Torvalds return err; 4938*1da177e4SLinus Torvalds } 4939*1da177e4SLinus Torvalds 4940*1da177e4SLinus Torvalds if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) { 4941*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: error creating hwdep device\n"); 4942*1da177e4SLinus Torvalds return err; 4943*1da177e4SLinus Torvalds } 4944*1da177e4SLinus Torvalds snd_hdsp_initialize_channels(hdsp); 4945*1da177e4SLinus Torvalds snd_hdsp_initialize_midi_flush(hdsp); 4946*1da177e4SLinus Torvalds if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) { 4947*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: error creating alsa devices\n"); 4948*1da177e4SLinus Torvalds return err; 4949*1da177e4SLinus Torvalds } 4950*1da177e4SLinus Torvalds } 4951*1da177e4SLinus Torvalds return 0; 4952*1da177e4SLinus Torvalds } 4953*1da177e4SLinus Torvalds #endif 4954*1da177e4SLinus Torvalds 4955*1da177e4SLinus Torvalds static int __devinit snd_hdsp_create(snd_card_t *card, 4956*1da177e4SLinus Torvalds hdsp_t *hdsp) 4957*1da177e4SLinus Torvalds { 4958*1da177e4SLinus Torvalds struct pci_dev *pci = hdsp->pci; 4959*1da177e4SLinus Torvalds int err; 4960*1da177e4SLinus Torvalds int is_9652 = 0; 4961*1da177e4SLinus Torvalds int is_9632 = 0; 4962*1da177e4SLinus Torvalds 4963*1da177e4SLinus Torvalds hdsp->irq = -1; 4964*1da177e4SLinus Torvalds hdsp->state = 0; 4965*1da177e4SLinus Torvalds hdsp->midi[0].rmidi = NULL; 4966*1da177e4SLinus Torvalds hdsp->midi[1].rmidi = NULL; 4967*1da177e4SLinus Torvalds hdsp->midi[0].input = NULL; 4968*1da177e4SLinus Torvalds hdsp->midi[1].input = NULL; 4969*1da177e4SLinus Torvalds hdsp->midi[0].output = NULL; 4970*1da177e4SLinus Torvalds hdsp->midi[1].output = NULL; 4971*1da177e4SLinus Torvalds hdsp->midi[0].pending = 0; 4972*1da177e4SLinus Torvalds hdsp->midi[1].pending = 0; 4973*1da177e4SLinus Torvalds spin_lock_init(&hdsp->midi[0].lock); 4974*1da177e4SLinus Torvalds spin_lock_init(&hdsp->midi[1].lock); 4975*1da177e4SLinus Torvalds hdsp->iobase = NULL; 4976*1da177e4SLinus Torvalds hdsp->control_register = 0; 4977*1da177e4SLinus Torvalds hdsp->control2_register = 0; 4978*1da177e4SLinus Torvalds hdsp->io_type = Undefined; 4979*1da177e4SLinus Torvalds hdsp->max_channels = 26; 4980*1da177e4SLinus Torvalds 4981*1da177e4SLinus Torvalds hdsp->card = card; 4982*1da177e4SLinus Torvalds 4983*1da177e4SLinus Torvalds spin_lock_init(&hdsp->lock); 4984*1da177e4SLinus Torvalds 4985*1da177e4SLinus Torvalds tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp); 4986*1da177e4SLinus Torvalds 4987*1da177e4SLinus Torvalds pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev); 4988*1da177e4SLinus Torvalds hdsp->firmware_rev &= 0xff; 4989*1da177e4SLinus Torvalds 4990*1da177e4SLinus Torvalds /* From Martin Bjoernsen : 4991*1da177e4SLinus Torvalds "It is important that the card's latency timer register in 4992*1da177e4SLinus Torvalds the PCI configuration space is set to a value much larger 4993*1da177e4SLinus Torvalds than 0 by the computer's BIOS or the driver. 4994*1da177e4SLinus Torvalds The windows driver always sets this 8 bit register [...] 4995*1da177e4SLinus Torvalds to its maximum 255 to avoid problems with some computers." 4996*1da177e4SLinus Torvalds */ 4997*1da177e4SLinus Torvalds pci_write_config_byte(hdsp->pci, PCI_LATENCY_TIMER, 0xFF); 4998*1da177e4SLinus Torvalds 4999*1da177e4SLinus Torvalds strcpy(card->driver, "H-DSP"); 5000*1da177e4SLinus Torvalds strcpy(card->mixername, "Xilinx FPGA"); 5001*1da177e4SLinus Torvalds 5002*1da177e4SLinus Torvalds if (hdsp->firmware_rev < 0xa) { 5003*1da177e4SLinus Torvalds return -ENODEV; 5004*1da177e4SLinus Torvalds } else if (hdsp->firmware_rev < 0x64) { 5005*1da177e4SLinus Torvalds hdsp->card_name = "RME Hammerfall DSP"; 5006*1da177e4SLinus Torvalds } else if (hdsp->firmware_rev < 0x96) { 5007*1da177e4SLinus Torvalds hdsp->card_name = "RME HDSP 9652"; 5008*1da177e4SLinus Torvalds is_9652 = 1; 5009*1da177e4SLinus Torvalds } else { 5010*1da177e4SLinus Torvalds hdsp->card_name = "RME HDSP 9632"; 5011*1da177e4SLinus Torvalds hdsp->max_channels = 16; 5012*1da177e4SLinus Torvalds is_9632 = 1; 5013*1da177e4SLinus Torvalds } 5014*1da177e4SLinus Torvalds 5015*1da177e4SLinus Torvalds if ((err = pci_enable_device(pci)) < 0) { 5016*1da177e4SLinus Torvalds return err; 5017*1da177e4SLinus Torvalds } 5018*1da177e4SLinus Torvalds 5019*1da177e4SLinus Torvalds pci_set_master(hdsp->pci); 5020*1da177e4SLinus Torvalds 5021*1da177e4SLinus Torvalds if ((err = pci_request_regions(pci, "hdsp")) < 0) 5022*1da177e4SLinus Torvalds return err; 5023*1da177e4SLinus Torvalds hdsp->port = pci_resource_start(pci, 0); 5024*1da177e4SLinus Torvalds if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) { 5025*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1); 5026*1da177e4SLinus Torvalds return -EBUSY; 5027*1da177e4SLinus Torvalds } 5028*1da177e4SLinus Torvalds 5029*1da177e4SLinus Torvalds if (request_irq(pci->irq, snd_hdsp_interrupt, SA_INTERRUPT|SA_SHIRQ, "hdsp", (void *)hdsp)) { 5030*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: unable to use IRQ %d\n", pci->irq); 5031*1da177e4SLinus Torvalds return -EBUSY; 5032*1da177e4SLinus Torvalds } 5033*1da177e4SLinus Torvalds 5034*1da177e4SLinus Torvalds hdsp->irq = pci->irq; 5035*1da177e4SLinus Torvalds hdsp->precise_ptr = 1; 5036*1da177e4SLinus Torvalds hdsp->use_midi_tasklet = 1; 5037*1da177e4SLinus Torvalds 5038*1da177e4SLinus Torvalds if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) { 5039*1da177e4SLinus Torvalds return err; 5040*1da177e4SLinus Torvalds } 5041*1da177e4SLinus Torvalds 5042*1da177e4SLinus Torvalds if (!is_9652 && !is_9632) { 5043*1da177e4SLinus Torvalds /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */ 5044*1da177e4SLinus Torvalds if ((1000 / HZ) < 2000) { 5045*1da177e4SLinus Torvalds set_current_state(TASK_UNINTERRUPTIBLE); 5046*1da177e4SLinus Torvalds schedule_timeout((2000 * HZ + 999) / 1000); 5047*1da177e4SLinus Torvalds } else { 5048*1da177e4SLinus Torvalds mdelay(2000); 5049*1da177e4SLinus Torvalds } 5050*1da177e4SLinus Torvalds 5051*1da177e4SLinus Torvalds if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { 5052*1da177e4SLinus Torvalds #ifdef HDSP_FW_LOADER 5053*1da177e4SLinus Torvalds if ((err = hdsp_request_fw_loader(hdsp)) < 0) { 5054*1da177e4SLinus Torvalds /* we don't fail as this can happen 5055*1da177e4SLinus Torvalds if userspace is not ready for 5056*1da177e4SLinus Torvalds firmware upload 5057*1da177e4SLinus Torvalds */ 5058*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: couldn't get firmware from userspace. try using hdsploader\n"); 5059*1da177e4SLinus Torvalds } else { 5060*1da177e4SLinus Torvalds /* init is complete, we return */ 5061*1da177e4SLinus Torvalds return 0; 5062*1da177e4SLinus Torvalds } 5063*1da177e4SLinus Torvalds #endif 5064*1da177e4SLinus Torvalds /* no iobox connected, we defer initialization */ 5065*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: card initialization pending : waiting for firmware\n"); 5066*1da177e4SLinus Torvalds if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) { 5067*1da177e4SLinus Torvalds return err; 5068*1da177e4SLinus Torvalds } 5069*1da177e4SLinus Torvalds return 0; 5070*1da177e4SLinus Torvalds } else { 5071*1da177e4SLinus Torvalds snd_printk("Hammerfall-DSP: Firmware already present, initializing card.\n"); 5072*1da177e4SLinus Torvalds if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) { 5073*1da177e4SLinus Torvalds hdsp->io_type = Multiface; 5074*1da177e4SLinus Torvalds } else { 5075*1da177e4SLinus Torvalds hdsp->io_type = Digiface; 5076*1da177e4SLinus Torvalds } 5077*1da177e4SLinus Torvalds } 5078*1da177e4SLinus Torvalds } 5079*1da177e4SLinus Torvalds 5080*1da177e4SLinus Torvalds if ((err = snd_hdsp_enable_io(hdsp)) != 0) { 5081*1da177e4SLinus Torvalds return err; 5082*1da177e4SLinus Torvalds } 5083*1da177e4SLinus Torvalds 5084*1da177e4SLinus Torvalds if (is_9652) { 5085*1da177e4SLinus Torvalds hdsp->io_type = H9652; 5086*1da177e4SLinus Torvalds } 5087*1da177e4SLinus Torvalds 5088*1da177e4SLinus Torvalds if (is_9632) { 5089*1da177e4SLinus Torvalds hdsp->io_type = H9632; 5090*1da177e4SLinus Torvalds } 5091*1da177e4SLinus Torvalds 5092*1da177e4SLinus Torvalds if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) { 5093*1da177e4SLinus Torvalds return err; 5094*1da177e4SLinus Torvalds } 5095*1da177e4SLinus Torvalds 5096*1da177e4SLinus Torvalds snd_hdsp_initialize_channels(hdsp); 5097*1da177e4SLinus Torvalds snd_hdsp_initialize_midi_flush(hdsp); 5098*1da177e4SLinus Torvalds 5099*1da177e4SLinus Torvalds hdsp->state |= HDSP_FirmwareLoaded; 5100*1da177e4SLinus Torvalds 5101*1da177e4SLinus Torvalds if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0) { 5102*1da177e4SLinus Torvalds return err; 5103*1da177e4SLinus Torvalds } 5104*1da177e4SLinus Torvalds 5105*1da177e4SLinus Torvalds return 0; 5106*1da177e4SLinus Torvalds } 5107*1da177e4SLinus Torvalds 5108*1da177e4SLinus Torvalds static int snd_hdsp_free(hdsp_t *hdsp) 5109*1da177e4SLinus Torvalds { 5110*1da177e4SLinus Torvalds if (hdsp->port) { 5111*1da177e4SLinus Torvalds /* stop the audio, and cancel all interrupts */ 5112*1da177e4SLinus Torvalds tasklet_kill(&hdsp->midi_tasklet); 5113*1da177e4SLinus Torvalds hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable); 5114*1da177e4SLinus Torvalds hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register); 5115*1da177e4SLinus Torvalds } 5116*1da177e4SLinus Torvalds 5117*1da177e4SLinus Torvalds if (hdsp->irq >= 0) 5118*1da177e4SLinus Torvalds free_irq(hdsp->irq, (void *)hdsp); 5119*1da177e4SLinus Torvalds 5120*1da177e4SLinus Torvalds snd_hdsp_free_buffers(hdsp); 5121*1da177e4SLinus Torvalds 5122*1da177e4SLinus Torvalds if (hdsp->iobase) 5123*1da177e4SLinus Torvalds iounmap(hdsp->iobase); 5124*1da177e4SLinus Torvalds 5125*1da177e4SLinus Torvalds if (hdsp->port) 5126*1da177e4SLinus Torvalds pci_release_regions(hdsp->pci); 5127*1da177e4SLinus Torvalds 5128*1da177e4SLinus Torvalds pci_disable_device(hdsp->pci); 5129*1da177e4SLinus Torvalds return 0; 5130*1da177e4SLinus Torvalds } 5131*1da177e4SLinus Torvalds 5132*1da177e4SLinus Torvalds static void snd_hdsp_card_free(snd_card_t *card) 5133*1da177e4SLinus Torvalds { 5134*1da177e4SLinus Torvalds hdsp_t *hdsp = (hdsp_t *) card->private_data; 5135*1da177e4SLinus Torvalds 5136*1da177e4SLinus Torvalds if (hdsp) 5137*1da177e4SLinus Torvalds snd_hdsp_free(hdsp); 5138*1da177e4SLinus Torvalds } 5139*1da177e4SLinus Torvalds 5140*1da177e4SLinus Torvalds static int __devinit snd_hdsp_probe(struct pci_dev *pci, 5141*1da177e4SLinus Torvalds const struct pci_device_id *pci_id) 5142*1da177e4SLinus Torvalds { 5143*1da177e4SLinus Torvalds static int dev; 5144*1da177e4SLinus Torvalds hdsp_t *hdsp; 5145*1da177e4SLinus Torvalds snd_card_t *card; 5146*1da177e4SLinus Torvalds int err; 5147*1da177e4SLinus Torvalds 5148*1da177e4SLinus Torvalds if (dev >= SNDRV_CARDS) 5149*1da177e4SLinus Torvalds return -ENODEV; 5150*1da177e4SLinus Torvalds if (!enable[dev]) { 5151*1da177e4SLinus Torvalds dev++; 5152*1da177e4SLinus Torvalds return -ENOENT; 5153*1da177e4SLinus Torvalds } 5154*1da177e4SLinus Torvalds 5155*1da177e4SLinus Torvalds if (!(card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(hdsp_t)))) 5156*1da177e4SLinus Torvalds return -ENOMEM; 5157*1da177e4SLinus Torvalds 5158*1da177e4SLinus Torvalds hdsp = (hdsp_t *) card->private_data; 5159*1da177e4SLinus Torvalds card->private_free = snd_hdsp_card_free; 5160*1da177e4SLinus Torvalds hdsp->dev = dev; 5161*1da177e4SLinus Torvalds hdsp->pci = pci; 5162*1da177e4SLinus Torvalds snd_card_set_dev(card, &pci->dev); 5163*1da177e4SLinus Torvalds 5164*1da177e4SLinus Torvalds if ((err = snd_hdsp_create(card, hdsp)) < 0) { 5165*1da177e4SLinus Torvalds snd_card_free(card); 5166*1da177e4SLinus Torvalds return err; 5167*1da177e4SLinus Torvalds } 5168*1da177e4SLinus Torvalds 5169*1da177e4SLinus Torvalds strcpy(card->shortname, "Hammerfall DSP"); 5170*1da177e4SLinus Torvalds sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name, 5171*1da177e4SLinus Torvalds hdsp->port, hdsp->irq); 5172*1da177e4SLinus Torvalds 5173*1da177e4SLinus Torvalds if ((err = snd_card_register(card)) < 0) { 5174*1da177e4SLinus Torvalds snd_card_free(card); 5175*1da177e4SLinus Torvalds return err; 5176*1da177e4SLinus Torvalds } 5177*1da177e4SLinus Torvalds pci_set_drvdata(pci, card); 5178*1da177e4SLinus Torvalds dev++; 5179*1da177e4SLinus Torvalds return 0; 5180*1da177e4SLinus Torvalds } 5181*1da177e4SLinus Torvalds 5182*1da177e4SLinus Torvalds static void __devexit snd_hdsp_remove(struct pci_dev *pci) 5183*1da177e4SLinus Torvalds { 5184*1da177e4SLinus Torvalds snd_card_free(pci_get_drvdata(pci)); 5185*1da177e4SLinus Torvalds pci_set_drvdata(pci, NULL); 5186*1da177e4SLinus Torvalds } 5187*1da177e4SLinus Torvalds 5188*1da177e4SLinus Torvalds static struct pci_driver driver = { 5189*1da177e4SLinus Torvalds .name = "RME Hammerfall DSP", 5190*1da177e4SLinus Torvalds .id_table = snd_hdsp_ids, 5191*1da177e4SLinus Torvalds .probe = snd_hdsp_probe, 5192*1da177e4SLinus Torvalds .remove = __devexit_p(snd_hdsp_remove), 5193*1da177e4SLinus Torvalds }; 5194*1da177e4SLinus Torvalds 5195*1da177e4SLinus Torvalds static int __init alsa_card_hdsp_init(void) 5196*1da177e4SLinus Torvalds { 5197*1da177e4SLinus Torvalds return pci_module_init(&driver); 5198*1da177e4SLinus Torvalds } 5199*1da177e4SLinus Torvalds 5200*1da177e4SLinus Torvalds static void __exit alsa_card_hdsp_exit(void) 5201*1da177e4SLinus Torvalds { 5202*1da177e4SLinus Torvalds pci_unregister_driver(&driver); 5203*1da177e4SLinus Torvalds } 5204*1da177e4SLinus Torvalds 5205*1da177e4SLinus Torvalds module_init(alsa_card_hdsp_init) 5206*1da177e4SLinus Torvalds module_exit(alsa_card_hdsp_exit) 5207