blob: b044dea3c8157e73cbeff3ad4f021f17db6296cd [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * ALSA driver for RME Hammerfall DSP audio interface(s)
3 *
4 * Copyright (c) 2002 Paul Davis
5 * Marcus Andersson
6 * Thomas Charbonnel
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/init.h>
25#include <linux/delay.h>
26#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/pci.h>
28#include <linux/firmware.h>
Paul Gortmaker65a77212011-07-15 13:13:37 -040029#include <linux/module.h>
Takashi Iwai3f7440a2009-06-05 17:40:04 +020030#include <linux/math64.h>
Takashi Iwai82329322012-11-22 21:19:18 +010031#include <linux/vmalloc.h>
Takashi Iwai6cbbfe12015-01-28 16:49:33 +010032#include <linux/io.h>
Gustavo A. R. Silvaf2f87232018-12-18 11:18:34 -060033#include <linux/nospec.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
35#include <sound/core.h>
36#include <sound/control.h>
37#include <sound/pcm.h>
38#include <sound/info.h>
39#include <sound/asoundef.h>
40#include <sound/rawmidi.h>
41#include <sound/hwdep.h>
42#include <sound/initval.h>
43#include <sound/hdsp.h>
44
45#include <asm/byteorder.h>
46#include <asm/current.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
48static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
49static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
Rusty Russella67ff6a2011-12-15 13:49:36 +103050static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
52module_param_array(index, int, NULL, 0444);
53MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface.");
54module_param_array(id, charp, NULL, 0444);
55MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface.");
56module_param_array(enable, bool, NULL, 0444);
57MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards.");
58MODULE_AUTHOR("Paul Davis <paul@linuxaudiosystems.com>, Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
59MODULE_DESCRIPTION("RME Hammerfall DSP");
60MODULE_LICENSE("GPL");
61MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
62 "{RME HDSP-9652},"
63 "{RME HDSP-9632}}");
Florian Faber28b26e12010-12-01 12:14:47 +010064MODULE_FIRMWARE("rpm_firmware.bin");
Clemens Ladisch7e0af292007-05-03 17:59:54 +020065MODULE_FIRMWARE("multiface_firmware.bin");
66MODULE_FIRMWARE("multiface_firmware_rev11.bin");
67MODULE_FIRMWARE("digiface_firmware.bin");
68MODULE_FIRMWARE("digiface_firmware_rev11.bin");
Linus Torvalds1da177e2005-04-16 15:20:36 -070069
70#define HDSP_MAX_CHANNELS 26
71#define HDSP_MAX_DS_CHANNELS 14
72#define HDSP_MAX_QS_CHANNELS 8
73#define DIGIFACE_SS_CHANNELS 26
74#define DIGIFACE_DS_CHANNELS 14
75#define MULTIFACE_SS_CHANNELS 18
76#define MULTIFACE_DS_CHANNELS 14
77#define H9652_SS_CHANNELS 26
78#define H9652_DS_CHANNELS 14
79/* This does not include possible Analog Extension Boards
80 AEBs are detected at card initialization
81*/
82#define H9632_SS_CHANNELS 12
83#define H9632_DS_CHANNELS 8
84#define H9632_QS_CHANNELS 4
Florian Faber28b26e12010-12-01 12:14:47 +010085#define RPM_CHANNELS 6
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87/* Write registers. These are defined as byte-offsets from the iobase value.
88 */
89#define HDSP_resetPointer 0
Remy Brunod7923b22006-10-17 12:41:56 +020090#define HDSP_freqReg 0
Linus Torvalds1da177e2005-04-16 15:20:36 -070091#define HDSP_outputBufferAddress 32
92#define HDSP_inputBufferAddress 36
93#define HDSP_controlRegister 64
94#define HDSP_interruptConfirmation 96
95#define HDSP_outputEnable 128
96#define HDSP_control2Reg 256
97#define HDSP_midiDataOut0 352
98#define HDSP_midiDataOut1 356
99#define HDSP_fifoData 368
100#define HDSP_inputEnable 384
101
102/* Read registers. These are defined as byte-offsets from the iobase value
103 */
104
105#define HDSP_statusRegister 0
106#define HDSP_timecode 128
107#define HDSP_status2Register 192
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108#define HDSP_midiDataIn0 360
109#define HDSP_midiDataIn1 364
110#define HDSP_midiStatusOut0 384
111#define HDSP_midiStatusOut1 388
112#define HDSP_midiStatusIn0 392
113#define HDSP_midiStatusIn1 396
114#define HDSP_fifoStatus 400
115
116/* the meters are regular i/o-mapped registers, but offset
117 considerably from the rest. the peak registers are reset
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100118 when read; the least-significant 4 bits are full-scale counters;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 the actual peak value is in the most-significant 24 bits.
120*/
121
122#define HDSP_playbackPeakLevel 4096 /* 26 * 32 bit values */
123#define HDSP_inputPeakLevel 4224 /* 26 * 32 bit values */
124#define HDSP_outputPeakLevel 4352 /* (26+2) * 32 bit values */
125#define HDSP_playbackRmsLevel 4612 /* 26 * 64 bit values */
126#define HDSP_inputRmsLevel 4868 /* 26 * 64 bit values */
127
128
129/* This is for H9652 cards
130 Peak values are read downward from the base
131 Rms values are read upward
132 There are rms values for the outputs too
133 26*3 values are read in ss mode
134 14*3 in ds mode, with no gap between values
135*/
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100136#define HDSP_9652_peakBase 7164
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137#define HDSP_9652_rmsBase 4096
138
139/* c.f. the hdsp_9632_meters_t struct */
140#define HDSP_9632_metersBase 4096
141
142#define HDSP_IO_EXTENT 7168
143
144/* control2 register bits */
145
146#define HDSP_TMS 0x01
147#define HDSP_TCK 0x02
148#define HDSP_TDI 0x04
149#define HDSP_JTAG 0x08
150#define HDSP_PWDN 0x10
151#define HDSP_PROGRAM 0x020
152#define HDSP_CONFIG_MODE_0 0x040
153#define HDSP_CONFIG_MODE_1 0x080
Adrian Knotha3466862011-10-27 21:57:53 +0200154#define HDSP_VERSION_BIT (0x100 | HDSP_S_LOAD)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155#define HDSP_BIGENDIAN_MODE 0x200
156#define HDSP_RD_MULTIPLE 0x400
157#define HDSP_9652_ENABLE_MIXER 0x800
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100158#define HDSP_S200 0x800
159#define HDSP_S300 (0x100 | HDSP_S200) /* dummy, purpose of 0x100 unknown */
160#define HDSP_CYCLIC_MODE 0x1000
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161#define HDSP_TDO 0x10000000
162
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100163#define HDSP_S_PROGRAM (HDSP_CYCLIC_MODE|HDSP_PROGRAM|HDSP_CONFIG_MODE_0)
164#define HDSP_S_LOAD (HDSP_CYCLIC_MODE|HDSP_PROGRAM|HDSP_CONFIG_MODE_1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165
166/* Control Register bits */
167
168#define HDSP_Start (1<<0) /* start engine */
169#define HDSP_Latency0 (1<<1) /* buffer size = 2^n where n is defined by Latency{2,1,0} */
170#define HDSP_Latency1 (1<<2) /* [ see above ] */
171#define HDSP_Latency2 (1<<3) /* [ see above ] */
172#define HDSP_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */
173#define HDSP_AudioInterruptEnable (1<<5) /* what do you think ? */
174#define HDSP_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz/176.4kHz 1=48kHz/96kHz/192kHz */
175#define HDSP_Frequency1 (1<<7) /* 0=32kHz/64kHz/128kHz */
176#define HDSP_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
177#define HDSP_SPDIFProfessional (1<<9) /* 0=consumer, 1=professional */
178#define HDSP_SPDIFEmphasis (1<<10) /* 0=none, 1=on */
179#define HDSP_SPDIFNonAudio (1<<11) /* 0=off, 1=on */
180#define HDSP_SPDIFOpticalOut (1<<12) /* 1=use 1st ADAT connector for SPDIF, 0=do not */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100181#define HDSP_SyncRef2 (1<<13)
182#define HDSP_SPDIFInputSelect0 (1<<14)
183#define HDSP_SPDIFInputSelect1 (1<<15)
184#define HDSP_SyncRef0 (1<<16)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185#define HDSP_SyncRef1 (1<<17)
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100186#define HDSP_AnalogExtensionBoard (1<<18) /* For H9632 cards */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187#define HDSP_XLRBreakoutCable (1<<20) /* For H9632 cards */
188#define HDSP_Midi0InterruptEnable (1<<22)
189#define HDSP_Midi1InterruptEnable (1<<23)
190#define HDSP_LineOut (1<<24)
191#define HDSP_ADGain0 (1<<25) /* From here : H9632 specific */
192#define HDSP_ADGain1 (1<<26)
193#define HDSP_DAGain0 (1<<27)
194#define HDSP_DAGain1 (1<<28)
195#define HDSP_PhoneGain0 (1<<29)
196#define HDSP_PhoneGain1 (1<<30)
197#define HDSP_QuadSpeed (1<<31)
198
Florian Faber28b26e12010-12-01 12:14:47 +0100199/* RPM uses some of the registers for special purposes */
200#define HDSP_RPM_Inp12 0x04A00
201#define HDSP_RPM_Inp12_Phon_6dB 0x00800 /* Dolby */
202#define HDSP_RPM_Inp12_Phon_0dB 0x00000 /* .. */
203#define HDSP_RPM_Inp12_Phon_n6dB 0x04000 /* inp_0 */
204#define HDSP_RPM_Inp12_Line_0dB 0x04200 /* Dolby+PRO */
205#define HDSP_RPM_Inp12_Line_n6dB 0x00200 /* PRO */
206
207#define HDSP_RPM_Inp34 0x32000
208#define HDSP_RPM_Inp34_Phon_6dB 0x20000 /* SyncRef1 */
209#define HDSP_RPM_Inp34_Phon_0dB 0x00000 /* .. */
210#define HDSP_RPM_Inp34_Phon_n6dB 0x02000 /* SyncRef2 */
211#define HDSP_RPM_Inp34_Line_0dB 0x30000 /* SyncRef1+SyncRef0 */
212#define HDSP_RPM_Inp34_Line_n6dB 0x10000 /* SyncRef0 */
213
214#define HDSP_RPM_Bypass 0x01000
215
216#define HDSP_RPM_Disconnect 0x00001
217
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218#define HDSP_ADGainMask (HDSP_ADGain0|HDSP_ADGain1)
219#define HDSP_ADGainMinus10dBV HDSP_ADGainMask
220#define HDSP_ADGainPlus4dBu (HDSP_ADGain0)
221#define HDSP_ADGainLowGain 0
222
223#define HDSP_DAGainMask (HDSP_DAGain0|HDSP_DAGain1)
224#define HDSP_DAGainHighGain HDSP_DAGainMask
225#define HDSP_DAGainPlus4dBu (HDSP_DAGain0)
226#define HDSP_DAGainMinus10dBV 0
227
228#define HDSP_PhoneGainMask (HDSP_PhoneGain0|HDSP_PhoneGain1)
229#define HDSP_PhoneGain0dB HDSP_PhoneGainMask
230#define HDSP_PhoneGainMinus6dB (HDSP_PhoneGain0)
231#define HDSP_PhoneGainMinus12dB 0
232
233#define HDSP_LatencyMask (HDSP_Latency0|HDSP_Latency1|HDSP_Latency2)
234#define HDSP_FrequencyMask (HDSP_Frequency0|HDSP_Frequency1|HDSP_DoubleSpeed|HDSP_QuadSpeed)
235
236#define HDSP_SPDIFInputMask (HDSP_SPDIFInputSelect0|HDSP_SPDIFInputSelect1)
237#define HDSP_SPDIFInputADAT1 0
238#define HDSP_SPDIFInputCoaxial (HDSP_SPDIFInputSelect0)
239#define HDSP_SPDIFInputCdrom (HDSP_SPDIFInputSelect1)
240#define HDSP_SPDIFInputAES (HDSP_SPDIFInputSelect0|HDSP_SPDIFInputSelect1)
241
242#define HDSP_SyncRefMask (HDSP_SyncRef0|HDSP_SyncRef1|HDSP_SyncRef2)
243#define HDSP_SyncRef_ADAT1 0
244#define HDSP_SyncRef_ADAT2 (HDSP_SyncRef0)
245#define HDSP_SyncRef_ADAT3 (HDSP_SyncRef1)
246#define HDSP_SyncRef_SPDIF (HDSP_SyncRef0|HDSP_SyncRef1)
247#define HDSP_SyncRef_WORD (HDSP_SyncRef2)
248#define HDSP_SyncRef_ADAT_SYNC (HDSP_SyncRef0|HDSP_SyncRef2)
249
250/* Sample Clock Sources */
251
252#define HDSP_CLOCK_SOURCE_AUTOSYNC 0
253#define HDSP_CLOCK_SOURCE_INTERNAL_32KHZ 1
254#define HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ 2
255#define HDSP_CLOCK_SOURCE_INTERNAL_48KHZ 3
256#define HDSP_CLOCK_SOURCE_INTERNAL_64KHZ 4
257#define HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ 5
258#define HDSP_CLOCK_SOURCE_INTERNAL_96KHZ 6
259#define HDSP_CLOCK_SOURCE_INTERNAL_128KHZ 7
260#define HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ 8
261#define HDSP_CLOCK_SOURCE_INTERNAL_192KHZ 9
262
263/* Preferred sync reference choices - used by "pref_sync_ref" control switch */
264
265#define HDSP_SYNC_FROM_WORD 0
266#define HDSP_SYNC_FROM_SPDIF 1
267#define HDSP_SYNC_FROM_ADAT1 2
268#define HDSP_SYNC_FROM_ADAT_SYNC 3
269#define HDSP_SYNC_FROM_ADAT2 4
270#define HDSP_SYNC_FROM_ADAT3 5
271
272/* SyncCheck status */
273
274#define HDSP_SYNC_CHECK_NO_LOCK 0
275#define HDSP_SYNC_CHECK_LOCK 1
276#define HDSP_SYNC_CHECK_SYNC 2
277
278/* AutoSync references - used by "autosync_ref" control switch */
279
280#define HDSP_AUTOSYNC_FROM_WORD 0
281#define HDSP_AUTOSYNC_FROM_ADAT_SYNC 1
282#define HDSP_AUTOSYNC_FROM_SPDIF 2
283#define HDSP_AUTOSYNC_FROM_NONE 3
284#define HDSP_AUTOSYNC_FROM_ADAT1 4
285#define HDSP_AUTOSYNC_FROM_ADAT2 5
286#define HDSP_AUTOSYNC_FROM_ADAT3 6
287
288/* Possible sources of S/PDIF input */
289
290#define HDSP_SPDIFIN_OPTICAL 0 /* optical (ADAT1) */
291#define HDSP_SPDIFIN_COAXIAL 1 /* coaxial (RCA) */
292#define HDSP_SPDIFIN_INTERNAL 2 /* internal (CDROM) */
293#define HDSP_SPDIFIN_AES 3 /* xlr for H9632 (AES)*/
294
295#define HDSP_Frequency32KHz HDSP_Frequency0
296#define HDSP_Frequency44_1KHz HDSP_Frequency1
297#define HDSP_Frequency48KHz (HDSP_Frequency1|HDSP_Frequency0)
298#define HDSP_Frequency64KHz (HDSP_DoubleSpeed|HDSP_Frequency0)
299#define HDSP_Frequency88_2KHz (HDSP_DoubleSpeed|HDSP_Frequency1)
300#define HDSP_Frequency96KHz (HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0)
301/* For H9632 cards */
302#define HDSP_Frequency128KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency0)
303#define HDSP_Frequency176_4KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1)
304#define HDSP_Frequency192KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0)
Julian Cablee4b60882007-03-19 11:44:40 +0100305/* RME says n = 104857600000000, but in the windows MADI driver, I see:
306 return 104857600000000 / rate; // 100 MHz
307 return 110100480000000 / rate; // 105 MHz
308*/
309#define DDS_NUMERATOR 104857600000000ULL; /* = 2^20 * 10^8 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310
311#define hdsp_encode_latency(x) (((x)<<1) & HDSP_LatencyMask)
312#define hdsp_decode_latency(x) (((x) & HDSP_LatencyMask)>>1)
313
314#define hdsp_encode_spdif_in(x) (((x)&0x3)<<14)
315#define hdsp_decode_spdif_in(x) (((x)>>14)&0x3)
316
317/* Status Register bits */
318
319#define HDSP_audioIRQPending (1<<0)
320#define HDSP_Lock2 (1<<1) /* this is for Digiface and H9652 */
321#define HDSP_spdifFrequency3 HDSP_Lock2 /* this is for H9632 only */
322#define HDSP_Lock1 (1<<2)
323#define HDSP_Lock0 (1<<3)
324#define HDSP_SPDIFSync (1<<4)
325#define HDSP_TimecodeLock (1<<5)
326#define HDSP_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
327#define HDSP_Sync2 (1<<16)
328#define HDSP_Sync1 (1<<17)
329#define HDSP_Sync0 (1<<18)
330#define HDSP_DoubleSpeedStatus (1<<19)
331#define HDSP_ConfigError (1<<20)
332#define HDSP_DllError (1<<21)
333#define HDSP_spdifFrequency0 (1<<22)
334#define HDSP_spdifFrequency1 (1<<23)
335#define HDSP_spdifFrequency2 (1<<24)
336#define HDSP_SPDIFErrorFlag (1<<25)
337#define HDSP_BufferID (1<<26)
338#define HDSP_TimecodeSync (1<<27)
339#define HDSP_AEBO (1<<28) /* H9632 specific Analog Extension Boards */
340#define HDSP_AEBI (1<<29) /* 0 = present, 1 = absent */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100341#define HDSP_midi0IRQPending (1<<30)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342#define HDSP_midi1IRQPending (1<<31)
343
344#define HDSP_spdifFrequencyMask (HDSP_spdifFrequency0|HDSP_spdifFrequency1|HDSP_spdifFrequency2)
Remy Bruno47ba97f2008-02-22 17:57:02 +0100345#define HDSP_spdifFrequencyMask_9632 (HDSP_spdifFrequency0|\
346 HDSP_spdifFrequency1|\
347 HDSP_spdifFrequency2|\
348 HDSP_spdifFrequency3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
350#define HDSP_spdifFrequency32KHz (HDSP_spdifFrequency0)
351#define HDSP_spdifFrequency44_1KHz (HDSP_spdifFrequency1)
352#define HDSP_spdifFrequency48KHz (HDSP_spdifFrequency0|HDSP_spdifFrequency1)
353
354#define HDSP_spdifFrequency64KHz (HDSP_spdifFrequency2)
355#define HDSP_spdifFrequency88_2KHz (HDSP_spdifFrequency0|HDSP_spdifFrequency2)
356#define HDSP_spdifFrequency96KHz (HDSP_spdifFrequency2|HDSP_spdifFrequency1)
357
358/* This is for H9632 cards */
Remy Bruno47ba97f2008-02-22 17:57:02 +0100359#define HDSP_spdifFrequency128KHz (HDSP_spdifFrequency0|\
360 HDSP_spdifFrequency1|\
361 HDSP_spdifFrequency2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362#define HDSP_spdifFrequency176_4KHz HDSP_spdifFrequency3
363#define HDSP_spdifFrequency192KHz (HDSP_spdifFrequency3|HDSP_spdifFrequency0)
364
365/* Status2 Register bits */
366
367#define HDSP_version0 (1<<0)
368#define HDSP_version1 (1<<1)
369#define HDSP_version2 (1<<2)
370#define HDSP_wc_lock (1<<3)
371#define HDSP_wc_sync (1<<4)
372#define HDSP_inp_freq0 (1<<5)
373#define HDSP_inp_freq1 (1<<6)
374#define HDSP_inp_freq2 (1<<7)
375#define HDSP_SelSyncRef0 (1<<8)
376#define HDSP_SelSyncRef1 (1<<9)
377#define HDSP_SelSyncRef2 (1<<10)
378
379#define HDSP_wc_valid (HDSP_wc_lock|HDSP_wc_sync)
380
381#define HDSP_systemFrequencyMask (HDSP_inp_freq0|HDSP_inp_freq1|HDSP_inp_freq2)
382#define HDSP_systemFrequency32 (HDSP_inp_freq0)
383#define HDSP_systemFrequency44_1 (HDSP_inp_freq1)
384#define HDSP_systemFrequency48 (HDSP_inp_freq0|HDSP_inp_freq1)
385#define HDSP_systemFrequency64 (HDSP_inp_freq2)
386#define HDSP_systemFrequency88_2 (HDSP_inp_freq0|HDSP_inp_freq2)
387#define HDSP_systemFrequency96 (HDSP_inp_freq1|HDSP_inp_freq2)
388/* FIXME : more values for 9632 cards ? */
389
390#define HDSP_SelSyncRefMask (HDSP_SelSyncRef0|HDSP_SelSyncRef1|HDSP_SelSyncRef2)
391#define HDSP_SelSyncRef_ADAT1 0
392#define HDSP_SelSyncRef_ADAT2 (HDSP_SelSyncRef0)
393#define HDSP_SelSyncRef_ADAT3 (HDSP_SelSyncRef1)
394#define HDSP_SelSyncRef_SPDIF (HDSP_SelSyncRef0|HDSP_SelSyncRef1)
395#define HDSP_SelSyncRef_WORD (HDSP_SelSyncRef2)
396#define HDSP_SelSyncRef_ADAT_SYNC (HDSP_SelSyncRef0|HDSP_SelSyncRef2)
397
398/* Card state flags */
399
400#define HDSP_InitializationComplete (1<<0)
401#define HDSP_FirmwareLoaded (1<<1)
402#define HDSP_FirmwareCached (1<<2)
403
404/* FIFO wait times, defined in terms of 1/10ths of msecs */
405
406#define HDSP_LONG_WAIT 5000
407#define HDSP_SHORT_WAIT 30
408
409#define UNITY_GAIN 32768
410#define MINUS_INFINITY_GAIN 0
411
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412/* the size of a substream (1 mono data stream) */
413
414#define HDSP_CHANNEL_BUFFER_SAMPLES (16*1024)
415#define HDSP_CHANNEL_BUFFER_BYTES (4*HDSP_CHANNEL_BUFFER_SAMPLES)
416
417/* the size of the area we need to allocate for DMA transfers. the
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100418 size is the same regardless of the number of channels - the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 Multiface still uses the same memory area.
420
421 Note that we allocate 1 more channel than is apparently needed
422 because the h/w seems to write 1 byte beyond the end of the last
423 page. Sigh.
424*/
425
426#define HDSP_DMA_AREA_BYTES ((HDSP_MAX_CHANNELS+1) * HDSP_CHANNEL_BUFFER_BYTES)
427#define HDSP_DMA_AREA_KILOBYTES (HDSP_DMA_AREA_BYTES/1024)
428
Takashi Iwai90caaef2012-11-22 16:55:11 +0100429#define HDSP_FIRMWARE_SIZE (24413 * 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
Takashi Iwai55e957d2005-11-17 14:52:13 +0100431struct hdsp_9632_meters {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 u32 input_peak[16];
433 u32 playback_peak[16];
434 u32 output_peak[16];
435 u32 xxx_peak[16];
436 u32 padding[64];
437 u32 input_rms_low[16];
438 u32 playback_rms_low[16];
439 u32 output_rms_low[16];
440 u32 xxx_rms_low[16];
441 u32 input_rms_high[16];
442 u32 playback_rms_high[16];
443 u32 output_rms_high[16];
444 u32 xxx_rms_high[16];
445};
446
Takashi Iwai55e957d2005-11-17 14:52:13 +0100447struct hdsp_midi {
448 struct hdsp *hdsp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 int id;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100450 struct snd_rawmidi *rmidi;
451 struct snd_rawmidi_substream *input;
452 struct snd_rawmidi_substream *output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 char istimer; /* timer in use */
454 struct timer_list timer;
455 spinlock_t lock;
456 int pending;
457};
458
Takashi Iwai55e957d2005-11-17 14:52:13 +0100459struct hdsp {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 spinlock_t lock;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100461 struct snd_pcm_substream *capture_substream;
462 struct snd_pcm_substream *playback_substream;
463 struct hdsp_midi midi[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 struct tasklet_struct midi_tasklet;
465 int use_midi_tasklet;
466 int precise_ptr;
467 u32 control_register; /* cached value */
468 u32 control2_register; /* cached value */
469 u32 creg_spdif;
470 u32 creg_spdif_stream;
Takashi Iwaie3ea4d82005-07-04 18:12:39 +0200471 int clock_source_locked;
Florian Faber28b26e12010-12-01 12:14:47 +0100472 char *card_name; /* digiface/multiface/rpm */
Takashi Iwai55e957d2005-11-17 14:52:13 +0100473 enum HDSP_IO_Type io_type; /* ditto, but for code use */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 unsigned short firmware_rev;
475 unsigned short state; /* stores state bits */
Takashi Iwai90caaef2012-11-22 16:55:11 +0100476 const struct firmware *firmware;
477 u32 *fw_uploaded;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 size_t period_bytes; /* guess what this is */
479 unsigned char max_channels;
480 unsigned char qs_in_channels; /* quad speed mode for H9632 */
481 unsigned char ds_in_channels;
482 unsigned char ss_in_channels; /* different for multiface/digiface */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100483 unsigned char qs_out_channels;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 unsigned char ds_out_channels;
485 unsigned char ss_out_channels;
486
487 struct snd_dma_buffer capture_dma_buf;
488 struct snd_dma_buffer playback_dma_buf;
489 unsigned char *capture_buffer; /* suitably aligned address */
490 unsigned char *playback_buffer; /* suitably aligned address */
491
492 pid_t capture_pid;
493 pid_t playback_pid;
494 int running;
495 int system_sample_rate;
496 char *channel_map;
497 int dev;
498 int irq;
499 unsigned long port;
500 void __iomem *iobase;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100501 struct snd_card *card;
502 struct snd_pcm *pcm;
503 struct snd_hwdep *hwdep;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 struct pci_dev *pci;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100505 struct snd_kcontrol *spdif_ctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE];
Remy Brunod7923b22006-10-17 12:41:56 +0200507 unsigned int dds_value; /* last value written to freq register */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508};
509
510/* These tables map the ALSA channels 1..N to the channels that we
511 need to use in order to find the relevant channel buffer. RME
512 refer to this kind of mapping as between "the ADAT channel and
513 the DMA channel." We index it using the logical audio channel,
514 and the value is the DMA channel (i.e. channel buffer number)
515 where the data for that channel can be read/written from/to.
516*/
517
518static char channel_map_df_ss[HDSP_MAX_CHANNELS] = {
519 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
520 18, 19, 20, 21, 22, 23, 24, 25
521};
522
523static char channel_map_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */
524 /* Analog */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100525 0, 1, 2, 3, 4, 5, 6, 7,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 /* ADAT 2 */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100527 16, 17, 18, 19, 20, 21, 22, 23,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 /* SPDIF */
529 24, 25,
530 -1, -1, -1, -1, -1, -1, -1, -1
531};
532
533static char channel_map_ds[HDSP_MAX_CHANNELS] = {
534 /* ADAT channels are remapped */
535 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23,
536 /* channels 12 and 13 are S/PDIF */
537 24, 25,
538 /* others don't exist */
539 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
540};
541
542static char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = {
543 /* ADAT channels */
544 0, 1, 2, 3, 4, 5, 6, 7,
545 /* SPDIF */
546 8, 9,
547 /* Analog */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100548 10, 11,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 /* AO4S-192 and AI4S-192 extension boards */
550 12, 13, 14, 15,
551 /* others don't exist */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100552 -1, -1, -1, -1, -1, -1, -1, -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 -1, -1
554};
555
556static char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = {
557 /* ADAT */
558 1, 3, 5, 7,
559 /* SPDIF */
560 8, 9,
561 /* Analog */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100562 10, 11,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 /* AO4S-192 and AI4S-192 extension boards */
564 12, 13, 14, 15,
565 /* others don't exist */
566 -1, -1, -1, -1, -1, -1, -1, -1,
567 -1, -1, -1, -1, -1, -1
568};
569
570static char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = {
571 /* ADAT is disabled in this mode */
572 /* SPDIF */
573 8, 9,
574 /* Analog */
575 10, 11,
576 /* AO4S-192 and AI4S-192 extension boards */
577 12, 13, 14, 15,
578 /* others don't exist */
579 -1, -1, -1, -1, -1, -1, -1, -1,
580 -1, -1, -1, -1, -1, -1, -1, -1,
581 -1, -1
582};
583
584static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
585{
586 dmab->dev.type = SNDRV_DMA_TYPE_DEV;
587 dmab->dev.dev = snd_dma_pci_data(pci);
Takashi Iwaib6a96912005-05-30 18:27:03 +0200588 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
589 size, dmab) < 0)
590 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 return 0;
592}
593
594static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
595{
Takashi Iwai47d98c02014-01-08 16:12:25 +0100596 if (dmab->area)
597 snd_dma_free_pages(dmab);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598}
599
600
Benoit Taine9baa3c32014-08-08 15:56:03 +0200601static const struct pci_device_id snd_hdsp_ids[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 {
603 .vendor = PCI_VENDOR_ID_XILINX,
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100604 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 .subvendor = PCI_ANY_ID,
606 .subdevice = PCI_ANY_ID,
607 }, /* RME Hammerfall-DSP */
608 { 0, },
609};
610
611MODULE_DEVICE_TABLE(pci, snd_hdsp_ids);
612
613/* prototypes */
Takashi Iwai55e957d2005-11-17 14:52:13 +0100614static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp);
615static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp);
616static int snd_hdsp_enable_io (struct hdsp *hdsp);
617static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp);
618static void snd_hdsp_initialize_channels (struct hdsp *hdsp);
619static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout);
620static int hdsp_autosync_ref(struct hdsp *hdsp);
621static int snd_hdsp_set_defaults(struct hdsp *hdsp);
622static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623
Takashi Iwai55e957d2005-11-17 14:52:13 +0100624static int hdsp_playback_to_output_key (struct hdsp *hdsp, int in, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625{
Remy Brunoa3a68c82007-08-31 12:33:54 +0200626 switch (hdsp->io_type) {
627 case Multiface:
628 case Digiface:
Florian Faber28b26e12010-12-01 12:14:47 +0100629 case RPM:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 default:
Andreas Degert192b8e32008-01-16 15:59:48 +0100631 if (hdsp->firmware_rev == 0xa)
632 return (64 * out) + (32 + (in));
633 else
634 return (52 * out) + (26 + (in));
Remy Brunoa3a68c82007-08-31 12:33:54 +0200635 case H9632:
636 return (32 * out) + (16 + (in));
637 case H9652:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 return (52 * out) + (26 + (in));
639 }
640}
641
Takashi Iwai55e957d2005-11-17 14:52:13 +0100642static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643{
Remy Brunoa3a68c82007-08-31 12:33:54 +0200644 switch (hdsp->io_type) {
645 case Multiface:
646 case Digiface:
Florian Faber28b26e12010-12-01 12:14:47 +0100647 case RPM:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 default:
Andreas Degert192b8e32008-01-16 15:59:48 +0100649 if (hdsp->firmware_rev == 0xa)
650 return (64 * out) + in;
651 else
652 return (52 * out) + in;
Remy Brunoa3a68c82007-08-31 12:33:54 +0200653 case H9632:
654 return (32 * out) + in;
655 case H9652:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 return (52 * out) + in;
657 }
658}
659
Takashi Iwai55e957d2005-11-17 14:52:13 +0100660static void hdsp_write(struct hdsp *hdsp, int reg, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661{
662 writel(val, hdsp->iobase + reg);
663}
664
Takashi Iwai55e957d2005-11-17 14:52:13 +0100665static unsigned int hdsp_read(struct hdsp *hdsp, int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666{
667 return readl (hdsp->iobase + reg);
668}
669
Takashi Iwai55e957d2005-11-17 14:52:13 +0100670static int hdsp_check_for_iobox (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671{
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100672 int i;
673
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100675 for (i = 0; i < 500; i++) {
676 if (0 == (hdsp_read(hdsp, HDSP_statusRegister) &
677 HDSP_ConfigError)) {
678 if (i) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100679 dev_dbg(hdsp->card->dev,
680 "IO box found after %d ms\n",
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100681 (20 * i));
682 }
683 return 0;
684 }
685 msleep(20);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 }
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100687 dev_err(hdsp->card->dev, "no IO box connected!\n");
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100688 hdsp->state &= ~HDSP_FirmwareLoaded;
689 return -EIO;
Tim Blechmanne588ed82009-02-20 19:30:35 +0100690}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
Tim Blechmanne588ed82009-02-20 19:30:35 +0100692static int hdsp_wait_for_iobox(struct hdsp *hdsp, unsigned int loops,
693 unsigned int delay)
694{
695 unsigned int i;
696
697 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
698 return 0;
699
700 for (i = 0; i != loops; ++i) {
701 if (hdsp_read(hdsp, HDSP_statusRegister) & HDSP_ConfigError)
702 msleep(delay);
703 else {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100704 dev_dbg(hdsp->card->dev, "iobox found after %ums!\n",
Tim Blechmanne588ed82009-02-20 19:30:35 +0100705 i * delay);
706 return 0;
707 }
708 }
709
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100710 dev_info(hdsp->card->dev, "no IO box connected!\n");
Tim Blechmanne588ed82009-02-20 19:30:35 +0100711 hdsp->state &= ~HDSP_FirmwareLoaded;
712 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713}
714
Takashi Iwai55e957d2005-11-17 14:52:13 +0100715static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
717 int i;
718 unsigned long flags;
Takashi Iwai90caaef2012-11-22 16:55:11 +0100719 const u32 *cache;
720
721 if (hdsp->fw_uploaded)
722 cache = hdsp->fw_uploaded;
723 else {
724 if (!hdsp->firmware)
725 return -ENODEV;
726 cache = (u32 *)hdsp->firmware->data;
727 if (!cache)
728 return -ENODEV;
729 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730
731 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100732
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100733 dev_info(hdsp->card->dev, "loading firmware\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734
735 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM);
736 hdsp_write (hdsp, HDSP_fifoData, 0);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100737
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100739 dev_info(hdsp->card->dev,
740 "timeout waiting for download preparation\n");
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100741 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 return -EIO;
743 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100744
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100746
Takashi Iwai90caaef2012-11-22 16:55:11 +0100747 for (i = 0; i < HDSP_FIRMWARE_SIZE / 4; ++i) {
748 hdsp_write(hdsp, HDSP_fifoData, cache[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100750 dev_info(hdsp->card->dev,
751 "timeout during firmware loading\n");
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100752 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 return -EIO;
754 }
755 }
756
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100757 hdsp_fifo_wait(hdsp, 3, HDSP_LONG_WAIT);
758 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200);
759
Takashi Iwaib0b98112005-10-20 18:29:58 +0200760 ssleep(3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761#ifdef SNDRV_BIG_ENDIAN
762 hdsp->control2_register = HDSP_BIGENDIAN_MODE;
763#else
764 hdsp->control2_register = 0;
765#endif
766 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100767 dev_info(hdsp->card->dev, "finished firmware loading\n");
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100768
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 }
770 if (hdsp->state & HDSP_InitializationComplete) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100771 dev_info(hdsp->card->dev,
772 "firmware loaded from cache, restoring defaults\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 spin_lock_irqsave(&hdsp->lock, flags);
774 snd_hdsp_set_defaults(hdsp);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100775 spin_unlock_irqrestore(&hdsp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100777
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 hdsp->state |= HDSP_FirmwareLoaded;
779
780 return 0;
781}
782
Takashi Iwai55e957d2005-11-17 14:52:13 +0100783static int hdsp_get_iobox_version (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784{
785 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100786
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100787 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD);
788 hdsp_write(hdsp, HDSP_fifoData, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100790 if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) {
791 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S300);
Florian Faber28b26e12010-12-01 12:14:47 +0100792 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100793 }
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100794
795 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200 | HDSP_PROGRAM);
796 hdsp_write (hdsp, HDSP_fifoData, 0);
797 if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) {
798 hdsp->io_type = Multiface;
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100799 dev_info(hdsp->card->dev, "Multiface found\n");
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100800 return 0;
801 }
802
803 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD);
804 hdsp_write(hdsp, HDSP_fifoData, 0);
805 if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) == 0) {
806 hdsp->io_type = Digiface;
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100807 dev_info(hdsp->card->dev, "Digiface found\n");
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100808 return 0;
809 }
810
811 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S300);
812 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD);
813 hdsp_write(hdsp, HDSP_fifoData, 0);
814 if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) == 0) {
815 hdsp->io_type = Multiface;
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100816 dev_info(hdsp->card->dev, "Multiface found\n");
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100817 return 0;
818 }
819
820 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S300);
821 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD);
822 hdsp_write(hdsp, HDSP_fifoData, 0);
823 if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) {
824 hdsp->io_type = Multiface;
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100825 dev_info(hdsp->card->dev, "Multiface found\n");
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100826 return 0;
827 }
828
829 hdsp->io_type = RPM;
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100830 dev_info(hdsp->card->dev, "RPM found\n");
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100831 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 } else {
833 /* firmware was already loaded, get iobox type */
Florian Faber28b26e12010-12-01 12:14:47 +0100834 if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version2)
835 hdsp->io_type = RPM;
836 else if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 hdsp->io_type = Multiface;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200838 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 hdsp->io_type = Digiface;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 }
841 return 0;
842}
843
844
Takashi Iwai92eed662008-02-22 18:35:56 +0100845static int hdsp_request_fw_loader(struct hdsp *hdsp);
Takashi Iwai311e70a2006-09-06 12:13:37 +0200846
847static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848{
Takashi Iwai311e70a2006-09-06 12:13:37 +0200849 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
850 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 hdsp->state &= ~HDSP_FirmwareLoaded;
Takashi Iwai311e70a2006-09-06 12:13:37 +0200853 if (! load_on_demand)
Takashi Iwaib0b98112005-10-20 18:29:58 +0200854 return -EIO;
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100855 dev_err(hdsp->card->dev, "firmware not present.\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +0200856 /* try to load firmware */
Takashi Iwai311e70a2006-09-06 12:13:37 +0200857 if (! (hdsp->state & HDSP_FirmwareCached)) {
Takashi Iwai311e70a2006-09-06 12:13:37 +0200858 if (! hdsp_request_fw_loader(hdsp))
859 return 0;
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100860 dev_err(hdsp->card->dev,
861 "No firmware loaded nor cached, please upload firmware.\n");
Takashi Iwai311e70a2006-09-06 12:13:37 +0200862 return -EIO;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200863 }
Takashi Iwai311e70a2006-09-06 12:13:37 +0200864 if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100865 dev_err(hdsp->card->dev,
866 "Firmware loading from cache failed, please upload manually.\n");
Takashi Iwai311e70a2006-09-06 12:13:37 +0200867 return -EIO;
868 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 }
870 return 0;
871}
872
873
Takashi Iwai55e957d2005-11-17 14:52:13 +0100874static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout)
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100875{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 int i;
877
878 /* the fifoStatus registers reports on how many words
879 are available in the command FIFO.
880 */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100881
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 for (i = 0; i < timeout; i++) {
883
884 if ((int)(hdsp_read (hdsp, HDSP_fifoStatus) & 0xff) <= count)
885 return 0;
886
887 /* not very friendly, but we only do this during a firmware
888 load and changing the mixer, so we just put up with it.
889 */
890
891 udelay (100);
892 }
893
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100894 dev_warn(hdsp->card->dev,
895 "wait for FIFO status <= %d failed after %d iterations\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 count, timeout);
897 return -1;
898}
899
Takashi Iwai55e957d2005-11-17 14:52:13 +0100900static int hdsp_read_gain (struct hdsp *hdsp, unsigned int addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901{
Takashi Iwaib0b98112005-10-20 18:29:58 +0200902 if (addr >= HDSP_MATRIX_MIXER_SIZE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200904
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 return hdsp->mixer_matrix[addr];
906}
907
Takashi Iwai55e957d2005-11-17 14:52:13 +0100908static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909{
910 unsigned int ad;
911
912 if (addr >= HDSP_MATRIX_MIXER_SIZE)
913 return -1;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100914
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) {
916
917 /* from martin bjornsen:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100918
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 "You can only write dwords to the
920 mixer memory which contain two
921 mixer values in the low and high
922 word. So if you want to change
923 value 0 you have to read value 1
924 from the cache and write both to
925 the first dword in the mixer
926 memory."
927 */
928
Takashi Iwaib0b98112005-10-20 18:29:58 +0200929 if (hdsp->io_type == H9632 && addr >= 512)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931
Takashi Iwaib0b98112005-10-20 18:29:58 +0200932 if (hdsp->io_type == H9652 && addr >= 1352)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934
935 hdsp->mixer_matrix[addr] = data;
936
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100937
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 /* `addr' addresses a 16-bit wide address, but
939 the address space accessed via hdsp_write
940 uses byte offsets. put another way, addr
941 varies from 0 to 1351, but to access the
942 corresponding memory location, we need
943 to access 0 to 2703 ...
944 */
945 ad = addr/2;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100946
947 hdsp_write (hdsp, 4096 + (ad*4),
948 (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) +
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 hdsp->mixer_matrix[addr&0x7fe]);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100950
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 return 0;
952
953 } else {
954
955 ad = (addr << 16) + data;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100956
Takashi Iwaib0b98112005-10-20 18:29:58 +0200957 if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959
960 hdsp_write (hdsp, HDSP_fifoData, ad);
961 hdsp->mixer_matrix[addr] = data;
962
963 }
964
965 return 0;
966}
967
Takashi Iwai55e957d2005-11-17 14:52:13 +0100968static int snd_hdsp_use_is_exclusive(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969{
970 unsigned long flags;
971 int ret = 1;
972
973 spin_lock_irqsave(&hdsp->lock, flags);
974 if ((hdsp->playback_pid != hdsp->capture_pid) &&
Takashi Iwaib0b98112005-10-20 18:29:58 +0200975 (hdsp->playback_pid >= 0) && (hdsp->capture_pid >= 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 spin_unlock_irqrestore(&hdsp->lock, flags);
978 return ret;
979}
980
Takashi Iwai55e957d2005-11-17 14:52:13 +0100981static int hdsp_spdif_sample_rate(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982{
983 unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);
984 unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);
985
Remy Bruno47ba97f2008-02-22 17:57:02 +0100986 /* For the 9632, the mask is different */
987 if (hdsp->io_type == H9632)
988 rate_bits = (status & HDSP_spdifFrequencyMask_9632);
989
Takashi Iwaib0b98112005-10-20 18:29:58 +0200990 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 return 0;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100992
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 switch (rate_bits) {
994 case HDSP_spdifFrequency32KHz: return 32000;
995 case HDSP_spdifFrequency44_1KHz: return 44100;
996 case HDSP_spdifFrequency48KHz: return 48000;
997 case HDSP_spdifFrequency64KHz: return 64000;
998 case HDSP_spdifFrequency88_2KHz: return 88200;
999 case HDSP_spdifFrequency96KHz: return 96000;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001000 case HDSP_spdifFrequency128KHz:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 if (hdsp->io_type == H9632) return 128000;
1002 break;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001003 case HDSP_spdifFrequency176_4KHz:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 if (hdsp->io_type == H9632) return 176400;
1005 break;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001006 case HDSP_spdifFrequency192KHz:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 if (hdsp->io_type == H9632) return 192000;
1008 break;
1009 default:
1010 break;
1011 }
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01001012 dev_warn(hdsp->card->dev,
1013 "unknown spdif frequency status; bits = 0x%x, status = 0x%x\n",
1014 rate_bits, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 return 0;
1016}
1017
Remy Bruno47ba97f2008-02-22 17:57:02 +01001018static int hdsp_external_sample_rate(struct hdsp *hdsp)
1019{
1020 unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
1021 unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
1022
1023 /* For the 9632 card, there seems to be no bit for indicating external
1024 * sample rate greater than 96kHz. The card reports the corresponding
1025 * single speed. So the best means seems to get spdif rate when
1026 * autosync reference is spdif */
1027 if (hdsp->io_type == H9632 &&
1028 hdsp_autosync_ref(hdsp) == HDSP_AUTOSYNC_FROM_SPDIF)
1029 return hdsp_spdif_sample_rate(hdsp);
1030
1031 switch (rate_bits) {
1032 case HDSP_systemFrequency32: return 32000;
1033 case HDSP_systemFrequency44_1: return 44100;
1034 case HDSP_systemFrequency48: return 48000;
1035 case HDSP_systemFrequency64: return 64000;
1036 case HDSP_systemFrequency88_2: return 88200;
1037 case HDSP_systemFrequency96: return 96000;
1038 default:
1039 return 0;
1040 }
1041}
1042
Takashi Iwai55e957d2005-11-17 14:52:13 +01001043static void hdsp_compute_period_size(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044{
1045 hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));
1046}
1047
Takashi Iwai55e957d2005-11-17 14:52:13 +01001048static snd_pcm_uframes_t hdsp_hw_pointer(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049{
1050 int position;
1051
1052 position = hdsp_read(hdsp, HDSP_statusRegister);
1053
Takashi Iwaib0b98112005-10-20 18:29:58 +02001054 if (!hdsp->precise_ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 return (position & HDSP_BufferID) ? (hdsp->period_bytes / 4) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056
1057 position &= HDSP_BufferPositionMask;
1058 position /= 4;
1059 position &= (hdsp->period_bytes/2) - 1;
1060 return position;
1061}
1062
Takashi Iwai55e957d2005-11-17 14:52:13 +01001063static void hdsp_reset_hw_pointer(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064{
1065 hdsp_write (hdsp, HDSP_resetPointer, 0);
Remy Brunod7923b22006-10-17 12:41:56 +02001066 if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152)
1067 /* HDSP_resetPointer = HDSP_freqReg, which is strange and
1068 * requires (?) to write again DDS value after a reset pointer
1069 * (at least, it works like this) */
1070 hdsp_write (hdsp, HDSP_freqReg, hdsp->dds_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071}
1072
Takashi Iwai55e957d2005-11-17 14:52:13 +01001073static void hdsp_start_audio(struct hdsp *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074{
1075 s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start);
1076 hdsp_write(s, HDSP_controlRegister, s->control_register);
1077}
1078
Takashi Iwai55e957d2005-11-17 14:52:13 +01001079static void hdsp_stop_audio(struct hdsp *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080{
1081 s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable);
1082 hdsp_write(s, HDSP_controlRegister, s->control_register);
1083}
1084
Takashi Iwai55e957d2005-11-17 14:52:13 +01001085static void hdsp_silence_playback(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086{
1087 memset(hdsp->playback_buffer, 0, HDSP_DMA_AREA_BYTES);
1088}
1089
Takashi Iwai55e957d2005-11-17 14:52:13 +01001090static int hdsp_set_interrupt_interval(struct hdsp *s, unsigned int frames)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091{
1092 int n;
1093
1094 spin_lock_irq(&s->lock);
1095
1096 frames >>= 7;
1097 n = 0;
1098 while (frames) {
1099 n++;
1100 frames >>= 1;
1101 }
1102
1103 s->control_register &= ~HDSP_LatencyMask;
1104 s->control_register |= hdsp_encode_latency(n);
1105
1106 hdsp_write(s, HDSP_controlRegister, s->control_register);
1107
1108 hdsp_compute_period_size(s);
1109
1110 spin_unlock_irq(&s->lock);
1111
1112 return 0;
1113}
1114
Remy Brunod7923b22006-10-17 12:41:56 +02001115static void hdsp_set_dds_value(struct hdsp *hdsp, int rate)
1116{
1117 u64 n;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001118
Remy Brunod7923b22006-10-17 12:41:56 +02001119 if (rate >= 112000)
1120 rate /= 4;
1121 else if (rate >= 56000)
1122 rate /= 2;
1123
Julian Cablee4b60882007-03-19 11:44:40 +01001124 n = DDS_NUMERATOR;
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001125 n = div_u64(n, rate);
Remy Brunod7923b22006-10-17 12:41:56 +02001126 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001127 snd_BUG_ON(n >> 32);
Remy Brunod7923b22006-10-17 12:41:56 +02001128 /* HDSP_freqReg and HDSP_resetPointer are the same, so keep the DDS
1129 value to write it after a reset */
1130 hdsp->dds_value = n;
1131 hdsp_write(hdsp, HDSP_freqReg, hdsp->dds_value);
1132}
1133
Takashi Iwai55e957d2005-11-17 14:52:13 +01001134static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135{
1136 int reject_if_open = 0;
1137 int current_rate;
1138 int rate_bits;
1139
1140 /* ASSUMPTION: hdsp->lock is either held, or
1141 there is no need for it (e.g. during module
1142 initialization).
1143 */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001144
1145 if (!(hdsp->control_register & HDSP_ClockModeMaster)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 if (called_internally) {
1147 /* request from ctl or card initialization */
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01001148 dev_err(hdsp->card->dev,
1149 "device is not running as a clock master: cannot set sample rate.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 return -1;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001151 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 /* hw_param request while in AutoSync mode */
1153 int external_freq = hdsp_external_sample_rate(hdsp);
1154 int spdif_freq = hdsp_spdif_sample_rate(hdsp);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001155
Takashi Iwaib0b98112005-10-20 18:29:58 +02001156 if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1))
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01001157 dev_info(hdsp->card->dev,
1158 "Detected ADAT in double speed mode\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02001159 else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1))
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01001160 dev_info(hdsp->card->dev,
1161 "Detected ADAT in quad speed mode\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02001162 else if (rate != external_freq) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01001163 dev_info(hdsp->card->dev,
1164 "No AutoSync source for requested rate\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 return -1;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001166 }
1167 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 }
1169
1170 current_rate = hdsp->system_sample_rate;
1171
1172 /* Changing from a "single speed" to a "double speed" rate is
1173 not allowed if any substreams are open. This is because
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001174 such a change causes a shift in the location of
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 the DMA buffers and a reduction in the number of available
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001176 buffers.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177
1178 Note that a similar but essentially insoluble problem
1179 exists for externally-driven rate changes. All we can do
1180 is to flag rate changes in the read/write routines. */
1181
Takashi Iwaib0b98112005-10-20 18:29:58 +02001182 if (rate > 96000 && hdsp->io_type != H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 return -EINVAL;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001184
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 switch (rate) {
1186 case 32000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001187 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 rate_bits = HDSP_Frequency32KHz;
1190 break;
1191 case 44100:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001192 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 rate_bits = HDSP_Frequency44_1KHz;
1195 break;
1196 case 48000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001197 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 rate_bits = HDSP_Frequency48KHz;
1200 break;
1201 case 64000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001202 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 rate_bits = HDSP_Frequency64KHz;
1205 break;
1206 case 88200:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001207 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 rate_bits = HDSP_Frequency88_2KHz;
1210 break;
1211 case 96000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001212 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 rate_bits = HDSP_Frequency96KHz;
1215 break;
1216 case 128000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001217 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 rate_bits = HDSP_Frequency128KHz;
1220 break;
1221 case 176400:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001222 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 rate_bits = HDSP_Frequency176_4KHz;
1225 break;
1226 case 192000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001227 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 rate_bits = HDSP_Frequency192KHz;
1230 break;
1231 default:
1232 return -EINVAL;
1233 }
1234
1235 if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01001236 dev_warn(hdsp->card->dev,
1237 "cannot change speed mode (capture PID = %d, playback PID = %d)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 hdsp->capture_pid,
1239 hdsp->playback_pid);
1240 return -EBUSY;
1241 }
1242
1243 hdsp->control_register &= ~HDSP_FrequencyMask;
1244 hdsp->control_register |= rate_bits;
1245 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1246
Remy Brunod7923b22006-10-17 12:41:56 +02001247 /* For HDSP9632 rev 152, need to set DDS value in FREQ register */
1248 if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152)
1249 hdsp_set_dds_value(hdsp, rate);
1250
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 if (rate >= 128000) {
1252 hdsp->channel_map = channel_map_H9632_qs;
1253 } else if (rate > 48000) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001254 if (hdsp->io_type == H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 hdsp->channel_map = channel_map_H9632_ds;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001256 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 hdsp->channel_map = channel_map_ds;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 } else {
1259 switch (hdsp->io_type) {
Florian Faber28b26e12010-12-01 12:14:47 +01001260 case RPM:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 case Multiface:
1262 hdsp->channel_map = channel_map_mf_ss;
1263 break;
1264 case Digiface:
1265 case H9652:
1266 hdsp->channel_map = channel_map_df_ss;
1267 break;
1268 case H9632:
1269 hdsp->channel_map = channel_map_H9632_ss;
1270 break;
1271 default:
1272 /* should never happen */
1273 break;
1274 }
1275 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001276
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 hdsp->system_sample_rate = rate;
1278
1279 return 0;
1280}
1281
1282/*----------------------------------------------------------------------------
1283 MIDI
1284 ----------------------------------------------------------------------------*/
1285
Takashi Iwai55e957d2005-11-17 14:52:13 +01001286static unsigned char snd_hdsp_midi_read_byte (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287{
1288 /* the hardware already does the relevant bit-mask with 0xff */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001289 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 return hdsp_read(hdsp, HDSP_midiDataIn1);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001291 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 return hdsp_read(hdsp, HDSP_midiDataIn0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293}
1294
Takashi Iwai55e957d2005-11-17 14:52:13 +01001295static void snd_hdsp_midi_write_byte (struct hdsp *hdsp, int id, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296{
1297 /* the hardware already does the relevant bit-mask with 0xff */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001298 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 hdsp_write(hdsp, HDSP_midiDataOut1, val);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001300 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 hdsp_write(hdsp, HDSP_midiDataOut0, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302}
1303
Takashi Iwai55e957d2005-11-17 14:52:13 +01001304static int snd_hdsp_midi_input_available (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001306 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 return (hdsp_read(hdsp, HDSP_midiStatusIn1) & 0xff);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001308 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 return (hdsp_read(hdsp, HDSP_midiStatusIn0) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310}
1311
Takashi Iwai55e957d2005-11-17 14:52:13 +01001312static int snd_hdsp_midi_output_possible (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313{
1314 int fifo_bytes_used;
1315
Takashi Iwaib0b98112005-10-20 18:29:58 +02001316 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut1) & 0xff;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001318 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut0) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320
Takashi Iwaib0b98112005-10-20 18:29:58 +02001321 if (fifo_bytes_used < 128)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 return 128 - fifo_bytes_used;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001323 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325}
1326
Takashi Iwai55e957d2005-11-17 14:52:13 +01001327static void snd_hdsp_flush_midi_input (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001329 while (snd_hdsp_midi_input_available (hdsp, id))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 snd_hdsp_midi_read_byte (hdsp, id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331}
1332
Takashi Iwai55e957d2005-11-17 14:52:13 +01001333static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334{
1335 unsigned long flags;
1336 int n_pending;
1337 int to_write;
1338 int i;
1339 unsigned char buf[128];
1340
1341 /* Output is not interrupt driven */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001342
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 spin_lock_irqsave (&hmidi->lock, flags);
1344 if (hmidi->output) {
1345 if (!snd_rawmidi_transmit_empty (hmidi->output)) {
1346 if ((n_pending = snd_hdsp_midi_output_possible (hmidi->hdsp, hmidi->id)) > 0) {
1347 if (n_pending > (int)sizeof (buf))
1348 n_pending = sizeof (buf);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001349
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001351 for (i = 0; i < to_write; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 snd_hdsp_midi_write_byte (hmidi->hdsp, hmidi->id, buf[i]);
1353 }
1354 }
1355 }
1356 }
1357 spin_unlock_irqrestore (&hmidi->lock, flags);
1358 return 0;
1359}
1360
Takashi Iwai55e957d2005-11-17 14:52:13 +01001361static int snd_hdsp_midi_input_read (struct hdsp_midi *hmidi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362{
1363 unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
1364 unsigned long flags;
1365 int n_pending;
1366 int i;
1367
1368 spin_lock_irqsave (&hmidi->lock, flags);
1369 if ((n_pending = snd_hdsp_midi_input_available (hmidi->hdsp, hmidi->id)) > 0) {
1370 if (hmidi->input) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001371 if (n_pending > (int)sizeof (buf))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 n_pending = sizeof (buf);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001373 for (i = 0; i < n_pending; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 buf[i] = snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001375 if (n_pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 snd_rawmidi_receive (hmidi->input, buf, n_pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 } else {
1378 /* flush the MIDI input FIFO */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001379 while (--n_pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 }
1382 }
1383 hmidi->pending = 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001384 if (hmidi->id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 hmidi->hdsp->control_register |= HDSP_Midi1InterruptEnable;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001386 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 hmidi->hdsp->control_register |= HDSP_Midi0InterruptEnable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 hdsp_write(hmidi->hdsp, HDSP_controlRegister, hmidi->hdsp->control_register);
1389 spin_unlock_irqrestore (&hmidi->lock, flags);
1390 return snd_hdsp_midi_output_write (hmidi);
1391}
1392
Takashi Iwai55e957d2005-11-17 14:52:13 +01001393static void snd_hdsp_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001395 struct hdsp *hdsp;
1396 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 unsigned long flags;
1398 u32 ie;
1399
Takashi Iwai55e957d2005-11-17 14:52:13 +01001400 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 hdsp = hmidi->hdsp;
1402 ie = hmidi->id ? HDSP_Midi1InterruptEnable : HDSP_Midi0InterruptEnable;
1403 spin_lock_irqsave (&hdsp->lock, flags);
1404 if (up) {
1405 if (!(hdsp->control_register & ie)) {
1406 snd_hdsp_flush_midi_input (hdsp, hmidi->id);
1407 hdsp->control_register |= ie;
1408 }
1409 } else {
1410 hdsp->control_register &= ~ie;
1411 tasklet_kill(&hdsp->midi_tasklet);
1412 }
1413
1414 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1415 spin_unlock_irqrestore (&hdsp->lock, flags);
1416}
1417
1418static void snd_hdsp_midi_output_timer(unsigned long data)
1419{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001420 struct hdsp_midi *hmidi = (struct hdsp_midi *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 unsigned long flags;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001422
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 snd_hdsp_midi_output_write(hmidi);
1424 spin_lock_irqsave (&hmidi->lock, flags);
1425
1426 /* this does not bump hmidi->istimer, because the
1427 kernel automatically removed the timer when it
1428 expired, and we are now adding it back, thus
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001429 leaving istimer wherever it was set before.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 */
1431
Takashi Iwaic41c0092015-01-19 11:34:36 +01001432 if (hmidi->istimer)
1433 mod_timer(&hmidi->timer, 1 + jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434
1435 spin_unlock_irqrestore (&hmidi->lock, flags);
1436}
1437
Takashi Iwai55e957d2005-11-17 14:52:13 +01001438static void snd_hdsp_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001440 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 unsigned long flags;
1442
Takashi Iwai55e957d2005-11-17 14:52:13 +01001443 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 spin_lock_irqsave (&hmidi->lock, flags);
1445 if (up) {
1446 if (!hmidi->istimer) {
Takashi Iwaic41c0092015-01-19 11:34:36 +01001447 setup_timer(&hmidi->timer, snd_hdsp_midi_output_timer,
1448 (unsigned long) hmidi);
1449 mod_timer(&hmidi->timer, 1 + jiffies);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 hmidi->istimer++;
1451 }
1452 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001453 if (hmidi->istimer && --hmidi->istimer <= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 del_timer (&hmidi->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 }
1456 spin_unlock_irqrestore (&hmidi->lock, flags);
1457 if (up)
1458 snd_hdsp_midi_output_write(hmidi);
1459}
1460
Takashi Iwai55e957d2005-11-17 14:52:13 +01001461static int snd_hdsp_midi_input_open(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001463 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
Takashi Iwai55e957d2005-11-17 14:52:13 +01001465 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 spin_lock_irq (&hmidi->lock);
1467 snd_hdsp_flush_midi_input (hmidi->hdsp, hmidi->id);
1468 hmidi->input = substream;
1469 spin_unlock_irq (&hmidi->lock);
1470
1471 return 0;
1472}
1473
Takashi Iwai55e957d2005-11-17 14:52:13 +01001474static int snd_hdsp_midi_output_open(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001476 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
Takashi Iwai55e957d2005-11-17 14:52:13 +01001478 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 spin_lock_irq (&hmidi->lock);
1480 hmidi->output = substream;
1481 spin_unlock_irq (&hmidi->lock);
1482
1483 return 0;
1484}
1485
Takashi Iwai55e957d2005-11-17 14:52:13 +01001486static int snd_hdsp_midi_input_close(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001488 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489
1490 snd_hdsp_midi_input_trigger (substream, 0);
1491
Takashi Iwai55e957d2005-11-17 14:52:13 +01001492 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 spin_lock_irq (&hmidi->lock);
1494 hmidi->input = NULL;
1495 spin_unlock_irq (&hmidi->lock);
1496
1497 return 0;
1498}
1499
Takashi Iwai55e957d2005-11-17 14:52:13 +01001500static int snd_hdsp_midi_output_close(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001502 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503
1504 snd_hdsp_midi_output_trigger (substream, 0);
1505
Takashi Iwai55e957d2005-11-17 14:52:13 +01001506 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 spin_lock_irq (&hmidi->lock);
1508 hmidi->output = NULL;
1509 spin_unlock_irq (&hmidi->lock);
1510
1511 return 0;
1512}
1513
Takashi Iwai55e957d2005-11-17 14:52:13 +01001514static struct snd_rawmidi_ops snd_hdsp_midi_output =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515{
1516 .open = snd_hdsp_midi_output_open,
1517 .close = snd_hdsp_midi_output_close,
1518 .trigger = snd_hdsp_midi_output_trigger,
1519};
1520
Takashi Iwai55e957d2005-11-17 14:52:13 +01001521static struct snd_rawmidi_ops snd_hdsp_midi_input =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522{
1523 .open = snd_hdsp_midi_input_open,
1524 .close = snd_hdsp_midi_input_close,
1525 .trigger = snd_hdsp_midi_input_trigger,
1526};
1527
Takashi Iwaif40b6892006-07-05 16:51:05 +02001528static int snd_hdsp_create_midi (struct snd_card *card, struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529{
Dan Carpentera3b3a9d2015-08-22 12:24:13 +03001530 char buf[40];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531
1532 hdsp->midi[id].id = id;
1533 hdsp->midi[id].rmidi = NULL;
1534 hdsp->midi[id].input = NULL;
1535 hdsp->midi[id].output = NULL;
1536 hdsp->midi[id].hdsp = hdsp;
1537 hdsp->midi[id].istimer = 0;
1538 hdsp->midi[id].pending = 0;
1539 spin_lock_init (&hdsp->midi[id].lock);
1540
Dan Carpentera3b3a9d2015-08-22 12:24:13 +03001541 snprintf(buf, sizeof(buf), "%s MIDI %d", card->shortname, id + 1);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001542 if (snd_rawmidi_new (card, buf, id, 1, 1, &hdsp->midi[id].rmidi) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544
Jaroslav Kysela972d4c52008-11-12 16:37:48 +01001545 sprintf(hdsp->midi[id].rmidi->name, "HDSP MIDI %d", id+1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 hdsp->midi[id].rmidi->private_data = &hdsp->midi[id];
1547
1548 snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdsp_midi_output);
1549 snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdsp_midi_input);
1550
1551 hdsp->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
1552 SNDRV_RAWMIDI_INFO_INPUT |
1553 SNDRV_RAWMIDI_INFO_DUPLEX;
1554
1555 return 0;
1556}
1557
1558/*-----------------------------------------------------------------------------
1559 Control Interface
1560 ----------------------------------------------------------------------------*/
1561
Takashi Iwai55e957d2005-11-17 14:52:13 +01001562static u32 snd_hdsp_convert_from_aes(struct snd_aes_iec958 *aes)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563{
1564 u32 val = 0;
1565 val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? HDSP_SPDIFProfessional : 0;
1566 val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? HDSP_SPDIFNonAudio : 0;
1567 if (val & HDSP_SPDIFProfessional)
1568 val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0;
1569 else
1570 val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0;
1571 return val;
1572}
1573
Takashi Iwai55e957d2005-11-17 14:52:13 +01001574static void snd_hdsp_convert_to_aes(struct snd_aes_iec958 *aes, u32 val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575{
1576 aes->status[0] = ((val & HDSP_SPDIFProfessional) ? IEC958_AES0_PROFESSIONAL : 0) |
1577 ((val & HDSP_SPDIFNonAudio) ? IEC958_AES0_NONAUDIO : 0);
1578 if (val & HDSP_SPDIFProfessional)
1579 aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0;
1580 else
1581 aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_CON_EMPHASIS_5015 : 0;
1582}
1583
Takashi Iwai55e957d2005-11-17 14:52:13 +01001584static int snd_hdsp_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585{
1586 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1587 uinfo->count = 1;
1588 return 0;
1589}
1590
Takashi Iwai55e957d2005-11-17 14:52:13 +01001591static int snd_hdsp_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001593 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001594
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif);
1596 return 0;
1597}
1598
Takashi Iwai55e957d2005-11-17 14:52:13 +01001599static int snd_hdsp_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001601 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 int change;
1603 u32 val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001604
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
1606 spin_lock_irq(&hdsp->lock);
1607 change = val != hdsp->creg_spdif;
1608 hdsp->creg_spdif = val;
1609 spin_unlock_irq(&hdsp->lock);
1610 return change;
1611}
1612
Takashi Iwai55e957d2005-11-17 14:52:13 +01001613static int snd_hdsp_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614{
1615 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1616 uinfo->count = 1;
1617 return 0;
1618}
1619
Takashi Iwai55e957d2005-11-17 14:52:13 +01001620static int snd_hdsp_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001622 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001623
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream);
1625 return 0;
1626}
1627
Takashi Iwai55e957d2005-11-17 14:52:13 +01001628static int snd_hdsp_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001630 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 int change;
1632 u32 val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001633
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
1635 spin_lock_irq(&hdsp->lock);
1636 change = val != hdsp->creg_spdif_stream;
1637 hdsp->creg_spdif_stream = val;
1638 hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
1639 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= val);
1640 spin_unlock_irq(&hdsp->lock);
1641 return change;
1642}
1643
Takashi Iwai55e957d2005-11-17 14:52:13 +01001644static int snd_hdsp_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645{
1646 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1647 uinfo->count = 1;
1648 return 0;
1649}
1650
Takashi Iwai55e957d2005-11-17 14:52:13 +01001651static int snd_hdsp_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652{
1653 ucontrol->value.iec958.status[0] = kcontrol->private_value;
1654 return 0;
1655}
1656
1657#define HDSP_SPDIF_IN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001658{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 .name = xname, \
1660 .index = xindex, \
1661 .info = snd_hdsp_info_spdif_in, \
1662 .get = snd_hdsp_get_spdif_in, \
1663 .put = snd_hdsp_put_spdif_in }
1664
Takashi Iwai55e957d2005-11-17 14:52:13 +01001665static unsigned int hdsp_spdif_in(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666{
1667 return hdsp_decode_spdif_in(hdsp->control_register & HDSP_SPDIFInputMask);
1668}
1669
Takashi Iwai55e957d2005-11-17 14:52:13 +01001670static int hdsp_set_spdif_input(struct hdsp *hdsp, int in)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671{
1672 hdsp->control_register &= ~HDSP_SPDIFInputMask;
1673 hdsp->control_register |= hdsp_encode_spdif_in(in);
1674 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1675 return 0;
1676}
1677
Takashi Iwai55e957d2005-11-17 14:52:13 +01001678static int snd_hdsp_info_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679{
Takashi Iwai8d678da2014-10-20 18:19:34 +02001680 static const char * const texts[4] = {
1681 "Optical", "Coaxial", "Internal", "AES"
1682 };
Takashi Iwai55e957d2005-11-17 14:52:13 +01001683 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684
Takashi Iwai8d678da2014-10-20 18:19:34 +02001685 return snd_ctl_enum_info(uinfo, 1, (hdsp->io_type == H9632) ? 4 : 3,
1686 texts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687}
1688
Takashi Iwai55e957d2005-11-17 14:52:13 +01001689static int snd_hdsp_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001691 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001692
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp);
1694 return 0;
1695}
1696
Takashi Iwai55e957d2005-11-17 14:52:13 +01001697static int snd_hdsp_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001699 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 int change;
1701 unsigned int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001702
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 if (!snd_hdsp_use_is_exclusive(hdsp))
1704 return -EBUSY;
1705 val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3);
1706 spin_lock_irq(&hdsp->lock);
1707 change = val != hdsp_spdif_in(hdsp);
1708 if (change)
1709 hdsp_set_spdif_input(hdsp, val);
1710 spin_unlock_irq(&hdsp->lock);
1711 return change;
1712}
1713
Adrian Knoth66d92442013-01-15 18:52:21 +01001714#define HDSP_TOGGLE_SETTING(xname, xindex) \
1715{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1716 .name = xname, \
1717 .private_value = xindex, \
1718 .info = snd_hdsp_info_toggle_setting, \
1719 .get = snd_hdsp_get_toggle_setting, \
1720 .put = snd_hdsp_put_toggle_setting \
1721}
1722
1723static int hdsp_toggle_setting(struct hdsp *hdsp, u32 regmask)
1724{
1725 return (hdsp->control_register & regmask) ? 1 : 0;
1726}
1727
1728static int hdsp_set_toggle_setting(struct hdsp *hdsp, u32 regmask, int out)
1729{
1730 if (out)
1731 hdsp->control_register |= regmask;
1732 else
1733 hdsp->control_register &= ~regmask;
1734 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1735
1736 return 0;
1737}
1738
1739#define snd_hdsp_info_toggle_setting snd_ctl_boolean_mono_info
1740
1741static int snd_hdsp_get_toggle_setting(struct snd_kcontrol *kcontrol,
1742 struct snd_ctl_elem_value *ucontrol)
1743{
1744 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
1745 u32 regmask = kcontrol->private_value;
1746
1747 spin_lock_irq(&hdsp->lock);
1748 ucontrol->value.integer.value[0] = hdsp_toggle_setting(hdsp, regmask);
1749 spin_unlock_irq(&hdsp->lock);
1750 return 0;
1751}
1752
1753static int snd_hdsp_put_toggle_setting(struct snd_kcontrol *kcontrol,
1754 struct snd_ctl_elem_value *ucontrol)
1755{
1756 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
1757 u32 regmask = kcontrol->private_value;
1758 int change;
1759 unsigned int val;
1760
1761 if (!snd_hdsp_use_is_exclusive(hdsp))
1762 return -EBUSY;
1763 val = ucontrol->value.integer.value[0] & 1;
1764 spin_lock_irq(&hdsp->lock);
1765 change = (int) val != hdsp_toggle_setting(hdsp, regmask);
1766 if (change)
1767 hdsp_set_toggle_setting(hdsp, regmask, val);
1768 spin_unlock_irq(&hdsp->lock);
1769 return change;
1770}
1771
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772#define HDSP_SPDIF_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001773{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 .name = xname, \
1775 .index = xindex, \
1776 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1777 .info = snd_hdsp_info_spdif_sample_rate, \
1778 .get = snd_hdsp_get_spdif_sample_rate \
1779}
1780
Takashi Iwai55e957d2005-11-17 14:52:13 +01001781static int snd_hdsp_info_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782{
Takashi Iwai8d678da2014-10-20 18:19:34 +02001783 static const char * const texts[] = {
1784 "32000", "44100", "48000", "64000", "88200", "96000",
1785 "None", "128000", "176400", "192000"
1786 };
Takashi Iwai55e957d2005-11-17 14:52:13 +01001787 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788
Takashi Iwai8d678da2014-10-20 18:19:34 +02001789 return snd_ctl_enum_info(uinfo, 1, (hdsp->io_type == H9632) ? 10 : 7,
1790 texts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791}
1792
Takashi Iwai55e957d2005-11-17 14:52:13 +01001793static int snd_hdsp_get_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001795 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001796
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 switch (hdsp_spdif_sample_rate(hdsp)) {
1798 case 32000:
1799 ucontrol->value.enumerated.item[0] = 0;
1800 break;
1801 case 44100:
1802 ucontrol->value.enumerated.item[0] = 1;
1803 break;
1804 case 48000:
1805 ucontrol->value.enumerated.item[0] = 2;
1806 break;
1807 case 64000:
1808 ucontrol->value.enumerated.item[0] = 3;
1809 break;
1810 case 88200:
1811 ucontrol->value.enumerated.item[0] = 4;
1812 break;
1813 case 96000:
1814 ucontrol->value.enumerated.item[0] = 5;
1815 break;
1816 case 128000:
1817 ucontrol->value.enumerated.item[0] = 7;
1818 break;
1819 case 176400:
1820 ucontrol->value.enumerated.item[0] = 8;
1821 break;
1822 case 192000:
1823 ucontrol->value.enumerated.item[0] = 9;
1824 break;
1825 default:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001826 ucontrol->value.enumerated.item[0] = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 }
1828 return 0;
1829}
1830
1831#define HDSP_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001832{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 .name = xname, \
1834 .index = xindex, \
1835 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1836 .info = snd_hdsp_info_system_sample_rate, \
1837 .get = snd_hdsp_get_system_sample_rate \
1838}
1839
Takashi Iwai55e957d2005-11-17 14:52:13 +01001840static int snd_hdsp_info_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841{
1842 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1843 uinfo->count = 1;
1844 return 0;
1845}
1846
Takashi Iwai55e957d2005-11-17 14:52:13 +01001847static int snd_hdsp_get_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001849 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001850
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate;
1852 return 0;
1853}
1854
1855#define HDSP_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001856{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 .name = xname, \
1858 .index = xindex, \
1859 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1860 .info = snd_hdsp_info_autosync_sample_rate, \
1861 .get = snd_hdsp_get_autosync_sample_rate \
1862}
1863
Takashi Iwai55e957d2005-11-17 14:52:13 +01001864static int snd_hdsp_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001866 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Takashi Iwai8d678da2014-10-20 18:19:34 +02001867 static const char * const texts[] = {
1868 "32000", "44100", "48000", "64000", "88200", "96000",
1869 "None", "128000", "176400", "192000"
1870 };
1871
1872 return snd_ctl_enum_info(uinfo, 1, (hdsp->io_type == H9632) ? 10 : 7,
1873 texts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874}
1875
Takashi Iwai55e957d2005-11-17 14:52:13 +01001876static int snd_hdsp_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001878 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001879
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 switch (hdsp_external_sample_rate(hdsp)) {
1881 case 32000:
1882 ucontrol->value.enumerated.item[0] = 0;
1883 break;
1884 case 44100:
1885 ucontrol->value.enumerated.item[0] = 1;
1886 break;
1887 case 48000:
1888 ucontrol->value.enumerated.item[0] = 2;
1889 break;
1890 case 64000:
1891 ucontrol->value.enumerated.item[0] = 3;
1892 break;
1893 case 88200:
1894 ucontrol->value.enumerated.item[0] = 4;
1895 break;
1896 case 96000:
1897 ucontrol->value.enumerated.item[0] = 5;
1898 break;
1899 case 128000:
1900 ucontrol->value.enumerated.item[0] = 7;
1901 break;
1902 case 176400:
1903 ucontrol->value.enumerated.item[0] = 8;
1904 break;
1905 case 192000:
1906 ucontrol->value.enumerated.item[0] = 9;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001907 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 default:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001909 ucontrol->value.enumerated.item[0] = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910 }
1911 return 0;
1912}
1913
1914#define HDSP_SYSTEM_CLOCK_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001915{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 .name = xname, \
1917 .index = xindex, \
1918 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1919 .info = snd_hdsp_info_system_clock_mode, \
1920 .get = snd_hdsp_get_system_clock_mode \
1921}
1922
Takashi Iwai55e957d2005-11-17 14:52:13 +01001923static int hdsp_system_clock_mode(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001925 if (hdsp->control_register & HDSP_ClockModeMaster)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001927 else if (hdsp_external_sample_rate(hdsp) != hdsp->system_sample_rate)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 return 1;
1930}
1931
Takashi Iwai55e957d2005-11-17 14:52:13 +01001932static int snd_hdsp_info_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933{
Takashi Iwai8d678da2014-10-20 18:19:34 +02001934 static const char * const texts[] = {"Master", "Slave" };
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001935
Takashi Iwai8d678da2014-10-20 18:19:34 +02001936 return snd_ctl_enum_info(uinfo, 1, 2, texts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937}
1938
Takashi Iwai55e957d2005-11-17 14:52:13 +01001939static int snd_hdsp_get_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001941 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001942
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp);
1944 return 0;
1945}
1946
1947#define HDSP_CLOCK_SOURCE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001948{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 .name = xname, \
1950 .index = xindex, \
1951 .info = snd_hdsp_info_clock_source, \
1952 .get = snd_hdsp_get_clock_source, \
1953 .put = snd_hdsp_put_clock_source \
1954}
1955
Takashi Iwai55e957d2005-11-17 14:52:13 +01001956static int hdsp_clock_source(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957{
1958 if (hdsp->control_register & HDSP_ClockModeMaster) {
1959 switch (hdsp->system_sample_rate) {
1960 case 32000:
1961 return 1;
1962 case 44100:
1963 return 2;
1964 case 48000:
1965 return 3;
1966 case 64000:
1967 return 4;
1968 case 88200:
1969 return 5;
1970 case 96000:
1971 return 6;
1972 case 128000:
1973 return 7;
1974 case 176400:
1975 return 8;
1976 case 192000:
1977 return 9;
1978 default:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001979 return 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980 }
1981 } else {
1982 return 0;
1983 }
1984}
1985
Takashi Iwai55e957d2005-11-17 14:52:13 +01001986static int hdsp_set_clock_source(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987{
1988 int rate;
1989 switch (mode) {
1990 case HDSP_CLOCK_SOURCE_AUTOSYNC:
1991 if (hdsp_external_sample_rate(hdsp) != 0) {
1992 if (!hdsp_set_rate(hdsp, hdsp_external_sample_rate(hdsp), 1)) {
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001993 hdsp->control_register &= ~HDSP_ClockModeMaster;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1995 return 0;
1996 }
1997 }
1998 return -1;
1999 case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ:
2000 rate = 32000;
2001 break;
2002 case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ:
2003 rate = 44100;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002004 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ:
2006 rate = 48000;
2007 break;
2008 case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ:
2009 rate = 64000;
2010 break;
2011 case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ:
2012 rate = 88200;
2013 break;
2014 case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ:
2015 rate = 96000;
2016 break;
2017 case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ:
2018 rate = 128000;
2019 break;
2020 case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ:
2021 rate = 176400;
2022 break;
2023 case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ:
2024 rate = 192000;
2025 break;
2026 default:
2027 rate = 48000;
2028 }
2029 hdsp->control_register |= HDSP_ClockModeMaster;
2030 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2031 hdsp_set_rate(hdsp, rate, 1);
2032 return 0;
2033}
2034
Takashi Iwai55e957d2005-11-17 14:52:13 +01002035static int snd_hdsp_info_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036{
Takashi Iwai8d678da2014-10-20 18:19:34 +02002037 static const char * const texts[] = {
2038 "AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz",
2039 "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz",
2040 "Internal 96.0 kHz", "Internal 128 kHz", "Internal 176.4 kHz",
2041 "Internal 192.0 KHz"
2042 };
Takashi Iwai55e957d2005-11-17 14:52:13 +01002043 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002044
Takashi Iwai8d678da2014-10-20 18:19:34 +02002045 return snd_ctl_enum_info(uinfo, 1, (hdsp->io_type == H9632) ? 10 : 7,
2046 texts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047}
2048
Takashi Iwai55e957d2005-11-17 14:52:13 +01002049static int snd_hdsp_get_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002051 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002052
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp);
2054 return 0;
2055}
2056
Takashi Iwai55e957d2005-11-17 14:52:13 +01002057static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002059 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 int change;
2061 int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002062
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 if (!snd_hdsp_use_is_exclusive(hdsp))
2064 return -EBUSY;
2065 val = ucontrol->value.enumerated.item[0];
2066 if (val < 0) val = 0;
2067 if (hdsp->io_type == H9632) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002068 if (val > 9)
2069 val = 9;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002071 if (val > 6)
2072 val = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073 }
2074 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002075 if (val != hdsp_clock_source(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076 change = (hdsp_set_clock_source(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002077 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 spin_unlock_irq(&hdsp->lock);
2080 return change;
2081}
2082
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002083#define snd_hdsp_info_clock_source_lock snd_ctl_boolean_mono_info
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002084
Takashi Iwai55e957d2005-11-17 14:52:13 +01002085static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002086{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002087 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002088
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002089 ucontrol->value.integer.value[0] = hdsp->clock_source_locked;
2090 return 0;
2091}
2092
Takashi Iwai55e957d2005-11-17 14:52:13 +01002093static int snd_hdsp_put_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002094{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002095 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002096 int change;
2097
2098 change = (int)ucontrol->value.integer.value[0] != hdsp->clock_source_locked;
2099 if (change)
Takashi Iwai4e98d6a2007-11-15 15:58:13 +01002100 hdsp->clock_source_locked = !!ucontrol->value.integer.value[0];
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002101 return change;
2102}
2103
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104#define HDSP_DA_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002105{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 .name = xname, \
2107 .index = xindex, \
2108 .info = snd_hdsp_info_da_gain, \
2109 .get = snd_hdsp_get_da_gain, \
2110 .put = snd_hdsp_put_da_gain \
2111}
2112
Takashi Iwai55e957d2005-11-17 14:52:13 +01002113static int hdsp_da_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114{
2115 switch (hdsp->control_register & HDSP_DAGainMask) {
2116 case HDSP_DAGainHighGain:
2117 return 0;
2118 case HDSP_DAGainPlus4dBu:
2119 return 1;
2120 case HDSP_DAGainMinus10dBV:
2121 return 2;
2122 default:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002123 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 }
2125}
2126
Takashi Iwai55e957d2005-11-17 14:52:13 +01002127static int hdsp_set_da_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128{
2129 hdsp->control_register &= ~HDSP_DAGainMask;
2130 switch (mode) {
2131 case 0:
2132 hdsp->control_register |= HDSP_DAGainHighGain;
2133 break;
2134 case 1:
2135 hdsp->control_register |= HDSP_DAGainPlus4dBu;
2136 break;
2137 case 2:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002138 hdsp->control_register |= HDSP_DAGainMinus10dBV;
2139 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 default:
2141 return -1;
2142
2143 }
2144 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2145 return 0;
2146}
2147
Takashi Iwai55e957d2005-11-17 14:52:13 +01002148static int snd_hdsp_info_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149{
Takashi Iwai8d678da2014-10-20 18:19:34 +02002150 static const char * const texts[] = {"Hi Gain", "+4 dBu", "-10 dbV"};
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002151
Takashi Iwai8d678da2014-10-20 18:19:34 +02002152 return snd_ctl_enum_info(uinfo, 1, 3, texts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153}
2154
Takashi Iwai55e957d2005-11-17 14:52:13 +01002155static int snd_hdsp_get_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002157 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002158
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp);
2160 return 0;
2161}
2162
Takashi Iwai55e957d2005-11-17 14:52:13 +01002163static int snd_hdsp_put_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002165 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 int change;
2167 int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002168
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 if (!snd_hdsp_use_is_exclusive(hdsp))
2170 return -EBUSY;
2171 val = ucontrol->value.enumerated.item[0];
2172 if (val < 0) val = 0;
2173 if (val > 2) val = 2;
2174 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002175 if (val != hdsp_da_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 change = (hdsp_set_da_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002177 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 spin_unlock_irq(&hdsp->lock);
2180 return change;
2181}
2182
2183#define HDSP_AD_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002184{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 .name = xname, \
2186 .index = xindex, \
2187 .info = snd_hdsp_info_ad_gain, \
2188 .get = snd_hdsp_get_ad_gain, \
2189 .put = snd_hdsp_put_ad_gain \
2190}
2191
Takashi Iwai55e957d2005-11-17 14:52:13 +01002192static int hdsp_ad_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193{
2194 switch (hdsp->control_register & HDSP_ADGainMask) {
2195 case HDSP_ADGainMinus10dBV:
2196 return 0;
2197 case HDSP_ADGainPlus4dBu:
2198 return 1;
2199 case HDSP_ADGainLowGain:
2200 return 2;
2201 default:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002202 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 }
2204}
2205
Takashi Iwai55e957d2005-11-17 14:52:13 +01002206static int hdsp_set_ad_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207{
2208 hdsp->control_register &= ~HDSP_ADGainMask;
2209 switch (mode) {
2210 case 0:
2211 hdsp->control_register |= HDSP_ADGainMinus10dBV;
2212 break;
2213 case 1:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002214 hdsp->control_register |= HDSP_ADGainPlus4dBu;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 break;
2216 case 2:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002217 hdsp->control_register |= HDSP_ADGainLowGain;
2218 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 default:
2220 return -1;
2221
2222 }
2223 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2224 return 0;
2225}
2226
Takashi Iwai55e957d2005-11-17 14:52:13 +01002227static int snd_hdsp_info_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228{
Takashi Iwai8d678da2014-10-20 18:19:34 +02002229 static const char * const texts[] = {"-10 dBV", "+4 dBu", "Lo Gain"};
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002230
Takashi Iwai8d678da2014-10-20 18:19:34 +02002231 return snd_ctl_enum_info(uinfo, 1, 3, texts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232}
2233
Takashi Iwai55e957d2005-11-17 14:52:13 +01002234static int snd_hdsp_get_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002236 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002237
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp);
2239 return 0;
2240}
2241
Takashi Iwai55e957d2005-11-17 14:52:13 +01002242static int snd_hdsp_put_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002244 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 int change;
2246 int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002247
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 if (!snd_hdsp_use_is_exclusive(hdsp))
2249 return -EBUSY;
2250 val = ucontrol->value.enumerated.item[0];
2251 if (val < 0) val = 0;
2252 if (val > 2) val = 2;
2253 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002254 if (val != hdsp_ad_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 change = (hdsp_set_ad_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002256 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 spin_unlock_irq(&hdsp->lock);
2259 return change;
2260}
2261
2262#define HDSP_PHONE_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002263{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264 .name = xname, \
2265 .index = xindex, \
2266 .info = snd_hdsp_info_phone_gain, \
2267 .get = snd_hdsp_get_phone_gain, \
2268 .put = snd_hdsp_put_phone_gain \
2269}
2270
Takashi Iwai55e957d2005-11-17 14:52:13 +01002271static int hdsp_phone_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272{
2273 switch (hdsp->control_register & HDSP_PhoneGainMask) {
2274 case HDSP_PhoneGain0dB:
2275 return 0;
2276 case HDSP_PhoneGainMinus6dB:
2277 return 1;
2278 case HDSP_PhoneGainMinus12dB:
2279 return 2;
2280 default:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002281 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 }
2283}
2284
Takashi Iwai55e957d2005-11-17 14:52:13 +01002285static int hdsp_set_phone_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286{
2287 hdsp->control_register &= ~HDSP_PhoneGainMask;
2288 switch (mode) {
2289 case 0:
2290 hdsp->control_register |= HDSP_PhoneGain0dB;
2291 break;
2292 case 1:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002293 hdsp->control_register |= HDSP_PhoneGainMinus6dB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 break;
2295 case 2:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002296 hdsp->control_register |= HDSP_PhoneGainMinus12dB;
2297 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 default:
2299 return -1;
2300
2301 }
2302 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2303 return 0;
2304}
2305
Takashi Iwai55e957d2005-11-17 14:52:13 +01002306static int snd_hdsp_info_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307{
Takashi Iwai8d678da2014-10-20 18:19:34 +02002308 static const char * const texts[] = {"0 dB", "-6 dB", "-12 dB"};
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002309
Takashi Iwai8d678da2014-10-20 18:19:34 +02002310 return snd_ctl_enum_info(uinfo, 1, 3, texts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311}
2312
Takashi Iwai55e957d2005-11-17 14:52:13 +01002313static int snd_hdsp_get_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002315 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002316
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp);
2318 return 0;
2319}
2320
Takashi Iwai55e957d2005-11-17 14:52:13 +01002321static int snd_hdsp_put_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002323 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 int change;
2325 int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002326
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 if (!snd_hdsp_use_is_exclusive(hdsp))
2328 return -EBUSY;
2329 val = ucontrol->value.enumerated.item[0];
2330 if (val < 0) val = 0;
2331 if (val > 2) val = 2;
2332 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002333 if (val != hdsp_phone_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 change = (hdsp_set_phone_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002335 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 spin_unlock_irq(&hdsp->lock);
2338 return change;
2339}
2340
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341#define HDSP_PREF_SYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002342{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343 .name = xname, \
2344 .index = xindex, \
2345 .info = snd_hdsp_info_pref_sync_ref, \
2346 .get = snd_hdsp_get_pref_sync_ref, \
2347 .put = snd_hdsp_put_pref_sync_ref \
2348}
2349
Takashi Iwai55e957d2005-11-17 14:52:13 +01002350static int hdsp_pref_sync_ref(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351{
2352 /* Notice that this looks at the requested sync source,
2353 not the one actually in use.
2354 */
2355
2356 switch (hdsp->control_register & HDSP_SyncRefMask) {
2357 case HDSP_SyncRef_ADAT1:
2358 return HDSP_SYNC_FROM_ADAT1;
2359 case HDSP_SyncRef_ADAT2:
2360 return HDSP_SYNC_FROM_ADAT2;
2361 case HDSP_SyncRef_ADAT3:
2362 return HDSP_SYNC_FROM_ADAT3;
2363 case HDSP_SyncRef_SPDIF:
2364 return HDSP_SYNC_FROM_SPDIF;
2365 case HDSP_SyncRef_WORD:
2366 return HDSP_SYNC_FROM_WORD;
2367 case HDSP_SyncRef_ADAT_SYNC:
2368 return HDSP_SYNC_FROM_ADAT_SYNC;
2369 default:
2370 return HDSP_SYNC_FROM_WORD;
2371 }
2372 return 0;
2373}
2374
Takashi Iwai55e957d2005-11-17 14:52:13 +01002375static int hdsp_set_pref_sync_ref(struct hdsp *hdsp, int pref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376{
2377 hdsp->control_register &= ~HDSP_SyncRefMask;
2378 switch (pref) {
2379 case HDSP_SYNC_FROM_ADAT1:
2380 hdsp->control_register &= ~HDSP_SyncRefMask; /* clear SyncRef bits */
2381 break;
2382 case HDSP_SYNC_FROM_ADAT2:
2383 hdsp->control_register |= HDSP_SyncRef_ADAT2;
2384 break;
2385 case HDSP_SYNC_FROM_ADAT3:
2386 hdsp->control_register |= HDSP_SyncRef_ADAT3;
2387 break;
2388 case HDSP_SYNC_FROM_SPDIF:
2389 hdsp->control_register |= HDSP_SyncRef_SPDIF;
2390 break;
2391 case HDSP_SYNC_FROM_WORD:
2392 hdsp->control_register |= HDSP_SyncRef_WORD;
2393 break;
2394 case HDSP_SYNC_FROM_ADAT_SYNC:
2395 hdsp->control_register |= HDSP_SyncRef_ADAT_SYNC;
2396 break;
2397 default:
2398 return -1;
2399 }
2400 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2401 return 0;
2402}
2403
Takashi Iwai55e957d2005-11-17 14:52:13 +01002404static int snd_hdsp_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405{
Takashi Iwai8d678da2014-10-20 18:19:34 +02002406 static const char * const texts[] = {
2407 "Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3"
2408 };
Takashi Iwai55e957d2005-11-17 14:52:13 +01002409 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Takashi Iwai8d678da2014-10-20 18:19:34 +02002410 int num_items;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411
2412 switch (hdsp->io_type) {
2413 case Digiface:
2414 case H9652:
Takashi Iwai8d678da2014-10-20 18:19:34 +02002415 num_items = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416 break;
2417 case Multiface:
Takashi Iwai8d678da2014-10-20 18:19:34 +02002418 num_items = 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 break;
2420 case H9632:
Takashi Iwai8d678da2014-10-20 18:19:34 +02002421 num_items = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422 break;
2423 default:
Takashi Iwai9badda02012-01-09 18:22:35 +01002424 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002426
Takashi Iwai8d678da2014-10-20 18:19:34 +02002427 return snd_ctl_enum_info(uinfo, 1, num_items, texts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428}
2429
Takashi Iwai55e957d2005-11-17 14:52:13 +01002430static int snd_hdsp_get_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002432 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002433
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434 ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp);
2435 return 0;
2436}
2437
Takashi Iwai55e957d2005-11-17 14:52:13 +01002438static int snd_hdsp_put_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002440 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441 int change, max;
2442 unsigned int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002443
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 if (!snd_hdsp_use_is_exclusive(hdsp))
2445 return -EBUSY;
2446
2447 switch (hdsp->io_type) {
2448 case Digiface:
2449 case H9652:
2450 max = 6;
2451 break;
2452 case Multiface:
2453 max = 4;
2454 break;
2455 case H9632:
2456 max = 3;
2457 break;
2458 default:
2459 return -EIO;
2460 }
2461
2462 val = ucontrol->value.enumerated.item[0] % max;
2463 spin_lock_irq(&hdsp->lock);
2464 change = (int)val != hdsp_pref_sync_ref(hdsp);
2465 hdsp_set_pref_sync_ref(hdsp, val);
2466 spin_unlock_irq(&hdsp->lock);
2467 return change;
2468}
2469
2470#define HDSP_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002471{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 .name = xname, \
2473 .index = xindex, \
2474 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2475 .info = snd_hdsp_info_autosync_ref, \
2476 .get = snd_hdsp_get_autosync_ref, \
2477}
2478
Takashi Iwai55e957d2005-11-17 14:52:13 +01002479static int hdsp_autosync_ref(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480{
2481 /* This looks at the autosync selected sync reference */
2482 unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
2483
2484 switch (status2 & HDSP_SelSyncRefMask) {
2485 case HDSP_SelSyncRef_WORD:
2486 return HDSP_AUTOSYNC_FROM_WORD;
2487 case HDSP_SelSyncRef_ADAT_SYNC:
2488 return HDSP_AUTOSYNC_FROM_ADAT_SYNC;
2489 case HDSP_SelSyncRef_SPDIF:
2490 return HDSP_AUTOSYNC_FROM_SPDIF;
2491 case HDSP_SelSyncRefMask:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002492 return HDSP_AUTOSYNC_FROM_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493 case HDSP_SelSyncRef_ADAT1:
2494 return HDSP_AUTOSYNC_FROM_ADAT1;
2495 case HDSP_SelSyncRef_ADAT2:
2496 return HDSP_AUTOSYNC_FROM_ADAT2;
2497 case HDSP_SelSyncRef_ADAT3:
2498 return HDSP_AUTOSYNC_FROM_ADAT3;
2499 default:
2500 return HDSP_AUTOSYNC_FROM_WORD;
2501 }
2502 return 0;
2503}
2504
Takashi Iwai55e957d2005-11-17 14:52:13 +01002505static int snd_hdsp_info_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506{
Takashi Iwai8d678da2014-10-20 18:19:34 +02002507 static const char * const texts[] = {
2508 "Word", "ADAT Sync", "IEC958", "None", "ADAT1", "ADAT2", "ADAT3"
2509 };
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002510
Takashi Iwai8d678da2014-10-20 18:19:34 +02002511 return snd_ctl_enum_info(uinfo, 1, 7, texts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512}
2513
Takashi Iwai55e957d2005-11-17 14:52:13 +01002514static int snd_hdsp_get_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002516 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002517
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518 ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp);
2519 return 0;
2520}
2521
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522#define HDSP_PRECISE_POINTER(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002523{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524 .name = xname, \
2525 .index = xindex, \
2526 .info = snd_hdsp_info_precise_pointer, \
2527 .get = snd_hdsp_get_precise_pointer, \
2528 .put = snd_hdsp_put_precise_pointer \
2529}
2530
Takashi Iwai55e957d2005-11-17 14:52:13 +01002531static int hdsp_set_precise_pointer(struct hdsp *hdsp, int precise)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002533 if (precise)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534 hdsp->precise_ptr = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002535 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536 hdsp->precise_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537 return 0;
2538}
2539
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002540#define snd_hdsp_info_precise_pointer snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541
Takashi Iwai55e957d2005-11-17 14:52:13 +01002542static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002544 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002545
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546 spin_lock_irq(&hdsp->lock);
2547 ucontrol->value.integer.value[0] = hdsp->precise_ptr;
2548 spin_unlock_irq(&hdsp->lock);
2549 return 0;
2550}
2551
Takashi Iwai55e957d2005-11-17 14:52:13 +01002552static int snd_hdsp_put_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002554 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 int change;
2556 unsigned int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002557
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558 if (!snd_hdsp_use_is_exclusive(hdsp))
2559 return -EBUSY;
2560 val = ucontrol->value.integer.value[0] & 1;
2561 spin_lock_irq(&hdsp->lock);
2562 change = (int)val != hdsp->precise_ptr;
2563 hdsp_set_precise_pointer(hdsp, val);
2564 spin_unlock_irq(&hdsp->lock);
2565 return change;
2566}
2567
2568#define HDSP_USE_MIDI_TASKLET(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002569{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 .name = xname, \
2571 .index = xindex, \
2572 .info = snd_hdsp_info_use_midi_tasklet, \
2573 .get = snd_hdsp_get_use_midi_tasklet, \
2574 .put = snd_hdsp_put_use_midi_tasklet \
2575}
2576
Takashi Iwai55e957d2005-11-17 14:52:13 +01002577static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002579 if (use_tasklet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 hdsp->use_midi_tasklet = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002581 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 hdsp->use_midi_tasklet = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 return 0;
2584}
2585
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002586#define snd_hdsp_info_use_midi_tasklet snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587
Takashi Iwai55e957d2005-11-17 14:52:13 +01002588static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002590 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002591
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 spin_lock_irq(&hdsp->lock);
2593 ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet;
2594 spin_unlock_irq(&hdsp->lock);
2595 return 0;
2596}
2597
Takashi Iwai55e957d2005-11-17 14:52:13 +01002598static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002600 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 int change;
2602 unsigned int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002603
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 if (!snd_hdsp_use_is_exclusive(hdsp))
2605 return -EBUSY;
2606 val = ucontrol->value.integer.value[0] & 1;
2607 spin_lock_irq(&hdsp->lock);
2608 change = (int)val != hdsp->use_midi_tasklet;
2609 hdsp_set_use_midi_tasklet(hdsp, val);
2610 spin_unlock_irq(&hdsp->lock);
2611 return change;
2612}
2613
2614#define HDSP_MIXER(xname, xindex) \
2615{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
2616 .name = xname, \
2617 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002618 .device = 0, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2620 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2621 .info = snd_hdsp_info_mixer, \
2622 .get = snd_hdsp_get_mixer, \
2623 .put = snd_hdsp_put_mixer \
2624}
2625
Takashi Iwai55e957d2005-11-17 14:52:13 +01002626static int snd_hdsp_info_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627{
2628 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2629 uinfo->count = 3;
2630 uinfo->value.integer.min = 0;
2631 uinfo->value.integer.max = 65536;
2632 uinfo->value.integer.step = 1;
2633 return 0;
2634}
2635
Takashi Iwai55e957d2005-11-17 14:52:13 +01002636static int snd_hdsp_get_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002638 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 int source;
2640 int destination;
2641 int addr;
2642
2643 source = ucontrol->value.integer.value[0];
2644 destination = ucontrol->value.integer.value[1];
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002645
Takashi Iwaib0b98112005-10-20 18:29:58 +02002646 if (source >= hdsp->max_channels)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647 addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels,destination);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002648 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 addr = hdsp_input_to_output_key(hdsp,source, destination);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002650
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651 spin_lock_irq(&hdsp->lock);
2652 ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr);
2653 spin_unlock_irq(&hdsp->lock);
2654 return 0;
2655}
2656
Takashi Iwai55e957d2005-11-17 14:52:13 +01002657static int snd_hdsp_put_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002659 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660 int change;
2661 int source;
2662 int destination;
2663 int gain;
2664 int addr;
2665
2666 if (!snd_hdsp_use_is_exclusive(hdsp))
2667 return -EBUSY;
2668
2669 source = ucontrol->value.integer.value[0];
2670 destination = ucontrol->value.integer.value[1];
2671
Takashi Iwaib0b98112005-10-20 18:29:58 +02002672 if (source >= hdsp->max_channels)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels, destination);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002674 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675 addr = hdsp_input_to_output_key(hdsp,source, destination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676
2677 gain = ucontrol->value.integer.value[2];
2678
2679 spin_lock_irq(&hdsp->lock);
2680 change = gain != hdsp_read_gain(hdsp, addr);
2681 if (change)
2682 hdsp_write_gain(hdsp, addr, gain);
2683 spin_unlock_irq(&hdsp->lock);
2684 return change;
2685}
2686
2687#define HDSP_WC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002688{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689 .name = xname, \
2690 .index = xindex, \
2691 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2692 .info = snd_hdsp_info_sync_check, \
2693 .get = snd_hdsp_get_wc_sync_check \
2694}
2695
Takashi Iwai55e957d2005-11-17 14:52:13 +01002696static int snd_hdsp_info_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697{
Takashi Iwai8d678da2014-10-20 18:19:34 +02002698 static const char * const texts[] = {"No Lock", "Lock", "Sync" };
2699
2700 return snd_ctl_enum_info(uinfo, 1, 3, texts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701}
2702
Takashi Iwai55e957d2005-11-17 14:52:13 +01002703static int hdsp_wc_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704{
2705 int status2 = hdsp_read(hdsp, HDSP_status2Register);
2706 if (status2 & HDSP_wc_lock) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002707 if (status2 & HDSP_wc_sync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002709 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002711 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 return 0;
2714}
2715
Takashi Iwai55e957d2005-11-17 14:52:13 +01002716static int snd_hdsp_get_wc_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002718 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719
2720 ucontrol->value.enumerated.item[0] = hdsp_wc_sync_check(hdsp);
2721 return 0;
2722}
2723
2724#define HDSP_SPDIF_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002725{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 .name = xname, \
2727 .index = xindex, \
2728 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2729 .info = snd_hdsp_info_sync_check, \
2730 .get = snd_hdsp_get_spdif_sync_check \
2731}
2732
Takashi Iwai55e957d2005-11-17 14:52:13 +01002733static int hdsp_spdif_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734{
2735 int status = hdsp_read(hdsp, HDSP_statusRegister);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002736 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 return 0;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002738 else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002739 if (status & HDSP_SPDIFSync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002741 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 }
2744 return 0;
2745}
2746
Takashi Iwai55e957d2005-11-17 14:52:13 +01002747static int snd_hdsp_get_spdif_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002749 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750
2751 ucontrol->value.enumerated.item[0] = hdsp_spdif_sync_check(hdsp);
2752 return 0;
2753}
2754
2755#define HDSP_ADATSYNC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002756{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757 .name = xname, \
2758 .index = xindex, \
2759 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2760 .info = snd_hdsp_info_sync_check, \
2761 .get = snd_hdsp_get_adatsync_sync_check \
2762}
2763
Takashi Iwai55e957d2005-11-17 14:52:13 +01002764static int hdsp_adatsync_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765{
2766 int status = hdsp_read(hdsp, HDSP_statusRegister);
2767 if (status & HDSP_TimecodeLock) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002768 if (status & HDSP_TimecodeSync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002770 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002772 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 return 0;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002774}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775
Takashi Iwai55e957d2005-11-17 14:52:13 +01002776static int snd_hdsp_get_adatsync_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002778 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779
2780 ucontrol->value.enumerated.item[0] = hdsp_adatsync_sync_check(hdsp);
2781 return 0;
2782}
2783
2784#define HDSP_ADAT_SYNC_CHECK \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002785{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2787 .info = snd_hdsp_info_sync_check, \
2788 .get = snd_hdsp_get_adat_sync_check \
2789}
2790
Takashi Iwai55e957d2005-11-17 14:52:13 +01002791static int hdsp_adat_sync_check(struct hdsp *hdsp, int idx)
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002792{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 int status = hdsp_read(hdsp, HDSP_statusRegister);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002794
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795 if (status & (HDSP_Lock0>>idx)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002796 if (status & (HDSP_Sync0>>idx))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002798 else
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002799 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002800 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801 return 0;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002802}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803
Takashi Iwai55e957d2005-11-17 14:52:13 +01002804static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805{
2806 int offset;
Takashi Iwai55e957d2005-11-17 14:52:13 +01002807 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808
2809 offset = ucontrol->id.index - 1;
Dan Carpenter9e46aed2015-08-21 14:25:34 +03002810 if (snd_BUG_ON(offset < 0))
2811 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812
2813 switch (hdsp->io_type) {
2814 case Digiface:
2815 case H9652:
2816 if (offset >= 3)
2817 return -EINVAL;
2818 break;
2819 case Multiface:
2820 case H9632:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002821 if (offset >= 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 return -EINVAL;
2823 break;
2824 default:
2825 return -EIO;
2826 }
2827
2828 ucontrol->value.enumerated.item[0] = hdsp_adat_sync_check(hdsp, offset);
2829 return 0;
2830}
2831
Julian Cablee4b60882007-03-19 11:44:40 +01002832#define HDSP_DDS_OFFSET(xname, xindex) \
2833{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2834 .name = xname, \
2835 .index = xindex, \
2836 .info = snd_hdsp_info_dds_offset, \
2837 .get = snd_hdsp_get_dds_offset, \
2838 .put = snd_hdsp_put_dds_offset \
2839}
2840
2841static int hdsp_dds_offset(struct hdsp *hdsp)
2842{
2843 u64 n;
Julian Cablee4b60882007-03-19 11:44:40 +01002844 unsigned int dds_value = hdsp->dds_value;
2845 int system_sample_rate = hdsp->system_sample_rate;
2846
Takashi Iwai2a3988f2007-10-16 14:26:32 +02002847 if (!dds_value)
2848 return 0;
2849
Julian Cablee4b60882007-03-19 11:44:40 +01002850 n = DDS_NUMERATOR;
2851 /*
2852 * dds_value = n / rate
2853 * rate = n / dds_value
2854 */
Takashi Iwai3f7440a2009-06-05 17:40:04 +02002855 n = div_u64(n, dds_value);
Julian Cablee4b60882007-03-19 11:44:40 +01002856 if (system_sample_rate >= 112000)
2857 n *= 4;
2858 else if (system_sample_rate >= 56000)
2859 n *= 2;
2860 return ((int)n) - system_sample_rate;
2861}
2862
2863static int hdsp_set_dds_offset(struct hdsp *hdsp, int offset_hz)
2864{
2865 int rate = hdsp->system_sample_rate + offset_hz;
2866 hdsp_set_dds_value(hdsp, rate);
2867 return 0;
2868}
2869
2870static int snd_hdsp_info_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
2871{
2872 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2873 uinfo->count = 1;
2874 uinfo->value.integer.min = -5000;
2875 uinfo->value.integer.max = 5000;
2876 return 0;
2877}
2878
2879static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2880{
2881 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002882
Takashi Iwaieab3c4d2016-02-29 14:26:43 +01002883 ucontrol->value.integer.value[0] = hdsp_dds_offset(hdsp);
Julian Cablee4b60882007-03-19 11:44:40 +01002884 return 0;
2885}
2886
2887static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2888{
2889 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
2890 int change;
2891 int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002892
Julian Cablee4b60882007-03-19 11:44:40 +01002893 if (!snd_hdsp_use_is_exclusive(hdsp))
2894 return -EBUSY;
Takashi Iwaieab3c4d2016-02-29 14:26:43 +01002895 val = ucontrol->value.integer.value[0];
Julian Cablee4b60882007-03-19 11:44:40 +01002896 spin_lock_irq(&hdsp->lock);
2897 if (val != hdsp_dds_offset(hdsp))
2898 change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0;
2899 else
2900 change = 0;
2901 spin_unlock_irq(&hdsp->lock);
2902 return change;
2903}
2904
Takashi Iwai55e957d2005-11-17 14:52:13 +01002905static struct snd_kcontrol_new snd_hdsp_9632_controls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906HDSP_DA_GAIN("DA Gain", 0),
2907HDSP_AD_GAIN("AD Gain", 0),
2908HDSP_PHONE_GAIN("Phones Gain", 0),
Adrian Knoth4833c672013-01-15 18:52:22 +01002909HDSP_TOGGLE_SETTING("XLR Breakout Cable", HDSP_XLRBreakoutCable),
Julian Cablee4b60882007-03-19 11:44:40 +01002910HDSP_DDS_OFFSET("DDS Sample Rate Offset", 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911};
2912
Takashi Iwai55e957d2005-11-17 14:52:13 +01002913static struct snd_kcontrol_new snd_hdsp_controls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914{
Clemens Ladisch5549d542005-08-03 13:50:30 +02002915 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2917 .info = snd_hdsp_control_spdif_info,
2918 .get = snd_hdsp_control_spdif_get,
2919 .put = snd_hdsp_control_spdif_put,
2920},
2921{
2922 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch5549d542005-08-03 13:50:30 +02002923 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
2925 .info = snd_hdsp_control_spdif_stream_info,
2926 .get = snd_hdsp_control_spdif_stream_get,
2927 .put = snd_hdsp_control_spdif_stream_put,
2928},
2929{
2930 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +02002931 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2933 .info = snd_hdsp_control_spdif_mask_info,
2934 .get = snd_hdsp_control_spdif_mask_get,
2935 .private_value = IEC958_AES0_NONAUDIO |
2936 IEC958_AES0_PROFESSIONAL |
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002937 IEC958_AES0_CON_EMPHASIS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938},
2939{
2940 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +02002941 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002942 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2943 .info = snd_hdsp_control_spdif_mask_info,
2944 .get = snd_hdsp_control_spdif_mask_get,
2945 .private_value = IEC958_AES0_NONAUDIO |
2946 IEC958_AES0_PROFESSIONAL |
2947 IEC958_AES0_PRO_EMPHASIS,
2948},
2949HDSP_MIXER("Mixer", 0),
2950HDSP_SPDIF_IN("IEC958 Input Connector", 0),
Adrian Knoth4833c672013-01-15 18:52:22 +01002951HDSP_TOGGLE_SETTING("IEC958 Output also on ADAT1", HDSP_SPDIFOpticalOut),
2952HDSP_TOGGLE_SETTING("IEC958 Professional Bit", HDSP_SPDIFProfessional),
2953HDSP_TOGGLE_SETTING("IEC958 Emphasis Bit", HDSP_SPDIFEmphasis),
2954HDSP_TOGGLE_SETTING("IEC958 Non-audio Bit", HDSP_SPDIFNonAudio),
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002955/* 'Sample Clock Source' complies with the alsa control naming scheme */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956HDSP_CLOCK_SOURCE("Sample Clock Source", 0),
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002957{
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002958 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2959 .name = "Sample Clock Source Locking",
2960 .info = snd_hdsp_info_clock_source_lock,
2961 .get = snd_hdsp_get_clock_source_lock,
2962 .put = snd_hdsp_put_clock_source_lock,
2963},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964HDSP_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
2965HDSP_PREF_SYNC_REF("Preferred Sync Reference", 0),
2966HDSP_AUTOSYNC_REF("AutoSync Reference", 0),
2967HDSP_SPDIF_SAMPLE_RATE("SPDIF Sample Rate", 0),
2968HDSP_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
2969/* 'External Rate' complies with the alsa control naming scheme */
2970HDSP_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
2971HDSP_WC_SYNC_CHECK("Word Clock Lock Status", 0),
2972HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0),
2973HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0),
Adrian Knoth4833c672013-01-15 18:52:22 +01002974HDSP_TOGGLE_SETTING("Line Out", HDSP_LineOut),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975HDSP_PRECISE_POINTER("Precise Pointer", 0),
2976HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0),
2977};
2978
Florian Faber28b26e12010-12-01 12:14:47 +01002979
2980static int hdsp_rpm_input12(struct hdsp *hdsp)
2981{
2982 switch (hdsp->control_register & HDSP_RPM_Inp12) {
2983 case HDSP_RPM_Inp12_Phon_6dB:
2984 return 0;
2985 case HDSP_RPM_Inp12_Phon_n6dB:
2986 return 2;
2987 case HDSP_RPM_Inp12_Line_0dB:
2988 return 3;
2989 case HDSP_RPM_Inp12_Line_n6dB:
2990 return 4;
2991 }
2992 return 1;
2993}
2994
2995
2996static int snd_hdsp_get_rpm_input12(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2997{
2998 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
2999
3000 ucontrol->value.enumerated.item[0] = hdsp_rpm_input12(hdsp);
3001 return 0;
3002}
3003
3004
3005static int hdsp_set_rpm_input12(struct hdsp *hdsp, int mode)
3006{
3007 hdsp->control_register &= ~HDSP_RPM_Inp12;
3008 switch (mode) {
3009 case 0:
3010 hdsp->control_register |= HDSP_RPM_Inp12_Phon_6dB;
3011 break;
3012 case 1:
3013 break;
3014 case 2:
3015 hdsp->control_register |= HDSP_RPM_Inp12_Phon_n6dB;
3016 break;
3017 case 3:
3018 hdsp->control_register |= HDSP_RPM_Inp12_Line_0dB;
3019 break;
3020 case 4:
3021 hdsp->control_register |= HDSP_RPM_Inp12_Line_n6dB;
3022 break;
3023 default:
3024 return -1;
3025 }
3026
3027 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3028 return 0;
3029}
3030
3031
3032static int snd_hdsp_put_rpm_input12(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3033{
3034 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3035 int change;
3036 int val;
3037
3038 if (!snd_hdsp_use_is_exclusive(hdsp))
3039 return -EBUSY;
3040 val = ucontrol->value.enumerated.item[0];
3041 if (val < 0)
3042 val = 0;
3043 if (val > 4)
3044 val = 4;
3045 spin_lock_irq(&hdsp->lock);
3046 if (val != hdsp_rpm_input12(hdsp))
3047 change = (hdsp_set_rpm_input12(hdsp, val) == 0) ? 1 : 0;
3048 else
3049 change = 0;
3050 spin_unlock_irq(&hdsp->lock);
3051 return change;
3052}
3053
3054
3055static int snd_hdsp_info_rpm_input(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3056{
Takashi Iwai8d678da2014-10-20 18:19:34 +02003057 static const char * const texts[] = {
3058 "Phono +6dB", "Phono 0dB", "Phono -6dB", "Line 0dB", "Line -6dB"
3059 };
Florian Faber28b26e12010-12-01 12:14:47 +01003060
Takashi Iwai8d678da2014-10-20 18:19:34 +02003061 return snd_ctl_enum_info(uinfo, 1, 5, texts);
Florian Faber28b26e12010-12-01 12:14:47 +01003062}
3063
3064
3065static int hdsp_rpm_input34(struct hdsp *hdsp)
3066{
3067 switch (hdsp->control_register & HDSP_RPM_Inp34) {
3068 case HDSP_RPM_Inp34_Phon_6dB:
3069 return 0;
3070 case HDSP_RPM_Inp34_Phon_n6dB:
3071 return 2;
3072 case HDSP_RPM_Inp34_Line_0dB:
3073 return 3;
3074 case HDSP_RPM_Inp34_Line_n6dB:
3075 return 4;
3076 }
3077 return 1;
3078}
3079
3080
3081static int snd_hdsp_get_rpm_input34(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3082{
3083 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3084
3085 ucontrol->value.enumerated.item[0] = hdsp_rpm_input34(hdsp);
3086 return 0;
3087}
3088
3089
3090static int hdsp_set_rpm_input34(struct hdsp *hdsp, int mode)
3091{
3092 hdsp->control_register &= ~HDSP_RPM_Inp34;
3093 switch (mode) {
3094 case 0:
3095 hdsp->control_register |= HDSP_RPM_Inp34_Phon_6dB;
3096 break;
3097 case 1:
3098 break;
3099 case 2:
3100 hdsp->control_register |= HDSP_RPM_Inp34_Phon_n6dB;
3101 break;
3102 case 3:
3103 hdsp->control_register |= HDSP_RPM_Inp34_Line_0dB;
3104 break;
3105 case 4:
3106 hdsp->control_register |= HDSP_RPM_Inp34_Line_n6dB;
3107 break;
3108 default:
3109 return -1;
3110 }
3111
3112 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3113 return 0;
3114}
3115
3116
3117static int snd_hdsp_put_rpm_input34(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3118{
3119 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3120 int change;
3121 int val;
3122
3123 if (!snd_hdsp_use_is_exclusive(hdsp))
3124 return -EBUSY;
3125 val = ucontrol->value.enumerated.item[0];
3126 if (val < 0)
3127 val = 0;
3128 if (val > 4)
3129 val = 4;
3130 spin_lock_irq(&hdsp->lock);
3131 if (val != hdsp_rpm_input34(hdsp))
3132 change = (hdsp_set_rpm_input34(hdsp, val) == 0) ? 1 : 0;
3133 else
3134 change = 0;
3135 spin_unlock_irq(&hdsp->lock);
3136 return change;
3137}
3138
3139
3140/* RPM Bypass switch */
3141static int hdsp_rpm_bypass(struct hdsp *hdsp)
3142{
3143 return (hdsp->control_register & HDSP_RPM_Bypass) ? 1 : 0;
3144}
3145
3146
3147static int snd_hdsp_get_rpm_bypass(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3148{
3149 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3150
3151 ucontrol->value.integer.value[0] = hdsp_rpm_bypass(hdsp);
3152 return 0;
3153}
3154
3155
3156static int hdsp_set_rpm_bypass(struct hdsp *hdsp, int on)
3157{
3158 if (on)
3159 hdsp->control_register |= HDSP_RPM_Bypass;
3160 else
3161 hdsp->control_register &= ~HDSP_RPM_Bypass;
3162 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3163 return 0;
3164}
3165
3166
3167static int snd_hdsp_put_rpm_bypass(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3168{
3169 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3170 int change;
3171 unsigned int val;
3172
3173 if (!snd_hdsp_use_is_exclusive(hdsp))
3174 return -EBUSY;
3175 val = ucontrol->value.integer.value[0] & 1;
3176 spin_lock_irq(&hdsp->lock);
3177 change = (int)val != hdsp_rpm_bypass(hdsp);
3178 hdsp_set_rpm_bypass(hdsp, val);
3179 spin_unlock_irq(&hdsp->lock);
3180 return change;
3181}
3182
3183
3184static int snd_hdsp_info_rpm_bypass(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3185{
Takashi Iwai8d678da2014-10-20 18:19:34 +02003186 static const char * const texts[] = {"On", "Off"};
Florian Faber28b26e12010-12-01 12:14:47 +01003187
Takashi Iwai8d678da2014-10-20 18:19:34 +02003188 return snd_ctl_enum_info(uinfo, 1, 2, texts);
Florian Faber28b26e12010-12-01 12:14:47 +01003189}
3190
3191
3192/* RPM Disconnect switch */
3193static int hdsp_rpm_disconnect(struct hdsp *hdsp)
3194{
3195 return (hdsp->control_register & HDSP_RPM_Disconnect) ? 1 : 0;
3196}
3197
3198
3199static int snd_hdsp_get_rpm_disconnect(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3200{
3201 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3202
3203 ucontrol->value.integer.value[0] = hdsp_rpm_disconnect(hdsp);
3204 return 0;
3205}
3206
3207
3208static int hdsp_set_rpm_disconnect(struct hdsp *hdsp, int on)
3209{
3210 if (on)
3211 hdsp->control_register |= HDSP_RPM_Disconnect;
3212 else
3213 hdsp->control_register &= ~HDSP_RPM_Disconnect;
3214 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3215 return 0;
3216}
3217
3218
3219static int snd_hdsp_put_rpm_disconnect(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3220{
3221 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3222 int change;
3223 unsigned int val;
3224
3225 if (!snd_hdsp_use_is_exclusive(hdsp))
3226 return -EBUSY;
3227 val = ucontrol->value.integer.value[0] & 1;
3228 spin_lock_irq(&hdsp->lock);
3229 change = (int)val != hdsp_rpm_disconnect(hdsp);
3230 hdsp_set_rpm_disconnect(hdsp, val);
3231 spin_unlock_irq(&hdsp->lock);
3232 return change;
3233}
3234
3235static int snd_hdsp_info_rpm_disconnect(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3236{
Takashi Iwai8d678da2014-10-20 18:19:34 +02003237 static const char * const texts[] = {"On", "Off"};
Florian Faber28b26e12010-12-01 12:14:47 +01003238
Takashi Iwai8d678da2014-10-20 18:19:34 +02003239 return snd_ctl_enum_info(uinfo, 1, 2, texts);
Florian Faber28b26e12010-12-01 12:14:47 +01003240}
3241
3242static struct snd_kcontrol_new snd_hdsp_rpm_controls[] = {
3243 {
3244 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3245 .name = "RPM Bypass",
3246 .get = snd_hdsp_get_rpm_bypass,
3247 .put = snd_hdsp_put_rpm_bypass,
3248 .info = snd_hdsp_info_rpm_bypass
3249 },
3250 {
3251 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3252 .name = "RPM Disconnect",
3253 .get = snd_hdsp_get_rpm_disconnect,
3254 .put = snd_hdsp_put_rpm_disconnect,
3255 .info = snd_hdsp_info_rpm_disconnect
3256 },
3257 {
3258 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3259 .name = "Input 1/2",
3260 .get = snd_hdsp_get_rpm_input12,
3261 .put = snd_hdsp_put_rpm_input12,
3262 .info = snd_hdsp_info_rpm_input
3263 },
3264 {
3265 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3266 .name = "Input 3/4",
3267 .get = snd_hdsp_get_rpm_input34,
3268 .put = snd_hdsp_put_rpm_input34,
3269 .info = snd_hdsp_info_rpm_input
3270 },
3271 HDSP_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
3272 HDSP_MIXER("Mixer", 0)
3273};
3274
Adrian Knoth4833c672013-01-15 18:52:22 +01003275static struct snd_kcontrol_new snd_hdsp_96xx_aeb =
3276 HDSP_TOGGLE_SETTING("Analog Extension Board",
3277 HDSP_AnalogExtensionBoard);
Takashi Iwai55e957d2005-11-17 14:52:13 +01003278static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279
Takashi Iwai55e957d2005-11-17 14:52:13 +01003280static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281{
3282 unsigned int idx;
3283 int err;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003284 struct snd_kcontrol *kctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285
Florian Faber28b26e12010-12-01 12:14:47 +01003286 if (hdsp->io_type == RPM) {
3287 /* RPM Bypass, Disconnect and Input switches */
3288 for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_rpm_controls); idx++) {
3289 err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_rpm_controls[idx], hdsp));
3290 if (err < 0)
3291 return err;
3292 }
3293 return 0;
3294 }
3295
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296 for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003297 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299 if (idx == 1) /* IEC958 (S/PDIF) Stream */
3300 hdsp->spdif_ctl = kctl;
3301 }
3302
3303 /* ADAT SyncCheck status */
3304 snd_hdsp_adat_sync_check.name = "ADAT Lock Status";
3305 snd_hdsp_adat_sync_check.index = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003306 if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003308 if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
3309 for (idx = 1; idx < 3; ++idx) {
3310 snd_hdsp_adat_sync_check.index = idx+1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003311 if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313 }
3314 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003315
Linus Torvalds1da177e2005-04-16 15:20:36 -07003316 /* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */
3317 if (hdsp->io_type == H9632) {
3318 for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003319 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003320 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321 }
3322 }
3323
3324 /* AEB control for H96xx card */
3325 if (hdsp->io_type == H9632 || hdsp->io_type == H9652) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003326 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003327 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328 }
3329
3330 return 0;
3331}
3332
3333/*------------------------------------------------------------
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003334 /proc interface
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335 ------------------------------------------------------------*/
3336
3337static void
Takashi Iwai55e957d2005-11-17 14:52:13 +01003338snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339{
Joe Perches9fe856e2010-09-04 18:52:54 -07003340 struct hdsp *hdsp = entry->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003341 unsigned int status;
3342 unsigned int status2;
3343 char *pref_sync_ref;
3344 char *autosync_ref;
3345 char *system_clock_mode;
3346 char *clock_source;
3347 int x;
3348
Tim Blechmannc18bc9b2009-08-12 18:21:30 +02003349 status = hdsp_read(hdsp, HDSP_statusRegister);
3350 status2 = hdsp_read(hdsp, HDSP_status2Register);
3351
3352 snd_iprintf(buffer, "%s (Card #%d)\n", hdsp->card_name,
3353 hdsp->card->number + 1);
3354 snd_iprintf(buffer, "Buffers: capture %p playback %p\n",
3355 hdsp->capture_buffer, hdsp->playback_buffer);
3356 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
3357 hdsp->irq, hdsp->port, (unsigned long)hdsp->iobase);
3358 snd_iprintf(buffer, "Control register: 0x%x\n", hdsp->control_register);
3359 snd_iprintf(buffer, "Control2 register: 0x%x\n",
3360 hdsp->control2_register);
3361 snd_iprintf(buffer, "Status register: 0x%x\n", status);
3362 snd_iprintf(buffer, "Status2 register: 0x%x\n", status2);
3363
3364 if (hdsp_check_for_iobox(hdsp)) {
3365 snd_iprintf(buffer, "No I/O box connected.\n"
3366 "Please connect one and upload firmware.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367 return;
Tim Blechmannc18bc9b2009-08-12 18:21:30 +02003368 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369
Takashi Iwaib0b98112005-10-20 18:29:58 +02003370 if (hdsp_check_for_firmware(hdsp, 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371 if (hdsp->state & HDSP_FirmwareCached) {
3372 if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
Tim Blechmannc18bc9b2009-08-12 18:21:30 +02003373 snd_iprintf(buffer, "Firmware loading from "
3374 "cache failed, "
3375 "please upload manually.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376 return;
3377 }
3378 } else {
Takashi Iwai311e70a2006-09-06 12:13:37 +02003379 int err = -EINVAL;
Takashi Iwai311e70a2006-09-06 12:13:37 +02003380 err = hdsp_request_fw_loader(hdsp);
Takashi Iwai311e70a2006-09-06 12:13:37 +02003381 if (err < 0) {
3382 snd_iprintf(buffer,
3383 "No firmware loaded nor cached, "
3384 "please upload firmware.\n");
3385 return;
3386 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387 }
3388 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003389
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390 snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff);
3391 snd_iprintf(buffer, "MIDI1 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut0));
3392 snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0));
3393 snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1));
3394 snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1));
3395 snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off");
3396
3397 snd_iprintf(buffer, "\n");
3398
3399 x = 1 << (6 + hdsp_decode_latency(hdsp->control_register & HDSP_LatencyMask));
3400
3401 snd_iprintf(buffer, "Buffer Size (Latency): %d samples (2 periods of %lu bytes)\n", x, (unsigned long) hdsp->period_bytes);
3402 snd_iprintf(buffer, "Hardware pointer (frames): %ld\n", hdsp_hw_pointer(hdsp));
3403 snd_iprintf(buffer, "Precise pointer: %s\n", hdsp->precise_ptr ? "on" : "off");
3404 snd_iprintf(buffer, "Line out: %s\n", (hdsp->control_register & HDSP_LineOut) ? "on" : "off");
3405
3406 snd_iprintf(buffer, "Firmware version: %d\n", (status2&HDSP_version0)|(status2&HDSP_version1)<<1|(status2&HDSP_version2)<<2);
3407
3408 snd_iprintf(buffer, "\n");
3409
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410 switch (hdsp_clock_source(hdsp)) {
3411 case HDSP_CLOCK_SOURCE_AUTOSYNC:
3412 clock_source = "AutoSync";
3413 break;
3414 case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ:
3415 clock_source = "Internal 32 kHz";
3416 break;
3417 case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ:
3418 clock_source = "Internal 44.1 kHz";
3419 break;
3420 case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ:
3421 clock_source = "Internal 48 kHz";
3422 break;
3423 case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ:
3424 clock_source = "Internal 64 kHz";
3425 break;
3426 case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ:
3427 clock_source = "Internal 88.2 kHz";
3428 break;
3429 case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ:
3430 clock_source = "Internal 96 kHz";
3431 break;
3432 case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ:
3433 clock_source = "Internal 128 kHz";
3434 break;
3435 case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ:
3436 clock_source = "Internal 176.4 kHz";
3437 break;
3438 case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ:
3439 clock_source = "Internal 192 kHz";
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003440 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441 default:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003442 clock_source = "Error";
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443 }
3444 snd_iprintf (buffer, "Sample Clock Source: %s\n", clock_source);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003445
Takashi Iwaib0b98112005-10-20 18:29:58 +02003446 if (hdsp_system_clock_mode(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447 system_clock_mode = "Slave";
Takashi Iwaib0b98112005-10-20 18:29:58 +02003448 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449 system_clock_mode = "Master";
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003450
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451 switch (hdsp_pref_sync_ref (hdsp)) {
3452 case HDSP_SYNC_FROM_WORD:
3453 pref_sync_ref = "Word Clock";
3454 break;
3455 case HDSP_SYNC_FROM_ADAT_SYNC:
3456 pref_sync_ref = "ADAT Sync";
3457 break;
3458 case HDSP_SYNC_FROM_SPDIF:
3459 pref_sync_ref = "SPDIF";
3460 break;
3461 case HDSP_SYNC_FROM_ADAT1:
3462 pref_sync_ref = "ADAT1";
3463 break;
3464 case HDSP_SYNC_FROM_ADAT2:
3465 pref_sync_ref = "ADAT2";
3466 break;
3467 case HDSP_SYNC_FROM_ADAT3:
3468 pref_sync_ref = "ADAT3";
3469 break;
3470 default:
3471 pref_sync_ref = "Word Clock";
3472 break;
3473 }
3474 snd_iprintf (buffer, "Preferred Sync Reference: %s\n", pref_sync_ref);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003475
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476 switch (hdsp_autosync_ref (hdsp)) {
3477 case HDSP_AUTOSYNC_FROM_WORD:
3478 autosync_ref = "Word Clock";
3479 break;
3480 case HDSP_AUTOSYNC_FROM_ADAT_SYNC:
3481 autosync_ref = "ADAT Sync";
3482 break;
3483 case HDSP_AUTOSYNC_FROM_SPDIF:
3484 autosync_ref = "SPDIF";
3485 break;
3486 case HDSP_AUTOSYNC_FROM_NONE:
3487 autosync_ref = "None";
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003488 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489 case HDSP_AUTOSYNC_FROM_ADAT1:
3490 autosync_ref = "ADAT1";
3491 break;
3492 case HDSP_AUTOSYNC_FROM_ADAT2:
3493 autosync_ref = "ADAT2";
3494 break;
3495 case HDSP_AUTOSYNC_FROM_ADAT3:
3496 autosync_ref = "ADAT3";
3497 break;
3498 default:
3499 autosync_ref = "---";
3500 break;
3501 }
3502 snd_iprintf (buffer, "AutoSync Reference: %s\n", autosync_ref);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003503
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504 snd_iprintf (buffer, "AutoSync Frequency: %d\n", hdsp_external_sample_rate(hdsp));
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003505
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode);
3507
3508 snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003509 snd_iprintf (buffer, "System Clock Locked: %s\n", hdsp->clock_source_locked ? "Yes" : "No");
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003510
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511 snd_iprintf(buffer, "\n");
3512
Florian Faber28b26e12010-12-01 12:14:47 +01003513 if (hdsp->io_type != RPM) {
3514 switch (hdsp_spdif_in(hdsp)) {
3515 case HDSP_SPDIFIN_OPTICAL:
3516 snd_iprintf(buffer, "IEC958 input: Optical\n");
3517 break;
3518 case HDSP_SPDIFIN_COAXIAL:
3519 snd_iprintf(buffer, "IEC958 input: Coaxial\n");
3520 break;
3521 case HDSP_SPDIFIN_INTERNAL:
3522 snd_iprintf(buffer, "IEC958 input: Internal\n");
3523 break;
3524 case HDSP_SPDIFIN_AES:
3525 snd_iprintf(buffer, "IEC958 input: AES\n");
3526 break;
3527 default:
3528 snd_iprintf(buffer, "IEC958 input: ???\n");
3529 break;
3530 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003531 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003532
Florian Faber28b26e12010-12-01 12:14:47 +01003533 if (RPM == hdsp->io_type) {
3534 if (hdsp->control_register & HDSP_RPM_Bypass)
3535 snd_iprintf(buffer, "RPM Bypass: disabled\n");
3536 else
3537 snd_iprintf(buffer, "RPM Bypass: enabled\n");
3538 if (hdsp->control_register & HDSP_RPM_Disconnect)
3539 snd_iprintf(buffer, "RPM disconnected\n");
3540 else
3541 snd_iprintf(buffer, "RPM connected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542
Florian Faber28b26e12010-12-01 12:14:47 +01003543 switch (hdsp->control_register & HDSP_RPM_Inp12) {
3544 case HDSP_RPM_Inp12_Phon_6dB:
3545 snd_iprintf(buffer, "Input 1/2: Phono, 6dB\n");
3546 break;
3547 case HDSP_RPM_Inp12_Phon_0dB:
3548 snd_iprintf(buffer, "Input 1/2: Phono, 0dB\n");
3549 break;
3550 case HDSP_RPM_Inp12_Phon_n6dB:
3551 snd_iprintf(buffer, "Input 1/2: Phono, -6dB\n");
3552 break;
3553 case HDSP_RPM_Inp12_Line_0dB:
3554 snd_iprintf(buffer, "Input 1/2: Line, 0dB\n");
3555 break;
3556 case HDSP_RPM_Inp12_Line_n6dB:
3557 snd_iprintf(buffer, "Input 1/2: Line, -6dB\n");
3558 break;
3559 default:
3560 snd_iprintf(buffer, "Input 1/2: ???\n");
3561 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003562
Florian Faber28b26e12010-12-01 12:14:47 +01003563 switch (hdsp->control_register & HDSP_RPM_Inp34) {
3564 case HDSP_RPM_Inp34_Phon_6dB:
3565 snd_iprintf(buffer, "Input 3/4: Phono, 6dB\n");
3566 break;
3567 case HDSP_RPM_Inp34_Phon_0dB:
3568 snd_iprintf(buffer, "Input 3/4: Phono, 0dB\n");
3569 break;
3570 case HDSP_RPM_Inp34_Phon_n6dB:
3571 snd_iprintf(buffer, "Input 3/4: Phono, -6dB\n");
3572 break;
3573 case HDSP_RPM_Inp34_Line_0dB:
3574 snd_iprintf(buffer, "Input 3/4: Line, 0dB\n");
3575 break;
3576 case HDSP_RPM_Inp34_Line_n6dB:
3577 snd_iprintf(buffer, "Input 3/4: Line, -6dB\n");
3578 break;
3579 default:
3580 snd_iprintf(buffer, "Input 3/4: ???\n");
3581 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582
Florian Faber28b26e12010-12-01 12:14:47 +01003583 } else {
3584 if (hdsp->control_register & HDSP_SPDIFOpticalOut)
3585 snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n");
3586 else
3587 snd_iprintf(buffer, "IEC958 output: Coaxial only\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588
Florian Faber28b26e12010-12-01 12:14:47 +01003589 if (hdsp->control_register & HDSP_SPDIFProfessional)
3590 snd_iprintf(buffer, "IEC958 quality: Professional\n");
3591 else
3592 snd_iprintf(buffer, "IEC958 quality: Consumer\n");
3593
3594 if (hdsp->control_register & HDSP_SPDIFEmphasis)
3595 snd_iprintf(buffer, "IEC958 emphasis: on\n");
3596 else
3597 snd_iprintf(buffer, "IEC958 emphasis: off\n");
3598
3599 if (hdsp->control_register & HDSP_SPDIFNonAudio)
3600 snd_iprintf(buffer, "IEC958 NonAudio: on\n");
3601 else
3602 snd_iprintf(buffer, "IEC958 NonAudio: off\n");
3603 x = hdsp_spdif_sample_rate(hdsp);
3604 if (x != 0)
3605 snd_iprintf(buffer, "IEC958 sample rate: %d\n", x);
3606 else
3607 snd_iprintf(buffer, "IEC958 sample rate: Error flag set\n");
3608 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609 snd_iprintf(buffer, "\n");
3610
3611 /* Sync Check */
3612 x = status & HDSP_Sync0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003613 if (status & HDSP_Lock0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614 snd_iprintf(buffer, "ADAT1: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003615 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616 snd_iprintf(buffer, "ADAT1: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617
3618 switch (hdsp->io_type) {
3619 case Digiface:
3620 case H9652:
3621 x = status & HDSP_Sync1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003622 if (status & HDSP_Lock1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623 snd_iprintf(buffer, "ADAT2: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003624 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625 snd_iprintf(buffer, "ADAT2: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626 x = status & HDSP_Sync2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003627 if (status & HDSP_Lock2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628 snd_iprintf(buffer, "ADAT3: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003629 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630 snd_iprintf(buffer, "ADAT3: No Lock\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003631 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632 default:
3633 /* relax */
3634 break;
3635 }
3636
3637 x = status & HDSP_SPDIFSync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003638 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639 snd_iprintf (buffer, "SPDIF: No Lock\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003640 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641 snd_iprintf (buffer, "SPDIF: %s\n", x ? "Sync" : "Lock");
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003642
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643 x = status2 & HDSP_wc_sync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003644 if (status2 & HDSP_wc_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645 snd_iprintf (buffer, "Word Clock: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003646 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647 snd_iprintf (buffer, "Word Clock: No Lock\n");
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003648
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649 x = status & HDSP_TimecodeSync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003650 if (status & HDSP_TimecodeLock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651 snd_iprintf(buffer, "ADAT Sync: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003652 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653 snd_iprintf(buffer, "ADAT Sync: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654
3655 snd_iprintf(buffer, "\n");
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003656
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657 /* Informations about H9632 specific controls */
3658 if (hdsp->io_type == H9632) {
3659 char *tmp;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003660
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661 switch (hdsp_ad_gain(hdsp)) {
3662 case 0:
3663 tmp = "-10 dBV";
3664 break;
3665 case 1:
3666 tmp = "+4 dBu";
3667 break;
3668 default:
3669 tmp = "Lo Gain";
3670 break;
3671 }
3672 snd_iprintf(buffer, "AD Gain : %s\n", tmp);
3673
3674 switch (hdsp_da_gain(hdsp)) {
3675 case 0:
3676 tmp = "Hi Gain";
3677 break;
3678 case 1:
3679 tmp = "+4 dBu";
3680 break;
3681 default:
3682 tmp = "-10 dBV";
3683 break;
3684 }
3685 snd_iprintf(buffer, "DA Gain : %s\n", tmp);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003686
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687 switch (hdsp_phone_gain(hdsp)) {
3688 case 0:
3689 tmp = "0 dB";
3690 break;
3691 case 1:
3692 tmp = "-6 dB";
3693 break;
3694 default:
3695 tmp = "-12 dB";
3696 break;
3697 }
3698 snd_iprintf(buffer, "Phones Gain : %s\n", tmp);
3699
Adrian Knoth4833c672013-01-15 18:52:22 +01003700 snd_iprintf(buffer, "XLR Breakout Cable : %s\n",
3701 hdsp_toggle_setting(hdsp, HDSP_XLRBreakoutCable) ?
3702 "yes" : "no");
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003703
Takashi Iwaib0b98112005-10-20 18:29:58 +02003704 if (hdsp->control_register & HDSP_AnalogExtensionBoard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705 snd_iprintf(buffer, "AEB : on (ADAT1 internal)\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003706 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707 snd_iprintf(buffer, "AEB : off (ADAT1 external)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708 snd_iprintf(buffer, "\n");
3709 }
3710
3711}
3712
Randy Dunlap1374f8c2008-01-16 14:55:42 +01003713static void snd_hdsp_proc_init(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003715 struct snd_info_entry *entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716
3717 if (! snd_card_proc_new(hdsp->card, "hdsp", &entry))
Takashi Iwaibf850202006-04-28 15:13:41 +02003718 snd_info_set_text_ops(entry, hdsp, snd_hdsp_proc_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719}
3720
Takashi Iwai55e957d2005-11-17 14:52:13 +01003721static void snd_hdsp_free_buffers(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722{
3723 snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci);
3724 snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
3725}
3726
Bill Pembertone23e7a12012-12-06 12:35:10 -05003727static int snd_hdsp_initialize_memory(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003728{
3729 unsigned long pb_bus, cb_bus;
3730
3731 if (snd_hammerfall_get_buffer(hdsp->pci, &hdsp->capture_dma_buf, HDSP_DMA_AREA_BYTES) < 0 ||
3732 snd_hammerfall_get_buffer(hdsp->pci, &hdsp->playback_dma_buf, HDSP_DMA_AREA_BYTES) < 0) {
3733 if (hdsp->capture_dma_buf.area)
3734 snd_dma_free_pages(&hdsp->capture_dma_buf);
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01003735 dev_err(hdsp->card->dev,
3736 "%s: no buffers available\n", hdsp->card_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737 return -ENOMEM;
3738 }
3739
3740 /* Align to bus-space 64K boundary */
3741
Clemens Ladisch7ab39922006-10-09 08:13:32 +02003742 cb_bus = ALIGN(hdsp->capture_dma_buf.addr, 0x10000ul);
3743 pb_bus = ALIGN(hdsp->playback_dma_buf.addr, 0x10000ul);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744
3745 /* Tell the card where it is */
3746
3747 hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus);
3748 hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus);
3749
3750 hdsp->capture_buffer = hdsp->capture_dma_buf.area + (cb_bus - hdsp->capture_dma_buf.addr);
3751 hdsp->playback_buffer = hdsp->playback_dma_buf.area + (pb_bus - hdsp->playback_dma_buf.addr);
3752
3753 return 0;
3754}
3755
Takashi Iwai55e957d2005-11-17 14:52:13 +01003756static int snd_hdsp_set_defaults(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757{
3758 unsigned int i;
3759
3760 /* ASSUMPTION: hdsp->lock is either held, or
3761 there is no need to hold it (e.g. during module
Joe Perches561de312007-12-18 13:13:47 +01003762 initialization).
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763 */
3764
3765 /* set defaults:
3766
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003767 SPDIF Input via Coax
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768 Master clock mode
3769 maximum latency (7 => 2^7 = 8192 samples, 64Kbyte buffer,
3770 which implies 2 4096 sample, 32Kbyte periods).
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003771 Enable line out.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772 */
3773
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003774 hdsp->control_register = HDSP_ClockModeMaster |
3775 HDSP_SPDIFInputCoaxial |
3776 hdsp_encode_latency(7) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777 HDSP_LineOut;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003778
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779
3780 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3781
3782#ifdef SNDRV_BIG_ENDIAN
3783 hdsp->control2_register = HDSP_BIGENDIAN_MODE;
3784#else
3785 hdsp->control2_register = 0;
3786#endif
Takashi Iwaib0b98112005-10-20 18:29:58 +02003787 if (hdsp->io_type == H9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788 snd_hdsp_9652_enable_mixer (hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003789 else
3790 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791
3792 hdsp_reset_hw_pointer(hdsp);
3793 hdsp_compute_period_size(hdsp);
3794
3795 /* silence everything */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003796
Takashi Iwaib0b98112005-10-20 18:29:58 +02003797 for (i = 0; i < HDSP_MATRIX_MIXER_SIZE; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798 hdsp->mixer_matrix[i] = MINUS_INFINITY_GAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799
3800 for (i = 0; i < ((hdsp->io_type == H9652 || hdsp->io_type == H9632) ? 1352 : HDSP_MATRIX_MIXER_SIZE); ++i) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003801 if (hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003804
Linus Torvalds1da177e2005-04-16 15:20:36 -07003805 /* H9632 specific defaults */
3806 if (hdsp->io_type == H9632) {
3807 hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB);
3808 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3809 }
3810
3811 /* set a default rate so that the channel map is set up.
3812 */
3813
3814 hdsp_set_rate(hdsp, 48000, 1);
3815
3816 return 0;
3817}
3818
3819static void hdsp_midi_tasklet(unsigned long arg)
3820{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003821 struct hdsp *hdsp = (struct hdsp *)arg;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003822
Takashi Iwaib0b98112005-10-20 18:29:58 +02003823 if (hdsp->midi[0].pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824 snd_hdsp_midi_input_read (&hdsp->midi[0]);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003825 if (hdsp->midi[1].pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826 snd_hdsp_midi_input_read (&hdsp->midi[1]);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003827}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828
David Howells7d12e782006-10-05 14:55:46 +01003829static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003831 struct hdsp *hdsp = (struct hdsp *) dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832 unsigned int status;
3833 int audio;
3834 int midi0;
3835 int midi1;
3836 unsigned int midi0status;
3837 unsigned int midi1status;
3838 int schedule = 0;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003839
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840 status = hdsp_read(hdsp, HDSP_statusRegister);
3841
3842 audio = status & HDSP_audioIRQPending;
3843 midi0 = status & HDSP_midi0IRQPending;
3844 midi1 = status & HDSP_midi1IRQPending;
3845
Takashi Iwaib0b98112005-10-20 18:29:58 +02003846 if (!audio && !midi0 && !midi1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847 return IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848
3849 hdsp_write(hdsp, HDSP_interruptConfirmation, 0);
3850
3851 midi0status = hdsp_read (hdsp, HDSP_midiStatusIn0) & 0xff;
3852 midi1status = hdsp_read (hdsp, HDSP_midiStatusIn1) & 0xff;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003853
Takashi Iwaic2503cd2009-03-05 09:37:40 +01003854 if (!(hdsp->state & HDSP_InitializationComplete))
3855 return IRQ_HANDLED;
3856
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857 if (audio) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003858 if (hdsp->capture_substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859 snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003860
Takashi Iwaib0b98112005-10-20 18:29:58 +02003861 if (hdsp->playback_substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862 snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003864
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865 if (midi0 && midi0status) {
3866 if (hdsp->use_midi_tasklet) {
3867 /* we disable interrupts for this input until processing is done */
3868 hdsp->control_register &= ~HDSP_Midi0InterruptEnable;
3869 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3870 hdsp->midi[0].pending = 1;
3871 schedule = 1;
3872 } else {
3873 snd_hdsp_midi_input_read (&hdsp->midi[0]);
3874 }
3875 }
Florian Faber28b26e12010-12-01 12:14:47 +01003876 if (hdsp->io_type != Multiface && hdsp->io_type != RPM && hdsp->io_type != H9632 && midi1 && midi1status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877 if (hdsp->use_midi_tasklet) {
3878 /* we disable interrupts for this input until processing is done */
3879 hdsp->control_register &= ~HDSP_Midi1InterruptEnable;
3880 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3881 hdsp->midi[1].pending = 1;
3882 schedule = 1;
3883 } else {
3884 snd_hdsp_midi_input_read (&hdsp->midi[1]);
3885 }
3886 }
3887 if (hdsp->use_midi_tasklet && schedule)
Takashi Iwai1f041282008-12-18 12:17:55 +01003888 tasklet_schedule(&hdsp->midi_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 return IRQ_HANDLED;
3890}
3891
Takashi Iwai55e957d2005-11-17 14:52:13 +01003892static snd_pcm_uframes_t snd_hdsp_hw_pointer(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003894 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 return hdsp_hw_pointer(hdsp);
3896}
3897
Takashi Iwai55e957d2005-11-17 14:52:13 +01003898static char *hdsp_channel_buffer_location(struct hdsp *hdsp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899 int stream,
3900 int channel)
3901
3902{
3903 int mapped_channel;
3904
Takashi Iwaida3cec32008-08-08 17:12:14 +02003905 if (snd_BUG_ON(channel < 0 || channel >= hdsp->max_channels))
3906 return NULL;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003907
Takashi Iwaib0b98112005-10-20 18:29:58 +02003908 if ((mapped_channel = hdsp->channel_map[channel]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003909 return NULL;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003910
Takashi Iwaib0b98112005-10-20 18:29:58 +02003911 if (stream == SNDRV_PCM_STREAM_CAPTURE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 return hdsp->capture_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003913 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914 return hdsp->playback_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915}
3916
Takashi Iwai55e957d2005-11-17 14:52:13 +01003917static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918 snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
3919{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003920 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921 char *channel_buf;
3922
Takashi Iwaida3cec32008-08-08 17:12:14 +02003923 if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4))
3924 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925
3926 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
Takashi Iwaida3cec32008-08-08 17:12:14 +02003927 if (snd_BUG_ON(!channel_buf))
3928 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929 if (copy_from_user(channel_buf + pos * 4, src, count * 4))
3930 return -EFAULT;
3931 return count;
3932}
3933
Takashi Iwai55e957d2005-11-17 14:52:13 +01003934static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003935 snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count)
3936{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003937 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938 char *channel_buf;
3939
Takashi Iwaida3cec32008-08-08 17:12:14 +02003940 if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4))
3941 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942
3943 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
Takashi Iwaida3cec32008-08-08 17:12:14 +02003944 if (snd_BUG_ON(!channel_buf))
3945 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
3947 return -EFAULT;
3948 return count;
3949}
3950
Takashi Iwai55e957d2005-11-17 14:52:13 +01003951static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952 snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
3953{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003954 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003955 char *channel_buf;
3956
3957 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
Takashi Iwaida3cec32008-08-08 17:12:14 +02003958 if (snd_BUG_ON(!channel_buf))
3959 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960 memset(channel_buf + pos * 4, 0, count * 4);
3961 return count;
3962}
3963
Takashi Iwai55e957d2005-11-17 14:52:13 +01003964static int snd_hdsp_reset(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003966 struct snd_pcm_runtime *runtime = substream->runtime;
3967 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
3968 struct snd_pcm_substream *other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3970 other = hdsp->capture_substream;
3971 else
3972 other = hdsp->playback_substream;
3973 if (hdsp->running)
3974 runtime->status->hw_ptr = hdsp_hw_pointer(hdsp);
3975 else
3976 runtime->status->hw_ptr = 0;
3977 if (other) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01003978 struct snd_pcm_substream *s;
3979 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01003980 snd_pcm_group_for_each_entry(s, substream) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981 if (s == other) {
3982 oruntime->status->hw_ptr = runtime->status->hw_ptr;
3983 break;
3984 }
3985 }
3986 }
3987 return 0;
3988}
3989
Takashi Iwai55e957d2005-11-17 14:52:13 +01003990static int snd_hdsp_hw_params(struct snd_pcm_substream *substream,
3991 struct snd_pcm_hw_params *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003993 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994 int err;
3995 pid_t this_pid;
3996 pid_t other_pid;
3997
Takashi Iwaib0b98112005-10-20 18:29:58 +02003998 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000
Takashi Iwaib0b98112005-10-20 18:29:58 +02004001 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003
4004 spin_lock_irq(&hdsp->lock);
4005
4006 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
4007 hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
4008 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= hdsp->creg_spdif_stream);
4009 this_pid = hdsp->playback_pid;
4010 other_pid = hdsp->capture_pid;
4011 } else {
4012 this_pid = hdsp->capture_pid;
4013 other_pid = hdsp->playback_pid;
4014 }
4015
4016 if ((other_pid > 0) && (this_pid != other_pid)) {
4017
4018 /* The other stream is open, and not by the same
4019 task as this one. Make sure that the parameters
4020 that matter are the same.
4021 */
4022
4023 if (params_rate(params) != hdsp->system_sample_rate) {
4024 spin_unlock_irq(&hdsp->lock);
4025 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
4026 return -EBUSY;
4027 }
4028
4029 if (params_period_size(params) != hdsp->period_bytes / 4) {
4030 spin_unlock_irq(&hdsp->lock);
4031 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
4032 return -EBUSY;
4033 }
4034
4035 /* We're fine. */
4036
4037 spin_unlock_irq(&hdsp->lock);
4038 return 0;
4039
4040 } else {
4041 spin_unlock_irq(&hdsp->lock);
4042 }
4043
4044 /* how to make sure that the rate matches an externally-set one ?
4045 */
4046
4047 spin_lock_irq(&hdsp->lock);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02004048 if (! hdsp->clock_source_locked) {
4049 if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) {
4050 spin_unlock_irq(&hdsp->lock);
4051 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
4052 return err;
4053 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 }
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02004055 spin_unlock_irq(&hdsp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056
4057 if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) {
4058 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
4059 return err;
4060 }
4061
4062 return 0;
4063}
4064
Takashi Iwai55e957d2005-11-17 14:52:13 +01004065static int snd_hdsp_channel_info(struct snd_pcm_substream *substream,
4066 struct snd_pcm_channel_info *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004068 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Gustavo A. R. Silvaf2f87232018-12-18 11:18:34 -06004069 unsigned int channel = info->channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070
Gustavo A. R. Silvaf2f87232018-12-18 11:18:34 -06004071 if (snd_BUG_ON(channel >= hdsp->max_channels))
4072 return -EINVAL;
4073 channel = array_index_nospec(channel, hdsp->max_channels);
4074
4075 if (hdsp->channel_map[channel] < 0)
Takashi Iwaida3cec32008-08-08 17:12:14 +02004076 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077
Gustavo A. R. Silvaf2f87232018-12-18 11:18:34 -06004078 info->offset = hdsp->channel_map[channel] * HDSP_CHANNEL_BUFFER_BYTES;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079 info->first = 0;
4080 info->step = 32;
4081 return 0;
4082}
4083
Takashi Iwai55e957d2005-11-17 14:52:13 +01004084static int snd_hdsp_ioctl(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085 unsigned int cmd, void *arg)
4086{
4087 switch (cmd) {
4088 case SNDRV_PCM_IOCTL1_RESET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089 return snd_hdsp_reset(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Takashi Iwaib0b98112005-10-20 18:29:58 +02004091 return snd_hdsp_channel_info(substream, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092 default:
4093 break;
4094 }
4095
4096 return snd_pcm_lib_ioctl(substream, cmd, arg);
4097}
4098
Takashi Iwai55e957d2005-11-17 14:52:13 +01004099static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004101 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4102 struct snd_pcm_substream *other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103 int running;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004104
Takashi Iwaib0b98112005-10-20 18:29:58 +02004105 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107
Takashi Iwai311e70a2006-09-06 12:13:37 +02004108 if (hdsp_check_for_firmware(hdsp, 0)) /* no auto-loading in trigger */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110
4111 spin_lock(&hdsp->lock);
4112 running = hdsp->running;
4113 switch (cmd) {
4114 case SNDRV_PCM_TRIGGER_START:
4115 running |= 1 << substream->stream;
4116 break;
4117 case SNDRV_PCM_TRIGGER_STOP:
4118 running &= ~(1 << substream->stream);
4119 break;
4120 default:
4121 snd_BUG();
4122 spin_unlock(&hdsp->lock);
4123 return -EINVAL;
4124 }
4125 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
4126 other = hdsp->capture_substream;
4127 else
4128 other = hdsp->playback_substream;
4129
4130 if (other) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004131 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01004132 snd_pcm_group_for_each_entry(s, substream) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133 if (s == other) {
4134 snd_pcm_trigger_done(s, substream);
4135 if (cmd == SNDRV_PCM_TRIGGER_START)
4136 running |= 1 << s->stream;
4137 else
4138 running &= ~(1 << s->stream);
4139 goto _ok;
4140 }
4141 }
4142 if (cmd == SNDRV_PCM_TRIGGER_START) {
4143 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) &&
4144 substream->stream == SNDRV_PCM_STREAM_CAPTURE)
4145 hdsp_silence_playback(hdsp);
4146 } else {
4147 if (running &&
4148 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
4149 hdsp_silence_playback(hdsp);
4150 }
4151 } else {
4152 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
4153 hdsp_silence_playback(hdsp);
4154 }
4155 _ok:
4156 snd_pcm_trigger_done(substream, substream);
4157 if (!hdsp->running && running)
4158 hdsp_start_audio(hdsp);
4159 else if (hdsp->running && !running)
4160 hdsp_stop_audio(hdsp);
4161 hdsp->running = running;
4162 spin_unlock(&hdsp->lock);
4163
4164 return 0;
4165}
4166
Takashi Iwai55e957d2005-11-17 14:52:13 +01004167static int snd_hdsp_prepare(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004169 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170 int result = 0;
4171
Takashi Iwaib0b98112005-10-20 18:29:58 +02004172 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174
Takashi Iwaib0b98112005-10-20 18:29:58 +02004175 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177
4178 spin_lock_irq(&hdsp->lock);
4179 if (!hdsp->running)
4180 hdsp_reset_hw_pointer(hdsp);
4181 spin_unlock_irq(&hdsp->lock);
4182 return result;
4183}
4184
Takashi Iwai55e957d2005-11-17 14:52:13 +01004185static struct snd_pcm_hardware snd_hdsp_playback_subinfo =
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186{
4187 .info = (SNDRV_PCM_INFO_MMAP |
4188 SNDRV_PCM_INFO_MMAP_VALID |
4189 SNDRV_PCM_INFO_NONINTERLEAVED |
4190 SNDRV_PCM_INFO_SYNC_START |
4191 SNDRV_PCM_INFO_DOUBLE),
4192#ifdef SNDRV_BIG_ENDIAN
4193 .formats = SNDRV_PCM_FMTBIT_S32_BE,
4194#else
4195 .formats = SNDRV_PCM_FMTBIT_S32_LE,
4196#endif
4197 .rates = (SNDRV_PCM_RATE_32000 |
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004198 SNDRV_PCM_RATE_44100 |
4199 SNDRV_PCM_RATE_48000 |
4200 SNDRV_PCM_RATE_64000 |
4201 SNDRV_PCM_RATE_88200 |
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202 SNDRV_PCM_RATE_96000),
4203 .rate_min = 32000,
4204 .rate_max = 96000,
Florian Faber28b26e12010-12-01 12:14:47 +01004205 .channels_min = 6,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206 .channels_max = HDSP_MAX_CHANNELS,
4207 .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS,
4208 .period_bytes_min = (64 * 4) * 10,
4209 .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS,
4210 .periods_min = 2,
4211 .periods_max = 2,
4212 .fifo_size = 0
4213};
4214
Takashi Iwai55e957d2005-11-17 14:52:13 +01004215static struct snd_pcm_hardware snd_hdsp_capture_subinfo =
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216{
4217 .info = (SNDRV_PCM_INFO_MMAP |
4218 SNDRV_PCM_INFO_MMAP_VALID |
4219 SNDRV_PCM_INFO_NONINTERLEAVED |
4220 SNDRV_PCM_INFO_SYNC_START),
4221#ifdef SNDRV_BIG_ENDIAN
4222 .formats = SNDRV_PCM_FMTBIT_S32_BE,
4223#else
4224 .formats = SNDRV_PCM_FMTBIT_S32_LE,
4225#endif
4226 .rates = (SNDRV_PCM_RATE_32000 |
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004227 SNDRV_PCM_RATE_44100 |
4228 SNDRV_PCM_RATE_48000 |
4229 SNDRV_PCM_RATE_64000 |
4230 SNDRV_PCM_RATE_88200 |
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231 SNDRV_PCM_RATE_96000),
4232 .rate_min = 32000,
4233 .rate_max = 96000,
Florian Faber28b26e12010-12-01 12:14:47 +01004234 .channels_min = 5,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235 .channels_max = HDSP_MAX_CHANNELS,
4236 .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS,
4237 .period_bytes_min = (64 * 4) * 10,
4238 .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS,
4239 .periods_min = 2,
4240 .periods_max = 2,
4241 .fifo_size = 0
4242};
4243
4244static unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
4245
Takashi Iwai55e957d2005-11-17 14:52:13 +01004246static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_period_sizes = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247 .count = ARRAY_SIZE(hdsp_period_sizes),
4248 .list = hdsp_period_sizes,
4249 .mask = 0
4250};
4251
4252static unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 };
4253
Takashi Iwai55e957d2005-11-17 14:52:13 +01004254static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_9632_sample_rates = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255 .count = ARRAY_SIZE(hdsp_9632_sample_rates),
4256 .list = hdsp_9632_sample_rates,
4257 .mask = 0
4258};
4259
Takashi Iwai55e957d2005-11-17 14:52:13 +01004260static int snd_hdsp_hw_rule_in_channels(struct snd_pcm_hw_params *params,
4261 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004263 struct hdsp *hdsp = rule->private;
4264 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265 if (hdsp->io_type == H9632) {
4266 unsigned int list[3];
4267 list[0] = hdsp->qs_in_channels;
4268 list[1] = hdsp->ds_in_channels;
4269 list[2] = hdsp->ss_in_channels;
4270 return snd_interval_list(c, 3, list, 0);
4271 } else {
4272 unsigned int list[2];
4273 list[0] = hdsp->ds_in_channels;
4274 list[1] = hdsp->ss_in_channels;
4275 return snd_interval_list(c, 2, list, 0);
4276 }
4277}
4278
Takashi Iwai55e957d2005-11-17 14:52:13 +01004279static int snd_hdsp_hw_rule_out_channels(struct snd_pcm_hw_params *params,
4280 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004281{
4282 unsigned int list[3];
Takashi Iwai55e957d2005-11-17 14:52:13 +01004283 struct hdsp *hdsp = rule->private;
4284 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285 if (hdsp->io_type == H9632) {
4286 list[0] = hdsp->qs_out_channels;
4287 list[1] = hdsp->ds_out_channels;
4288 list[2] = hdsp->ss_out_channels;
4289 return snd_interval_list(c, 3, list, 0);
4290 } else {
4291 list[0] = hdsp->ds_out_channels;
4292 list[1] = hdsp->ss_out_channels;
4293 }
4294 return snd_interval_list(c, 2, list, 0);
4295}
4296
Takashi Iwai55e957d2005-11-17 14:52:13 +01004297static int snd_hdsp_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
4298 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004300 struct hdsp *hdsp = rule->private;
4301 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4302 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303 if (r->min > 96000 && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004304 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305 .min = hdsp->qs_in_channels,
4306 .max = hdsp->qs_in_channels,
4307 .integer = 1,
4308 };
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004309 return snd_interval_refine(c, &t);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310 } else if (r->min > 48000 && r->max <= 96000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004311 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312 .min = hdsp->ds_in_channels,
4313 .max = hdsp->ds_in_channels,
4314 .integer = 1,
4315 };
4316 return snd_interval_refine(c, &t);
4317 } else if (r->max < 64000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004318 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319 .min = hdsp->ss_in_channels,
4320 .max = hdsp->ss_in_channels,
4321 .integer = 1,
4322 };
4323 return snd_interval_refine(c, &t);
4324 }
4325 return 0;
4326}
4327
Takashi Iwai55e957d2005-11-17 14:52:13 +01004328static int snd_hdsp_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
4329 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004331 struct hdsp *hdsp = rule->private;
4332 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4333 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334 if (r->min > 96000 && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004335 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336 .min = hdsp->qs_out_channels,
4337 .max = hdsp->qs_out_channels,
4338 .integer = 1,
4339 };
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004340 return snd_interval_refine(c, &t);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341 } else if (r->min > 48000 && r->max <= 96000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004342 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343 .min = hdsp->ds_out_channels,
4344 .max = hdsp->ds_out_channels,
4345 .integer = 1,
4346 };
4347 return snd_interval_refine(c, &t);
4348 } else if (r->max < 64000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004349 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350 .min = hdsp->ss_out_channels,
4351 .max = hdsp->ss_out_channels,
4352 .integer = 1,
4353 };
4354 return snd_interval_refine(c, &t);
4355 }
4356 return 0;
4357}
4358
Takashi Iwai55e957d2005-11-17 14:52:13 +01004359static int snd_hdsp_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
4360 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004362 struct hdsp *hdsp = rule->private;
4363 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4364 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365 if (c->min >= hdsp->ss_out_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004366 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367 .min = 32000,
4368 .max = 48000,
4369 .integer = 1,
4370 };
4371 return snd_interval_refine(r, &t);
4372 } else if (c->max <= hdsp->qs_out_channels && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004373 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374 .min = 128000,
4375 .max = 192000,
4376 .integer = 1,
4377 };
4378 return snd_interval_refine(r, &t);
4379 } else if (c->max <= hdsp->ds_out_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004380 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004381 .min = 64000,
4382 .max = 96000,
4383 .integer = 1,
4384 };
4385 return snd_interval_refine(r, &t);
4386 }
4387 return 0;
4388}
4389
Takashi Iwai55e957d2005-11-17 14:52:13 +01004390static int snd_hdsp_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
4391 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004393 struct hdsp *hdsp = rule->private;
4394 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4395 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396 if (c->min >= hdsp->ss_in_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004397 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 .min = 32000,
4399 .max = 48000,
4400 .integer = 1,
4401 };
4402 return snd_interval_refine(r, &t);
4403 } else if (c->max <= hdsp->qs_in_channels && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004404 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405 .min = 128000,
4406 .max = 192000,
4407 .integer = 1,
4408 };
4409 return snd_interval_refine(r, &t);
4410 } else if (c->max <= hdsp->ds_in_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004411 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412 .min = 64000,
4413 .max = 96000,
4414 .integer = 1,
4415 };
4416 return snd_interval_refine(r, &t);
4417 }
4418 return 0;
4419}
4420
Takashi Iwai55e957d2005-11-17 14:52:13 +01004421static int snd_hdsp_playback_open(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004423 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4424 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425
Takashi Iwaib0b98112005-10-20 18:29:58 +02004426 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428
Takashi Iwaib0b98112005-10-20 18:29:58 +02004429 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431
4432 spin_lock_irq(&hdsp->lock);
4433
4434 snd_pcm_set_sync(substream);
4435
4436 runtime->hw = snd_hdsp_playback_subinfo;
4437 runtime->dma_area = hdsp->playback_buffer;
4438 runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
4439
4440 hdsp->playback_pid = current->pid;
4441 hdsp->playback_substream = substream;
4442
4443 spin_unlock_irq(&hdsp->lock);
4444
4445 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4446 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02004447 if (hdsp->clock_source_locked) {
4448 runtime->hw.rate_min = runtime->hw.rate_max = hdsp->system_sample_rate;
4449 } else if (hdsp->io_type == H9632) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004450 runtime->hw.rate_max = 192000;
4451 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
4452 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates);
4453 }
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02004454 if (hdsp->io_type == H9632) {
4455 runtime->hw.channels_min = hdsp->qs_out_channels;
4456 runtime->hw.channels_max = hdsp->ss_out_channels;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004457 }
4458
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4460 snd_hdsp_hw_rule_out_channels, hdsp,
4461 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4462 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4463 snd_hdsp_hw_rule_out_channels_rate, hdsp,
4464 SNDRV_PCM_HW_PARAM_RATE, -1);
4465 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4466 snd_hdsp_hw_rule_rate_out_channels, hdsp,
4467 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4468
Florian Faber28b26e12010-12-01 12:14:47 +01004469 if (RPM != hdsp->io_type) {
4470 hdsp->creg_spdif_stream = hdsp->creg_spdif;
4471 hdsp->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
4472 snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
4473 SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id);
4474 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475 return 0;
4476}
4477
Takashi Iwai55e957d2005-11-17 14:52:13 +01004478static int snd_hdsp_playback_release(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004479{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004480 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004481
4482 spin_lock_irq(&hdsp->lock);
4483
4484 hdsp->playback_pid = -1;
4485 hdsp->playback_substream = NULL;
4486
4487 spin_unlock_irq(&hdsp->lock);
4488
Florian Faber28b26e12010-12-01 12:14:47 +01004489 if (RPM != hdsp->io_type) {
4490 hdsp->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
4491 snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
4492 SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id);
4493 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494 return 0;
4495}
4496
4497
Takashi Iwai55e957d2005-11-17 14:52:13 +01004498static int snd_hdsp_capture_open(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004499{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004500 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4501 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004502
Takashi Iwaib0b98112005-10-20 18:29:58 +02004503 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004504 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004505
Takashi Iwaib0b98112005-10-20 18:29:58 +02004506 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004508
4509 spin_lock_irq(&hdsp->lock);
4510
4511 snd_pcm_set_sync(substream);
4512
4513 runtime->hw = snd_hdsp_capture_subinfo;
4514 runtime->dma_area = hdsp->capture_buffer;
4515 runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
4516
4517 hdsp->capture_pid = current->pid;
4518 hdsp->capture_substream = substream;
4519
4520 spin_unlock_irq(&hdsp->lock);
4521
4522 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4523 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes);
4524 if (hdsp->io_type == H9632) {
4525 runtime->hw.channels_min = hdsp->qs_in_channels;
4526 runtime->hw.channels_max = hdsp->ss_in_channels;
4527 runtime->hw.rate_max = 192000;
4528 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
4529 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates);
4530 }
4531 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4532 snd_hdsp_hw_rule_in_channels, hdsp,
4533 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4534 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4535 snd_hdsp_hw_rule_in_channels_rate, hdsp,
4536 SNDRV_PCM_HW_PARAM_RATE, -1);
4537 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4538 snd_hdsp_hw_rule_rate_in_channels, hdsp,
4539 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4540 return 0;
4541}
4542
Takashi Iwai55e957d2005-11-17 14:52:13 +01004543static int snd_hdsp_capture_release(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004544{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004545 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004546
4547 spin_lock_irq(&hdsp->lock);
4548
4549 hdsp->capture_pid = -1;
4550 hdsp->capture_substream = NULL;
4551
4552 spin_unlock_irq(&hdsp->lock);
4553 return 0;
4554}
4555
Linus Torvalds1da177e2005-04-16 15:20:36 -07004556/* helper functions for copying meter values */
4557static inline int copy_u32_le(void __user *dest, void __iomem *src)
4558{
4559 u32 val = readl(src);
4560 return copy_to_user(dest, &val, 4);
4561}
4562
4563static inline int copy_u64_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
4564{
4565 u32 rms_low, rms_high;
4566 u64 rms;
4567 rms_low = readl(src_low);
4568 rms_high = readl(src_high);
4569 rms = ((u64)rms_high << 32) | rms_low;
4570 return copy_to_user(dest, &rms, 8);
4571}
4572
4573static inline int copy_u48_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
4574{
4575 u32 rms_low, rms_high;
4576 u64 rms;
4577 rms_low = readl(src_low) & 0xffffff00;
4578 rms_high = readl(src_high) & 0xffffff00;
4579 rms = ((u64)rms_high << 32) | rms_low;
4580 return copy_to_user(dest, &rms, 8);
4581}
4582
Takashi Iwai55e957d2005-11-17 14:52:13 +01004583static int hdsp_9652_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004584{
4585 int doublespeed = 0;
4586 int i, j, channels, ofs;
4587
4588 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
4589 doublespeed = 1;
4590 channels = doublespeed ? 14 : 26;
4591 for (i = 0, j = 0; i < 26; ++i) {
4592 if (doublespeed && (i & 4))
4593 continue;
4594 ofs = HDSP_9652_peakBase - j * 4;
4595 if (copy_u32_le(&peak_rms->input_peaks[i], hdsp->iobase + ofs))
4596 return -EFAULT;
4597 ofs -= channels * 4;
4598 if (copy_u32_le(&peak_rms->playback_peaks[i], hdsp->iobase + ofs))
4599 return -EFAULT;
4600 ofs -= channels * 4;
4601 if (copy_u32_le(&peak_rms->output_peaks[i], hdsp->iobase + ofs))
4602 return -EFAULT;
4603 ofs = HDSP_9652_rmsBase + j * 8;
4604 if (copy_u48_le(&peak_rms->input_rms[i], hdsp->iobase + ofs,
4605 hdsp->iobase + ofs + 4))
4606 return -EFAULT;
4607 ofs += channels * 8;
4608 if (copy_u48_le(&peak_rms->playback_rms[i], hdsp->iobase + ofs,
4609 hdsp->iobase + ofs + 4))
4610 return -EFAULT;
4611 ofs += channels * 8;
4612 if (copy_u48_le(&peak_rms->output_rms[i], hdsp->iobase + ofs,
4613 hdsp->iobase + ofs + 4))
4614 return -EFAULT;
4615 j++;
4616 }
4617 return 0;
4618}
4619
Takashi Iwai55e957d2005-11-17 14:52:13 +01004620static int hdsp_9632_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004621{
4622 int i, j;
Takashi Iwai55e957d2005-11-17 14:52:13 +01004623 struct hdsp_9632_meters __iomem *m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004624 int doublespeed = 0;
4625
4626 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
4627 doublespeed = 1;
Takashi Iwai55e957d2005-11-17 14:52:13 +01004628 m = (struct hdsp_9632_meters __iomem *)(hdsp->iobase+HDSP_9632_metersBase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004629 for (i = 0, j = 0; i < 16; ++i, ++j) {
4630 if (copy_u32_le(&peak_rms->input_peaks[i], &m->input_peak[j]))
4631 return -EFAULT;
4632 if (copy_u32_le(&peak_rms->playback_peaks[i], &m->playback_peak[j]))
4633 return -EFAULT;
4634 if (copy_u32_le(&peak_rms->output_peaks[i], &m->output_peak[j]))
4635 return -EFAULT;
4636 if (copy_u64_le(&peak_rms->input_rms[i], &m->input_rms_low[j],
4637 &m->input_rms_high[j]))
4638 return -EFAULT;
4639 if (copy_u64_le(&peak_rms->playback_rms[i], &m->playback_rms_low[j],
4640 &m->playback_rms_high[j]))
4641 return -EFAULT;
4642 if (copy_u64_le(&peak_rms->output_rms[i], &m->output_rms_low[j],
4643 &m->output_rms_high[j]))
4644 return -EFAULT;
4645 if (doublespeed && i == 3) i += 4;
4646 }
4647 return 0;
4648}
4649
Takashi Iwai55e957d2005-11-17 14:52:13 +01004650static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004651{
4652 int i;
4653
4654 for (i = 0; i < 26; i++) {
4655 if (copy_u32_le(&peak_rms->playback_peaks[i],
4656 hdsp->iobase + HDSP_playbackPeakLevel + i * 4))
4657 return -EFAULT;
4658 if (copy_u32_le(&peak_rms->input_peaks[i],
4659 hdsp->iobase + HDSP_inputPeakLevel + i * 4))
4660 return -EFAULT;
4661 }
4662 for (i = 0; i < 28; i++) {
4663 if (copy_u32_le(&peak_rms->output_peaks[i],
4664 hdsp->iobase + HDSP_outputPeakLevel + i * 4))
4665 return -EFAULT;
4666 }
4667 for (i = 0; i < 26; ++i) {
4668 if (copy_u64_le(&peak_rms->playback_rms[i],
4669 hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4,
4670 hdsp->iobase + HDSP_playbackRmsLevel + i * 8))
4671 return -EFAULT;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004672 if (copy_u64_le(&peak_rms->input_rms[i],
Linus Torvalds1da177e2005-04-16 15:20:36 -07004673 hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4,
4674 hdsp->iobase + HDSP_inputRmsLevel + i * 8))
4675 return -EFAULT;
4676 }
4677 return 0;
4678}
4679
Takashi Iwai55e957d2005-11-17 14:52:13 +01004680static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004681{
Joe Perches9fe856e2010-09-04 18:52:54 -07004682 struct hdsp *hdsp = hw->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004683 void __user *argp = (void __user *)arg;
Tim Blechmann3ae7e2e2008-11-08 14:42:18 +01004684 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004685
4686 switch (cmd) {
4687 case SNDRV_HDSP_IOCTL_GET_PEAK_RMS: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004688 struct hdsp_peak_rms __user *peak_rms = (struct hdsp_peak_rms __user *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004689
Tim Blechmann3ae7e2e2008-11-08 14:42:18 +01004690 err = hdsp_check_for_iobox(hdsp);
4691 if (err < 0)
4692 return err;
4693
4694 err = hdsp_check_for_firmware(hdsp, 1);
4695 if (err < 0)
4696 return err;
4697
Linus Torvalds1da177e2005-04-16 15:20:36 -07004698 if (!(hdsp->state & HDSP_FirmwareLoaded)) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01004699 dev_err(hdsp->card->dev,
4700 "firmware needs to be uploaded to the card.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004701 return -EINVAL;
4702 }
4703
4704 switch (hdsp->io_type) {
4705 case H9652:
4706 return hdsp_9652_get_peak(hdsp, peak_rms);
4707 case H9632:
4708 return hdsp_9632_get_peak(hdsp, peak_rms);
4709 default:
4710 return hdsp_get_peak(hdsp, peak_rms);
4711 }
4712 }
4713 case SNDRV_HDSP_IOCTL_GET_CONFIG_INFO: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004714 struct hdsp_config_info info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004715 unsigned long flags;
4716 int i;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004717
Tim Blechmann3ae7e2e2008-11-08 14:42:18 +01004718 err = hdsp_check_for_iobox(hdsp);
4719 if (err < 0)
4720 return err;
4721
4722 err = hdsp_check_for_firmware(hdsp, 1);
4723 if (err < 0)
4724 return err;
4725
Dan Rosenberge68d3b32010-09-25 11:07:27 -04004726 memset(&info, 0, sizeof(info));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727 spin_lock_irqsave(&hdsp->lock, flags);
4728 info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp);
4729 info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02004730 if (hdsp->io_type != H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004731 info.adatsync_sync_check = (unsigned char)hdsp_adatsync_sync_check(hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004732 info.spdif_sync_check = (unsigned char)hdsp_spdif_sync_check(hdsp);
Florian Faber28b26e12010-12-01 12:14:47 +01004733 for (i = 0; i < ((hdsp->io_type != Multiface && hdsp->io_type != RPM && hdsp->io_type != H9632) ? 3 : 1); ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004734 info.adat_sync_check[i] = (unsigned char)hdsp_adat_sync_check(hdsp, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004735 info.spdif_in = (unsigned char)hdsp_spdif_in(hdsp);
Adrian Knoth4833c672013-01-15 18:52:22 +01004736 info.spdif_out = (unsigned char)hdsp_toggle_setting(hdsp,
4737 HDSP_SPDIFOpticalOut);
4738 info.spdif_professional = (unsigned char)
4739 hdsp_toggle_setting(hdsp, HDSP_SPDIFProfessional);
4740 info.spdif_emphasis = (unsigned char)
4741 hdsp_toggle_setting(hdsp, HDSP_SPDIFEmphasis);
4742 info.spdif_nonaudio = (unsigned char)
4743 hdsp_toggle_setting(hdsp, HDSP_SPDIFNonAudio);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004744 info.spdif_sample_rate = hdsp_spdif_sample_rate(hdsp);
4745 info.system_sample_rate = hdsp->system_sample_rate;
4746 info.autosync_sample_rate = hdsp_external_sample_rate(hdsp);
4747 info.system_clock_mode = (unsigned char)hdsp_system_clock_mode(hdsp);
4748 info.clock_source = (unsigned char)hdsp_clock_source(hdsp);
4749 info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp);
Adrian Knoth4833c672013-01-15 18:52:22 +01004750 info.line_out = (unsigned char)
4751 hdsp_toggle_setting(hdsp, HDSP_LineOut);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004752 if (hdsp->io_type == H9632) {
4753 info.da_gain = (unsigned char)hdsp_da_gain(hdsp);
4754 info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp);
4755 info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp);
Adrian Knoth4833c672013-01-15 18:52:22 +01004756 info.xlr_breakout_cable =
4757 (unsigned char)hdsp_toggle_setting(hdsp,
4758 HDSP_XLRBreakoutCable);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004759
Florian Faber28b26e12010-12-01 12:14:47 +01004760 } else if (hdsp->io_type == RPM) {
4761 info.da_gain = (unsigned char) hdsp_rpm_input12(hdsp);
4762 info.ad_gain = (unsigned char) hdsp_rpm_input34(hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004763 }
Takashi Iwaib0b98112005-10-20 18:29:58 +02004764 if (hdsp->io_type == H9632 || hdsp->io_type == H9652)
Adrian Knoth4833c672013-01-15 18:52:22 +01004765 info.analog_extension_board =
4766 (unsigned char)hdsp_toggle_setting(hdsp,
4767 HDSP_AnalogExtensionBoard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004768 spin_unlock_irqrestore(&hdsp->lock, flags);
4769 if (copy_to_user(argp, &info, sizeof(info)))
4770 return -EFAULT;
4771 break;
4772 }
4773 case SNDRV_HDSP_IOCTL_GET_9632_AEB: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004774 struct hdsp_9632_aeb h9632_aeb;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004775
Linus Torvalds1da177e2005-04-16 15:20:36 -07004776 if (hdsp->io_type != H9632) return -EINVAL;
4777 h9632_aeb.aebi = hdsp->ss_in_channels - H9632_SS_CHANNELS;
4778 h9632_aeb.aebo = hdsp->ss_out_channels - H9632_SS_CHANNELS;
4779 if (copy_to_user(argp, &h9632_aeb, sizeof(h9632_aeb)))
4780 return -EFAULT;
4781 break;
4782 }
4783 case SNDRV_HDSP_IOCTL_GET_VERSION: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004784 struct hdsp_version hdsp_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004785 int err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004786
Linus Torvalds1da177e2005-04-16 15:20:36 -07004787 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
4788 if (hdsp->io_type == Undefined) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004789 if ((err = hdsp_get_iobox_version(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004790 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004791 }
Dan Carpenterd14df332013-10-16 11:44:25 +03004792 memset(&hdsp_version, 0, sizeof(hdsp_version));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004793 hdsp_version.io_type = hdsp->io_type;
4794 hdsp_version.firmware_rev = hdsp->firmware_rev;
Takashi Iwaib0b98112005-10-20 18:29:58 +02004795 if ((err = copy_to_user(argp, &hdsp_version, sizeof(hdsp_version))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004796 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004797 break;
4798 }
4799 case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004800 struct hdsp_firmware __user *firmware;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004801 u32 __user *firmware_data;
4802 int err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004803
Linus Torvalds1da177e2005-04-16 15:20:36 -07004804 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
4805 /* SNDRV_HDSP_IOCTL_GET_VERSION must have been called */
4806 if (hdsp->io_type == Undefined) return -EINVAL;
4807
4808 if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded))
4809 return -EBUSY;
4810
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01004811 dev_info(hdsp->card->dev,
4812 "initializing firmware upload\n");
Takashi Iwai55e957d2005-11-17 14:52:13 +01004813 firmware = (struct hdsp_firmware __user *)argp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004814
Takashi Iwaib0b98112005-10-20 18:29:58 +02004815 if (get_user(firmware_data, &firmware->firmware_data))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004816 return -EFAULT;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004817
Takashi Iwaib0b98112005-10-20 18:29:58 +02004818 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004819 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004820
Takashi Iwai90caaef2012-11-22 16:55:11 +01004821 if (!hdsp->fw_uploaded) {
4822 hdsp->fw_uploaded = vmalloc(HDSP_FIRMWARE_SIZE);
4823 if (!hdsp->fw_uploaded)
4824 return -ENOMEM;
4825 }
4826
4827 if (copy_from_user(hdsp->fw_uploaded, firmware_data,
4828 HDSP_FIRMWARE_SIZE)) {
4829 vfree(hdsp->fw_uploaded);
4830 hdsp->fw_uploaded = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004831 return -EFAULT;
Takashi Iwai90caaef2012-11-22 16:55:11 +01004832 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004833
Linus Torvalds1da177e2005-04-16 15:20:36 -07004834 hdsp->state |= HDSP_FirmwareCached;
4835
Takashi Iwaib0b98112005-10-20 18:29:58 +02004836 if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004837 return err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004838
Linus Torvalds1da177e2005-04-16 15:20:36 -07004839 if (!(hdsp->state & HDSP_InitializationComplete)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004840 if ((err = snd_hdsp_enable_io(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004841 return err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004842
4843 snd_hdsp_initialize_channels(hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004844 snd_hdsp_initialize_midi_flush(hdsp);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004845
Linus Torvalds1da177e2005-04-16 15:20:36 -07004846 if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01004847 dev_err(hdsp->card->dev,
4848 "error creating alsa devices\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02004849 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004850 }
4851 }
4852 break;
4853 }
4854 case SNDRV_HDSP_IOCTL_GET_MIXER: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004855 struct hdsp_mixer __user *mixer = (struct hdsp_mixer __user *)argp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004856 if (copy_to_user(mixer->matrix, hdsp->mixer_matrix, sizeof(unsigned short)*HDSP_MATRIX_MIXER_SIZE))
4857 return -EFAULT;
4858 break;
4859 }
4860 default:
4861 return -EINVAL;
4862 }
4863 return 0;
4864}
4865
Julia Lawall6769e982016-09-02 00:13:10 +02004866static const struct snd_pcm_ops snd_hdsp_playback_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004867 .open = snd_hdsp_playback_open,
4868 .close = snd_hdsp_playback_release,
4869 .ioctl = snd_hdsp_ioctl,
4870 .hw_params = snd_hdsp_hw_params,
4871 .prepare = snd_hdsp_prepare,
4872 .trigger = snd_hdsp_trigger,
4873 .pointer = snd_hdsp_hw_pointer,
4874 .copy = snd_hdsp_playback_copy,
4875 .silence = snd_hdsp_hw_silence,
4876};
4877
Julia Lawall6769e982016-09-02 00:13:10 +02004878static const struct snd_pcm_ops snd_hdsp_capture_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004879 .open = snd_hdsp_capture_open,
4880 .close = snd_hdsp_capture_release,
4881 .ioctl = snd_hdsp_ioctl,
4882 .hw_params = snd_hdsp_hw_params,
4883 .prepare = snd_hdsp_prepare,
4884 .trigger = snd_hdsp_trigger,
4885 .pointer = snd_hdsp_hw_pointer,
4886 .copy = snd_hdsp_capture_copy,
4887};
4888
Takashi Iwai92eed662008-02-22 18:35:56 +01004889static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004890{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004891 struct snd_hwdep *hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004892 int err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004893
Linus Torvalds1da177e2005-04-16 15:20:36 -07004894 if ((err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw)) < 0)
4895 return err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004896
Linus Torvalds1da177e2005-04-16 15:20:36 -07004897 hdsp->hwdep = hw;
4898 hw->private_data = hdsp;
4899 strcpy(hw->name, "HDSP hwdep interface");
4900
Linus Torvalds1da177e2005-04-16 15:20:36 -07004901 hw->ops.ioctl = snd_hdsp_hwdep_ioctl;
Andre Schramm42eb9232012-05-07 18:52:51 +02004902 hw->ops.ioctl_compat = snd_hdsp_hwdep_ioctl;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004903
Linus Torvalds1da177e2005-04-16 15:20:36 -07004904 return 0;
4905}
4906
Takashi Iwai55e957d2005-11-17 14:52:13 +01004907static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004908{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004909 struct snd_pcm *pcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004910 int err;
4911
4912 if ((err = snd_pcm_new(card, hdsp->card_name, 0, 1, 1, &pcm)) < 0)
4913 return err;
4914
4915 hdsp->pcm = pcm;
4916 pcm->private_data = hdsp;
4917 strcpy(pcm->name, hdsp->card_name);
4918
4919 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_hdsp_playback_ops);
4920 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_hdsp_capture_ops);
4921
4922 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
4923
4924 return 0;
4925}
4926
Takashi Iwai55e957d2005-11-17 14:52:13 +01004927static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004928{
4929 hdsp->control2_register |= HDSP_9652_ENABLE_MIXER;
4930 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
4931}
4932
Takashi Iwai55e957d2005-11-17 14:52:13 +01004933static int snd_hdsp_enable_io (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004934{
4935 int i;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004936
Linus Torvalds1da177e2005-04-16 15:20:36 -07004937 if (hdsp_fifo_wait (hdsp, 0, 100)) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01004938 dev_err(hdsp->card->dev,
4939 "enable_io fifo_wait failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004940 return -EIO;
4941 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004942
Linus Torvalds1da177e2005-04-16 15:20:36 -07004943 for (i = 0; i < hdsp->max_channels; ++i) {
4944 hdsp_write (hdsp, HDSP_inputEnable + (4 * i), 1);
4945 hdsp_write (hdsp, HDSP_outputEnable + (4 * i), 1);
4946 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004947
Linus Torvalds1da177e2005-04-16 15:20:36 -07004948 return 0;
4949}
4950
Takashi Iwai55e957d2005-11-17 14:52:13 +01004951static void snd_hdsp_initialize_channels(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004952{
4953 int status, aebi_channels, aebo_channels;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004954
Linus Torvalds1da177e2005-04-16 15:20:36 -07004955 switch (hdsp->io_type) {
4956 case Digiface:
4957 hdsp->card_name = "RME Hammerfall DSP + Digiface";
4958 hdsp->ss_in_channels = hdsp->ss_out_channels = DIGIFACE_SS_CHANNELS;
4959 hdsp->ds_in_channels = hdsp->ds_out_channels = DIGIFACE_DS_CHANNELS;
4960 break;
4961
4962 case H9652:
4963 hdsp->card_name = "RME Hammerfall HDSP 9652";
4964 hdsp->ss_in_channels = hdsp->ss_out_channels = H9652_SS_CHANNELS;
4965 hdsp->ds_in_channels = hdsp->ds_out_channels = H9652_DS_CHANNELS;
4966 break;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004967
Linus Torvalds1da177e2005-04-16 15:20:36 -07004968 case H9632:
4969 status = hdsp_read(hdsp, HDSP_statusRegister);
4970 /* HDSP_AEBx bits are low when AEB are connected */
4971 aebi_channels = (status & HDSP_AEBI) ? 0 : 4;
4972 aebo_channels = (status & HDSP_AEBO) ? 0 : 4;
4973 hdsp->card_name = "RME Hammerfall HDSP 9632";
4974 hdsp->ss_in_channels = H9632_SS_CHANNELS+aebi_channels;
4975 hdsp->ds_in_channels = H9632_DS_CHANNELS+aebi_channels;
4976 hdsp->qs_in_channels = H9632_QS_CHANNELS+aebi_channels;
4977 hdsp->ss_out_channels = H9632_SS_CHANNELS+aebo_channels;
4978 hdsp->ds_out_channels = H9632_DS_CHANNELS+aebo_channels;
4979 hdsp->qs_out_channels = H9632_QS_CHANNELS+aebo_channels;
4980 break;
4981
4982 case Multiface:
4983 hdsp->card_name = "RME Hammerfall DSP + Multiface";
4984 hdsp->ss_in_channels = hdsp->ss_out_channels = MULTIFACE_SS_CHANNELS;
4985 hdsp->ds_in_channels = hdsp->ds_out_channels = MULTIFACE_DS_CHANNELS;
4986 break;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004987
Florian Faber28b26e12010-12-01 12:14:47 +01004988 case RPM:
4989 hdsp->card_name = "RME Hammerfall DSP + RPM";
4990 hdsp->ss_in_channels = RPM_CHANNELS-1;
4991 hdsp->ss_out_channels = RPM_CHANNELS;
4992 hdsp->ds_in_channels = RPM_CHANNELS-1;
4993 hdsp->ds_out_channels = RPM_CHANNELS;
4994 break;
4995
Linus Torvalds1da177e2005-04-16 15:20:36 -07004996 default:
4997 /* should never get here */
4998 break;
4999 }
5000}
5001
Takashi Iwai55e957d2005-11-17 14:52:13 +01005002static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005003{
5004 snd_hdsp_flush_midi_input (hdsp, 0);
5005 snd_hdsp_flush_midi_input (hdsp, 1);
5006}
5007
Takashi Iwai55e957d2005-11-17 14:52:13 +01005008static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005009{
5010 int err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005011
Linus Torvalds1da177e2005-04-16 15:20:36 -07005012 if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005013 dev_err(card->dev,
5014 "Error creating pcm interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005015 return err;
5016 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005017
Linus Torvalds1da177e2005-04-16 15:20:36 -07005018
5019 if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005020 dev_err(card->dev,
5021 "Error creating first midi interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005022 return err;
5023 }
5024
5025 if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
5026 if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005027 dev_err(card->dev,
5028 "Error creating second midi interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005029 return err;
5030 }
5031 }
5032
5033 if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005034 dev_err(card->dev,
5035 "Error creating ctl interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005036 return err;
5037 }
5038
5039 snd_hdsp_proc_init(hdsp);
5040
5041 hdsp->system_sample_rate = -1;
5042 hdsp->playback_pid = -1;
5043 hdsp->capture_pid = -1;
5044 hdsp->capture_substream = NULL;
5045 hdsp->playback_substream = NULL;
5046
5047 if ((err = snd_hdsp_set_defaults(hdsp)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005048 dev_err(card->dev,
5049 "Error setting default values\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005050 return err;
5051 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005052
Linus Torvalds1da177e2005-04-16 15:20:36 -07005053 if (!(hdsp->state & HDSP_InitializationComplete)) {
Clemens Ladischb73c1c12005-09-02 08:49:21 +02005054 strcpy(card->shortname, "Hammerfall DSP");
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005055 sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005056 hdsp->port, hdsp->irq);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005057
Linus Torvalds1da177e2005-04-16 15:20:36 -07005058 if ((err = snd_card_register(card)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005059 dev_err(card->dev,
5060 "error registering card\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005061 return err;
5062 }
5063 hdsp->state |= HDSP_InitializationComplete;
5064 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005065
Linus Torvalds1da177e2005-04-16 15:20:36 -07005066 return 0;
5067}
5068
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069/* load firmware via hotplug fw loader */
Takashi Iwai92eed662008-02-22 18:35:56 +01005070static int hdsp_request_fw_loader(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005071{
5072 const char *fwfile;
5073 const struct firmware *fw;
5074 int err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005075
Linus Torvalds1da177e2005-04-16 15:20:36 -07005076 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
5077 return 0;
5078 if (hdsp->io_type == Undefined) {
5079 if ((err = hdsp_get_iobox_version(hdsp)) < 0)
5080 return err;
5081 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
5082 return 0;
5083 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005084
Linus Torvalds1da177e2005-04-16 15:20:36 -07005085 /* caution: max length of firmware filename is 30! */
5086 switch (hdsp->io_type) {
Florian Faber28b26e12010-12-01 12:14:47 +01005087 case RPM:
5088 fwfile = "rpm_firmware.bin";
5089 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005090 case Multiface:
5091 if (hdsp->firmware_rev == 0xa)
5092 fwfile = "multiface_firmware.bin";
5093 else
5094 fwfile = "multiface_firmware_rev11.bin";
5095 break;
5096 case Digiface:
5097 if (hdsp->firmware_rev == 0xa)
5098 fwfile = "digiface_firmware.bin";
5099 else
5100 fwfile = "digiface_firmware_rev11.bin";
5101 break;
5102 default:
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005103 dev_err(hdsp->card->dev,
5104 "invalid io_type %d\n", hdsp->io_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005105 return -EINVAL;
5106 }
5107
5108 if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005109 dev_err(hdsp->card->dev,
5110 "cannot load firmware %s\n", fwfile);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005111 return -ENOENT;
5112 }
Takashi Iwai90caaef2012-11-22 16:55:11 +01005113 if (fw->size < HDSP_FIRMWARE_SIZE) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005114 dev_err(hdsp->card->dev,
5115 "too short firmware size %d (expected %d)\n",
Takashi Iwai90caaef2012-11-22 16:55:11 +01005116 (int)fw->size, HDSP_FIRMWARE_SIZE);
Sudip Mukherjee29d28c52015-09-11 19:10:38 +05305117 release_firmware(fw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005118 return -EINVAL;
5119 }
Thomas Charbonnel7679a032005-04-25 11:35:29 +02005120
Takashi Iwai90caaef2012-11-22 16:55:11 +01005121 hdsp->firmware = fw;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005122
Linus Torvalds1da177e2005-04-16 15:20:36 -07005123 hdsp->state |= HDSP_FirmwareCached;
5124
5125 if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
5126 return err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005127
Linus Torvalds1da177e2005-04-16 15:20:36 -07005128 if (!(hdsp->state & HDSP_InitializationComplete)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02005129 if ((err = snd_hdsp_enable_io(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005130 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005131
5132 if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005133 dev_err(hdsp->card->dev,
5134 "error creating hwdep device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005135 return err;
5136 }
5137 snd_hdsp_initialize_channels(hdsp);
5138 snd_hdsp_initialize_midi_flush(hdsp);
5139 if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005140 dev_err(hdsp->card->dev,
5141 "error creating alsa devices\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005142 return err;
5143 }
5144 }
5145 return 0;
5146}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005147
Bill Pembertone23e7a12012-12-06 12:35:10 -05005148static int snd_hdsp_create(struct snd_card *card,
5149 struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005150{
5151 struct pci_dev *pci = hdsp->pci;
5152 int err;
5153 int is_9652 = 0;
5154 int is_9632 = 0;
5155
5156 hdsp->irq = -1;
5157 hdsp->state = 0;
5158 hdsp->midi[0].rmidi = NULL;
5159 hdsp->midi[1].rmidi = NULL;
5160 hdsp->midi[0].input = NULL;
5161 hdsp->midi[1].input = NULL;
5162 hdsp->midi[0].output = NULL;
5163 hdsp->midi[1].output = NULL;
5164 hdsp->midi[0].pending = 0;
5165 hdsp->midi[1].pending = 0;
5166 spin_lock_init(&hdsp->midi[0].lock);
5167 spin_lock_init(&hdsp->midi[1].lock);
5168 hdsp->iobase = NULL;
5169 hdsp->control_register = 0;
5170 hdsp->control2_register = 0;
5171 hdsp->io_type = Undefined;
5172 hdsp->max_channels = 26;
5173
5174 hdsp->card = card;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005175
Linus Torvalds1da177e2005-04-16 15:20:36 -07005176 spin_lock_init(&hdsp->lock);
5177
5178 tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005179
Linus Torvalds1da177e2005-04-16 15:20:36 -07005180 pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev);
5181 hdsp->firmware_rev &= 0xff;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005182
Linus Torvalds1da177e2005-04-16 15:20:36 -07005183 /* From Martin Bjoernsen :
5184 "It is important that the card's latency timer register in
5185 the PCI configuration space is set to a value much larger
5186 than 0 by the computer's BIOS or the driver.
5187 The windows driver always sets this 8 bit register [...]
5188 to its maximum 255 to avoid problems with some computers."
5189 */
5190 pci_write_config_byte(hdsp->pci, PCI_LATENCY_TIMER, 0xFF);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005191
Linus Torvalds1da177e2005-04-16 15:20:36 -07005192 strcpy(card->driver, "H-DSP");
5193 strcpy(card->mixername, "Xilinx FPGA");
5194
Takashi Iwaib0b98112005-10-20 18:29:58 +02005195 if (hdsp->firmware_rev < 0xa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005196 return -ENODEV;
Takashi Iwaib0b98112005-10-20 18:29:58 +02005197 else if (hdsp->firmware_rev < 0x64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005198 hdsp->card_name = "RME Hammerfall DSP";
Takashi Iwaib0b98112005-10-20 18:29:58 +02005199 else if (hdsp->firmware_rev < 0x96) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005200 hdsp->card_name = "RME HDSP 9652";
5201 is_9652 = 1;
5202 } else {
5203 hdsp->card_name = "RME HDSP 9632";
5204 hdsp->max_channels = 16;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005205 is_9632 = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005206 }
5207
Takashi Iwaib0b98112005-10-20 18:29:58 +02005208 if ((err = pci_enable_device(pci)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005209 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005210
5211 pci_set_master(hdsp->pci);
5212
5213 if ((err = pci_request_regions(pci, "hdsp")) < 0)
5214 return err;
5215 hdsp->port = pci_resource_start(pci, 0);
5216 if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005217 dev_err(hdsp->card->dev, "unable to remap region 0x%lx-0x%lx\n",
5218 hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005219 return -EBUSY;
5220 }
5221
Takashi Iwai437a5a42006-11-21 12:14:23 +01005222 if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_SHARED,
Takashi Iwai934c2b62011-06-10 16:36:37 +02005223 KBUILD_MODNAME, hdsp)) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005224 dev_err(hdsp->card->dev, "unable to use IRQ %d\n", pci->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005225 return -EBUSY;
5226 }
5227
5228 hdsp->irq = pci->irq;
Remy Bruno176546a2006-10-16 12:32:53 +02005229 hdsp->precise_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005230 hdsp->use_midi_tasklet = 1;
Remy Brunod7923b22006-10-17 12:41:56 +02005231 hdsp->dds_value = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005232
Takashi Iwaib0b98112005-10-20 18:29:58 +02005233 if ((err = snd_hdsp_initialize_memory(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005234 return err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005235
Linus Torvalds1da177e2005-04-16 15:20:36 -07005236 if (!is_9652 && !is_9632) {
Tim Blechmanne588ed82009-02-20 19:30:35 +01005237 /* we wait a maximum of 10 seconds to let freshly
5238 * inserted cardbus cards do their hardware init */
5239 err = hdsp_wait_for_iobox(hdsp, 1000, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005240
Tim Blechmann00c9ddd2008-11-09 12:50:52 +01005241 if (err < 0)
5242 return err;
5243
Linus Torvalds1da177e2005-04-16 15:20:36 -07005244 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02005245 if ((err = hdsp_request_fw_loader(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005246 /* we don't fail as this can happen
5247 if userspace is not ready for
5248 firmware upload
5249 */
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005250 dev_err(hdsp->card->dev,
5251 "couldn't get firmware from userspace. try using hdsploader\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02005252 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07005253 /* init is complete, we return */
5254 return 0;
Tim Blechmann00c9ddd2008-11-09 12:50:52 +01005255 /* we defer initialization */
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005256 dev_info(hdsp->card->dev,
5257 "card initialization pending : waiting for firmware\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02005258 if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005259 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005260 return 0;
5261 } else {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005262 dev_info(hdsp->card->dev,
5263 "Firmware already present, initializing card.\n");
Florian Faber28b26e12010-12-01 12:14:47 +01005264 if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version2)
5265 hdsp->io_type = RPM;
5266 else if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005267 hdsp->io_type = Multiface;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005268 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269 hdsp->io_type = Digiface;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005270 }
5271 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005272
Takashi Iwaib0b98112005-10-20 18:29:58 +02005273 if ((err = snd_hdsp_enable_io(hdsp)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005274 return err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005275
Takashi Iwaib0b98112005-10-20 18:29:58 +02005276 if (is_9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005277 hdsp->io_type = H9652;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005278
Takashi Iwaib0b98112005-10-20 18:29:58 +02005279 if (is_9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005280 hdsp->io_type = H9632;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005281
Takashi Iwaib0b98112005-10-20 18:29:58 +02005282 if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005283 return err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005284
Linus Torvalds1da177e2005-04-16 15:20:36 -07005285 snd_hdsp_initialize_channels(hdsp);
5286 snd_hdsp_initialize_midi_flush(hdsp);
5287
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005288 hdsp->state |= HDSP_FirmwareLoaded;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005289
Takashi Iwaib0b98112005-10-20 18:29:58 +02005290 if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005291 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005292
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005293 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005294}
5295
Takashi Iwai55e957d2005-11-17 14:52:13 +01005296static int snd_hdsp_free(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005297{
5298 if (hdsp->port) {
5299 /* stop the audio, and cancel all interrupts */
5300 tasklet_kill(&hdsp->midi_tasklet);
5301 hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable);
5302 hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
5303 }
5304
5305 if (hdsp->irq >= 0)
5306 free_irq(hdsp->irq, (void *)hdsp);
5307
5308 snd_hdsp_free_buffers(hdsp);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005309
Markus Elfringc2836612014-11-17 13:04:14 +01005310 release_firmware(hdsp->firmware);
Takashi Iwai90caaef2012-11-22 16:55:11 +01005311 vfree(hdsp->fw_uploaded);
Markus Elfringff6defa2015-01-03 22:55:54 +01005312 iounmap(hdsp->iobase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005313
5314 if (hdsp->port)
5315 pci_release_regions(hdsp->pci);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005316
Linus Torvalds1da177e2005-04-16 15:20:36 -07005317 pci_disable_device(hdsp->pci);
5318 return 0;
5319}
5320
Takashi Iwai55e957d2005-11-17 14:52:13 +01005321static void snd_hdsp_card_free(struct snd_card *card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005322{
Joe Perches9fe856e2010-09-04 18:52:54 -07005323 struct hdsp *hdsp = card->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005324
5325 if (hdsp)
5326 snd_hdsp_free(hdsp);
5327}
5328
Bill Pembertone23e7a12012-12-06 12:35:10 -05005329static int snd_hdsp_probe(struct pci_dev *pci,
5330 const struct pci_device_id *pci_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005331{
5332 static int dev;
Takashi Iwai55e957d2005-11-17 14:52:13 +01005333 struct hdsp *hdsp;
5334 struct snd_card *card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005335 int err;
5336
5337 if (dev >= SNDRV_CARDS)
5338 return -ENODEV;
5339 if (!enable[dev]) {
5340 dev++;
5341 return -ENOENT;
5342 }
5343
Takashi Iwai60c57722014-01-29 14:20:19 +01005344 err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
5345 sizeof(struct hdsp), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01005346 if (err < 0)
5347 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005348
Joe Perches9fe856e2010-09-04 18:52:54 -07005349 hdsp = card->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005350 card->private_free = snd_hdsp_card_free;
5351 hdsp->dev = dev;
5352 hdsp->pci = pci;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005353
5354 if ((err = snd_hdsp_create(card, hdsp)) < 0) {
5355 snd_card_free(card);
5356 return err;
5357 }
5358
5359 strcpy(card->shortname, "Hammerfall DSP");
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005360 sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005361 hdsp->port, hdsp->irq);
5362
5363 if ((err = snd_card_register(card)) < 0) {
5364 snd_card_free(card);
5365 return err;
5366 }
5367 pci_set_drvdata(pci, card);
5368 dev++;
5369 return 0;
5370}
5371
Bill Pembertone23e7a12012-12-06 12:35:10 -05005372static void snd_hdsp_remove(struct pci_dev *pci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005373{
5374 snd_card_free(pci_get_drvdata(pci));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005375}
5376
Takashi Iwaie9f66d92012-04-24 12:25:00 +02005377static struct pci_driver hdsp_driver = {
Takashi Iwai3733e422011-06-10 16:20:20 +02005378 .name = KBUILD_MODNAME,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005379 .id_table = snd_hdsp_ids,
5380 .probe = snd_hdsp_probe,
Bill Pembertone23e7a12012-12-06 12:35:10 -05005381 .remove = snd_hdsp_remove,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005382};
5383
Takashi Iwaie9f66d92012-04-24 12:25:00 +02005384module_pci_driver(hdsp_driver);