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