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