blob: 4c6f5d1c9882c1e054f0b785995083430cd6be0f [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032
33#include <sound/core.h>
34#include <sound/control.h>
35#include <sound/pcm.h>
36#include <sound/info.h>
37#include <sound/asoundef.h>
38#include <sound/rawmidi.h>
39#include <sound/hwdep.h>
40#include <sound/initval.h>
41#include <sound/hdsp.h>
42
43#include <asm/byteorder.h>
44#include <asm/current.h>
45#include <asm/io.h>
46
47static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
48static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
Rusty Russella67ff6a2011-12-15 13:49:36 +103049static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51module_param_array(index, int, NULL, 0444);
52MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface.");
53module_param_array(id, charp, NULL, 0444);
54MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface.");
55module_param_array(enable, bool, NULL, 0444);
56MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards.");
57MODULE_AUTHOR("Paul Davis <paul@linuxaudiosystems.com>, Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
58MODULE_DESCRIPTION("RME Hammerfall DSP");
59MODULE_LICENSE("GPL");
60MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
61 "{RME HDSP-9652},"
62 "{RME HDSP-9632}}");
Florian Faber28b26e12010-12-01 12:14:47 +010063MODULE_FIRMWARE("rpm_firmware.bin");
Clemens Ladisch7e0af292007-05-03 17:59:54 +020064MODULE_FIRMWARE("multiface_firmware.bin");
65MODULE_FIRMWARE("multiface_firmware_rev11.bin");
66MODULE_FIRMWARE("digiface_firmware.bin");
67MODULE_FIRMWARE("digiface_firmware_rev11.bin");
Linus Torvalds1da177e2005-04-16 15:20:36 -070068
69#define HDSP_MAX_CHANNELS 26
70#define HDSP_MAX_DS_CHANNELS 14
71#define HDSP_MAX_QS_CHANNELS 8
72#define DIGIFACE_SS_CHANNELS 26
73#define DIGIFACE_DS_CHANNELS 14
74#define MULTIFACE_SS_CHANNELS 18
75#define MULTIFACE_DS_CHANNELS 14
76#define H9652_SS_CHANNELS 26
77#define H9652_DS_CHANNELS 14
78/* This does not include possible Analog Extension Boards
79 AEBs are detected at card initialization
80*/
81#define H9632_SS_CHANNELS 12
82#define H9632_DS_CHANNELS 8
83#define H9632_QS_CHANNELS 4
Florian Faber28b26e12010-12-01 12:14:47 +010084#define RPM_CHANNELS 6
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
86/* Write registers. These are defined as byte-offsets from the iobase value.
87 */
88#define HDSP_resetPointer 0
Remy Brunod7923b22006-10-17 12:41:56 +020089#define HDSP_freqReg 0
Linus Torvalds1da177e2005-04-16 15:20:36 -070090#define HDSP_outputBufferAddress 32
91#define HDSP_inputBufferAddress 36
92#define HDSP_controlRegister 64
93#define HDSP_interruptConfirmation 96
94#define HDSP_outputEnable 128
95#define HDSP_control2Reg 256
96#define HDSP_midiDataOut0 352
97#define HDSP_midiDataOut1 356
98#define HDSP_fifoData 368
99#define HDSP_inputEnable 384
100
101/* Read registers. These are defined as byte-offsets from the iobase value
102 */
103
104#define HDSP_statusRegister 0
105#define HDSP_timecode 128
106#define HDSP_status2Register 192
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107#define HDSP_midiDataIn0 360
108#define HDSP_midiDataIn1 364
109#define HDSP_midiStatusOut0 384
110#define HDSP_midiStatusOut1 388
111#define HDSP_midiStatusIn0 392
112#define HDSP_midiStatusIn1 396
113#define HDSP_fifoStatus 400
114
115/* the meters are regular i/o-mapped registers, but offset
116 considerably from the rest. the peak registers are reset
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100117 when read; the least-significant 4 bits are full-scale counters;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 the actual peak value is in the most-significant 24 bits.
119*/
120
121#define HDSP_playbackPeakLevel 4096 /* 26 * 32 bit values */
122#define HDSP_inputPeakLevel 4224 /* 26 * 32 bit values */
123#define HDSP_outputPeakLevel 4352 /* (26+2) * 32 bit values */
124#define HDSP_playbackRmsLevel 4612 /* 26 * 64 bit values */
125#define HDSP_inputRmsLevel 4868 /* 26 * 64 bit values */
126
127
128/* This is for H9652 cards
129 Peak values are read downward from the base
130 Rms values are read upward
131 There are rms values for the outputs too
132 26*3 values are read in ss mode
133 14*3 in ds mode, with no gap between values
134*/
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100135#define HDSP_9652_peakBase 7164
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136#define HDSP_9652_rmsBase 4096
137
138/* c.f. the hdsp_9632_meters_t struct */
139#define HDSP_9632_metersBase 4096
140
141#define HDSP_IO_EXTENT 7168
142
143/* control2 register bits */
144
145#define HDSP_TMS 0x01
146#define HDSP_TCK 0x02
147#define HDSP_TDI 0x04
148#define HDSP_JTAG 0x08
149#define HDSP_PWDN 0x10
150#define HDSP_PROGRAM 0x020
151#define HDSP_CONFIG_MODE_0 0x040
152#define HDSP_CONFIG_MODE_1 0x080
Adrian Knotha3466862011-10-27 21:57:53 +0200153#define HDSP_VERSION_BIT (0x100 | HDSP_S_LOAD)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154#define HDSP_BIGENDIAN_MODE 0x200
155#define HDSP_RD_MULTIPLE 0x400
156#define HDSP_9652_ENABLE_MIXER 0x800
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100157#define HDSP_S200 0x800
158#define HDSP_S300 (0x100 | HDSP_S200) /* dummy, purpose of 0x100 unknown */
159#define HDSP_CYCLIC_MODE 0x1000
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160#define HDSP_TDO 0x10000000
161
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100162#define HDSP_S_PROGRAM (HDSP_CYCLIC_MODE|HDSP_PROGRAM|HDSP_CONFIG_MODE_0)
163#define HDSP_S_LOAD (HDSP_CYCLIC_MODE|HDSP_PROGRAM|HDSP_CONFIG_MODE_1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164
165/* Control Register bits */
166
167#define HDSP_Start (1<<0) /* start engine */
168#define HDSP_Latency0 (1<<1) /* buffer size = 2^n where n is defined by Latency{2,1,0} */
169#define HDSP_Latency1 (1<<2) /* [ see above ] */
170#define HDSP_Latency2 (1<<3) /* [ see above ] */
171#define HDSP_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */
172#define HDSP_AudioInterruptEnable (1<<5) /* what do you think ? */
173#define HDSP_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz/176.4kHz 1=48kHz/96kHz/192kHz */
174#define HDSP_Frequency1 (1<<7) /* 0=32kHz/64kHz/128kHz */
175#define HDSP_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
176#define HDSP_SPDIFProfessional (1<<9) /* 0=consumer, 1=professional */
177#define HDSP_SPDIFEmphasis (1<<10) /* 0=none, 1=on */
178#define HDSP_SPDIFNonAudio (1<<11) /* 0=off, 1=on */
179#define HDSP_SPDIFOpticalOut (1<<12) /* 1=use 1st ADAT connector for SPDIF, 0=do not */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100180#define HDSP_SyncRef2 (1<<13)
181#define HDSP_SPDIFInputSelect0 (1<<14)
182#define HDSP_SPDIFInputSelect1 (1<<15)
183#define HDSP_SyncRef0 (1<<16)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184#define HDSP_SyncRef1 (1<<17)
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100185#define HDSP_AnalogExtensionBoard (1<<18) /* For H9632 cards */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186#define HDSP_XLRBreakoutCable (1<<20) /* For H9632 cards */
187#define HDSP_Midi0InterruptEnable (1<<22)
188#define HDSP_Midi1InterruptEnable (1<<23)
189#define HDSP_LineOut (1<<24)
190#define HDSP_ADGain0 (1<<25) /* From here : H9632 specific */
191#define HDSP_ADGain1 (1<<26)
192#define HDSP_DAGain0 (1<<27)
193#define HDSP_DAGain1 (1<<28)
194#define HDSP_PhoneGain0 (1<<29)
195#define HDSP_PhoneGain1 (1<<30)
196#define HDSP_QuadSpeed (1<<31)
197
Florian Faber28b26e12010-12-01 12:14:47 +0100198/* RPM uses some of the registers for special purposes */
199#define HDSP_RPM_Inp12 0x04A00
200#define HDSP_RPM_Inp12_Phon_6dB 0x00800 /* Dolby */
201#define HDSP_RPM_Inp12_Phon_0dB 0x00000 /* .. */
202#define HDSP_RPM_Inp12_Phon_n6dB 0x04000 /* inp_0 */
203#define HDSP_RPM_Inp12_Line_0dB 0x04200 /* Dolby+PRO */
204#define HDSP_RPM_Inp12_Line_n6dB 0x00200 /* PRO */
205
206#define HDSP_RPM_Inp34 0x32000
207#define HDSP_RPM_Inp34_Phon_6dB 0x20000 /* SyncRef1 */
208#define HDSP_RPM_Inp34_Phon_0dB 0x00000 /* .. */
209#define HDSP_RPM_Inp34_Phon_n6dB 0x02000 /* SyncRef2 */
210#define HDSP_RPM_Inp34_Line_0dB 0x30000 /* SyncRef1+SyncRef0 */
211#define HDSP_RPM_Inp34_Line_n6dB 0x10000 /* SyncRef0 */
212
213#define HDSP_RPM_Bypass 0x01000
214
215#define HDSP_RPM_Disconnect 0x00001
216
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217#define HDSP_ADGainMask (HDSP_ADGain0|HDSP_ADGain1)
218#define HDSP_ADGainMinus10dBV HDSP_ADGainMask
219#define HDSP_ADGainPlus4dBu (HDSP_ADGain0)
220#define HDSP_ADGainLowGain 0
221
222#define HDSP_DAGainMask (HDSP_DAGain0|HDSP_DAGain1)
223#define HDSP_DAGainHighGain HDSP_DAGainMask
224#define HDSP_DAGainPlus4dBu (HDSP_DAGain0)
225#define HDSP_DAGainMinus10dBV 0
226
227#define HDSP_PhoneGainMask (HDSP_PhoneGain0|HDSP_PhoneGain1)
228#define HDSP_PhoneGain0dB HDSP_PhoneGainMask
229#define HDSP_PhoneGainMinus6dB (HDSP_PhoneGain0)
230#define HDSP_PhoneGainMinus12dB 0
231
232#define HDSP_LatencyMask (HDSP_Latency0|HDSP_Latency1|HDSP_Latency2)
233#define HDSP_FrequencyMask (HDSP_Frequency0|HDSP_Frequency1|HDSP_DoubleSpeed|HDSP_QuadSpeed)
234
235#define HDSP_SPDIFInputMask (HDSP_SPDIFInputSelect0|HDSP_SPDIFInputSelect1)
236#define HDSP_SPDIFInputADAT1 0
237#define HDSP_SPDIFInputCoaxial (HDSP_SPDIFInputSelect0)
238#define HDSP_SPDIFInputCdrom (HDSP_SPDIFInputSelect1)
239#define HDSP_SPDIFInputAES (HDSP_SPDIFInputSelect0|HDSP_SPDIFInputSelect1)
240
241#define HDSP_SyncRefMask (HDSP_SyncRef0|HDSP_SyncRef1|HDSP_SyncRef2)
242#define HDSP_SyncRef_ADAT1 0
243#define HDSP_SyncRef_ADAT2 (HDSP_SyncRef0)
244#define HDSP_SyncRef_ADAT3 (HDSP_SyncRef1)
245#define HDSP_SyncRef_SPDIF (HDSP_SyncRef0|HDSP_SyncRef1)
246#define HDSP_SyncRef_WORD (HDSP_SyncRef2)
247#define HDSP_SyncRef_ADAT_SYNC (HDSP_SyncRef0|HDSP_SyncRef2)
248
249/* Sample Clock Sources */
250
251#define HDSP_CLOCK_SOURCE_AUTOSYNC 0
252#define HDSP_CLOCK_SOURCE_INTERNAL_32KHZ 1
253#define HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ 2
254#define HDSP_CLOCK_SOURCE_INTERNAL_48KHZ 3
255#define HDSP_CLOCK_SOURCE_INTERNAL_64KHZ 4
256#define HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ 5
257#define HDSP_CLOCK_SOURCE_INTERNAL_96KHZ 6
258#define HDSP_CLOCK_SOURCE_INTERNAL_128KHZ 7
259#define HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ 8
260#define HDSP_CLOCK_SOURCE_INTERNAL_192KHZ 9
261
262/* Preferred sync reference choices - used by "pref_sync_ref" control switch */
263
264#define HDSP_SYNC_FROM_WORD 0
265#define HDSP_SYNC_FROM_SPDIF 1
266#define HDSP_SYNC_FROM_ADAT1 2
267#define HDSP_SYNC_FROM_ADAT_SYNC 3
268#define HDSP_SYNC_FROM_ADAT2 4
269#define HDSP_SYNC_FROM_ADAT3 5
270
271/* SyncCheck status */
272
273#define HDSP_SYNC_CHECK_NO_LOCK 0
274#define HDSP_SYNC_CHECK_LOCK 1
275#define HDSP_SYNC_CHECK_SYNC 2
276
277/* AutoSync references - used by "autosync_ref" control switch */
278
279#define HDSP_AUTOSYNC_FROM_WORD 0
280#define HDSP_AUTOSYNC_FROM_ADAT_SYNC 1
281#define HDSP_AUTOSYNC_FROM_SPDIF 2
282#define HDSP_AUTOSYNC_FROM_NONE 3
283#define HDSP_AUTOSYNC_FROM_ADAT1 4
284#define HDSP_AUTOSYNC_FROM_ADAT2 5
285#define HDSP_AUTOSYNC_FROM_ADAT3 6
286
287/* Possible sources of S/PDIF input */
288
289#define HDSP_SPDIFIN_OPTICAL 0 /* optical (ADAT1) */
290#define HDSP_SPDIFIN_COAXIAL 1 /* coaxial (RCA) */
291#define HDSP_SPDIFIN_INTERNAL 2 /* internal (CDROM) */
292#define HDSP_SPDIFIN_AES 3 /* xlr for H9632 (AES)*/
293
294#define HDSP_Frequency32KHz HDSP_Frequency0
295#define HDSP_Frequency44_1KHz HDSP_Frequency1
296#define HDSP_Frequency48KHz (HDSP_Frequency1|HDSP_Frequency0)
297#define HDSP_Frequency64KHz (HDSP_DoubleSpeed|HDSP_Frequency0)
298#define HDSP_Frequency88_2KHz (HDSP_DoubleSpeed|HDSP_Frequency1)
299#define HDSP_Frequency96KHz (HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0)
300/* For H9632 cards */
301#define HDSP_Frequency128KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency0)
302#define HDSP_Frequency176_4KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1)
303#define HDSP_Frequency192KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0)
Julian Cablee4b60882007-03-19 11:44:40 +0100304/* RME says n = 104857600000000, but in the windows MADI driver, I see:
305 return 104857600000000 / rate; // 100 MHz
306 return 110100480000000 / rate; // 105 MHz
307*/
308#define DDS_NUMERATOR 104857600000000ULL; /* = 2^20 * 10^8 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
310#define hdsp_encode_latency(x) (((x)<<1) & HDSP_LatencyMask)
311#define hdsp_decode_latency(x) (((x) & HDSP_LatencyMask)>>1)
312
313#define hdsp_encode_spdif_in(x) (((x)&0x3)<<14)
314#define hdsp_decode_spdif_in(x) (((x)>>14)&0x3)
315
316/* Status Register bits */
317
318#define HDSP_audioIRQPending (1<<0)
319#define HDSP_Lock2 (1<<1) /* this is for Digiface and H9652 */
320#define HDSP_spdifFrequency3 HDSP_Lock2 /* this is for H9632 only */
321#define HDSP_Lock1 (1<<2)
322#define HDSP_Lock0 (1<<3)
323#define HDSP_SPDIFSync (1<<4)
324#define HDSP_TimecodeLock (1<<5)
325#define HDSP_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
326#define HDSP_Sync2 (1<<16)
327#define HDSP_Sync1 (1<<17)
328#define HDSP_Sync0 (1<<18)
329#define HDSP_DoubleSpeedStatus (1<<19)
330#define HDSP_ConfigError (1<<20)
331#define HDSP_DllError (1<<21)
332#define HDSP_spdifFrequency0 (1<<22)
333#define HDSP_spdifFrequency1 (1<<23)
334#define HDSP_spdifFrequency2 (1<<24)
335#define HDSP_SPDIFErrorFlag (1<<25)
336#define HDSP_BufferID (1<<26)
337#define HDSP_TimecodeSync (1<<27)
338#define HDSP_AEBO (1<<28) /* H9632 specific Analog Extension Boards */
339#define HDSP_AEBI (1<<29) /* 0 = present, 1 = absent */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100340#define HDSP_midi0IRQPending (1<<30)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341#define HDSP_midi1IRQPending (1<<31)
342
343#define HDSP_spdifFrequencyMask (HDSP_spdifFrequency0|HDSP_spdifFrequency1|HDSP_spdifFrequency2)
Remy Bruno47ba97f2008-02-22 17:57:02 +0100344#define HDSP_spdifFrequencyMask_9632 (HDSP_spdifFrequency0|\
345 HDSP_spdifFrequency1|\
346 HDSP_spdifFrequency2|\
347 HDSP_spdifFrequency3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348
349#define HDSP_spdifFrequency32KHz (HDSP_spdifFrequency0)
350#define HDSP_spdifFrequency44_1KHz (HDSP_spdifFrequency1)
351#define HDSP_spdifFrequency48KHz (HDSP_spdifFrequency0|HDSP_spdifFrequency1)
352
353#define HDSP_spdifFrequency64KHz (HDSP_spdifFrequency2)
354#define HDSP_spdifFrequency88_2KHz (HDSP_spdifFrequency0|HDSP_spdifFrequency2)
355#define HDSP_spdifFrequency96KHz (HDSP_spdifFrequency2|HDSP_spdifFrequency1)
356
357/* This is for H9632 cards */
Remy Bruno47ba97f2008-02-22 17:57:02 +0100358#define HDSP_spdifFrequency128KHz (HDSP_spdifFrequency0|\
359 HDSP_spdifFrequency1|\
360 HDSP_spdifFrequency2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361#define HDSP_spdifFrequency176_4KHz HDSP_spdifFrequency3
362#define HDSP_spdifFrequency192KHz (HDSP_spdifFrequency3|HDSP_spdifFrequency0)
363
364/* Status2 Register bits */
365
366#define HDSP_version0 (1<<0)
367#define HDSP_version1 (1<<1)
368#define HDSP_version2 (1<<2)
369#define HDSP_wc_lock (1<<3)
370#define HDSP_wc_sync (1<<4)
371#define HDSP_inp_freq0 (1<<5)
372#define HDSP_inp_freq1 (1<<6)
373#define HDSP_inp_freq2 (1<<7)
374#define HDSP_SelSyncRef0 (1<<8)
375#define HDSP_SelSyncRef1 (1<<9)
376#define HDSP_SelSyncRef2 (1<<10)
377
378#define HDSP_wc_valid (HDSP_wc_lock|HDSP_wc_sync)
379
380#define HDSP_systemFrequencyMask (HDSP_inp_freq0|HDSP_inp_freq1|HDSP_inp_freq2)
381#define HDSP_systemFrequency32 (HDSP_inp_freq0)
382#define HDSP_systemFrequency44_1 (HDSP_inp_freq1)
383#define HDSP_systemFrequency48 (HDSP_inp_freq0|HDSP_inp_freq1)
384#define HDSP_systemFrequency64 (HDSP_inp_freq2)
385#define HDSP_systemFrequency88_2 (HDSP_inp_freq0|HDSP_inp_freq2)
386#define HDSP_systemFrequency96 (HDSP_inp_freq1|HDSP_inp_freq2)
387/* FIXME : more values for 9632 cards ? */
388
389#define HDSP_SelSyncRefMask (HDSP_SelSyncRef0|HDSP_SelSyncRef1|HDSP_SelSyncRef2)
390#define HDSP_SelSyncRef_ADAT1 0
391#define HDSP_SelSyncRef_ADAT2 (HDSP_SelSyncRef0)
392#define HDSP_SelSyncRef_ADAT3 (HDSP_SelSyncRef1)
393#define HDSP_SelSyncRef_SPDIF (HDSP_SelSyncRef0|HDSP_SelSyncRef1)
394#define HDSP_SelSyncRef_WORD (HDSP_SelSyncRef2)
395#define HDSP_SelSyncRef_ADAT_SYNC (HDSP_SelSyncRef0|HDSP_SelSyncRef2)
396
397/* Card state flags */
398
399#define HDSP_InitializationComplete (1<<0)
400#define HDSP_FirmwareLoaded (1<<1)
401#define HDSP_FirmwareCached (1<<2)
402
403/* FIFO wait times, defined in terms of 1/10ths of msecs */
404
405#define HDSP_LONG_WAIT 5000
406#define HDSP_SHORT_WAIT 30
407
408#define UNITY_GAIN 32768
409#define MINUS_INFINITY_GAIN 0
410
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411/* the size of a substream (1 mono data stream) */
412
413#define HDSP_CHANNEL_BUFFER_SAMPLES (16*1024)
414#define HDSP_CHANNEL_BUFFER_BYTES (4*HDSP_CHANNEL_BUFFER_SAMPLES)
415
416/* the size of the area we need to allocate for DMA transfers. the
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100417 size is the same regardless of the number of channels - the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 Multiface still uses the same memory area.
419
420 Note that we allocate 1 more channel than is apparently needed
421 because the h/w seems to write 1 byte beyond the end of the last
422 page. Sigh.
423*/
424
425#define HDSP_DMA_AREA_BYTES ((HDSP_MAX_CHANNELS+1) * HDSP_CHANNEL_BUFFER_BYTES)
426#define HDSP_DMA_AREA_KILOBYTES (HDSP_DMA_AREA_BYTES/1024)
427
Takashi Iwai90caaef2012-11-22 16:55:11 +0100428#define HDSP_FIRMWARE_SIZE (24413 * 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
Takashi Iwai55e957d2005-11-17 14:52:13 +0100430struct hdsp_9632_meters {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 u32 input_peak[16];
432 u32 playback_peak[16];
433 u32 output_peak[16];
434 u32 xxx_peak[16];
435 u32 padding[64];
436 u32 input_rms_low[16];
437 u32 playback_rms_low[16];
438 u32 output_rms_low[16];
439 u32 xxx_rms_low[16];
440 u32 input_rms_high[16];
441 u32 playback_rms_high[16];
442 u32 output_rms_high[16];
443 u32 xxx_rms_high[16];
444};
445
Takashi Iwai55e957d2005-11-17 14:52:13 +0100446struct hdsp_midi {
447 struct hdsp *hdsp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 int id;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100449 struct snd_rawmidi *rmidi;
450 struct snd_rawmidi_substream *input;
451 struct snd_rawmidi_substream *output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 char istimer; /* timer in use */
453 struct timer_list timer;
454 spinlock_t lock;
455 int pending;
456};
457
Takashi Iwai55e957d2005-11-17 14:52:13 +0100458struct hdsp {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 spinlock_t lock;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100460 struct snd_pcm_substream *capture_substream;
461 struct snd_pcm_substream *playback_substream;
462 struct hdsp_midi midi[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 struct tasklet_struct midi_tasklet;
464 int use_midi_tasklet;
465 int precise_ptr;
466 u32 control_register; /* cached value */
467 u32 control2_register; /* cached value */
468 u32 creg_spdif;
469 u32 creg_spdif_stream;
Takashi Iwaie3ea4d82005-07-04 18:12:39 +0200470 int clock_source_locked;
Florian Faber28b26e12010-12-01 12:14:47 +0100471 char *card_name; /* digiface/multiface/rpm */
Takashi Iwai55e957d2005-11-17 14:52:13 +0100472 enum HDSP_IO_Type io_type; /* ditto, but for code use */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 unsigned short firmware_rev;
474 unsigned short state; /* stores state bits */
Takashi Iwai90caaef2012-11-22 16:55:11 +0100475 const struct firmware *firmware;
476 u32 *fw_uploaded;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 size_t period_bytes; /* guess what this is */
478 unsigned char max_channels;
479 unsigned char qs_in_channels; /* quad speed mode for H9632 */
480 unsigned char ds_in_channels;
481 unsigned char ss_in_channels; /* different for multiface/digiface */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100482 unsigned char qs_out_channels;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 unsigned char ds_out_channels;
484 unsigned char ss_out_channels;
485
486 struct snd_dma_buffer capture_dma_buf;
487 struct snd_dma_buffer playback_dma_buf;
488 unsigned char *capture_buffer; /* suitably aligned address */
489 unsigned char *playback_buffer; /* suitably aligned address */
490
491 pid_t capture_pid;
492 pid_t playback_pid;
493 int running;
494 int system_sample_rate;
495 char *channel_map;
496 int dev;
497 int irq;
498 unsigned long port;
499 void __iomem *iobase;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100500 struct snd_card *card;
501 struct snd_pcm *pcm;
502 struct snd_hwdep *hwdep;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 struct pci_dev *pci;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100504 struct snd_kcontrol *spdif_ctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE];
Remy Brunod7923b22006-10-17 12:41:56 +0200506 unsigned int dds_value; /* last value written to freq register */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507};
508
509/* These tables map the ALSA channels 1..N to the channels that we
510 need to use in order to find the relevant channel buffer. RME
511 refer to this kind of mapping as between "the ADAT channel and
512 the DMA channel." We index it using the logical audio channel,
513 and the value is the DMA channel (i.e. channel buffer number)
514 where the data for that channel can be read/written from/to.
515*/
516
517static char channel_map_df_ss[HDSP_MAX_CHANNELS] = {
518 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
519 18, 19, 20, 21, 22, 23, 24, 25
520};
521
522static char channel_map_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */
523 /* Analog */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100524 0, 1, 2, 3, 4, 5, 6, 7,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 /* ADAT 2 */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100526 16, 17, 18, 19, 20, 21, 22, 23,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 /* SPDIF */
528 24, 25,
529 -1, -1, -1, -1, -1, -1, -1, -1
530};
531
532static char channel_map_ds[HDSP_MAX_CHANNELS] = {
533 /* ADAT channels are remapped */
534 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23,
535 /* channels 12 and 13 are S/PDIF */
536 24, 25,
537 /* others don't exist */
538 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
539};
540
541static char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = {
542 /* ADAT channels */
543 0, 1, 2, 3, 4, 5, 6, 7,
544 /* SPDIF */
545 8, 9,
546 /* Analog */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100547 10, 11,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 /* AO4S-192 and AI4S-192 extension boards */
549 12, 13, 14, 15,
550 /* others don't exist */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100551 -1, -1, -1, -1, -1, -1, -1, -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 -1, -1
553};
554
555static char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = {
556 /* ADAT */
557 1, 3, 5, 7,
558 /* SPDIF */
559 8, 9,
560 /* Analog */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100561 10, 11,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 /* AO4S-192 and AI4S-192 extension boards */
563 12, 13, 14, 15,
564 /* others don't exist */
565 -1, -1, -1, -1, -1, -1, -1, -1,
566 -1, -1, -1, -1, -1, -1
567};
568
569static char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = {
570 /* ADAT is disabled in this mode */
571 /* SPDIF */
572 8, 9,
573 /* Analog */
574 10, 11,
575 /* AO4S-192 and AI4S-192 extension boards */
576 12, 13, 14, 15,
577 /* others don't exist */
578 -1, -1, -1, -1, -1, -1, -1, -1,
579 -1, -1, -1, -1, -1, -1, -1, -1,
580 -1, -1
581};
582
583static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
584{
585 dmab->dev.type = SNDRV_DMA_TYPE_DEV;
586 dmab->dev.dev = snd_dma_pci_data(pci);
Takashi Iwaib6a96912005-05-30 18:27:03 +0200587 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
588 size, dmab) < 0)
589 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 return 0;
591}
592
593static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
594{
Takashi Iwai47d98c02014-01-08 16:12:25 +0100595 if (dmab->area)
596 snd_dma_free_pages(dmab);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597}
598
599
Alexey Dobriyancebe41d2010-02-06 00:21:03 +0200600static DEFINE_PCI_DEVICE_TABLE(snd_hdsp_ids) = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 {
602 .vendor = PCI_VENDOR_ID_XILINX,
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100603 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 .subvendor = PCI_ANY_ID,
605 .subdevice = PCI_ANY_ID,
606 }, /* RME Hammerfall-DSP */
607 { 0, },
608};
609
610MODULE_DEVICE_TABLE(pci, snd_hdsp_ids);
611
612/* prototypes */
Takashi Iwai55e957d2005-11-17 14:52:13 +0100613static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp);
614static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp);
615static int snd_hdsp_enable_io (struct hdsp *hdsp);
616static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp);
617static void snd_hdsp_initialize_channels (struct hdsp *hdsp);
618static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout);
619static int hdsp_autosync_ref(struct hdsp *hdsp);
620static int snd_hdsp_set_defaults(struct hdsp *hdsp);
621static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622
Takashi Iwai55e957d2005-11-17 14:52:13 +0100623static int hdsp_playback_to_output_key (struct hdsp *hdsp, int in, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624{
Remy Brunoa3a68c82007-08-31 12:33:54 +0200625 switch (hdsp->io_type) {
626 case Multiface:
627 case Digiface:
Florian Faber28b26e12010-12-01 12:14:47 +0100628 case RPM:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 default:
Andreas Degert192b8e32008-01-16 15:59:48 +0100630 if (hdsp->firmware_rev == 0xa)
631 return (64 * out) + (32 + (in));
632 else
633 return (52 * out) + (26 + (in));
Remy Brunoa3a68c82007-08-31 12:33:54 +0200634 case H9632:
635 return (32 * out) + (16 + (in));
636 case H9652:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 return (52 * out) + (26 + (in));
638 }
639}
640
Takashi Iwai55e957d2005-11-17 14:52:13 +0100641static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642{
Remy Brunoa3a68c82007-08-31 12:33:54 +0200643 switch (hdsp->io_type) {
644 case Multiface:
645 case Digiface:
Florian Faber28b26e12010-12-01 12:14:47 +0100646 case RPM:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 default:
Andreas Degert192b8e32008-01-16 15:59:48 +0100648 if (hdsp->firmware_rev == 0xa)
649 return (64 * out) + in;
650 else
651 return (52 * out) + in;
Remy Brunoa3a68c82007-08-31 12:33:54 +0200652 case H9632:
653 return (32 * out) + in;
654 case H9652:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 return (52 * out) + in;
656 }
657}
658
Takashi Iwai55e957d2005-11-17 14:52:13 +0100659static void hdsp_write(struct hdsp *hdsp, int reg, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660{
661 writel(val, hdsp->iobase + reg);
662}
663
Takashi Iwai55e957d2005-11-17 14:52:13 +0100664static unsigned int hdsp_read(struct hdsp *hdsp, int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665{
666 return readl (hdsp->iobase + reg);
667}
668
Takashi Iwai55e957d2005-11-17 14:52:13 +0100669static int hdsp_check_for_iobox (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670{
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100671 int i;
672
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100674 for (i = 0; i < 500; i++) {
675 if (0 == (hdsp_read(hdsp, HDSP_statusRegister) &
676 HDSP_ConfigError)) {
677 if (i) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100678 dev_dbg(hdsp->card->dev,
679 "IO box found after %d ms\n",
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100680 (20 * i));
681 }
682 return 0;
683 }
684 msleep(20);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 }
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100686 dev_err(hdsp->card->dev, "no IO box connected!\n");
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100687 hdsp->state &= ~HDSP_FirmwareLoaded;
688 return -EIO;
Tim Blechmanne588ed82009-02-20 19:30:35 +0100689}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690
Tim Blechmanne588ed82009-02-20 19:30:35 +0100691static int hdsp_wait_for_iobox(struct hdsp *hdsp, unsigned int loops,
692 unsigned int delay)
693{
694 unsigned int i;
695
696 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
697 return 0;
698
699 for (i = 0; i != loops; ++i) {
700 if (hdsp_read(hdsp, HDSP_statusRegister) & HDSP_ConfigError)
701 msleep(delay);
702 else {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100703 dev_dbg(hdsp->card->dev, "iobox found after %ums!\n",
Tim Blechmanne588ed82009-02-20 19:30:35 +0100704 i * delay);
705 return 0;
706 }
707 }
708
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100709 dev_info(hdsp->card->dev, "no IO box connected!\n");
Tim Blechmanne588ed82009-02-20 19:30:35 +0100710 hdsp->state &= ~HDSP_FirmwareLoaded;
711 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712}
713
Takashi Iwai55e957d2005-11-17 14:52:13 +0100714static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
716 int i;
717 unsigned long flags;
Takashi Iwai90caaef2012-11-22 16:55:11 +0100718 const u32 *cache;
719
720 if (hdsp->fw_uploaded)
721 cache = hdsp->fw_uploaded;
722 else {
723 if (!hdsp->firmware)
724 return -ENODEV;
725 cache = (u32 *)hdsp->firmware->data;
726 if (!cache)
727 return -ENODEV;
728 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
730 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100731
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100732 dev_info(hdsp->card->dev, "loading firmware\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733
734 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM);
735 hdsp_write (hdsp, HDSP_fifoData, 0);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100736
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100738 dev_info(hdsp->card->dev,
739 "timeout waiting for download preparation\n");
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100740 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 return -EIO;
742 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100743
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100745
Takashi Iwai90caaef2012-11-22 16:55:11 +0100746 for (i = 0; i < HDSP_FIRMWARE_SIZE / 4; ++i) {
747 hdsp_write(hdsp, HDSP_fifoData, cache[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100749 dev_info(hdsp->card->dev,
750 "timeout during firmware loading\n");
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100751 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 return -EIO;
753 }
754 }
755
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100756 hdsp_fifo_wait(hdsp, 3, HDSP_LONG_WAIT);
757 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200);
758
Takashi Iwaib0b98112005-10-20 18:29:58 +0200759 ssleep(3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760#ifdef SNDRV_BIG_ENDIAN
761 hdsp->control2_register = HDSP_BIGENDIAN_MODE;
762#else
763 hdsp->control2_register = 0;
764#endif
765 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100766 dev_info(hdsp->card->dev, "finished firmware loading\n");
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100767
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 }
769 if (hdsp->state & HDSP_InitializationComplete) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100770 dev_info(hdsp->card->dev,
771 "firmware loaded from cache, restoring defaults\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 spin_lock_irqsave(&hdsp->lock, flags);
773 snd_hdsp_set_defaults(hdsp);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100774 spin_unlock_irqrestore(&hdsp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100776
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 hdsp->state |= HDSP_FirmwareLoaded;
778
779 return 0;
780}
781
Takashi Iwai55e957d2005-11-17 14:52:13 +0100782static int hdsp_get_iobox_version (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783{
784 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100785
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100786 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD);
787 hdsp_write(hdsp, HDSP_fifoData, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100789 if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) {
790 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S300);
Florian Faber28b26e12010-12-01 12:14:47 +0100791 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100792 }
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100793
794 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200 | HDSP_PROGRAM);
795 hdsp_write (hdsp, HDSP_fifoData, 0);
796 if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) {
797 hdsp->io_type = Multiface;
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100798 dev_info(hdsp->card->dev, "Multiface found\n");
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100799 return 0;
800 }
801
802 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD);
803 hdsp_write(hdsp, HDSP_fifoData, 0);
804 if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) == 0) {
805 hdsp->io_type = Digiface;
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100806 dev_info(hdsp->card->dev, "Digiface found\n");
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100807 return 0;
808 }
809
810 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S300);
811 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD);
812 hdsp_write(hdsp, HDSP_fifoData, 0);
813 if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) == 0) {
814 hdsp->io_type = Multiface;
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100815 dev_info(hdsp->card->dev, "Multiface found\n");
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100816 return 0;
817 }
818
819 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S300);
820 hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD);
821 hdsp_write(hdsp, HDSP_fifoData, 0);
822 if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) {
823 hdsp->io_type = Multiface;
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100824 dev_info(hdsp->card->dev, "Multiface found\n");
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100825 return 0;
826 }
827
828 hdsp->io_type = RPM;
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100829 dev_info(hdsp->card->dev, "RPM found\n");
Adrian Knoth0c2bc7c2013-01-15 18:52:20 +0100830 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 } else {
832 /* firmware was already loaded, get iobox type */
Florian Faber28b26e12010-12-01 12:14:47 +0100833 if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version2)
834 hdsp->io_type = RPM;
835 else if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 hdsp->io_type = Multiface;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200837 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 hdsp->io_type = Digiface;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 }
840 return 0;
841}
842
843
Takashi Iwai92eed662008-02-22 18:35:56 +0100844static int hdsp_request_fw_loader(struct hdsp *hdsp);
Takashi Iwai311e70a2006-09-06 12:13:37 +0200845
846static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847{
Takashi Iwai311e70a2006-09-06 12:13:37 +0200848 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
849 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 hdsp->state &= ~HDSP_FirmwareLoaded;
Takashi Iwai311e70a2006-09-06 12:13:37 +0200852 if (! load_on_demand)
Takashi Iwaib0b98112005-10-20 18:29:58 +0200853 return -EIO;
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100854 dev_err(hdsp->card->dev, "firmware not present.\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +0200855 /* try to load firmware */
Takashi Iwai311e70a2006-09-06 12:13:37 +0200856 if (! (hdsp->state & HDSP_FirmwareCached)) {
Takashi Iwai311e70a2006-09-06 12:13:37 +0200857 if (! hdsp_request_fw_loader(hdsp))
858 return 0;
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100859 dev_err(hdsp->card->dev,
860 "No firmware loaded nor cached, please upload firmware.\n");
Takashi Iwai311e70a2006-09-06 12:13:37 +0200861 return -EIO;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200862 }
Takashi Iwai311e70a2006-09-06 12:13:37 +0200863 if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100864 dev_err(hdsp->card->dev,
865 "Firmware loading from cache failed, please upload manually.\n");
Takashi Iwai311e70a2006-09-06 12:13:37 +0200866 return -EIO;
867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 }
869 return 0;
870}
871
872
Takashi Iwai55e957d2005-11-17 14:52:13 +0100873static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout)
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100874{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 int i;
876
877 /* the fifoStatus registers reports on how many words
878 are available in the command FIFO.
879 */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100880
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 for (i = 0; i < timeout; i++) {
882
883 if ((int)(hdsp_read (hdsp, HDSP_fifoStatus) & 0xff) <= count)
884 return 0;
885
886 /* not very friendly, but we only do this during a firmware
887 load and changing the mixer, so we just put up with it.
888 */
889
890 udelay (100);
891 }
892
Takashi Iwaia54ba0f2014-02-26 12:05:11 +0100893 dev_warn(hdsp->card->dev,
894 "wait for FIFO status <= %d failed after %d iterations\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 count, timeout);
896 return -1;
897}
898
Takashi Iwai55e957d2005-11-17 14:52:13 +0100899static int hdsp_read_gain (struct hdsp *hdsp, unsigned int addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900{
Takashi Iwaib0b98112005-10-20 18:29:58 +0200901 if (addr >= HDSP_MATRIX_MIXER_SIZE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200903
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 return hdsp->mixer_matrix[addr];
905}
906
Takashi Iwai55e957d2005-11-17 14:52:13 +0100907static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908{
909 unsigned int ad;
910
911 if (addr >= HDSP_MATRIX_MIXER_SIZE)
912 return -1;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100913
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) {
915
916 /* from martin bjornsen:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100917
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 "You can only write dwords to the
919 mixer memory which contain two
920 mixer values in the low and high
921 word. So if you want to change
922 value 0 you have to read value 1
923 from the cache and write both to
924 the first dword in the mixer
925 memory."
926 */
927
Takashi Iwaib0b98112005-10-20 18:29:58 +0200928 if (hdsp->io_type == H9632 && addr >= 512)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930
Takashi Iwaib0b98112005-10-20 18:29:58 +0200931 if (hdsp->io_type == H9652 && addr >= 1352)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933
934 hdsp->mixer_matrix[addr] = data;
935
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100936
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 /* `addr' addresses a 16-bit wide address, but
938 the address space accessed via hdsp_write
939 uses byte offsets. put another way, addr
940 varies from 0 to 1351, but to access the
941 corresponding memory location, we need
942 to access 0 to 2703 ...
943 */
944 ad = addr/2;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100945
946 hdsp_write (hdsp, 4096 + (ad*4),
947 (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) +
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 hdsp->mixer_matrix[addr&0x7fe]);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100949
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 return 0;
951
952 } else {
953
954 ad = (addr << 16) + data;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100955
Takashi Iwaib0b98112005-10-20 18:29:58 +0200956 if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958
959 hdsp_write (hdsp, HDSP_fifoData, ad);
960 hdsp->mixer_matrix[addr] = data;
961
962 }
963
964 return 0;
965}
966
Takashi Iwai55e957d2005-11-17 14:52:13 +0100967static int snd_hdsp_use_is_exclusive(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968{
969 unsigned long flags;
970 int ret = 1;
971
972 spin_lock_irqsave(&hdsp->lock, flags);
973 if ((hdsp->playback_pid != hdsp->capture_pid) &&
Takashi Iwaib0b98112005-10-20 18:29:58 +0200974 (hdsp->playback_pid >= 0) && (hdsp->capture_pid >= 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 spin_unlock_irqrestore(&hdsp->lock, flags);
977 return ret;
978}
979
Takashi Iwai55e957d2005-11-17 14:52:13 +0100980static int hdsp_spdif_sample_rate(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981{
982 unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);
983 unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);
984
Remy Bruno47ba97f2008-02-22 17:57:02 +0100985 /* For the 9632, the mask is different */
986 if (hdsp->io_type == H9632)
987 rate_bits = (status & HDSP_spdifFrequencyMask_9632);
988
Takashi Iwaib0b98112005-10-20 18:29:58 +0200989 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 return 0;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100991
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 switch (rate_bits) {
993 case HDSP_spdifFrequency32KHz: return 32000;
994 case HDSP_spdifFrequency44_1KHz: return 44100;
995 case HDSP_spdifFrequency48KHz: return 48000;
996 case HDSP_spdifFrequency64KHz: return 64000;
997 case HDSP_spdifFrequency88_2KHz: return 88200;
998 case HDSP_spdifFrequency96KHz: return 96000;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +0100999 case HDSP_spdifFrequency128KHz:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 if (hdsp->io_type == H9632) return 128000;
1001 break;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001002 case HDSP_spdifFrequency176_4KHz:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 if (hdsp->io_type == H9632) return 176400;
1004 break;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001005 case HDSP_spdifFrequency192KHz:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 if (hdsp->io_type == H9632) return 192000;
1007 break;
1008 default:
1009 break;
1010 }
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01001011 dev_warn(hdsp->card->dev,
1012 "unknown spdif frequency status; bits = 0x%x, status = 0x%x\n",
1013 rate_bits, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 return 0;
1015}
1016
Remy Bruno47ba97f2008-02-22 17:57:02 +01001017static int hdsp_external_sample_rate(struct hdsp *hdsp)
1018{
1019 unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
1020 unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
1021
1022 /* For the 9632 card, there seems to be no bit for indicating external
1023 * sample rate greater than 96kHz. The card reports the corresponding
1024 * single speed. So the best means seems to get spdif rate when
1025 * autosync reference is spdif */
1026 if (hdsp->io_type == H9632 &&
1027 hdsp_autosync_ref(hdsp) == HDSP_AUTOSYNC_FROM_SPDIF)
1028 return hdsp_spdif_sample_rate(hdsp);
1029
1030 switch (rate_bits) {
1031 case HDSP_systemFrequency32: return 32000;
1032 case HDSP_systemFrequency44_1: return 44100;
1033 case HDSP_systemFrequency48: return 48000;
1034 case HDSP_systemFrequency64: return 64000;
1035 case HDSP_systemFrequency88_2: return 88200;
1036 case HDSP_systemFrequency96: return 96000;
1037 default:
1038 return 0;
1039 }
1040}
1041
Takashi Iwai55e957d2005-11-17 14:52:13 +01001042static void hdsp_compute_period_size(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043{
1044 hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));
1045}
1046
Takashi Iwai55e957d2005-11-17 14:52:13 +01001047static snd_pcm_uframes_t hdsp_hw_pointer(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048{
1049 int position;
1050
1051 position = hdsp_read(hdsp, HDSP_statusRegister);
1052
Takashi Iwaib0b98112005-10-20 18:29:58 +02001053 if (!hdsp->precise_ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 return (position & HDSP_BufferID) ? (hdsp->period_bytes / 4) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055
1056 position &= HDSP_BufferPositionMask;
1057 position /= 4;
1058 position &= (hdsp->period_bytes/2) - 1;
1059 return position;
1060}
1061
Takashi Iwai55e957d2005-11-17 14:52:13 +01001062static void hdsp_reset_hw_pointer(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063{
1064 hdsp_write (hdsp, HDSP_resetPointer, 0);
Remy Brunod7923b22006-10-17 12:41:56 +02001065 if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152)
1066 /* HDSP_resetPointer = HDSP_freqReg, which is strange and
1067 * requires (?) to write again DDS value after a reset pointer
1068 * (at least, it works like this) */
1069 hdsp_write (hdsp, HDSP_freqReg, hdsp->dds_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070}
1071
Takashi Iwai55e957d2005-11-17 14:52:13 +01001072static void hdsp_start_audio(struct hdsp *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073{
1074 s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start);
1075 hdsp_write(s, HDSP_controlRegister, s->control_register);
1076}
1077
Takashi Iwai55e957d2005-11-17 14:52:13 +01001078static void hdsp_stop_audio(struct hdsp *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079{
1080 s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable);
1081 hdsp_write(s, HDSP_controlRegister, s->control_register);
1082}
1083
Takashi Iwai55e957d2005-11-17 14:52:13 +01001084static void hdsp_silence_playback(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085{
1086 memset(hdsp->playback_buffer, 0, HDSP_DMA_AREA_BYTES);
1087}
1088
Takashi Iwai55e957d2005-11-17 14:52:13 +01001089static int hdsp_set_interrupt_interval(struct hdsp *s, unsigned int frames)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090{
1091 int n;
1092
1093 spin_lock_irq(&s->lock);
1094
1095 frames >>= 7;
1096 n = 0;
1097 while (frames) {
1098 n++;
1099 frames >>= 1;
1100 }
1101
1102 s->control_register &= ~HDSP_LatencyMask;
1103 s->control_register |= hdsp_encode_latency(n);
1104
1105 hdsp_write(s, HDSP_controlRegister, s->control_register);
1106
1107 hdsp_compute_period_size(s);
1108
1109 spin_unlock_irq(&s->lock);
1110
1111 return 0;
1112}
1113
Remy Brunod7923b22006-10-17 12:41:56 +02001114static void hdsp_set_dds_value(struct hdsp *hdsp, int rate)
1115{
1116 u64 n;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001117
Remy Brunod7923b22006-10-17 12:41:56 +02001118 if (rate >= 112000)
1119 rate /= 4;
1120 else if (rate >= 56000)
1121 rate /= 2;
1122
Julian Cablee4b60882007-03-19 11:44:40 +01001123 n = DDS_NUMERATOR;
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001124 n = div_u64(n, rate);
Remy Brunod7923b22006-10-17 12:41:56 +02001125 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001126 snd_BUG_ON(n >> 32);
Remy Brunod7923b22006-10-17 12:41:56 +02001127 /* HDSP_freqReg and HDSP_resetPointer are the same, so keep the DDS
1128 value to write it after a reset */
1129 hdsp->dds_value = n;
1130 hdsp_write(hdsp, HDSP_freqReg, hdsp->dds_value);
1131}
1132
Takashi Iwai55e957d2005-11-17 14:52:13 +01001133static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134{
1135 int reject_if_open = 0;
1136 int current_rate;
1137 int rate_bits;
1138
1139 /* ASSUMPTION: hdsp->lock is either held, or
1140 there is no need for it (e.g. during module
1141 initialization).
1142 */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001143
1144 if (!(hdsp->control_register & HDSP_ClockModeMaster)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 if (called_internally) {
1146 /* request from ctl or card initialization */
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01001147 dev_err(hdsp->card->dev,
1148 "device is not running as a clock master: cannot set sample rate.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 return -1;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001150 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 /* hw_param request while in AutoSync mode */
1152 int external_freq = hdsp_external_sample_rate(hdsp);
1153 int spdif_freq = hdsp_spdif_sample_rate(hdsp);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001154
Takashi Iwaib0b98112005-10-20 18:29:58 +02001155 if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1))
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01001156 dev_info(hdsp->card->dev,
1157 "Detected ADAT in double speed mode\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02001158 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 +01001159 dev_info(hdsp->card->dev,
1160 "Detected ADAT in quad speed mode\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02001161 else if (rate != external_freq) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01001162 dev_info(hdsp->card->dev,
1163 "No AutoSync source for requested rate\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 return -1;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001165 }
1166 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 }
1168
1169 current_rate = hdsp->system_sample_rate;
1170
1171 /* Changing from a "single speed" to a "double speed" rate is
1172 not allowed if any substreams are open. This is because
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001173 such a change causes a shift in the location of
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 the DMA buffers and a reduction in the number of available
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001175 buffers.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176
1177 Note that a similar but essentially insoluble problem
1178 exists for externally-driven rate changes. All we can do
1179 is to flag rate changes in the read/write routines. */
1180
Takashi Iwaib0b98112005-10-20 18:29:58 +02001181 if (rate > 96000 && hdsp->io_type != H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 return -EINVAL;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001183
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 switch (rate) {
1185 case 32000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001186 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 rate_bits = HDSP_Frequency32KHz;
1189 break;
1190 case 44100:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001191 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 rate_bits = HDSP_Frequency44_1KHz;
1194 break;
1195 case 48000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001196 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 rate_bits = HDSP_Frequency48KHz;
1199 break;
1200 case 64000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001201 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 rate_bits = HDSP_Frequency64KHz;
1204 break;
1205 case 88200:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001206 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 rate_bits = HDSP_Frequency88_2KHz;
1209 break;
1210 case 96000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001211 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 rate_bits = HDSP_Frequency96KHz;
1214 break;
1215 case 128000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001216 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 rate_bits = HDSP_Frequency128KHz;
1219 break;
1220 case 176400:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001221 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 rate_bits = HDSP_Frequency176_4KHz;
1224 break;
1225 case 192000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001226 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 rate_bits = HDSP_Frequency192KHz;
1229 break;
1230 default:
1231 return -EINVAL;
1232 }
1233
1234 if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01001235 dev_warn(hdsp->card->dev,
1236 "cannot change speed mode (capture PID = %d, playback PID = %d)\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 hdsp->capture_pid,
1238 hdsp->playback_pid);
1239 return -EBUSY;
1240 }
1241
1242 hdsp->control_register &= ~HDSP_FrequencyMask;
1243 hdsp->control_register |= rate_bits;
1244 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1245
Remy Brunod7923b22006-10-17 12:41:56 +02001246 /* For HDSP9632 rev 152, need to set DDS value in FREQ register */
1247 if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152)
1248 hdsp_set_dds_value(hdsp, rate);
1249
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 if (rate >= 128000) {
1251 hdsp->channel_map = channel_map_H9632_qs;
1252 } else if (rate > 48000) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001253 if (hdsp->io_type == H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 hdsp->channel_map = channel_map_H9632_ds;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001255 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 hdsp->channel_map = channel_map_ds;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 } else {
1258 switch (hdsp->io_type) {
Florian Faber28b26e12010-12-01 12:14:47 +01001259 case RPM:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 case Multiface:
1261 hdsp->channel_map = channel_map_mf_ss;
1262 break;
1263 case Digiface:
1264 case H9652:
1265 hdsp->channel_map = channel_map_df_ss;
1266 break;
1267 case H9632:
1268 hdsp->channel_map = channel_map_H9632_ss;
1269 break;
1270 default:
1271 /* should never happen */
1272 break;
1273 }
1274 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001275
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 hdsp->system_sample_rate = rate;
1277
1278 return 0;
1279}
1280
1281/*----------------------------------------------------------------------------
1282 MIDI
1283 ----------------------------------------------------------------------------*/
1284
Takashi Iwai55e957d2005-11-17 14:52:13 +01001285static unsigned char snd_hdsp_midi_read_byte (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286{
1287 /* the hardware already does the relevant bit-mask with 0xff */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001288 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 return hdsp_read(hdsp, HDSP_midiDataIn1);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001290 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 return hdsp_read(hdsp, HDSP_midiDataIn0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292}
1293
Takashi Iwai55e957d2005-11-17 14:52:13 +01001294static void snd_hdsp_midi_write_byte (struct hdsp *hdsp, int id, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295{
1296 /* the hardware already does the relevant bit-mask with 0xff */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001297 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 hdsp_write(hdsp, HDSP_midiDataOut1, val);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001299 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 hdsp_write(hdsp, HDSP_midiDataOut0, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301}
1302
Takashi Iwai55e957d2005-11-17 14:52:13 +01001303static int snd_hdsp_midi_input_available (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001305 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 return (hdsp_read(hdsp, HDSP_midiStatusIn1) & 0xff);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001307 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 return (hdsp_read(hdsp, HDSP_midiStatusIn0) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309}
1310
Takashi Iwai55e957d2005-11-17 14:52:13 +01001311static int snd_hdsp_midi_output_possible (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312{
1313 int fifo_bytes_used;
1314
Takashi Iwaib0b98112005-10-20 18:29:58 +02001315 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut1) & 0xff;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001317 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut0) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319
Takashi Iwaib0b98112005-10-20 18:29:58 +02001320 if (fifo_bytes_used < 128)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 return 128 - fifo_bytes_used;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001322 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324}
1325
Takashi Iwai55e957d2005-11-17 14:52:13 +01001326static void snd_hdsp_flush_midi_input (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001328 while (snd_hdsp_midi_input_available (hdsp, id))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 snd_hdsp_midi_read_byte (hdsp, id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330}
1331
Takashi Iwai55e957d2005-11-17 14:52:13 +01001332static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333{
1334 unsigned long flags;
1335 int n_pending;
1336 int to_write;
1337 int i;
1338 unsigned char buf[128];
1339
1340 /* Output is not interrupt driven */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001341
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 spin_lock_irqsave (&hmidi->lock, flags);
1343 if (hmidi->output) {
1344 if (!snd_rawmidi_transmit_empty (hmidi->output)) {
1345 if ((n_pending = snd_hdsp_midi_output_possible (hmidi->hdsp, hmidi->id)) > 0) {
1346 if (n_pending > (int)sizeof (buf))
1347 n_pending = sizeof (buf);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001348
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001350 for (i = 0; i < to_write; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 snd_hdsp_midi_write_byte (hmidi->hdsp, hmidi->id, buf[i]);
1352 }
1353 }
1354 }
1355 }
1356 spin_unlock_irqrestore (&hmidi->lock, flags);
1357 return 0;
1358}
1359
Takashi Iwai55e957d2005-11-17 14:52:13 +01001360static int snd_hdsp_midi_input_read (struct hdsp_midi *hmidi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361{
1362 unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
1363 unsigned long flags;
1364 int n_pending;
1365 int i;
1366
1367 spin_lock_irqsave (&hmidi->lock, flags);
1368 if ((n_pending = snd_hdsp_midi_input_available (hmidi->hdsp, hmidi->id)) > 0) {
1369 if (hmidi->input) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001370 if (n_pending > (int)sizeof (buf))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 n_pending = sizeof (buf);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001372 for (i = 0; i < n_pending; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 buf[i] = snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001374 if (n_pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 snd_rawmidi_receive (hmidi->input, buf, n_pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 } else {
1377 /* flush the MIDI input FIFO */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001378 while (--n_pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 }
1381 }
1382 hmidi->pending = 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001383 if (hmidi->id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 hmidi->hdsp->control_register |= HDSP_Midi1InterruptEnable;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001385 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 hmidi->hdsp->control_register |= HDSP_Midi0InterruptEnable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 hdsp_write(hmidi->hdsp, HDSP_controlRegister, hmidi->hdsp->control_register);
1388 spin_unlock_irqrestore (&hmidi->lock, flags);
1389 return snd_hdsp_midi_output_write (hmidi);
1390}
1391
Takashi Iwai55e957d2005-11-17 14:52:13 +01001392static void snd_hdsp_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001394 struct hdsp *hdsp;
1395 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 unsigned long flags;
1397 u32 ie;
1398
Takashi Iwai55e957d2005-11-17 14:52:13 +01001399 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 hdsp = hmidi->hdsp;
1401 ie = hmidi->id ? HDSP_Midi1InterruptEnable : HDSP_Midi0InterruptEnable;
1402 spin_lock_irqsave (&hdsp->lock, flags);
1403 if (up) {
1404 if (!(hdsp->control_register & ie)) {
1405 snd_hdsp_flush_midi_input (hdsp, hmidi->id);
1406 hdsp->control_register |= ie;
1407 }
1408 } else {
1409 hdsp->control_register &= ~ie;
1410 tasklet_kill(&hdsp->midi_tasklet);
1411 }
1412
1413 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1414 spin_unlock_irqrestore (&hdsp->lock, flags);
1415}
1416
1417static void snd_hdsp_midi_output_timer(unsigned long data)
1418{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001419 struct hdsp_midi *hmidi = (struct hdsp_midi *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 unsigned long flags;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001421
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 snd_hdsp_midi_output_write(hmidi);
1423 spin_lock_irqsave (&hmidi->lock, flags);
1424
1425 /* this does not bump hmidi->istimer, because the
1426 kernel automatically removed the timer when it
1427 expired, and we are now adding it back, thus
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001428 leaving istimer wherever it was set before.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 */
1430
1431 if (hmidi->istimer) {
1432 hmidi->timer.expires = 1 + jiffies;
1433 add_timer(&hmidi->timer);
1434 }
1435
1436 spin_unlock_irqrestore (&hmidi->lock, flags);
1437}
1438
Takashi Iwai55e957d2005-11-17 14:52:13 +01001439static void snd_hdsp_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001441 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 unsigned long flags;
1443
Takashi Iwai55e957d2005-11-17 14:52:13 +01001444 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 spin_lock_irqsave (&hmidi->lock, flags);
1446 if (up) {
1447 if (!hmidi->istimer) {
1448 init_timer(&hmidi->timer);
1449 hmidi->timer.function = snd_hdsp_midi_output_timer;
1450 hmidi->timer.data = (unsigned long) hmidi;
1451 hmidi->timer.expires = 1 + jiffies;
1452 add_timer(&hmidi->timer);
1453 hmidi->istimer++;
1454 }
1455 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001456 if (hmidi->istimer && --hmidi->istimer <= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 del_timer (&hmidi->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 }
1459 spin_unlock_irqrestore (&hmidi->lock, flags);
1460 if (up)
1461 snd_hdsp_midi_output_write(hmidi);
1462}
1463
Takashi Iwai55e957d2005-11-17 14:52:13 +01001464static int snd_hdsp_midi_input_open(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001466 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
Takashi Iwai55e957d2005-11-17 14:52:13 +01001468 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 spin_lock_irq (&hmidi->lock);
1470 snd_hdsp_flush_midi_input (hmidi->hdsp, hmidi->id);
1471 hmidi->input = substream;
1472 spin_unlock_irq (&hmidi->lock);
1473
1474 return 0;
1475}
1476
Takashi Iwai55e957d2005-11-17 14:52:13 +01001477static int snd_hdsp_midi_output_open(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001479 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480
Takashi Iwai55e957d2005-11-17 14:52:13 +01001481 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 spin_lock_irq (&hmidi->lock);
1483 hmidi->output = substream;
1484 spin_unlock_irq (&hmidi->lock);
1485
1486 return 0;
1487}
1488
Takashi Iwai55e957d2005-11-17 14:52:13 +01001489static int snd_hdsp_midi_input_close(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001491 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492
1493 snd_hdsp_midi_input_trigger (substream, 0);
1494
Takashi Iwai55e957d2005-11-17 14:52:13 +01001495 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 spin_lock_irq (&hmidi->lock);
1497 hmidi->input = NULL;
1498 spin_unlock_irq (&hmidi->lock);
1499
1500 return 0;
1501}
1502
Takashi Iwai55e957d2005-11-17 14:52:13 +01001503static int snd_hdsp_midi_output_close(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001505 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506
1507 snd_hdsp_midi_output_trigger (substream, 0);
1508
Takashi Iwai55e957d2005-11-17 14:52:13 +01001509 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 spin_lock_irq (&hmidi->lock);
1511 hmidi->output = NULL;
1512 spin_unlock_irq (&hmidi->lock);
1513
1514 return 0;
1515}
1516
Takashi Iwai55e957d2005-11-17 14:52:13 +01001517static struct snd_rawmidi_ops snd_hdsp_midi_output =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518{
1519 .open = snd_hdsp_midi_output_open,
1520 .close = snd_hdsp_midi_output_close,
1521 .trigger = snd_hdsp_midi_output_trigger,
1522};
1523
Takashi Iwai55e957d2005-11-17 14:52:13 +01001524static struct snd_rawmidi_ops snd_hdsp_midi_input =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525{
1526 .open = snd_hdsp_midi_input_open,
1527 .close = snd_hdsp_midi_input_close,
1528 .trigger = snd_hdsp_midi_input_trigger,
1529};
1530
Takashi Iwaif40b6892006-07-05 16:51:05 +02001531static int snd_hdsp_create_midi (struct snd_card *card, struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532{
1533 char buf[32];
1534
1535 hdsp->midi[id].id = id;
1536 hdsp->midi[id].rmidi = NULL;
1537 hdsp->midi[id].input = NULL;
1538 hdsp->midi[id].output = NULL;
1539 hdsp->midi[id].hdsp = hdsp;
1540 hdsp->midi[id].istimer = 0;
1541 hdsp->midi[id].pending = 0;
1542 spin_lock_init (&hdsp->midi[id].lock);
1543
1544 sprintf (buf, "%s MIDI %d", card->shortname, id+1);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001545 if (snd_rawmidi_new (card, buf, id, 1, 1, &hdsp->midi[id].rmidi) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547
Jaroslav Kysela972d4c52008-11-12 16:37:48 +01001548 sprintf(hdsp->midi[id].rmidi->name, "HDSP MIDI %d", id+1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 hdsp->midi[id].rmidi->private_data = &hdsp->midi[id];
1550
1551 snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdsp_midi_output);
1552 snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdsp_midi_input);
1553
1554 hdsp->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
1555 SNDRV_RAWMIDI_INFO_INPUT |
1556 SNDRV_RAWMIDI_INFO_DUPLEX;
1557
1558 return 0;
1559}
1560
1561/*-----------------------------------------------------------------------------
1562 Control Interface
1563 ----------------------------------------------------------------------------*/
1564
Takashi Iwai55e957d2005-11-17 14:52:13 +01001565static u32 snd_hdsp_convert_from_aes(struct snd_aes_iec958 *aes)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566{
1567 u32 val = 0;
1568 val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? HDSP_SPDIFProfessional : 0;
1569 val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? HDSP_SPDIFNonAudio : 0;
1570 if (val & HDSP_SPDIFProfessional)
1571 val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0;
1572 else
1573 val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0;
1574 return val;
1575}
1576
Takashi Iwai55e957d2005-11-17 14:52:13 +01001577static void snd_hdsp_convert_to_aes(struct snd_aes_iec958 *aes, u32 val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578{
1579 aes->status[0] = ((val & HDSP_SPDIFProfessional) ? IEC958_AES0_PROFESSIONAL : 0) |
1580 ((val & HDSP_SPDIFNonAudio) ? IEC958_AES0_NONAUDIO : 0);
1581 if (val & HDSP_SPDIFProfessional)
1582 aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0;
1583 else
1584 aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_CON_EMPHASIS_5015 : 0;
1585}
1586
Takashi Iwai55e957d2005-11-17 14:52:13 +01001587static int snd_hdsp_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588{
1589 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1590 uinfo->count = 1;
1591 return 0;
1592}
1593
Takashi Iwai55e957d2005-11-17 14:52:13 +01001594static int snd_hdsp_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001596 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001597
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif);
1599 return 0;
1600}
1601
Takashi Iwai55e957d2005-11-17 14:52:13 +01001602static int snd_hdsp_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001604 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 int change;
1606 u32 val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001607
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
1609 spin_lock_irq(&hdsp->lock);
1610 change = val != hdsp->creg_spdif;
1611 hdsp->creg_spdif = val;
1612 spin_unlock_irq(&hdsp->lock);
1613 return change;
1614}
1615
Takashi Iwai55e957d2005-11-17 14:52:13 +01001616static int snd_hdsp_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617{
1618 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1619 uinfo->count = 1;
1620 return 0;
1621}
1622
Takashi Iwai55e957d2005-11-17 14:52:13 +01001623static int snd_hdsp_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001625 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001626
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream);
1628 return 0;
1629}
1630
Takashi Iwai55e957d2005-11-17 14:52:13 +01001631static int snd_hdsp_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001633 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 int change;
1635 u32 val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001636
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
1638 spin_lock_irq(&hdsp->lock);
1639 change = val != hdsp->creg_spdif_stream;
1640 hdsp->creg_spdif_stream = val;
1641 hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
1642 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= val);
1643 spin_unlock_irq(&hdsp->lock);
1644 return change;
1645}
1646
Takashi Iwai55e957d2005-11-17 14:52:13 +01001647static int snd_hdsp_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648{
1649 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1650 uinfo->count = 1;
1651 return 0;
1652}
1653
Takashi Iwai55e957d2005-11-17 14:52:13 +01001654static int snd_hdsp_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655{
1656 ucontrol->value.iec958.status[0] = kcontrol->private_value;
1657 return 0;
1658}
1659
1660#define HDSP_SPDIF_IN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001661{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 .name = xname, \
1663 .index = xindex, \
1664 .info = snd_hdsp_info_spdif_in, \
1665 .get = snd_hdsp_get_spdif_in, \
1666 .put = snd_hdsp_put_spdif_in }
1667
Takashi Iwai55e957d2005-11-17 14:52:13 +01001668static unsigned int hdsp_spdif_in(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669{
1670 return hdsp_decode_spdif_in(hdsp->control_register & HDSP_SPDIFInputMask);
1671}
1672
Takashi Iwai55e957d2005-11-17 14:52:13 +01001673static int hdsp_set_spdif_input(struct hdsp *hdsp, int in)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674{
1675 hdsp->control_register &= ~HDSP_SPDIFInputMask;
1676 hdsp->control_register |= hdsp_encode_spdif_in(in);
1677 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1678 return 0;
1679}
1680
Takashi Iwai55e957d2005-11-17 14:52:13 +01001681static int snd_hdsp_info_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682{
1683 static char *texts[4] = {"Optical", "Coaxial", "Internal", "AES"};
Takashi Iwai55e957d2005-11-17 14:52:13 +01001684 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685
1686 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1687 uinfo->count = 1;
1688 uinfo->value.enumerated.items = ((hdsp->io_type == H9632) ? 4 : 3);
1689 if (uinfo->value.enumerated.item > ((hdsp->io_type == H9632) ? 3 : 2))
1690 uinfo->value.enumerated.item = ((hdsp->io_type == H9632) ? 3 : 2);
1691 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1692 return 0;
1693}
1694
Takashi Iwai55e957d2005-11-17 14:52:13 +01001695static int snd_hdsp_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001697 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001698
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp);
1700 return 0;
1701}
1702
Takashi Iwai55e957d2005-11-17 14:52:13 +01001703static int snd_hdsp_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001705 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 int change;
1707 unsigned int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001708
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 if (!snd_hdsp_use_is_exclusive(hdsp))
1710 return -EBUSY;
1711 val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3);
1712 spin_lock_irq(&hdsp->lock);
1713 change = val != hdsp_spdif_in(hdsp);
1714 if (change)
1715 hdsp_set_spdif_input(hdsp, val);
1716 spin_unlock_irq(&hdsp->lock);
1717 return change;
1718}
1719
Adrian Knoth66d92442013-01-15 18:52:21 +01001720#define HDSP_TOGGLE_SETTING(xname, xindex) \
1721{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1722 .name = xname, \
1723 .private_value = xindex, \
1724 .info = snd_hdsp_info_toggle_setting, \
1725 .get = snd_hdsp_get_toggle_setting, \
1726 .put = snd_hdsp_put_toggle_setting \
1727}
1728
1729static int hdsp_toggle_setting(struct hdsp *hdsp, u32 regmask)
1730{
1731 return (hdsp->control_register & regmask) ? 1 : 0;
1732}
1733
1734static int hdsp_set_toggle_setting(struct hdsp *hdsp, u32 regmask, int out)
1735{
1736 if (out)
1737 hdsp->control_register |= regmask;
1738 else
1739 hdsp->control_register &= ~regmask;
1740 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1741
1742 return 0;
1743}
1744
1745#define snd_hdsp_info_toggle_setting snd_ctl_boolean_mono_info
1746
1747static int snd_hdsp_get_toggle_setting(struct snd_kcontrol *kcontrol,
1748 struct snd_ctl_elem_value *ucontrol)
1749{
1750 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
1751 u32 regmask = kcontrol->private_value;
1752
1753 spin_lock_irq(&hdsp->lock);
1754 ucontrol->value.integer.value[0] = hdsp_toggle_setting(hdsp, regmask);
1755 spin_unlock_irq(&hdsp->lock);
1756 return 0;
1757}
1758
1759static int snd_hdsp_put_toggle_setting(struct snd_kcontrol *kcontrol,
1760 struct snd_ctl_elem_value *ucontrol)
1761{
1762 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
1763 u32 regmask = kcontrol->private_value;
1764 int change;
1765 unsigned int val;
1766
1767 if (!snd_hdsp_use_is_exclusive(hdsp))
1768 return -EBUSY;
1769 val = ucontrol->value.integer.value[0] & 1;
1770 spin_lock_irq(&hdsp->lock);
1771 change = (int) val != hdsp_toggle_setting(hdsp, regmask);
1772 if (change)
1773 hdsp_set_toggle_setting(hdsp, regmask, val);
1774 spin_unlock_irq(&hdsp->lock);
1775 return change;
1776}
1777
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778#define HDSP_SPDIF_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001779{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 .name = xname, \
1781 .index = xindex, \
1782 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1783 .info = snd_hdsp_info_spdif_sample_rate, \
1784 .get = snd_hdsp_get_spdif_sample_rate \
1785}
1786
Takashi Iwai55e957d2005-11-17 14:52:13 +01001787static int snd_hdsp_info_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788{
1789 static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
Takashi Iwai55e957d2005-11-17 14:52:13 +01001790 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791
1792 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1793 uinfo->count = 1;
1794 uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7;
1795 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1796 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1797 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1798 return 0;
1799}
1800
Takashi Iwai55e957d2005-11-17 14:52:13 +01001801static int snd_hdsp_get_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001803 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001804
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 switch (hdsp_spdif_sample_rate(hdsp)) {
1806 case 32000:
1807 ucontrol->value.enumerated.item[0] = 0;
1808 break;
1809 case 44100:
1810 ucontrol->value.enumerated.item[0] = 1;
1811 break;
1812 case 48000:
1813 ucontrol->value.enumerated.item[0] = 2;
1814 break;
1815 case 64000:
1816 ucontrol->value.enumerated.item[0] = 3;
1817 break;
1818 case 88200:
1819 ucontrol->value.enumerated.item[0] = 4;
1820 break;
1821 case 96000:
1822 ucontrol->value.enumerated.item[0] = 5;
1823 break;
1824 case 128000:
1825 ucontrol->value.enumerated.item[0] = 7;
1826 break;
1827 case 176400:
1828 ucontrol->value.enumerated.item[0] = 8;
1829 break;
1830 case 192000:
1831 ucontrol->value.enumerated.item[0] = 9;
1832 break;
1833 default:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001834 ucontrol->value.enumerated.item[0] = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 }
1836 return 0;
1837}
1838
1839#define HDSP_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001840{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 .name = xname, \
1842 .index = xindex, \
1843 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1844 .info = snd_hdsp_info_system_sample_rate, \
1845 .get = snd_hdsp_get_system_sample_rate \
1846}
1847
Takashi Iwai55e957d2005-11-17 14:52:13 +01001848static int snd_hdsp_info_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849{
1850 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1851 uinfo->count = 1;
1852 return 0;
1853}
1854
Takashi Iwai55e957d2005-11-17 14:52:13 +01001855static int snd_hdsp_get_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001857 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001858
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate;
1860 return 0;
1861}
1862
1863#define HDSP_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001864{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 .name = xname, \
1866 .index = xindex, \
1867 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1868 .info = snd_hdsp_info_autosync_sample_rate, \
1869 .get = snd_hdsp_get_autosync_sample_rate \
1870}
1871
Takashi Iwai55e957d2005-11-17 14:52:13 +01001872static int snd_hdsp_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001874 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001875 static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1877 uinfo->count = 1;
1878 uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7 ;
1879 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1880 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1881 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1882 return 0;
1883}
1884
Takashi Iwai55e957d2005-11-17 14:52:13 +01001885static int snd_hdsp_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001887 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001888
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889 switch (hdsp_external_sample_rate(hdsp)) {
1890 case 32000:
1891 ucontrol->value.enumerated.item[0] = 0;
1892 break;
1893 case 44100:
1894 ucontrol->value.enumerated.item[0] = 1;
1895 break;
1896 case 48000:
1897 ucontrol->value.enumerated.item[0] = 2;
1898 break;
1899 case 64000:
1900 ucontrol->value.enumerated.item[0] = 3;
1901 break;
1902 case 88200:
1903 ucontrol->value.enumerated.item[0] = 4;
1904 break;
1905 case 96000:
1906 ucontrol->value.enumerated.item[0] = 5;
1907 break;
1908 case 128000:
1909 ucontrol->value.enumerated.item[0] = 7;
1910 break;
1911 case 176400:
1912 ucontrol->value.enumerated.item[0] = 8;
1913 break;
1914 case 192000:
1915 ucontrol->value.enumerated.item[0] = 9;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001916 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 default:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001918 ucontrol->value.enumerated.item[0] = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 }
1920 return 0;
1921}
1922
1923#define HDSP_SYSTEM_CLOCK_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001924{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 .name = xname, \
1926 .index = xindex, \
1927 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1928 .info = snd_hdsp_info_system_clock_mode, \
1929 .get = snd_hdsp_get_system_clock_mode \
1930}
1931
Takashi Iwai55e957d2005-11-17 14:52:13 +01001932static int hdsp_system_clock_mode(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001934 if (hdsp->control_register & HDSP_ClockModeMaster)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001936 else if (hdsp_external_sample_rate(hdsp) != hdsp->system_sample_rate)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 return 1;
1939}
1940
Takashi Iwai55e957d2005-11-17 14:52:13 +01001941static int snd_hdsp_info_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942{
1943 static char *texts[] = {"Master", "Slave" };
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001944
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1946 uinfo->count = 1;
1947 uinfo->value.enumerated.items = 2;
1948 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1949 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1950 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1951 return 0;
1952}
1953
Takashi Iwai55e957d2005-11-17 14:52:13 +01001954static int snd_hdsp_get_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001956 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001957
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp);
1959 return 0;
1960}
1961
1962#define HDSP_CLOCK_SOURCE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001963{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 .name = xname, \
1965 .index = xindex, \
1966 .info = snd_hdsp_info_clock_source, \
1967 .get = snd_hdsp_get_clock_source, \
1968 .put = snd_hdsp_put_clock_source \
1969}
1970
Takashi Iwai55e957d2005-11-17 14:52:13 +01001971static int hdsp_clock_source(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972{
1973 if (hdsp->control_register & HDSP_ClockModeMaster) {
1974 switch (hdsp->system_sample_rate) {
1975 case 32000:
1976 return 1;
1977 case 44100:
1978 return 2;
1979 case 48000:
1980 return 3;
1981 case 64000:
1982 return 4;
1983 case 88200:
1984 return 5;
1985 case 96000:
1986 return 6;
1987 case 128000:
1988 return 7;
1989 case 176400:
1990 return 8;
1991 case 192000:
1992 return 9;
1993 default:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01001994 return 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995 }
1996 } else {
1997 return 0;
1998 }
1999}
2000
Takashi Iwai55e957d2005-11-17 14:52:13 +01002001static int hdsp_set_clock_source(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002{
2003 int rate;
2004 switch (mode) {
2005 case HDSP_CLOCK_SOURCE_AUTOSYNC:
2006 if (hdsp_external_sample_rate(hdsp) != 0) {
2007 if (!hdsp_set_rate(hdsp, hdsp_external_sample_rate(hdsp), 1)) {
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002008 hdsp->control_register &= ~HDSP_ClockModeMaster;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2010 return 0;
2011 }
2012 }
2013 return -1;
2014 case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ:
2015 rate = 32000;
2016 break;
2017 case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ:
2018 rate = 44100;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002019 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ:
2021 rate = 48000;
2022 break;
2023 case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ:
2024 rate = 64000;
2025 break;
2026 case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ:
2027 rate = 88200;
2028 break;
2029 case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ:
2030 rate = 96000;
2031 break;
2032 case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ:
2033 rate = 128000;
2034 break;
2035 case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ:
2036 rate = 176400;
2037 break;
2038 case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ:
2039 rate = 192000;
2040 break;
2041 default:
2042 rate = 48000;
2043 }
2044 hdsp->control_register |= HDSP_ClockModeMaster;
2045 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2046 hdsp_set_rate(hdsp, rate, 1);
2047 return 0;
2048}
2049
Takashi Iwai55e957d2005-11-17 14:52:13 +01002050static int snd_hdsp_info_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051{
2052 static char *texts[] = {"AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz", "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz", "Internal 96.0 kHz", "Internal 128 kHz", "Internal 176.4 kHz", "Internal 192.0 KHz" };
Takashi Iwai55e957d2005-11-17 14:52:13 +01002053 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002054
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2056 uinfo->count = 1;
2057 if (hdsp->io_type == H9632)
2058 uinfo->value.enumerated.items = 10;
2059 else
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002060 uinfo->value.enumerated.items = 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2062 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2063 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2064 return 0;
2065}
2066
Takashi Iwai55e957d2005-11-17 14:52:13 +01002067static int snd_hdsp_get_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002069 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002070
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp);
2072 return 0;
2073}
2074
Takashi Iwai55e957d2005-11-17 14:52:13 +01002075static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002077 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 int change;
2079 int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002080
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 if (!snd_hdsp_use_is_exclusive(hdsp))
2082 return -EBUSY;
2083 val = ucontrol->value.enumerated.item[0];
2084 if (val < 0) val = 0;
2085 if (hdsp->io_type == H9632) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002086 if (val > 9)
2087 val = 9;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002089 if (val > 6)
2090 val = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 }
2092 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002093 if (val != hdsp_clock_source(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 change = (hdsp_set_clock_source(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002095 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097 spin_unlock_irq(&hdsp->lock);
2098 return change;
2099}
2100
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002101#define snd_hdsp_info_clock_source_lock snd_ctl_boolean_mono_info
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002102
Takashi Iwai55e957d2005-11-17 14:52:13 +01002103static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002104{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002105 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002106
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002107 ucontrol->value.integer.value[0] = hdsp->clock_source_locked;
2108 return 0;
2109}
2110
Takashi Iwai55e957d2005-11-17 14:52:13 +01002111static int snd_hdsp_put_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002112{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002113 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002114 int change;
2115
2116 change = (int)ucontrol->value.integer.value[0] != hdsp->clock_source_locked;
2117 if (change)
Takashi Iwai4e98d6a2007-11-15 15:58:13 +01002118 hdsp->clock_source_locked = !!ucontrol->value.integer.value[0];
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002119 return change;
2120}
2121
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122#define HDSP_DA_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002123{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 .name = xname, \
2125 .index = xindex, \
2126 .info = snd_hdsp_info_da_gain, \
2127 .get = snd_hdsp_get_da_gain, \
2128 .put = snd_hdsp_put_da_gain \
2129}
2130
Takashi Iwai55e957d2005-11-17 14:52:13 +01002131static int hdsp_da_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132{
2133 switch (hdsp->control_register & HDSP_DAGainMask) {
2134 case HDSP_DAGainHighGain:
2135 return 0;
2136 case HDSP_DAGainPlus4dBu:
2137 return 1;
2138 case HDSP_DAGainMinus10dBV:
2139 return 2;
2140 default:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002141 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 }
2143}
2144
Takashi Iwai55e957d2005-11-17 14:52:13 +01002145static int hdsp_set_da_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146{
2147 hdsp->control_register &= ~HDSP_DAGainMask;
2148 switch (mode) {
2149 case 0:
2150 hdsp->control_register |= HDSP_DAGainHighGain;
2151 break;
2152 case 1:
2153 hdsp->control_register |= HDSP_DAGainPlus4dBu;
2154 break;
2155 case 2:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002156 hdsp->control_register |= HDSP_DAGainMinus10dBV;
2157 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 default:
2159 return -1;
2160
2161 }
2162 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2163 return 0;
2164}
2165
Takashi Iwai55e957d2005-11-17 14:52:13 +01002166static int snd_hdsp_info_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167{
2168 static char *texts[] = {"Hi Gain", "+4 dBu", "-10 dbV"};
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002169
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2171 uinfo->count = 1;
2172 uinfo->value.enumerated.items = 3;
2173 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2174 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2175 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2176 return 0;
2177}
2178
Takashi Iwai55e957d2005-11-17 14:52:13 +01002179static int snd_hdsp_get_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002181 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002182
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp);
2184 return 0;
2185}
2186
Takashi Iwai55e957d2005-11-17 14:52:13 +01002187static int snd_hdsp_put_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002189 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 int change;
2191 int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002192
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 if (!snd_hdsp_use_is_exclusive(hdsp))
2194 return -EBUSY;
2195 val = ucontrol->value.enumerated.item[0];
2196 if (val < 0) val = 0;
2197 if (val > 2) val = 2;
2198 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002199 if (val != hdsp_da_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 change = (hdsp_set_da_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002201 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 spin_unlock_irq(&hdsp->lock);
2204 return change;
2205}
2206
2207#define HDSP_AD_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002208{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 .name = xname, \
2210 .index = xindex, \
2211 .info = snd_hdsp_info_ad_gain, \
2212 .get = snd_hdsp_get_ad_gain, \
2213 .put = snd_hdsp_put_ad_gain \
2214}
2215
Takashi Iwai55e957d2005-11-17 14:52:13 +01002216static int hdsp_ad_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217{
2218 switch (hdsp->control_register & HDSP_ADGainMask) {
2219 case HDSP_ADGainMinus10dBV:
2220 return 0;
2221 case HDSP_ADGainPlus4dBu:
2222 return 1;
2223 case HDSP_ADGainLowGain:
2224 return 2;
2225 default:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002226 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 }
2228}
2229
Takashi Iwai55e957d2005-11-17 14:52:13 +01002230static int hdsp_set_ad_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231{
2232 hdsp->control_register &= ~HDSP_ADGainMask;
2233 switch (mode) {
2234 case 0:
2235 hdsp->control_register |= HDSP_ADGainMinus10dBV;
2236 break;
2237 case 1:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002238 hdsp->control_register |= HDSP_ADGainPlus4dBu;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 break;
2240 case 2:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002241 hdsp->control_register |= HDSP_ADGainLowGain;
2242 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 default:
2244 return -1;
2245
2246 }
2247 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2248 return 0;
2249}
2250
Takashi Iwai55e957d2005-11-17 14:52:13 +01002251static int snd_hdsp_info_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252{
2253 static char *texts[] = {"-10 dBV", "+4 dBu", "Lo Gain"};
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002254
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2256 uinfo->count = 1;
2257 uinfo->value.enumerated.items = 3;
2258 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2259 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2260 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2261 return 0;
2262}
2263
Takashi Iwai55e957d2005-11-17 14:52:13 +01002264static int snd_hdsp_get_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002266 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002267
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268 ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp);
2269 return 0;
2270}
2271
Takashi Iwai55e957d2005-11-17 14:52:13 +01002272static int snd_hdsp_put_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002274 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 int change;
2276 int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002277
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 if (!snd_hdsp_use_is_exclusive(hdsp))
2279 return -EBUSY;
2280 val = ucontrol->value.enumerated.item[0];
2281 if (val < 0) val = 0;
2282 if (val > 2) val = 2;
2283 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002284 if (val != hdsp_ad_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 change = (hdsp_set_ad_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002286 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 spin_unlock_irq(&hdsp->lock);
2289 return change;
2290}
2291
2292#define HDSP_PHONE_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002293{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 .name = xname, \
2295 .index = xindex, \
2296 .info = snd_hdsp_info_phone_gain, \
2297 .get = snd_hdsp_get_phone_gain, \
2298 .put = snd_hdsp_put_phone_gain \
2299}
2300
Takashi Iwai55e957d2005-11-17 14:52:13 +01002301static int hdsp_phone_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302{
2303 switch (hdsp->control_register & HDSP_PhoneGainMask) {
2304 case HDSP_PhoneGain0dB:
2305 return 0;
2306 case HDSP_PhoneGainMinus6dB:
2307 return 1;
2308 case HDSP_PhoneGainMinus12dB:
2309 return 2;
2310 default:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002311 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 }
2313}
2314
Takashi Iwai55e957d2005-11-17 14:52:13 +01002315static int hdsp_set_phone_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316{
2317 hdsp->control_register &= ~HDSP_PhoneGainMask;
2318 switch (mode) {
2319 case 0:
2320 hdsp->control_register |= HDSP_PhoneGain0dB;
2321 break;
2322 case 1:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002323 hdsp->control_register |= HDSP_PhoneGainMinus6dB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 break;
2325 case 2:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002326 hdsp->control_register |= HDSP_PhoneGainMinus12dB;
2327 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 default:
2329 return -1;
2330
2331 }
2332 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2333 return 0;
2334}
2335
Takashi Iwai55e957d2005-11-17 14:52:13 +01002336static int snd_hdsp_info_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337{
2338 static char *texts[] = {"0 dB", "-6 dB", "-12 dB"};
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002339
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2341 uinfo->count = 1;
2342 uinfo->value.enumerated.items = 3;
2343 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2344 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2345 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2346 return 0;
2347}
2348
Takashi Iwai55e957d2005-11-17 14:52:13 +01002349static int snd_hdsp_get_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002351 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002352
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp);
2354 return 0;
2355}
2356
Takashi Iwai55e957d2005-11-17 14:52:13 +01002357static int snd_hdsp_put_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002359 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 int change;
2361 int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002362
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 if (!snd_hdsp_use_is_exclusive(hdsp))
2364 return -EBUSY;
2365 val = ucontrol->value.enumerated.item[0];
2366 if (val < 0) val = 0;
2367 if (val > 2) val = 2;
2368 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002369 if (val != hdsp_phone_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 change = (hdsp_set_phone_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002371 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373 spin_unlock_irq(&hdsp->lock);
2374 return change;
2375}
2376
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377#define HDSP_PREF_SYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002378{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 .name = xname, \
2380 .index = xindex, \
2381 .info = snd_hdsp_info_pref_sync_ref, \
2382 .get = snd_hdsp_get_pref_sync_ref, \
2383 .put = snd_hdsp_put_pref_sync_ref \
2384}
2385
Takashi Iwai55e957d2005-11-17 14:52:13 +01002386static int hdsp_pref_sync_ref(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387{
2388 /* Notice that this looks at the requested sync source,
2389 not the one actually in use.
2390 */
2391
2392 switch (hdsp->control_register & HDSP_SyncRefMask) {
2393 case HDSP_SyncRef_ADAT1:
2394 return HDSP_SYNC_FROM_ADAT1;
2395 case HDSP_SyncRef_ADAT2:
2396 return HDSP_SYNC_FROM_ADAT2;
2397 case HDSP_SyncRef_ADAT3:
2398 return HDSP_SYNC_FROM_ADAT3;
2399 case HDSP_SyncRef_SPDIF:
2400 return HDSP_SYNC_FROM_SPDIF;
2401 case HDSP_SyncRef_WORD:
2402 return HDSP_SYNC_FROM_WORD;
2403 case HDSP_SyncRef_ADAT_SYNC:
2404 return HDSP_SYNC_FROM_ADAT_SYNC;
2405 default:
2406 return HDSP_SYNC_FROM_WORD;
2407 }
2408 return 0;
2409}
2410
Takashi Iwai55e957d2005-11-17 14:52:13 +01002411static int hdsp_set_pref_sync_ref(struct hdsp *hdsp, int pref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412{
2413 hdsp->control_register &= ~HDSP_SyncRefMask;
2414 switch (pref) {
2415 case HDSP_SYNC_FROM_ADAT1:
2416 hdsp->control_register &= ~HDSP_SyncRefMask; /* clear SyncRef bits */
2417 break;
2418 case HDSP_SYNC_FROM_ADAT2:
2419 hdsp->control_register |= HDSP_SyncRef_ADAT2;
2420 break;
2421 case HDSP_SYNC_FROM_ADAT3:
2422 hdsp->control_register |= HDSP_SyncRef_ADAT3;
2423 break;
2424 case HDSP_SYNC_FROM_SPDIF:
2425 hdsp->control_register |= HDSP_SyncRef_SPDIF;
2426 break;
2427 case HDSP_SYNC_FROM_WORD:
2428 hdsp->control_register |= HDSP_SyncRef_WORD;
2429 break;
2430 case HDSP_SYNC_FROM_ADAT_SYNC:
2431 hdsp->control_register |= HDSP_SyncRef_ADAT_SYNC;
2432 break;
2433 default:
2434 return -1;
2435 }
2436 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2437 return 0;
2438}
2439
Takashi Iwai55e957d2005-11-17 14:52:13 +01002440static int snd_hdsp_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441{
2442 static char *texts[] = {"Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3" };
Takashi Iwai55e957d2005-11-17 14:52:13 +01002443 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002444
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2446 uinfo->count = 1;
2447
2448 switch (hdsp->io_type) {
2449 case Digiface:
2450 case H9652:
2451 uinfo->value.enumerated.items = 6;
2452 break;
2453 case Multiface:
2454 uinfo->value.enumerated.items = 4;
2455 break;
2456 case H9632:
2457 uinfo->value.enumerated.items = 3;
2458 break;
2459 default:
Takashi Iwai9badda02012-01-09 18:22:35 +01002460 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002462
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2464 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2465 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2466 return 0;
2467}
2468
Takashi Iwai55e957d2005-11-17 14:52:13 +01002469static int snd_hdsp_get_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002471 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002472
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473 ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp);
2474 return 0;
2475}
2476
Takashi Iwai55e957d2005-11-17 14:52:13 +01002477static int snd_hdsp_put_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002479 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 int change, max;
2481 unsigned int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002482
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483 if (!snd_hdsp_use_is_exclusive(hdsp))
2484 return -EBUSY;
2485
2486 switch (hdsp->io_type) {
2487 case Digiface:
2488 case H9652:
2489 max = 6;
2490 break;
2491 case Multiface:
2492 max = 4;
2493 break;
2494 case H9632:
2495 max = 3;
2496 break;
2497 default:
2498 return -EIO;
2499 }
2500
2501 val = ucontrol->value.enumerated.item[0] % max;
2502 spin_lock_irq(&hdsp->lock);
2503 change = (int)val != hdsp_pref_sync_ref(hdsp);
2504 hdsp_set_pref_sync_ref(hdsp, val);
2505 spin_unlock_irq(&hdsp->lock);
2506 return change;
2507}
2508
2509#define HDSP_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002510{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 .name = xname, \
2512 .index = xindex, \
2513 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2514 .info = snd_hdsp_info_autosync_ref, \
2515 .get = snd_hdsp_get_autosync_ref, \
2516}
2517
Takashi Iwai55e957d2005-11-17 14:52:13 +01002518static int hdsp_autosync_ref(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519{
2520 /* This looks at the autosync selected sync reference */
2521 unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
2522
2523 switch (status2 & HDSP_SelSyncRefMask) {
2524 case HDSP_SelSyncRef_WORD:
2525 return HDSP_AUTOSYNC_FROM_WORD;
2526 case HDSP_SelSyncRef_ADAT_SYNC:
2527 return HDSP_AUTOSYNC_FROM_ADAT_SYNC;
2528 case HDSP_SelSyncRef_SPDIF:
2529 return HDSP_AUTOSYNC_FROM_SPDIF;
2530 case HDSP_SelSyncRefMask:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002531 return HDSP_AUTOSYNC_FROM_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532 case HDSP_SelSyncRef_ADAT1:
2533 return HDSP_AUTOSYNC_FROM_ADAT1;
2534 case HDSP_SelSyncRef_ADAT2:
2535 return HDSP_AUTOSYNC_FROM_ADAT2;
2536 case HDSP_SelSyncRef_ADAT3:
2537 return HDSP_AUTOSYNC_FROM_ADAT3;
2538 default:
2539 return HDSP_AUTOSYNC_FROM_WORD;
2540 }
2541 return 0;
2542}
2543
Takashi Iwai55e957d2005-11-17 14:52:13 +01002544static int snd_hdsp_info_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545{
2546 static char *texts[] = {"Word", "ADAT Sync", "IEC958", "None", "ADAT1", "ADAT2", "ADAT3" };
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002547
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2549 uinfo->count = 1;
2550 uinfo->value.enumerated.items = 7;
2551 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2552 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2553 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2554 return 0;
2555}
2556
Takashi Iwai55e957d2005-11-17 14:52:13 +01002557static int snd_hdsp_get_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002559 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002560
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp);
2562 return 0;
2563}
2564
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565#define HDSP_PRECISE_POINTER(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002566{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 .name = xname, \
2568 .index = xindex, \
2569 .info = snd_hdsp_info_precise_pointer, \
2570 .get = snd_hdsp_get_precise_pointer, \
2571 .put = snd_hdsp_put_precise_pointer \
2572}
2573
Takashi Iwai55e957d2005-11-17 14:52:13 +01002574static int hdsp_set_precise_pointer(struct hdsp *hdsp, int precise)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002576 if (precise)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 hdsp->precise_ptr = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002578 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579 hdsp->precise_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 return 0;
2581}
2582
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002583#define snd_hdsp_info_precise_pointer snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584
Takashi Iwai55e957d2005-11-17 14:52:13 +01002585static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002587 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002588
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 spin_lock_irq(&hdsp->lock);
2590 ucontrol->value.integer.value[0] = hdsp->precise_ptr;
2591 spin_unlock_irq(&hdsp->lock);
2592 return 0;
2593}
2594
Takashi Iwai55e957d2005-11-17 14:52:13 +01002595static int snd_hdsp_put_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002597 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 int change;
2599 unsigned int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002600
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 if (!snd_hdsp_use_is_exclusive(hdsp))
2602 return -EBUSY;
2603 val = ucontrol->value.integer.value[0] & 1;
2604 spin_lock_irq(&hdsp->lock);
2605 change = (int)val != hdsp->precise_ptr;
2606 hdsp_set_precise_pointer(hdsp, val);
2607 spin_unlock_irq(&hdsp->lock);
2608 return change;
2609}
2610
2611#define HDSP_USE_MIDI_TASKLET(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002612{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 .name = xname, \
2614 .index = xindex, \
2615 .info = snd_hdsp_info_use_midi_tasklet, \
2616 .get = snd_hdsp_get_use_midi_tasklet, \
2617 .put = snd_hdsp_put_use_midi_tasklet \
2618}
2619
Takashi Iwai55e957d2005-11-17 14:52:13 +01002620static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002622 if (use_tasklet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 hdsp->use_midi_tasklet = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002624 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625 hdsp->use_midi_tasklet = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 return 0;
2627}
2628
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002629#define snd_hdsp_info_use_midi_tasklet snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630
Takashi Iwai55e957d2005-11-17 14:52:13 +01002631static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002633 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002634
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 spin_lock_irq(&hdsp->lock);
2636 ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet;
2637 spin_unlock_irq(&hdsp->lock);
2638 return 0;
2639}
2640
Takashi Iwai55e957d2005-11-17 14:52:13 +01002641static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002643 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 int change;
2645 unsigned int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002646
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647 if (!snd_hdsp_use_is_exclusive(hdsp))
2648 return -EBUSY;
2649 val = ucontrol->value.integer.value[0] & 1;
2650 spin_lock_irq(&hdsp->lock);
2651 change = (int)val != hdsp->use_midi_tasklet;
2652 hdsp_set_use_midi_tasklet(hdsp, val);
2653 spin_unlock_irq(&hdsp->lock);
2654 return change;
2655}
2656
2657#define HDSP_MIXER(xname, xindex) \
2658{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
2659 .name = xname, \
2660 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002661 .device = 0, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2663 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2664 .info = snd_hdsp_info_mixer, \
2665 .get = snd_hdsp_get_mixer, \
2666 .put = snd_hdsp_put_mixer \
2667}
2668
Takashi Iwai55e957d2005-11-17 14:52:13 +01002669static int snd_hdsp_info_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670{
2671 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2672 uinfo->count = 3;
2673 uinfo->value.integer.min = 0;
2674 uinfo->value.integer.max = 65536;
2675 uinfo->value.integer.step = 1;
2676 return 0;
2677}
2678
Takashi Iwai55e957d2005-11-17 14:52:13 +01002679static int snd_hdsp_get_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002681 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 int source;
2683 int destination;
2684 int addr;
2685
2686 source = ucontrol->value.integer.value[0];
2687 destination = ucontrol->value.integer.value[1];
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002688
Takashi Iwaib0b98112005-10-20 18:29:58 +02002689 if (source >= hdsp->max_channels)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels,destination);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002691 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692 addr = hdsp_input_to_output_key(hdsp,source, destination);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002693
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 spin_lock_irq(&hdsp->lock);
2695 ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr);
2696 spin_unlock_irq(&hdsp->lock);
2697 return 0;
2698}
2699
Takashi Iwai55e957d2005-11-17 14:52:13 +01002700static int snd_hdsp_put_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002702 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 int change;
2704 int source;
2705 int destination;
2706 int gain;
2707 int addr;
2708
2709 if (!snd_hdsp_use_is_exclusive(hdsp))
2710 return -EBUSY;
2711
2712 source = ucontrol->value.integer.value[0];
2713 destination = ucontrol->value.integer.value[1];
2714
Takashi Iwaib0b98112005-10-20 18:29:58 +02002715 if (source >= hdsp->max_channels)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels, destination);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002717 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718 addr = hdsp_input_to_output_key(hdsp,source, destination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719
2720 gain = ucontrol->value.integer.value[2];
2721
2722 spin_lock_irq(&hdsp->lock);
2723 change = gain != hdsp_read_gain(hdsp, addr);
2724 if (change)
2725 hdsp_write_gain(hdsp, addr, gain);
2726 spin_unlock_irq(&hdsp->lock);
2727 return change;
2728}
2729
2730#define HDSP_WC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002731{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 .name = xname, \
2733 .index = xindex, \
2734 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2735 .info = snd_hdsp_info_sync_check, \
2736 .get = snd_hdsp_get_wc_sync_check \
2737}
2738
Takashi Iwai55e957d2005-11-17 14:52:13 +01002739static int snd_hdsp_info_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740{
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002741 static char *texts[] = {"No Lock", "Lock", "Sync" };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2743 uinfo->count = 1;
2744 uinfo->value.enumerated.items = 3;
2745 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2746 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2747 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2748 return 0;
2749}
2750
Takashi Iwai55e957d2005-11-17 14:52:13 +01002751static int hdsp_wc_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752{
2753 int status2 = hdsp_read(hdsp, HDSP_status2Register);
2754 if (status2 & HDSP_wc_lock) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002755 if (status2 & HDSP_wc_sync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002757 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002759 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 return 0;
2762}
2763
Takashi Iwai55e957d2005-11-17 14:52:13 +01002764static int snd_hdsp_get_wc_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002766 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767
2768 ucontrol->value.enumerated.item[0] = hdsp_wc_sync_check(hdsp);
2769 return 0;
2770}
2771
2772#define HDSP_SPDIF_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002773{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 .name = xname, \
2775 .index = xindex, \
2776 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2777 .info = snd_hdsp_info_sync_check, \
2778 .get = snd_hdsp_get_spdif_sync_check \
2779}
2780
Takashi Iwai55e957d2005-11-17 14:52:13 +01002781static int hdsp_spdif_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782{
2783 int status = hdsp_read(hdsp, HDSP_statusRegister);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002784 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 return 0;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002786 else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002787 if (status & HDSP_SPDIFSync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002789 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 }
2792 return 0;
2793}
2794
Takashi Iwai55e957d2005-11-17 14:52:13 +01002795static int snd_hdsp_get_spdif_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002797 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798
2799 ucontrol->value.enumerated.item[0] = hdsp_spdif_sync_check(hdsp);
2800 return 0;
2801}
2802
2803#define HDSP_ADATSYNC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002804{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805 .name = xname, \
2806 .index = xindex, \
2807 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2808 .info = snd_hdsp_info_sync_check, \
2809 .get = snd_hdsp_get_adatsync_sync_check \
2810}
2811
Takashi Iwai55e957d2005-11-17 14:52:13 +01002812static int hdsp_adatsync_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813{
2814 int status = hdsp_read(hdsp, HDSP_statusRegister);
2815 if (status & HDSP_TimecodeLock) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002816 if (status & HDSP_TimecodeSync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002818 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002820 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 return 0;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002822}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823
Takashi Iwai55e957d2005-11-17 14:52:13 +01002824static int snd_hdsp_get_adatsync_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002826 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827
2828 ucontrol->value.enumerated.item[0] = hdsp_adatsync_sync_check(hdsp);
2829 return 0;
2830}
2831
2832#define HDSP_ADAT_SYNC_CHECK \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002833{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2835 .info = snd_hdsp_info_sync_check, \
2836 .get = snd_hdsp_get_adat_sync_check \
2837}
2838
Takashi Iwai55e957d2005-11-17 14:52:13 +01002839static int hdsp_adat_sync_check(struct hdsp *hdsp, int idx)
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002840{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841 int status = hdsp_read(hdsp, HDSP_statusRegister);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002842
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843 if (status & (HDSP_Lock0>>idx)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002844 if (status & (HDSP_Sync0>>idx))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002846 else
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002847 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002848 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849 return 0;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002850}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851
Takashi Iwai55e957d2005-11-17 14:52:13 +01002852static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853{
2854 int offset;
Takashi Iwai55e957d2005-11-17 14:52:13 +01002855 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856
2857 offset = ucontrol->id.index - 1;
Takashi Iwaida3cec32008-08-08 17:12:14 +02002858 snd_BUG_ON(offset < 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859
2860 switch (hdsp->io_type) {
2861 case Digiface:
2862 case H9652:
2863 if (offset >= 3)
2864 return -EINVAL;
2865 break;
2866 case Multiface:
2867 case H9632:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002868 if (offset >= 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 return -EINVAL;
2870 break;
2871 default:
2872 return -EIO;
2873 }
2874
2875 ucontrol->value.enumerated.item[0] = hdsp_adat_sync_check(hdsp, offset);
2876 return 0;
2877}
2878
Julian Cablee4b60882007-03-19 11:44:40 +01002879#define HDSP_DDS_OFFSET(xname, xindex) \
2880{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2881 .name = xname, \
2882 .index = xindex, \
2883 .info = snd_hdsp_info_dds_offset, \
2884 .get = snd_hdsp_get_dds_offset, \
2885 .put = snd_hdsp_put_dds_offset \
2886}
2887
2888static int hdsp_dds_offset(struct hdsp *hdsp)
2889{
2890 u64 n;
Julian Cablee4b60882007-03-19 11:44:40 +01002891 unsigned int dds_value = hdsp->dds_value;
2892 int system_sample_rate = hdsp->system_sample_rate;
2893
Takashi Iwai2a3988f2007-10-16 14:26:32 +02002894 if (!dds_value)
2895 return 0;
2896
Julian Cablee4b60882007-03-19 11:44:40 +01002897 n = DDS_NUMERATOR;
2898 /*
2899 * dds_value = n / rate
2900 * rate = n / dds_value
2901 */
Takashi Iwai3f7440a2009-06-05 17:40:04 +02002902 n = div_u64(n, dds_value);
Julian Cablee4b60882007-03-19 11:44:40 +01002903 if (system_sample_rate >= 112000)
2904 n *= 4;
2905 else if (system_sample_rate >= 56000)
2906 n *= 2;
2907 return ((int)n) - system_sample_rate;
2908}
2909
2910static int hdsp_set_dds_offset(struct hdsp *hdsp, int offset_hz)
2911{
2912 int rate = hdsp->system_sample_rate + offset_hz;
2913 hdsp_set_dds_value(hdsp, rate);
2914 return 0;
2915}
2916
2917static int snd_hdsp_info_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
2918{
2919 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2920 uinfo->count = 1;
2921 uinfo->value.integer.min = -5000;
2922 uinfo->value.integer.max = 5000;
2923 return 0;
2924}
2925
2926static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2927{
2928 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002929
Julian Cablee4b60882007-03-19 11:44:40 +01002930 ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp);
2931 return 0;
2932}
2933
2934static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2935{
2936 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
2937 int change;
2938 int val;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002939
Julian Cablee4b60882007-03-19 11:44:40 +01002940 if (!snd_hdsp_use_is_exclusive(hdsp))
2941 return -EBUSY;
2942 val = ucontrol->value.enumerated.item[0];
2943 spin_lock_irq(&hdsp->lock);
2944 if (val != hdsp_dds_offset(hdsp))
2945 change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0;
2946 else
2947 change = 0;
2948 spin_unlock_irq(&hdsp->lock);
2949 return change;
2950}
2951
Takashi Iwai55e957d2005-11-17 14:52:13 +01002952static struct snd_kcontrol_new snd_hdsp_9632_controls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953HDSP_DA_GAIN("DA Gain", 0),
2954HDSP_AD_GAIN("AD Gain", 0),
2955HDSP_PHONE_GAIN("Phones Gain", 0),
Adrian Knoth4833c672013-01-15 18:52:22 +01002956HDSP_TOGGLE_SETTING("XLR Breakout Cable", HDSP_XLRBreakoutCable),
Julian Cablee4b60882007-03-19 11:44:40 +01002957HDSP_DDS_OFFSET("DDS Sample Rate Offset", 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958};
2959
Takashi Iwai55e957d2005-11-17 14:52:13 +01002960static struct snd_kcontrol_new snd_hdsp_controls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961{
Clemens Ladisch5549d542005-08-03 13:50:30 +02002962 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2964 .info = snd_hdsp_control_spdif_info,
2965 .get = snd_hdsp_control_spdif_get,
2966 .put = snd_hdsp_control_spdif_put,
2967},
2968{
2969 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch5549d542005-08-03 13:50:30 +02002970 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
2972 .info = snd_hdsp_control_spdif_stream_info,
2973 .get = snd_hdsp_control_spdif_stream_get,
2974 .put = snd_hdsp_control_spdif_stream_put,
2975},
2976{
2977 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +02002978 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
2980 .info = snd_hdsp_control_spdif_mask_info,
2981 .get = snd_hdsp_control_spdif_mask_get,
2982 .private_value = IEC958_AES0_NONAUDIO |
2983 IEC958_AES0_PROFESSIONAL |
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01002984 IEC958_AES0_CON_EMPHASIS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985},
2986{
2987 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +02002988 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
2990 .info = snd_hdsp_control_spdif_mask_info,
2991 .get = snd_hdsp_control_spdif_mask_get,
2992 .private_value = IEC958_AES0_NONAUDIO |
2993 IEC958_AES0_PROFESSIONAL |
2994 IEC958_AES0_PRO_EMPHASIS,
2995},
2996HDSP_MIXER("Mixer", 0),
2997HDSP_SPDIF_IN("IEC958 Input Connector", 0),
Adrian Knoth4833c672013-01-15 18:52:22 +01002998HDSP_TOGGLE_SETTING("IEC958 Output also on ADAT1", HDSP_SPDIFOpticalOut),
2999HDSP_TOGGLE_SETTING("IEC958 Professional Bit", HDSP_SPDIFProfessional),
3000HDSP_TOGGLE_SETTING("IEC958 Emphasis Bit", HDSP_SPDIFEmphasis),
3001HDSP_TOGGLE_SETTING("IEC958 Non-audio Bit", HDSP_SPDIFNonAudio),
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003002/* 'Sample Clock Source' complies with the alsa control naming scheme */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003HDSP_CLOCK_SOURCE("Sample Clock Source", 0),
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003004{
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003005 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3006 .name = "Sample Clock Source Locking",
3007 .info = snd_hdsp_info_clock_source_lock,
3008 .get = snd_hdsp_get_clock_source_lock,
3009 .put = snd_hdsp_put_clock_source_lock,
3010},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011HDSP_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
3012HDSP_PREF_SYNC_REF("Preferred Sync Reference", 0),
3013HDSP_AUTOSYNC_REF("AutoSync Reference", 0),
3014HDSP_SPDIF_SAMPLE_RATE("SPDIF Sample Rate", 0),
3015HDSP_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
3016/* 'External Rate' complies with the alsa control naming scheme */
3017HDSP_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
3018HDSP_WC_SYNC_CHECK("Word Clock Lock Status", 0),
3019HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0),
3020HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0),
Adrian Knoth4833c672013-01-15 18:52:22 +01003021HDSP_TOGGLE_SETTING("Line Out", HDSP_LineOut),
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022HDSP_PRECISE_POINTER("Precise Pointer", 0),
3023HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0),
3024};
3025
Florian Faber28b26e12010-12-01 12:14:47 +01003026
3027static int hdsp_rpm_input12(struct hdsp *hdsp)
3028{
3029 switch (hdsp->control_register & HDSP_RPM_Inp12) {
3030 case HDSP_RPM_Inp12_Phon_6dB:
3031 return 0;
3032 case HDSP_RPM_Inp12_Phon_n6dB:
3033 return 2;
3034 case HDSP_RPM_Inp12_Line_0dB:
3035 return 3;
3036 case HDSP_RPM_Inp12_Line_n6dB:
3037 return 4;
3038 }
3039 return 1;
3040}
3041
3042
3043static int snd_hdsp_get_rpm_input12(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3044{
3045 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3046
3047 ucontrol->value.enumerated.item[0] = hdsp_rpm_input12(hdsp);
3048 return 0;
3049}
3050
3051
3052static int hdsp_set_rpm_input12(struct hdsp *hdsp, int mode)
3053{
3054 hdsp->control_register &= ~HDSP_RPM_Inp12;
3055 switch (mode) {
3056 case 0:
3057 hdsp->control_register |= HDSP_RPM_Inp12_Phon_6dB;
3058 break;
3059 case 1:
3060 break;
3061 case 2:
3062 hdsp->control_register |= HDSP_RPM_Inp12_Phon_n6dB;
3063 break;
3064 case 3:
3065 hdsp->control_register |= HDSP_RPM_Inp12_Line_0dB;
3066 break;
3067 case 4:
3068 hdsp->control_register |= HDSP_RPM_Inp12_Line_n6dB;
3069 break;
3070 default:
3071 return -1;
3072 }
3073
3074 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3075 return 0;
3076}
3077
3078
3079static int snd_hdsp_put_rpm_input12(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3080{
3081 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3082 int change;
3083 int val;
3084
3085 if (!snd_hdsp_use_is_exclusive(hdsp))
3086 return -EBUSY;
3087 val = ucontrol->value.enumerated.item[0];
3088 if (val < 0)
3089 val = 0;
3090 if (val > 4)
3091 val = 4;
3092 spin_lock_irq(&hdsp->lock);
3093 if (val != hdsp_rpm_input12(hdsp))
3094 change = (hdsp_set_rpm_input12(hdsp, val) == 0) ? 1 : 0;
3095 else
3096 change = 0;
3097 spin_unlock_irq(&hdsp->lock);
3098 return change;
3099}
3100
3101
3102static int snd_hdsp_info_rpm_input(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3103{
3104 static char *texts[] = {"Phono +6dB", "Phono 0dB", "Phono -6dB", "Line 0dB", "Line -6dB"};
3105
3106 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3107 uinfo->count = 1;
3108 uinfo->value.enumerated.items = 5;
3109 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3110 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
3111 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
3112 return 0;
3113}
3114
3115
3116static int hdsp_rpm_input34(struct hdsp *hdsp)
3117{
3118 switch (hdsp->control_register & HDSP_RPM_Inp34) {
3119 case HDSP_RPM_Inp34_Phon_6dB:
3120 return 0;
3121 case HDSP_RPM_Inp34_Phon_n6dB:
3122 return 2;
3123 case HDSP_RPM_Inp34_Line_0dB:
3124 return 3;
3125 case HDSP_RPM_Inp34_Line_n6dB:
3126 return 4;
3127 }
3128 return 1;
3129}
3130
3131
3132static int snd_hdsp_get_rpm_input34(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3133{
3134 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3135
3136 ucontrol->value.enumerated.item[0] = hdsp_rpm_input34(hdsp);
3137 return 0;
3138}
3139
3140
3141static int hdsp_set_rpm_input34(struct hdsp *hdsp, int mode)
3142{
3143 hdsp->control_register &= ~HDSP_RPM_Inp34;
3144 switch (mode) {
3145 case 0:
3146 hdsp->control_register |= HDSP_RPM_Inp34_Phon_6dB;
3147 break;
3148 case 1:
3149 break;
3150 case 2:
3151 hdsp->control_register |= HDSP_RPM_Inp34_Phon_n6dB;
3152 break;
3153 case 3:
3154 hdsp->control_register |= HDSP_RPM_Inp34_Line_0dB;
3155 break;
3156 case 4:
3157 hdsp->control_register |= HDSP_RPM_Inp34_Line_n6dB;
3158 break;
3159 default:
3160 return -1;
3161 }
3162
3163 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3164 return 0;
3165}
3166
3167
3168static int snd_hdsp_put_rpm_input34(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3169{
3170 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3171 int change;
3172 int val;
3173
3174 if (!snd_hdsp_use_is_exclusive(hdsp))
3175 return -EBUSY;
3176 val = ucontrol->value.enumerated.item[0];
3177 if (val < 0)
3178 val = 0;
3179 if (val > 4)
3180 val = 4;
3181 spin_lock_irq(&hdsp->lock);
3182 if (val != hdsp_rpm_input34(hdsp))
3183 change = (hdsp_set_rpm_input34(hdsp, val) == 0) ? 1 : 0;
3184 else
3185 change = 0;
3186 spin_unlock_irq(&hdsp->lock);
3187 return change;
3188}
3189
3190
3191/* RPM Bypass switch */
3192static int hdsp_rpm_bypass(struct hdsp *hdsp)
3193{
3194 return (hdsp->control_register & HDSP_RPM_Bypass) ? 1 : 0;
3195}
3196
3197
3198static int snd_hdsp_get_rpm_bypass(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3199{
3200 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3201
3202 ucontrol->value.integer.value[0] = hdsp_rpm_bypass(hdsp);
3203 return 0;
3204}
3205
3206
3207static int hdsp_set_rpm_bypass(struct hdsp *hdsp, int on)
3208{
3209 if (on)
3210 hdsp->control_register |= HDSP_RPM_Bypass;
3211 else
3212 hdsp->control_register &= ~HDSP_RPM_Bypass;
3213 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3214 return 0;
3215}
3216
3217
3218static int snd_hdsp_put_rpm_bypass(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3219{
3220 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3221 int change;
3222 unsigned int val;
3223
3224 if (!snd_hdsp_use_is_exclusive(hdsp))
3225 return -EBUSY;
3226 val = ucontrol->value.integer.value[0] & 1;
3227 spin_lock_irq(&hdsp->lock);
3228 change = (int)val != hdsp_rpm_bypass(hdsp);
3229 hdsp_set_rpm_bypass(hdsp, val);
3230 spin_unlock_irq(&hdsp->lock);
3231 return change;
3232}
3233
3234
3235static int snd_hdsp_info_rpm_bypass(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3236{
3237 static char *texts[] = {"On", "Off"};
3238
3239 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3240 uinfo->count = 1;
3241 uinfo->value.enumerated.items = 2;
3242 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3243 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
3244 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
3245 return 0;
3246}
3247
3248
3249/* RPM Disconnect switch */
3250static int hdsp_rpm_disconnect(struct hdsp *hdsp)
3251{
3252 return (hdsp->control_register & HDSP_RPM_Disconnect) ? 1 : 0;
3253}
3254
3255
3256static int snd_hdsp_get_rpm_disconnect(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3257{
3258 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3259
3260 ucontrol->value.integer.value[0] = hdsp_rpm_disconnect(hdsp);
3261 return 0;
3262}
3263
3264
3265static int hdsp_set_rpm_disconnect(struct hdsp *hdsp, int on)
3266{
3267 if (on)
3268 hdsp->control_register |= HDSP_RPM_Disconnect;
3269 else
3270 hdsp->control_register &= ~HDSP_RPM_Disconnect;
3271 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3272 return 0;
3273}
3274
3275
3276static int snd_hdsp_put_rpm_disconnect(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3277{
3278 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3279 int change;
3280 unsigned int val;
3281
3282 if (!snd_hdsp_use_is_exclusive(hdsp))
3283 return -EBUSY;
3284 val = ucontrol->value.integer.value[0] & 1;
3285 spin_lock_irq(&hdsp->lock);
3286 change = (int)val != hdsp_rpm_disconnect(hdsp);
3287 hdsp_set_rpm_disconnect(hdsp, val);
3288 spin_unlock_irq(&hdsp->lock);
3289 return change;
3290}
3291
3292static int snd_hdsp_info_rpm_disconnect(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3293{
3294 static char *texts[] = {"On", "Off"};
3295
3296 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3297 uinfo->count = 1;
3298 uinfo->value.enumerated.items = 2;
3299 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3300 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
3301 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
3302 return 0;
3303}
3304
3305static struct snd_kcontrol_new snd_hdsp_rpm_controls[] = {
3306 {
3307 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3308 .name = "RPM Bypass",
3309 .get = snd_hdsp_get_rpm_bypass,
3310 .put = snd_hdsp_put_rpm_bypass,
3311 .info = snd_hdsp_info_rpm_bypass
3312 },
3313 {
3314 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3315 .name = "RPM Disconnect",
3316 .get = snd_hdsp_get_rpm_disconnect,
3317 .put = snd_hdsp_put_rpm_disconnect,
3318 .info = snd_hdsp_info_rpm_disconnect
3319 },
3320 {
3321 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3322 .name = "Input 1/2",
3323 .get = snd_hdsp_get_rpm_input12,
3324 .put = snd_hdsp_put_rpm_input12,
3325 .info = snd_hdsp_info_rpm_input
3326 },
3327 {
3328 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3329 .name = "Input 3/4",
3330 .get = snd_hdsp_get_rpm_input34,
3331 .put = snd_hdsp_put_rpm_input34,
3332 .info = snd_hdsp_info_rpm_input
3333 },
3334 HDSP_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
3335 HDSP_MIXER("Mixer", 0)
3336};
3337
Adrian Knoth4833c672013-01-15 18:52:22 +01003338static struct snd_kcontrol_new snd_hdsp_96xx_aeb =
3339 HDSP_TOGGLE_SETTING("Analog Extension Board",
3340 HDSP_AnalogExtensionBoard);
Takashi Iwai55e957d2005-11-17 14:52:13 +01003341static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342
Takashi Iwai55e957d2005-11-17 14:52:13 +01003343static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344{
3345 unsigned int idx;
3346 int err;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003347 struct snd_kcontrol *kctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003348
Florian Faber28b26e12010-12-01 12:14:47 +01003349 if (hdsp->io_type == RPM) {
3350 /* RPM Bypass, Disconnect and Input switches */
3351 for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_rpm_controls); idx++) {
3352 err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_rpm_controls[idx], hdsp));
3353 if (err < 0)
3354 return err;
3355 }
3356 return 0;
3357 }
3358
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359 for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003360 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362 if (idx == 1) /* IEC958 (S/PDIF) Stream */
3363 hdsp->spdif_ctl = kctl;
3364 }
3365
3366 /* ADAT SyncCheck status */
3367 snd_hdsp_adat_sync_check.name = "ADAT Lock Status";
3368 snd_hdsp_adat_sync_check.index = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003369 if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371 if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
3372 for (idx = 1; idx < 3; ++idx) {
3373 snd_hdsp_adat_sync_check.index = idx+1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003374 if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376 }
3377 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003378
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379 /* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */
3380 if (hdsp->io_type == H9632) {
3381 for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003382 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003384 }
3385 }
3386
3387 /* AEB control for H96xx card */
3388 if (hdsp->io_type == H9632 || hdsp->io_type == H9652) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003389 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391 }
3392
3393 return 0;
3394}
3395
3396/*------------------------------------------------------------
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003397 /proc interface
Linus Torvalds1da177e2005-04-16 15:20:36 -07003398 ------------------------------------------------------------*/
3399
3400static void
Takashi Iwai55e957d2005-11-17 14:52:13 +01003401snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003402{
Joe Perches9fe856e2010-09-04 18:52:54 -07003403 struct hdsp *hdsp = entry->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404 unsigned int status;
3405 unsigned int status2;
3406 char *pref_sync_ref;
3407 char *autosync_ref;
3408 char *system_clock_mode;
3409 char *clock_source;
3410 int x;
3411
Tim Blechmannc18bc9b2009-08-12 18:21:30 +02003412 status = hdsp_read(hdsp, HDSP_statusRegister);
3413 status2 = hdsp_read(hdsp, HDSP_status2Register);
3414
3415 snd_iprintf(buffer, "%s (Card #%d)\n", hdsp->card_name,
3416 hdsp->card->number + 1);
3417 snd_iprintf(buffer, "Buffers: capture %p playback %p\n",
3418 hdsp->capture_buffer, hdsp->playback_buffer);
3419 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
3420 hdsp->irq, hdsp->port, (unsigned long)hdsp->iobase);
3421 snd_iprintf(buffer, "Control register: 0x%x\n", hdsp->control_register);
3422 snd_iprintf(buffer, "Control2 register: 0x%x\n",
3423 hdsp->control2_register);
3424 snd_iprintf(buffer, "Status register: 0x%x\n", status);
3425 snd_iprintf(buffer, "Status2 register: 0x%x\n", status2);
3426
3427 if (hdsp_check_for_iobox(hdsp)) {
3428 snd_iprintf(buffer, "No I/O box connected.\n"
3429 "Please connect one and upload firmware.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430 return;
Tim Blechmannc18bc9b2009-08-12 18:21:30 +02003431 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003432
Takashi Iwaib0b98112005-10-20 18:29:58 +02003433 if (hdsp_check_for_firmware(hdsp, 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434 if (hdsp->state & HDSP_FirmwareCached) {
3435 if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
Tim Blechmannc18bc9b2009-08-12 18:21:30 +02003436 snd_iprintf(buffer, "Firmware loading from "
3437 "cache failed, "
3438 "please upload manually.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439 return;
3440 }
3441 } else {
Takashi Iwai311e70a2006-09-06 12:13:37 +02003442 int err = -EINVAL;
Takashi Iwai311e70a2006-09-06 12:13:37 +02003443 err = hdsp_request_fw_loader(hdsp);
Takashi Iwai311e70a2006-09-06 12:13:37 +02003444 if (err < 0) {
3445 snd_iprintf(buffer,
3446 "No firmware loaded nor cached, "
3447 "please upload firmware.\n");
3448 return;
3449 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003450 }
3451 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003452
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453 snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff);
3454 snd_iprintf(buffer, "MIDI1 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut0));
3455 snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0));
3456 snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1));
3457 snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1));
3458 snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off");
3459
3460 snd_iprintf(buffer, "\n");
3461
3462 x = 1 << (6 + hdsp_decode_latency(hdsp->control_register & HDSP_LatencyMask));
3463
3464 snd_iprintf(buffer, "Buffer Size (Latency): %d samples (2 periods of %lu bytes)\n", x, (unsigned long) hdsp->period_bytes);
3465 snd_iprintf(buffer, "Hardware pointer (frames): %ld\n", hdsp_hw_pointer(hdsp));
3466 snd_iprintf(buffer, "Precise pointer: %s\n", hdsp->precise_ptr ? "on" : "off");
3467 snd_iprintf(buffer, "Line out: %s\n", (hdsp->control_register & HDSP_LineOut) ? "on" : "off");
3468
3469 snd_iprintf(buffer, "Firmware version: %d\n", (status2&HDSP_version0)|(status2&HDSP_version1)<<1|(status2&HDSP_version2)<<2);
3470
3471 snd_iprintf(buffer, "\n");
3472
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473 switch (hdsp_clock_source(hdsp)) {
3474 case HDSP_CLOCK_SOURCE_AUTOSYNC:
3475 clock_source = "AutoSync";
3476 break;
3477 case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ:
3478 clock_source = "Internal 32 kHz";
3479 break;
3480 case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ:
3481 clock_source = "Internal 44.1 kHz";
3482 break;
3483 case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ:
3484 clock_source = "Internal 48 kHz";
3485 break;
3486 case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ:
3487 clock_source = "Internal 64 kHz";
3488 break;
3489 case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ:
3490 clock_source = "Internal 88.2 kHz";
3491 break;
3492 case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ:
3493 clock_source = "Internal 96 kHz";
3494 break;
3495 case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ:
3496 clock_source = "Internal 128 kHz";
3497 break;
3498 case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ:
3499 clock_source = "Internal 176.4 kHz";
3500 break;
3501 case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ:
3502 clock_source = "Internal 192 kHz";
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003503 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504 default:
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003505 clock_source = "Error";
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 }
3507 snd_iprintf (buffer, "Sample Clock Source: %s\n", clock_source);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003508
Takashi Iwaib0b98112005-10-20 18:29:58 +02003509 if (hdsp_system_clock_mode(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510 system_clock_mode = "Slave";
Takashi Iwaib0b98112005-10-20 18:29:58 +02003511 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512 system_clock_mode = "Master";
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003513
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514 switch (hdsp_pref_sync_ref (hdsp)) {
3515 case HDSP_SYNC_FROM_WORD:
3516 pref_sync_ref = "Word Clock";
3517 break;
3518 case HDSP_SYNC_FROM_ADAT_SYNC:
3519 pref_sync_ref = "ADAT Sync";
3520 break;
3521 case HDSP_SYNC_FROM_SPDIF:
3522 pref_sync_ref = "SPDIF";
3523 break;
3524 case HDSP_SYNC_FROM_ADAT1:
3525 pref_sync_ref = "ADAT1";
3526 break;
3527 case HDSP_SYNC_FROM_ADAT2:
3528 pref_sync_ref = "ADAT2";
3529 break;
3530 case HDSP_SYNC_FROM_ADAT3:
3531 pref_sync_ref = "ADAT3";
3532 break;
3533 default:
3534 pref_sync_ref = "Word Clock";
3535 break;
3536 }
3537 snd_iprintf (buffer, "Preferred Sync Reference: %s\n", pref_sync_ref);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003538
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539 switch (hdsp_autosync_ref (hdsp)) {
3540 case HDSP_AUTOSYNC_FROM_WORD:
3541 autosync_ref = "Word Clock";
3542 break;
3543 case HDSP_AUTOSYNC_FROM_ADAT_SYNC:
3544 autosync_ref = "ADAT Sync";
3545 break;
3546 case HDSP_AUTOSYNC_FROM_SPDIF:
3547 autosync_ref = "SPDIF";
3548 break;
3549 case HDSP_AUTOSYNC_FROM_NONE:
3550 autosync_ref = "None";
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003551 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552 case HDSP_AUTOSYNC_FROM_ADAT1:
3553 autosync_ref = "ADAT1";
3554 break;
3555 case HDSP_AUTOSYNC_FROM_ADAT2:
3556 autosync_ref = "ADAT2";
3557 break;
3558 case HDSP_AUTOSYNC_FROM_ADAT3:
3559 autosync_ref = "ADAT3";
3560 break;
3561 default:
3562 autosync_ref = "---";
3563 break;
3564 }
3565 snd_iprintf (buffer, "AutoSync Reference: %s\n", autosync_ref);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003566
Linus Torvalds1da177e2005-04-16 15:20:36 -07003567 snd_iprintf (buffer, "AutoSync Frequency: %d\n", hdsp_external_sample_rate(hdsp));
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003568
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569 snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode);
3570
3571 snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003572 snd_iprintf (buffer, "System Clock Locked: %s\n", hdsp->clock_source_locked ? "Yes" : "No");
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003573
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574 snd_iprintf(buffer, "\n");
3575
Florian Faber28b26e12010-12-01 12:14:47 +01003576 if (hdsp->io_type != RPM) {
3577 switch (hdsp_spdif_in(hdsp)) {
3578 case HDSP_SPDIFIN_OPTICAL:
3579 snd_iprintf(buffer, "IEC958 input: Optical\n");
3580 break;
3581 case HDSP_SPDIFIN_COAXIAL:
3582 snd_iprintf(buffer, "IEC958 input: Coaxial\n");
3583 break;
3584 case HDSP_SPDIFIN_INTERNAL:
3585 snd_iprintf(buffer, "IEC958 input: Internal\n");
3586 break;
3587 case HDSP_SPDIFIN_AES:
3588 snd_iprintf(buffer, "IEC958 input: AES\n");
3589 break;
3590 default:
3591 snd_iprintf(buffer, "IEC958 input: ???\n");
3592 break;
3593 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003594 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003595
Florian Faber28b26e12010-12-01 12:14:47 +01003596 if (RPM == hdsp->io_type) {
3597 if (hdsp->control_register & HDSP_RPM_Bypass)
3598 snd_iprintf(buffer, "RPM Bypass: disabled\n");
3599 else
3600 snd_iprintf(buffer, "RPM Bypass: enabled\n");
3601 if (hdsp->control_register & HDSP_RPM_Disconnect)
3602 snd_iprintf(buffer, "RPM disconnected\n");
3603 else
3604 snd_iprintf(buffer, "RPM connected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605
Florian Faber28b26e12010-12-01 12:14:47 +01003606 switch (hdsp->control_register & HDSP_RPM_Inp12) {
3607 case HDSP_RPM_Inp12_Phon_6dB:
3608 snd_iprintf(buffer, "Input 1/2: Phono, 6dB\n");
3609 break;
3610 case HDSP_RPM_Inp12_Phon_0dB:
3611 snd_iprintf(buffer, "Input 1/2: Phono, 0dB\n");
3612 break;
3613 case HDSP_RPM_Inp12_Phon_n6dB:
3614 snd_iprintf(buffer, "Input 1/2: Phono, -6dB\n");
3615 break;
3616 case HDSP_RPM_Inp12_Line_0dB:
3617 snd_iprintf(buffer, "Input 1/2: Line, 0dB\n");
3618 break;
3619 case HDSP_RPM_Inp12_Line_n6dB:
3620 snd_iprintf(buffer, "Input 1/2: Line, -6dB\n");
3621 break;
3622 default:
3623 snd_iprintf(buffer, "Input 1/2: ???\n");
3624 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625
Florian Faber28b26e12010-12-01 12:14:47 +01003626 switch (hdsp->control_register & HDSP_RPM_Inp34) {
3627 case HDSP_RPM_Inp34_Phon_6dB:
3628 snd_iprintf(buffer, "Input 3/4: Phono, 6dB\n");
3629 break;
3630 case HDSP_RPM_Inp34_Phon_0dB:
3631 snd_iprintf(buffer, "Input 3/4: Phono, 0dB\n");
3632 break;
3633 case HDSP_RPM_Inp34_Phon_n6dB:
3634 snd_iprintf(buffer, "Input 3/4: Phono, -6dB\n");
3635 break;
3636 case HDSP_RPM_Inp34_Line_0dB:
3637 snd_iprintf(buffer, "Input 3/4: Line, 0dB\n");
3638 break;
3639 case HDSP_RPM_Inp34_Line_n6dB:
3640 snd_iprintf(buffer, "Input 3/4: Line, -6dB\n");
3641 break;
3642 default:
3643 snd_iprintf(buffer, "Input 3/4: ???\n");
3644 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645
Florian Faber28b26e12010-12-01 12:14:47 +01003646 } else {
3647 if (hdsp->control_register & HDSP_SPDIFOpticalOut)
3648 snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n");
3649 else
3650 snd_iprintf(buffer, "IEC958 output: Coaxial only\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651
Florian Faber28b26e12010-12-01 12:14:47 +01003652 if (hdsp->control_register & HDSP_SPDIFProfessional)
3653 snd_iprintf(buffer, "IEC958 quality: Professional\n");
3654 else
3655 snd_iprintf(buffer, "IEC958 quality: Consumer\n");
3656
3657 if (hdsp->control_register & HDSP_SPDIFEmphasis)
3658 snd_iprintf(buffer, "IEC958 emphasis: on\n");
3659 else
3660 snd_iprintf(buffer, "IEC958 emphasis: off\n");
3661
3662 if (hdsp->control_register & HDSP_SPDIFNonAudio)
3663 snd_iprintf(buffer, "IEC958 NonAudio: on\n");
3664 else
3665 snd_iprintf(buffer, "IEC958 NonAudio: off\n");
3666 x = hdsp_spdif_sample_rate(hdsp);
3667 if (x != 0)
3668 snd_iprintf(buffer, "IEC958 sample rate: %d\n", x);
3669 else
3670 snd_iprintf(buffer, "IEC958 sample rate: Error flag set\n");
3671 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672 snd_iprintf(buffer, "\n");
3673
3674 /* Sync Check */
3675 x = status & HDSP_Sync0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003676 if (status & HDSP_Lock0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677 snd_iprintf(buffer, "ADAT1: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003678 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679 snd_iprintf(buffer, "ADAT1: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680
3681 switch (hdsp->io_type) {
3682 case Digiface:
3683 case H9652:
3684 x = status & HDSP_Sync1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003685 if (status & HDSP_Lock1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686 snd_iprintf(buffer, "ADAT2: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003687 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003688 snd_iprintf(buffer, "ADAT2: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689 x = status & HDSP_Sync2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003690 if (status & HDSP_Lock2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003691 snd_iprintf(buffer, "ADAT3: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003692 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693 snd_iprintf(buffer, "ADAT3: No Lock\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003694 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695 default:
3696 /* relax */
3697 break;
3698 }
3699
3700 x = status & HDSP_SPDIFSync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003701 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702 snd_iprintf (buffer, "SPDIF: No Lock\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003703 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704 snd_iprintf (buffer, "SPDIF: %s\n", x ? "Sync" : "Lock");
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003705
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 x = status2 & HDSP_wc_sync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003707 if (status2 & HDSP_wc_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708 snd_iprintf (buffer, "Word Clock: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003709 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710 snd_iprintf (buffer, "Word Clock: No Lock\n");
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003711
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712 x = status & HDSP_TimecodeSync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003713 if (status & HDSP_TimecodeLock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714 snd_iprintf(buffer, "ADAT Sync: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003715 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716 snd_iprintf(buffer, "ADAT Sync: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003717
3718 snd_iprintf(buffer, "\n");
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003719
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720 /* Informations about H9632 specific controls */
3721 if (hdsp->io_type == H9632) {
3722 char *tmp;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003723
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724 switch (hdsp_ad_gain(hdsp)) {
3725 case 0:
3726 tmp = "-10 dBV";
3727 break;
3728 case 1:
3729 tmp = "+4 dBu";
3730 break;
3731 default:
3732 tmp = "Lo Gain";
3733 break;
3734 }
3735 snd_iprintf(buffer, "AD Gain : %s\n", tmp);
3736
3737 switch (hdsp_da_gain(hdsp)) {
3738 case 0:
3739 tmp = "Hi Gain";
3740 break;
3741 case 1:
3742 tmp = "+4 dBu";
3743 break;
3744 default:
3745 tmp = "-10 dBV";
3746 break;
3747 }
3748 snd_iprintf(buffer, "DA Gain : %s\n", tmp);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003749
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750 switch (hdsp_phone_gain(hdsp)) {
3751 case 0:
3752 tmp = "0 dB";
3753 break;
3754 case 1:
3755 tmp = "-6 dB";
3756 break;
3757 default:
3758 tmp = "-12 dB";
3759 break;
3760 }
3761 snd_iprintf(buffer, "Phones Gain : %s\n", tmp);
3762
Adrian Knoth4833c672013-01-15 18:52:22 +01003763 snd_iprintf(buffer, "XLR Breakout Cable : %s\n",
3764 hdsp_toggle_setting(hdsp, HDSP_XLRBreakoutCable) ?
3765 "yes" : "no");
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003766
Takashi Iwaib0b98112005-10-20 18:29:58 +02003767 if (hdsp->control_register & HDSP_AnalogExtensionBoard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768 snd_iprintf(buffer, "AEB : on (ADAT1 internal)\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003769 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770 snd_iprintf(buffer, "AEB : off (ADAT1 external)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771 snd_iprintf(buffer, "\n");
3772 }
3773
3774}
3775
Randy Dunlap1374f8c2008-01-16 14:55:42 +01003776static void snd_hdsp_proc_init(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003778 struct snd_info_entry *entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779
3780 if (! snd_card_proc_new(hdsp->card, "hdsp", &entry))
Takashi Iwaibf850202006-04-28 15:13:41 +02003781 snd_info_set_text_ops(entry, hdsp, snd_hdsp_proc_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782}
3783
Takashi Iwai55e957d2005-11-17 14:52:13 +01003784static void snd_hdsp_free_buffers(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785{
3786 snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci);
3787 snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
3788}
3789
Bill Pembertone23e7a12012-12-06 12:35:10 -05003790static int snd_hdsp_initialize_memory(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791{
3792 unsigned long pb_bus, cb_bus;
3793
3794 if (snd_hammerfall_get_buffer(hdsp->pci, &hdsp->capture_dma_buf, HDSP_DMA_AREA_BYTES) < 0 ||
3795 snd_hammerfall_get_buffer(hdsp->pci, &hdsp->playback_dma_buf, HDSP_DMA_AREA_BYTES) < 0) {
3796 if (hdsp->capture_dma_buf.area)
3797 snd_dma_free_pages(&hdsp->capture_dma_buf);
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01003798 dev_err(hdsp->card->dev,
3799 "%s: no buffers available\n", hdsp->card_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800 return -ENOMEM;
3801 }
3802
3803 /* Align to bus-space 64K boundary */
3804
Clemens Ladisch7ab39922006-10-09 08:13:32 +02003805 cb_bus = ALIGN(hdsp->capture_dma_buf.addr, 0x10000ul);
3806 pb_bus = ALIGN(hdsp->playback_dma_buf.addr, 0x10000ul);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807
3808 /* Tell the card where it is */
3809
3810 hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus);
3811 hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus);
3812
3813 hdsp->capture_buffer = hdsp->capture_dma_buf.area + (cb_bus - hdsp->capture_dma_buf.addr);
3814 hdsp->playback_buffer = hdsp->playback_dma_buf.area + (pb_bus - hdsp->playback_dma_buf.addr);
3815
3816 return 0;
3817}
3818
Takashi Iwai55e957d2005-11-17 14:52:13 +01003819static int snd_hdsp_set_defaults(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003820{
3821 unsigned int i;
3822
3823 /* ASSUMPTION: hdsp->lock is either held, or
3824 there is no need to hold it (e.g. during module
Joe Perches561de312007-12-18 13:13:47 +01003825 initialization).
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826 */
3827
3828 /* set defaults:
3829
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003830 SPDIF Input via Coax
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831 Master clock mode
3832 maximum latency (7 => 2^7 = 8192 samples, 64Kbyte buffer,
3833 which implies 2 4096 sample, 32Kbyte periods).
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003834 Enable line out.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835 */
3836
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003837 hdsp->control_register = HDSP_ClockModeMaster |
3838 HDSP_SPDIFInputCoaxial |
3839 hdsp_encode_latency(7) |
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840 HDSP_LineOut;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003841
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842
3843 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3844
3845#ifdef SNDRV_BIG_ENDIAN
3846 hdsp->control2_register = HDSP_BIGENDIAN_MODE;
3847#else
3848 hdsp->control2_register = 0;
3849#endif
Takashi Iwaib0b98112005-10-20 18:29:58 +02003850 if (hdsp->io_type == H9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851 snd_hdsp_9652_enable_mixer (hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003852 else
3853 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854
3855 hdsp_reset_hw_pointer(hdsp);
3856 hdsp_compute_period_size(hdsp);
3857
3858 /* silence everything */
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003859
Takashi Iwaib0b98112005-10-20 18:29:58 +02003860 for (i = 0; i < HDSP_MATRIX_MIXER_SIZE; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861 hdsp->mixer_matrix[i] = MINUS_INFINITY_GAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862
3863 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 +02003864 if (hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003867
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868 /* H9632 specific defaults */
3869 if (hdsp->io_type == H9632) {
3870 hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB);
3871 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3872 }
3873
3874 /* set a default rate so that the channel map is set up.
3875 */
3876
3877 hdsp_set_rate(hdsp, 48000, 1);
3878
3879 return 0;
3880}
3881
3882static void hdsp_midi_tasklet(unsigned long arg)
3883{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003884 struct hdsp *hdsp = (struct hdsp *)arg;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003885
Takashi Iwaib0b98112005-10-20 18:29:58 +02003886 if (hdsp->midi[0].pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887 snd_hdsp_midi_input_read (&hdsp->midi[0]);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003888 if (hdsp->midi[1].pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 snd_hdsp_midi_input_read (&hdsp->midi[1]);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003890}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891
David Howells7d12e782006-10-05 14:55:46 +01003892static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003894 struct hdsp *hdsp = (struct hdsp *) dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 unsigned int status;
3896 int audio;
3897 int midi0;
3898 int midi1;
3899 unsigned int midi0status;
3900 unsigned int midi1status;
3901 int schedule = 0;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003902
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903 status = hdsp_read(hdsp, HDSP_statusRegister);
3904
3905 audio = status & HDSP_audioIRQPending;
3906 midi0 = status & HDSP_midi0IRQPending;
3907 midi1 = status & HDSP_midi1IRQPending;
3908
Takashi Iwaib0b98112005-10-20 18:29:58 +02003909 if (!audio && !midi0 && !midi1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910 return IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911
3912 hdsp_write(hdsp, HDSP_interruptConfirmation, 0);
3913
3914 midi0status = hdsp_read (hdsp, HDSP_midiStatusIn0) & 0xff;
3915 midi1status = hdsp_read (hdsp, HDSP_midiStatusIn1) & 0xff;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003916
Takashi Iwaic2503cd2009-03-05 09:37:40 +01003917 if (!(hdsp->state & HDSP_InitializationComplete))
3918 return IRQ_HANDLED;
3919
Linus Torvalds1da177e2005-04-16 15:20:36 -07003920 if (audio) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003921 if (hdsp->capture_substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922 snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003923
Takashi Iwaib0b98112005-10-20 18:29:58 +02003924 if (hdsp->playback_substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925 snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003927
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928 if (midi0 && midi0status) {
3929 if (hdsp->use_midi_tasklet) {
3930 /* we disable interrupts for this input until processing is done */
3931 hdsp->control_register &= ~HDSP_Midi0InterruptEnable;
3932 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3933 hdsp->midi[0].pending = 1;
3934 schedule = 1;
3935 } else {
3936 snd_hdsp_midi_input_read (&hdsp->midi[0]);
3937 }
3938 }
Florian Faber28b26e12010-12-01 12:14:47 +01003939 if (hdsp->io_type != Multiface && hdsp->io_type != RPM && hdsp->io_type != H9632 && midi1 && midi1status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940 if (hdsp->use_midi_tasklet) {
3941 /* we disable interrupts for this input until processing is done */
3942 hdsp->control_register &= ~HDSP_Midi1InterruptEnable;
3943 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3944 hdsp->midi[1].pending = 1;
3945 schedule = 1;
3946 } else {
3947 snd_hdsp_midi_input_read (&hdsp->midi[1]);
3948 }
3949 }
3950 if (hdsp->use_midi_tasklet && schedule)
Takashi Iwai1f041282008-12-18 12:17:55 +01003951 tasklet_schedule(&hdsp->midi_tasklet);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952 return IRQ_HANDLED;
3953}
3954
Takashi Iwai55e957d2005-11-17 14:52:13 +01003955static snd_pcm_uframes_t snd_hdsp_hw_pointer(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003957 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 return hdsp_hw_pointer(hdsp);
3959}
3960
Takashi Iwai55e957d2005-11-17 14:52:13 +01003961static char *hdsp_channel_buffer_location(struct hdsp *hdsp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962 int stream,
3963 int channel)
3964
3965{
3966 int mapped_channel;
3967
Takashi Iwaida3cec32008-08-08 17:12:14 +02003968 if (snd_BUG_ON(channel < 0 || channel >= hdsp->max_channels))
3969 return NULL;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003970
Takashi Iwaib0b98112005-10-20 18:29:58 +02003971 if ((mapped_channel = hdsp->channel_map[channel]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972 return NULL;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01003973
Takashi Iwaib0b98112005-10-20 18:29:58 +02003974 if (stream == SNDRV_PCM_STREAM_CAPTURE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975 return hdsp->capture_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003976 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977 return hdsp->playback_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978}
3979
Takashi Iwai55e957d2005-11-17 14:52:13 +01003980static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981 snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
3982{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003983 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984 char *channel_buf;
3985
Takashi Iwaida3cec32008-08-08 17:12:14 +02003986 if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4))
3987 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988
3989 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
Takashi Iwaida3cec32008-08-08 17:12:14 +02003990 if (snd_BUG_ON(!channel_buf))
3991 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992 if (copy_from_user(channel_buf + pos * 4, src, count * 4))
3993 return -EFAULT;
3994 return count;
3995}
3996
Takashi Iwai55e957d2005-11-17 14:52:13 +01003997static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998 snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count)
3999{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004000 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001 char *channel_buf;
4002
Takashi Iwaida3cec32008-08-08 17:12:14 +02004003 if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4))
4004 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005
4006 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
Takashi Iwaida3cec32008-08-08 17:12:14 +02004007 if (snd_BUG_ON(!channel_buf))
4008 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
4010 return -EFAULT;
4011 return count;
4012}
4013
Takashi Iwai55e957d2005-11-17 14:52:13 +01004014static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015 snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
4016{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004017 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018 char *channel_buf;
4019
4020 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
Takashi Iwaida3cec32008-08-08 17:12:14 +02004021 if (snd_BUG_ON(!channel_buf))
4022 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023 memset(channel_buf + pos * 4, 0, count * 4);
4024 return count;
4025}
4026
Takashi Iwai55e957d2005-11-17 14:52:13 +01004027static int snd_hdsp_reset(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004029 struct snd_pcm_runtime *runtime = substream->runtime;
4030 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4031 struct snd_pcm_substream *other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
4033 other = hdsp->capture_substream;
4034 else
4035 other = hdsp->playback_substream;
4036 if (hdsp->running)
4037 runtime->status->hw_ptr = hdsp_hw_pointer(hdsp);
4038 else
4039 runtime->status->hw_ptr = 0;
4040 if (other) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004041 struct snd_pcm_substream *s;
4042 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01004043 snd_pcm_group_for_each_entry(s, substream) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044 if (s == other) {
4045 oruntime->status->hw_ptr = runtime->status->hw_ptr;
4046 break;
4047 }
4048 }
4049 }
4050 return 0;
4051}
4052
Takashi Iwai55e957d2005-11-17 14:52:13 +01004053static int snd_hdsp_hw_params(struct snd_pcm_substream *substream,
4054 struct snd_pcm_hw_params *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004056 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057 int err;
4058 pid_t this_pid;
4059 pid_t other_pid;
4060
Takashi Iwaib0b98112005-10-20 18:29:58 +02004061 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004062 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063
Takashi Iwaib0b98112005-10-20 18:29:58 +02004064 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066
4067 spin_lock_irq(&hdsp->lock);
4068
4069 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
4070 hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
4071 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= hdsp->creg_spdif_stream);
4072 this_pid = hdsp->playback_pid;
4073 other_pid = hdsp->capture_pid;
4074 } else {
4075 this_pid = hdsp->capture_pid;
4076 other_pid = hdsp->playback_pid;
4077 }
4078
4079 if ((other_pid > 0) && (this_pid != other_pid)) {
4080
4081 /* The other stream is open, and not by the same
4082 task as this one. Make sure that the parameters
4083 that matter are the same.
4084 */
4085
4086 if (params_rate(params) != hdsp->system_sample_rate) {
4087 spin_unlock_irq(&hdsp->lock);
4088 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
4089 return -EBUSY;
4090 }
4091
4092 if (params_period_size(params) != hdsp->period_bytes / 4) {
4093 spin_unlock_irq(&hdsp->lock);
4094 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
4095 return -EBUSY;
4096 }
4097
4098 /* We're fine. */
4099
4100 spin_unlock_irq(&hdsp->lock);
4101 return 0;
4102
4103 } else {
4104 spin_unlock_irq(&hdsp->lock);
4105 }
4106
4107 /* how to make sure that the rate matches an externally-set one ?
4108 */
4109
4110 spin_lock_irq(&hdsp->lock);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02004111 if (! hdsp->clock_source_locked) {
4112 if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) {
4113 spin_unlock_irq(&hdsp->lock);
4114 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
4115 return err;
4116 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117 }
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02004118 spin_unlock_irq(&hdsp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119
4120 if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) {
4121 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
4122 return err;
4123 }
4124
4125 return 0;
4126}
4127
Takashi Iwai55e957d2005-11-17 14:52:13 +01004128static int snd_hdsp_channel_info(struct snd_pcm_substream *substream,
4129 struct snd_pcm_channel_info *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004131 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132 int mapped_channel;
4133
Takashi Iwaida3cec32008-08-08 17:12:14 +02004134 if (snd_BUG_ON(info->channel >= hdsp->max_channels))
4135 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136
Takashi Iwaib0b98112005-10-20 18:29:58 +02004137 if ((mapped_channel = hdsp->channel_map[info->channel]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139
4140 info->offset = mapped_channel * HDSP_CHANNEL_BUFFER_BYTES;
4141 info->first = 0;
4142 info->step = 32;
4143 return 0;
4144}
4145
Takashi Iwai55e957d2005-11-17 14:52:13 +01004146static int snd_hdsp_ioctl(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147 unsigned int cmd, void *arg)
4148{
4149 switch (cmd) {
4150 case SNDRV_PCM_IOCTL1_RESET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 return snd_hdsp_reset(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Takashi Iwaib0b98112005-10-20 18:29:58 +02004153 return snd_hdsp_channel_info(substream, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154 default:
4155 break;
4156 }
4157
4158 return snd_pcm_lib_ioctl(substream, cmd, arg);
4159}
4160
Takashi Iwai55e957d2005-11-17 14:52:13 +01004161static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004163 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4164 struct snd_pcm_substream *other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165 int running;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004166
Takashi Iwaib0b98112005-10-20 18:29:58 +02004167 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169
Takashi Iwai311e70a2006-09-06 12:13:37 +02004170 if (hdsp_check_for_firmware(hdsp, 0)) /* no auto-loading in trigger */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172
4173 spin_lock(&hdsp->lock);
4174 running = hdsp->running;
4175 switch (cmd) {
4176 case SNDRV_PCM_TRIGGER_START:
4177 running |= 1 << substream->stream;
4178 break;
4179 case SNDRV_PCM_TRIGGER_STOP:
4180 running &= ~(1 << substream->stream);
4181 break;
4182 default:
4183 snd_BUG();
4184 spin_unlock(&hdsp->lock);
4185 return -EINVAL;
4186 }
4187 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
4188 other = hdsp->capture_substream;
4189 else
4190 other = hdsp->playback_substream;
4191
4192 if (other) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004193 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01004194 snd_pcm_group_for_each_entry(s, substream) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195 if (s == other) {
4196 snd_pcm_trigger_done(s, substream);
4197 if (cmd == SNDRV_PCM_TRIGGER_START)
4198 running |= 1 << s->stream;
4199 else
4200 running &= ~(1 << s->stream);
4201 goto _ok;
4202 }
4203 }
4204 if (cmd == SNDRV_PCM_TRIGGER_START) {
4205 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) &&
4206 substream->stream == SNDRV_PCM_STREAM_CAPTURE)
4207 hdsp_silence_playback(hdsp);
4208 } else {
4209 if (running &&
4210 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
4211 hdsp_silence_playback(hdsp);
4212 }
4213 } else {
4214 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
4215 hdsp_silence_playback(hdsp);
4216 }
4217 _ok:
4218 snd_pcm_trigger_done(substream, substream);
4219 if (!hdsp->running && running)
4220 hdsp_start_audio(hdsp);
4221 else if (hdsp->running && !running)
4222 hdsp_stop_audio(hdsp);
4223 hdsp->running = running;
4224 spin_unlock(&hdsp->lock);
4225
4226 return 0;
4227}
4228
Takashi Iwai55e957d2005-11-17 14:52:13 +01004229static int snd_hdsp_prepare(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004231 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232 int result = 0;
4233
Takashi Iwaib0b98112005-10-20 18:29:58 +02004234 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236
Takashi Iwaib0b98112005-10-20 18:29:58 +02004237 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239
4240 spin_lock_irq(&hdsp->lock);
4241 if (!hdsp->running)
4242 hdsp_reset_hw_pointer(hdsp);
4243 spin_unlock_irq(&hdsp->lock);
4244 return result;
4245}
4246
Takashi Iwai55e957d2005-11-17 14:52:13 +01004247static struct snd_pcm_hardware snd_hdsp_playback_subinfo =
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248{
4249 .info = (SNDRV_PCM_INFO_MMAP |
4250 SNDRV_PCM_INFO_MMAP_VALID |
4251 SNDRV_PCM_INFO_NONINTERLEAVED |
4252 SNDRV_PCM_INFO_SYNC_START |
4253 SNDRV_PCM_INFO_DOUBLE),
4254#ifdef SNDRV_BIG_ENDIAN
4255 .formats = SNDRV_PCM_FMTBIT_S32_BE,
4256#else
4257 .formats = SNDRV_PCM_FMTBIT_S32_LE,
4258#endif
4259 .rates = (SNDRV_PCM_RATE_32000 |
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004260 SNDRV_PCM_RATE_44100 |
4261 SNDRV_PCM_RATE_48000 |
4262 SNDRV_PCM_RATE_64000 |
4263 SNDRV_PCM_RATE_88200 |
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264 SNDRV_PCM_RATE_96000),
4265 .rate_min = 32000,
4266 .rate_max = 96000,
Florian Faber28b26e12010-12-01 12:14:47 +01004267 .channels_min = 6,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268 .channels_max = HDSP_MAX_CHANNELS,
4269 .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS,
4270 .period_bytes_min = (64 * 4) * 10,
4271 .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS,
4272 .periods_min = 2,
4273 .periods_max = 2,
4274 .fifo_size = 0
4275};
4276
Takashi Iwai55e957d2005-11-17 14:52:13 +01004277static struct snd_pcm_hardware snd_hdsp_capture_subinfo =
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278{
4279 .info = (SNDRV_PCM_INFO_MMAP |
4280 SNDRV_PCM_INFO_MMAP_VALID |
4281 SNDRV_PCM_INFO_NONINTERLEAVED |
4282 SNDRV_PCM_INFO_SYNC_START),
4283#ifdef SNDRV_BIG_ENDIAN
4284 .formats = SNDRV_PCM_FMTBIT_S32_BE,
4285#else
4286 .formats = SNDRV_PCM_FMTBIT_S32_LE,
4287#endif
4288 .rates = (SNDRV_PCM_RATE_32000 |
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004289 SNDRV_PCM_RATE_44100 |
4290 SNDRV_PCM_RATE_48000 |
4291 SNDRV_PCM_RATE_64000 |
4292 SNDRV_PCM_RATE_88200 |
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293 SNDRV_PCM_RATE_96000),
4294 .rate_min = 32000,
4295 .rate_max = 96000,
Florian Faber28b26e12010-12-01 12:14:47 +01004296 .channels_min = 5,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297 .channels_max = HDSP_MAX_CHANNELS,
4298 .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS,
4299 .period_bytes_min = (64 * 4) * 10,
4300 .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS,
4301 .periods_min = 2,
4302 .periods_max = 2,
4303 .fifo_size = 0
4304};
4305
4306static unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
4307
Takashi Iwai55e957d2005-11-17 14:52:13 +01004308static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_period_sizes = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309 .count = ARRAY_SIZE(hdsp_period_sizes),
4310 .list = hdsp_period_sizes,
4311 .mask = 0
4312};
4313
4314static unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 };
4315
Takashi Iwai55e957d2005-11-17 14:52:13 +01004316static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_9632_sample_rates = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317 .count = ARRAY_SIZE(hdsp_9632_sample_rates),
4318 .list = hdsp_9632_sample_rates,
4319 .mask = 0
4320};
4321
Takashi Iwai55e957d2005-11-17 14:52:13 +01004322static int snd_hdsp_hw_rule_in_channels(struct snd_pcm_hw_params *params,
4323 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004325 struct hdsp *hdsp = rule->private;
4326 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327 if (hdsp->io_type == H9632) {
4328 unsigned int list[3];
4329 list[0] = hdsp->qs_in_channels;
4330 list[1] = hdsp->ds_in_channels;
4331 list[2] = hdsp->ss_in_channels;
4332 return snd_interval_list(c, 3, list, 0);
4333 } else {
4334 unsigned int list[2];
4335 list[0] = hdsp->ds_in_channels;
4336 list[1] = hdsp->ss_in_channels;
4337 return snd_interval_list(c, 2, list, 0);
4338 }
4339}
4340
Takashi Iwai55e957d2005-11-17 14:52:13 +01004341static int snd_hdsp_hw_rule_out_channels(struct snd_pcm_hw_params *params,
4342 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343{
4344 unsigned int list[3];
Takashi Iwai55e957d2005-11-17 14:52:13 +01004345 struct hdsp *hdsp = rule->private;
4346 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347 if (hdsp->io_type == H9632) {
4348 list[0] = hdsp->qs_out_channels;
4349 list[1] = hdsp->ds_out_channels;
4350 list[2] = hdsp->ss_out_channels;
4351 return snd_interval_list(c, 3, list, 0);
4352 } else {
4353 list[0] = hdsp->ds_out_channels;
4354 list[1] = hdsp->ss_out_channels;
4355 }
4356 return snd_interval_list(c, 2, list, 0);
4357}
4358
Takashi Iwai55e957d2005-11-17 14:52:13 +01004359static int snd_hdsp_hw_rule_in_channels_rate(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 (r->min > 96000 && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004366 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367 .min = hdsp->qs_in_channels,
4368 .max = hdsp->qs_in_channels,
4369 .integer = 1,
4370 };
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004371 return snd_interval_refine(c, &t);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372 } else if (r->min > 48000 && r->max <= 96000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004373 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374 .min = hdsp->ds_in_channels,
4375 .max = hdsp->ds_in_channels,
4376 .integer = 1,
4377 };
4378 return snd_interval_refine(c, &t);
4379 } else if (r->max < 64000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004380 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004381 .min = hdsp->ss_in_channels,
4382 .max = hdsp->ss_in_channels,
4383 .integer = 1,
4384 };
4385 return snd_interval_refine(c, &t);
4386 }
4387 return 0;
4388}
4389
Takashi Iwai55e957d2005-11-17 14:52:13 +01004390static int snd_hdsp_hw_rule_out_channels_rate(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 (r->min > 96000 && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004397 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 .min = hdsp->qs_out_channels,
4399 .max = hdsp->qs_out_channels,
4400 .integer = 1,
4401 };
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004402 return snd_interval_refine(c, &t);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403 } else if (r->min > 48000 && r->max <= 96000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004404 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405 .min = hdsp->ds_out_channels,
4406 .max = hdsp->ds_out_channels,
4407 .integer = 1,
4408 };
4409 return snd_interval_refine(c, &t);
4410 } else if (r->max < 64000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004411 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412 .min = hdsp->ss_out_channels,
4413 .max = hdsp->ss_out_channels,
4414 .integer = 1,
4415 };
4416 return snd_interval_refine(c, &t);
4417 }
4418 return 0;
4419}
4420
Takashi Iwai55e957d2005-11-17 14:52:13 +01004421static int snd_hdsp_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
4422 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004424 struct hdsp *hdsp = rule->private;
4425 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4426 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427 if (c->min >= hdsp->ss_out_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004428 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429 .min = 32000,
4430 .max = 48000,
4431 .integer = 1,
4432 };
4433 return snd_interval_refine(r, &t);
4434 } else if (c->max <= hdsp->qs_out_channels && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004435 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436 .min = 128000,
4437 .max = 192000,
4438 .integer = 1,
4439 };
4440 return snd_interval_refine(r, &t);
4441 } else if (c->max <= hdsp->ds_out_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004442 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443 .min = 64000,
4444 .max = 96000,
4445 .integer = 1,
4446 };
4447 return snd_interval_refine(r, &t);
4448 }
4449 return 0;
4450}
4451
Takashi Iwai55e957d2005-11-17 14:52:13 +01004452static int snd_hdsp_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
4453 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004455 struct hdsp *hdsp = rule->private;
4456 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4457 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004458 if (c->min >= hdsp->ss_in_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004459 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004460 .min = 32000,
4461 .max = 48000,
4462 .integer = 1,
4463 };
4464 return snd_interval_refine(r, &t);
4465 } else if (c->max <= hdsp->qs_in_channels && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004466 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467 .min = 128000,
4468 .max = 192000,
4469 .integer = 1,
4470 };
4471 return snd_interval_refine(r, &t);
4472 } else if (c->max <= hdsp->ds_in_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004473 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474 .min = 64000,
4475 .max = 96000,
4476 .integer = 1,
4477 };
4478 return snd_interval_refine(r, &t);
4479 }
4480 return 0;
4481}
4482
Takashi Iwai55e957d2005-11-17 14:52:13 +01004483static int snd_hdsp_playback_open(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004484{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004485 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4486 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487
Takashi Iwaib0b98112005-10-20 18:29:58 +02004488 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004489 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490
Takashi Iwaib0b98112005-10-20 18:29:58 +02004491 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493
4494 spin_lock_irq(&hdsp->lock);
4495
4496 snd_pcm_set_sync(substream);
4497
4498 runtime->hw = snd_hdsp_playback_subinfo;
4499 runtime->dma_area = hdsp->playback_buffer;
4500 runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
4501
4502 hdsp->playback_pid = current->pid;
4503 hdsp->playback_substream = substream;
4504
4505 spin_unlock_irq(&hdsp->lock);
4506
4507 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4508 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 +02004509 if (hdsp->clock_source_locked) {
4510 runtime->hw.rate_min = runtime->hw.rate_max = hdsp->system_sample_rate;
4511 } else if (hdsp->io_type == H9632) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512 runtime->hw.rate_max = 192000;
4513 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
4514 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates);
4515 }
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02004516 if (hdsp->io_type == H9632) {
4517 runtime->hw.channels_min = hdsp->qs_out_channels;
4518 runtime->hw.channels_max = hdsp->ss_out_channels;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004519 }
4520
Linus Torvalds1da177e2005-04-16 15:20:36 -07004521 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4522 snd_hdsp_hw_rule_out_channels, hdsp,
4523 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4524 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4525 snd_hdsp_hw_rule_out_channels_rate, hdsp,
4526 SNDRV_PCM_HW_PARAM_RATE, -1);
4527 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4528 snd_hdsp_hw_rule_rate_out_channels, hdsp,
4529 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4530
Florian Faber28b26e12010-12-01 12:14:47 +01004531 if (RPM != hdsp->io_type) {
4532 hdsp->creg_spdif_stream = hdsp->creg_spdif;
4533 hdsp->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
4534 snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
4535 SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id);
4536 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004537 return 0;
4538}
4539
Takashi Iwai55e957d2005-11-17 14:52:13 +01004540static int snd_hdsp_playback_release(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004542 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004543
4544 spin_lock_irq(&hdsp->lock);
4545
4546 hdsp->playback_pid = -1;
4547 hdsp->playback_substream = NULL;
4548
4549 spin_unlock_irq(&hdsp->lock);
4550
Florian Faber28b26e12010-12-01 12:14:47 +01004551 if (RPM != hdsp->io_type) {
4552 hdsp->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
4553 snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
4554 SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id);
4555 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004556 return 0;
4557}
4558
4559
Takashi Iwai55e957d2005-11-17 14:52:13 +01004560static int snd_hdsp_capture_open(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004561{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004562 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4563 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564
Takashi Iwaib0b98112005-10-20 18:29:58 +02004565 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004567
Takashi Iwaib0b98112005-10-20 18:29:58 +02004568 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004569 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004570
4571 spin_lock_irq(&hdsp->lock);
4572
4573 snd_pcm_set_sync(substream);
4574
4575 runtime->hw = snd_hdsp_capture_subinfo;
4576 runtime->dma_area = hdsp->capture_buffer;
4577 runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
4578
4579 hdsp->capture_pid = current->pid;
4580 hdsp->capture_substream = substream;
4581
4582 spin_unlock_irq(&hdsp->lock);
4583
4584 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4585 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes);
4586 if (hdsp->io_type == H9632) {
4587 runtime->hw.channels_min = hdsp->qs_in_channels;
4588 runtime->hw.channels_max = hdsp->ss_in_channels;
4589 runtime->hw.rate_max = 192000;
4590 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
4591 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates);
4592 }
4593 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4594 snd_hdsp_hw_rule_in_channels, hdsp,
4595 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4596 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4597 snd_hdsp_hw_rule_in_channels_rate, hdsp,
4598 SNDRV_PCM_HW_PARAM_RATE, -1);
4599 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4600 snd_hdsp_hw_rule_rate_in_channels, hdsp,
4601 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4602 return 0;
4603}
4604
Takashi Iwai55e957d2005-11-17 14:52:13 +01004605static int snd_hdsp_capture_release(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004606{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004607 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004608
4609 spin_lock_irq(&hdsp->lock);
4610
4611 hdsp->capture_pid = -1;
4612 hdsp->capture_substream = NULL;
4613
4614 spin_unlock_irq(&hdsp->lock);
4615 return 0;
4616}
4617
Linus Torvalds1da177e2005-04-16 15:20:36 -07004618/* helper functions for copying meter values */
4619static inline int copy_u32_le(void __user *dest, void __iomem *src)
4620{
4621 u32 val = readl(src);
4622 return copy_to_user(dest, &val, 4);
4623}
4624
4625static inline int copy_u64_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
4626{
4627 u32 rms_low, rms_high;
4628 u64 rms;
4629 rms_low = readl(src_low);
4630 rms_high = readl(src_high);
4631 rms = ((u64)rms_high << 32) | rms_low;
4632 return copy_to_user(dest, &rms, 8);
4633}
4634
4635static inline int copy_u48_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
4636{
4637 u32 rms_low, rms_high;
4638 u64 rms;
4639 rms_low = readl(src_low) & 0xffffff00;
4640 rms_high = readl(src_high) & 0xffffff00;
4641 rms = ((u64)rms_high << 32) | rms_low;
4642 return copy_to_user(dest, &rms, 8);
4643}
4644
Takashi Iwai55e957d2005-11-17 14:52:13 +01004645static int hdsp_9652_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004646{
4647 int doublespeed = 0;
4648 int i, j, channels, ofs;
4649
4650 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
4651 doublespeed = 1;
4652 channels = doublespeed ? 14 : 26;
4653 for (i = 0, j = 0; i < 26; ++i) {
4654 if (doublespeed && (i & 4))
4655 continue;
4656 ofs = HDSP_9652_peakBase - j * 4;
4657 if (copy_u32_le(&peak_rms->input_peaks[i], hdsp->iobase + ofs))
4658 return -EFAULT;
4659 ofs -= channels * 4;
4660 if (copy_u32_le(&peak_rms->playback_peaks[i], hdsp->iobase + ofs))
4661 return -EFAULT;
4662 ofs -= channels * 4;
4663 if (copy_u32_le(&peak_rms->output_peaks[i], hdsp->iobase + ofs))
4664 return -EFAULT;
4665 ofs = HDSP_9652_rmsBase + j * 8;
4666 if (copy_u48_le(&peak_rms->input_rms[i], hdsp->iobase + ofs,
4667 hdsp->iobase + ofs + 4))
4668 return -EFAULT;
4669 ofs += channels * 8;
4670 if (copy_u48_le(&peak_rms->playback_rms[i], hdsp->iobase + ofs,
4671 hdsp->iobase + ofs + 4))
4672 return -EFAULT;
4673 ofs += channels * 8;
4674 if (copy_u48_le(&peak_rms->output_rms[i], hdsp->iobase + ofs,
4675 hdsp->iobase + ofs + 4))
4676 return -EFAULT;
4677 j++;
4678 }
4679 return 0;
4680}
4681
Takashi Iwai55e957d2005-11-17 14:52:13 +01004682static int hdsp_9632_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004683{
4684 int i, j;
Takashi Iwai55e957d2005-11-17 14:52:13 +01004685 struct hdsp_9632_meters __iomem *m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004686 int doublespeed = 0;
4687
4688 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
4689 doublespeed = 1;
Takashi Iwai55e957d2005-11-17 14:52:13 +01004690 m = (struct hdsp_9632_meters __iomem *)(hdsp->iobase+HDSP_9632_metersBase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004691 for (i = 0, j = 0; i < 16; ++i, ++j) {
4692 if (copy_u32_le(&peak_rms->input_peaks[i], &m->input_peak[j]))
4693 return -EFAULT;
4694 if (copy_u32_le(&peak_rms->playback_peaks[i], &m->playback_peak[j]))
4695 return -EFAULT;
4696 if (copy_u32_le(&peak_rms->output_peaks[i], &m->output_peak[j]))
4697 return -EFAULT;
4698 if (copy_u64_le(&peak_rms->input_rms[i], &m->input_rms_low[j],
4699 &m->input_rms_high[j]))
4700 return -EFAULT;
4701 if (copy_u64_le(&peak_rms->playback_rms[i], &m->playback_rms_low[j],
4702 &m->playback_rms_high[j]))
4703 return -EFAULT;
4704 if (copy_u64_le(&peak_rms->output_rms[i], &m->output_rms_low[j],
4705 &m->output_rms_high[j]))
4706 return -EFAULT;
4707 if (doublespeed && i == 3) i += 4;
4708 }
4709 return 0;
4710}
4711
Takashi Iwai55e957d2005-11-17 14:52:13 +01004712static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004713{
4714 int i;
4715
4716 for (i = 0; i < 26; i++) {
4717 if (copy_u32_le(&peak_rms->playback_peaks[i],
4718 hdsp->iobase + HDSP_playbackPeakLevel + i * 4))
4719 return -EFAULT;
4720 if (copy_u32_le(&peak_rms->input_peaks[i],
4721 hdsp->iobase + HDSP_inputPeakLevel + i * 4))
4722 return -EFAULT;
4723 }
4724 for (i = 0; i < 28; i++) {
4725 if (copy_u32_le(&peak_rms->output_peaks[i],
4726 hdsp->iobase + HDSP_outputPeakLevel + i * 4))
4727 return -EFAULT;
4728 }
4729 for (i = 0; i < 26; ++i) {
4730 if (copy_u64_le(&peak_rms->playback_rms[i],
4731 hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4,
4732 hdsp->iobase + HDSP_playbackRmsLevel + i * 8))
4733 return -EFAULT;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004734 if (copy_u64_le(&peak_rms->input_rms[i],
Linus Torvalds1da177e2005-04-16 15:20:36 -07004735 hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4,
4736 hdsp->iobase + HDSP_inputRmsLevel + i * 8))
4737 return -EFAULT;
4738 }
4739 return 0;
4740}
4741
Takashi Iwai55e957d2005-11-17 14:52:13 +01004742static 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 -07004743{
Joe Perches9fe856e2010-09-04 18:52:54 -07004744 struct hdsp *hdsp = hw->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004745 void __user *argp = (void __user *)arg;
Tim Blechmann3ae7e2e2008-11-08 14:42:18 +01004746 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004747
4748 switch (cmd) {
4749 case SNDRV_HDSP_IOCTL_GET_PEAK_RMS: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004750 struct hdsp_peak_rms __user *peak_rms = (struct hdsp_peak_rms __user *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004751
Tim Blechmann3ae7e2e2008-11-08 14:42:18 +01004752 err = hdsp_check_for_iobox(hdsp);
4753 if (err < 0)
4754 return err;
4755
4756 err = hdsp_check_for_firmware(hdsp, 1);
4757 if (err < 0)
4758 return err;
4759
Linus Torvalds1da177e2005-04-16 15:20:36 -07004760 if (!(hdsp->state & HDSP_FirmwareLoaded)) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01004761 dev_err(hdsp->card->dev,
4762 "firmware needs to be uploaded to the card.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004763 return -EINVAL;
4764 }
4765
4766 switch (hdsp->io_type) {
4767 case H9652:
4768 return hdsp_9652_get_peak(hdsp, peak_rms);
4769 case H9632:
4770 return hdsp_9632_get_peak(hdsp, peak_rms);
4771 default:
4772 return hdsp_get_peak(hdsp, peak_rms);
4773 }
4774 }
4775 case SNDRV_HDSP_IOCTL_GET_CONFIG_INFO: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004776 struct hdsp_config_info info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004777 unsigned long flags;
4778 int i;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004779
Tim Blechmann3ae7e2e2008-11-08 14:42:18 +01004780 err = hdsp_check_for_iobox(hdsp);
4781 if (err < 0)
4782 return err;
4783
4784 err = hdsp_check_for_firmware(hdsp, 1);
4785 if (err < 0)
4786 return err;
4787
Dan Rosenberge68d3b32010-09-25 11:07:27 -04004788 memset(&info, 0, sizeof(info));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004789 spin_lock_irqsave(&hdsp->lock, flags);
4790 info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp);
4791 info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02004792 if (hdsp->io_type != H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004793 info.adatsync_sync_check = (unsigned char)hdsp_adatsync_sync_check(hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004794 info.spdif_sync_check = (unsigned char)hdsp_spdif_sync_check(hdsp);
Florian Faber28b26e12010-12-01 12:14:47 +01004795 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 -07004796 info.adat_sync_check[i] = (unsigned char)hdsp_adat_sync_check(hdsp, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004797 info.spdif_in = (unsigned char)hdsp_spdif_in(hdsp);
Adrian Knoth4833c672013-01-15 18:52:22 +01004798 info.spdif_out = (unsigned char)hdsp_toggle_setting(hdsp,
4799 HDSP_SPDIFOpticalOut);
4800 info.spdif_professional = (unsigned char)
4801 hdsp_toggle_setting(hdsp, HDSP_SPDIFProfessional);
4802 info.spdif_emphasis = (unsigned char)
4803 hdsp_toggle_setting(hdsp, HDSP_SPDIFEmphasis);
4804 info.spdif_nonaudio = (unsigned char)
4805 hdsp_toggle_setting(hdsp, HDSP_SPDIFNonAudio);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004806 info.spdif_sample_rate = hdsp_spdif_sample_rate(hdsp);
4807 info.system_sample_rate = hdsp->system_sample_rate;
4808 info.autosync_sample_rate = hdsp_external_sample_rate(hdsp);
4809 info.system_clock_mode = (unsigned char)hdsp_system_clock_mode(hdsp);
4810 info.clock_source = (unsigned char)hdsp_clock_source(hdsp);
4811 info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp);
Adrian Knoth4833c672013-01-15 18:52:22 +01004812 info.line_out = (unsigned char)
4813 hdsp_toggle_setting(hdsp, HDSP_LineOut);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004814 if (hdsp->io_type == H9632) {
4815 info.da_gain = (unsigned char)hdsp_da_gain(hdsp);
4816 info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp);
4817 info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp);
Adrian Knoth4833c672013-01-15 18:52:22 +01004818 info.xlr_breakout_cable =
4819 (unsigned char)hdsp_toggle_setting(hdsp,
4820 HDSP_XLRBreakoutCable);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004821
Florian Faber28b26e12010-12-01 12:14:47 +01004822 } else if (hdsp->io_type == RPM) {
4823 info.da_gain = (unsigned char) hdsp_rpm_input12(hdsp);
4824 info.ad_gain = (unsigned char) hdsp_rpm_input34(hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004825 }
Takashi Iwaib0b98112005-10-20 18:29:58 +02004826 if (hdsp->io_type == H9632 || hdsp->io_type == H9652)
Adrian Knoth4833c672013-01-15 18:52:22 +01004827 info.analog_extension_board =
4828 (unsigned char)hdsp_toggle_setting(hdsp,
4829 HDSP_AnalogExtensionBoard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004830 spin_unlock_irqrestore(&hdsp->lock, flags);
4831 if (copy_to_user(argp, &info, sizeof(info)))
4832 return -EFAULT;
4833 break;
4834 }
4835 case SNDRV_HDSP_IOCTL_GET_9632_AEB: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004836 struct hdsp_9632_aeb h9632_aeb;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004837
Linus Torvalds1da177e2005-04-16 15:20:36 -07004838 if (hdsp->io_type != H9632) return -EINVAL;
4839 h9632_aeb.aebi = hdsp->ss_in_channels - H9632_SS_CHANNELS;
4840 h9632_aeb.aebo = hdsp->ss_out_channels - H9632_SS_CHANNELS;
4841 if (copy_to_user(argp, &h9632_aeb, sizeof(h9632_aeb)))
4842 return -EFAULT;
4843 break;
4844 }
4845 case SNDRV_HDSP_IOCTL_GET_VERSION: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004846 struct hdsp_version hdsp_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004847 int err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004848
Linus Torvalds1da177e2005-04-16 15:20:36 -07004849 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
4850 if (hdsp->io_type == Undefined) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004851 if ((err = hdsp_get_iobox_version(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004852 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004853 }
Dan Carpenterd14df332013-10-16 11:44:25 +03004854 memset(&hdsp_version, 0, sizeof(hdsp_version));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004855 hdsp_version.io_type = hdsp->io_type;
4856 hdsp_version.firmware_rev = hdsp->firmware_rev;
Takashi Iwaib0b98112005-10-20 18:29:58 +02004857 if ((err = copy_to_user(argp, &hdsp_version, sizeof(hdsp_version))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004858 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004859 break;
4860 }
4861 case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004862 struct hdsp_firmware __user *firmware;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004863 u32 __user *firmware_data;
4864 int err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004865
Linus Torvalds1da177e2005-04-16 15:20:36 -07004866 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
4867 /* SNDRV_HDSP_IOCTL_GET_VERSION must have been called */
4868 if (hdsp->io_type == Undefined) return -EINVAL;
4869
4870 if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded))
4871 return -EBUSY;
4872
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01004873 dev_info(hdsp->card->dev,
4874 "initializing firmware upload\n");
Takashi Iwai55e957d2005-11-17 14:52:13 +01004875 firmware = (struct hdsp_firmware __user *)argp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004876
Takashi Iwaib0b98112005-10-20 18:29:58 +02004877 if (get_user(firmware_data, &firmware->firmware_data))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004878 return -EFAULT;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004879
Takashi Iwaib0b98112005-10-20 18:29:58 +02004880 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004881 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004882
Takashi Iwai90caaef2012-11-22 16:55:11 +01004883 if (!hdsp->fw_uploaded) {
4884 hdsp->fw_uploaded = vmalloc(HDSP_FIRMWARE_SIZE);
4885 if (!hdsp->fw_uploaded)
4886 return -ENOMEM;
4887 }
4888
4889 if (copy_from_user(hdsp->fw_uploaded, firmware_data,
4890 HDSP_FIRMWARE_SIZE)) {
4891 vfree(hdsp->fw_uploaded);
4892 hdsp->fw_uploaded = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004893 return -EFAULT;
Takashi Iwai90caaef2012-11-22 16:55:11 +01004894 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004895
Linus Torvalds1da177e2005-04-16 15:20:36 -07004896 hdsp->state |= HDSP_FirmwareCached;
4897
Takashi Iwaib0b98112005-10-20 18:29:58 +02004898 if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004899 return err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004900
Linus Torvalds1da177e2005-04-16 15:20:36 -07004901 if (!(hdsp->state & HDSP_InitializationComplete)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004902 if ((err = snd_hdsp_enable_io(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004903 return err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004904
4905 snd_hdsp_initialize_channels(hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004906 snd_hdsp_initialize_midi_flush(hdsp);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004907
Linus Torvalds1da177e2005-04-16 15:20:36 -07004908 if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01004909 dev_err(hdsp->card->dev,
4910 "error creating alsa devices\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02004911 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004912 }
4913 }
4914 break;
4915 }
4916 case SNDRV_HDSP_IOCTL_GET_MIXER: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004917 struct hdsp_mixer __user *mixer = (struct hdsp_mixer __user *)argp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004918 if (copy_to_user(mixer->matrix, hdsp->mixer_matrix, sizeof(unsigned short)*HDSP_MATRIX_MIXER_SIZE))
4919 return -EFAULT;
4920 break;
4921 }
4922 default:
4923 return -EINVAL;
4924 }
4925 return 0;
4926}
4927
Takashi Iwai55e957d2005-11-17 14:52:13 +01004928static struct snd_pcm_ops snd_hdsp_playback_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004929 .open = snd_hdsp_playback_open,
4930 .close = snd_hdsp_playback_release,
4931 .ioctl = snd_hdsp_ioctl,
4932 .hw_params = snd_hdsp_hw_params,
4933 .prepare = snd_hdsp_prepare,
4934 .trigger = snd_hdsp_trigger,
4935 .pointer = snd_hdsp_hw_pointer,
4936 .copy = snd_hdsp_playback_copy,
4937 .silence = snd_hdsp_hw_silence,
4938};
4939
Takashi Iwai55e957d2005-11-17 14:52:13 +01004940static struct snd_pcm_ops snd_hdsp_capture_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004941 .open = snd_hdsp_capture_open,
4942 .close = snd_hdsp_capture_release,
4943 .ioctl = snd_hdsp_ioctl,
4944 .hw_params = snd_hdsp_hw_params,
4945 .prepare = snd_hdsp_prepare,
4946 .trigger = snd_hdsp_trigger,
4947 .pointer = snd_hdsp_hw_pointer,
4948 .copy = snd_hdsp_capture_copy,
4949};
4950
Takashi Iwai92eed662008-02-22 18:35:56 +01004951static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004952{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004953 struct snd_hwdep *hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004954 int err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004955
Linus Torvalds1da177e2005-04-16 15:20:36 -07004956 if ((err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw)) < 0)
4957 return err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004958
Linus Torvalds1da177e2005-04-16 15:20:36 -07004959 hdsp->hwdep = hw;
4960 hw->private_data = hdsp;
4961 strcpy(hw->name, "HDSP hwdep interface");
4962
Linus Torvalds1da177e2005-04-16 15:20:36 -07004963 hw->ops.ioctl = snd_hdsp_hwdep_ioctl;
Andre Schramm42eb9232012-05-07 18:52:51 +02004964 hw->ops.ioctl_compat = snd_hdsp_hwdep_ioctl;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004965
Linus Torvalds1da177e2005-04-16 15:20:36 -07004966 return 0;
4967}
4968
Takashi Iwai55e957d2005-11-17 14:52:13 +01004969static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004970{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004971 struct snd_pcm *pcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004972 int err;
4973
4974 if ((err = snd_pcm_new(card, hdsp->card_name, 0, 1, 1, &pcm)) < 0)
4975 return err;
4976
4977 hdsp->pcm = pcm;
4978 pcm->private_data = hdsp;
4979 strcpy(pcm->name, hdsp->card_name);
4980
4981 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_hdsp_playback_ops);
4982 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_hdsp_capture_ops);
4983
4984 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
4985
4986 return 0;
4987}
4988
Takashi Iwai55e957d2005-11-17 14:52:13 +01004989static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004990{
4991 hdsp->control2_register |= HDSP_9652_ENABLE_MIXER;
4992 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
4993}
4994
Takashi Iwai55e957d2005-11-17 14:52:13 +01004995static int snd_hdsp_enable_io (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004996{
4997 int i;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01004998
Linus Torvalds1da177e2005-04-16 15:20:36 -07004999 if (hdsp_fifo_wait (hdsp, 0, 100)) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005000 dev_err(hdsp->card->dev,
5001 "enable_io fifo_wait failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005002 return -EIO;
5003 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005004
Linus Torvalds1da177e2005-04-16 15:20:36 -07005005 for (i = 0; i < hdsp->max_channels; ++i) {
5006 hdsp_write (hdsp, HDSP_inputEnable + (4 * i), 1);
5007 hdsp_write (hdsp, HDSP_outputEnable + (4 * i), 1);
5008 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005009
Linus Torvalds1da177e2005-04-16 15:20:36 -07005010 return 0;
5011}
5012
Takashi Iwai55e957d2005-11-17 14:52:13 +01005013static void snd_hdsp_initialize_channels(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005014{
5015 int status, aebi_channels, aebo_channels;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005016
Linus Torvalds1da177e2005-04-16 15:20:36 -07005017 switch (hdsp->io_type) {
5018 case Digiface:
5019 hdsp->card_name = "RME Hammerfall DSP + Digiface";
5020 hdsp->ss_in_channels = hdsp->ss_out_channels = DIGIFACE_SS_CHANNELS;
5021 hdsp->ds_in_channels = hdsp->ds_out_channels = DIGIFACE_DS_CHANNELS;
5022 break;
5023
5024 case H9652:
5025 hdsp->card_name = "RME Hammerfall HDSP 9652";
5026 hdsp->ss_in_channels = hdsp->ss_out_channels = H9652_SS_CHANNELS;
5027 hdsp->ds_in_channels = hdsp->ds_out_channels = H9652_DS_CHANNELS;
5028 break;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005029
Linus Torvalds1da177e2005-04-16 15:20:36 -07005030 case H9632:
5031 status = hdsp_read(hdsp, HDSP_statusRegister);
5032 /* HDSP_AEBx bits are low when AEB are connected */
5033 aebi_channels = (status & HDSP_AEBI) ? 0 : 4;
5034 aebo_channels = (status & HDSP_AEBO) ? 0 : 4;
5035 hdsp->card_name = "RME Hammerfall HDSP 9632";
5036 hdsp->ss_in_channels = H9632_SS_CHANNELS+aebi_channels;
5037 hdsp->ds_in_channels = H9632_DS_CHANNELS+aebi_channels;
5038 hdsp->qs_in_channels = H9632_QS_CHANNELS+aebi_channels;
5039 hdsp->ss_out_channels = H9632_SS_CHANNELS+aebo_channels;
5040 hdsp->ds_out_channels = H9632_DS_CHANNELS+aebo_channels;
5041 hdsp->qs_out_channels = H9632_QS_CHANNELS+aebo_channels;
5042 break;
5043
5044 case Multiface:
5045 hdsp->card_name = "RME Hammerfall DSP + Multiface";
5046 hdsp->ss_in_channels = hdsp->ss_out_channels = MULTIFACE_SS_CHANNELS;
5047 hdsp->ds_in_channels = hdsp->ds_out_channels = MULTIFACE_DS_CHANNELS;
5048 break;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005049
Florian Faber28b26e12010-12-01 12:14:47 +01005050 case RPM:
5051 hdsp->card_name = "RME Hammerfall DSP + RPM";
5052 hdsp->ss_in_channels = RPM_CHANNELS-1;
5053 hdsp->ss_out_channels = RPM_CHANNELS;
5054 hdsp->ds_in_channels = RPM_CHANNELS-1;
5055 hdsp->ds_out_channels = RPM_CHANNELS;
5056 break;
5057
Linus Torvalds1da177e2005-04-16 15:20:36 -07005058 default:
5059 /* should never get here */
5060 break;
5061 }
5062}
5063
Takashi Iwai55e957d2005-11-17 14:52:13 +01005064static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005065{
5066 snd_hdsp_flush_midi_input (hdsp, 0);
5067 snd_hdsp_flush_midi_input (hdsp, 1);
5068}
5069
Takashi Iwai55e957d2005-11-17 14:52:13 +01005070static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005071{
5072 int err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005073
Linus Torvalds1da177e2005-04-16 15:20:36 -07005074 if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005075 dev_err(card->dev,
5076 "Error creating pcm interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005077 return err;
5078 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005079
Linus Torvalds1da177e2005-04-16 15:20:36 -07005080
5081 if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005082 dev_err(card->dev,
5083 "Error creating first midi interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005084 return err;
5085 }
5086
5087 if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
5088 if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005089 dev_err(card->dev,
5090 "Error creating second midi interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005091 return err;
5092 }
5093 }
5094
5095 if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005096 dev_err(card->dev,
5097 "Error creating ctl interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005098 return err;
5099 }
5100
5101 snd_hdsp_proc_init(hdsp);
5102
5103 hdsp->system_sample_rate = -1;
5104 hdsp->playback_pid = -1;
5105 hdsp->capture_pid = -1;
5106 hdsp->capture_substream = NULL;
5107 hdsp->playback_substream = NULL;
5108
5109 if ((err = snd_hdsp_set_defaults(hdsp)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005110 dev_err(card->dev,
5111 "Error setting default values\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112 return err;
5113 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005114
Linus Torvalds1da177e2005-04-16 15:20:36 -07005115 if (!(hdsp->state & HDSP_InitializationComplete)) {
Clemens Ladischb73c1c12005-09-02 08:49:21 +02005116 strcpy(card->shortname, "Hammerfall DSP");
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005117 sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005118 hdsp->port, hdsp->irq);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005119
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120 if ((err = snd_card_register(card)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005121 dev_err(card->dev,
5122 "error registering card\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005123 return err;
5124 }
5125 hdsp->state |= HDSP_InitializationComplete;
5126 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005127
Linus Torvalds1da177e2005-04-16 15:20:36 -07005128 return 0;
5129}
5130
Linus Torvalds1da177e2005-04-16 15:20:36 -07005131/* load firmware via hotplug fw loader */
Takashi Iwai92eed662008-02-22 18:35:56 +01005132static int hdsp_request_fw_loader(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005133{
5134 const char *fwfile;
5135 const struct firmware *fw;
5136 int err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005137
Linus Torvalds1da177e2005-04-16 15:20:36 -07005138 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
5139 return 0;
5140 if (hdsp->io_type == Undefined) {
5141 if ((err = hdsp_get_iobox_version(hdsp)) < 0)
5142 return err;
5143 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
5144 return 0;
5145 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005146
Linus Torvalds1da177e2005-04-16 15:20:36 -07005147 /* caution: max length of firmware filename is 30! */
5148 switch (hdsp->io_type) {
Florian Faber28b26e12010-12-01 12:14:47 +01005149 case RPM:
5150 fwfile = "rpm_firmware.bin";
5151 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005152 case Multiface:
5153 if (hdsp->firmware_rev == 0xa)
5154 fwfile = "multiface_firmware.bin";
5155 else
5156 fwfile = "multiface_firmware_rev11.bin";
5157 break;
5158 case Digiface:
5159 if (hdsp->firmware_rev == 0xa)
5160 fwfile = "digiface_firmware.bin";
5161 else
5162 fwfile = "digiface_firmware_rev11.bin";
5163 break;
5164 default:
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005165 dev_err(hdsp->card->dev,
5166 "invalid io_type %d\n", hdsp->io_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005167 return -EINVAL;
5168 }
5169
5170 if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005171 dev_err(hdsp->card->dev,
5172 "cannot load firmware %s\n", fwfile);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005173 return -ENOENT;
5174 }
Takashi Iwai90caaef2012-11-22 16:55:11 +01005175 if (fw->size < HDSP_FIRMWARE_SIZE) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005176 dev_err(hdsp->card->dev,
5177 "too short firmware size %d (expected %d)\n",
Takashi Iwai90caaef2012-11-22 16:55:11 +01005178 (int)fw->size, HDSP_FIRMWARE_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005179 return -EINVAL;
5180 }
Thomas Charbonnel7679a032005-04-25 11:35:29 +02005181
Takashi Iwai90caaef2012-11-22 16:55:11 +01005182 hdsp->firmware = fw;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005183
Linus Torvalds1da177e2005-04-16 15:20:36 -07005184 hdsp->state |= HDSP_FirmwareCached;
5185
5186 if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
5187 return err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005188
Linus Torvalds1da177e2005-04-16 15:20:36 -07005189 if (!(hdsp->state & HDSP_InitializationComplete)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02005190 if ((err = snd_hdsp_enable_io(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005191 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005192
5193 if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005194 dev_err(hdsp->card->dev,
5195 "error creating hwdep device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005196 return err;
5197 }
5198 snd_hdsp_initialize_channels(hdsp);
5199 snd_hdsp_initialize_midi_flush(hdsp);
5200 if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005201 dev_err(hdsp->card->dev,
5202 "error creating alsa devices\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005203 return err;
5204 }
5205 }
5206 return 0;
5207}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005208
Bill Pembertone23e7a12012-12-06 12:35:10 -05005209static int snd_hdsp_create(struct snd_card *card,
5210 struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005211{
5212 struct pci_dev *pci = hdsp->pci;
5213 int err;
5214 int is_9652 = 0;
5215 int is_9632 = 0;
5216
5217 hdsp->irq = -1;
5218 hdsp->state = 0;
5219 hdsp->midi[0].rmidi = NULL;
5220 hdsp->midi[1].rmidi = NULL;
5221 hdsp->midi[0].input = NULL;
5222 hdsp->midi[1].input = NULL;
5223 hdsp->midi[0].output = NULL;
5224 hdsp->midi[1].output = NULL;
5225 hdsp->midi[0].pending = 0;
5226 hdsp->midi[1].pending = 0;
5227 spin_lock_init(&hdsp->midi[0].lock);
5228 spin_lock_init(&hdsp->midi[1].lock);
5229 hdsp->iobase = NULL;
5230 hdsp->control_register = 0;
5231 hdsp->control2_register = 0;
5232 hdsp->io_type = Undefined;
5233 hdsp->max_channels = 26;
5234
5235 hdsp->card = card;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005236
Linus Torvalds1da177e2005-04-16 15:20:36 -07005237 spin_lock_init(&hdsp->lock);
5238
5239 tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005240
Linus Torvalds1da177e2005-04-16 15:20:36 -07005241 pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev);
5242 hdsp->firmware_rev &= 0xff;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005243
Linus Torvalds1da177e2005-04-16 15:20:36 -07005244 /* From Martin Bjoernsen :
5245 "It is important that the card's latency timer register in
5246 the PCI configuration space is set to a value much larger
5247 than 0 by the computer's BIOS or the driver.
5248 The windows driver always sets this 8 bit register [...]
5249 to its maximum 255 to avoid problems with some computers."
5250 */
5251 pci_write_config_byte(hdsp->pci, PCI_LATENCY_TIMER, 0xFF);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005252
Linus Torvalds1da177e2005-04-16 15:20:36 -07005253 strcpy(card->driver, "H-DSP");
5254 strcpy(card->mixername, "Xilinx FPGA");
5255
Takashi Iwaib0b98112005-10-20 18:29:58 +02005256 if (hdsp->firmware_rev < 0xa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005257 return -ENODEV;
Takashi Iwaib0b98112005-10-20 18:29:58 +02005258 else if (hdsp->firmware_rev < 0x64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005259 hdsp->card_name = "RME Hammerfall DSP";
Takashi Iwaib0b98112005-10-20 18:29:58 +02005260 else if (hdsp->firmware_rev < 0x96) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005261 hdsp->card_name = "RME HDSP 9652";
5262 is_9652 = 1;
5263 } else {
5264 hdsp->card_name = "RME HDSP 9632";
5265 hdsp->max_channels = 16;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005266 is_9632 = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005267 }
5268
Takashi Iwaib0b98112005-10-20 18:29:58 +02005269 if ((err = pci_enable_device(pci)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005270 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005271
5272 pci_set_master(hdsp->pci);
5273
5274 if ((err = pci_request_regions(pci, "hdsp")) < 0)
5275 return err;
5276 hdsp->port = pci_resource_start(pci, 0);
5277 if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005278 dev_err(hdsp->card->dev, "unable to remap region 0x%lx-0x%lx\n",
5279 hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005280 return -EBUSY;
5281 }
5282
Takashi Iwai437a5a42006-11-21 12:14:23 +01005283 if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_SHARED,
Takashi Iwai934c2b62011-06-10 16:36:37 +02005284 KBUILD_MODNAME, hdsp)) {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005285 dev_err(hdsp->card->dev, "unable to use IRQ %d\n", pci->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005286 return -EBUSY;
5287 }
5288
5289 hdsp->irq = pci->irq;
Remy Bruno176546a2006-10-16 12:32:53 +02005290 hdsp->precise_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005291 hdsp->use_midi_tasklet = 1;
Remy Brunod7923b22006-10-17 12:41:56 +02005292 hdsp->dds_value = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005293
Takashi Iwaib0b98112005-10-20 18:29:58 +02005294 if ((err = snd_hdsp_initialize_memory(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005295 return err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005296
Linus Torvalds1da177e2005-04-16 15:20:36 -07005297 if (!is_9652 && !is_9632) {
Tim Blechmanne588ed82009-02-20 19:30:35 +01005298 /* we wait a maximum of 10 seconds to let freshly
5299 * inserted cardbus cards do their hardware init */
5300 err = hdsp_wait_for_iobox(hdsp, 1000, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005301
Tim Blechmann00c9ddd2008-11-09 12:50:52 +01005302 if (err < 0)
5303 return err;
5304
Linus Torvalds1da177e2005-04-16 15:20:36 -07005305 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02005306 if ((err = hdsp_request_fw_loader(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005307 /* we don't fail as this can happen
5308 if userspace is not ready for
5309 firmware upload
5310 */
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005311 dev_err(hdsp->card->dev,
5312 "couldn't get firmware from userspace. try using hdsploader\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02005313 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07005314 /* init is complete, we return */
5315 return 0;
Tim Blechmann00c9ddd2008-11-09 12:50:52 +01005316 /* we defer initialization */
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005317 dev_info(hdsp->card->dev,
5318 "card initialization pending : waiting for firmware\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02005319 if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005320 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005321 return 0;
5322 } else {
Takashi Iwaia54ba0f2014-02-26 12:05:11 +01005323 dev_info(hdsp->card->dev,
5324 "Firmware already present, initializing card.\n");
Florian Faber28b26e12010-12-01 12:14:47 +01005325 if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version2)
5326 hdsp->io_type = RPM;
5327 else if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005328 hdsp->io_type = Multiface;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005329 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07005330 hdsp->io_type = Digiface;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005331 }
5332 }
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005333
Takashi Iwaib0b98112005-10-20 18:29:58 +02005334 if ((err = snd_hdsp_enable_io(hdsp)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005335 return err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005336
Takashi Iwaib0b98112005-10-20 18:29:58 +02005337 if (is_9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005338 hdsp->io_type = H9652;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005339
Takashi Iwaib0b98112005-10-20 18:29:58 +02005340 if (is_9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005341 hdsp->io_type = H9632;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005342
Takashi Iwaib0b98112005-10-20 18:29:58 +02005343 if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005344 return err;
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005345
Linus Torvalds1da177e2005-04-16 15:20:36 -07005346 snd_hdsp_initialize_channels(hdsp);
5347 snd_hdsp_initialize_midi_flush(hdsp);
5348
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005349 hdsp->state |= HDSP_FirmwareLoaded;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005350
Takashi Iwaib0b98112005-10-20 18:29:58 +02005351 if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005352 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005353
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005354 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005355}
5356
Takashi Iwai55e957d2005-11-17 14:52:13 +01005357static int snd_hdsp_free(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005358{
5359 if (hdsp->port) {
5360 /* stop the audio, and cancel all interrupts */
5361 tasklet_kill(&hdsp->midi_tasklet);
5362 hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable);
5363 hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
5364 }
5365
5366 if (hdsp->irq >= 0)
5367 free_irq(hdsp->irq, (void *)hdsp);
5368
5369 snd_hdsp_free_buffers(hdsp);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005370
Takashi Iwai90caaef2012-11-22 16:55:11 +01005371 if (hdsp->firmware)
5372 release_firmware(hdsp->firmware);
5373 vfree(hdsp->fw_uploaded);
5374
Linus Torvalds1da177e2005-04-16 15:20:36 -07005375 if (hdsp->iobase)
5376 iounmap(hdsp->iobase);
5377
5378 if (hdsp->port)
5379 pci_release_regions(hdsp->pci);
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005380
Linus Torvalds1da177e2005-04-16 15:20:36 -07005381 pci_disable_device(hdsp->pci);
5382 return 0;
5383}
5384
Takashi Iwai55e957d2005-11-17 14:52:13 +01005385static void snd_hdsp_card_free(struct snd_card *card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005386{
Joe Perches9fe856e2010-09-04 18:52:54 -07005387 struct hdsp *hdsp = card->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005388
5389 if (hdsp)
5390 snd_hdsp_free(hdsp);
5391}
5392
Bill Pembertone23e7a12012-12-06 12:35:10 -05005393static int snd_hdsp_probe(struct pci_dev *pci,
5394 const struct pci_device_id *pci_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005395{
5396 static int dev;
Takashi Iwai55e957d2005-11-17 14:52:13 +01005397 struct hdsp *hdsp;
5398 struct snd_card *card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005399 int err;
5400
5401 if (dev >= SNDRV_CARDS)
5402 return -ENODEV;
5403 if (!enable[dev]) {
5404 dev++;
5405 return -ENOENT;
5406 }
5407
Takashi Iwai60c57722014-01-29 14:20:19 +01005408 err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
5409 sizeof(struct hdsp), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01005410 if (err < 0)
5411 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005412
Joe Perches9fe856e2010-09-04 18:52:54 -07005413 hdsp = card->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005414 card->private_free = snd_hdsp_card_free;
5415 hdsp->dev = dev;
5416 hdsp->pci = pci;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005417
5418 if ((err = snd_hdsp_create(card, hdsp)) < 0) {
5419 snd_card_free(card);
5420 return err;
5421 }
5422
5423 strcpy(card->shortname, "Hammerfall DSP");
Tim Blechmannf9ffc5d2009-02-20 19:38:16 +01005424 sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005425 hdsp->port, hdsp->irq);
5426
5427 if ((err = snd_card_register(card)) < 0) {
5428 snd_card_free(card);
5429 return err;
5430 }
5431 pci_set_drvdata(pci, card);
5432 dev++;
5433 return 0;
5434}
5435
Bill Pembertone23e7a12012-12-06 12:35:10 -05005436static void snd_hdsp_remove(struct pci_dev *pci)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005437{
5438 snd_card_free(pci_get_drvdata(pci));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005439}
5440
Takashi Iwaie9f66d92012-04-24 12:25:00 +02005441static struct pci_driver hdsp_driver = {
Takashi Iwai3733e422011-06-10 16:20:20 +02005442 .name = KBUILD_MODNAME,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005443 .id_table = snd_hdsp_ids,
5444 .probe = snd_hdsp_probe,
Bill Pembertone23e7a12012-12-06 12:35:10 -05005445 .remove = snd_hdsp_remove,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005446};
5447
Takashi Iwaie9f66d92012-04-24 12:25:00 +02005448module_pci_driver(hdsp_driver);