blob: 4d6fbb36ab8af1f2b7df881ff402402af28f8b53 [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>
27#include <linux/slab.h>
28#include <linux/pci.h>
29#include <linux/firmware.h>
30#include <linux/moduleparam.h>
31
32#include <sound/core.h>
33#include <sound/control.h>
34#include <sound/pcm.h>
35#include <sound/info.h>
36#include <sound/asoundef.h>
37#include <sound/rawmidi.h>
38#include <sound/hwdep.h>
39#include <sound/initval.h>
40#include <sound/hdsp.h>
41
42#include <asm/byteorder.h>
43#include <asm/current.h>
44#include <asm/io.h>
45
46static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
47static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
48static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
49
50module_param_array(index, int, NULL, 0444);
51MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface.");
52module_param_array(id, charp, NULL, 0444);
53MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface.");
54module_param_array(enable, bool, NULL, 0444);
55MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards.");
56MODULE_AUTHOR("Paul Davis <paul@linuxaudiosystems.com>, Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
57MODULE_DESCRIPTION("RME Hammerfall DSP");
58MODULE_LICENSE("GPL");
59MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
60 "{RME HDSP-9652},"
61 "{RME HDSP-9632}}");
Clemens Ladisch7e0af292007-05-03 17:59:54 +020062#ifdef HDSP_FW_LOADER
63MODULE_FIRMWARE("multiface_firmware.bin");
64MODULE_FIRMWARE("multiface_firmware_rev11.bin");
65MODULE_FIRMWARE("digiface_firmware.bin");
66MODULE_FIRMWARE("digiface_firmware_rev11.bin");
67#endif
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
84
85/* Write registers. These are defined as byte-offsets from the iobase value.
86 */
87#define HDSP_resetPointer 0
Remy Brunod7923b22006-10-17 12:41:56 +020088#define HDSP_freqReg 0
Linus Torvalds1da177e2005-04-16 15:20:36 -070089#define HDSP_outputBufferAddress 32
90#define HDSP_inputBufferAddress 36
91#define HDSP_controlRegister 64
92#define HDSP_interruptConfirmation 96
93#define HDSP_outputEnable 128
94#define HDSP_control2Reg 256
95#define HDSP_midiDataOut0 352
96#define HDSP_midiDataOut1 356
97#define HDSP_fifoData 368
98#define HDSP_inputEnable 384
99
100/* Read registers. These are defined as byte-offsets from the iobase value
101 */
102
103#define HDSP_statusRegister 0
104#define HDSP_timecode 128
105#define HDSP_status2Register 192
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106#define HDSP_midiDataIn0 360
107#define HDSP_midiDataIn1 364
108#define HDSP_midiStatusOut0 384
109#define HDSP_midiStatusOut1 388
110#define HDSP_midiStatusIn0 392
111#define HDSP_midiStatusIn1 396
112#define HDSP_fifoStatus 400
113
114/* the meters are regular i/o-mapped registers, but offset
115 considerably from the rest. the peak registers are reset
116 when read; the least-significant 4 bits are full-scale counters;
117 the actual peak value is in the most-significant 24 bits.
118*/
119
120#define HDSP_playbackPeakLevel 4096 /* 26 * 32 bit values */
121#define HDSP_inputPeakLevel 4224 /* 26 * 32 bit values */
122#define HDSP_outputPeakLevel 4352 /* (26+2) * 32 bit values */
123#define HDSP_playbackRmsLevel 4612 /* 26 * 64 bit values */
124#define HDSP_inputRmsLevel 4868 /* 26 * 64 bit values */
125
126
127/* This is for H9652 cards
128 Peak values are read downward from the base
129 Rms values are read upward
130 There are rms values for the outputs too
131 26*3 values are read in ss mode
132 14*3 in ds mode, with no gap between values
133*/
134#define HDSP_9652_peakBase 7164
135#define HDSP_9652_rmsBase 4096
136
137/* c.f. the hdsp_9632_meters_t struct */
138#define HDSP_9632_metersBase 4096
139
140#define HDSP_IO_EXTENT 7168
141
142/* control2 register bits */
143
144#define HDSP_TMS 0x01
145#define HDSP_TCK 0x02
146#define HDSP_TDI 0x04
147#define HDSP_JTAG 0x08
148#define HDSP_PWDN 0x10
149#define HDSP_PROGRAM 0x020
150#define HDSP_CONFIG_MODE_0 0x040
151#define HDSP_CONFIG_MODE_1 0x080
152#define HDSP_VERSION_BIT 0x100
153#define HDSP_BIGENDIAN_MODE 0x200
154#define HDSP_RD_MULTIPLE 0x400
155#define HDSP_9652_ENABLE_MIXER 0x800
156#define HDSP_TDO 0x10000000
157
158#define HDSP_S_PROGRAM (HDSP_PROGRAM|HDSP_CONFIG_MODE_0)
159#define HDSP_S_LOAD (HDSP_PROGRAM|HDSP_CONFIG_MODE_1)
160
161/* Control Register bits */
162
163#define HDSP_Start (1<<0) /* start engine */
164#define HDSP_Latency0 (1<<1) /* buffer size = 2^n where n is defined by Latency{2,1,0} */
165#define HDSP_Latency1 (1<<2) /* [ see above ] */
166#define HDSP_Latency2 (1<<3) /* [ see above ] */
167#define HDSP_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */
168#define HDSP_AudioInterruptEnable (1<<5) /* what do you think ? */
169#define HDSP_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz/176.4kHz 1=48kHz/96kHz/192kHz */
170#define HDSP_Frequency1 (1<<7) /* 0=32kHz/64kHz/128kHz */
171#define HDSP_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
172#define HDSP_SPDIFProfessional (1<<9) /* 0=consumer, 1=professional */
173#define HDSP_SPDIFEmphasis (1<<10) /* 0=none, 1=on */
174#define HDSP_SPDIFNonAudio (1<<11) /* 0=off, 1=on */
175#define HDSP_SPDIFOpticalOut (1<<12) /* 1=use 1st ADAT connector for SPDIF, 0=do not */
176#define HDSP_SyncRef2 (1<<13)
177#define HDSP_SPDIFInputSelect0 (1<<14)
178#define HDSP_SPDIFInputSelect1 (1<<15)
179#define HDSP_SyncRef0 (1<<16)
180#define HDSP_SyncRef1 (1<<17)
181#define HDSP_AnalogExtensionBoard (1<<18) /* For H9632 cards */
182#define HDSP_XLRBreakoutCable (1<<20) /* For H9632 cards */
183#define HDSP_Midi0InterruptEnable (1<<22)
184#define HDSP_Midi1InterruptEnable (1<<23)
185#define HDSP_LineOut (1<<24)
186#define HDSP_ADGain0 (1<<25) /* From here : H9632 specific */
187#define HDSP_ADGain1 (1<<26)
188#define HDSP_DAGain0 (1<<27)
189#define HDSP_DAGain1 (1<<28)
190#define HDSP_PhoneGain0 (1<<29)
191#define HDSP_PhoneGain1 (1<<30)
192#define HDSP_QuadSpeed (1<<31)
193
194#define HDSP_ADGainMask (HDSP_ADGain0|HDSP_ADGain1)
195#define HDSP_ADGainMinus10dBV HDSP_ADGainMask
196#define HDSP_ADGainPlus4dBu (HDSP_ADGain0)
197#define HDSP_ADGainLowGain 0
198
199#define HDSP_DAGainMask (HDSP_DAGain0|HDSP_DAGain1)
200#define HDSP_DAGainHighGain HDSP_DAGainMask
201#define HDSP_DAGainPlus4dBu (HDSP_DAGain0)
202#define HDSP_DAGainMinus10dBV 0
203
204#define HDSP_PhoneGainMask (HDSP_PhoneGain0|HDSP_PhoneGain1)
205#define HDSP_PhoneGain0dB HDSP_PhoneGainMask
206#define HDSP_PhoneGainMinus6dB (HDSP_PhoneGain0)
207#define HDSP_PhoneGainMinus12dB 0
208
209#define HDSP_LatencyMask (HDSP_Latency0|HDSP_Latency1|HDSP_Latency2)
210#define HDSP_FrequencyMask (HDSP_Frequency0|HDSP_Frequency1|HDSP_DoubleSpeed|HDSP_QuadSpeed)
211
212#define HDSP_SPDIFInputMask (HDSP_SPDIFInputSelect0|HDSP_SPDIFInputSelect1)
213#define HDSP_SPDIFInputADAT1 0
214#define HDSP_SPDIFInputCoaxial (HDSP_SPDIFInputSelect0)
215#define HDSP_SPDIFInputCdrom (HDSP_SPDIFInputSelect1)
216#define HDSP_SPDIFInputAES (HDSP_SPDIFInputSelect0|HDSP_SPDIFInputSelect1)
217
218#define HDSP_SyncRefMask (HDSP_SyncRef0|HDSP_SyncRef1|HDSP_SyncRef2)
219#define HDSP_SyncRef_ADAT1 0
220#define HDSP_SyncRef_ADAT2 (HDSP_SyncRef0)
221#define HDSP_SyncRef_ADAT3 (HDSP_SyncRef1)
222#define HDSP_SyncRef_SPDIF (HDSP_SyncRef0|HDSP_SyncRef1)
223#define HDSP_SyncRef_WORD (HDSP_SyncRef2)
224#define HDSP_SyncRef_ADAT_SYNC (HDSP_SyncRef0|HDSP_SyncRef2)
225
226/* Sample Clock Sources */
227
228#define HDSP_CLOCK_SOURCE_AUTOSYNC 0
229#define HDSP_CLOCK_SOURCE_INTERNAL_32KHZ 1
230#define HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ 2
231#define HDSP_CLOCK_SOURCE_INTERNAL_48KHZ 3
232#define HDSP_CLOCK_SOURCE_INTERNAL_64KHZ 4
233#define HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ 5
234#define HDSP_CLOCK_SOURCE_INTERNAL_96KHZ 6
235#define HDSP_CLOCK_SOURCE_INTERNAL_128KHZ 7
236#define HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ 8
237#define HDSP_CLOCK_SOURCE_INTERNAL_192KHZ 9
238
239/* Preferred sync reference choices - used by "pref_sync_ref" control switch */
240
241#define HDSP_SYNC_FROM_WORD 0
242#define HDSP_SYNC_FROM_SPDIF 1
243#define HDSP_SYNC_FROM_ADAT1 2
244#define HDSP_SYNC_FROM_ADAT_SYNC 3
245#define HDSP_SYNC_FROM_ADAT2 4
246#define HDSP_SYNC_FROM_ADAT3 5
247
248/* SyncCheck status */
249
250#define HDSP_SYNC_CHECK_NO_LOCK 0
251#define HDSP_SYNC_CHECK_LOCK 1
252#define HDSP_SYNC_CHECK_SYNC 2
253
254/* AutoSync references - used by "autosync_ref" control switch */
255
256#define HDSP_AUTOSYNC_FROM_WORD 0
257#define HDSP_AUTOSYNC_FROM_ADAT_SYNC 1
258#define HDSP_AUTOSYNC_FROM_SPDIF 2
259#define HDSP_AUTOSYNC_FROM_NONE 3
260#define HDSP_AUTOSYNC_FROM_ADAT1 4
261#define HDSP_AUTOSYNC_FROM_ADAT2 5
262#define HDSP_AUTOSYNC_FROM_ADAT3 6
263
264/* Possible sources of S/PDIF input */
265
266#define HDSP_SPDIFIN_OPTICAL 0 /* optical (ADAT1) */
267#define HDSP_SPDIFIN_COAXIAL 1 /* coaxial (RCA) */
268#define HDSP_SPDIFIN_INTERNAL 2 /* internal (CDROM) */
269#define HDSP_SPDIFIN_AES 3 /* xlr for H9632 (AES)*/
270
271#define HDSP_Frequency32KHz HDSP_Frequency0
272#define HDSP_Frequency44_1KHz HDSP_Frequency1
273#define HDSP_Frequency48KHz (HDSP_Frequency1|HDSP_Frequency0)
274#define HDSP_Frequency64KHz (HDSP_DoubleSpeed|HDSP_Frequency0)
275#define HDSP_Frequency88_2KHz (HDSP_DoubleSpeed|HDSP_Frequency1)
276#define HDSP_Frequency96KHz (HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0)
277/* For H9632 cards */
278#define HDSP_Frequency128KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency0)
279#define HDSP_Frequency176_4KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1)
280#define HDSP_Frequency192KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0)
Julian Cablee4b60882007-03-19 11:44:40 +0100281/* RME says n = 104857600000000, but in the windows MADI driver, I see:
282 return 104857600000000 / rate; // 100 MHz
283 return 110100480000000 / rate; // 105 MHz
284*/
285#define DDS_NUMERATOR 104857600000000ULL; /* = 2^20 * 10^8 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
287#define hdsp_encode_latency(x) (((x)<<1) & HDSP_LatencyMask)
288#define hdsp_decode_latency(x) (((x) & HDSP_LatencyMask)>>1)
289
290#define hdsp_encode_spdif_in(x) (((x)&0x3)<<14)
291#define hdsp_decode_spdif_in(x) (((x)>>14)&0x3)
292
293/* Status Register bits */
294
295#define HDSP_audioIRQPending (1<<0)
296#define HDSP_Lock2 (1<<1) /* this is for Digiface and H9652 */
297#define HDSP_spdifFrequency3 HDSP_Lock2 /* this is for H9632 only */
298#define HDSP_Lock1 (1<<2)
299#define HDSP_Lock0 (1<<3)
300#define HDSP_SPDIFSync (1<<4)
301#define HDSP_TimecodeLock (1<<5)
302#define HDSP_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
303#define HDSP_Sync2 (1<<16)
304#define HDSP_Sync1 (1<<17)
305#define HDSP_Sync0 (1<<18)
306#define HDSP_DoubleSpeedStatus (1<<19)
307#define HDSP_ConfigError (1<<20)
308#define HDSP_DllError (1<<21)
309#define HDSP_spdifFrequency0 (1<<22)
310#define HDSP_spdifFrequency1 (1<<23)
311#define HDSP_spdifFrequency2 (1<<24)
312#define HDSP_SPDIFErrorFlag (1<<25)
313#define HDSP_BufferID (1<<26)
314#define HDSP_TimecodeSync (1<<27)
315#define HDSP_AEBO (1<<28) /* H9632 specific Analog Extension Boards */
316#define HDSP_AEBI (1<<29) /* 0 = present, 1 = absent */
317#define HDSP_midi0IRQPending (1<<30)
318#define HDSP_midi1IRQPending (1<<31)
319
320#define HDSP_spdifFrequencyMask (HDSP_spdifFrequency0|HDSP_spdifFrequency1|HDSP_spdifFrequency2)
Remy Bruno47ba97f2008-02-22 17:57:02 +0100321#define HDSP_spdifFrequencyMask_9632 (HDSP_spdifFrequency0|\
322 HDSP_spdifFrequency1|\
323 HDSP_spdifFrequency2|\
324 HDSP_spdifFrequency3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325
326#define HDSP_spdifFrequency32KHz (HDSP_spdifFrequency0)
327#define HDSP_spdifFrequency44_1KHz (HDSP_spdifFrequency1)
328#define HDSP_spdifFrequency48KHz (HDSP_spdifFrequency0|HDSP_spdifFrequency1)
329
330#define HDSP_spdifFrequency64KHz (HDSP_spdifFrequency2)
331#define HDSP_spdifFrequency88_2KHz (HDSP_spdifFrequency0|HDSP_spdifFrequency2)
332#define HDSP_spdifFrequency96KHz (HDSP_spdifFrequency2|HDSP_spdifFrequency1)
333
334/* This is for H9632 cards */
Remy Bruno47ba97f2008-02-22 17:57:02 +0100335#define HDSP_spdifFrequency128KHz (HDSP_spdifFrequency0|\
336 HDSP_spdifFrequency1|\
337 HDSP_spdifFrequency2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338#define HDSP_spdifFrequency176_4KHz HDSP_spdifFrequency3
339#define HDSP_spdifFrequency192KHz (HDSP_spdifFrequency3|HDSP_spdifFrequency0)
340
341/* Status2 Register bits */
342
343#define HDSP_version0 (1<<0)
344#define HDSP_version1 (1<<1)
345#define HDSP_version2 (1<<2)
346#define HDSP_wc_lock (1<<3)
347#define HDSP_wc_sync (1<<4)
348#define HDSP_inp_freq0 (1<<5)
349#define HDSP_inp_freq1 (1<<6)
350#define HDSP_inp_freq2 (1<<7)
351#define HDSP_SelSyncRef0 (1<<8)
352#define HDSP_SelSyncRef1 (1<<9)
353#define HDSP_SelSyncRef2 (1<<10)
354
355#define HDSP_wc_valid (HDSP_wc_lock|HDSP_wc_sync)
356
357#define HDSP_systemFrequencyMask (HDSP_inp_freq0|HDSP_inp_freq1|HDSP_inp_freq2)
358#define HDSP_systemFrequency32 (HDSP_inp_freq0)
359#define HDSP_systemFrequency44_1 (HDSP_inp_freq1)
360#define HDSP_systemFrequency48 (HDSP_inp_freq0|HDSP_inp_freq1)
361#define HDSP_systemFrequency64 (HDSP_inp_freq2)
362#define HDSP_systemFrequency88_2 (HDSP_inp_freq0|HDSP_inp_freq2)
363#define HDSP_systemFrequency96 (HDSP_inp_freq1|HDSP_inp_freq2)
364/* FIXME : more values for 9632 cards ? */
365
366#define HDSP_SelSyncRefMask (HDSP_SelSyncRef0|HDSP_SelSyncRef1|HDSP_SelSyncRef2)
367#define HDSP_SelSyncRef_ADAT1 0
368#define HDSP_SelSyncRef_ADAT2 (HDSP_SelSyncRef0)
369#define HDSP_SelSyncRef_ADAT3 (HDSP_SelSyncRef1)
370#define HDSP_SelSyncRef_SPDIF (HDSP_SelSyncRef0|HDSP_SelSyncRef1)
371#define HDSP_SelSyncRef_WORD (HDSP_SelSyncRef2)
372#define HDSP_SelSyncRef_ADAT_SYNC (HDSP_SelSyncRef0|HDSP_SelSyncRef2)
373
374/* Card state flags */
375
376#define HDSP_InitializationComplete (1<<0)
377#define HDSP_FirmwareLoaded (1<<1)
378#define HDSP_FirmwareCached (1<<2)
379
380/* FIFO wait times, defined in terms of 1/10ths of msecs */
381
382#define HDSP_LONG_WAIT 5000
383#define HDSP_SHORT_WAIT 30
384
385#define UNITY_GAIN 32768
386#define MINUS_INFINITY_GAIN 0
387
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388/* the size of a substream (1 mono data stream) */
389
390#define HDSP_CHANNEL_BUFFER_SAMPLES (16*1024)
391#define HDSP_CHANNEL_BUFFER_BYTES (4*HDSP_CHANNEL_BUFFER_SAMPLES)
392
393/* the size of the area we need to allocate for DMA transfers. the
394 size is the same regardless of the number of channels - the
395 Multiface still uses the same memory area.
396
397 Note that we allocate 1 more channel than is apparently needed
398 because the h/w seems to write 1 byte beyond the end of the last
399 page. Sigh.
400*/
401
402#define HDSP_DMA_AREA_BYTES ((HDSP_MAX_CHANNELS+1) * HDSP_CHANNEL_BUFFER_BYTES)
403#define HDSP_DMA_AREA_KILOBYTES (HDSP_DMA_AREA_BYTES/1024)
404
405/* use hotplug firmeare loader? */
406#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
Takashi Iwai140432f2006-05-22 14:31:57 +0200407#if !defined(HDSP_USE_HWDEP_LOADER) && !defined(CONFIG_SND_HDSP)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408#define HDSP_FW_LOADER
409#endif
410#endif
411
Takashi Iwai55e957d2005-11-17 14:52:13 +0100412struct hdsp_9632_meters {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 u32 input_peak[16];
414 u32 playback_peak[16];
415 u32 output_peak[16];
416 u32 xxx_peak[16];
417 u32 padding[64];
418 u32 input_rms_low[16];
419 u32 playback_rms_low[16];
420 u32 output_rms_low[16];
421 u32 xxx_rms_low[16];
422 u32 input_rms_high[16];
423 u32 playback_rms_high[16];
424 u32 output_rms_high[16];
425 u32 xxx_rms_high[16];
426};
427
Takashi Iwai55e957d2005-11-17 14:52:13 +0100428struct hdsp_midi {
429 struct hdsp *hdsp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 int id;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100431 struct snd_rawmidi *rmidi;
432 struct snd_rawmidi_substream *input;
433 struct snd_rawmidi_substream *output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 char istimer; /* timer in use */
435 struct timer_list timer;
436 spinlock_t lock;
437 int pending;
438};
439
Takashi Iwai55e957d2005-11-17 14:52:13 +0100440struct hdsp {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 spinlock_t lock;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100442 struct snd_pcm_substream *capture_substream;
443 struct snd_pcm_substream *playback_substream;
444 struct hdsp_midi midi[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 struct tasklet_struct midi_tasklet;
446 int use_midi_tasklet;
447 int precise_ptr;
448 u32 control_register; /* cached value */
449 u32 control2_register; /* cached value */
450 u32 creg_spdif;
451 u32 creg_spdif_stream;
Takashi Iwaie3ea4d82005-07-04 18:12:39 +0200452 int clock_source_locked;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 char *card_name; /* digiface/multiface */
Takashi Iwai55e957d2005-11-17 14:52:13 +0100454 enum HDSP_IO_Type io_type; /* ditto, but for code use */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 unsigned short firmware_rev;
456 unsigned short state; /* stores state bits */
457 u32 firmware_cache[24413]; /* this helps recover from accidental iobox power failure */
458 size_t period_bytes; /* guess what this is */
459 unsigned char max_channels;
460 unsigned char qs_in_channels; /* quad speed mode for H9632 */
461 unsigned char ds_in_channels;
462 unsigned char ss_in_channels; /* different for multiface/digiface */
463 unsigned char qs_out_channels;
464 unsigned char ds_out_channels;
465 unsigned char ss_out_channels;
466
467 struct snd_dma_buffer capture_dma_buf;
468 struct snd_dma_buffer playback_dma_buf;
469 unsigned char *capture_buffer; /* suitably aligned address */
470 unsigned char *playback_buffer; /* suitably aligned address */
471
472 pid_t capture_pid;
473 pid_t playback_pid;
474 int running;
475 int system_sample_rate;
476 char *channel_map;
477 int dev;
478 int irq;
479 unsigned long port;
480 void __iomem *iobase;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100481 struct snd_card *card;
482 struct snd_pcm *pcm;
483 struct snd_hwdep *hwdep;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 struct pci_dev *pci;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100485 struct snd_kcontrol *spdif_ctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE];
Remy Brunod7923b22006-10-17 12:41:56 +0200487 unsigned int dds_value; /* last value written to freq register */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488};
489
490/* These tables map the ALSA channels 1..N to the channels that we
491 need to use in order to find the relevant channel buffer. RME
492 refer to this kind of mapping as between "the ADAT channel and
493 the DMA channel." We index it using the logical audio channel,
494 and the value is the DMA channel (i.e. channel buffer number)
495 where the data for that channel can be read/written from/to.
496*/
497
498static char channel_map_df_ss[HDSP_MAX_CHANNELS] = {
499 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
500 18, 19, 20, 21, 22, 23, 24, 25
501};
502
503static char channel_map_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */
504 /* Analog */
505 0, 1, 2, 3, 4, 5, 6, 7,
506 /* ADAT 2 */
507 16, 17, 18, 19, 20, 21, 22, 23,
508 /* SPDIF */
509 24, 25,
510 -1, -1, -1, -1, -1, -1, -1, -1
511};
512
513static char channel_map_ds[HDSP_MAX_CHANNELS] = {
514 /* ADAT channels are remapped */
515 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23,
516 /* channels 12 and 13 are S/PDIF */
517 24, 25,
518 /* others don't exist */
519 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
520};
521
522static char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = {
523 /* ADAT channels */
524 0, 1, 2, 3, 4, 5, 6, 7,
525 /* SPDIF */
526 8, 9,
527 /* Analog */
528 10, 11,
529 /* AO4S-192 and AI4S-192 extension boards */
530 12, 13, 14, 15,
531 /* others don't exist */
532 -1, -1, -1, -1, -1, -1, -1, -1,
533 -1, -1
534};
535
536static char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = {
537 /* ADAT */
538 1, 3, 5, 7,
539 /* SPDIF */
540 8, 9,
541 /* Analog */
542 10, 11,
543 /* AO4S-192 and AI4S-192 extension boards */
544 12, 13, 14, 15,
545 /* others don't exist */
546 -1, -1, -1, -1, -1, -1, -1, -1,
547 -1, -1, -1, -1, -1, -1
548};
549
550static char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = {
551 /* ADAT is disabled in this mode */
552 /* SPDIF */
553 8, 9,
554 /* Analog */
555 10, 11,
556 /* AO4S-192 and AI4S-192 extension boards */
557 12, 13, 14, 15,
558 /* others don't exist */
559 -1, -1, -1, -1, -1, -1, -1, -1,
560 -1, -1, -1, -1, -1, -1, -1, -1,
561 -1, -1
562};
563
564static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
565{
566 dmab->dev.type = SNDRV_DMA_TYPE_DEV;
567 dmab->dev.dev = snd_dma_pci_data(pci);
Takashi Iwaib6a96912005-05-30 18:27:03 +0200568 if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
569 if (dmab->bytes >= size)
570 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 }
Takashi Iwaib6a96912005-05-30 18:27:03 +0200572 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
573 size, dmab) < 0)
574 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 return 0;
576}
577
578static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
579{
Takashi Iwaib6a96912005-05-30 18:27:03 +0200580 if (dmab->area) {
581 dmab->dev.dev = NULL; /* make it anonymous */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
Takashi Iwaib6a96912005-05-30 18:27:03 +0200583 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584}
585
586
Takashi Iwaif40b6892006-07-05 16:51:05 +0200587static struct pci_device_id snd_hdsp_ids[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 {
589 .vendor = PCI_VENDOR_ID_XILINX,
590 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP,
591 .subvendor = PCI_ANY_ID,
592 .subdevice = PCI_ANY_ID,
593 }, /* RME Hammerfall-DSP */
594 { 0, },
595};
596
597MODULE_DEVICE_TABLE(pci, snd_hdsp_ids);
598
599/* prototypes */
Takashi Iwai55e957d2005-11-17 14:52:13 +0100600static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp);
601static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp);
602static int snd_hdsp_enable_io (struct hdsp *hdsp);
603static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp);
604static void snd_hdsp_initialize_channels (struct hdsp *hdsp);
605static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout);
606static int hdsp_autosync_ref(struct hdsp *hdsp);
607static int snd_hdsp_set_defaults(struct hdsp *hdsp);
608static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609
Takashi Iwai55e957d2005-11-17 14:52:13 +0100610static int hdsp_playback_to_output_key (struct hdsp *hdsp, int in, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611{
Remy Brunoa3a68c82007-08-31 12:33:54 +0200612 switch (hdsp->io_type) {
613 case Multiface:
614 case Digiface:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 default:
Andreas Degert192b8e32008-01-16 15:59:48 +0100616 if (hdsp->firmware_rev == 0xa)
617 return (64 * out) + (32 + (in));
618 else
619 return (52 * out) + (26 + (in));
Remy Brunoa3a68c82007-08-31 12:33:54 +0200620 case H9632:
621 return (32 * out) + (16 + (in));
622 case H9652:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 return (52 * out) + (26 + (in));
624 }
625}
626
Takashi Iwai55e957d2005-11-17 14:52:13 +0100627static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628{
Remy Brunoa3a68c82007-08-31 12:33:54 +0200629 switch (hdsp->io_type) {
630 case Multiface:
631 case Digiface:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 default:
Andreas Degert192b8e32008-01-16 15:59:48 +0100633 if (hdsp->firmware_rev == 0xa)
634 return (64 * out) + in;
635 else
636 return (52 * out) + in;
Remy Brunoa3a68c82007-08-31 12:33:54 +0200637 case H9632:
638 return (32 * out) + in;
639 case H9652:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 return (52 * out) + in;
641 }
642}
643
Takashi Iwai55e957d2005-11-17 14:52:13 +0100644static void hdsp_write(struct hdsp *hdsp, int reg, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645{
646 writel(val, hdsp->iobase + reg);
647}
648
Takashi Iwai55e957d2005-11-17 14:52:13 +0100649static unsigned int hdsp_read(struct hdsp *hdsp, int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650{
651 return readl (hdsp->iobase + reg);
652}
653
Takashi Iwai55e957d2005-11-17 14:52:13 +0100654static int hdsp_check_for_iobox (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655{
656
657 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
658 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_ConfigError) {
659 snd_printk ("Hammerfall-DSP: no Digiface or Multiface connected!\n");
660 hdsp->state &= ~HDSP_FirmwareLoaded;
661 return -EIO;
662 }
663 return 0;
664
665}
666
Takashi Iwai55e957d2005-11-17 14:52:13 +0100667static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668
669 int i;
670 unsigned long flags;
671
672 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
673
674 snd_printk ("Hammerfall-DSP: loading firmware\n");
675
676 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM);
677 hdsp_write (hdsp, HDSP_fifoData, 0);
678
679 if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
680 snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n");
681 return -EIO;
682 }
683
684 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
685
686 for (i = 0; i < 24413; ++i) {
687 hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]);
688 if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) {
689 snd_printk ("Hammerfall-DSP: timeout during firmware loading\n");
690 return -EIO;
691 }
692 }
693
Takashi Iwaib0b98112005-10-20 18:29:58 +0200694 ssleep(3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695
696 if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
697 snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n");
698 return -EIO;
699 }
700
701#ifdef SNDRV_BIG_ENDIAN
702 hdsp->control2_register = HDSP_BIGENDIAN_MODE;
703#else
704 hdsp->control2_register = 0;
705#endif
706 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
707 snd_printk ("Hammerfall-DSP: finished firmware loading\n");
708
709 }
710 if (hdsp->state & HDSP_InitializationComplete) {
Takashi Iwaib0b98112005-10-20 18:29:58 +0200711 snd_printk(KERN_INFO "Hammerfall-DSP: firmware loaded from cache, restoring defaults\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 spin_lock_irqsave(&hdsp->lock, flags);
713 snd_hdsp_set_defaults(hdsp);
714 spin_unlock_irqrestore(&hdsp->lock, flags);
715 }
716
717 hdsp->state |= HDSP_FirmwareLoaded;
718
719 return 0;
720}
721
Takashi Iwai55e957d2005-11-17 14:52:13 +0100722static int hdsp_get_iobox_version (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723{
724 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
725
726 hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM);
727 hdsp_write (hdsp, HDSP_fifoData, 0);
Takashi Iwaib0b98112005-10-20 18:29:58 +0200728 if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730
731 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
732 hdsp_write (hdsp, HDSP_fifoData, 0);
733
734 if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT)) {
735 hdsp->io_type = Multiface;
736 hdsp_write (hdsp, HDSP_control2Reg, HDSP_VERSION_BIT);
737 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
738 hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT);
739 } else {
740 hdsp->io_type = Digiface;
741 }
742 } else {
743 /* firmware was already loaded, get iobox type */
Takashi Iwaib0b98112005-10-20 18:29:58 +0200744 if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 hdsp->io_type = Multiface;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200746 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 hdsp->io_type = Digiface;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 }
749 return 0;
750}
751
752
Takashi Iwai311e70a2006-09-06 12:13:37 +0200753#ifdef HDSP_FW_LOADER
Takashi Iwai92eed662008-02-22 18:35:56 +0100754static int hdsp_request_fw_loader(struct hdsp *hdsp);
Takashi Iwai311e70a2006-09-06 12:13:37 +0200755#endif
756
757static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758{
Takashi Iwai311e70a2006-09-06 12:13:37 +0200759 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
760 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 hdsp->state &= ~HDSP_FirmwareLoaded;
Takashi Iwai311e70a2006-09-06 12:13:37 +0200763 if (! load_on_demand)
Takashi Iwaib0b98112005-10-20 18:29:58 +0200764 return -EIO;
Takashi Iwai311e70a2006-09-06 12:13:37 +0200765 snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +0200766 /* try to load firmware */
Takashi Iwai311e70a2006-09-06 12:13:37 +0200767 if (! (hdsp->state & HDSP_FirmwareCached)) {
768#ifdef HDSP_FW_LOADER
769 if (! hdsp_request_fw_loader(hdsp))
770 return 0;
771#endif
772 snd_printk(KERN_ERR
773 "Hammerfall-DSP: No firmware loaded nor "
774 "cached, please upload firmware.\n");
775 return -EIO;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200776 }
Takashi Iwai311e70a2006-09-06 12:13:37 +0200777 if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
778 snd_printk(KERN_ERR
779 "Hammerfall-DSP: Firmware loading from "
780 "cache failed, please upload manually.\n");
781 return -EIO;
782 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 }
784 return 0;
785}
786
787
Takashi Iwai55e957d2005-11-17 14:52:13 +0100788static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789{
790 int i;
791
792 /* the fifoStatus registers reports on how many words
793 are available in the command FIFO.
794 */
795
796 for (i = 0; i < timeout; i++) {
797
798 if ((int)(hdsp_read (hdsp, HDSP_fifoStatus) & 0xff) <= count)
799 return 0;
800
801 /* not very friendly, but we only do this during a firmware
802 load and changing the mixer, so we just put up with it.
803 */
804
805 udelay (100);
806 }
807
808 snd_printk ("Hammerfall-DSP: wait for FIFO status <= %d failed after %d iterations\n",
809 count, timeout);
810 return -1;
811}
812
Takashi Iwai55e957d2005-11-17 14:52:13 +0100813static int hdsp_read_gain (struct hdsp *hdsp, unsigned int addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814{
Takashi Iwaib0b98112005-10-20 18:29:58 +0200815 if (addr >= HDSP_MATRIX_MIXER_SIZE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200817
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 return hdsp->mixer_matrix[addr];
819}
820
Takashi Iwai55e957d2005-11-17 14:52:13 +0100821static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822{
823 unsigned int ad;
824
825 if (addr >= HDSP_MATRIX_MIXER_SIZE)
826 return -1;
827
828 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) {
829
830 /* from martin bjornsen:
831
832 "You can only write dwords to the
833 mixer memory which contain two
834 mixer values in the low and high
835 word. So if you want to change
836 value 0 you have to read value 1
837 from the cache and write both to
838 the first dword in the mixer
839 memory."
840 */
841
Takashi Iwaib0b98112005-10-20 18:29:58 +0200842 if (hdsp->io_type == H9632 && addr >= 512)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844
Takashi Iwaib0b98112005-10-20 18:29:58 +0200845 if (hdsp->io_type == H9652 && addr >= 1352)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847
848 hdsp->mixer_matrix[addr] = data;
849
850
851 /* `addr' addresses a 16-bit wide address, but
852 the address space accessed via hdsp_write
853 uses byte offsets. put another way, addr
854 varies from 0 to 1351, but to access the
855 corresponding memory location, we need
856 to access 0 to 2703 ...
857 */
858 ad = addr/2;
859
860 hdsp_write (hdsp, 4096 + (ad*4),
861 (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) +
862 hdsp->mixer_matrix[addr&0x7fe]);
863
864 return 0;
865
866 } else {
867
868 ad = (addr << 16) + data;
869
Takashi Iwaib0b98112005-10-20 18:29:58 +0200870 if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872
873 hdsp_write (hdsp, HDSP_fifoData, ad);
874 hdsp->mixer_matrix[addr] = data;
875
876 }
877
878 return 0;
879}
880
Takashi Iwai55e957d2005-11-17 14:52:13 +0100881static int snd_hdsp_use_is_exclusive(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882{
883 unsigned long flags;
884 int ret = 1;
885
886 spin_lock_irqsave(&hdsp->lock, flags);
887 if ((hdsp->playback_pid != hdsp->capture_pid) &&
Takashi Iwaib0b98112005-10-20 18:29:58 +0200888 (hdsp->playback_pid >= 0) && (hdsp->capture_pid >= 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 spin_unlock_irqrestore(&hdsp->lock, flags);
891 return ret;
892}
893
Takashi Iwai55e957d2005-11-17 14:52:13 +0100894static int hdsp_spdif_sample_rate(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895{
896 unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);
897 unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);
898
Remy Bruno47ba97f2008-02-22 17:57:02 +0100899 /* For the 9632, the mask is different */
900 if (hdsp->io_type == H9632)
901 rate_bits = (status & HDSP_spdifFrequencyMask_9632);
902
Takashi Iwaib0b98112005-10-20 18:29:58 +0200903 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
906 switch (rate_bits) {
907 case HDSP_spdifFrequency32KHz: return 32000;
908 case HDSP_spdifFrequency44_1KHz: return 44100;
909 case HDSP_spdifFrequency48KHz: return 48000;
910 case HDSP_spdifFrequency64KHz: return 64000;
911 case HDSP_spdifFrequency88_2KHz: return 88200;
912 case HDSP_spdifFrequency96KHz: return 96000;
913 case HDSP_spdifFrequency128KHz:
914 if (hdsp->io_type == H9632) return 128000;
915 break;
916 case HDSP_spdifFrequency176_4KHz:
917 if (hdsp->io_type == H9632) return 176400;
918 break;
919 case HDSP_spdifFrequency192KHz:
920 if (hdsp->io_type == H9632) return 192000;
921 break;
922 default:
923 break;
924 }
925 snd_printk ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status);
926 return 0;
927}
928
Remy Bruno47ba97f2008-02-22 17:57:02 +0100929static int hdsp_external_sample_rate(struct hdsp *hdsp)
930{
931 unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
932 unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
933
934 /* For the 9632 card, there seems to be no bit for indicating external
935 * sample rate greater than 96kHz. The card reports the corresponding
936 * single speed. So the best means seems to get spdif rate when
937 * autosync reference is spdif */
938 if (hdsp->io_type == H9632 &&
939 hdsp_autosync_ref(hdsp) == HDSP_AUTOSYNC_FROM_SPDIF)
940 return hdsp_spdif_sample_rate(hdsp);
941
942 switch (rate_bits) {
943 case HDSP_systemFrequency32: return 32000;
944 case HDSP_systemFrequency44_1: return 44100;
945 case HDSP_systemFrequency48: return 48000;
946 case HDSP_systemFrequency64: return 64000;
947 case HDSP_systemFrequency88_2: return 88200;
948 case HDSP_systemFrequency96: return 96000;
949 default:
950 return 0;
951 }
952}
953
Takashi Iwai55e957d2005-11-17 14:52:13 +0100954static void hdsp_compute_period_size(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955{
956 hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));
957}
958
Takashi Iwai55e957d2005-11-17 14:52:13 +0100959static snd_pcm_uframes_t hdsp_hw_pointer(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960{
961 int position;
962
963 position = hdsp_read(hdsp, HDSP_statusRegister);
964
Takashi Iwaib0b98112005-10-20 18:29:58 +0200965 if (!hdsp->precise_ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 return (position & HDSP_BufferID) ? (hdsp->period_bytes / 4) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967
968 position &= HDSP_BufferPositionMask;
969 position /= 4;
970 position &= (hdsp->period_bytes/2) - 1;
971 return position;
972}
973
Takashi Iwai55e957d2005-11-17 14:52:13 +0100974static void hdsp_reset_hw_pointer(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975{
976 hdsp_write (hdsp, HDSP_resetPointer, 0);
Remy Brunod7923b22006-10-17 12:41:56 +0200977 if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152)
978 /* HDSP_resetPointer = HDSP_freqReg, which is strange and
979 * requires (?) to write again DDS value after a reset pointer
980 * (at least, it works like this) */
981 hdsp_write (hdsp, HDSP_freqReg, hdsp->dds_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982}
983
Takashi Iwai55e957d2005-11-17 14:52:13 +0100984static void hdsp_start_audio(struct hdsp *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985{
986 s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start);
987 hdsp_write(s, HDSP_controlRegister, s->control_register);
988}
989
Takashi Iwai55e957d2005-11-17 14:52:13 +0100990static void hdsp_stop_audio(struct hdsp *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991{
992 s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable);
993 hdsp_write(s, HDSP_controlRegister, s->control_register);
994}
995
Takashi Iwai55e957d2005-11-17 14:52:13 +0100996static void hdsp_silence_playback(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997{
998 memset(hdsp->playback_buffer, 0, HDSP_DMA_AREA_BYTES);
999}
1000
Takashi Iwai55e957d2005-11-17 14:52:13 +01001001static int hdsp_set_interrupt_interval(struct hdsp *s, unsigned int frames)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002{
1003 int n;
1004
1005 spin_lock_irq(&s->lock);
1006
1007 frames >>= 7;
1008 n = 0;
1009 while (frames) {
1010 n++;
1011 frames >>= 1;
1012 }
1013
1014 s->control_register &= ~HDSP_LatencyMask;
1015 s->control_register |= hdsp_encode_latency(n);
1016
1017 hdsp_write(s, HDSP_controlRegister, s->control_register);
1018
1019 hdsp_compute_period_size(s);
1020
1021 spin_unlock_irq(&s->lock);
1022
1023 return 0;
1024}
1025
Remy Brunod7923b22006-10-17 12:41:56 +02001026static void hdsp_set_dds_value(struct hdsp *hdsp, int rate)
1027{
1028 u64 n;
1029 u32 r;
1030
1031 if (rate >= 112000)
1032 rate /= 4;
1033 else if (rate >= 56000)
1034 rate /= 2;
1035
Julian Cablee4b60882007-03-19 11:44:40 +01001036 n = DDS_NUMERATOR;
Remy Brunod7923b22006-10-17 12:41:56 +02001037 div64_32(&n, rate, &r);
1038 /* n should be less than 2^32 for being written to FREQ register */
1039 snd_assert((n >> 32) == 0);
1040 /* HDSP_freqReg and HDSP_resetPointer are the same, so keep the DDS
1041 value to write it after a reset */
1042 hdsp->dds_value = n;
1043 hdsp_write(hdsp, HDSP_freqReg, hdsp->dds_value);
1044}
1045
Takashi Iwai55e957d2005-11-17 14:52:13 +01001046static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047{
1048 int reject_if_open = 0;
1049 int current_rate;
1050 int rate_bits;
1051
1052 /* ASSUMPTION: hdsp->lock is either held, or
1053 there is no need for it (e.g. during module
1054 initialization).
1055 */
1056
1057 if (!(hdsp->control_register & HDSP_ClockModeMaster)) {
1058 if (called_internally) {
1059 /* request from ctl or card initialization */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001060 snd_printk(KERN_ERR "Hammerfall-DSP: device is not running as a clock master: cannot set sample rate.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 return -1;
1062 } else {
1063 /* hw_param request while in AutoSync mode */
1064 int external_freq = hdsp_external_sample_rate(hdsp);
1065 int spdif_freq = hdsp_spdif_sample_rate(hdsp);
1066
Takashi Iwaib0b98112005-10-20 18:29:58 +02001067 if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1))
1068 snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in double speed mode\n");
1069 else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1))
1070 snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in quad speed mode\n");
1071 else if (rate != external_freq) {
1072 snd_printk(KERN_INFO "Hammerfall-DSP: No AutoSync source for requested rate\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 return -1;
1074 }
1075 }
1076 }
1077
1078 current_rate = hdsp->system_sample_rate;
1079
1080 /* Changing from a "single speed" to a "double speed" rate is
1081 not allowed if any substreams are open. This is because
1082 such a change causes a shift in the location of
1083 the DMA buffers and a reduction in the number of available
1084 buffers.
1085
1086 Note that a similar but essentially insoluble problem
1087 exists for externally-driven rate changes. All we can do
1088 is to flag rate changes in the read/write routines. */
1089
Takashi Iwaib0b98112005-10-20 18:29:58 +02001090 if (rate > 96000 && hdsp->io_type != H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092
1093 switch (rate) {
1094 case 32000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001095 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 rate_bits = HDSP_Frequency32KHz;
1098 break;
1099 case 44100:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001100 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 rate_bits = HDSP_Frequency44_1KHz;
1103 break;
1104 case 48000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001105 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 rate_bits = HDSP_Frequency48KHz;
1108 break;
1109 case 64000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001110 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 rate_bits = HDSP_Frequency64KHz;
1113 break;
1114 case 88200:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001115 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 rate_bits = HDSP_Frequency88_2KHz;
1118 break;
1119 case 96000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001120 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 rate_bits = HDSP_Frequency96KHz;
1123 break;
1124 case 128000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001125 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 rate_bits = HDSP_Frequency128KHz;
1128 break;
1129 case 176400:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001130 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 rate_bits = HDSP_Frequency176_4KHz;
1133 break;
1134 case 192000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001135 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 rate_bits = HDSP_Frequency192KHz;
1138 break;
1139 default:
1140 return -EINVAL;
1141 }
1142
1143 if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) {
1144 snd_printk ("Hammerfall-DSP: cannot change speed mode (capture PID = %d, playback PID = %d)\n",
1145 hdsp->capture_pid,
1146 hdsp->playback_pid);
1147 return -EBUSY;
1148 }
1149
1150 hdsp->control_register &= ~HDSP_FrequencyMask;
1151 hdsp->control_register |= rate_bits;
1152 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1153
Remy Brunod7923b22006-10-17 12:41:56 +02001154 /* For HDSP9632 rev 152, need to set DDS value in FREQ register */
1155 if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152)
1156 hdsp_set_dds_value(hdsp, rate);
1157
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 if (rate >= 128000) {
1159 hdsp->channel_map = channel_map_H9632_qs;
1160 } else if (rate > 48000) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001161 if (hdsp->io_type == H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 hdsp->channel_map = channel_map_H9632_ds;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001163 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 hdsp->channel_map = channel_map_ds;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 } else {
1166 switch (hdsp->io_type) {
1167 case Multiface:
1168 hdsp->channel_map = channel_map_mf_ss;
1169 break;
1170 case Digiface:
1171 case H9652:
1172 hdsp->channel_map = channel_map_df_ss;
1173 break;
1174 case H9632:
1175 hdsp->channel_map = channel_map_H9632_ss;
1176 break;
1177 default:
1178 /* should never happen */
1179 break;
1180 }
1181 }
1182
1183 hdsp->system_sample_rate = rate;
1184
1185 return 0;
1186}
1187
1188/*----------------------------------------------------------------------------
1189 MIDI
1190 ----------------------------------------------------------------------------*/
1191
Takashi Iwai55e957d2005-11-17 14:52:13 +01001192static unsigned char snd_hdsp_midi_read_byte (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193{
1194 /* the hardware already does the relevant bit-mask with 0xff */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001195 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 return hdsp_read(hdsp, HDSP_midiDataIn1);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001197 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 return hdsp_read(hdsp, HDSP_midiDataIn0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199}
1200
Takashi Iwai55e957d2005-11-17 14:52:13 +01001201static void snd_hdsp_midi_write_byte (struct hdsp *hdsp, int id, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202{
1203 /* the hardware already does the relevant bit-mask with 0xff */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001204 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 hdsp_write(hdsp, HDSP_midiDataOut1, val);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001206 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 hdsp_write(hdsp, HDSP_midiDataOut0, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208}
1209
Takashi Iwai55e957d2005-11-17 14:52:13 +01001210static int snd_hdsp_midi_input_available (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001212 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 return (hdsp_read(hdsp, HDSP_midiStatusIn1) & 0xff);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001214 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 return (hdsp_read(hdsp, HDSP_midiStatusIn0) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216}
1217
Takashi Iwai55e957d2005-11-17 14:52:13 +01001218static int snd_hdsp_midi_output_possible (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219{
1220 int fifo_bytes_used;
1221
Takashi Iwaib0b98112005-10-20 18:29:58 +02001222 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut1) & 0xff;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001224 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut0) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226
Takashi Iwaib0b98112005-10-20 18:29:58 +02001227 if (fifo_bytes_used < 128)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 return 128 - fifo_bytes_used;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001229 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231}
1232
Takashi Iwai55e957d2005-11-17 14:52:13 +01001233static void snd_hdsp_flush_midi_input (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001235 while (snd_hdsp_midi_input_available (hdsp, id))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 snd_hdsp_midi_read_byte (hdsp, id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237}
1238
Takashi Iwai55e957d2005-11-17 14:52:13 +01001239static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240{
1241 unsigned long flags;
1242 int n_pending;
1243 int to_write;
1244 int i;
1245 unsigned char buf[128];
1246
1247 /* Output is not interrupt driven */
1248
1249 spin_lock_irqsave (&hmidi->lock, flags);
1250 if (hmidi->output) {
1251 if (!snd_rawmidi_transmit_empty (hmidi->output)) {
1252 if ((n_pending = snd_hdsp_midi_output_possible (hmidi->hdsp, hmidi->id)) > 0) {
1253 if (n_pending > (int)sizeof (buf))
1254 n_pending = sizeof (buf);
1255
1256 if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {
1257 for (i = 0; i < to_write; ++i)
1258 snd_hdsp_midi_write_byte (hmidi->hdsp, hmidi->id, buf[i]);
1259 }
1260 }
1261 }
1262 }
1263 spin_unlock_irqrestore (&hmidi->lock, flags);
1264 return 0;
1265}
1266
Takashi Iwai55e957d2005-11-17 14:52:13 +01001267static int snd_hdsp_midi_input_read (struct hdsp_midi *hmidi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268{
1269 unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
1270 unsigned long flags;
1271 int n_pending;
1272 int i;
1273
1274 spin_lock_irqsave (&hmidi->lock, flags);
1275 if ((n_pending = snd_hdsp_midi_input_available (hmidi->hdsp, hmidi->id)) > 0) {
1276 if (hmidi->input) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001277 if (n_pending > (int)sizeof (buf))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 n_pending = sizeof (buf);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001279 for (i = 0; i < n_pending; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 buf[i] = snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001281 if (n_pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 snd_rawmidi_receive (hmidi->input, buf, n_pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 } else {
1284 /* flush the MIDI input FIFO */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001285 while (--n_pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 }
1288 }
1289 hmidi->pending = 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001290 if (hmidi->id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 hmidi->hdsp->control_register |= HDSP_Midi1InterruptEnable;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001292 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 hmidi->hdsp->control_register |= HDSP_Midi0InterruptEnable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 hdsp_write(hmidi->hdsp, HDSP_controlRegister, hmidi->hdsp->control_register);
1295 spin_unlock_irqrestore (&hmidi->lock, flags);
1296 return snd_hdsp_midi_output_write (hmidi);
1297}
1298
Takashi Iwai55e957d2005-11-17 14:52:13 +01001299static void snd_hdsp_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001301 struct hdsp *hdsp;
1302 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 unsigned long flags;
1304 u32 ie;
1305
Takashi Iwai55e957d2005-11-17 14:52:13 +01001306 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 hdsp = hmidi->hdsp;
1308 ie = hmidi->id ? HDSP_Midi1InterruptEnable : HDSP_Midi0InterruptEnable;
1309 spin_lock_irqsave (&hdsp->lock, flags);
1310 if (up) {
1311 if (!(hdsp->control_register & ie)) {
1312 snd_hdsp_flush_midi_input (hdsp, hmidi->id);
1313 hdsp->control_register |= ie;
1314 }
1315 } else {
1316 hdsp->control_register &= ~ie;
1317 tasklet_kill(&hdsp->midi_tasklet);
1318 }
1319
1320 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1321 spin_unlock_irqrestore (&hdsp->lock, flags);
1322}
1323
1324static void snd_hdsp_midi_output_timer(unsigned long data)
1325{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001326 struct hdsp_midi *hmidi = (struct hdsp_midi *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 unsigned long flags;
1328
1329 snd_hdsp_midi_output_write(hmidi);
1330 spin_lock_irqsave (&hmidi->lock, flags);
1331
1332 /* this does not bump hmidi->istimer, because the
1333 kernel automatically removed the timer when it
1334 expired, and we are now adding it back, thus
1335 leaving istimer wherever it was set before.
1336 */
1337
1338 if (hmidi->istimer) {
1339 hmidi->timer.expires = 1 + jiffies;
1340 add_timer(&hmidi->timer);
1341 }
1342
1343 spin_unlock_irqrestore (&hmidi->lock, flags);
1344}
1345
Takashi Iwai55e957d2005-11-17 14:52:13 +01001346static void snd_hdsp_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001348 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 unsigned long flags;
1350
Takashi Iwai55e957d2005-11-17 14:52:13 +01001351 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 spin_lock_irqsave (&hmidi->lock, flags);
1353 if (up) {
1354 if (!hmidi->istimer) {
1355 init_timer(&hmidi->timer);
1356 hmidi->timer.function = snd_hdsp_midi_output_timer;
1357 hmidi->timer.data = (unsigned long) hmidi;
1358 hmidi->timer.expires = 1 + jiffies;
1359 add_timer(&hmidi->timer);
1360 hmidi->istimer++;
1361 }
1362 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001363 if (hmidi->istimer && --hmidi->istimer <= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 del_timer (&hmidi->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 }
1366 spin_unlock_irqrestore (&hmidi->lock, flags);
1367 if (up)
1368 snd_hdsp_midi_output_write(hmidi);
1369}
1370
Takashi Iwai55e957d2005-11-17 14:52:13 +01001371static int snd_hdsp_midi_input_open(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001373 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374
Takashi Iwai55e957d2005-11-17 14:52:13 +01001375 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 spin_lock_irq (&hmidi->lock);
1377 snd_hdsp_flush_midi_input (hmidi->hdsp, hmidi->id);
1378 hmidi->input = substream;
1379 spin_unlock_irq (&hmidi->lock);
1380
1381 return 0;
1382}
1383
Takashi Iwai55e957d2005-11-17 14:52:13 +01001384static int snd_hdsp_midi_output_open(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001386 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
Takashi Iwai55e957d2005-11-17 14:52:13 +01001388 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 spin_lock_irq (&hmidi->lock);
1390 hmidi->output = substream;
1391 spin_unlock_irq (&hmidi->lock);
1392
1393 return 0;
1394}
1395
Takashi Iwai55e957d2005-11-17 14:52:13 +01001396static int snd_hdsp_midi_input_close(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001398 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399
1400 snd_hdsp_midi_input_trigger (substream, 0);
1401
Takashi Iwai55e957d2005-11-17 14:52:13 +01001402 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 spin_lock_irq (&hmidi->lock);
1404 hmidi->input = NULL;
1405 spin_unlock_irq (&hmidi->lock);
1406
1407 return 0;
1408}
1409
Takashi Iwai55e957d2005-11-17 14:52:13 +01001410static int snd_hdsp_midi_output_close(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001412 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
1414 snd_hdsp_midi_output_trigger (substream, 0);
1415
Takashi Iwai55e957d2005-11-17 14:52:13 +01001416 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 spin_lock_irq (&hmidi->lock);
1418 hmidi->output = NULL;
1419 spin_unlock_irq (&hmidi->lock);
1420
1421 return 0;
1422}
1423
Takashi Iwai55e957d2005-11-17 14:52:13 +01001424static struct snd_rawmidi_ops snd_hdsp_midi_output =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425{
1426 .open = snd_hdsp_midi_output_open,
1427 .close = snd_hdsp_midi_output_close,
1428 .trigger = snd_hdsp_midi_output_trigger,
1429};
1430
Takashi Iwai55e957d2005-11-17 14:52:13 +01001431static struct snd_rawmidi_ops snd_hdsp_midi_input =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432{
1433 .open = snd_hdsp_midi_input_open,
1434 .close = snd_hdsp_midi_input_close,
1435 .trigger = snd_hdsp_midi_input_trigger,
1436};
1437
Takashi Iwaif40b6892006-07-05 16:51:05 +02001438static int snd_hdsp_create_midi (struct snd_card *card, struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439{
1440 char buf[32];
1441
1442 hdsp->midi[id].id = id;
1443 hdsp->midi[id].rmidi = NULL;
1444 hdsp->midi[id].input = NULL;
1445 hdsp->midi[id].output = NULL;
1446 hdsp->midi[id].hdsp = hdsp;
1447 hdsp->midi[id].istimer = 0;
1448 hdsp->midi[id].pending = 0;
1449 spin_lock_init (&hdsp->midi[id].lock);
1450
1451 sprintf (buf, "%s MIDI %d", card->shortname, id+1);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001452 if (snd_rawmidi_new (card, buf, id, 1, 1, &hdsp->midi[id].rmidi) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454
1455 sprintf (hdsp->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);
1456 hdsp->midi[id].rmidi->private_data = &hdsp->midi[id];
1457
1458 snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdsp_midi_output);
1459 snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdsp_midi_input);
1460
1461 hdsp->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
1462 SNDRV_RAWMIDI_INFO_INPUT |
1463 SNDRV_RAWMIDI_INFO_DUPLEX;
1464
1465 return 0;
1466}
1467
1468/*-----------------------------------------------------------------------------
1469 Control Interface
1470 ----------------------------------------------------------------------------*/
1471
Takashi Iwai55e957d2005-11-17 14:52:13 +01001472static u32 snd_hdsp_convert_from_aes(struct snd_aes_iec958 *aes)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473{
1474 u32 val = 0;
1475 val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? HDSP_SPDIFProfessional : 0;
1476 val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? HDSP_SPDIFNonAudio : 0;
1477 if (val & HDSP_SPDIFProfessional)
1478 val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0;
1479 else
1480 val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0;
1481 return val;
1482}
1483
Takashi Iwai55e957d2005-11-17 14:52:13 +01001484static void snd_hdsp_convert_to_aes(struct snd_aes_iec958 *aes, u32 val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485{
1486 aes->status[0] = ((val & HDSP_SPDIFProfessional) ? IEC958_AES0_PROFESSIONAL : 0) |
1487 ((val & HDSP_SPDIFNonAudio) ? IEC958_AES0_NONAUDIO : 0);
1488 if (val & HDSP_SPDIFProfessional)
1489 aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0;
1490 else
1491 aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_CON_EMPHASIS_5015 : 0;
1492}
1493
Takashi Iwai55e957d2005-11-17 14:52:13 +01001494static int snd_hdsp_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495{
1496 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1497 uinfo->count = 1;
1498 return 0;
1499}
1500
Takashi Iwai55e957d2005-11-17 14:52:13 +01001501static int snd_hdsp_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001503 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504
1505 snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif);
1506 return 0;
1507}
1508
Takashi Iwai55e957d2005-11-17 14:52:13 +01001509static int snd_hdsp_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001511 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 int change;
1513 u32 val;
1514
1515 val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
1516 spin_lock_irq(&hdsp->lock);
1517 change = val != hdsp->creg_spdif;
1518 hdsp->creg_spdif = val;
1519 spin_unlock_irq(&hdsp->lock);
1520 return change;
1521}
1522
Takashi Iwai55e957d2005-11-17 14:52:13 +01001523static int snd_hdsp_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524{
1525 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1526 uinfo->count = 1;
1527 return 0;
1528}
1529
Takashi Iwai55e957d2005-11-17 14:52:13 +01001530static int snd_hdsp_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001532 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533
1534 snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream);
1535 return 0;
1536}
1537
Takashi Iwai55e957d2005-11-17 14:52:13 +01001538static int snd_hdsp_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001540 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 int change;
1542 u32 val;
1543
1544 val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
1545 spin_lock_irq(&hdsp->lock);
1546 change = val != hdsp->creg_spdif_stream;
1547 hdsp->creg_spdif_stream = val;
1548 hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
1549 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= val);
1550 spin_unlock_irq(&hdsp->lock);
1551 return change;
1552}
1553
Takashi Iwai55e957d2005-11-17 14:52:13 +01001554static int snd_hdsp_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555{
1556 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1557 uinfo->count = 1;
1558 return 0;
1559}
1560
Takashi Iwai55e957d2005-11-17 14:52:13 +01001561static int snd_hdsp_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562{
1563 ucontrol->value.iec958.status[0] = kcontrol->private_value;
1564 return 0;
1565}
1566
1567#define HDSP_SPDIF_IN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001568{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 .name = xname, \
1570 .index = xindex, \
1571 .info = snd_hdsp_info_spdif_in, \
1572 .get = snd_hdsp_get_spdif_in, \
1573 .put = snd_hdsp_put_spdif_in }
1574
Takashi Iwai55e957d2005-11-17 14:52:13 +01001575static unsigned int hdsp_spdif_in(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576{
1577 return hdsp_decode_spdif_in(hdsp->control_register & HDSP_SPDIFInputMask);
1578}
1579
Takashi Iwai55e957d2005-11-17 14:52:13 +01001580static int hdsp_set_spdif_input(struct hdsp *hdsp, int in)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581{
1582 hdsp->control_register &= ~HDSP_SPDIFInputMask;
1583 hdsp->control_register |= hdsp_encode_spdif_in(in);
1584 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1585 return 0;
1586}
1587
Takashi Iwai55e957d2005-11-17 14:52:13 +01001588static int snd_hdsp_info_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589{
1590 static char *texts[4] = {"Optical", "Coaxial", "Internal", "AES"};
Takashi Iwai55e957d2005-11-17 14:52:13 +01001591 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592
1593 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1594 uinfo->count = 1;
1595 uinfo->value.enumerated.items = ((hdsp->io_type == H9632) ? 4 : 3);
1596 if (uinfo->value.enumerated.item > ((hdsp->io_type == H9632) ? 3 : 2))
1597 uinfo->value.enumerated.item = ((hdsp->io_type == H9632) ? 3 : 2);
1598 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1599 return 0;
1600}
1601
Takashi Iwai55e957d2005-11-17 14:52:13 +01001602static int snd_hdsp_get_spdif_in(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
1606 ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp);
1607 return 0;
1608}
1609
Takashi Iwai55e957d2005-11-17 14:52:13 +01001610static int snd_hdsp_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001612 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 int change;
1614 unsigned int val;
1615
1616 if (!snd_hdsp_use_is_exclusive(hdsp))
1617 return -EBUSY;
1618 val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3);
1619 spin_lock_irq(&hdsp->lock);
1620 change = val != hdsp_spdif_in(hdsp);
1621 if (change)
1622 hdsp_set_spdif_input(hdsp, val);
1623 spin_unlock_irq(&hdsp->lock);
1624 return change;
1625}
1626
1627#define HDSP_SPDIF_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001628{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 .info = snd_hdsp_info_spdif_bits, \
1630 .get = snd_hdsp_get_spdif_out, .put = snd_hdsp_put_spdif_out }
1631
Takashi Iwai55e957d2005-11-17 14:52:13 +01001632static int hdsp_spdif_out(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633{
1634 return (hdsp->control_register & HDSP_SPDIFOpticalOut) ? 1 : 0;
1635}
1636
Takashi Iwai55e957d2005-11-17 14:52:13 +01001637static int hdsp_set_spdif_output(struct hdsp *hdsp, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001639 if (out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 hdsp->control_register |= HDSP_SPDIFOpticalOut;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001641 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 hdsp->control_register &= ~HDSP_SPDIFOpticalOut;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1644 return 0;
1645}
1646
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001647#define snd_hdsp_info_spdif_bits snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648
Takashi Iwai55e957d2005-11-17 14:52:13 +01001649static int snd_hdsp_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001651 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652
1653 ucontrol->value.integer.value[0] = hdsp_spdif_out(hdsp);
1654 return 0;
1655}
1656
Takashi Iwai55e957d2005-11-17 14:52:13 +01001657static int snd_hdsp_put_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001659 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 int change;
1661 unsigned int val;
1662
1663 if (!snd_hdsp_use_is_exclusive(hdsp))
1664 return -EBUSY;
1665 val = ucontrol->value.integer.value[0] & 1;
1666 spin_lock_irq(&hdsp->lock);
1667 change = (int)val != hdsp_spdif_out(hdsp);
1668 hdsp_set_spdif_output(hdsp, val);
1669 spin_unlock_irq(&hdsp->lock);
1670 return change;
1671}
1672
1673#define HDSP_SPDIF_PROFESSIONAL(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001674{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 .info = snd_hdsp_info_spdif_bits, \
1676 .get = snd_hdsp_get_spdif_professional, .put = snd_hdsp_put_spdif_professional }
1677
Takashi Iwai55e957d2005-11-17 14:52:13 +01001678static int hdsp_spdif_professional(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679{
1680 return (hdsp->control_register & HDSP_SPDIFProfessional) ? 1 : 0;
1681}
1682
Takashi Iwai55e957d2005-11-17 14:52:13 +01001683static int hdsp_set_spdif_professional(struct hdsp *hdsp, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001685 if (val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 hdsp->control_register |= HDSP_SPDIFProfessional;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001687 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 hdsp->control_register &= ~HDSP_SPDIFProfessional;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1690 return 0;
1691}
1692
Takashi Iwai55e957d2005-11-17 14:52:13 +01001693static int snd_hdsp_get_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001695 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696
1697 ucontrol->value.integer.value[0] = hdsp_spdif_professional(hdsp);
1698 return 0;
1699}
1700
Takashi Iwai55e957d2005-11-17 14:52:13 +01001701static int snd_hdsp_put_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001703 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 int change;
1705 unsigned int val;
1706
1707 if (!snd_hdsp_use_is_exclusive(hdsp))
1708 return -EBUSY;
1709 val = ucontrol->value.integer.value[0] & 1;
1710 spin_lock_irq(&hdsp->lock);
1711 change = (int)val != hdsp_spdif_professional(hdsp);
1712 hdsp_set_spdif_professional(hdsp, val);
1713 spin_unlock_irq(&hdsp->lock);
1714 return change;
1715}
1716
1717#define HDSP_SPDIF_EMPHASIS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001718{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 .info = snd_hdsp_info_spdif_bits, \
1720 .get = snd_hdsp_get_spdif_emphasis, .put = snd_hdsp_put_spdif_emphasis }
1721
Takashi Iwai55e957d2005-11-17 14:52:13 +01001722static int hdsp_spdif_emphasis(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723{
1724 return (hdsp->control_register & HDSP_SPDIFEmphasis) ? 1 : 0;
1725}
1726
Takashi Iwai55e957d2005-11-17 14:52:13 +01001727static int hdsp_set_spdif_emphasis(struct hdsp *hdsp, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001729 if (val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 hdsp->control_register |= HDSP_SPDIFEmphasis;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001731 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 hdsp->control_register &= ~HDSP_SPDIFEmphasis;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1734 return 0;
1735}
1736
Takashi Iwai55e957d2005-11-17 14:52:13 +01001737static int snd_hdsp_get_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001739 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740
1741 ucontrol->value.integer.value[0] = hdsp_spdif_emphasis(hdsp);
1742 return 0;
1743}
1744
Takashi Iwai55e957d2005-11-17 14:52:13 +01001745static int snd_hdsp_put_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001747 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 int change;
1749 unsigned int val;
1750
1751 if (!snd_hdsp_use_is_exclusive(hdsp))
1752 return -EBUSY;
1753 val = ucontrol->value.integer.value[0] & 1;
1754 spin_lock_irq(&hdsp->lock);
1755 change = (int)val != hdsp_spdif_emphasis(hdsp);
1756 hdsp_set_spdif_emphasis(hdsp, val);
1757 spin_unlock_irq(&hdsp->lock);
1758 return change;
1759}
1760
1761#define HDSP_SPDIF_NON_AUDIO(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001762{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 .info = snd_hdsp_info_spdif_bits, \
1764 .get = snd_hdsp_get_spdif_nonaudio, .put = snd_hdsp_put_spdif_nonaudio }
1765
Takashi Iwai55e957d2005-11-17 14:52:13 +01001766static int hdsp_spdif_nonaudio(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767{
1768 return (hdsp->control_register & HDSP_SPDIFNonAudio) ? 1 : 0;
1769}
1770
Takashi Iwai55e957d2005-11-17 14:52:13 +01001771static int hdsp_set_spdif_nonaudio(struct hdsp *hdsp, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001773 if (val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 hdsp->control_register |= HDSP_SPDIFNonAudio;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001775 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776 hdsp->control_register &= ~HDSP_SPDIFNonAudio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1778 return 0;
1779}
1780
Takashi Iwai55e957d2005-11-17 14:52:13 +01001781static int snd_hdsp_get_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001783 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784
1785 ucontrol->value.integer.value[0] = hdsp_spdif_nonaudio(hdsp);
1786 return 0;
1787}
1788
Takashi Iwai55e957d2005-11-17 14:52:13 +01001789static int snd_hdsp_put_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001791 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 int change;
1793 unsigned int val;
1794
1795 if (!snd_hdsp_use_is_exclusive(hdsp))
1796 return -EBUSY;
1797 val = ucontrol->value.integer.value[0] & 1;
1798 spin_lock_irq(&hdsp->lock);
1799 change = (int)val != hdsp_spdif_nonaudio(hdsp);
1800 hdsp_set_spdif_nonaudio(hdsp, val);
1801 spin_unlock_irq(&hdsp->lock);
1802 return change;
1803}
1804
1805#define HDSP_SPDIF_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001806{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 .name = xname, \
1808 .index = xindex, \
1809 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1810 .info = snd_hdsp_info_spdif_sample_rate, \
1811 .get = snd_hdsp_get_spdif_sample_rate \
1812}
1813
Takashi Iwai55e957d2005-11-17 14:52:13 +01001814static int snd_hdsp_info_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815{
1816 static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
Takashi Iwai55e957d2005-11-17 14:52:13 +01001817 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818
1819 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1820 uinfo->count = 1;
1821 uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7;
1822 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1823 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1824 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1825 return 0;
1826}
1827
Takashi Iwai55e957d2005-11-17 14:52:13 +01001828static int snd_hdsp_get_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001830 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831
1832 switch (hdsp_spdif_sample_rate(hdsp)) {
1833 case 32000:
1834 ucontrol->value.enumerated.item[0] = 0;
1835 break;
1836 case 44100:
1837 ucontrol->value.enumerated.item[0] = 1;
1838 break;
1839 case 48000:
1840 ucontrol->value.enumerated.item[0] = 2;
1841 break;
1842 case 64000:
1843 ucontrol->value.enumerated.item[0] = 3;
1844 break;
1845 case 88200:
1846 ucontrol->value.enumerated.item[0] = 4;
1847 break;
1848 case 96000:
1849 ucontrol->value.enumerated.item[0] = 5;
1850 break;
1851 case 128000:
1852 ucontrol->value.enumerated.item[0] = 7;
1853 break;
1854 case 176400:
1855 ucontrol->value.enumerated.item[0] = 8;
1856 break;
1857 case 192000:
1858 ucontrol->value.enumerated.item[0] = 9;
1859 break;
1860 default:
1861 ucontrol->value.enumerated.item[0] = 6;
1862 }
1863 return 0;
1864}
1865
1866#define HDSP_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001867{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868 .name = xname, \
1869 .index = xindex, \
1870 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1871 .info = snd_hdsp_info_system_sample_rate, \
1872 .get = snd_hdsp_get_system_sample_rate \
1873}
1874
Takashi Iwai55e957d2005-11-17 14:52:13 +01001875static int snd_hdsp_info_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876{
1877 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1878 uinfo->count = 1;
1879 return 0;
1880}
1881
Takashi Iwai55e957d2005-11-17 14:52:13 +01001882static int snd_hdsp_get_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001884 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885
1886 ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate;
1887 return 0;
1888}
1889
1890#define HDSP_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001891{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 .name = xname, \
1893 .index = xindex, \
1894 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1895 .info = snd_hdsp_info_autosync_sample_rate, \
1896 .get = snd_hdsp_get_autosync_sample_rate \
1897}
1898
Takashi Iwai55e957d2005-11-17 14:52:13 +01001899static int snd_hdsp_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001901 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
1903 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1904 uinfo->count = 1;
1905 uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7 ;
1906 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1907 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1908 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1909 return 0;
1910}
1911
Takashi Iwai55e957d2005-11-17 14:52:13 +01001912static int snd_hdsp_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001914 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915
1916 switch (hdsp_external_sample_rate(hdsp)) {
1917 case 32000:
1918 ucontrol->value.enumerated.item[0] = 0;
1919 break;
1920 case 44100:
1921 ucontrol->value.enumerated.item[0] = 1;
1922 break;
1923 case 48000:
1924 ucontrol->value.enumerated.item[0] = 2;
1925 break;
1926 case 64000:
1927 ucontrol->value.enumerated.item[0] = 3;
1928 break;
1929 case 88200:
1930 ucontrol->value.enumerated.item[0] = 4;
1931 break;
1932 case 96000:
1933 ucontrol->value.enumerated.item[0] = 5;
1934 break;
1935 case 128000:
1936 ucontrol->value.enumerated.item[0] = 7;
1937 break;
1938 case 176400:
1939 ucontrol->value.enumerated.item[0] = 8;
1940 break;
1941 case 192000:
1942 ucontrol->value.enumerated.item[0] = 9;
1943 break;
1944 default:
1945 ucontrol->value.enumerated.item[0] = 6;
1946 }
1947 return 0;
1948}
1949
1950#define HDSP_SYSTEM_CLOCK_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001951{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 .name = xname, \
1953 .index = xindex, \
1954 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1955 .info = snd_hdsp_info_system_clock_mode, \
1956 .get = snd_hdsp_get_system_clock_mode \
1957}
1958
Takashi Iwai55e957d2005-11-17 14:52:13 +01001959static int hdsp_system_clock_mode(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001961 if (hdsp->control_register & HDSP_ClockModeMaster)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001963 else if (hdsp_external_sample_rate(hdsp) != hdsp->system_sample_rate)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965 return 1;
1966}
1967
Takashi Iwai55e957d2005-11-17 14:52:13 +01001968static int snd_hdsp_info_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969{
1970 static char *texts[] = {"Master", "Slave" };
1971
1972 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1973 uinfo->count = 1;
1974 uinfo->value.enumerated.items = 2;
1975 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1976 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1977 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1978 return 0;
1979}
1980
Takashi Iwai55e957d2005-11-17 14:52:13 +01001981static int snd_hdsp_get_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001983 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984
1985 ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp);
1986 return 0;
1987}
1988
1989#define HDSP_CLOCK_SOURCE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001990{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 .name = xname, \
1992 .index = xindex, \
1993 .info = snd_hdsp_info_clock_source, \
1994 .get = snd_hdsp_get_clock_source, \
1995 .put = snd_hdsp_put_clock_source \
1996}
1997
Takashi Iwai55e957d2005-11-17 14:52:13 +01001998static int hdsp_clock_source(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999{
2000 if (hdsp->control_register & HDSP_ClockModeMaster) {
2001 switch (hdsp->system_sample_rate) {
2002 case 32000:
2003 return 1;
2004 case 44100:
2005 return 2;
2006 case 48000:
2007 return 3;
2008 case 64000:
2009 return 4;
2010 case 88200:
2011 return 5;
2012 case 96000:
2013 return 6;
2014 case 128000:
2015 return 7;
2016 case 176400:
2017 return 8;
2018 case 192000:
2019 return 9;
2020 default:
2021 return 3;
2022 }
2023 } else {
2024 return 0;
2025 }
2026}
2027
Takashi Iwai55e957d2005-11-17 14:52:13 +01002028static int hdsp_set_clock_source(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029{
2030 int rate;
2031 switch (mode) {
2032 case HDSP_CLOCK_SOURCE_AUTOSYNC:
2033 if (hdsp_external_sample_rate(hdsp) != 0) {
2034 if (!hdsp_set_rate(hdsp, hdsp_external_sample_rate(hdsp), 1)) {
2035 hdsp->control_register &= ~HDSP_ClockModeMaster;
2036 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2037 return 0;
2038 }
2039 }
2040 return -1;
2041 case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ:
2042 rate = 32000;
2043 break;
2044 case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ:
2045 rate = 44100;
2046 break;
2047 case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ:
2048 rate = 48000;
2049 break;
2050 case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ:
2051 rate = 64000;
2052 break;
2053 case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ:
2054 rate = 88200;
2055 break;
2056 case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ:
2057 rate = 96000;
2058 break;
2059 case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ:
2060 rate = 128000;
2061 break;
2062 case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ:
2063 rate = 176400;
2064 break;
2065 case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ:
2066 rate = 192000;
2067 break;
2068 default:
2069 rate = 48000;
2070 }
2071 hdsp->control_register |= HDSP_ClockModeMaster;
2072 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2073 hdsp_set_rate(hdsp, rate, 1);
2074 return 0;
2075}
2076
Takashi Iwai55e957d2005-11-17 14:52:13 +01002077static int snd_hdsp_info_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078{
2079 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 +01002080 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081
2082 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2083 uinfo->count = 1;
2084 if (hdsp->io_type == H9632)
2085 uinfo->value.enumerated.items = 10;
2086 else
2087 uinfo->value.enumerated.items = 7;
2088 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2089 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2090 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2091 return 0;
2092}
2093
Takashi Iwai55e957d2005-11-17 14:52:13 +01002094static int snd_hdsp_get_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002096 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097
2098 ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp);
2099 return 0;
2100}
2101
Takashi Iwai55e957d2005-11-17 14:52:13 +01002102static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002104 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 int change;
2106 int val;
2107
2108 if (!snd_hdsp_use_is_exclusive(hdsp))
2109 return -EBUSY;
2110 val = ucontrol->value.enumerated.item[0];
2111 if (val < 0) val = 0;
2112 if (hdsp->io_type == H9632) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002113 if (val > 9)
2114 val = 9;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002116 if (val > 6)
2117 val = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 }
2119 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002120 if (val != hdsp_clock_source(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121 change = (hdsp_set_clock_source(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002122 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 spin_unlock_irq(&hdsp->lock);
2125 return change;
2126}
2127
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002128#define snd_hdsp_info_clock_source_lock snd_ctl_boolean_mono_info
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002129
Takashi Iwai55e957d2005-11-17 14:52:13 +01002130static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002131{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002132 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002133
2134 ucontrol->value.integer.value[0] = hdsp->clock_source_locked;
2135 return 0;
2136}
2137
Takashi Iwai55e957d2005-11-17 14:52:13 +01002138static int snd_hdsp_put_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002139{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002140 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002141 int change;
2142
2143 change = (int)ucontrol->value.integer.value[0] != hdsp->clock_source_locked;
2144 if (change)
Takashi Iwai4e98d6a2007-11-15 15:58:13 +01002145 hdsp->clock_source_locked = !!ucontrol->value.integer.value[0];
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002146 return change;
2147}
2148
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149#define HDSP_DA_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002150{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 .name = xname, \
2152 .index = xindex, \
2153 .info = snd_hdsp_info_da_gain, \
2154 .get = snd_hdsp_get_da_gain, \
2155 .put = snd_hdsp_put_da_gain \
2156}
2157
Takashi Iwai55e957d2005-11-17 14:52:13 +01002158static int hdsp_da_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159{
2160 switch (hdsp->control_register & HDSP_DAGainMask) {
2161 case HDSP_DAGainHighGain:
2162 return 0;
2163 case HDSP_DAGainPlus4dBu:
2164 return 1;
2165 case HDSP_DAGainMinus10dBV:
2166 return 2;
2167 default:
2168 return 1;
2169 }
2170}
2171
Takashi Iwai55e957d2005-11-17 14:52:13 +01002172static int hdsp_set_da_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173{
2174 hdsp->control_register &= ~HDSP_DAGainMask;
2175 switch (mode) {
2176 case 0:
2177 hdsp->control_register |= HDSP_DAGainHighGain;
2178 break;
2179 case 1:
2180 hdsp->control_register |= HDSP_DAGainPlus4dBu;
2181 break;
2182 case 2:
2183 hdsp->control_register |= HDSP_DAGainMinus10dBV;
2184 break;
2185 default:
2186 return -1;
2187
2188 }
2189 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2190 return 0;
2191}
2192
Takashi Iwai55e957d2005-11-17 14:52:13 +01002193static int snd_hdsp_info_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194{
2195 static char *texts[] = {"Hi Gain", "+4 dBu", "-10 dbV"};
2196
2197 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2198 uinfo->count = 1;
2199 uinfo->value.enumerated.items = 3;
2200 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2201 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2202 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2203 return 0;
2204}
2205
Takashi Iwai55e957d2005-11-17 14:52:13 +01002206static int snd_hdsp_get_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002208 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209
2210 ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp);
2211 return 0;
2212}
2213
Takashi Iwai55e957d2005-11-17 14:52:13 +01002214static int snd_hdsp_put_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002216 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 int change;
2218 int val;
2219
2220 if (!snd_hdsp_use_is_exclusive(hdsp))
2221 return -EBUSY;
2222 val = ucontrol->value.enumerated.item[0];
2223 if (val < 0) val = 0;
2224 if (val > 2) val = 2;
2225 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002226 if (val != hdsp_da_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 change = (hdsp_set_da_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002228 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 spin_unlock_irq(&hdsp->lock);
2231 return change;
2232}
2233
2234#define HDSP_AD_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002235{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 .name = xname, \
2237 .index = xindex, \
2238 .info = snd_hdsp_info_ad_gain, \
2239 .get = snd_hdsp_get_ad_gain, \
2240 .put = snd_hdsp_put_ad_gain \
2241}
2242
Takashi Iwai55e957d2005-11-17 14:52:13 +01002243static int hdsp_ad_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244{
2245 switch (hdsp->control_register & HDSP_ADGainMask) {
2246 case HDSP_ADGainMinus10dBV:
2247 return 0;
2248 case HDSP_ADGainPlus4dBu:
2249 return 1;
2250 case HDSP_ADGainLowGain:
2251 return 2;
2252 default:
2253 return 1;
2254 }
2255}
2256
Takashi Iwai55e957d2005-11-17 14:52:13 +01002257static int hdsp_set_ad_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258{
2259 hdsp->control_register &= ~HDSP_ADGainMask;
2260 switch (mode) {
2261 case 0:
2262 hdsp->control_register |= HDSP_ADGainMinus10dBV;
2263 break;
2264 case 1:
2265 hdsp->control_register |= HDSP_ADGainPlus4dBu;
2266 break;
2267 case 2:
2268 hdsp->control_register |= HDSP_ADGainLowGain;
2269 break;
2270 default:
2271 return -1;
2272
2273 }
2274 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2275 return 0;
2276}
2277
Takashi Iwai55e957d2005-11-17 14:52:13 +01002278static int snd_hdsp_info_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279{
2280 static char *texts[] = {"-10 dBV", "+4 dBu", "Lo Gain"};
2281
2282 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2283 uinfo->count = 1;
2284 uinfo->value.enumerated.items = 3;
2285 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2286 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2287 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2288 return 0;
2289}
2290
Takashi Iwai55e957d2005-11-17 14:52:13 +01002291static int snd_hdsp_get_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002293 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294
2295 ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp);
2296 return 0;
2297}
2298
Takashi Iwai55e957d2005-11-17 14:52:13 +01002299static int snd_hdsp_put_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002301 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 int change;
2303 int val;
2304
2305 if (!snd_hdsp_use_is_exclusive(hdsp))
2306 return -EBUSY;
2307 val = ucontrol->value.enumerated.item[0];
2308 if (val < 0) val = 0;
2309 if (val > 2) val = 2;
2310 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002311 if (val != hdsp_ad_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 change = (hdsp_set_ad_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002313 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 spin_unlock_irq(&hdsp->lock);
2316 return change;
2317}
2318
2319#define HDSP_PHONE_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002320{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 .name = xname, \
2322 .index = xindex, \
2323 .info = snd_hdsp_info_phone_gain, \
2324 .get = snd_hdsp_get_phone_gain, \
2325 .put = snd_hdsp_put_phone_gain \
2326}
2327
Takashi Iwai55e957d2005-11-17 14:52:13 +01002328static int hdsp_phone_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329{
2330 switch (hdsp->control_register & HDSP_PhoneGainMask) {
2331 case HDSP_PhoneGain0dB:
2332 return 0;
2333 case HDSP_PhoneGainMinus6dB:
2334 return 1;
2335 case HDSP_PhoneGainMinus12dB:
2336 return 2;
2337 default:
2338 return 0;
2339 }
2340}
2341
Takashi Iwai55e957d2005-11-17 14:52:13 +01002342static int hdsp_set_phone_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343{
2344 hdsp->control_register &= ~HDSP_PhoneGainMask;
2345 switch (mode) {
2346 case 0:
2347 hdsp->control_register |= HDSP_PhoneGain0dB;
2348 break;
2349 case 1:
2350 hdsp->control_register |= HDSP_PhoneGainMinus6dB;
2351 break;
2352 case 2:
2353 hdsp->control_register |= HDSP_PhoneGainMinus12dB;
2354 break;
2355 default:
2356 return -1;
2357
2358 }
2359 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2360 return 0;
2361}
2362
Takashi Iwai55e957d2005-11-17 14:52:13 +01002363static int snd_hdsp_info_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364{
2365 static char *texts[] = {"0 dB", "-6 dB", "-12 dB"};
2366
2367 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2368 uinfo->count = 1;
2369 uinfo->value.enumerated.items = 3;
2370 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2371 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2372 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2373 return 0;
2374}
2375
Takashi Iwai55e957d2005-11-17 14:52:13 +01002376static int snd_hdsp_get_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002378 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379
2380 ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp);
2381 return 0;
2382}
2383
Takashi Iwai55e957d2005-11-17 14:52:13 +01002384static int snd_hdsp_put_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002386 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 int change;
2388 int val;
2389
2390 if (!snd_hdsp_use_is_exclusive(hdsp))
2391 return -EBUSY;
2392 val = ucontrol->value.enumerated.item[0];
2393 if (val < 0) val = 0;
2394 if (val > 2) val = 2;
2395 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002396 if (val != hdsp_phone_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 change = (hdsp_set_phone_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002398 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 spin_unlock_irq(&hdsp->lock);
2401 return change;
2402}
2403
2404#define HDSP_XLR_BREAKOUT_CABLE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002405{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 .name = xname, \
2407 .index = xindex, \
2408 .info = snd_hdsp_info_xlr_breakout_cable, \
2409 .get = snd_hdsp_get_xlr_breakout_cable, \
2410 .put = snd_hdsp_put_xlr_breakout_cable \
2411}
2412
Takashi Iwai55e957d2005-11-17 14:52:13 +01002413static int hdsp_xlr_breakout_cable(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002415 if (hdsp->control_register & HDSP_XLRBreakoutCable)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417 return 0;
2418}
2419
Takashi Iwai55e957d2005-11-17 14:52:13 +01002420static int hdsp_set_xlr_breakout_cable(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002422 if (mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 hdsp->control_register |= HDSP_XLRBreakoutCable;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002424 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425 hdsp->control_register &= ~HDSP_XLRBreakoutCable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2427 return 0;
2428}
2429
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002430#define snd_hdsp_info_xlr_breakout_cable snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431
Takashi Iwai55e957d2005-11-17 14:52:13 +01002432static int snd_hdsp_get_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002434 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435
2436 ucontrol->value.enumerated.item[0] = hdsp_xlr_breakout_cable(hdsp);
2437 return 0;
2438}
2439
Takashi Iwai55e957d2005-11-17 14:52:13 +01002440static int snd_hdsp_put_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002442 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 int change;
2444 int val;
2445
2446 if (!snd_hdsp_use_is_exclusive(hdsp))
2447 return -EBUSY;
2448 val = ucontrol->value.integer.value[0] & 1;
2449 spin_lock_irq(&hdsp->lock);
2450 change = (int)val != hdsp_xlr_breakout_cable(hdsp);
2451 hdsp_set_xlr_breakout_cable(hdsp, val);
2452 spin_unlock_irq(&hdsp->lock);
2453 return change;
2454}
2455
2456/* (De)activates old RME Analog Extension Board
2457 These are connected to the internal ADAT connector
2458 Switching this on desactivates external ADAT
2459*/
2460#define HDSP_AEB(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002461{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 .name = xname, \
2463 .index = xindex, \
2464 .info = snd_hdsp_info_aeb, \
2465 .get = snd_hdsp_get_aeb, \
2466 .put = snd_hdsp_put_aeb \
2467}
2468
Takashi Iwai55e957d2005-11-17 14:52:13 +01002469static int hdsp_aeb(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002471 if (hdsp->control_register & HDSP_AnalogExtensionBoard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473 return 0;
2474}
2475
Takashi Iwai55e957d2005-11-17 14:52:13 +01002476static int hdsp_set_aeb(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002478 if (mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 hdsp->control_register |= HDSP_AnalogExtensionBoard;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002480 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481 hdsp->control_register &= ~HDSP_AnalogExtensionBoard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2483 return 0;
2484}
2485
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002486#define snd_hdsp_info_aeb snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487
Takashi Iwai55e957d2005-11-17 14:52:13 +01002488static int snd_hdsp_get_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002490 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491
2492 ucontrol->value.enumerated.item[0] = hdsp_aeb(hdsp);
2493 return 0;
2494}
2495
Takashi Iwai55e957d2005-11-17 14:52:13 +01002496static int snd_hdsp_put_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002498 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 int change;
2500 int val;
2501
2502 if (!snd_hdsp_use_is_exclusive(hdsp))
2503 return -EBUSY;
2504 val = ucontrol->value.integer.value[0] & 1;
2505 spin_lock_irq(&hdsp->lock);
2506 change = (int)val != hdsp_aeb(hdsp);
2507 hdsp_set_aeb(hdsp, val);
2508 spin_unlock_irq(&hdsp->lock);
2509 return change;
2510}
2511
2512#define HDSP_PREF_SYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002513{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514 .name = xname, \
2515 .index = xindex, \
2516 .info = snd_hdsp_info_pref_sync_ref, \
2517 .get = snd_hdsp_get_pref_sync_ref, \
2518 .put = snd_hdsp_put_pref_sync_ref \
2519}
2520
Takashi Iwai55e957d2005-11-17 14:52:13 +01002521static int hdsp_pref_sync_ref(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522{
2523 /* Notice that this looks at the requested sync source,
2524 not the one actually in use.
2525 */
2526
2527 switch (hdsp->control_register & HDSP_SyncRefMask) {
2528 case HDSP_SyncRef_ADAT1:
2529 return HDSP_SYNC_FROM_ADAT1;
2530 case HDSP_SyncRef_ADAT2:
2531 return HDSP_SYNC_FROM_ADAT2;
2532 case HDSP_SyncRef_ADAT3:
2533 return HDSP_SYNC_FROM_ADAT3;
2534 case HDSP_SyncRef_SPDIF:
2535 return HDSP_SYNC_FROM_SPDIF;
2536 case HDSP_SyncRef_WORD:
2537 return HDSP_SYNC_FROM_WORD;
2538 case HDSP_SyncRef_ADAT_SYNC:
2539 return HDSP_SYNC_FROM_ADAT_SYNC;
2540 default:
2541 return HDSP_SYNC_FROM_WORD;
2542 }
2543 return 0;
2544}
2545
Takashi Iwai55e957d2005-11-17 14:52:13 +01002546static int hdsp_set_pref_sync_ref(struct hdsp *hdsp, int pref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547{
2548 hdsp->control_register &= ~HDSP_SyncRefMask;
2549 switch (pref) {
2550 case HDSP_SYNC_FROM_ADAT1:
2551 hdsp->control_register &= ~HDSP_SyncRefMask; /* clear SyncRef bits */
2552 break;
2553 case HDSP_SYNC_FROM_ADAT2:
2554 hdsp->control_register |= HDSP_SyncRef_ADAT2;
2555 break;
2556 case HDSP_SYNC_FROM_ADAT3:
2557 hdsp->control_register |= HDSP_SyncRef_ADAT3;
2558 break;
2559 case HDSP_SYNC_FROM_SPDIF:
2560 hdsp->control_register |= HDSP_SyncRef_SPDIF;
2561 break;
2562 case HDSP_SYNC_FROM_WORD:
2563 hdsp->control_register |= HDSP_SyncRef_WORD;
2564 break;
2565 case HDSP_SYNC_FROM_ADAT_SYNC:
2566 hdsp->control_register |= HDSP_SyncRef_ADAT_SYNC;
2567 break;
2568 default:
2569 return -1;
2570 }
2571 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2572 return 0;
2573}
2574
Takashi Iwai55e957d2005-11-17 14:52:13 +01002575static int snd_hdsp_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576{
2577 static char *texts[] = {"Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3" };
Takashi Iwai55e957d2005-11-17 14:52:13 +01002578 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579
2580 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2581 uinfo->count = 1;
2582
2583 switch (hdsp->io_type) {
2584 case Digiface:
2585 case H9652:
2586 uinfo->value.enumerated.items = 6;
2587 break;
2588 case Multiface:
2589 uinfo->value.enumerated.items = 4;
2590 break;
2591 case H9632:
2592 uinfo->value.enumerated.items = 3;
2593 break;
2594 default:
2595 uinfo->value.enumerated.items = 0;
2596 break;
2597 }
2598
2599 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2600 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2601 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2602 return 0;
2603}
2604
Takashi Iwai55e957d2005-11-17 14:52:13 +01002605static int snd_hdsp_get_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002607 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608
2609 ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp);
2610 return 0;
2611}
2612
Takashi Iwai55e957d2005-11-17 14:52:13 +01002613static int snd_hdsp_put_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002615 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 int change, max;
2617 unsigned int val;
2618
2619 if (!snd_hdsp_use_is_exclusive(hdsp))
2620 return -EBUSY;
2621
2622 switch (hdsp->io_type) {
2623 case Digiface:
2624 case H9652:
2625 max = 6;
2626 break;
2627 case Multiface:
2628 max = 4;
2629 break;
2630 case H9632:
2631 max = 3;
2632 break;
2633 default:
2634 return -EIO;
2635 }
2636
2637 val = ucontrol->value.enumerated.item[0] % max;
2638 spin_lock_irq(&hdsp->lock);
2639 change = (int)val != hdsp_pref_sync_ref(hdsp);
2640 hdsp_set_pref_sync_ref(hdsp, val);
2641 spin_unlock_irq(&hdsp->lock);
2642 return change;
2643}
2644
2645#define HDSP_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002646{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647 .name = xname, \
2648 .index = xindex, \
2649 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2650 .info = snd_hdsp_info_autosync_ref, \
2651 .get = snd_hdsp_get_autosync_ref, \
2652}
2653
Takashi Iwai55e957d2005-11-17 14:52:13 +01002654static int hdsp_autosync_ref(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655{
2656 /* This looks at the autosync selected sync reference */
2657 unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
2658
2659 switch (status2 & HDSP_SelSyncRefMask) {
2660 case HDSP_SelSyncRef_WORD:
2661 return HDSP_AUTOSYNC_FROM_WORD;
2662 case HDSP_SelSyncRef_ADAT_SYNC:
2663 return HDSP_AUTOSYNC_FROM_ADAT_SYNC;
2664 case HDSP_SelSyncRef_SPDIF:
2665 return HDSP_AUTOSYNC_FROM_SPDIF;
2666 case HDSP_SelSyncRefMask:
2667 return HDSP_AUTOSYNC_FROM_NONE;
2668 case HDSP_SelSyncRef_ADAT1:
2669 return HDSP_AUTOSYNC_FROM_ADAT1;
2670 case HDSP_SelSyncRef_ADAT2:
2671 return HDSP_AUTOSYNC_FROM_ADAT2;
2672 case HDSP_SelSyncRef_ADAT3:
2673 return HDSP_AUTOSYNC_FROM_ADAT3;
2674 default:
2675 return HDSP_AUTOSYNC_FROM_WORD;
2676 }
2677 return 0;
2678}
2679
Takashi Iwai55e957d2005-11-17 14:52:13 +01002680static int snd_hdsp_info_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681{
2682 static char *texts[] = {"Word", "ADAT Sync", "IEC958", "None", "ADAT1", "ADAT2", "ADAT3" };
2683
2684 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2685 uinfo->count = 1;
2686 uinfo->value.enumerated.items = 7;
2687 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2688 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2689 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2690 return 0;
2691}
2692
Takashi Iwai55e957d2005-11-17 14:52:13 +01002693static int snd_hdsp_get_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002695 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696
2697 ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp);
2698 return 0;
2699}
2700
2701#define HDSP_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002702{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 .name = xname, \
2704 .index = xindex, \
2705 .info = snd_hdsp_info_line_out, \
2706 .get = snd_hdsp_get_line_out, \
2707 .put = snd_hdsp_put_line_out \
2708}
2709
Takashi Iwai55e957d2005-11-17 14:52:13 +01002710static int hdsp_line_out(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711{
2712 return (hdsp->control_register & HDSP_LineOut) ? 1 : 0;
2713}
2714
Takashi Iwai55e957d2005-11-17 14:52:13 +01002715static int hdsp_set_line_output(struct hdsp *hdsp, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002717 if (out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718 hdsp->control_register |= HDSP_LineOut;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002719 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 hdsp->control_register &= ~HDSP_LineOut;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2722 return 0;
2723}
2724
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002725#define snd_hdsp_info_line_out snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726
Takashi Iwai55e957d2005-11-17 14:52:13 +01002727static int snd_hdsp_get_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002729 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730
2731 spin_lock_irq(&hdsp->lock);
2732 ucontrol->value.integer.value[0] = hdsp_line_out(hdsp);
2733 spin_unlock_irq(&hdsp->lock);
2734 return 0;
2735}
2736
Takashi Iwai55e957d2005-11-17 14:52:13 +01002737static int snd_hdsp_put_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002739 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 int change;
2741 unsigned int val;
2742
2743 if (!snd_hdsp_use_is_exclusive(hdsp))
2744 return -EBUSY;
2745 val = ucontrol->value.integer.value[0] & 1;
2746 spin_lock_irq(&hdsp->lock);
2747 change = (int)val != hdsp_line_out(hdsp);
2748 hdsp_set_line_output(hdsp, val);
2749 spin_unlock_irq(&hdsp->lock);
2750 return change;
2751}
2752
2753#define HDSP_PRECISE_POINTER(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002754{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755 .name = xname, \
2756 .index = xindex, \
2757 .info = snd_hdsp_info_precise_pointer, \
2758 .get = snd_hdsp_get_precise_pointer, \
2759 .put = snd_hdsp_put_precise_pointer \
2760}
2761
Takashi Iwai55e957d2005-11-17 14:52:13 +01002762static int hdsp_set_precise_pointer(struct hdsp *hdsp, int precise)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002764 if (precise)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 hdsp->precise_ptr = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002766 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 hdsp->precise_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768 return 0;
2769}
2770
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002771#define snd_hdsp_info_precise_pointer snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772
Takashi Iwai55e957d2005-11-17 14:52:13 +01002773static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002775 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776
2777 spin_lock_irq(&hdsp->lock);
2778 ucontrol->value.integer.value[0] = hdsp->precise_ptr;
2779 spin_unlock_irq(&hdsp->lock);
2780 return 0;
2781}
2782
Takashi Iwai55e957d2005-11-17 14:52:13 +01002783static int snd_hdsp_put_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002785 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786 int change;
2787 unsigned int val;
2788
2789 if (!snd_hdsp_use_is_exclusive(hdsp))
2790 return -EBUSY;
2791 val = ucontrol->value.integer.value[0] & 1;
2792 spin_lock_irq(&hdsp->lock);
2793 change = (int)val != hdsp->precise_ptr;
2794 hdsp_set_precise_pointer(hdsp, val);
2795 spin_unlock_irq(&hdsp->lock);
2796 return change;
2797}
2798
2799#define HDSP_USE_MIDI_TASKLET(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002800{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801 .name = xname, \
2802 .index = xindex, \
2803 .info = snd_hdsp_info_use_midi_tasklet, \
2804 .get = snd_hdsp_get_use_midi_tasklet, \
2805 .put = snd_hdsp_put_use_midi_tasklet \
2806}
2807
Takashi Iwai55e957d2005-11-17 14:52:13 +01002808static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002810 if (use_tasklet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811 hdsp->use_midi_tasklet = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002812 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813 hdsp->use_midi_tasklet = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814 return 0;
2815}
2816
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002817#define snd_hdsp_info_use_midi_tasklet snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818
Takashi Iwai55e957d2005-11-17 14:52:13 +01002819static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002821 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822
2823 spin_lock_irq(&hdsp->lock);
2824 ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet;
2825 spin_unlock_irq(&hdsp->lock);
2826 return 0;
2827}
2828
Takashi Iwai55e957d2005-11-17 14:52:13 +01002829static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002831 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 int change;
2833 unsigned int val;
2834
2835 if (!snd_hdsp_use_is_exclusive(hdsp))
2836 return -EBUSY;
2837 val = ucontrol->value.integer.value[0] & 1;
2838 spin_lock_irq(&hdsp->lock);
2839 change = (int)val != hdsp->use_midi_tasklet;
2840 hdsp_set_use_midi_tasklet(hdsp, val);
2841 spin_unlock_irq(&hdsp->lock);
2842 return change;
2843}
2844
2845#define HDSP_MIXER(xname, xindex) \
2846{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
2847 .name = xname, \
2848 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002849 .device = 0, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2851 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2852 .info = snd_hdsp_info_mixer, \
2853 .get = snd_hdsp_get_mixer, \
2854 .put = snd_hdsp_put_mixer \
2855}
2856
Takashi Iwai55e957d2005-11-17 14:52:13 +01002857static int snd_hdsp_info_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858{
2859 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2860 uinfo->count = 3;
2861 uinfo->value.integer.min = 0;
2862 uinfo->value.integer.max = 65536;
2863 uinfo->value.integer.step = 1;
2864 return 0;
2865}
2866
Takashi Iwai55e957d2005-11-17 14:52:13 +01002867static int snd_hdsp_get_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002869 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870 int source;
2871 int destination;
2872 int addr;
2873
2874 source = ucontrol->value.integer.value[0];
2875 destination = ucontrol->value.integer.value[1];
2876
Takashi Iwaib0b98112005-10-20 18:29:58 +02002877 if (source >= hdsp->max_channels)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878 addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels,destination);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002879 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002880 addr = hdsp_input_to_output_key(hdsp,source, destination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881
2882 spin_lock_irq(&hdsp->lock);
2883 ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr);
2884 spin_unlock_irq(&hdsp->lock);
2885 return 0;
2886}
2887
Takashi Iwai55e957d2005-11-17 14:52:13 +01002888static int snd_hdsp_put_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002890 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891 int change;
2892 int source;
2893 int destination;
2894 int gain;
2895 int addr;
2896
2897 if (!snd_hdsp_use_is_exclusive(hdsp))
2898 return -EBUSY;
2899
2900 source = ucontrol->value.integer.value[0];
2901 destination = ucontrol->value.integer.value[1];
2902
Takashi Iwaib0b98112005-10-20 18:29:58 +02002903 if (source >= hdsp->max_channels)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002904 addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels, destination);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002905 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906 addr = hdsp_input_to_output_key(hdsp,source, destination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002907
2908 gain = ucontrol->value.integer.value[2];
2909
2910 spin_lock_irq(&hdsp->lock);
2911 change = gain != hdsp_read_gain(hdsp, addr);
2912 if (change)
2913 hdsp_write_gain(hdsp, addr, gain);
2914 spin_unlock_irq(&hdsp->lock);
2915 return change;
2916}
2917
2918#define HDSP_WC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002919{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920 .name = xname, \
2921 .index = xindex, \
2922 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2923 .info = snd_hdsp_info_sync_check, \
2924 .get = snd_hdsp_get_wc_sync_check \
2925}
2926
Takashi Iwai55e957d2005-11-17 14:52:13 +01002927static int snd_hdsp_info_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928{
2929 static char *texts[] = {"No Lock", "Lock", "Sync" };
2930 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2931 uinfo->count = 1;
2932 uinfo->value.enumerated.items = 3;
2933 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2934 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2935 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2936 return 0;
2937}
2938
Takashi Iwai55e957d2005-11-17 14:52:13 +01002939static int hdsp_wc_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940{
2941 int status2 = hdsp_read(hdsp, HDSP_status2Register);
2942 if (status2 & HDSP_wc_lock) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002943 if (status2 & HDSP_wc_sync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002945 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002947 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949 return 0;
2950}
2951
Takashi Iwai55e957d2005-11-17 14:52:13 +01002952static int snd_hdsp_get_wc_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002954 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955
2956 ucontrol->value.enumerated.item[0] = hdsp_wc_sync_check(hdsp);
2957 return 0;
2958}
2959
2960#define HDSP_SPDIF_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002961{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962 .name = xname, \
2963 .index = xindex, \
2964 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2965 .info = snd_hdsp_info_sync_check, \
2966 .get = snd_hdsp_get_spdif_sync_check \
2967}
2968
Takashi Iwai55e957d2005-11-17 14:52:13 +01002969static int hdsp_spdif_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970{
2971 int status = hdsp_read(hdsp, HDSP_statusRegister);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002972 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002974 else {
2975 if (status & HDSP_SPDIFSync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002977 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 }
2980 return 0;
2981}
2982
Takashi Iwai55e957d2005-11-17 14:52:13 +01002983static int snd_hdsp_get_spdif_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002985 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986
2987 ucontrol->value.enumerated.item[0] = hdsp_spdif_sync_check(hdsp);
2988 return 0;
2989}
2990
2991#define HDSP_ADATSYNC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002992{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993 .name = xname, \
2994 .index = xindex, \
2995 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2996 .info = snd_hdsp_info_sync_check, \
2997 .get = snd_hdsp_get_adatsync_sync_check \
2998}
2999
Takashi Iwai55e957d2005-11-17 14:52:13 +01003000static int hdsp_adatsync_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001{
3002 int status = hdsp_read(hdsp, HDSP_statusRegister);
3003 if (status & HDSP_TimecodeLock) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003004 if (status & HDSP_TimecodeSync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003006 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003008 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010}
3011
Takashi Iwai55e957d2005-11-17 14:52:13 +01003012static int snd_hdsp_get_adatsync_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003014 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015
3016 ucontrol->value.enumerated.item[0] = hdsp_adatsync_sync_check(hdsp);
3017 return 0;
3018}
3019
3020#define HDSP_ADAT_SYNC_CHECK \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003021{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3023 .info = snd_hdsp_info_sync_check, \
3024 .get = snd_hdsp_get_adat_sync_check \
3025}
3026
Takashi Iwai55e957d2005-11-17 14:52:13 +01003027static int hdsp_adat_sync_check(struct hdsp *hdsp, int idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028{
3029 int status = hdsp_read(hdsp, HDSP_statusRegister);
3030
3031 if (status & (HDSP_Lock0>>idx)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003032 if (status & (HDSP_Sync0>>idx))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003034 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003036 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038}
3039
Takashi Iwai55e957d2005-11-17 14:52:13 +01003040static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041{
3042 int offset;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003043 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044
3045 offset = ucontrol->id.index - 1;
3046 snd_assert(offset >= 0);
3047
3048 switch (hdsp->io_type) {
3049 case Digiface:
3050 case H9652:
3051 if (offset >= 3)
3052 return -EINVAL;
3053 break;
3054 case Multiface:
3055 case H9632:
3056 if (offset >= 1)
3057 return -EINVAL;
3058 break;
3059 default:
3060 return -EIO;
3061 }
3062
3063 ucontrol->value.enumerated.item[0] = hdsp_adat_sync_check(hdsp, offset);
3064 return 0;
3065}
3066
Julian Cablee4b60882007-03-19 11:44:40 +01003067#define HDSP_DDS_OFFSET(xname, xindex) \
3068{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3069 .name = xname, \
3070 .index = xindex, \
3071 .info = snd_hdsp_info_dds_offset, \
3072 .get = snd_hdsp_get_dds_offset, \
3073 .put = snd_hdsp_put_dds_offset \
3074}
3075
3076static int hdsp_dds_offset(struct hdsp *hdsp)
3077{
3078 u64 n;
3079 u32 r;
3080 unsigned int dds_value = hdsp->dds_value;
3081 int system_sample_rate = hdsp->system_sample_rate;
3082
Takashi Iwai2a3988f2007-10-16 14:26:32 +02003083 if (!dds_value)
3084 return 0;
3085
Julian Cablee4b60882007-03-19 11:44:40 +01003086 n = DDS_NUMERATOR;
3087 /*
3088 * dds_value = n / rate
3089 * rate = n / dds_value
3090 */
3091 div64_32(&n, dds_value, &r);
3092 if (system_sample_rate >= 112000)
3093 n *= 4;
3094 else if (system_sample_rate >= 56000)
3095 n *= 2;
3096 return ((int)n) - system_sample_rate;
3097}
3098
3099static int hdsp_set_dds_offset(struct hdsp *hdsp, int offset_hz)
3100{
3101 int rate = hdsp->system_sample_rate + offset_hz;
3102 hdsp_set_dds_value(hdsp, rate);
3103 return 0;
3104}
3105
3106static int snd_hdsp_info_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3107{
3108 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3109 uinfo->count = 1;
3110 uinfo->value.integer.min = -5000;
3111 uinfo->value.integer.max = 5000;
3112 return 0;
3113}
3114
3115static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3116{
3117 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3118
3119 ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp);
3120 return 0;
3121}
3122
3123static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3124{
3125 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3126 int change;
3127 int val;
3128
3129 if (!snd_hdsp_use_is_exclusive(hdsp))
3130 return -EBUSY;
3131 val = ucontrol->value.enumerated.item[0];
3132 spin_lock_irq(&hdsp->lock);
3133 if (val != hdsp_dds_offset(hdsp))
3134 change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0;
3135 else
3136 change = 0;
3137 spin_unlock_irq(&hdsp->lock);
3138 return change;
3139}
3140
Takashi Iwai55e957d2005-11-17 14:52:13 +01003141static struct snd_kcontrol_new snd_hdsp_9632_controls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142HDSP_DA_GAIN("DA Gain", 0),
3143HDSP_AD_GAIN("AD Gain", 0),
3144HDSP_PHONE_GAIN("Phones Gain", 0),
Julian Cablee4b60882007-03-19 11:44:40 +01003145HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0),
3146HDSP_DDS_OFFSET("DDS Sample Rate Offset", 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147};
3148
Takashi Iwai55e957d2005-11-17 14:52:13 +01003149static struct snd_kcontrol_new snd_hdsp_controls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150{
Clemens Ladisch5549d542005-08-03 13:50:30 +02003151 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
3153 .info = snd_hdsp_control_spdif_info,
3154 .get = snd_hdsp_control_spdif_get,
3155 .put = snd_hdsp_control_spdif_put,
3156},
3157{
3158 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch5549d542005-08-03 13:50:30 +02003159 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
3161 .info = snd_hdsp_control_spdif_stream_info,
3162 .get = snd_hdsp_control_spdif_stream_get,
3163 .put = snd_hdsp_control_spdif_stream_put,
3164},
3165{
3166 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +02003167 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
3169 .info = snd_hdsp_control_spdif_mask_info,
3170 .get = snd_hdsp_control_spdif_mask_get,
3171 .private_value = IEC958_AES0_NONAUDIO |
3172 IEC958_AES0_PROFESSIONAL |
3173 IEC958_AES0_CON_EMPHASIS,
3174},
3175{
3176 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +02003177 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
3179 .info = snd_hdsp_control_spdif_mask_info,
3180 .get = snd_hdsp_control_spdif_mask_get,
3181 .private_value = IEC958_AES0_NONAUDIO |
3182 IEC958_AES0_PROFESSIONAL |
3183 IEC958_AES0_PRO_EMPHASIS,
3184},
3185HDSP_MIXER("Mixer", 0),
3186HDSP_SPDIF_IN("IEC958 Input Connector", 0),
3187HDSP_SPDIF_OUT("IEC958 Output also on ADAT1", 0),
3188HDSP_SPDIF_PROFESSIONAL("IEC958 Professional Bit", 0),
3189HDSP_SPDIF_EMPHASIS("IEC958 Emphasis Bit", 0),
3190HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0),
3191/* 'Sample Clock Source' complies with the alsa control naming scheme */
3192HDSP_CLOCK_SOURCE("Sample Clock Source", 0),
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003193{
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003194 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3195 .name = "Sample Clock Source Locking",
3196 .info = snd_hdsp_info_clock_source_lock,
3197 .get = snd_hdsp_get_clock_source_lock,
3198 .put = snd_hdsp_put_clock_source_lock,
3199},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200HDSP_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
3201HDSP_PREF_SYNC_REF("Preferred Sync Reference", 0),
3202HDSP_AUTOSYNC_REF("AutoSync Reference", 0),
3203HDSP_SPDIF_SAMPLE_RATE("SPDIF Sample Rate", 0),
3204HDSP_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
3205/* 'External Rate' complies with the alsa control naming scheme */
3206HDSP_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
3207HDSP_WC_SYNC_CHECK("Word Clock Lock Status", 0),
3208HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0),
3209HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0),
3210HDSP_LINE_OUT("Line Out", 0),
3211HDSP_PRECISE_POINTER("Precise Pointer", 0),
3212HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0),
3213};
3214
Takashi Iwai55e957d2005-11-17 14:52:13 +01003215static struct snd_kcontrol_new snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0);
3216static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217
Takashi Iwai55e957d2005-11-17 14:52:13 +01003218static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003219{
3220 unsigned int idx;
3221 int err;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003222 struct snd_kcontrol *kctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003223
3224 for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003225 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227 if (idx == 1) /* IEC958 (S/PDIF) Stream */
3228 hdsp->spdif_ctl = kctl;
3229 }
3230
3231 /* ADAT SyncCheck status */
3232 snd_hdsp_adat_sync_check.name = "ADAT Lock Status";
3233 snd_hdsp_adat_sync_check.index = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003234 if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236 if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
3237 for (idx = 1; idx < 3; ++idx) {
3238 snd_hdsp_adat_sync_check.index = idx+1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003239 if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003241 }
3242 }
3243
3244 /* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */
3245 if (hdsp->io_type == H9632) {
3246 for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003247 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249 }
3250 }
3251
3252 /* AEB control for H96xx card */
3253 if (hdsp->io_type == H9632 || hdsp->io_type == H9652) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003254 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256 }
3257
3258 return 0;
3259}
3260
3261/*------------------------------------------------------------
3262 /proc interface
3263 ------------------------------------------------------------*/
3264
3265static void
Takashi Iwai55e957d2005-11-17 14:52:13 +01003266snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003268 struct hdsp *hdsp = (struct hdsp *) entry->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269 unsigned int status;
3270 unsigned int status2;
3271 char *pref_sync_ref;
3272 char *autosync_ref;
3273 char *system_clock_mode;
3274 char *clock_source;
3275 int x;
3276
Remy Brunoecb594e2006-06-12 09:25:22 +02003277 if (hdsp_check_for_iobox (hdsp)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278 snd_iprintf(buffer, "No I/O box connected.\nPlease connect one and upload firmware.\n");
3279 return;
Remy Brunoecb594e2006-06-12 09:25:22 +02003280 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281
Takashi Iwaib0b98112005-10-20 18:29:58 +02003282 if (hdsp_check_for_firmware(hdsp, 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283 if (hdsp->state & HDSP_FirmwareCached) {
3284 if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
3285 snd_iprintf(buffer, "Firmware loading from cache failed, please upload manually.\n");
3286 return;
3287 }
3288 } else {
Takashi Iwai311e70a2006-09-06 12:13:37 +02003289 int err = -EINVAL;
3290#ifdef HDSP_FW_LOADER
3291 err = hdsp_request_fw_loader(hdsp);
3292#endif
3293 if (err < 0) {
3294 snd_iprintf(buffer,
3295 "No firmware loaded nor cached, "
3296 "please upload firmware.\n");
3297 return;
3298 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299 }
3300 }
3301
3302 status = hdsp_read(hdsp, HDSP_statusRegister);
3303 status2 = hdsp_read(hdsp, HDSP_status2Register);
3304
3305 snd_iprintf(buffer, "%s (Card #%d)\n", hdsp->card_name, hdsp->card->number + 1);
3306 snd_iprintf(buffer, "Buffers: capture %p playback %p\n",
3307 hdsp->capture_buffer, hdsp->playback_buffer);
3308 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
3309 hdsp->irq, hdsp->port, (unsigned long)hdsp->iobase);
3310 snd_iprintf(buffer, "Control register: 0x%x\n", hdsp->control_register);
3311 snd_iprintf(buffer, "Control2 register: 0x%x\n", hdsp->control2_register);
3312 snd_iprintf(buffer, "Status register: 0x%x\n", status);
3313 snd_iprintf(buffer, "Status2 register: 0x%x\n", status2);
3314 snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff);
3315 snd_iprintf(buffer, "MIDI1 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut0));
3316 snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0));
3317 snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1));
3318 snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1));
3319 snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off");
3320
3321 snd_iprintf(buffer, "\n");
3322
3323 x = 1 << (6 + hdsp_decode_latency(hdsp->control_register & HDSP_LatencyMask));
3324
3325 snd_iprintf(buffer, "Buffer Size (Latency): %d samples (2 periods of %lu bytes)\n", x, (unsigned long) hdsp->period_bytes);
3326 snd_iprintf(buffer, "Hardware pointer (frames): %ld\n", hdsp_hw_pointer(hdsp));
3327 snd_iprintf(buffer, "Precise pointer: %s\n", hdsp->precise_ptr ? "on" : "off");
3328 snd_iprintf(buffer, "Line out: %s\n", (hdsp->control_register & HDSP_LineOut) ? "on" : "off");
3329
3330 snd_iprintf(buffer, "Firmware version: %d\n", (status2&HDSP_version0)|(status2&HDSP_version1)<<1|(status2&HDSP_version2)<<2);
3331
3332 snd_iprintf(buffer, "\n");
3333
3334
3335 switch (hdsp_clock_source(hdsp)) {
3336 case HDSP_CLOCK_SOURCE_AUTOSYNC:
3337 clock_source = "AutoSync";
3338 break;
3339 case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ:
3340 clock_source = "Internal 32 kHz";
3341 break;
3342 case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ:
3343 clock_source = "Internal 44.1 kHz";
3344 break;
3345 case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ:
3346 clock_source = "Internal 48 kHz";
3347 break;
3348 case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ:
3349 clock_source = "Internal 64 kHz";
3350 break;
3351 case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ:
3352 clock_source = "Internal 88.2 kHz";
3353 break;
3354 case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ:
3355 clock_source = "Internal 96 kHz";
3356 break;
3357 case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ:
3358 clock_source = "Internal 128 kHz";
3359 break;
3360 case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ:
3361 clock_source = "Internal 176.4 kHz";
3362 break;
3363 case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ:
3364 clock_source = "Internal 192 kHz";
3365 break;
3366 default:
3367 clock_source = "Error";
3368 }
3369 snd_iprintf (buffer, "Sample Clock Source: %s\n", clock_source);
3370
Takashi Iwaib0b98112005-10-20 18:29:58 +02003371 if (hdsp_system_clock_mode(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372 system_clock_mode = "Slave";
Takashi Iwaib0b98112005-10-20 18:29:58 +02003373 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374 system_clock_mode = "Master";
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375
3376 switch (hdsp_pref_sync_ref (hdsp)) {
3377 case HDSP_SYNC_FROM_WORD:
3378 pref_sync_ref = "Word Clock";
3379 break;
3380 case HDSP_SYNC_FROM_ADAT_SYNC:
3381 pref_sync_ref = "ADAT Sync";
3382 break;
3383 case HDSP_SYNC_FROM_SPDIF:
3384 pref_sync_ref = "SPDIF";
3385 break;
3386 case HDSP_SYNC_FROM_ADAT1:
3387 pref_sync_ref = "ADAT1";
3388 break;
3389 case HDSP_SYNC_FROM_ADAT2:
3390 pref_sync_ref = "ADAT2";
3391 break;
3392 case HDSP_SYNC_FROM_ADAT3:
3393 pref_sync_ref = "ADAT3";
3394 break;
3395 default:
3396 pref_sync_ref = "Word Clock";
3397 break;
3398 }
3399 snd_iprintf (buffer, "Preferred Sync Reference: %s\n", pref_sync_ref);
3400
3401 switch (hdsp_autosync_ref (hdsp)) {
3402 case HDSP_AUTOSYNC_FROM_WORD:
3403 autosync_ref = "Word Clock";
3404 break;
3405 case HDSP_AUTOSYNC_FROM_ADAT_SYNC:
3406 autosync_ref = "ADAT Sync";
3407 break;
3408 case HDSP_AUTOSYNC_FROM_SPDIF:
3409 autosync_ref = "SPDIF";
3410 break;
3411 case HDSP_AUTOSYNC_FROM_NONE:
3412 autosync_ref = "None";
3413 break;
3414 case HDSP_AUTOSYNC_FROM_ADAT1:
3415 autosync_ref = "ADAT1";
3416 break;
3417 case HDSP_AUTOSYNC_FROM_ADAT2:
3418 autosync_ref = "ADAT2";
3419 break;
3420 case HDSP_AUTOSYNC_FROM_ADAT3:
3421 autosync_ref = "ADAT3";
3422 break;
3423 default:
3424 autosync_ref = "---";
3425 break;
3426 }
3427 snd_iprintf (buffer, "AutoSync Reference: %s\n", autosync_ref);
3428
3429 snd_iprintf (buffer, "AutoSync Frequency: %d\n", hdsp_external_sample_rate(hdsp));
3430
3431 snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode);
3432
3433 snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003434 snd_iprintf (buffer, "System Clock Locked: %s\n", hdsp->clock_source_locked ? "Yes" : "No");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435
3436 snd_iprintf(buffer, "\n");
3437
3438 switch (hdsp_spdif_in(hdsp)) {
3439 case HDSP_SPDIFIN_OPTICAL:
3440 snd_iprintf(buffer, "IEC958 input: Optical\n");
3441 break;
3442 case HDSP_SPDIFIN_COAXIAL:
3443 snd_iprintf(buffer, "IEC958 input: Coaxial\n");
3444 break;
3445 case HDSP_SPDIFIN_INTERNAL:
3446 snd_iprintf(buffer, "IEC958 input: Internal\n");
3447 break;
3448 case HDSP_SPDIFIN_AES:
3449 snd_iprintf(buffer, "IEC958 input: AES\n");
3450 break;
3451 default:
3452 snd_iprintf(buffer, "IEC958 input: ???\n");
3453 break;
3454 }
3455
Takashi Iwaib0b98112005-10-20 18:29:58 +02003456 if (hdsp->control_register & HDSP_SPDIFOpticalOut)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457 snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003458 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459 snd_iprintf(buffer, "IEC958 output: Coaxial only\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460
Takashi Iwaib0b98112005-10-20 18:29:58 +02003461 if (hdsp->control_register & HDSP_SPDIFProfessional)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462 snd_iprintf(buffer, "IEC958 quality: Professional\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003463 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003464 snd_iprintf(buffer, "IEC958 quality: Consumer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465
Takashi Iwaib0b98112005-10-20 18:29:58 +02003466 if (hdsp->control_register & HDSP_SPDIFEmphasis)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467 snd_iprintf(buffer, "IEC958 emphasis: on\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003468 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469 snd_iprintf(buffer, "IEC958 emphasis: off\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470
Takashi Iwaib0b98112005-10-20 18:29:58 +02003471 if (hdsp->control_register & HDSP_SPDIFNonAudio)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472 snd_iprintf(buffer, "IEC958 NonAudio: on\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003473 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474 snd_iprintf(buffer, "IEC958 NonAudio: off\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003475 if ((x = hdsp_spdif_sample_rate (hdsp)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476 snd_iprintf (buffer, "IEC958 sample rate: %d\n", x);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003477 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478 snd_iprintf (buffer, "IEC958 sample rate: Error flag set\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479
3480 snd_iprintf(buffer, "\n");
3481
3482 /* Sync Check */
3483 x = status & HDSP_Sync0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003484 if (status & HDSP_Lock0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485 snd_iprintf(buffer, "ADAT1: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003486 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487 snd_iprintf(buffer, "ADAT1: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488
3489 switch (hdsp->io_type) {
3490 case Digiface:
3491 case H9652:
3492 x = status & HDSP_Sync1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003493 if (status & HDSP_Lock1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494 snd_iprintf(buffer, "ADAT2: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003495 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496 snd_iprintf(buffer, "ADAT2: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003497 x = status & HDSP_Sync2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003498 if (status & HDSP_Lock2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499 snd_iprintf(buffer, "ADAT3: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003500 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501 snd_iprintf(buffer, "ADAT3: No Lock\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003502 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003503 default:
3504 /* relax */
3505 break;
3506 }
3507
3508 x = status & HDSP_SPDIFSync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003509 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510 snd_iprintf (buffer, "SPDIF: No Lock\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003511 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512 snd_iprintf (buffer, "SPDIF: %s\n", x ? "Sync" : "Lock");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513
3514 x = status2 & HDSP_wc_sync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003515 if (status2 & HDSP_wc_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516 snd_iprintf (buffer, "Word Clock: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003517 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518 snd_iprintf (buffer, "Word Clock: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519
3520 x = status & HDSP_TimecodeSync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003521 if (status & HDSP_TimecodeLock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522 snd_iprintf(buffer, "ADAT Sync: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003523 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 snd_iprintf(buffer, "ADAT Sync: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003525
3526 snd_iprintf(buffer, "\n");
3527
3528 /* Informations about H9632 specific controls */
3529 if (hdsp->io_type == H9632) {
3530 char *tmp;
3531
3532 switch (hdsp_ad_gain(hdsp)) {
3533 case 0:
3534 tmp = "-10 dBV";
3535 break;
3536 case 1:
3537 tmp = "+4 dBu";
3538 break;
3539 default:
3540 tmp = "Lo Gain";
3541 break;
3542 }
3543 snd_iprintf(buffer, "AD Gain : %s\n", tmp);
3544
3545 switch (hdsp_da_gain(hdsp)) {
3546 case 0:
3547 tmp = "Hi Gain";
3548 break;
3549 case 1:
3550 tmp = "+4 dBu";
3551 break;
3552 default:
3553 tmp = "-10 dBV";
3554 break;
3555 }
3556 snd_iprintf(buffer, "DA Gain : %s\n", tmp);
3557
3558 switch (hdsp_phone_gain(hdsp)) {
3559 case 0:
3560 tmp = "0 dB";
3561 break;
3562 case 1:
3563 tmp = "-6 dB";
3564 break;
3565 default:
3566 tmp = "-12 dB";
3567 break;
3568 }
3569 snd_iprintf(buffer, "Phones Gain : %s\n", tmp);
3570
3571 snd_iprintf(buffer, "XLR Breakout Cable : %s\n", hdsp_xlr_breakout_cable(hdsp) ? "yes" : "no");
3572
Takashi Iwaib0b98112005-10-20 18:29:58 +02003573 if (hdsp->control_register & HDSP_AnalogExtensionBoard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574 snd_iprintf(buffer, "AEB : on (ADAT1 internal)\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003575 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003576 snd_iprintf(buffer, "AEB : off (ADAT1 external)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577 snd_iprintf(buffer, "\n");
3578 }
3579
3580}
3581
Randy Dunlap1374f8c2008-01-16 14:55:42 +01003582static void snd_hdsp_proc_init(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003583{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003584 struct snd_info_entry *entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003585
3586 if (! snd_card_proc_new(hdsp->card, "hdsp", &entry))
Takashi Iwaibf850202006-04-28 15:13:41 +02003587 snd_info_set_text_ops(entry, hdsp, snd_hdsp_proc_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588}
3589
Takashi Iwai55e957d2005-11-17 14:52:13 +01003590static void snd_hdsp_free_buffers(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591{
3592 snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci);
3593 snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
3594}
3595
Takashi Iwai55e957d2005-11-17 14:52:13 +01003596static int __devinit snd_hdsp_initialize_memory(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597{
3598 unsigned long pb_bus, cb_bus;
3599
3600 if (snd_hammerfall_get_buffer(hdsp->pci, &hdsp->capture_dma_buf, HDSP_DMA_AREA_BYTES) < 0 ||
3601 snd_hammerfall_get_buffer(hdsp->pci, &hdsp->playback_dma_buf, HDSP_DMA_AREA_BYTES) < 0) {
3602 if (hdsp->capture_dma_buf.area)
3603 snd_dma_free_pages(&hdsp->capture_dma_buf);
3604 printk(KERN_ERR "%s: no buffers available\n", hdsp->card_name);
3605 return -ENOMEM;
3606 }
3607
3608 /* Align to bus-space 64K boundary */
3609
Clemens Ladisch7ab39922006-10-09 08:13:32 +02003610 cb_bus = ALIGN(hdsp->capture_dma_buf.addr, 0x10000ul);
3611 pb_bus = ALIGN(hdsp->playback_dma_buf.addr, 0x10000ul);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612
3613 /* Tell the card where it is */
3614
3615 hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus);
3616 hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus);
3617
3618 hdsp->capture_buffer = hdsp->capture_dma_buf.area + (cb_bus - hdsp->capture_dma_buf.addr);
3619 hdsp->playback_buffer = hdsp->playback_dma_buf.area + (pb_bus - hdsp->playback_dma_buf.addr);
3620
3621 return 0;
3622}
3623
Takashi Iwai55e957d2005-11-17 14:52:13 +01003624static int snd_hdsp_set_defaults(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625{
3626 unsigned int i;
3627
3628 /* ASSUMPTION: hdsp->lock is either held, or
3629 there is no need to hold it (e.g. during module
Joe Perches561de312007-12-18 13:13:47 +01003630 initialization).
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 */
3632
3633 /* set defaults:
3634
3635 SPDIF Input via Coax
3636 Master clock mode
3637 maximum latency (7 => 2^7 = 8192 samples, 64Kbyte buffer,
3638 which implies 2 4096 sample, 32Kbyte periods).
3639 Enable line out.
3640 */
3641
3642 hdsp->control_register = HDSP_ClockModeMaster |
3643 HDSP_SPDIFInputCoaxial |
3644 hdsp_encode_latency(7) |
3645 HDSP_LineOut;
3646
3647
3648 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3649
3650#ifdef SNDRV_BIG_ENDIAN
3651 hdsp->control2_register = HDSP_BIGENDIAN_MODE;
3652#else
3653 hdsp->control2_register = 0;
3654#endif
Takashi Iwaib0b98112005-10-20 18:29:58 +02003655 if (hdsp->io_type == H9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656 snd_hdsp_9652_enable_mixer (hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003657 else
3658 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659
3660 hdsp_reset_hw_pointer(hdsp);
3661 hdsp_compute_period_size(hdsp);
3662
3663 /* silence everything */
3664
Takashi Iwaib0b98112005-10-20 18:29:58 +02003665 for (i = 0; i < HDSP_MATRIX_MIXER_SIZE; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666 hdsp->mixer_matrix[i] = MINUS_INFINITY_GAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003667
3668 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 +02003669 if (hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671 }
3672
3673 /* H9632 specific defaults */
3674 if (hdsp->io_type == H9632) {
3675 hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB);
3676 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3677 }
3678
3679 /* set a default rate so that the channel map is set up.
3680 */
3681
3682 hdsp_set_rate(hdsp, 48000, 1);
3683
3684 return 0;
3685}
3686
3687static void hdsp_midi_tasklet(unsigned long arg)
3688{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003689 struct hdsp *hdsp = (struct hdsp *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690
Takashi Iwaib0b98112005-10-20 18:29:58 +02003691 if (hdsp->midi[0].pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692 snd_hdsp_midi_input_read (&hdsp->midi[0]);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003693 if (hdsp->midi[1].pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694 snd_hdsp_midi_input_read (&hdsp->midi[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695}
3696
David Howells7d12e782006-10-05 14:55:46 +01003697static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003699 struct hdsp *hdsp = (struct hdsp *) dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700 unsigned int status;
3701 int audio;
3702 int midi0;
3703 int midi1;
3704 unsigned int midi0status;
3705 unsigned int midi1status;
3706 int schedule = 0;
3707
3708 status = hdsp_read(hdsp, HDSP_statusRegister);
3709
3710 audio = status & HDSP_audioIRQPending;
3711 midi0 = status & HDSP_midi0IRQPending;
3712 midi1 = status & HDSP_midi1IRQPending;
3713
Takashi Iwaib0b98112005-10-20 18:29:58 +02003714 if (!audio && !midi0 && !midi1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715 return IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716
3717 hdsp_write(hdsp, HDSP_interruptConfirmation, 0);
3718
3719 midi0status = hdsp_read (hdsp, HDSP_midiStatusIn0) & 0xff;
3720 midi1status = hdsp_read (hdsp, HDSP_midiStatusIn1) & 0xff;
3721
3722 if (audio) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003723 if (hdsp->capture_substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724 snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725
Takashi Iwaib0b98112005-10-20 18:29:58 +02003726 if (hdsp->playback_substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727 snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003728 }
3729
3730 if (midi0 && midi0status) {
3731 if (hdsp->use_midi_tasklet) {
3732 /* we disable interrupts for this input until processing is done */
3733 hdsp->control_register &= ~HDSP_Midi0InterruptEnable;
3734 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3735 hdsp->midi[0].pending = 1;
3736 schedule = 1;
3737 } else {
3738 snd_hdsp_midi_input_read (&hdsp->midi[0]);
3739 }
3740 }
3741 if (hdsp->io_type != Multiface && hdsp->io_type != H9632 && midi1 && midi1status) {
3742 if (hdsp->use_midi_tasklet) {
3743 /* we disable interrupts for this input until processing is done */
3744 hdsp->control_register &= ~HDSP_Midi1InterruptEnable;
3745 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3746 hdsp->midi[1].pending = 1;
3747 schedule = 1;
3748 } else {
3749 snd_hdsp_midi_input_read (&hdsp->midi[1]);
3750 }
3751 }
3752 if (hdsp->use_midi_tasklet && schedule)
3753 tasklet_hi_schedule(&hdsp->midi_tasklet);
3754 return IRQ_HANDLED;
3755}
3756
Takashi Iwai55e957d2005-11-17 14:52:13 +01003757static snd_pcm_uframes_t snd_hdsp_hw_pointer(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003759 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 return hdsp_hw_pointer(hdsp);
3761}
3762
Takashi Iwai55e957d2005-11-17 14:52:13 +01003763static char *hdsp_channel_buffer_location(struct hdsp *hdsp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764 int stream,
3765 int channel)
3766
3767{
3768 int mapped_channel;
3769
3770 snd_assert(channel >= 0 && channel < hdsp->max_channels, return NULL);
3771
Takashi Iwaib0b98112005-10-20 18:29:58 +02003772 if ((mapped_channel = hdsp->channel_map[channel]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774
Takashi Iwaib0b98112005-10-20 18:29:58 +02003775 if (stream == SNDRV_PCM_STREAM_CAPTURE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776 return hdsp->capture_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003777 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778 return hdsp->playback_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779}
3780
Takashi Iwai55e957d2005-11-17 14:52:13 +01003781static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782 snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
3783{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003784 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785 char *channel_buf;
3786
3787 snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
3788
3789 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
3790 snd_assert(channel_buf != NULL, return -EIO);
3791 if (copy_from_user(channel_buf + pos * 4, src, count * 4))
3792 return -EFAULT;
3793 return count;
3794}
3795
Takashi Iwai55e957d2005-11-17 14:52:13 +01003796static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797 snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count)
3798{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003799 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800 char *channel_buf;
3801
3802 snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
3803
3804 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
3805 snd_assert(channel_buf != NULL, return -EIO);
3806 if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
3807 return -EFAULT;
3808 return count;
3809}
3810
Takashi Iwai55e957d2005-11-17 14:52:13 +01003811static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812 snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
3813{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003814 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815 char *channel_buf;
3816
3817 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
3818 snd_assert(channel_buf != NULL, return -EIO);
3819 memset(channel_buf + pos * 4, 0, count * 4);
3820 return count;
3821}
3822
Takashi Iwai55e957d2005-11-17 14:52:13 +01003823static int snd_hdsp_reset(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003825 struct snd_pcm_runtime *runtime = substream->runtime;
3826 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
3827 struct snd_pcm_substream *other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3829 other = hdsp->capture_substream;
3830 else
3831 other = hdsp->playback_substream;
3832 if (hdsp->running)
3833 runtime->status->hw_ptr = hdsp_hw_pointer(hdsp);
3834 else
3835 runtime->status->hw_ptr = 0;
3836 if (other) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01003837 struct snd_pcm_substream *s;
3838 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01003839 snd_pcm_group_for_each_entry(s, substream) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840 if (s == other) {
3841 oruntime->status->hw_ptr = runtime->status->hw_ptr;
3842 break;
3843 }
3844 }
3845 }
3846 return 0;
3847}
3848
Takashi Iwai55e957d2005-11-17 14:52:13 +01003849static int snd_hdsp_hw_params(struct snd_pcm_substream *substream,
3850 struct snd_pcm_hw_params *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003852 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853 int err;
3854 pid_t this_pid;
3855 pid_t other_pid;
3856
Takashi Iwaib0b98112005-10-20 18:29:58 +02003857 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859
Takashi Iwaib0b98112005-10-20 18:29:58 +02003860 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862
3863 spin_lock_irq(&hdsp->lock);
3864
3865 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3866 hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
3867 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= hdsp->creg_spdif_stream);
3868 this_pid = hdsp->playback_pid;
3869 other_pid = hdsp->capture_pid;
3870 } else {
3871 this_pid = hdsp->capture_pid;
3872 other_pid = hdsp->playback_pid;
3873 }
3874
3875 if ((other_pid > 0) && (this_pid != other_pid)) {
3876
3877 /* The other stream is open, and not by the same
3878 task as this one. Make sure that the parameters
3879 that matter are the same.
3880 */
3881
3882 if (params_rate(params) != hdsp->system_sample_rate) {
3883 spin_unlock_irq(&hdsp->lock);
3884 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
3885 return -EBUSY;
3886 }
3887
3888 if (params_period_size(params) != hdsp->period_bytes / 4) {
3889 spin_unlock_irq(&hdsp->lock);
3890 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
3891 return -EBUSY;
3892 }
3893
3894 /* We're fine. */
3895
3896 spin_unlock_irq(&hdsp->lock);
3897 return 0;
3898
3899 } else {
3900 spin_unlock_irq(&hdsp->lock);
3901 }
3902
3903 /* how to make sure that the rate matches an externally-set one ?
3904 */
3905
3906 spin_lock_irq(&hdsp->lock);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003907 if (! hdsp->clock_source_locked) {
3908 if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) {
3909 spin_unlock_irq(&hdsp->lock);
3910 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
3911 return err;
3912 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913 }
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003914 spin_unlock_irq(&hdsp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915
3916 if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) {
3917 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
3918 return err;
3919 }
3920
3921 return 0;
3922}
3923
Takashi Iwai55e957d2005-11-17 14:52:13 +01003924static int snd_hdsp_channel_info(struct snd_pcm_substream *substream,
3925 struct snd_pcm_channel_info *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003927 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928 int mapped_channel;
3929
3930 snd_assert(info->channel < hdsp->max_channels, return -EINVAL);
3931
Takashi Iwaib0b98112005-10-20 18:29:58 +02003932 if ((mapped_channel = hdsp->channel_map[info->channel]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934
3935 info->offset = mapped_channel * HDSP_CHANNEL_BUFFER_BYTES;
3936 info->first = 0;
3937 info->step = 32;
3938 return 0;
3939}
3940
Takashi Iwai55e957d2005-11-17 14:52:13 +01003941static int snd_hdsp_ioctl(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 unsigned int cmd, void *arg)
3943{
3944 switch (cmd) {
3945 case SNDRV_PCM_IOCTL1_RESET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 return snd_hdsp_reset(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Takashi Iwaib0b98112005-10-20 18:29:58 +02003948 return snd_hdsp_channel_info(substream, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 default:
3950 break;
3951 }
3952
3953 return snd_pcm_lib_ioctl(substream, cmd, arg);
3954}
3955
Takashi Iwai55e957d2005-11-17 14:52:13 +01003956static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003958 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
3959 struct snd_pcm_substream *other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960 int running;
3961
Takashi Iwaib0b98112005-10-20 18:29:58 +02003962 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964
Takashi Iwai311e70a2006-09-06 12:13:37 +02003965 if (hdsp_check_for_firmware(hdsp, 0)) /* no auto-loading in trigger */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003966 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967
3968 spin_lock(&hdsp->lock);
3969 running = hdsp->running;
3970 switch (cmd) {
3971 case SNDRV_PCM_TRIGGER_START:
3972 running |= 1 << substream->stream;
3973 break;
3974 case SNDRV_PCM_TRIGGER_STOP:
3975 running &= ~(1 << substream->stream);
3976 break;
3977 default:
3978 snd_BUG();
3979 spin_unlock(&hdsp->lock);
3980 return -EINVAL;
3981 }
3982 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3983 other = hdsp->capture_substream;
3984 else
3985 other = hdsp->playback_substream;
3986
3987 if (other) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01003988 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01003989 snd_pcm_group_for_each_entry(s, substream) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990 if (s == other) {
3991 snd_pcm_trigger_done(s, substream);
3992 if (cmd == SNDRV_PCM_TRIGGER_START)
3993 running |= 1 << s->stream;
3994 else
3995 running &= ~(1 << s->stream);
3996 goto _ok;
3997 }
3998 }
3999 if (cmd == SNDRV_PCM_TRIGGER_START) {
4000 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) &&
4001 substream->stream == SNDRV_PCM_STREAM_CAPTURE)
4002 hdsp_silence_playback(hdsp);
4003 } else {
4004 if (running &&
4005 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
4006 hdsp_silence_playback(hdsp);
4007 }
4008 } else {
4009 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
4010 hdsp_silence_playback(hdsp);
4011 }
4012 _ok:
4013 snd_pcm_trigger_done(substream, substream);
4014 if (!hdsp->running && running)
4015 hdsp_start_audio(hdsp);
4016 else if (hdsp->running && !running)
4017 hdsp_stop_audio(hdsp);
4018 hdsp->running = running;
4019 spin_unlock(&hdsp->lock);
4020
4021 return 0;
4022}
4023
Takashi Iwai55e957d2005-11-17 14:52:13 +01004024static int snd_hdsp_prepare(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004026 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027 int result = 0;
4028
Takashi Iwaib0b98112005-10-20 18:29:58 +02004029 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031
Takashi Iwaib0b98112005-10-20 18:29:58 +02004032 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034
4035 spin_lock_irq(&hdsp->lock);
4036 if (!hdsp->running)
4037 hdsp_reset_hw_pointer(hdsp);
4038 spin_unlock_irq(&hdsp->lock);
4039 return result;
4040}
4041
Takashi Iwai55e957d2005-11-17 14:52:13 +01004042static struct snd_pcm_hardware snd_hdsp_playback_subinfo =
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043{
4044 .info = (SNDRV_PCM_INFO_MMAP |
4045 SNDRV_PCM_INFO_MMAP_VALID |
4046 SNDRV_PCM_INFO_NONINTERLEAVED |
4047 SNDRV_PCM_INFO_SYNC_START |
4048 SNDRV_PCM_INFO_DOUBLE),
4049#ifdef SNDRV_BIG_ENDIAN
4050 .formats = SNDRV_PCM_FMTBIT_S32_BE,
4051#else
4052 .formats = SNDRV_PCM_FMTBIT_S32_LE,
4053#endif
4054 .rates = (SNDRV_PCM_RATE_32000 |
4055 SNDRV_PCM_RATE_44100 |
4056 SNDRV_PCM_RATE_48000 |
4057 SNDRV_PCM_RATE_64000 |
4058 SNDRV_PCM_RATE_88200 |
4059 SNDRV_PCM_RATE_96000),
4060 .rate_min = 32000,
4061 .rate_max = 96000,
4062 .channels_min = 14,
4063 .channels_max = HDSP_MAX_CHANNELS,
4064 .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS,
4065 .period_bytes_min = (64 * 4) * 10,
4066 .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS,
4067 .periods_min = 2,
4068 .periods_max = 2,
4069 .fifo_size = 0
4070};
4071
Takashi Iwai55e957d2005-11-17 14:52:13 +01004072static struct snd_pcm_hardware snd_hdsp_capture_subinfo =
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073{
4074 .info = (SNDRV_PCM_INFO_MMAP |
4075 SNDRV_PCM_INFO_MMAP_VALID |
4076 SNDRV_PCM_INFO_NONINTERLEAVED |
4077 SNDRV_PCM_INFO_SYNC_START),
4078#ifdef SNDRV_BIG_ENDIAN
4079 .formats = SNDRV_PCM_FMTBIT_S32_BE,
4080#else
4081 .formats = SNDRV_PCM_FMTBIT_S32_LE,
4082#endif
4083 .rates = (SNDRV_PCM_RATE_32000 |
4084 SNDRV_PCM_RATE_44100 |
4085 SNDRV_PCM_RATE_48000 |
4086 SNDRV_PCM_RATE_64000 |
4087 SNDRV_PCM_RATE_88200 |
4088 SNDRV_PCM_RATE_96000),
4089 .rate_min = 32000,
4090 .rate_max = 96000,
4091 .channels_min = 14,
4092 .channels_max = HDSP_MAX_CHANNELS,
4093 .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS,
4094 .period_bytes_min = (64 * 4) * 10,
4095 .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS,
4096 .periods_min = 2,
4097 .periods_max = 2,
4098 .fifo_size = 0
4099};
4100
4101static unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
4102
Takashi Iwai55e957d2005-11-17 14:52:13 +01004103static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_period_sizes = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104 .count = ARRAY_SIZE(hdsp_period_sizes),
4105 .list = hdsp_period_sizes,
4106 .mask = 0
4107};
4108
4109static unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 };
4110
Takashi Iwai55e957d2005-11-17 14:52:13 +01004111static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_9632_sample_rates = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112 .count = ARRAY_SIZE(hdsp_9632_sample_rates),
4113 .list = hdsp_9632_sample_rates,
4114 .mask = 0
4115};
4116
Takashi Iwai55e957d2005-11-17 14:52:13 +01004117static int snd_hdsp_hw_rule_in_channels(struct snd_pcm_hw_params *params,
4118 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004120 struct hdsp *hdsp = rule->private;
4121 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122 if (hdsp->io_type == H9632) {
4123 unsigned int list[3];
4124 list[0] = hdsp->qs_in_channels;
4125 list[1] = hdsp->ds_in_channels;
4126 list[2] = hdsp->ss_in_channels;
4127 return snd_interval_list(c, 3, list, 0);
4128 } else {
4129 unsigned int list[2];
4130 list[0] = hdsp->ds_in_channels;
4131 list[1] = hdsp->ss_in_channels;
4132 return snd_interval_list(c, 2, list, 0);
4133 }
4134}
4135
Takashi Iwai55e957d2005-11-17 14:52:13 +01004136static int snd_hdsp_hw_rule_out_channels(struct snd_pcm_hw_params *params,
4137 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138{
4139 unsigned int list[3];
Takashi Iwai55e957d2005-11-17 14:52:13 +01004140 struct hdsp *hdsp = rule->private;
4141 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 if (hdsp->io_type == H9632) {
4143 list[0] = hdsp->qs_out_channels;
4144 list[1] = hdsp->ds_out_channels;
4145 list[2] = hdsp->ss_out_channels;
4146 return snd_interval_list(c, 3, list, 0);
4147 } else {
4148 list[0] = hdsp->ds_out_channels;
4149 list[1] = hdsp->ss_out_channels;
4150 }
4151 return snd_interval_list(c, 2, list, 0);
4152}
4153
Takashi Iwai55e957d2005-11-17 14:52:13 +01004154static int snd_hdsp_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
4155 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004157 struct hdsp *hdsp = rule->private;
4158 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4159 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160 if (r->min > 96000 && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004161 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162 .min = hdsp->qs_in_channels,
4163 .max = hdsp->qs_in_channels,
4164 .integer = 1,
4165 };
4166 return snd_interval_refine(c, &t);
4167 } else if (r->min > 48000 && r->max <= 96000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004168 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169 .min = hdsp->ds_in_channels,
4170 .max = hdsp->ds_in_channels,
4171 .integer = 1,
4172 };
4173 return snd_interval_refine(c, &t);
4174 } else if (r->max < 64000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004175 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176 .min = hdsp->ss_in_channels,
4177 .max = hdsp->ss_in_channels,
4178 .integer = 1,
4179 };
4180 return snd_interval_refine(c, &t);
4181 }
4182 return 0;
4183}
4184
Takashi Iwai55e957d2005-11-17 14:52:13 +01004185static int snd_hdsp_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
4186 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004188 struct hdsp *hdsp = rule->private;
4189 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4190 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191 if (r->min > 96000 && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004192 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004193 .min = hdsp->qs_out_channels,
4194 .max = hdsp->qs_out_channels,
4195 .integer = 1,
4196 };
4197 return snd_interval_refine(c, &t);
4198 } else if (r->min > 48000 && r->max <= 96000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004199 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200 .min = hdsp->ds_out_channels,
4201 .max = hdsp->ds_out_channels,
4202 .integer = 1,
4203 };
4204 return snd_interval_refine(c, &t);
4205 } else if (r->max < 64000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004206 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207 .min = hdsp->ss_out_channels,
4208 .max = hdsp->ss_out_channels,
4209 .integer = 1,
4210 };
4211 return snd_interval_refine(c, &t);
4212 }
4213 return 0;
4214}
4215
Takashi Iwai55e957d2005-11-17 14:52:13 +01004216static int snd_hdsp_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
4217 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004219 struct hdsp *hdsp = rule->private;
4220 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4221 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222 if (c->min >= hdsp->ss_out_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004223 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004224 .min = 32000,
4225 .max = 48000,
4226 .integer = 1,
4227 };
4228 return snd_interval_refine(r, &t);
4229 } else if (c->max <= hdsp->qs_out_channels && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004230 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231 .min = 128000,
4232 .max = 192000,
4233 .integer = 1,
4234 };
4235 return snd_interval_refine(r, &t);
4236 } else if (c->max <= hdsp->ds_out_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004237 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238 .min = 64000,
4239 .max = 96000,
4240 .integer = 1,
4241 };
4242 return snd_interval_refine(r, &t);
4243 }
4244 return 0;
4245}
4246
Takashi Iwai55e957d2005-11-17 14:52:13 +01004247static int snd_hdsp_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
4248 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004250 struct hdsp *hdsp = rule->private;
4251 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4252 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253 if (c->min >= hdsp->ss_in_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004254 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255 .min = 32000,
4256 .max = 48000,
4257 .integer = 1,
4258 };
4259 return snd_interval_refine(r, &t);
4260 } else if (c->max <= hdsp->qs_in_channels && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004261 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262 .min = 128000,
4263 .max = 192000,
4264 .integer = 1,
4265 };
4266 return snd_interval_refine(r, &t);
4267 } else if (c->max <= hdsp->ds_in_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004268 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269 .min = 64000,
4270 .max = 96000,
4271 .integer = 1,
4272 };
4273 return snd_interval_refine(r, &t);
4274 }
4275 return 0;
4276}
4277
Takashi Iwai55e957d2005-11-17 14:52:13 +01004278static int snd_hdsp_playback_open(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004280 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4281 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282
Takashi Iwaib0b98112005-10-20 18:29:58 +02004283 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004284 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285
Takashi Iwaib0b98112005-10-20 18:29:58 +02004286 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004287 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288
4289 spin_lock_irq(&hdsp->lock);
4290
4291 snd_pcm_set_sync(substream);
4292
4293 runtime->hw = snd_hdsp_playback_subinfo;
4294 runtime->dma_area = hdsp->playback_buffer;
4295 runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
4296
4297 hdsp->playback_pid = current->pid;
4298 hdsp->playback_substream = substream;
4299
4300 spin_unlock_irq(&hdsp->lock);
4301
4302 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4303 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 +02004304 if (hdsp->clock_source_locked) {
4305 runtime->hw.rate_min = runtime->hw.rate_max = hdsp->system_sample_rate;
4306 } else if (hdsp->io_type == H9632) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307 runtime->hw.rate_max = 192000;
4308 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
4309 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates);
4310 }
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02004311 if (hdsp->io_type == H9632) {
4312 runtime->hw.channels_min = hdsp->qs_out_channels;
4313 runtime->hw.channels_max = hdsp->ss_out_channels;
4314 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315
4316 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4317 snd_hdsp_hw_rule_out_channels, hdsp,
4318 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4319 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4320 snd_hdsp_hw_rule_out_channels_rate, hdsp,
4321 SNDRV_PCM_HW_PARAM_RATE, -1);
4322 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4323 snd_hdsp_hw_rule_rate_out_channels, hdsp,
4324 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4325
4326 hdsp->creg_spdif_stream = hdsp->creg_spdif;
4327 hdsp->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
4328 snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
4329 SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id);
4330 return 0;
4331}
4332
Takashi Iwai55e957d2005-11-17 14:52:13 +01004333static int snd_hdsp_playback_release(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004335 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336
4337 spin_lock_irq(&hdsp->lock);
4338
4339 hdsp->playback_pid = -1;
4340 hdsp->playback_substream = NULL;
4341
4342 spin_unlock_irq(&hdsp->lock);
4343
4344 hdsp->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
4345 snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
4346 SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id);
4347 return 0;
4348}
4349
4350
Takashi Iwai55e957d2005-11-17 14:52:13 +01004351static int snd_hdsp_capture_open(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004353 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4354 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004355
Takashi Iwaib0b98112005-10-20 18:29:58 +02004356 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358
Takashi Iwaib0b98112005-10-20 18:29:58 +02004359 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361
4362 spin_lock_irq(&hdsp->lock);
4363
4364 snd_pcm_set_sync(substream);
4365
4366 runtime->hw = snd_hdsp_capture_subinfo;
4367 runtime->dma_area = hdsp->capture_buffer;
4368 runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
4369
4370 hdsp->capture_pid = current->pid;
4371 hdsp->capture_substream = substream;
4372
4373 spin_unlock_irq(&hdsp->lock);
4374
4375 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4376 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes);
4377 if (hdsp->io_type == H9632) {
4378 runtime->hw.channels_min = hdsp->qs_in_channels;
4379 runtime->hw.channels_max = hdsp->ss_in_channels;
4380 runtime->hw.rate_max = 192000;
4381 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
4382 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates);
4383 }
4384 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4385 snd_hdsp_hw_rule_in_channels, hdsp,
4386 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4387 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4388 snd_hdsp_hw_rule_in_channels_rate, hdsp,
4389 SNDRV_PCM_HW_PARAM_RATE, -1);
4390 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4391 snd_hdsp_hw_rule_rate_in_channels, hdsp,
4392 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4393 return 0;
4394}
4395
Takashi Iwai55e957d2005-11-17 14:52:13 +01004396static int snd_hdsp_capture_release(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004398 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399
4400 spin_lock_irq(&hdsp->lock);
4401
4402 hdsp->capture_pid = -1;
4403 hdsp->capture_substream = NULL;
4404
4405 spin_unlock_irq(&hdsp->lock);
4406 return 0;
4407}
4408
Takashi Iwai55e957d2005-11-17 14:52:13 +01004409static int snd_hdsp_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410{
4411 /* we have nothing to initialize but the call is required */
4412 return 0;
4413}
4414
4415
4416/* helper functions for copying meter values */
4417static inline int copy_u32_le(void __user *dest, void __iomem *src)
4418{
4419 u32 val = readl(src);
4420 return copy_to_user(dest, &val, 4);
4421}
4422
4423static inline int copy_u64_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
4424{
4425 u32 rms_low, rms_high;
4426 u64 rms;
4427 rms_low = readl(src_low);
4428 rms_high = readl(src_high);
4429 rms = ((u64)rms_high << 32) | rms_low;
4430 return copy_to_user(dest, &rms, 8);
4431}
4432
4433static inline int copy_u48_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
4434{
4435 u32 rms_low, rms_high;
4436 u64 rms;
4437 rms_low = readl(src_low) & 0xffffff00;
4438 rms_high = readl(src_high) & 0xffffff00;
4439 rms = ((u64)rms_high << 32) | rms_low;
4440 return copy_to_user(dest, &rms, 8);
4441}
4442
Takashi Iwai55e957d2005-11-17 14:52:13 +01004443static int hdsp_9652_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444{
4445 int doublespeed = 0;
4446 int i, j, channels, ofs;
4447
4448 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
4449 doublespeed = 1;
4450 channels = doublespeed ? 14 : 26;
4451 for (i = 0, j = 0; i < 26; ++i) {
4452 if (doublespeed && (i & 4))
4453 continue;
4454 ofs = HDSP_9652_peakBase - j * 4;
4455 if (copy_u32_le(&peak_rms->input_peaks[i], hdsp->iobase + ofs))
4456 return -EFAULT;
4457 ofs -= channels * 4;
4458 if (copy_u32_le(&peak_rms->playback_peaks[i], hdsp->iobase + ofs))
4459 return -EFAULT;
4460 ofs -= channels * 4;
4461 if (copy_u32_le(&peak_rms->output_peaks[i], hdsp->iobase + ofs))
4462 return -EFAULT;
4463 ofs = HDSP_9652_rmsBase + j * 8;
4464 if (copy_u48_le(&peak_rms->input_rms[i], hdsp->iobase + ofs,
4465 hdsp->iobase + ofs + 4))
4466 return -EFAULT;
4467 ofs += channels * 8;
4468 if (copy_u48_le(&peak_rms->playback_rms[i], hdsp->iobase + ofs,
4469 hdsp->iobase + ofs + 4))
4470 return -EFAULT;
4471 ofs += channels * 8;
4472 if (copy_u48_le(&peak_rms->output_rms[i], hdsp->iobase + ofs,
4473 hdsp->iobase + ofs + 4))
4474 return -EFAULT;
4475 j++;
4476 }
4477 return 0;
4478}
4479
Takashi Iwai55e957d2005-11-17 14:52:13 +01004480static int hdsp_9632_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004481{
4482 int i, j;
Takashi Iwai55e957d2005-11-17 14:52:13 +01004483 struct hdsp_9632_meters __iomem *m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004484 int doublespeed = 0;
4485
4486 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
4487 doublespeed = 1;
Takashi Iwai55e957d2005-11-17 14:52:13 +01004488 m = (struct hdsp_9632_meters __iomem *)(hdsp->iobase+HDSP_9632_metersBase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004489 for (i = 0, j = 0; i < 16; ++i, ++j) {
4490 if (copy_u32_le(&peak_rms->input_peaks[i], &m->input_peak[j]))
4491 return -EFAULT;
4492 if (copy_u32_le(&peak_rms->playback_peaks[i], &m->playback_peak[j]))
4493 return -EFAULT;
4494 if (copy_u32_le(&peak_rms->output_peaks[i], &m->output_peak[j]))
4495 return -EFAULT;
4496 if (copy_u64_le(&peak_rms->input_rms[i], &m->input_rms_low[j],
4497 &m->input_rms_high[j]))
4498 return -EFAULT;
4499 if (copy_u64_le(&peak_rms->playback_rms[i], &m->playback_rms_low[j],
4500 &m->playback_rms_high[j]))
4501 return -EFAULT;
4502 if (copy_u64_le(&peak_rms->output_rms[i], &m->output_rms_low[j],
4503 &m->output_rms_high[j]))
4504 return -EFAULT;
4505 if (doublespeed && i == 3) i += 4;
4506 }
4507 return 0;
4508}
4509
Takashi Iwai55e957d2005-11-17 14:52:13 +01004510static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004511{
4512 int i;
4513
4514 for (i = 0; i < 26; i++) {
4515 if (copy_u32_le(&peak_rms->playback_peaks[i],
4516 hdsp->iobase + HDSP_playbackPeakLevel + i * 4))
4517 return -EFAULT;
4518 if (copy_u32_le(&peak_rms->input_peaks[i],
4519 hdsp->iobase + HDSP_inputPeakLevel + i * 4))
4520 return -EFAULT;
4521 }
4522 for (i = 0; i < 28; i++) {
4523 if (copy_u32_le(&peak_rms->output_peaks[i],
4524 hdsp->iobase + HDSP_outputPeakLevel + i * 4))
4525 return -EFAULT;
4526 }
4527 for (i = 0; i < 26; ++i) {
4528 if (copy_u64_le(&peak_rms->playback_rms[i],
4529 hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4,
4530 hdsp->iobase + HDSP_playbackRmsLevel + i * 8))
4531 return -EFAULT;
4532 if (copy_u64_le(&peak_rms->input_rms[i],
4533 hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4,
4534 hdsp->iobase + HDSP_inputRmsLevel + i * 8))
4535 return -EFAULT;
4536 }
4537 return 0;
4538}
4539
Takashi Iwai55e957d2005-11-17 14:52:13 +01004540static 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 -07004541{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004542 struct hdsp *hdsp = (struct hdsp *)hw->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004543 void __user *argp = (void __user *)arg;
4544
4545 switch (cmd) {
4546 case SNDRV_HDSP_IOCTL_GET_PEAK_RMS: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004547 struct hdsp_peak_rms __user *peak_rms = (struct hdsp_peak_rms __user *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004548
4549 if (!(hdsp->state & HDSP_FirmwareLoaded)) {
4550 snd_printk(KERN_ERR "Hammerfall-DSP: firmware needs to be uploaded to the card.\n");
4551 return -EINVAL;
4552 }
4553
4554 switch (hdsp->io_type) {
4555 case H9652:
4556 return hdsp_9652_get_peak(hdsp, peak_rms);
4557 case H9632:
4558 return hdsp_9632_get_peak(hdsp, peak_rms);
4559 default:
4560 return hdsp_get_peak(hdsp, peak_rms);
4561 }
4562 }
4563 case SNDRV_HDSP_IOCTL_GET_CONFIG_INFO: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004564 struct hdsp_config_info info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004565 unsigned long flags;
4566 int i;
4567
4568 if (!(hdsp->state & HDSP_FirmwareLoaded)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004569 snd_printk(KERN_ERR "Hammerfall-DSP: Firmware needs to be uploaded to the card.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004570 return -EINVAL;
4571 }
4572 spin_lock_irqsave(&hdsp->lock, flags);
4573 info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp);
4574 info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02004575 if (hdsp->io_type != H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004576 info.adatsync_sync_check = (unsigned char)hdsp_adatsync_sync_check(hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577 info.spdif_sync_check = (unsigned char)hdsp_spdif_sync_check(hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02004578 for (i = 0; i < ((hdsp->io_type != Multiface && hdsp->io_type != H9632) ? 3 : 1); ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004579 info.adat_sync_check[i] = (unsigned char)hdsp_adat_sync_check(hdsp, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004580 info.spdif_in = (unsigned char)hdsp_spdif_in(hdsp);
4581 info.spdif_out = (unsigned char)hdsp_spdif_out(hdsp);
4582 info.spdif_professional = (unsigned char)hdsp_spdif_professional(hdsp);
4583 info.spdif_emphasis = (unsigned char)hdsp_spdif_emphasis(hdsp);
4584 info.spdif_nonaudio = (unsigned char)hdsp_spdif_nonaudio(hdsp);
4585 info.spdif_sample_rate = hdsp_spdif_sample_rate(hdsp);
4586 info.system_sample_rate = hdsp->system_sample_rate;
4587 info.autosync_sample_rate = hdsp_external_sample_rate(hdsp);
4588 info.system_clock_mode = (unsigned char)hdsp_system_clock_mode(hdsp);
4589 info.clock_source = (unsigned char)hdsp_clock_source(hdsp);
4590 info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp);
4591 info.line_out = (unsigned char)hdsp_line_out(hdsp);
4592 if (hdsp->io_type == H9632) {
4593 info.da_gain = (unsigned char)hdsp_da_gain(hdsp);
4594 info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp);
4595 info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp);
4596 info.xlr_breakout_cable = (unsigned char)hdsp_xlr_breakout_cable(hdsp);
4597
4598 }
Takashi Iwaib0b98112005-10-20 18:29:58 +02004599 if (hdsp->io_type == H9632 || hdsp->io_type == H9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004600 info.analog_extension_board = (unsigned char)hdsp_aeb(hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004601 spin_unlock_irqrestore(&hdsp->lock, flags);
4602 if (copy_to_user(argp, &info, sizeof(info)))
4603 return -EFAULT;
4604 break;
4605 }
4606 case SNDRV_HDSP_IOCTL_GET_9632_AEB: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004607 struct hdsp_9632_aeb h9632_aeb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004608
4609 if (hdsp->io_type != H9632) return -EINVAL;
4610 h9632_aeb.aebi = hdsp->ss_in_channels - H9632_SS_CHANNELS;
4611 h9632_aeb.aebo = hdsp->ss_out_channels - H9632_SS_CHANNELS;
4612 if (copy_to_user(argp, &h9632_aeb, sizeof(h9632_aeb)))
4613 return -EFAULT;
4614 break;
4615 }
4616 case SNDRV_HDSP_IOCTL_GET_VERSION: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004617 struct hdsp_version hdsp_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004618 int err;
4619
4620 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
4621 if (hdsp->io_type == Undefined) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004622 if ((err = hdsp_get_iobox_version(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004623 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004624 }
4625 hdsp_version.io_type = hdsp->io_type;
4626 hdsp_version.firmware_rev = hdsp->firmware_rev;
Takashi Iwaib0b98112005-10-20 18:29:58 +02004627 if ((err = copy_to_user(argp, &hdsp_version, sizeof(hdsp_version))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004628 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004629 break;
4630 }
4631 case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004632 struct hdsp_firmware __user *firmware;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004633 u32 __user *firmware_data;
4634 int err;
4635
4636 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
4637 /* SNDRV_HDSP_IOCTL_GET_VERSION must have been called */
4638 if (hdsp->io_type == Undefined) return -EINVAL;
4639
4640 if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded))
4641 return -EBUSY;
4642
Takashi Iwaib0b98112005-10-20 18:29:58 +02004643 snd_printk(KERN_INFO "Hammerfall-DSP: initializing firmware upload\n");
Takashi Iwai55e957d2005-11-17 14:52:13 +01004644 firmware = (struct hdsp_firmware __user *)argp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004645
Takashi Iwaib0b98112005-10-20 18:29:58 +02004646 if (get_user(firmware_data, &firmware->firmware_data))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004647 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004648
Takashi Iwaib0b98112005-10-20 18:29:58 +02004649 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004650 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004651
Takashi Iwaib0b98112005-10-20 18:29:58 +02004652 if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004653 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004654
4655 hdsp->state |= HDSP_FirmwareCached;
4656
Takashi Iwaib0b98112005-10-20 18:29:58 +02004657 if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004658 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004659
4660 if (!(hdsp->state & HDSP_InitializationComplete)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004661 if ((err = snd_hdsp_enable_io(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004662 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004663
4664 snd_hdsp_initialize_channels(hdsp);
4665 snd_hdsp_initialize_midi_flush(hdsp);
4666
4667 if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004668 snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n");
4669 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004670 }
4671 }
4672 break;
4673 }
4674 case SNDRV_HDSP_IOCTL_GET_MIXER: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004675 struct hdsp_mixer __user *mixer = (struct hdsp_mixer __user *)argp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004676 if (copy_to_user(mixer->matrix, hdsp->mixer_matrix, sizeof(unsigned short)*HDSP_MATRIX_MIXER_SIZE))
4677 return -EFAULT;
4678 break;
4679 }
4680 default:
4681 return -EINVAL;
4682 }
4683 return 0;
4684}
4685
Takashi Iwai55e957d2005-11-17 14:52:13 +01004686static struct snd_pcm_ops snd_hdsp_playback_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004687 .open = snd_hdsp_playback_open,
4688 .close = snd_hdsp_playback_release,
4689 .ioctl = snd_hdsp_ioctl,
4690 .hw_params = snd_hdsp_hw_params,
4691 .prepare = snd_hdsp_prepare,
4692 .trigger = snd_hdsp_trigger,
4693 .pointer = snd_hdsp_hw_pointer,
4694 .copy = snd_hdsp_playback_copy,
4695 .silence = snd_hdsp_hw_silence,
4696};
4697
Takashi Iwai55e957d2005-11-17 14:52:13 +01004698static struct snd_pcm_ops snd_hdsp_capture_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004699 .open = snd_hdsp_capture_open,
4700 .close = snd_hdsp_capture_release,
4701 .ioctl = snd_hdsp_ioctl,
4702 .hw_params = snd_hdsp_hw_params,
4703 .prepare = snd_hdsp_prepare,
4704 .trigger = snd_hdsp_trigger,
4705 .pointer = snd_hdsp_hw_pointer,
4706 .copy = snd_hdsp_capture_copy,
4707};
4708
Takashi Iwai92eed662008-02-22 18:35:56 +01004709static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004710{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004711 struct snd_hwdep *hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004712 int err;
4713
4714 if ((err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw)) < 0)
4715 return err;
4716
4717 hdsp->hwdep = hw;
4718 hw->private_data = hdsp;
4719 strcpy(hw->name, "HDSP hwdep interface");
4720
4721 hw->ops.open = snd_hdsp_hwdep_dummy_op;
4722 hw->ops.ioctl = snd_hdsp_hwdep_ioctl;
4723 hw->ops.release = snd_hdsp_hwdep_dummy_op;
4724
4725 return 0;
4726}
4727
Takashi Iwai55e957d2005-11-17 14:52:13 +01004728static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004729{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004730 struct snd_pcm *pcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004731 int err;
4732
4733 if ((err = snd_pcm_new(card, hdsp->card_name, 0, 1, 1, &pcm)) < 0)
4734 return err;
4735
4736 hdsp->pcm = pcm;
4737 pcm->private_data = hdsp;
4738 strcpy(pcm->name, hdsp->card_name);
4739
4740 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_hdsp_playback_ops);
4741 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_hdsp_capture_ops);
4742
4743 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
4744
4745 return 0;
4746}
4747
Takashi Iwai55e957d2005-11-17 14:52:13 +01004748static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004749{
4750 hdsp->control2_register |= HDSP_9652_ENABLE_MIXER;
4751 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
4752}
4753
Takashi Iwai55e957d2005-11-17 14:52:13 +01004754static int snd_hdsp_enable_io (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004755{
4756 int i;
4757
4758 if (hdsp_fifo_wait (hdsp, 0, 100)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004759 snd_printk(KERN_ERR "Hammerfall-DSP: enable_io fifo_wait failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004760 return -EIO;
4761 }
4762
4763 for (i = 0; i < hdsp->max_channels; ++i) {
4764 hdsp_write (hdsp, HDSP_inputEnable + (4 * i), 1);
4765 hdsp_write (hdsp, HDSP_outputEnable + (4 * i), 1);
4766 }
4767
4768 return 0;
4769}
4770
Takashi Iwai55e957d2005-11-17 14:52:13 +01004771static void snd_hdsp_initialize_channels(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004772{
4773 int status, aebi_channels, aebo_channels;
4774
4775 switch (hdsp->io_type) {
4776 case Digiface:
4777 hdsp->card_name = "RME Hammerfall DSP + Digiface";
4778 hdsp->ss_in_channels = hdsp->ss_out_channels = DIGIFACE_SS_CHANNELS;
4779 hdsp->ds_in_channels = hdsp->ds_out_channels = DIGIFACE_DS_CHANNELS;
4780 break;
4781
4782 case H9652:
4783 hdsp->card_name = "RME Hammerfall HDSP 9652";
4784 hdsp->ss_in_channels = hdsp->ss_out_channels = H9652_SS_CHANNELS;
4785 hdsp->ds_in_channels = hdsp->ds_out_channels = H9652_DS_CHANNELS;
4786 break;
4787
4788 case H9632:
4789 status = hdsp_read(hdsp, HDSP_statusRegister);
4790 /* HDSP_AEBx bits are low when AEB are connected */
4791 aebi_channels = (status & HDSP_AEBI) ? 0 : 4;
4792 aebo_channels = (status & HDSP_AEBO) ? 0 : 4;
4793 hdsp->card_name = "RME Hammerfall HDSP 9632";
4794 hdsp->ss_in_channels = H9632_SS_CHANNELS+aebi_channels;
4795 hdsp->ds_in_channels = H9632_DS_CHANNELS+aebi_channels;
4796 hdsp->qs_in_channels = H9632_QS_CHANNELS+aebi_channels;
4797 hdsp->ss_out_channels = H9632_SS_CHANNELS+aebo_channels;
4798 hdsp->ds_out_channels = H9632_DS_CHANNELS+aebo_channels;
4799 hdsp->qs_out_channels = H9632_QS_CHANNELS+aebo_channels;
4800 break;
4801
4802 case Multiface:
4803 hdsp->card_name = "RME Hammerfall DSP + Multiface";
4804 hdsp->ss_in_channels = hdsp->ss_out_channels = MULTIFACE_SS_CHANNELS;
4805 hdsp->ds_in_channels = hdsp->ds_out_channels = MULTIFACE_DS_CHANNELS;
4806 break;
4807
4808 default:
4809 /* should never get here */
4810 break;
4811 }
4812}
4813
Takashi Iwai55e957d2005-11-17 14:52:13 +01004814static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004815{
4816 snd_hdsp_flush_midi_input (hdsp, 0);
4817 snd_hdsp_flush_midi_input (hdsp, 1);
4818}
4819
Takashi Iwai55e957d2005-11-17 14:52:13 +01004820static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004821{
4822 int err;
4823
4824 if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004825 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating pcm interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004826 return err;
4827 }
4828
4829
4830 if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004831 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating first midi interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004832 return err;
4833 }
4834
4835 if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
4836 if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004837 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating second midi interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004838 return err;
4839 }
4840 }
4841
4842 if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004843 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating ctl interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004844 return err;
4845 }
4846
4847 snd_hdsp_proc_init(hdsp);
4848
4849 hdsp->system_sample_rate = -1;
4850 hdsp->playback_pid = -1;
4851 hdsp->capture_pid = -1;
4852 hdsp->capture_substream = NULL;
4853 hdsp->playback_substream = NULL;
4854
4855 if ((err = snd_hdsp_set_defaults(hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004856 snd_printk(KERN_ERR "Hammerfall-DSP: Error setting default values\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004857 return err;
4858 }
4859
4860 if (!(hdsp->state & HDSP_InitializationComplete)) {
Clemens Ladischb73c1c12005-09-02 08:49:21 +02004861 strcpy(card->shortname, "Hammerfall DSP");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004862 sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
4863 hdsp->port, hdsp->irq);
4864
4865 if ((err = snd_card_register(card)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004866 snd_printk(KERN_ERR "Hammerfall-DSP: error registering card\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004867 return err;
4868 }
4869 hdsp->state |= HDSP_InitializationComplete;
4870 }
4871
4872 return 0;
4873}
4874
4875#ifdef HDSP_FW_LOADER
4876/* load firmware via hotplug fw loader */
Takashi Iwai92eed662008-02-22 18:35:56 +01004877static int hdsp_request_fw_loader(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004878{
4879 const char *fwfile;
4880 const struct firmware *fw;
4881 int err;
4882
4883 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
4884 return 0;
4885 if (hdsp->io_type == Undefined) {
4886 if ((err = hdsp_get_iobox_version(hdsp)) < 0)
4887 return err;
4888 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
4889 return 0;
4890 }
4891
4892 /* caution: max length of firmware filename is 30! */
4893 switch (hdsp->io_type) {
4894 case Multiface:
4895 if (hdsp->firmware_rev == 0xa)
4896 fwfile = "multiface_firmware.bin";
4897 else
4898 fwfile = "multiface_firmware_rev11.bin";
4899 break;
4900 case Digiface:
4901 if (hdsp->firmware_rev == 0xa)
4902 fwfile = "digiface_firmware.bin";
4903 else
4904 fwfile = "digiface_firmware_rev11.bin";
4905 break;
4906 default:
4907 snd_printk(KERN_ERR "Hammerfall-DSP: invalid io_type %d\n", hdsp->io_type);
4908 return -EINVAL;
4909 }
4910
4911 if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) {
4912 snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile);
4913 return -ENOENT;
4914 }
4915 if (fw->size < sizeof(hdsp->firmware_cache)) {
4916 snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n",
4917 (int)fw->size, (int)sizeof(hdsp->firmware_cache));
4918 release_firmware(fw);
4919 return -EINVAL;
4920 }
Thomas Charbonnel7679a032005-04-25 11:35:29 +02004921
Linus Torvalds1da177e2005-04-16 15:20:36 -07004922 memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache));
Thomas Charbonnel7679a032005-04-25 11:35:29 +02004923
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924 release_firmware(fw);
4925
4926 hdsp->state |= HDSP_FirmwareCached;
4927
4928 if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
4929 return err;
4930
4931 if (!(hdsp->state & HDSP_InitializationComplete)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004932 if ((err = snd_hdsp_enable_io(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004933 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004934
4935 if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004936 snd_printk(KERN_ERR "Hammerfall-DSP: error creating hwdep device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004937 return err;
4938 }
4939 snd_hdsp_initialize_channels(hdsp);
4940 snd_hdsp_initialize_midi_flush(hdsp);
4941 if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004942 snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004943 return err;
4944 }
4945 }
4946 return 0;
4947}
4948#endif
4949
Takashi Iwai55e957d2005-11-17 14:52:13 +01004950static int __devinit snd_hdsp_create(struct snd_card *card,
4951 struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004952{
4953 struct pci_dev *pci = hdsp->pci;
4954 int err;
4955 int is_9652 = 0;
4956 int is_9632 = 0;
4957
4958 hdsp->irq = -1;
4959 hdsp->state = 0;
4960 hdsp->midi[0].rmidi = NULL;
4961 hdsp->midi[1].rmidi = NULL;
4962 hdsp->midi[0].input = NULL;
4963 hdsp->midi[1].input = NULL;
4964 hdsp->midi[0].output = NULL;
4965 hdsp->midi[1].output = NULL;
4966 hdsp->midi[0].pending = 0;
4967 hdsp->midi[1].pending = 0;
4968 spin_lock_init(&hdsp->midi[0].lock);
4969 spin_lock_init(&hdsp->midi[1].lock);
4970 hdsp->iobase = NULL;
4971 hdsp->control_register = 0;
4972 hdsp->control2_register = 0;
4973 hdsp->io_type = Undefined;
4974 hdsp->max_channels = 26;
4975
4976 hdsp->card = card;
4977
4978 spin_lock_init(&hdsp->lock);
4979
4980 tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp);
4981
4982 pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev);
4983 hdsp->firmware_rev &= 0xff;
4984
4985 /* From Martin Bjoernsen :
4986 "It is important that the card's latency timer register in
4987 the PCI configuration space is set to a value much larger
4988 than 0 by the computer's BIOS or the driver.
4989 The windows driver always sets this 8 bit register [...]
4990 to its maximum 255 to avoid problems with some computers."
4991 */
4992 pci_write_config_byte(hdsp->pci, PCI_LATENCY_TIMER, 0xFF);
4993
4994 strcpy(card->driver, "H-DSP");
4995 strcpy(card->mixername, "Xilinx FPGA");
4996
Takashi Iwaib0b98112005-10-20 18:29:58 +02004997 if (hdsp->firmware_rev < 0xa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004998 return -ENODEV;
Takashi Iwaib0b98112005-10-20 18:29:58 +02004999 else if (hdsp->firmware_rev < 0x64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005000 hdsp->card_name = "RME Hammerfall DSP";
Takashi Iwaib0b98112005-10-20 18:29:58 +02005001 else if (hdsp->firmware_rev < 0x96) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005002 hdsp->card_name = "RME HDSP 9652";
5003 is_9652 = 1;
5004 } else {
5005 hdsp->card_name = "RME HDSP 9632";
5006 hdsp->max_channels = 16;
5007 is_9632 = 1;
5008 }
5009
Takashi Iwaib0b98112005-10-20 18:29:58 +02005010 if ((err = pci_enable_device(pci)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005011 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005012
5013 pci_set_master(hdsp->pci);
5014
5015 if ((err = pci_request_regions(pci, "hdsp")) < 0)
5016 return err;
5017 hdsp->port = pci_resource_start(pci, 0);
5018 if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02005019 snd_printk(KERN_ERR "Hammerfall-DSP: unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005020 return -EBUSY;
5021 }
5022
Takashi Iwai437a5a42006-11-21 12:14:23 +01005023 if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_SHARED,
5024 "hdsp", hdsp)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02005025 snd_printk(KERN_ERR "Hammerfall-DSP: unable to use IRQ %d\n", pci->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005026 return -EBUSY;
5027 }
5028
5029 hdsp->irq = pci->irq;
Remy Bruno176546a2006-10-16 12:32:53 +02005030 hdsp->precise_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005031 hdsp->use_midi_tasklet = 1;
Remy Brunod7923b22006-10-17 12:41:56 +02005032 hdsp->dds_value = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005033
Takashi Iwaib0b98112005-10-20 18:29:58 +02005034 if ((err = snd_hdsp_initialize_memory(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005035 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005036
5037 if (!is_9652 && !is_9632) {
5038 /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */
Takashi Iwaib0b98112005-10-20 18:29:58 +02005039 ssleep(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040
5041 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
5042#ifdef HDSP_FW_LOADER
Takashi Iwaib0b98112005-10-20 18:29:58 +02005043 if ((err = hdsp_request_fw_loader(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005044 /* we don't fail as this can happen
5045 if userspace is not ready for
5046 firmware upload
5047 */
Takashi Iwaib0b98112005-10-20 18:29:58 +02005048 snd_printk(KERN_ERR "Hammerfall-DSP: couldn't get firmware from userspace. try using hdsploader\n");
5049 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07005050 /* init is complete, we return */
5051 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052#endif
5053 /* no iobox connected, we defer initialization */
Takashi Iwaib0b98112005-10-20 18:29:58 +02005054 snd_printk(KERN_INFO "Hammerfall-DSP: card initialization pending : waiting for firmware\n");
5055 if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005056 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005057 return 0;
5058 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02005059 snd_printk(KERN_INFO "Hammerfall-DSP: Firmware already present, initializing card.\n");
5060 if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005061 hdsp->io_type = Multiface;
Takashi Iwaib0b98112005-10-20 18:29:58 +02005062 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07005063 hdsp->io_type = Digiface;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005064 }
5065 }
5066
Takashi Iwaib0b98112005-10-20 18:29:58 +02005067 if ((err = snd_hdsp_enable_io(hdsp)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005068 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069
Takashi Iwaib0b98112005-10-20 18:29:58 +02005070 if (is_9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005071 hdsp->io_type = H9652;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005072
Takashi Iwaib0b98112005-10-20 18:29:58 +02005073 if (is_9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005074 hdsp->io_type = H9632;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005075
Takashi Iwaib0b98112005-10-20 18:29:58 +02005076 if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005077 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005078
5079 snd_hdsp_initialize_channels(hdsp);
5080 snd_hdsp_initialize_midi_flush(hdsp);
5081
5082 hdsp->state |= HDSP_FirmwareLoaded;
5083
Takashi Iwaib0b98112005-10-20 18:29:58 +02005084 if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005085 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005086
5087 return 0;
5088}
5089
Takashi Iwai55e957d2005-11-17 14:52:13 +01005090static int snd_hdsp_free(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005091{
5092 if (hdsp->port) {
5093 /* stop the audio, and cancel all interrupts */
5094 tasklet_kill(&hdsp->midi_tasklet);
5095 hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable);
5096 hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
5097 }
5098
5099 if (hdsp->irq >= 0)
5100 free_irq(hdsp->irq, (void *)hdsp);
5101
5102 snd_hdsp_free_buffers(hdsp);
5103
5104 if (hdsp->iobase)
5105 iounmap(hdsp->iobase);
5106
5107 if (hdsp->port)
5108 pci_release_regions(hdsp->pci);
5109
5110 pci_disable_device(hdsp->pci);
5111 return 0;
5112}
5113
Takashi Iwai55e957d2005-11-17 14:52:13 +01005114static void snd_hdsp_card_free(struct snd_card *card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005115{
Takashi Iwai55e957d2005-11-17 14:52:13 +01005116 struct hdsp *hdsp = (struct hdsp *) card->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005117
5118 if (hdsp)
5119 snd_hdsp_free(hdsp);
5120}
5121
5122static int __devinit snd_hdsp_probe(struct pci_dev *pci,
5123 const struct pci_device_id *pci_id)
5124{
5125 static int dev;
Takashi Iwai55e957d2005-11-17 14:52:13 +01005126 struct hdsp *hdsp;
5127 struct snd_card *card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005128 int err;
5129
5130 if (dev >= SNDRV_CARDS)
5131 return -ENODEV;
5132 if (!enable[dev]) {
5133 dev++;
5134 return -ENOENT;
5135 }
5136
Takashi Iwai55e957d2005-11-17 14:52:13 +01005137 if (!(card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005138 return -ENOMEM;
5139
Takashi Iwai55e957d2005-11-17 14:52:13 +01005140 hdsp = (struct hdsp *) card->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005141 card->private_free = snd_hdsp_card_free;
5142 hdsp->dev = dev;
5143 hdsp->pci = pci;
5144 snd_card_set_dev(card, &pci->dev);
5145
5146 if ((err = snd_hdsp_create(card, hdsp)) < 0) {
5147 snd_card_free(card);
5148 return err;
5149 }
5150
5151 strcpy(card->shortname, "Hammerfall DSP");
5152 sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
5153 hdsp->port, hdsp->irq);
5154
5155 if ((err = snd_card_register(card)) < 0) {
5156 snd_card_free(card);
5157 return err;
5158 }
5159 pci_set_drvdata(pci, card);
5160 dev++;
5161 return 0;
5162}
5163
5164static void __devexit snd_hdsp_remove(struct pci_dev *pci)
5165{
5166 snd_card_free(pci_get_drvdata(pci));
5167 pci_set_drvdata(pci, NULL);
5168}
5169
5170static struct pci_driver driver = {
5171 .name = "RME Hammerfall DSP",
5172 .id_table = snd_hdsp_ids,
5173 .probe = snd_hdsp_probe,
5174 .remove = __devexit_p(snd_hdsp_remove),
5175};
5176
5177static int __init alsa_card_hdsp_init(void)
5178{
Takashi Iwai01d25d42005-04-11 16:58:24 +02005179 return pci_register_driver(&driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005180}
5181
5182static void __exit alsa_card_hdsp_exit(void)
5183{
5184 pci_unregister_driver(&driver);
5185}
5186
5187module_init(alsa_card_hdsp_init)
5188module_exit(alsa_card_hdsp_exit)