blob: 849ffe4aa5ca944f35dfa9dc55c5c5c24086bb6f [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
24#include <sound/driver.h>
25#include <linux/init.h>
26#include <linux/delay.h>
27#include <linux/interrupt.h>
28#include <linux/slab.h>
29#include <linux/pci.h>
30#include <linux/firmware.h>
31#include <linux/moduleparam.h>
32
33#include <sound/core.h>
34#include <sound/control.h>
35#include <sound/pcm.h>
36#include <sound/info.h>
37#include <sound/asoundef.h>
38#include <sound/rawmidi.h>
39#include <sound/hwdep.h>
40#include <sound/initval.h>
41#include <sound/hdsp.h>
42
43#include <asm/byteorder.h>
44#include <asm/current.h>
45#include <asm/io.h>
46
47static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
48static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
49static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
50
51module_param_array(index, int, NULL, 0444);
52MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface.");
53module_param_array(id, charp, NULL, 0444);
54MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface.");
55module_param_array(enable, bool, NULL, 0444);
56MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards.");
57MODULE_AUTHOR("Paul Davis <paul@linuxaudiosystems.com>, Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
58MODULE_DESCRIPTION("RME Hammerfall DSP");
59MODULE_LICENSE("GPL");
60MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
61 "{RME HDSP-9652},"
62 "{RME HDSP-9632}}");
63
64#define HDSP_MAX_CHANNELS 26
65#define HDSP_MAX_DS_CHANNELS 14
66#define HDSP_MAX_QS_CHANNELS 8
67#define DIGIFACE_SS_CHANNELS 26
68#define DIGIFACE_DS_CHANNELS 14
69#define MULTIFACE_SS_CHANNELS 18
70#define MULTIFACE_DS_CHANNELS 14
71#define H9652_SS_CHANNELS 26
72#define H9652_DS_CHANNELS 14
73/* This does not include possible Analog Extension Boards
74 AEBs are detected at card initialization
75*/
76#define H9632_SS_CHANNELS 12
77#define H9632_DS_CHANNELS 8
78#define H9632_QS_CHANNELS 4
79
80/* Write registers. These are defined as byte-offsets from the iobase value.
81 */
82#define HDSP_resetPointer 0
83#define HDSP_outputBufferAddress 32
84#define HDSP_inputBufferAddress 36
85#define HDSP_controlRegister 64
86#define HDSP_interruptConfirmation 96
87#define HDSP_outputEnable 128
88#define HDSP_control2Reg 256
89#define HDSP_midiDataOut0 352
90#define HDSP_midiDataOut1 356
91#define HDSP_fifoData 368
92#define HDSP_inputEnable 384
93
94/* Read registers. These are defined as byte-offsets from the iobase value
95 */
96
97#define HDSP_statusRegister 0
98#define HDSP_timecode 128
99#define HDSP_status2Register 192
100#define HDSP_midiDataOut0 352
101#define HDSP_midiDataOut1 356
102#define HDSP_midiDataIn0 360
103#define HDSP_midiDataIn1 364
104#define HDSP_midiStatusOut0 384
105#define HDSP_midiStatusOut1 388
106#define HDSP_midiStatusIn0 392
107#define HDSP_midiStatusIn1 396
108#define HDSP_fifoStatus 400
109
110/* the meters are regular i/o-mapped registers, but offset
111 considerably from the rest. the peak registers are reset
112 when read; the least-significant 4 bits are full-scale counters;
113 the actual peak value is in the most-significant 24 bits.
114*/
115
116#define HDSP_playbackPeakLevel 4096 /* 26 * 32 bit values */
117#define HDSP_inputPeakLevel 4224 /* 26 * 32 bit values */
118#define HDSP_outputPeakLevel 4352 /* (26+2) * 32 bit values */
119#define HDSP_playbackRmsLevel 4612 /* 26 * 64 bit values */
120#define HDSP_inputRmsLevel 4868 /* 26 * 64 bit values */
121
122
123/* This is for H9652 cards
124 Peak values are read downward from the base
125 Rms values are read upward
126 There are rms values for the outputs too
127 26*3 values are read in ss mode
128 14*3 in ds mode, with no gap between values
129*/
130#define HDSP_9652_peakBase 7164
131#define HDSP_9652_rmsBase 4096
132
133/* c.f. the hdsp_9632_meters_t struct */
134#define HDSP_9632_metersBase 4096
135
136#define HDSP_IO_EXTENT 7168
137
138/* control2 register bits */
139
140#define HDSP_TMS 0x01
141#define HDSP_TCK 0x02
142#define HDSP_TDI 0x04
143#define HDSP_JTAG 0x08
144#define HDSP_PWDN 0x10
145#define HDSP_PROGRAM 0x020
146#define HDSP_CONFIG_MODE_0 0x040
147#define HDSP_CONFIG_MODE_1 0x080
148#define HDSP_VERSION_BIT 0x100
149#define HDSP_BIGENDIAN_MODE 0x200
150#define HDSP_RD_MULTIPLE 0x400
151#define HDSP_9652_ENABLE_MIXER 0x800
152#define HDSP_TDO 0x10000000
153
154#define HDSP_S_PROGRAM (HDSP_PROGRAM|HDSP_CONFIG_MODE_0)
155#define HDSP_S_LOAD (HDSP_PROGRAM|HDSP_CONFIG_MODE_1)
156
157/* Control Register bits */
158
159#define HDSP_Start (1<<0) /* start engine */
160#define HDSP_Latency0 (1<<1) /* buffer size = 2^n where n is defined by Latency{2,1,0} */
161#define HDSP_Latency1 (1<<2) /* [ see above ] */
162#define HDSP_Latency2 (1<<3) /* [ see above ] */
163#define HDSP_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */
164#define HDSP_AudioInterruptEnable (1<<5) /* what do you think ? */
165#define HDSP_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz/176.4kHz 1=48kHz/96kHz/192kHz */
166#define HDSP_Frequency1 (1<<7) /* 0=32kHz/64kHz/128kHz */
167#define HDSP_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
168#define HDSP_SPDIFProfessional (1<<9) /* 0=consumer, 1=professional */
169#define HDSP_SPDIFEmphasis (1<<10) /* 0=none, 1=on */
170#define HDSP_SPDIFNonAudio (1<<11) /* 0=off, 1=on */
171#define HDSP_SPDIFOpticalOut (1<<12) /* 1=use 1st ADAT connector for SPDIF, 0=do not */
172#define HDSP_SyncRef2 (1<<13)
173#define HDSP_SPDIFInputSelect0 (1<<14)
174#define HDSP_SPDIFInputSelect1 (1<<15)
175#define HDSP_SyncRef0 (1<<16)
176#define HDSP_SyncRef1 (1<<17)
177#define HDSP_AnalogExtensionBoard (1<<18) /* For H9632 cards */
178#define HDSP_XLRBreakoutCable (1<<20) /* For H9632 cards */
179#define HDSP_Midi0InterruptEnable (1<<22)
180#define HDSP_Midi1InterruptEnable (1<<23)
181#define HDSP_LineOut (1<<24)
182#define HDSP_ADGain0 (1<<25) /* From here : H9632 specific */
183#define HDSP_ADGain1 (1<<26)
184#define HDSP_DAGain0 (1<<27)
185#define HDSP_DAGain1 (1<<28)
186#define HDSP_PhoneGain0 (1<<29)
187#define HDSP_PhoneGain1 (1<<30)
188#define HDSP_QuadSpeed (1<<31)
189
190#define HDSP_ADGainMask (HDSP_ADGain0|HDSP_ADGain1)
191#define HDSP_ADGainMinus10dBV HDSP_ADGainMask
192#define HDSP_ADGainPlus4dBu (HDSP_ADGain0)
193#define HDSP_ADGainLowGain 0
194
195#define HDSP_DAGainMask (HDSP_DAGain0|HDSP_DAGain1)
196#define HDSP_DAGainHighGain HDSP_DAGainMask
197#define HDSP_DAGainPlus4dBu (HDSP_DAGain0)
198#define HDSP_DAGainMinus10dBV 0
199
200#define HDSP_PhoneGainMask (HDSP_PhoneGain0|HDSP_PhoneGain1)
201#define HDSP_PhoneGain0dB HDSP_PhoneGainMask
202#define HDSP_PhoneGainMinus6dB (HDSP_PhoneGain0)
203#define HDSP_PhoneGainMinus12dB 0
204
205#define HDSP_LatencyMask (HDSP_Latency0|HDSP_Latency1|HDSP_Latency2)
206#define HDSP_FrequencyMask (HDSP_Frequency0|HDSP_Frequency1|HDSP_DoubleSpeed|HDSP_QuadSpeed)
207
208#define HDSP_SPDIFInputMask (HDSP_SPDIFInputSelect0|HDSP_SPDIFInputSelect1)
209#define HDSP_SPDIFInputADAT1 0
210#define HDSP_SPDIFInputCoaxial (HDSP_SPDIFInputSelect0)
211#define HDSP_SPDIFInputCdrom (HDSP_SPDIFInputSelect1)
212#define HDSP_SPDIFInputAES (HDSP_SPDIFInputSelect0|HDSP_SPDIFInputSelect1)
213
214#define HDSP_SyncRefMask (HDSP_SyncRef0|HDSP_SyncRef1|HDSP_SyncRef2)
215#define HDSP_SyncRef_ADAT1 0
216#define HDSP_SyncRef_ADAT2 (HDSP_SyncRef0)
217#define HDSP_SyncRef_ADAT3 (HDSP_SyncRef1)
218#define HDSP_SyncRef_SPDIF (HDSP_SyncRef0|HDSP_SyncRef1)
219#define HDSP_SyncRef_WORD (HDSP_SyncRef2)
220#define HDSP_SyncRef_ADAT_SYNC (HDSP_SyncRef0|HDSP_SyncRef2)
221
222/* Sample Clock Sources */
223
224#define HDSP_CLOCK_SOURCE_AUTOSYNC 0
225#define HDSP_CLOCK_SOURCE_INTERNAL_32KHZ 1
226#define HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ 2
227#define HDSP_CLOCK_SOURCE_INTERNAL_48KHZ 3
228#define HDSP_CLOCK_SOURCE_INTERNAL_64KHZ 4
229#define HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ 5
230#define HDSP_CLOCK_SOURCE_INTERNAL_96KHZ 6
231#define HDSP_CLOCK_SOURCE_INTERNAL_128KHZ 7
232#define HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ 8
233#define HDSP_CLOCK_SOURCE_INTERNAL_192KHZ 9
234
235/* Preferred sync reference choices - used by "pref_sync_ref" control switch */
236
237#define HDSP_SYNC_FROM_WORD 0
238#define HDSP_SYNC_FROM_SPDIF 1
239#define HDSP_SYNC_FROM_ADAT1 2
240#define HDSP_SYNC_FROM_ADAT_SYNC 3
241#define HDSP_SYNC_FROM_ADAT2 4
242#define HDSP_SYNC_FROM_ADAT3 5
243
244/* SyncCheck status */
245
246#define HDSP_SYNC_CHECK_NO_LOCK 0
247#define HDSP_SYNC_CHECK_LOCK 1
248#define HDSP_SYNC_CHECK_SYNC 2
249
250/* AutoSync references - used by "autosync_ref" control switch */
251
252#define HDSP_AUTOSYNC_FROM_WORD 0
253#define HDSP_AUTOSYNC_FROM_ADAT_SYNC 1
254#define HDSP_AUTOSYNC_FROM_SPDIF 2
255#define HDSP_AUTOSYNC_FROM_NONE 3
256#define HDSP_AUTOSYNC_FROM_ADAT1 4
257#define HDSP_AUTOSYNC_FROM_ADAT2 5
258#define HDSP_AUTOSYNC_FROM_ADAT3 6
259
260/* Possible sources of S/PDIF input */
261
262#define HDSP_SPDIFIN_OPTICAL 0 /* optical (ADAT1) */
263#define HDSP_SPDIFIN_COAXIAL 1 /* coaxial (RCA) */
264#define HDSP_SPDIFIN_INTERNAL 2 /* internal (CDROM) */
265#define HDSP_SPDIFIN_AES 3 /* xlr for H9632 (AES)*/
266
267#define HDSP_Frequency32KHz HDSP_Frequency0
268#define HDSP_Frequency44_1KHz HDSP_Frequency1
269#define HDSP_Frequency48KHz (HDSP_Frequency1|HDSP_Frequency0)
270#define HDSP_Frequency64KHz (HDSP_DoubleSpeed|HDSP_Frequency0)
271#define HDSP_Frequency88_2KHz (HDSP_DoubleSpeed|HDSP_Frequency1)
272#define HDSP_Frequency96KHz (HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0)
273/* For H9632 cards */
274#define HDSP_Frequency128KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency0)
275#define HDSP_Frequency176_4KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1)
276#define HDSP_Frequency192KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0)
277
278#define hdsp_encode_latency(x) (((x)<<1) & HDSP_LatencyMask)
279#define hdsp_decode_latency(x) (((x) & HDSP_LatencyMask)>>1)
280
281#define hdsp_encode_spdif_in(x) (((x)&0x3)<<14)
282#define hdsp_decode_spdif_in(x) (((x)>>14)&0x3)
283
284/* Status Register bits */
285
286#define HDSP_audioIRQPending (1<<0)
287#define HDSP_Lock2 (1<<1) /* this is for Digiface and H9652 */
288#define HDSP_spdifFrequency3 HDSP_Lock2 /* this is for H9632 only */
289#define HDSP_Lock1 (1<<2)
290#define HDSP_Lock0 (1<<3)
291#define HDSP_SPDIFSync (1<<4)
292#define HDSP_TimecodeLock (1<<5)
293#define HDSP_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
294#define HDSP_Sync2 (1<<16)
295#define HDSP_Sync1 (1<<17)
296#define HDSP_Sync0 (1<<18)
297#define HDSP_DoubleSpeedStatus (1<<19)
298#define HDSP_ConfigError (1<<20)
299#define HDSP_DllError (1<<21)
300#define HDSP_spdifFrequency0 (1<<22)
301#define HDSP_spdifFrequency1 (1<<23)
302#define HDSP_spdifFrequency2 (1<<24)
303#define HDSP_SPDIFErrorFlag (1<<25)
304#define HDSP_BufferID (1<<26)
305#define HDSP_TimecodeSync (1<<27)
306#define HDSP_AEBO (1<<28) /* H9632 specific Analog Extension Boards */
307#define HDSP_AEBI (1<<29) /* 0 = present, 1 = absent */
308#define HDSP_midi0IRQPending (1<<30)
309#define HDSP_midi1IRQPending (1<<31)
310
311#define HDSP_spdifFrequencyMask (HDSP_spdifFrequency0|HDSP_spdifFrequency1|HDSP_spdifFrequency2)
312
313#define HDSP_spdifFrequency32KHz (HDSP_spdifFrequency0)
314#define HDSP_spdifFrequency44_1KHz (HDSP_spdifFrequency1)
315#define HDSP_spdifFrequency48KHz (HDSP_spdifFrequency0|HDSP_spdifFrequency1)
316
317#define HDSP_spdifFrequency64KHz (HDSP_spdifFrequency2)
318#define HDSP_spdifFrequency88_2KHz (HDSP_spdifFrequency0|HDSP_spdifFrequency2)
319#define HDSP_spdifFrequency96KHz (HDSP_spdifFrequency2|HDSP_spdifFrequency1)
320
321/* This is for H9632 cards */
322#define HDSP_spdifFrequency128KHz HDSP_spdifFrequencyMask
323#define HDSP_spdifFrequency176_4KHz HDSP_spdifFrequency3
324#define HDSP_spdifFrequency192KHz (HDSP_spdifFrequency3|HDSP_spdifFrequency0)
325
326/* Status2 Register bits */
327
328#define HDSP_version0 (1<<0)
329#define HDSP_version1 (1<<1)
330#define HDSP_version2 (1<<2)
331#define HDSP_wc_lock (1<<3)
332#define HDSP_wc_sync (1<<4)
333#define HDSP_inp_freq0 (1<<5)
334#define HDSP_inp_freq1 (1<<6)
335#define HDSP_inp_freq2 (1<<7)
336#define HDSP_SelSyncRef0 (1<<8)
337#define HDSP_SelSyncRef1 (1<<9)
338#define HDSP_SelSyncRef2 (1<<10)
339
340#define HDSP_wc_valid (HDSP_wc_lock|HDSP_wc_sync)
341
342#define HDSP_systemFrequencyMask (HDSP_inp_freq0|HDSP_inp_freq1|HDSP_inp_freq2)
343#define HDSP_systemFrequency32 (HDSP_inp_freq0)
344#define HDSP_systemFrequency44_1 (HDSP_inp_freq1)
345#define HDSP_systemFrequency48 (HDSP_inp_freq0|HDSP_inp_freq1)
346#define HDSP_systemFrequency64 (HDSP_inp_freq2)
347#define HDSP_systemFrequency88_2 (HDSP_inp_freq0|HDSP_inp_freq2)
348#define HDSP_systemFrequency96 (HDSP_inp_freq1|HDSP_inp_freq2)
349/* FIXME : more values for 9632 cards ? */
350
351#define HDSP_SelSyncRefMask (HDSP_SelSyncRef0|HDSP_SelSyncRef1|HDSP_SelSyncRef2)
352#define HDSP_SelSyncRef_ADAT1 0
353#define HDSP_SelSyncRef_ADAT2 (HDSP_SelSyncRef0)
354#define HDSP_SelSyncRef_ADAT3 (HDSP_SelSyncRef1)
355#define HDSP_SelSyncRef_SPDIF (HDSP_SelSyncRef0|HDSP_SelSyncRef1)
356#define HDSP_SelSyncRef_WORD (HDSP_SelSyncRef2)
357#define HDSP_SelSyncRef_ADAT_SYNC (HDSP_SelSyncRef0|HDSP_SelSyncRef2)
358
359/* Card state flags */
360
361#define HDSP_InitializationComplete (1<<0)
362#define HDSP_FirmwareLoaded (1<<1)
363#define HDSP_FirmwareCached (1<<2)
364
365/* FIFO wait times, defined in terms of 1/10ths of msecs */
366
367#define HDSP_LONG_WAIT 5000
368#define HDSP_SHORT_WAIT 30
369
370#define UNITY_GAIN 32768
371#define MINUS_INFINITY_GAIN 0
372
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373/* the size of a substream (1 mono data stream) */
374
375#define HDSP_CHANNEL_BUFFER_SAMPLES (16*1024)
376#define HDSP_CHANNEL_BUFFER_BYTES (4*HDSP_CHANNEL_BUFFER_SAMPLES)
377
378/* the size of the area we need to allocate for DMA transfers. the
379 size is the same regardless of the number of channels - the
380 Multiface still uses the same memory area.
381
382 Note that we allocate 1 more channel than is apparently needed
383 because the h/w seems to write 1 byte beyond the end of the last
384 page. Sigh.
385*/
386
387#define HDSP_DMA_AREA_BYTES ((HDSP_MAX_CHANNELS+1) * HDSP_CHANNEL_BUFFER_BYTES)
388#define HDSP_DMA_AREA_KILOBYTES (HDSP_DMA_AREA_BYTES/1024)
389
390/* use hotplug firmeare loader? */
391#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
Takashi Iwai140432f2006-05-22 14:31:57 +0200392#if !defined(HDSP_USE_HWDEP_LOADER) && !defined(CONFIG_SND_HDSP)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393#define HDSP_FW_LOADER
394#endif
395#endif
396
Takashi Iwai55e957d2005-11-17 14:52:13 +0100397struct hdsp_9632_meters {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 u32 input_peak[16];
399 u32 playback_peak[16];
400 u32 output_peak[16];
401 u32 xxx_peak[16];
402 u32 padding[64];
403 u32 input_rms_low[16];
404 u32 playback_rms_low[16];
405 u32 output_rms_low[16];
406 u32 xxx_rms_low[16];
407 u32 input_rms_high[16];
408 u32 playback_rms_high[16];
409 u32 output_rms_high[16];
410 u32 xxx_rms_high[16];
411};
412
Takashi Iwai55e957d2005-11-17 14:52:13 +0100413struct hdsp_midi {
414 struct hdsp *hdsp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 int id;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100416 struct snd_rawmidi *rmidi;
417 struct snd_rawmidi_substream *input;
418 struct snd_rawmidi_substream *output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 char istimer; /* timer in use */
420 struct timer_list timer;
421 spinlock_t lock;
422 int pending;
423};
424
Takashi Iwai55e957d2005-11-17 14:52:13 +0100425struct hdsp {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 spinlock_t lock;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100427 struct snd_pcm_substream *capture_substream;
428 struct snd_pcm_substream *playback_substream;
429 struct hdsp_midi midi[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 struct tasklet_struct midi_tasklet;
431 int use_midi_tasklet;
432 int precise_ptr;
433 u32 control_register; /* cached value */
434 u32 control2_register; /* cached value */
435 u32 creg_spdif;
436 u32 creg_spdif_stream;
Takashi Iwaie3ea4d82005-07-04 18:12:39 +0200437 int clock_source_locked;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 char *card_name; /* digiface/multiface */
Takashi Iwai55e957d2005-11-17 14:52:13 +0100439 enum HDSP_IO_Type io_type; /* ditto, but for code use */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 unsigned short firmware_rev;
441 unsigned short state; /* stores state bits */
442 u32 firmware_cache[24413]; /* this helps recover from accidental iobox power failure */
443 size_t period_bytes; /* guess what this is */
444 unsigned char max_channels;
445 unsigned char qs_in_channels; /* quad speed mode for H9632 */
446 unsigned char ds_in_channels;
447 unsigned char ss_in_channels; /* different for multiface/digiface */
448 unsigned char qs_out_channels;
449 unsigned char ds_out_channels;
450 unsigned char ss_out_channels;
451
452 struct snd_dma_buffer capture_dma_buf;
453 struct snd_dma_buffer playback_dma_buf;
454 unsigned char *capture_buffer; /* suitably aligned address */
455 unsigned char *playback_buffer; /* suitably aligned address */
456
457 pid_t capture_pid;
458 pid_t playback_pid;
459 int running;
460 int system_sample_rate;
461 char *channel_map;
462 int dev;
463 int irq;
464 unsigned long port;
465 void __iomem *iobase;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100466 struct snd_card *card;
467 struct snd_pcm *pcm;
468 struct snd_hwdep *hwdep;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 struct pci_dev *pci;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100470 struct snd_kcontrol *spdif_ctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE];
472};
473
474/* These tables map the ALSA channels 1..N to the channels that we
475 need to use in order to find the relevant channel buffer. RME
476 refer to this kind of mapping as between "the ADAT channel and
477 the DMA channel." We index it using the logical audio channel,
478 and the value is the DMA channel (i.e. channel buffer number)
479 where the data for that channel can be read/written from/to.
480*/
481
482static char channel_map_df_ss[HDSP_MAX_CHANNELS] = {
483 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
484 18, 19, 20, 21, 22, 23, 24, 25
485};
486
487static char channel_map_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */
488 /* Analog */
489 0, 1, 2, 3, 4, 5, 6, 7,
490 /* ADAT 2 */
491 16, 17, 18, 19, 20, 21, 22, 23,
492 /* SPDIF */
493 24, 25,
494 -1, -1, -1, -1, -1, -1, -1, -1
495};
496
497static char channel_map_ds[HDSP_MAX_CHANNELS] = {
498 /* ADAT channels are remapped */
499 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23,
500 /* channels 12 and 13 are S/PDIF */
501 24, 25,
502 /* others don't exist */
503 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
504};
505
506static char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = {
507 /* ADAT channels */
508 0, 1, 2, 3, 4, 5, 6, 7,
509 /* SPDIF */
510 8, 9,
511 /* Analog */
512 10, 11,
513 /* AO4S-192 and AI4S-192 extension boards */
514 12, 13, 14, 15,
515 /* others don't exist */
516 -1, -1, -1, -1, -1, -1, -1, -1,
517 -1, -1
518};
519
520static char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = {
521 /* ADAT */
522 1, 3, 5, 7,
523 /* SPDIF */
524 8, 9,
525 /* Analog */
526 10, 11,
527 /* AO4S-192 and AI4S-192 extension boards */
528 12, 13, 14, 15,
529 /* others don't exist */
530 -1, -1, -1, -1, -1, -1, -1, -1,
531 -1, -1, -1, -1, -1, -1
532};
533
534static char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = {
535 /* ADAT is disabled in this mode */
536 /* SPDIF */
537 8, 9,
538 /* Analog */
539 10, 11,
540 /* AO4S-192 and AI4S-192 extension boards */
541 12, 13, 14, 15,
542 /* others don't exist */
543 -1, -1, -1, -1, -1, -1, -1, -1,
544 -1, -1, -1, -1, -1, -1, -1, -1,
545 -1, -1
546};
547
548static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
549{
550 dmab->dev.type = SNDRV_DMA_TYPE_DEV;
551 dmab->dev.dev = snd_dma_pci_data(pci);
Takashi Iwaib6a96912005-05-30 18:27:03 +0200552 if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
553 if (dmab->bytes >= size)
554 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 }
Takashi Iwaib6a96912005-05-30 18:27:03 +0200556 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
557 size, dmab) < 0)
558 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 return 0;
560}
561
562static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
563{
Takashi Iwaib6a96912005-05-30 18:27:03 +0200564 if (dmab->area) {
565 dmab->dev.dev = NULL; /* make it anonymous */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
Takashi Iwaib6a96912005-05-30 18:27:03 +0200567 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568}
569
570
Takashi Iwaif40b6892006-07-05 16:51:05 +0200571static struct pci_device_id snd_hdsp_ids[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 {
573 .vendor = PCI_VENDOR_ID_XILINX,
574 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP,
575 .subvendor = PCI_ANY_ID,
576 .subdevice = PCI_ANY_ID,
577 }, /* RME Hammerfall-DSP */
578 { 0, },
579};
580
581MODULE_DEVICE_TABLE(pci, snd_hdsp_ids);
582
583/* prototypes */
Takashi Iwai55e957d2005-11-17 14:52:13 +0100584static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp);
585static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp);
586static int snd_hdsp_enable_io (struct hdsp *hdsp);
587static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp);
588static void snd_hdsp_initialize_channels (struct hdsp *hdsp);
589static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout);
590static int hdsp_autosync_ref(struct hdsp *hdsp);
591static int snd_hdsp_set_defaults(struct hdsp *hdsp);
592static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593
Takashi Iwai55e957d2005-11-17 14:52:13 +0100594static int hdsp_playback_to_output_key (struct hdsp *hdsp, int in, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595{
596 switch (hdsp->firmware_rev) {
597 case 0xa:
598 return (64 * out) + (32 + (in));
599 case 0x96:
600 case 0x97:
Remy Bruno6add0f42006-10-09 15:52:01 +0200601 case 0x98:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 return (32 * out) + (16 + (in));
603 default:
604 return (52 * out) + (26 + (in));
605 }
606}
607
Takashi Iwai55e957d2005-11-17 14:52:13 +0100608static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609{
610 switch (hdsp->firmware_rev) {
611 case 0xa:
612 return (64 * out) + in;
613 case 0x96:
614 case 0x97:
Remy Bruno6add0f42006-10-09 15:52:01 +0200615 case 0x98:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 return (32 * out) + in;
617 default:
618 return (52 * out) + in;
619 }
620}
621
Takashi Iwai55e957d2005-11-17 14:52:13 +0100622static void hdsp_write(struct hdsp *hdsp, int reg, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623{
624 writel(val, hdsp->iobase + reg);
625}
626
Takashi Iwai55e957d2005-11-17 14:52:13 +0100627static unsigned int hdsp_read(struct hdsp *hdsp, int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628{
629 return readl (hdsp->iobase + reg);
630}
631
Takashi Iwai55e957d2005-11-17 14:52:13 +0100632static int hdsp_check_for_iobox (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633{
634
635 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
636 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_ConfigError) {
637 snd_printk ("Hammerfall-DSP: no Digiface or Multiface connected!\n");
638 hdsp->state &= ~HDSP_FirmwareLoaded;
639 return -EIO;
640 }
641 return 0;
642
643}
644
Takashi Iwai55e957d2005-11-17 14:52:13 +0100645static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
647 int i;
648 unsigned long flags;
649
650 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
651
652 snd_printk ("Hammerfall-DSP: loading firmware\n");
653
654 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM);
655 hdsp_write (hdsp, HDSP_fifoData, 0);
656
657 if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
658 snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n");
659 return -EIO;
660 }
661
662 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
663
664 for (i = 0; i < 24413; ++i) {
665 hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]);
666 if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) {
667 snd_printk ("Hammerfall-DSP: timeout during firmware loading\n");
668 return -EIO;
669 }
670 }
671
Takashi Iwaib0b98112005-10-20 18:29:58 +0200672 ssleep(3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673
674 if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
675 snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n");
676 return -EIO;
677 }
678
679#ifdef SNDRV_BIG_ENDIAN
680 hdsp->control2_register = HDSP_BIGENDIAN_MODE;
681#else
682 hdsp->control2_register = 0;
683#endif
684 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
685 snd_printk ("Hammerfall-DSP: finished firmware loading\n");
686
687 }
688 if (hdsp->state & HDSP_InitializationComplete) {
Takashi Iwaib0b98112005-10-20 18:29:58 +0200689 snd_printk(KERN_INFO "Hammerfall-DSP: firmware loaded from cache, restoring defaults\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 spin_lock_irqsave(&hdsp->lock, flags);
691 snd_hdsp_set_defaults(hdsp);
692 spin_unlock_irqrestore(&hdsp->lock, flags);
693 }
694
695 hdsp->state |= HDSP_FirmwareLoaded;
696
697 return 0;
698}
699
Takashi Iwai55e957d2005-11-17 14:52:13 +0100700static int hdsp_get_iobox_version (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701{
702 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
703
704 hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM);
705 hdsp_write (hdsp, HDSP_fifoData, 0);
Takashi Iwaib0b98112005-10-20 18:29:58 +0200706 if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
709 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
710 hdsp_write (hdsp, HDSP_fifoData, 0);
711
712 if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT)) {
713 hdsp->io_type = Multiface;
714 hdsp_write (hdsp, HDSP_control2Reg, HDSP_VERSION_BIT);
715 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
716 hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT);
717 } else {
718 hdsp->io_type = Digiface;
719 }
720 } else {
721 /* firmware was already loaded, get iobox type */
Takashi Iwaib0b98112005-10-20 18:29:58 +0200722 if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 hdsp->io_type = Multiface;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200724 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 hdsp->io_type = Digiface;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 }
727 return 0;
728}
729
730
Takashi Iwai311e70a2006-09-06 12:13:37 +0200731#ifdef HDSP_FW_LOADER
732static int __devinit hdsp_request_fw_loader(struct hdsp *hdsp);
733#endif
734
735static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736{
Takashi Iwai311e70a2006-09-06 12:13:37 +0200737 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
738 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 hdsp->state &= ~HDSP_FirmwareLoaded;
Takashi Iwai311e70a2006-09-06 12:13:37 +0200741 if (! load_on_demand)
Takashi Iwaib0b98112005-10-20 18:29:58 +0200742 return -EIO;
Takashi Iwai311e70a2006-09-06 12:13:37 +0200743 snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +0200744 /* try to load firmware */
Takashi Iwai311e70a2006-09-06 12:13:37 +0200745 if (! (hdsp->state & HDSP_FirmwareCached)) {
746#ifdef HDSP_FW_LOADER
747 if (! hdsp_request_fw_loader(hdsp))
748 return 0;
749#endif
750 snd_printk(KERN_ERR
751 "Hammerfall-DSP: No firmware loaded nor "
752 "cached, please upload firmware.\n");
753 return -EIO;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200754 }
Takashi Iwai311e70a2006-09-06 12:13:37 +0200755 if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
756 snd_printk(KERN_ERR
757 "Hammerfall-DSP: Firmware loading from "
758 "cache failed, please upload manually.\n");
759 return -EIO;
760 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 }
762 return 0;
763}
764
765
Takashi Iwai55e957d2005-11-17 14:52:13 +0100766static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767{
768 int i;
769
770 /* the fifoStatus registers reports on how many words
771 are available in the command FIFO.
772 */
773
774 for (i = 0; i < timeout; i++) {
775
776 if ((int)(hdsp_read (hdsp, HDSP_fifoStatus) & 0xff) <= count)
777 return 0;
778
779 /* not very friendly, but we only do this during a firmware
780 load and changing the mixer, so we just put up with it.
781 */
782
783 udelay (100);
784 }
785
786 snd_printk ("Hammerfall-DSP: wait for FIFO status <= %d failed after %d iterations\n",
787 count, timeout);
788 return -1;
789}
790
Takashi Iwai55e957d2005-11-17 14:52:13 +0100791static int hdsp_read_gain (struct hdsp *hdsp, unsigned int addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792{
Takashi Iwaib0b98112005-10-20 18:29:58 +0200793 if (addr >= HDSP_MATRIX_MIXER_SIZE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200795
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 return hdsp->mixer_matrix[addr];
797}
798
Takashi Iwai55e957d2005-11-17 14:52:13 +0100799static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800{
801 unsigned int ad;
802
803 if (addr >= HDSP_MATRIX_MIXER_SIZE)
804 return -1;
805
806 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) {
807
808 /* from martin bjornsen:
809
810 "You can only write dwords to the
811 mixer memory which contain two
812 mixer values in the low and high
813 word. So if you want to change
814 value 0 you have to read value 1
815 from the cache and write both to
816 the first dword in the mixer
817 memory."
818 */
819
Takashi Iwaib0b98112005-10-20 18:29:58 +0200820 if (hdsp->io_type == H9632 && addr >= 512)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822
Takashi Iwaib0b98112005-10-20 18:29:58 +0200823 if (hdsp->io_type == H9652 && addr >= 1352)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825
826 hdsp->mixer_matrix[addr] = data;
827
828
829 /* `addr' addresses a 16-bit wide address, but
830 the address space accessed via hdsp_write
831 uses byte offsets. put another way, addr
832 varies from 0 to 1351, but to access the
833 corresponding memory location, we need
834 to access 0 to 2703 ...
835 */
836 ad = addr/2;
837
838 hdsp_write (hdsp, 4096 + (ad*4),
839 (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) +
840 hdsp->mixer_matrix[addr&0x7fe]);
841
842 return 0;
843
844 } else {
845
846 ad = (addr << 16) + data;
847
Takashi Iwaib0b98112005-10-20 18:29:58 +0200848 if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850
851 hdsp_write (hdsp, HDSP_fifoData, ad);
852 hdsp->mixer_matrix[addr] = data;
853
854 }
855
856 return 0;
857}
858
Takashi Iwai55e957d2005-11-17 14:52:13 +0100859static int snd_hdsp_use_is_exclusive(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860{
861 unsigned long flags;
862 int ret = 1;
863
864 spin_lock_irqsave(&hdsp->lock, flags);
865 if ((hdsp->playback_pid != hdsp->capture_pid) &&
Takashi Iwaib0b98112005-10-20 18:29:58 +0200866 (hdsp->playback_pid >= 0) && (hdsp->capture_pid >= 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 spin_unlock_irqrestore(&hdsp->lock, flags);
869 return ret;
870}
871
Takashi Iwai55e957d2005-11-17 14:52:13 +0100872static int hdsp_external_sample_rate (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873{
874 unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
875 unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
876
877 switch (rate_bits) {
878 case HDSP_systemFrequency32: return 32000;
879 case HDSP_systemFrequency44_1: return 44100;
880 case HDSP_systemFrequency48: return 48000;
881 case HDSP_systemFrequency64: return 64000;
882 case HDSP_systemFrequency88_2: return 88200;
883 case HDSP_systemFrequency96: return 96000;
884 default:
885 return 0;
886 }
887}
888
Takashi Iwai55e957d2005-11-17 14:52:13 +0100889static int hdsp_spdif_sample_rate(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890{
891 unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);
892 unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);
893
Takashi Iwaib0b98112005-10-20 18:29:58 +0200894 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896
897 switch (rate_bits) {
898 case HDSP_spdifFrequency32KHz: return 32000;
899 case HDSP_spdifFrequency44_1KHz: return 44100;
900 case HDSP_spdifFrequency48KHz: return 48000;
901 case HDSP_spdifFrequency64KHz: return 64000;
902 case HDSP_spdifFrequency88_2KHz: return 88200;
903 case HDSP_spdifFrequency96KHz: return 96000;
904 case HDSP_spdifFrequency128KHz:
905 if (hdsp->io_type == H9632) return 128000;
906 break;
907 case HDSP_spdifFrequency176_4KHz:
908 if (hdsp->io_type == H9632) return 176400;
909 break;
910 case HDSP_spdifFrequency192KHz:
911 if (hdsp->io_type == H9632) return 192000;
912 break;
913 default:
914 break;
915 }
916 snd_printk ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status);
917 return 0;
918}
919
Takashi Iwai55e957d2005-11-17 14:52:13 +0100920static void hdsp_compute_period_size(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921{
922 hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));
923}
924
Takashi Iwai55e957d2005-11-17 14:52:13 +0100925static snd_pcm_uframes_t hdsp_hw_pointer(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926{
927 int position;
928
929 position = hdsp_read(hdsp, HDSP_statusRegister);
930
Takashi Iwaib0b98112005-10-20 18:29:58 +0200931 if (!hdsp->precise_ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 return (position & HDSP_BufferID) ? (hdsp->period_bytes / 4) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933
934 position &= HDSP_BufferPositionMask;
935 position /= 4;
936 position &= (hdsp->period_bytes/2) - 1;
937 return position;
938}
939
Takashi Iwai55e957d2005-11-17 14:52:13 +0100940static void hdsp_reset_hw_pointer(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941{
942 hdsp_write (hdsp, HDSP_resetPointer, 0);
943}
944
Takashi Iwai55e957d2005-11-17 14:52:13 +0100945static void hdsp_start_audio(struct hdsp *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946{
947 s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start);
948 hdsp_write(s, HDSP_controlRegister, s->control_register);
949}
950
Takashi Iwai55e957d2005-11-17 14:52:13 +0100951static void hdsp_stop_audio(struct hdsp *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952{
953 s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable);
954 hdsp_write(s, HDSP_controlRegister, s->control_register);
955}
956
Takashi Iwai55e957d2005-11-17 14:52:13 +0100957static void hdsp_silence_playback(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958{
959 memset(hdsp->playback_buffer, 0, HDSP_DMA_AREA_BYTES);
960}
961
Takashi Iwai55e957d2005-11-17 14:52:13 +0100962static int hdsp_set_interrupt_interval(struct hdsp *s, unsigned int frames)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963{
964 int n;
965
966 spin_lock_irq(&s->lock);
967
968 frames >>= 7;
969 n = 0;
970 while (frames) {
971 n++;
972 frames >>= 1;
973 }
974
975 s->control_register &= ~HDSP_LatencyMask;
976 s->control_register |= hdsp_encode_latency(n);
977
978 hdsp_write(s, HDSP_controlRegister, s->control_register);
979
980 hdsp_compute_period_size(s);
981
982 spin_unlock_irq(&s->lock);
983
984 return 0;
985}
986
Takashi Iwai55e957d2005-11-17 14:52:13 +0100987static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988{
989 int reject_if_open = 0;
990 int current_rate;
991 int rate_bits;
992
993 /* ASSUMPTION: hdsp->lock is either held, or
994 there is no need for it (e.g. during module
995 initialization).
996 */
997
998 if (!(hdsp->control_register & HDSP_ClockModeMaster)) {
999 if (called_internally) {
1000 /* request from ctl or card initialization */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001001 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 -07001002 return -1;
1003 } else {
1004 /* hw_param request while in AutoSync mode */
1005 int external_freq = hdsp_external_sample_rate(hdsp);
1006 int spdif_freq = hdsp_spdif_sample_rate(hdsp);
1007
Takashi Iwaib0b98112005-10-20 18:29:58 +02001008 if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1))
1009 snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in double speed mode\n");
1010 else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1))
1011 snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in quad speed mode\n");
1012 else if (rate != external_freq) {
1013 snd_printk(KERN_INFO "Hammerfall-DSP: No AutoSync source for requested rate\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 return -1;
1015 }
1016 }
1017 }
1018
1019 current_rate = hdsp->system_sample_rate;
1020
1021 /* Changing from a "single speed" to a "double speed" rate is
1022 not allowed if any substreams are open. This is because
1023 such a change causes a shift in the location of
1024 the DMA buffers and a reduction in the number of available
1025 buffers.
1026
1027 Note that a similar but essentially insoluble problem
1028 exists for externally-driven rate changes. All we can do
1029 is to flag rate changes in the read/write routines. */
1030
Takashi Iwaib0b98112005-10-20 18:29:58 +02001031 if (rate > 96000 && hdsp->io_type != H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033
1034 switch (rate) {
1035 case 32000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001036 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 rate_bits = HDSP_Frequency32KHz;
1039 break;
1040 case 44100:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001041 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 rate_bits = HDSP_Frequency44_1KHz;
1044 break;
1045 case 48000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001046 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 rate_bits = HDSP_Frequency48KHz;
1049 break;
1050 case 64000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001051 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 rate_bits = HDSP_Frequency64KHz;
1054 break;
1055 case 88200:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001056 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 rate_bits = HDSP_Frequency88_2KHz;
1059 break;
1060 case 96000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001061 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 rate_bits = HDSP_Frequency96KHz;
1064 break;
1065 case 128000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001066 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 rate_bits = HDSP_Frequency128KHz;
1069 break;
1070 case 176400:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001071 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 rate_bits = HDSP_Frequency176_4KHz;
1074 break;
1075 case 192000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001076 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 rate_bits = HDSP_Frequency192KHz;
1079 break;
1080 default:
1081 return -EINVAL;
1082 }
1083
1084 if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) {
1085 snd_printk ("Hammerfall-DSP: cannot change speed mode (capture PID = %d, playback PID = %d)\n",
1086 hdsp->capture_pid,
1087 hdsp->playback_pid);
1088 return -EBUSY;
1089 }
1090
1091 hdsp->control_register &= ~HDSP_FrequencyMask;
1092 hdsp->control_register |= rate_bits;
1093 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1094
1095 if (rate >= 128000) {
1096 hdsp->channel_map = channel_map_H9632_qs;
1097 } else if (rate > 48000) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001098 if (hdsp->io_type == H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 hdsp->channel_map = channel_map_H9632_ds;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001100 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 hdsp->channel_map = channel_map_ds;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 } else {
1103 switch (hdsp->io_type) {
1104 case Multiface:
1105 hdsp->channel_map = channel_map_mf_ss;
1106 break;
1107 case Digiface:
1108 case H9652:
1109 hdsp->channel_map = channel_map_df_ss;
1110 break;
1111 case H9632:
1112 hdsp->channel_map = channel_map_H9632_ss;
1113 break;
1114 default:
1115 /* should never happen */
1116 break;
1117 }
1118 }
1119
1120 hdsp->system_sample_rate = rate;
1121
1122 return 0;
1123}
1124
1125/*----------------------------------------------------------------------------
1126 MIDI
1127 ----------------------------------------------------------------------------*/
1128
Takashi Iwai55e957d2005-11-17 14:52:13 +01001129static unsigned char snd_hdsp_midi_read_byte (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130{
1131 /* the hardware already does the relevant bit-mask with 0xff */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001132 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 return hdsp_read(hdsp, HDSP_midiDataIn1);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001134 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 return hdsp_read(hdsp, HDSP_midiDataIn0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136}
1137
Takashi Iwai55e957d2005-11-17 14:52:13 +01001138static void snd_hdsp_midi_write_byte (struct hdsp *hdsp, int id, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139{
1140 /* the hardware already does the relevant bit-mask with 0xff */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001141 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 hdsp_write(hdsp, HDSP_midiDataOut1, val);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001143 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 hdsp_write(hdsp, HDSP_midiDataOut0, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145}
1146
Takashi Iwai55e957d2005-11-17 14:52:13 +01001147static int snd_hdsp_midi_input_available (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001149 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 return (hdsp_read(hdsp, HDSP_midiStatusIn1) & 0xff);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001151 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 return (hdsp_read(hdsp, HDSP_midiStatusIn0) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153}
1154
Takashi Iwai55e957d2005-11-17 14:52:13 +01001155static int snd_hdsp_midi_output_possible (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156{
1157 int fifo_bytes_used;
1158
Takashi Iwaib0b98112005-10-20 18:29:58 +02001159 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut1) & 0xff;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001161 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut0) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
Takashi Iwaib0b98112005-10-20 18:29:58 +02001164 if (fifo_bytes_used < 128)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 return 128 - fifo_bytes_used;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001166 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168}
1169
Takashi Iwai55e957d2005-11-17 14:52:13 +01001170static void snd_hdsp_flush_midi_input (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001172 while (snd_hdsp_midi_input_available (hdsp, id))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 snd_hdsp_midi_read_byte (hdsp, id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174}
1175
Takashi Iwai55e957d2005-11-17 14:52:13 +01001176static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177{
1178 unsigned long flags;
1179 int n_pending;
1180 int to_write;
1181 int i;
1182 unsigned char buf[128];
1183
1184 /* Output is not interrupt driven */
1185
1186 spin_lock_irqsave (&hmidi->lock, flags);
1187 if (hmidi->output) {
1188 if (!snd_rawmidi_transmit_empty (hmidi->output)) {
1189 if ((n_pending = snd_hdsp_midi_output_possible (hmidi->hdsp, hmidi->id)) > 0) {
1190 if (n_pending > (int)sizeof (buf))
1191 n_pending = sizeof (buf);
1192
1193 if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {
1194 for (i = 0; i < to_write; ++i)
1195 snd_hdsp_midi_write_byte (hmidi->hdsp, hmidi->id, buf[i]);
1196 }
1197 }
1198 }
1199 }
1200 spin_unlock_irqrestore (&hmidi->lock, flags);
1201 return 0;
1202}
1203
Takashi Iwai55e957d2005-11-17 14:52:13 +01001204static int snd_hdsp_midi_input_read (struct hdsp_midi *hmidi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205{
1206 unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
1207 unsigned long flags;
1208 int n_pending;
1209 int i;
1210
1211 spin_lock_irqsave (&hmidi->lock, flags);
1212 if ((n_pending = snd_hdsp_midi_input_available (hmidi->hdsp, hmidi->id)) > 0) {
1213 if (hmidi->input) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001214 if (n_pending > (int)sizeof (buf))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 n_pending = sizeof (buf);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001216 for (i = 0; i < n_pending; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 buf[i] = snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001218 if (n_pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 snd_rawmidi_receive (hmidi->input, buf, n_pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 } else {
1221 /* flush the MIDI input FIFO */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001222 while (--n_pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 }
1225 }
1226 hmidi->pending = 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001227 if (hmidi->id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 hmidi->hdsp->control_register |= HDSP_Midi1InterruptEnable;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001229 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 hmidi->hdsp->control_register |= HDSP_Midi0InterruptEnable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 hdsp_write(hmidi->hdsp, HDSP_controlRegister, hmidi->hdsp->control_register);
1232 spin_unlock_irqrestore (&hmidi->lock, flags);
1233 return snd_hdsp_midi_output_write (hmidi);
1234}
1235
Takashi Iwai55e957d2005-11-17 14:52:13 +01001236static void snd_hdsp_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001238 struct hdsp *hdsp;
1239 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 unsigned long flags;
1241 u32 ie;
1242
Takashi Iwai55e957d2005-11-17 14:52:13 +01001243 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 hdsp = hmidi->hdsp;
1245 ie = hmidi->id ? HDSP_Midi1InterruptEnable : HDSP_Midi0InterruptEnable;
1246 spin_lock_irqsave (&hdsp->lock, flags);
1247 if (up) {
1248 if (!(hdsp->control_register & ie)) {
1249 snd_hdsp_flush_midi_input (hdsp, hmidi->id);
1250 hdsp->control_register |= ie;
1251 }
1252 } else {
1253 hdsp->control_register &= ~ie;
1254 tasklet_kill(&hdsp->midi_tasklet);
1255 }
1256
1257 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1258 spin_unlock_irqrestore (&hdsp->lock, flags);
1259}
1260
1261static void snd_hdsp_midi_output_timer(unsigned long data)
1262{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001263 struct hdsp_midi *hmidi = (struct hdsp_midi *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 unsigned long flags;
1265
1266 snd_hdsp_midi_output_write(hmidi);
1267 spin_lock_irqsave (&hmidi->lock, flags);
1268
1269 /* this does not bump hmidi->istimer, because the
1270 kernel automatically removed the timer when it
1271 expired, and we are now adding it back, thus
1272 leaving istimer wherever it was set before.
1273 */
1274
1275 if (hmidi->istimer) {
1276 hmidi->timer.expires = 1 + jiffies;
1277 add_timer(&hmidi->timer);
1278 }
1279
1280 spin_unlock_irqrestore (&hmidi->lock, flags);
1281}
1282
Takashi Iwai55e957d2005-11-17 14:52:13 +01001283static void snd_hdsp_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001285 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 unsigned long flags;
1287
Takashi Iwai55e957d2005-11-17 14:52:13 +01001288 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 spin_lock_irqsave (&hmidi->lock, flags);
1290 if (up) {
1291 if (!hmidi->istimer) {
1292 init_timer(&hmidi->timer);
1293 hmidi->timer.function = snd_hdsp_midi_output_timer;
1294 hmidi->timer.data = (unsigned long) hmidi;
1295 hmidi->timer.expires = 1 + jiffies;
1296 add_timer(&hmidi->timer);
1297 hmidi->istimer++;
1298 }
1299 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001300 if (hmidi->istimer && --hmidi->istimer <= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 del_timer (&hmidi->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 }
1303 spin_unlock_irqrestore (&hmidi->lock, flags);
1304 if (up)
1305 snd_hdsp_midi_output_write(hmidi);
1306}
1307
Takashi Iwai55e957d2005-11-17 14:52:13 +01001308static int snd_hdsp_midi_input_open(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001310 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
Takashi Iwai55e957d2005-11-17 14:52:13 +01001312 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 spin_lock_irq (&hmidi->lock);
1314 snd_hdsp_flush_midi_input (hmidi->hdsp, hmidi->id);
1315 hmidi->input = substream;
1316 spin_unlock_irq (&hmidi->lock);
1317
1318 return 0;
1319}
1320
Takashi Iwai55e957d2005-11-17 14:52:13 +01001321static int snd_hdsp_midi_output_open(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001323 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324
Takashi Iwai55e957d2005-11-17 14:52:13 +01001325 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 spin_lock_irq (&hmidi->lock);
1327 hmidi->output = substream;
1328 spin_unlock_irq (&hmidi->lock);
1329
1330 return 0;
1331}
1332
Takashi Iwai55e957d2005-11-17 14:52:13 +01001333static int snd_hdsp_midi_input_close(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001335 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
1337 snd_hdsp_midi_input_trigger (substream, 0);
1338
Takashi Iwai55e957d2005-11-17 14:52:13 +01001339 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 spin_lock_irq (&hmidi->lock);
1341 hmidi->input = NULL;
1342 spin_unlock_irq (&hmidi->lock);
1343
1344 return 0;
1345}
1346
Takashi Iwai55e957d2005-11-17 14:52:13 +01001347static int snd_hdsp_midi_output_close(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001349 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350
1351 snd_hdsp_midi_output_trigger (substream, 0);
1352
Takashi Iwai55e957d2005-11-17 14:52:13 +01001353 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 spin_lock_irq (&hmidi->lock);
1355 hmidi->output = NULL;
1356 spin_unlock_irq (&hmidi->lock);
1357
1358 return 0;
1359}
1360
Takashi Iwai55e957d2005-11-17 14:52:13 +01001361static struct snd_rawmidi_ops snd_hdsp_midi_output =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362{
1363 .open = snd_hdsp_midi_output_open,
1364 .close = snd_hdsp_midi_output_close,
1365 .trigger = snd_hdsp_midi_output_trigger,
1366};
1367
Takashi Iwai55e957d2005-11-17 14:52:13 +01001368static struct snd_rawmidi_ops snd_hdsp_midi_input =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369{
1370 .open = snd_hdsp_midi_input_open,
1371 .close = snd_hdsp_midi_input_close,
1372 .trigger = snd_hdsp_midi_input_trigger,
1373};
1374
Takashi Iwaif40b6892006-07-05 16:51:05 +02001375static int snd_hdsp_create_midi (struct snd_card *card, struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376{
1377 char buf[32];
1378
1379 hdsp->midi[id].id = id;
1380 hdsp->midi[id].rmidi = NULL;
1381 hdsp->midi[id].input = NULL;
1382 hdsp->midi[id].output = NULL;
1383 hdsp->midi[id].hdsp = hdsp;
1384 hdsp->midi[id].istimer = 0;
1385 hdsp->midi[id].pending = 0;
1386 spin_lock_init (&hdsp->midi[id].lock);
1387
1388 sprintf (buf, "%s MIDI %d", card->shortname, id+1);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001389 if (snd_rawmidi_new (card, buf, id, 1, 1, &hdsp->midi[id].rmidi) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
1392 sprintf (hdsp->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);
1393 hdsp->midi[id].rmidi->private_data = &hdsp->midi[id];
1394
1395 snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdsp_midi_output);
1396 snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdsp_midi_input);
1397
1398 hdsp->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
1399 SNDRV_RAWMIDI_INFO_INPUT |
1400 SNDRV_RAWMIDI_INFO_DUPLEX;
1401
1402 return 0;
1403}
1404
1405/*-----------------------------------------------------------------------------
1406 Control Interface
1407 ----------------------------------------------------------------------------*/
1408
Takashi Iwai55e957d2005-11-17 14:52:13 +01001409static u32 snd_hdsp_convert_from_aes(struct snd_aes_iec958 *aes)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410{
1411 u32 val = 0;
1412 val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? HDSP_SPDIFProfessional : 0;
1413 val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? HDSP_SPDIFNonAudio : 0;
1414 if (val & HDSP_SPDIFProfessional)
1415 val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0;
1416 else
1417 val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0;
1418 return val;
1419}
1420
Takashi Iwai55e957d2005-11-17 14:52:13 +01001421static void snd_hdsp_convert_to_aes(struct snd_aes_iec958 *aes, u32 val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422{
1423 aes->status[0] = ((val & HDSP_SPDIFProfessional) ? IEC958_AES0_PROFESSIONAL : 0) |
1424 ((val & HDSP_SPDIFNonAudio) ? IEC958_AES0_NONAUDIO : 0);
1425 if (val & HDSP_SPDIFProfessional)
1426 aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0;
1427 else
1428 aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_CON_EMPHASIS_5015 : 0;
1429}
1430
Takashi Iwai55e957d2005-11-17 14:52:13 +01001431static int snd_hdsp_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432{
1433 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1434 uinfo->count = 1;
1435 return 0;
1436}
1437
Takashi Iwai55e957d2005-11-17 14:52:13 +01001438static int snd_hdsp_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001440 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441
1442 snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif);
1443 return 0;
1444}
1445
Takashi Iwai55e957d2005-11-17 14:52:13 +01001446static int snd_hdsp_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001448 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 int change;
1450 u32 val;
1451
1452 val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
1453 spin_lock_irq(&hdsp->lock);
1454 change = val != hdsp->creg_spdif;
1455 hdsp->creg_spdif = val;
1456 spin_unlock_irq(&hdsp->lock);
1457 return change;
1458}
1459
Takashi Iwai55e957d2005-11-17 14:52:13 +01001460static int snd_hdsp_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461{
1462 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1463 uinfo->count = 1;
1464 return 0;
1465}
1466
Takashi Iwai55e957d2005-11-17 14:52:13 +01001467static int snd_hdsp_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001469 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
1471 snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream);
1472 return 0;
1473}
1474
Takashi Iwai55e957d2005-11-17 14:52:13 +01001475static int snd_hdsp_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001477 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 int change;
1479 u32 val;
1480
1481 val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
1482 spin_lock_irq(&hdsp->lock);
1483 change = val != hdsp->creg_spdif_stream;
1484 hdsp->creg_spdif_stream = val;
1485 hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
1486 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= val);
1487 spin_unlock_irq(&hdsp->lock);
1488 return change;
1489}
1490
Takashi Iwai55e957d2005-11-17 14:52:13 +01001491static int snd_hdsp_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492{
1493 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1494 uinfo->count = 1;
1495 return 0;
1496}
1497
Takashi Iwai55e957d2005-11-17 14:52:13 +01001498static int snd_hdsp_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499{
1500 ucontrol->value.iec958.status[0] = kcontrol->private_value;
1501 return 0;
1502}
1503
1504#define HDSP_SPDIF_IN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001505{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 .name = xname, \
1507 .index = xindex, \
1508 .info = snd_hdsp_info_spdif_in, \
1509 .get = snd_hdsp_get_spdif_in, \
1510 .put = snd_hdsp_put_spdif_in }
1511
Takashi Iwai55e957d2005-11-17 14:52:13 +01001512static unsigned int hdsp_spdif_in(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513{
1514 return hdsp_decode_spdif_in(hdsp->control_register & HDSP_SPDIFInputMask);
1515}
1516
Takashi Iwai55e957d2005-11-17 14:52:13 +01001517static int hdsp_set_spdif_input(struct hdsp *hdsp, int in)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518{
1519 hdsp->control_register &= ~HDSP_SPDIFInputMask;
1520 hdsp->control_register |= hdsp_encode_spdif_in(in);
1521 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1522 return 0;
1523}
1524
Takashi Iwai55e957d2005-11-17 14:52:13 +01001525static int snd_hdsp_info_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526{
1527 static char *texts[4] = {"Optical", "Coaxial", "Internal", "AES"};
Takashi Iwai55e957d2005-11-17 14:52:13 +01001528 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529
1530 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1531 uinfo->count = 1;
1532 uinfo->value.enumerated.items = ((hdsp->io_type == H9632) ? 4 : 3);
1533 if (uinfo->value.enumerated.item > ((hdsp->io_type == H9632) ? 3 : 2))
1534 uinfo->value.enumerated.item = ((hdsp->io_type == H9632) ? 3 : 2);
1535 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1536 return 0;
1537}
1538
Takashi Iwai55e957d2005-11-17 14:52:13 +01001539static int snd_hdsp_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001541 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542
1543 ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp);
1544 return 0;
1545}
1546
Takashi Iwai55e957d2005-11-17 14:52:13 +01001547static int snd_hdsp_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001549 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 int change;
1551 unsigned int val;
1552
1553 if (!snd_hdsp_use_is_exclusive(hdsp))
1554 return -EBUSY;
1555 val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3);
1556 spin_lock_irq(&hdsp->lock);
1557 change = val != hdsp_spdif_in(hdsp);
1558 if (change)
1559 hdsp_set_spdif_input(hdsp, val);
1560 spin_unlock_irq(&hdsp->lock);
1561 return change;
1562}
1563
1564#define HDSP_SPDIF_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001565{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 .info = snd_hdsp_info_spdif_bits, \
1567 .get = snd_hdsp_get_spdif_out, .put = snd_hdsp_put_spdif_out }
1568
Takashi Iwai55e957d2005-11-17 14:52:13 +01001569static int hdsp_spdif_out(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570{
1571 return (hdsp->control_register & HDSP_SPDIFOpticalOut) ? 1 : 0;
1572}
1573
Takashi Iwai55e957d2005-11-17 14:52:13 +01001574static int hdsp_set_spdif_output(struct hdsp *hdsp, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001576 if (out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 hdsp->control_register |= HDSP_SPDIFOpticalOut;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001578 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 hdsp->control_register &= ~HDSP_SPDIFOpticalOut;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1581 return 0;
1582}
1583
Takashi Iwai55e957d2005-11-17 14:52:13 +01001584static int snd_hdsp_info_spdif_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585{
1586 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1587 uinfo->count = 1;
1588 uinfo->value.integer.min = 0;
1589 uinfo->value.integer.max = 1;
1590 return 0;
1591}
1592
Takashi Iwai55e957d2005-11-17 14:52:13 +01001593static int snd_hdsp_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001595 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596
1597 ucontrol->value.integer.value[0] = hdsp_spdif_out(hdsp);
1598 return 0;
1599}
1600
Takashi Iwai55e957d2005-11-17 14:52:13 +01001601static int snd_hdsp_put_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001603 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 int change;
1605 unsigned int val;
1606
1607 if (!snd_hdsp_use_is_exclusive(hdsp))
1608 return -EBUSY;
1609 val = ucontrol->value.integer.value[0] & 1;
1610 spin_lock_irq(&hdsp->lock);
1611 change = (int)val != hdsp_spdif_out(hdsp);
1612 hdsp_set_spdif_output(hdsp, val);
1613 spin_unlock_irq(&hdsp->lock);
1614 return change;
1615}
1616
1617#define HDSP_SPDIF_PROFESSIONAL(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001618{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 .info = snd_hdsp_info_spdif_bits, \
1620 .get = snd_hdsp_get_spdif_professional, .put = snd_hdsp_put_spdif_professional }
1621
Takashi Iwai55e957d2005-11-17 14:52:13 +01001622static int hdsp_spdif_professional(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623{
1624 return (hdsp->control_register & HDSP_SPDIFProfessional) ? 1 : 0;
1625}
1626
Takashi Iwai55e957d2005-11-17 14:52:13 +01001627static int hdsp_set_spdif_professional(struct hdsp *hdsp, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001629 if (val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 hdsp->control_register |= HDSP_SPDIFProfessional;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001631 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 hdsp->control_register &= ~HDSP_SPDIFProfessional;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1634 return 0;
1635}
1636
Takashi Iwai55e957d2005-11-17 14:52:13 +01001637static int snd_hdsp_get_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001639 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640
1641 ucontrol->value.integer.value[0] = hdsp_spdif_professional(hdsp);
1642 return 0;
1643}
1644
Takashi Iwai55e957d2005-11-17 14:52:13 +01001645static int snd_hdsp_put_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001647 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 int change;
1649 unsigned int val;
1650
1651 if (!snd_hdsp_use_is_exclusive(hdsp))
1652 return -EBUSY;
1653 val = ucontrol->value.integer.value[0] & 1;
1654 spin_lock_irq(&hdsp->lock);
1655 change = (int)val != hdsp_spdif_professional(hdsp);
1656 hdsp_set_spdif_professional(hdsp, val);
1657 spin_unlock_irq(&hdsp->lock);
1658 return change;
1659}
1660
1661#define HDSP_SPDIF_EMPHASIS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001662{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 .info = snd_hdsp_info_spdif_bits, \
1664 .get = snd_hdsp_get_spdif_emphasis, .put = snd_hdsp_put_spdif_emphasis }
1665
Takashi Iwai55e957d2005-11-17 14:52:13 +01001666static int hdsp_spdif_emphasis(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667{
1668 return (hdsp->control_register & HDSP_SPDIFEmphasis) ? 1 : 0;
1669}
1670
Takashi Iwai55e957d2005-11-17 14:52:13 +01001671static int hdsp_set_spdif_emphasis(struct hdsp *hdsp, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001673 if (val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 hdsp->control_register |= HDSP_SPDIFEmphasis;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001675 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 hdsp->control_register &= ~HDSP_SPDIFEmphasis;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1678 return 0;
1679}
1680
Takashi Iwai55e957d2005-11-17 14:52:13 +01001681static int snd_hdsp_get_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001683 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684
1685 ucontrol->value.integer.value[0] = hdsp_spdif_emphasis(hdsp);
1686 return 0;
1687}
1688
Takashi Iwai55e957d2005-11-17 14:52:13 +01001689static int snd_hdsp_put_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001691 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 int change;
1693 unsigned int val;
1694
1695 if (!snd_hdsp_use_is_exclusive(hdsp))
1696 return -EBUSY;
1697 val = ucontrol->value.integer.value[0] & 1;
1698 spin_lock_irq(&hdsp->lock);
1699 change = (int)val != hdsp_spdif_emphasis(hdsp);
1700 hdsp_set_spdif_emphasis(hdsp, val);
1701 spin_unlock_irq(&hdsp->lock);
1702 return change;
1703}
1704
1705#define HDSP_SPDIF_NON_AUDIO(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001706{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 .info = snd_hdsp_info_spdif_bits, \
1708 .get = snd_hdsp_get_spdif_nonaudio, .put = snd_hdsp_put_spdif_nonaudio }
1709
Takashi Iwai55e957d2005-11-17 14:52:13 +01001710static int hdsp_spdif_nonaudio(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711{
1712 return (hdsp->control_register & HDSP_SPDIFNonAudio) ? 1 : 0;
1713}
1714
Takashi Iwai55e957d2005-11-17 14:52:13 +01001715static int hdsp_set_spdif_nonaudio(struct hdsp *hdsp, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001717 if (val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 hdsp->control_register |= HDSP_SPDIFNonAudio;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001719 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 hdsp->control_register &= ~HDSP_SPDIFNonAudio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1722 return 0;
1723}
1724
Takashi Iwai55e957d2005-11-17 14:52:13 +01001725static int snd_hdsp_get_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001727 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728
1729 ucontrol->value.integer.value[0] = hdsp_spdif_nonaudio(hdsp);
1730 return 0;
1731}
1732
Takashi Iwai55e957d2005-11-17 14:52:13 +01001733static int snd_hdsp_put_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001735 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 int change;
1737 unsigned int val;
1738
1739 if (!snd_hdsp_use_is_exclusive(hdsp))
1740 return -EBUSY;
1741 val = ucontrol->value.integer.value[0] & 1;
1742 spin_lock_irq(&hdsp->lock);
1743 change = (int)val != hdsp_spdif_nonaudio(hdsp);
1744 hdsp_set_spdif_nonaudio(hdsp, val);
1745 spin_unlock_irq(&hdsp->lock);
1746 return change;
1747}
1748
1749#define HDSP_SPDIF_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001750{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 .name = xname, \
1752 .index = xindex, \
1753 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1754 .info = snd_hdsp_info_spdif_sample_rate, \
1755 .get = snd_hdsp_get_spdif_sample_rate \
1756}
1757
Takashi Iwai55e957d2005-11-17 14:52:13 +01001758static int snd_hdsp_info_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759{
1760 static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
Takashi Iwai55e957d2005-11-17 14:52:13 +01001761 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762
1763 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1764 uinfo->count = 1;
1765 uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7;
1766 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1767 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1768 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1769 return 0;
1770}
1771
Takashi Iwai55e957d2005-11-17 14:52:13 +01001772static int snd_hdsp_get_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001774 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775
1776 switch (hdsp_spdif_sample_rate(hdsp)) {
1777 case 32000:
1778 ucontrol->value.enumerated.item[0] = 0;
1779 break;
1780 case 44100:
1781 ucontrol->value.enumerated.item[0] = 1;
1782 break;
1783 case 48000:
1784 ucontrol->value.enumerated.item[0] = 2;
1785 break;
1786 case 64000:
1787 ucontrol->value.enumerated.item[0] = 3;
1788 break;
1789 case 88200:
1790 ucontrol->value.enumerated.item[0] = 4;
1791 break;
1792 case 96000:
1793 ucontrol->value.enumerated.item[0] = 5;
1794 break;
1795 case 128000:
1796 ucontrol->value.enumerated.item[0] = 7;
1797 break;
1798 case 176400:
1799 ucontrol->value.enumerated.item[0] = 8;
1800 break;
1801 case 192000:
1802 ucontrol->value.enumerated.item[0] = 9;
1803 break;
1804 default:
1805 ucontrol->value.enumerated.item[0] = 6;
1806 }
1807 return 0;
1808}
1809
1810#define HDSP_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001811{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 .name = xname, \
1813 .index = xindex, \
1814 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1815 .info = snd_hdsp_info_system_sample_rate, \
1816 .get = snd_hdsp_get_system_sample_rate \
1817}
1818
Takashi Iwai55e957d2005-11-17 14:52:13 +01001819static int snd_hdsp_info_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820{
1821 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1822 uinfo->count = 1;
1823 return 0;
1824}
1825
Takashi Iwai55e957d2005-11-17 14:52:13 +01001826static int snd_hdsp_get_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001828 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829
1830 ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate;
1831 return 0;
1832}
1833
1834#define HDSP_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001835{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 .name = xname, \
1837 .index = xindex, \
1838 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1839 .info = snd_hdsp_info_autosync_sample_rate, \
1840 .get = snd_hdsp_get_autosync_sample_rate \
1841}
1842
Takashi Iwai55e957d2005-11-17 14:52:13 +01001843static int snd_hdsp_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001845 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
1847 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1848 uinfo->count = 1;
1849 uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7 ;
1850 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1851 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1852 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1853 return 0;
1854}
1855
Takashi Iwai55e957d2005-11-17 14:52:13 +01001856static int snd_hdsp_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001858 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859
1860 switch (hdsp_external_sample_rate(hdsp)) {
1861 case 32000:
1862 ucontrol->value.enumerated.item[0] = 0;
1863 break;
1864 case 44100:
1865 ucontrol->value.enumerated.item[0] = 1;
1866 break;
1867 case 48000:
1868 ucontrol->value.enumerated.item[0] = 2;
1869 break;
1870 case 64000:
1871 ucontrol->value.enumerated.item[0] = 3;
1872 break;
1873 case 88200:
1874 ucontrol->value.enumerated.item[0] = 4;
1875 break;
1876 case 96000:
1877 ucontrol->value.enumerated.item[0] = 5;
1878 break;
1879 case 128000:
1880 ucontrol->value.enumerated.item[0] = 7;
1881 break;
1882 case 176400:
1883 ucontrol->value.enumerated.item[0] = 8;
1884 break;
1885 case 192000:
1886 ucontrol->value.enumerated.item[0] = 9;
1887 break;
1888 default:
1889 ucontrol->value.enumerated.item[0] = 6;
1890 }
1891 return 0;
1892}
1893
1894#define HDSP_SYSTEM_CLOCK_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001895{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 .name = xname, \
1897 .index = xindex, \
1898 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1899 .info = snd_hdsp_info_system_clock_mode, \
1900 .get = snd_hdsp_get_system_clock_mode \
1901}
1902
Takashi Iwai55e957d2005-11-17 14:52:13 +01001903static int hdsp_system_clock_mode(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001905 if (hdsp->control_register & HDSP_ClockModeMaster)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001907 else if (hdsp_external_sample_rate(hdsp) != hdsp->system_sample_rate)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 return 1;
1910}
1911
Takashi Iwai55e957d2005-11-17 14:52:13 +01001912static int snd_hdsp_info_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913{
1914 static char *texts[] = {"Master", "Slave" };
1915
1916 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1917 uinfo->count = 1;
1918 uinfo->value.enumerated.items = 2;
1919 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1920 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1921 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1922 return 0;
1923}
1924
Takashi Iwai55e957d2005-11-17 14:52:13 +01001925static int snd_hdsp_get_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001927 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928
1929 ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp);
1930 return 0;
1931}
1932
1933#define HDSP_CLOCK_SOURCE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001934{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 .name = xname, \
1936 .index = xindex, \
1937 .info = snd_hdsp_info_clock_source, \
1938 .get = snd_hdsp_get_clock_source, \
1939 .put = snd_hdsp_put_clock_source \
1940}
1941
Takashi Iwai55e957d2005-11-17 14:52:13 +01001942static int hdsp_clock_source(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943{
1944 if (hdsp->control_register & HDSP_ClockModeMaster) {
1945 switch (hdsp->system_sample_rate) {
1946 case 32000:
1947 return 1;
1948 case 44100:
1949 return 2;
1950 case 48000:
1951 return 3;
1952 case 64000:
1953 return 4;
1954 case 88200:
1955 return 5;
1956 case 96000:
1957 return 6;
1958 case 128000:
1959 return 7;
1960 case 176400:
1961 return 8;
1962 case 192000:
1963 return 9;
1964 default:
1965 return 3;
1966 }
1967 } else {
1968 return 0;
1969 }
1970}
1971
Takashi Iwai55e957d2005-11-17 14:52:13 +01001972static int hdsp_set_clock_source(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973{
1974 int rate;
1975 switch (mode) {
1976 case HDSP_CLOCK_SOURCE_AUTOSYNC:
1977 if (hdsp_external_sample_rate(hdsp) != 0) {
1978 if (!hdsp_set_rate(hdsp, hdsp_external_sample_rate(hdsp), 1)) {
1979 hdsp->control_register &= ~HDSP_ClockModeMaster;
1980 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1981 return 0;
1982 }
1983 }
1984 return -1;
1985 case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ:
1986 rate = 32000;
1987 break;
1988 case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ:
1989 rate = 44100;
1990 break;
1991 case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ:
1992 rate = 48000;
1993 break;
1994 case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ:
1995 rate = 64000;
1996 break;
1997 case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ:
1998 rate = 88200;
1999 break;
2000 case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ:
2001 rate = 96000;
2002 break;
2003 case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ:
2004 rate = 128000;
2005 break;
2006 case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ:
2007 rate = 176400;
2008 break;
2009 case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ:
2010 rate = 192000;
2011 break;
2012 default:
2013 rate = 48000;
2014 }
2015 hdsp->control_register |= HDSP_ClockModeMaster;
2016 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2017 hdsp_set_rate(hdsp, rate, 1);
2018 return 0;
2019}
2020
Takashi Iwai55e957d2005-11-17 14:52:13 +01002021static int snd_hdsp_info_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022{
2023 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 +01002024 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025
2026 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2027 uinfo->count = 1;
2028 if (hdsp->io_type == H9632)
2029 uinfo->value.enumerated.items = 10;
2030 else
2031 uinfo->value.enumerated.items = 7;
2032 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2033 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2034 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2035 return 0;
2036}
2037
Takashi Iwai55e957d2005-11-17 14:52:13 +01002038static int snd_hdsp_get_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002040 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041
2042 ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp);
2043 return 0;
2044}
2045
Takashi Iwai55e957d2005-11-17 14:52:13 +01002046static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002048 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049 int change;
2050 int val;
2051
2052 if (!snd_hdsp_use_is_exclusive(hdsp))
2053 return -EBUSY;
2054 val = ucontrol->value.enumerated.item[0];
2055 if (val < 0) val = 0;
2056 if (hdsp->io_type == H9632) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002057 if (val > 9)
2058 val = 9;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002060 if (val > 6)
2061 val = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 }
2063 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002064 if (val != hdsp_clock_source(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 change = (hdsp_set_clock_source(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002066 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 spin_unlock_irq(&hdsp->lock);
2069 return change;
2070}
2071
Takashi Iwai55e957d2005-11-17 14:52:13 +01002072static int snd_hdsp_info_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002073{
2074 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2075 uinfo->count = 1;
2076 uinfo->value.integer.min = 0;
2077 uinfo->value.integer.max = 1;
2078 return 0;
2079}
2080
Takashi Iwai55e957d2005-11-17 14:52:13 +01002081static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002082{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002083 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002084
2085 ucontrol->value.integer.value[0] = hdsp->clock_source_locked;
2086 return 0;
2087}
2088
Takashi Iwai55e957d2005-11-17 14:52:13 +01002089static int snd_hdsp_put_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002090{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002091 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002092 int change;
2093
2094 change = (int)ucontrol->value.integer.value[0] != hdsp->clock_source_locked;
2095 if (change)
2096 hdsp->clock_source_locked = ucontrol->value.integer.value[0];
2097 return change;
2098}
2099
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100#define HDSP_DA_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002101{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 .name = xname, \
2103 .index = xindex, \
2104 .info = snd_hdsp_info_da_gain, \
2105 .get = snd_hdsp_get_da_gain, \
2106 .put = snd_hdsp_put_da_gain \
2107}
2108
Takashi Iwai55e957d2005-11-17 14:52:13 +01002109static int hdsp_da_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110{
2111 switch (hdsp->control_register & HDSP_DAGainMask) {
2112 case HDSP_DAGainHighGain:
2113 return 0;
2114 case HDSP_DAGainPlus4dBu:
2115 return 1;
2116 case HDSP_DAGainMinus10dBV:
2117 return 2;
2118 default:
2119 return 1;
2120 }
2121}
2122
Takashi Iwai55e957d2005-11-17 14:52:13 +01002123static int hdsp_set_da_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124{
2125 hdsp->control_register &= ~HDSP_DAGainMask;
2126 switch (mode) {
2127 case 0:
2128 hdsp->control_register |= HDSP_DAGainHighGain;
2129 break;
2130 case 1:
2131 hdsp->control_register |= HDSP_DAGainPlus4dBu;
2132 break;
2133 case 2:
2134 hdsp->control_register |= HDSP_DAGainMinus10dBV;
2135 break;
2136 default:
2137 return -1;
2138
2139 }
2140 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2141 return 0;
2142}
2143
Takashi Iwai55e957d2005-11-17 14:52:13 +01002144static int snd_hdsp_info_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145{
2146 static char *texts[] = {"Hi Gain", "+4 dBu", "-10 dbV"};
2147
2148 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2149 uinfo->count = 1;
2150 uinfo->value.enumerated.items = 3;
2151 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2152 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2153 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2154 return 0;
2155}
2156
Takashi Iwai55e957d2005-11-17 14:52:13 +01002157static int snd_hdsp_get_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002159 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160
2161 ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp);
2162 return 0;
2163}
2164
Takashi Iwai55e957d2005-11-17 14:52:13 +01002165static int snd_hdsp_put_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002167 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 int change;
2169 int val;
2170
2171 if (!snd_hdsp_use_is_exclusive(hdsp))
2172 return -EBUSY;
2173 val = ucontrol->value.enumerated.item[0];
2174 if (val < 0) val = 0;
2175 if (val > 2) val = 2;
2176 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002177 if (val != hdsp_da_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 change = (hdsp_set_da_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002179 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 spin_unlock_irq(&hdsp->lock);
2182 return change;
2183}
2184
2185#define HDSP_AD_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002186{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 .name = xname, \
2188 .index = xindex, \
2189 .info = snd_hdsp_info_ad_gain, \
2190 .get = snd_hdsp_get_ad_gain, \
2191 .put = snd_hdsp_put_ad_gain \
2192}
2193
Takashi Iwai55e957d2005-11-17 14:52:13 +01002194static int hdsp_ad_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195{
2196 switch (hdsp->control_register & HDSP_ADGainMask) {
2197 case HDSP_ADGainMinus10dBV:
2198 return 0;
2199 case HDSP_ADGainPlus4dBu:
2200 return 1;
2201 case HDSP_ADGainLowGain:
2202 return 2;
2203 default:
2204 return 1;
2205 }
2206}
2207
Takashi Iwai55e957d2005-11-17 14:52:13 +01002208static int hdsp_set_ad_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209{
2210 hdsp->control_register &= ~HDSP_ADGainMask;
2211 switch (mode) {
2212 case 0:
2213 hdsp->control_register |= HDSP_ADGainMinus10dBV;
2214 break;
2215 case 1:
2216 hdsp->control_register |= HDSP_ADGainPlus4dBu;
2217 break;
2218 case 2:
2219 hdsp->control_register |= HDSP_ADGainLowGain;
2220 break;
2221 default:
2222 return -1;
2223
2224 }
2225 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2226 return 0;
2227}
2228
Takashi Iwai55e957d2005-11-17 14:52:13 +01002229static int snd_hdsp_info_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230{
2231 static char *texts[] = {"-10 dBV", "+4 dBu", "Lo Gain"};
2232
2233 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2234 uinfo->count = 1;
2235 uinfo->value.enumerated.items = 3;
2236 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2237 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2238 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2239 return 0;
2240}
2241
Takashi Iwai55e957d2005-11-17 14:52:13 +01002242static int snd_hdsp_get_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002244 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245
2246 ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp);
2247 return 0;
2248}
2249
Takashi Iwai55e957d2005-11-17 14:52:13 +01002250static int snd_hdsp_put_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002252 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 int change;
2254 int val;
2255
2256 if (!snd_hdsp_use_is_exclusive(hdsp))
2257 return -EBUSY;
2258 val = ucontrol->value.enumerated.item[0];
2259 if (val < 0) val = 0;
2260 if (val > 2) val = 2;
2261 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002262 if (val != hdsp_ad_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 change = (hdsp_set_ad_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002264 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 spin_unlock_irq(&hdsp->lock);
2267 return change;
2268}
2269
2270#define HDSP_PHONE_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002271{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 .name = xname, \
2273 .index = xindex, \
2274 .info = snd_hdsp_info_phone_gain, \
2275 .get = snd_hdsp_get_phone_gain, \
2276 .put = snd_hdsp_put_phone_gain \
2277}
2278
Takashi Iwai55e957d2005-11-17 14:52:13 +01002279static int hdsp_phone_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280{
2281 switch (hdsp->control_register & HDSP_PhoneGainMask) {
2282 case HDSP_PhoneGain0dB:
2283 return 0;
2284 case HDSP_PhoneGainMinus6dB:
2285 return 1;
2286 case HDSP_PhoneGainMinus12dB:
2287 return 2;
2288 default:
2289 return 0;
2290 }
2291}
2292
Takashi Iwai55e957d2005-11-17 14:52:13 +01002293static int hdsp_set_phone_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294{
2295 hdsp->control_register &= ~HDSP_PhoneGainMask;
2296 switch (mode) {
2297 case 0:
2298 hdsp->control_register |= HDSP_PhoneGain0dB;
2299 break;
2300 case 1:
2301 hdsp->control_register |= HDSP_PhoneGainMinus6dB;
2302 break;
2303 case 2:
2304 hdsp->control_register |= HDSP_PhoneGainMinus12dB;
2305 break;
2306 default:
2307 return -1;
2308
2309 }
2310 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2311 return 0;
2312}
2313
Takashi Iwai55e957d2005-11-17 14:52:13 +01002314static int snd_hdsp_info_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315{
2316 static char *texts[] = {"0 dB", "-6 dB", "-12 dB"};
2317
2318 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2319 uinfo->count = 1;
2320 uinfo->value.enumerated.items = 3;
2321 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2322 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2323 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2324 return 0;
2325}
2326
Takashi Iwai55e957d2005-11-17 14:52:13 +01002327static int snd_hdsp_get_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002329 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330
2331 ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp);
2332 return 0;
2333}
2334
Takashi Iwai55e957d2005-11-17 14:52:13 +01002335static int snd_hdsp_put_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002337 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 int change;
2339 int val;
2340
2341 if (!snd_hdsp_use_is_exclusive(hdsp))
2342 return -EBUSY;
2343 val = ucontrol->value.enumerated.item[0];
2344 if (val < 0) val = 0;
2345 if (val > 2) val = 2;
2346 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002347 if (val != hdsp_phone_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 change = (hdsp_set_phone_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002349 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 spin_unlock_irq(&hdsp->lock);
2352 return change;
2353}
2354
2355#define HDSP_XLR_BREAKOUT_CABLE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002356{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 .name = xname, \
2358 .index = xindex, \
2359 .info = snd_hdsp_info_xlr_breakout_cable, \
2360 .get = snd_hdsp_get_xlr_breakout_cable, \
2361 .put = snd_hdsp_put_xlr_breakout_cable \
2362}
2363
Takashi Iwai55e957d2005-11-17 14:52:13 +01002364static int hdsp_xlr_breakout_cable(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002366 if (hdsp->control_register & HDSP_XLRBreakoutCable)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 return 0;
2369}
2370
Takashi Iwai55e957d2005-11-17 14:52:13 +01002371static int hdsp_set_xlr_breakout_cable(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002373 if (mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 hdsp->control_register |= HDSP_XLRBreakoutCable;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002375 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 hdsp->control_register &= ~HDSP_XLRBreakoutCable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2378 return 0;
2379}
2380
Takashi Iwai55e957d2005-11-17 14:52:13 +01002381static int snd_hdsp_info_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382{
2383 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2384 uinfo->count = 1;
2385 uinfo->value.integer.min = 0;
2386 uinfo->value.integer.max = 1;
2387 return 0;
2388}
2389
Takashi Iwai55e957d2005-11-17 14:52:13 +01002390static int snd_hdsp_get_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002392 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393
2394 ucontrol->value.enumerated.item[0] = hdsp_xlr_breakout_cable(hdsp);
2395 return 0;
2396}
2397
Takashi Iwai55e957d2005-11-17 14:52:13 +01002398static int snd_hdsp_put_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002400 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 int change;
2402 int val;
2403
2404 if (!snd_hdsp_use_is_exclusive(hdsp))
2405 return -EBUSY;
2406 val = ucontrol->value.integer.value[0] & 1;
2407 spin_lock_irq(&hdsp->lock);
2408 change = (int)val != hdsp_xlr_breakout_cable(hdsp);
2409 hdsp_set_xlr_breakout_cable(hdsp, val);
2410 spin_unlock_irq(&hdsp->lock);
2411 return change;
2412}
2413
2414/* (De)activates old RME Analog Extension Board
2415 These are connected to the internal ADAT connector
2416 Switching this on desactivates external ADAT
2417*/
2418#define HDSP_AEB(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002419{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420 .name = xname, \
2421 .index = xindex, \
2422 .info = snd_hdsp_info_aeb, \
2423 .get = snd_hdsp_get_aeb, \
2424 .put = snd_hdsp_put_aeb \
2425}
2426
Takashi Iwai55e957d2005-11-17 14:52:13 +01002427static int hdsp_aeb(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002429 if (hdsp->control_register & HDSP_AnalogExtensionBoard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431 return 0;
2432}
2433
Takashi Iwai55e957d2005-11-17 14:52:13 +01002434static int hdsp_set_aeb(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002436 if (mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 hdsp->control_register |= HDSP_AnalogExtensionBoard;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002438 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439 hdsp->control_register &= ~HDSP_AnalogExtensionBoard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2441 return 0;
2442}
2443
Takashi Iwai55e957d2005-11-17 14:52:13 +01002444static int snd_hdsp_info_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445{
2446 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2447 uinfo->count = 1;
2448 uinfo->value.integer.min = 0;
2449 uinfo->value.integer.max = 1;
2450 return 0;
2451}
2452
Takashi Iwai55e957d2005-11-17 14:52:13 +01002453static int snd_hdsp_get_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002455 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456
2457 ucontrol->value.enumerated.item[0] = hdsp_aeb(hdsp);
2458 return 0;
2459}
2460
Takashi Iwai55e957d2005-11-17 14:52:13 +01002461static int snd_hdsp_put_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002463 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 int change;
2465 int val;
2466
2467 if (!snd_hdsp_use_is_exclusive(hdsp))
2468 return -EBUSY;
2469 val = ucontrol->value.integer.value[0] & 1;
2470 spin_lock_irq(&hdsp->lock);
2471 change = (int)val != hdsp_aeb(hdsp);
2472 hdsp_set_aeb(hdsp, val);
2473 spin_unlock_irq(&hdsp->lock);
2474 return change;
2475}
2476
2477#define HDSP_PREF_SYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002478{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 .name = xname, \
2480 .index = xindex, \
2481 .info = snd_hdsp_info_pref_sync_ref, \
2482 .get = snd_hdsp_get_pref_sync_ref, \
2483 .put = snd_hdsp_put_pref_sync_ref \
2484}
2485
Takashi Iwai55e957d2005-11-17 14:52:13 +01002486static int hdsp_pref_sync_ref(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487{
2488 /* Notice that this looks at the requested sync source,
2489 not the one actually in use.
2490 */
2491
2492 switch (hdsp->control_register & HDSP_SyncRefMask) {
2493 case HDSP_SyncRef_ADAT1:
2494 return HDSP_SYNC_FROM_ADAT1;
2495 case HDSP_SyncRef_ADAT2:
2496 return HDSP_SYNC_FROM_ADAT2;
2497 case HDSP_SyncRef_ADAT3:
2498 return HDSP_SYNC_FROM_ADAT3;
2499 case HDSP_SyncRef_SPDIF:
2500 return HDSP_SYNC_FROM_SPDIF;
2501 case HDSP_SyncRef_WORD:
2502 return HDSP_SYNC_FROM_WORD;
2503 case HDSP_SyncRef_ADAT_SYNC:
2504 return HDSP_SYNC_FROM_ADAT_SYNC;
2505 default:
2506 return HDSP_SYNC_FROM_WORD;
2507 }
2508 return 0;
2509}
2510
Takashi Iwai55e957d2005-11-17 14:52:13 +01002511static int hdsp_set_pref_sync_ref(struct hdsp *hdsp, int pref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512{
2513 hdsp->control_register &= ~HDSP_SyncRefMask;
2514 switch (pref) {
2515 case HDSP_SYNC_FROM_ADAT1:
2516 hdsp->control_register &= ~HDSP_SyncRefMask; /* clear SyncRef bits */
2517 break;
2518 case HDSP_SYNC_FROM_ADAT2:
2519 hdsp->control_register |= HDSP_SyncRef_ADAT2;
2520 break;
2521 case HDSP_SYNC_FROM_ADAT3:
2522 hdsp->control_register |= HDSP_SyncRef_ADAT3;
2523 break;
2524 case HDSP_SYNC_FROM_SPDIF:
2525 hdsp->control_register |= HDSP_SyncRef_SPDIF;
2526 break;
2527 case HDSP_SYNC_FROM_WORD:
2528 hdsp->control_register |= HDSP_SyncRef_WORD;
2529 break;
2530 case HDSP_SYNC_FROM_ADAT_SYNC:
2531 hdsp->control_register |= HDSP_SyncRef_ADAT_SYNC;
2532 break;
2533 default:
2534 return -1;
2535 }
2536 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2537 return 0;
2538}
2539
Takashi Iwai55e957d2005-11-17 14:52:13 +01002540static int snd_hdsp_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541{
2542 static char *texts[] = {"Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3" };
Takashi Iwai55e957d2005-11-17 14:52:13 +01002543 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544
2545 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2546 uinfo->count = 1;
2547
2548 switch (hdsp->io_type) {
2549 case Digiface:
2550 case H9652:
2551 uinfo->value.enumerated.items = 6;
2552 break;
2553 case Multiface:
2554 uinfo->value.enumerated.items = 4;
2555 break;
2556 case H9632:
2557 uinfo->value.enumerated.items = 3;
2558 break;
2559 default:
2560 uinfo->value.enumerated.items = 0;
2561 break;
2562 }
2563
2564 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2565 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2566 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2567 return 0;
2568}
2569
Takashi Iwai55e957d2005-11-17 14:52:13 +01002570static int snd_hdsp_get_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002572 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573
2574 ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp);
2575 return 0;
2576}
2577
Takashi Iwai55e957d2005-11-17 14:52:13 +01002578static int snd_hdsp_put_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002580 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 int change, max;
2582 unsigned int val;
2583
2584 if (!snd_hdsp_use_is_exclusive(hdsp))
2585 return -EBUSY;
2586
2587 switch (hdsp->io_type) {
2588 case Digiface:
2589 case H9652:
2590 max = 6;
2591 break;
2592 case Multiface:
2593 max = 4;
2594 break;
2595 case H9632:
2596 max = 3;
2597 break;
2598 default:
2599 return -EIO;
2600 }
2601
2602 val = ucontrol->value.enumerated.item[0] % max;
2603 spin_lock_irq(&hdsp->lock);
2604 change = (int)val != hdsp_pref_sync_ref(hdsp);
2605 hdsp_set_pref_sync_ref(hdsp, val);
2606 spin_unlock_irq(&hdsp->lock);
2607 return change;
2608}
2609
2610#define HDSP_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002611{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612 .name = xname, \
2613 .index = xindex, \
2614 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2615 .info = snd_hdsp_info_autosync_ref, \
2616 .get = snd_hdsp_get_autosync_ref, \
2617}
2618
Takashi Iwai55e957d2005-11-17 14:52:13 +01002619static int hdsp_autosync_ref(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620{
2621 /* This looks at the autosync selected sync reference */
2622 unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
2623
2624 switch (status2 & HDSP_SelSyncRefMask) {
2625 case HDSP_SelSyncRef_WORD:
2626 return HDSP_AUTOSYNC_FROM_WORD;
2627 case HDSP_SelSyncRef_ADAT_SYNC:
2628 return HDSP_AUTOSYNC_FROM_ADAT_SYNC;
2629 case HDSP_SelSyncRef_SPDIF:
2630 return HDSP_AUTOSYNC_FROM_SPDIF;
2631 case HDSP_SelSyncRefMask:
2632 return HDSP_AUTOSYNC_FROM_NONE;
2633 case HDSP_SelSyncRef_ADAT1:
2634 return HDSP_AUTOSYNC_FROM_ADAT1;
2635 case HDSP_SelSyncRef_ADAT2:
2636 return HDSP_AUTOSYNC_FROM_ADAT2;
2637 case HDSP_SelSyncRef_ADAT3:
2638 return HDSP_AUTOSYNC_FROM_ADAT3;
2639 default:
2640 return HDSP_AUTOSYNC_FROM_WORD;
2641 }
2642 return 0;
2643}
2644
Takashi Iwai55e957d2005-11-17 14:52:13 +01002645static int snd_hdsp_info_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646{
2647 static char *texts[] = {"Word", "ADAT Sync", "IEC958", "None", "ADAT1", "ADAT2", "ADAT3" };
2648
2649 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2650 uinfo->count = 1;
2651 uinfo->value.enumerated.items = 7;
2652 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2653 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2654 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2655 return 0;
2656}
2657
Takashi Iwai55e957d2005-11-17 14:52:13 +01002658static int snd_hdsp_get_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002660 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661
2662 ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp);
2663 return 0;
2664}
2665
2666#define HDSP_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002667{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668 .name = xname, \
2669 .index = xindex, \
2670 .info = snd_hdsp_info_line_out, \
2671 .get = snd_hdsp_get_line_out, \
2672 .put = snd_hdsp_put_line_out \
2673}
2674
Takashi Iwai55e957d2005-11-17 14:52:13 +01002675static int hdsp_line_out(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676{
2677 return (hdsp->control_register & HDSP_LineOut) ? 1 : 0;
2678}
2679
Takashi Iwai55e957d2005-11-17 14:52:13 +01002680static int hdsp_set_line_output(struct hdsp *hdsp, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002682 if (out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 hdsp->control_register |= HDSP_LineOut;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002684 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 hdsp->control_register &= ~HDSP_LineOut;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2687 return 0;
2688}
2689
Takashi Iwai55e957d2005-11-17 14:52:13 +01002690static int snd_hdsp_info_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691{
2692 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2693 uinfo->count = 1;
2694 uinfo->value.integer.min = 0;
2695 uinfo->value.integer.max = 1;
2696 return 0;
2697}
2698
Takashi Iwai55e957d2005-11-17 14:52:13 +01002699static int snd_hdsp_get_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002701 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702
2703 spin_lock_irq(&hdsp->lock);
2704 ucontrol->value.integer.value[0] = hdsp_line_out(hdsp);
2705 spin_unlock_irq(&hdsp->lock);
2706 return 0;
2707}
2708
Takashi Iwai55e957d2005-11-17 14:52:13 +01002709static int snd_hdsp_put_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002711 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712 int change;
2713 unsigned int val;
2714
2715 if (!snd_hdsp_use_is_exclusive(hdsp))
2716 return -EBUSY;
2717 val = ucontrol->value.integer.value[0] & 1;
2718 spin_lock_irq(&hdsp->lock);
2719 change = (int)val != hdsp_line_out(hdsp);
2720 hdsp_set_line_output(hdsp, val);
2721 spin_unlock_irq(&hdsp->lock);
2722 return change;
2723}
2724
2725#define HDSP_PRECISE_POINTER(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002726{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 .name = xname, \
2728 .index = xindex, \
2729 .info = snd_hdsp_info_precise_pointer, \
2730 .get = snd_hdsp_get_precise_pointer, \
2731 .put = snd_hdsp_put_precise_pointer \
2732}
2733
Takashi Iwai55e957d2005-11-17 14:52:13 +01002734static int hdsp_set_precise_pointer(struct hdsp *hdsp, int precise)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002736 if (precise)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 hdsp->precise_ptr = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002738 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 hdsp->precise_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 return 0;
2741}
2742
Takashi Iwai55e957d2005-11-17 14:52:13 +01002743static int snd_hdsp_info_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744{
2745 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2746 uinfo->count = 1;
2747 uinfo->value.integer.min = 0;
2748 uinfo->value.integer.max = 1;
2749 return 0;
2750}
2751
Takashi Iwai55e957d2005-11-17 14:52:13 +01002752static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002754 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755
2756 spin_lock_irq(&hdsp->lock);
2757 ucontrol->value.integer.value[0] = hdsp->precise_ptr;
2758 spin_unlock_irq(&hdsp->lock);
2759 return 0;
2760}
2761
Takashi Iwai55e957d2005-11-17 14:52:13 +01002762static int snd_hdsp_put_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002764 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 int change;
2766 unsigned int val;
2767
2768 if (!snd_hdsp_use_is_exclusive(hdsp))
2769 return -EBUSY;
2770 val = ucontrol->value.integer.value[0] & 1;
2771 spin_lock_irq(&hdsp->lock);
2772 change = (int)val != hdsp->precise_ptr;
2773 hdsp_set_precise_pointer(hdsp, val);
2774 spin_unlock_irq(&hdsp->lock);
2775 return change;
2776}
2777
2778#define HDSP_USE_MIDI_TASKLET(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002779{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780 .name = xname, \
2781 .index = xindex, \
2782 .info = snd_hdsp_info_use_midi_tasklet, \
2783 .get = snd_hdsp_get_use_midi_tasklet, \
2784 .put = snd_hdsp_put_use_midi_tasklet \
2785}
2786
Takashi Iwai55e957d2005-11-17 14:52:13 +01002787static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002789 if (use_tasklet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790 hdsp->use_midi_tasklet = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002791 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792 hdsp->use_midi_tasklet = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 return 0;
2794}
2795
Takashi Iwai55e957d2005-11-17 14:52:13 +01002796static int snd_hdsp_info_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797{
2798 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2799 uinfo->count = 1;
2800 uinfo->value.integer.min = 0;
2801 uinfo->value.integer.max = 1;
2802 return 0;
2803}
2804
Takashi Iwai55e957d2005-11-17 14:52:13 +01002805static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002807 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808
2809 spin_lock_irq(&hdsp->lock);
2810 ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet;
2811 spin_unlock_irq(&hdsp->lock);
2812 return 0;
2813}
2814
Takashi Iwai55e957d2005-11-17 14:52:13 +01002815static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002817 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818 int change;
2819 unsigned int val;
2820
2821 if (!snd_hdsp_use_is_exclusive(hdsp))
2822 return -EBUSY;
2823 val = ucontrol->value.integer.value[0] & 1;
2824 spin_lock_irq(&hdsp->lock);
2825 change = (int)val != hdsp->use_midi_tasklet;
2826 hdsp_set_use_midi_tasklet(hdsp, val);
2827 spin_unlock_irq(&hdsp->lock);
2828 return change;
2829}
2830
2831#define HDSP_MIXER(xname, xindex) \
2832{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
2833 .name = xname, \
2834 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002835 .device = 0, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2837 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2838 .info = snd_hdsp_info_mixer, \
2839 .get = snd_hdsp_get_mixer, \
2840 .put = snd_hdsp_put_mixer \
2841}
2842
Takashi Iwai55e957d2005-11-17 14:52:13 +01002843static int snd_hdsp_info_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844{
2845 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2846 uinfo->count = 3;
2847 uinfo->value.integer.min = 0;
2848 uinfo->value.integer.max = 65536;
2849 uinfo->value.integer.step = 1;
2850 return 0;
2851}
2852
Takashi Iwai55e957d2005-11-17 14:52:13 +01002853static int snd_hdsp_get_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002855 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856 int source;
2857 int destination;
2858 int addr;
2859
2860 source = ucontrol->value.integer.value[0];
2861 destination = ucontrol->value.integer.value[1];
2862
Takashi Iwaib0b98112005-10-20 18:29:58 +02002863 if (source >= hdsp->max_channels)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864 addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels,destination);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002865 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866 addr = hdsp_input_to_output_key(hdsp,source, destination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867
2868 spin_lock_irq(&hdsp->lock);
2869 ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr);
2870 spin_unlock_irq(&hdsp->lock);
2871 return 0;
2872}
2873
Takashi Iwai55e957d2005-11-17 14:52:13 +01002874static int snd_hdsp_put_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002876 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877 int change;
2878 int source;
2879 int destination;
2880 int gain;
2881 int addr;
2882
2883 if (!snd_hdsp_use_is_exclusive(hdsp))
2884 return -EBUSY;
2885
2886 source = ucontrol->value.integer.value[0];
2887 destination = ucontrol->value.integer.value[1];
2888
Takashi Iwaib0b98112005-10-20 18:29:58 +02002889 if (source >= hdsp->max_channels)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890 addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels, destination);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002891 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892 addr = hdsp_input_to_output_key(hdsp,source, destination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893
2894 gain = ucontrol->value.integer.value[2];
2895
2896 spin_lock_irq(&hdsp->lock);
2897 change = gain != hdsp_read_gain(hdsp, addr);
2898 if (change)
2899 hdsp_write_gain(hdsp, addr, gain);
2900 spin_unlock_irq(&hdsp->lock);
2901 return change;
2902}
2903
2904#define HDSP_WC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002905{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906 .name = xname, \
2907 .index = xindex, \
2908 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2909 .info = snd_hdsp_info_sync_check, \
2910 .get = snd_hdsp_get_wc_sync_check \
2911}
2912
Takashi Iwai55e957d2005-11-17 14:52:13 +01002913static int snd_hdsp_info_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914{
2915 static char *texts[] = {"No Lock", "Lock", "Sync" };
2916 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2917 uinfo->count = 1;
2918 uinfo->value.enumerated.items = 3;
2919 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2920 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2921 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2922 return 0;
2923}
2924
Takashi Iwai55e957d2005-11-17 14:52:13 +01002925static int hdsp_wc_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926{
2927 int status2 = hdsp_read(hdsp, HDSP_status2Register);
2928 if (status2 & HDSP_wc_lock) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002929 if (status2 & HDSP_wc_sync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002931 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002933 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935 return 0;
2936}
2937
Takashi Iwai55e957d2005-11-17 14:52:13 +01002938static int snd_hdsp_get_wc_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002940 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941
2942 ucontrol->value.enumerated.item[0] = hdsp_wc_sync_check(hdsp);
2943 return 0;
2944}
2945
2946#define HDSP_SPDIF_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002947{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948 .name = xname, \
2949 .index = xindex, \
2950 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2951 .info = snd_hdsp_info_sync_check, \
2952 .get = snd_hdsp_get_spdif_sync_check \
2953}
2954
Takashi Iwai55e957d2005-11-17 14:52:13 +01002955static int hdsp_spdif_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956{
2957 int status = hdsp_read(hdsp, HDSP_statusRegister);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002958 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002960 else {
2961 if (status & HDSP_SPDIFSync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002963 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965 }
2966 return 0;
2967}
2968
Takashi Iwai55e957d2005-11-17 14:52:13 +01002969static int snd_hdsp_get_spdif_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002971 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972
2973 ucontrol->value.enumerated.item[0] = hdsp_spdif_sync_check(hdsp);
2974 return 0;
2975}
2976
2977#define HDSP_ADATSYNC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002978{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 .name = xname, \
2980 .index = xindex, \
2981 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2982 .info = snd_hdsp_info_sync_check, \
2983 .get = snd_hdsp_get_adatsync_sync_check \
2984}
2985
Takashi Iwai55e957d2005-11-17 14:52:13 +01002986static int hdsp_adatsync_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987{
2988 int status = hdsp_read(hdsp, HDSP_statusRegister);
2989 if (status & HDSP_TimecodeLock) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002990 if (status & HDSP_TimecodeSync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002992 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002994 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996}
2997
Takashi Iwai55e957d2005-11-17 14:52:13 +01002998static int snd_hdsp_get_adatsync_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003000 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001
3002 ucontrol->value.enumerated.item[0] = hdsp_adatsync_sync_check(hdsp);
3003 return 0;
3004}
3005
3006#define HDSP_ADAT_SYNC_CHECK \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003007{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3009 .info = snd_hdsp_info_sync_check, \
3010 .get = snd_hdsp_get_adat_sync_check \
3011}
3012
Takashi Iwai55e957d2005-11-17 14:52:13 +01003013static int hdsp_adat_sync_check(struct hdsp *hdsp, int idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014{
3015 int status = hdsp_read(hdsp, HDSP_statusRegister);
3016
3017 if (status & (HDSP_Lock0>>idx)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003018 if (status & (HDSP_Sync0>>idx))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003020 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003022 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024}
3025
Takashi Iwai55e957d2005-11-17 14:52:13 +01003026static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027{
3028 int offset;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003029 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030
3031 offset = ucontrol->id.index - 1;
3032 snd_assert(offset >= 0);
3033
3034 switch (hdsp->io_type) {
3035 case Digiface:
3036 case H9652:
3037 if (offset >= 3)
3038 return -EINVAL;
3039 break;
3040 case Multiface:
3041 case H9632:
3042 if (offset >= 1)
3043 return -EINVAL;
3044 break;
3045 default:
3046 return -EIO;
3047 }
3048
3049 ucontrol->value.enumerated.item[0] = hdsp_adat_sync_check(hdsp, offset);
3050 return 0;
3051}
3052
Takashi Iwai55e957d2005-11-17 14:52:13 +01003053static struct snd_kcontrol_new snd_hdsp_9632_controls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054HDSP_DA_GAIN("DA Gain", 0),
3055HDSP_AD_GAIN("AD Gain", 0),
3056HDSP_PHONE_GAIN("Phones Gain", 0),
3057HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0)
3058};
3059
Takashi Iwai55e957d2005-11-17 14:52:13 +01003060static struct snd_kcontrol_new snd_hdsp_controls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061{
Clemens Ladisch5549d542005-08-03 13:50:30 +02003062 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
3064 .info = snd_hdsp_control_spdif_info,
3065 .get = snd_hdsp_control_spdif_get,
3066 .put = snd_hdsp_control_spdif_put,
3067},
3068{
3069 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch5549d542005-08-03 13:50:30 +02003070 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
3072 .info = snd_hdsp_control_spdif_stream_info,
3073 .get = snd_hdsp_control_spdif_stream_get,
3074 .put = snd_hdsp_control_spdif_stream_put,
3075},
3076{
3077 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +02003078 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
3080 .info = snd_hdsp_control_spdif_mask_info,
3081 .get = snd_hdsp_control_spdif_mask_get,
3082 .private_value = IEC958_AES0_NONAUDIO |
3083 IEC958_AES0_PROFESSIONAL |
3084 IEC958_AES0_CON_EMPHASIS,
3085},
3086{
3087 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +02003088 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
3090 .info = snd_hdsp_control_spdif_mask_info,
3091 .get = snd_hdsp_control_spdif_mask_get,
3092 .private_value = IEC958_AES0_NONAUDIO |
3093 IEC958_AES0_PROFESSIONAL |
3094 IEC958_AES0_PRO_EMPHASIS,
3095},
3096HDSP_MIXER("Mixer", 0),
3097HDSP_SPDIF_IN("IEC958 Input Connector", 0),
3098HDSP_SPDIF_OUT("IEC958 Output also on ADAT1", 0),
3099HDSP_SPDIF_PROFESSIONAL("IEC958 Professional Bit", 0),
3100HDSP_SPDIF_EMPHASIS("IEC958 Emphasis Bit", 0),
3101HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0),
3102/* 'Sample Clock Source' complies with the alsa control naming scheme */
3103HDSP_CLOCK_SOURCE("Sample Clock Source", 0),
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003104{
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003105 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3106 .name = "Sample Clock Source Locking",
3107 .info = snd_hdsp_info_clock_source_lock,
3108 .get = snd_hdsp_get_clock_source_lock,
3109 .put = snd_hdsp_put_clock_source_lock,
3110},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111HDSP_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
3112HDSP_PREF_SYNC_REF("Preferred Sync Reference", 0),
3113HDSP_AUTOSYNC_REF("AutoSync Reference", 0),
3114HDSP_SPDIF_SAMPLE_RATE("SPDIF Sample Rate", 0),
3115HDSP_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
3116/* 'External Rate' complies with the alsa control naming scheme */
3117HDSP_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
3118HDSP_WC_SYNC_CHECK("Word Clock Lock Status", 0),
3119HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0),
3120HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0),
3121HDSP_LINE_OUT("Line Out", 0),
3122HDSP_PRECISE_POINTER("Precise Pointer", 0),
3123HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0),
3124};
3125
Takashi Iwai55e957d2005-11-17 14:52:13 +01003126static struct snd_kcontrol_new snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0);
3127static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128
Takashi Iwai55e957d2005-11-17 14:52:13 +01003129static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130{
3131 unsigned int idx;
3132 int err;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003133 struct snd_kcontrol *kctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134
3135 for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003136 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 if (idx == 1) /* IEC958 (S/PDIF) Stream */
3139 hdsp->spdif_ctl = kctl;
3140 }
3141
3142 /* ADAT SyncCheck status */
3143 snd_hdsp_adat_sync_check.name = "ADAT Lock Status";
3144 snd_hdsp_adat_sync_check.index = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003145 if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147 if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
3148 for (idx = 1; idx < 3; ++idx) {
3149 snd_hdsp_adat_sync_check.index = idx+1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003150 if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152 }
3153 }
3154
3155 /* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */
3156 if (hdsp->io_type == H9632) {
3157 for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003158 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160 }
3161 }
3162
3163 /* AEB control for H96xx card */
3164 if (hdsp->io_type == H9632 || hdsp->io_type == H9652) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003165 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167 }
3168
3169 return 0;
3170}
3171
3172/*------------------------------------------------------------
3173 /proc interface
3174 ------------------------------------------------------------*/
3175
3176static void
Takashi Iwai55e957d2005-11-17 14:52:13 +01003177snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003179 struct hdsp *hdsp = (struct hdsp *) entry->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180 unsigned int status;
3181 unsigned int status2;
3182 char *pref_sync_ref;
3183 char *autosync_ref;
3184 char *system_clock_mode;
3185 char *clock_source;
3186 int x;
3187
Remy Brunoecb594e2006-06-12 09:25:22 +02003188 if (hdsp_check_for_iobox (hdsp)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003189 snd_iprintf(buffer, "No I/O box connected.\nPlease connect one and upload firmware.\n");
3190 return;
Remy Brunoecb594e2006-06-12 09:25:22 +02003191 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192
Takashi Iwaib0b98112005-10-20 18:29:58 +02003193 if (hdsp_check_for_firmware(hdsp, 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194 if (hdsp->state & HDSP_FirmwareCached) {
3195 if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
3196 snd_iprintf(buffer, "Firmware loading from cache failed, please upload manually.\n");
3197 return;
3198 }
3199 } else {
Takashi Iwai311e70a2006-09-06 12:13:37 +02003200 int err = -EINVAL;
3201#ifdef HDSP_FW_LOADER
3202 err = hdsp_request_fw_loader(hdsp);
3203#endif
3204 if (err < 0) {
3205 snd_iprintf(buffer,
3206 "No firmware loaded nor cached, "
3207 "please upload firmware.\n");
3208 return;
3209 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210 }
3211 }
3212
3213 status = hdsp_read(hdsp, HDSP_statusRegister);
3214 status2 = hdsp_read(hdsp, HDSP_status2Register);
3215
3216 snd_iprintf(buffer, "%s (Card #%d)\n", hdsp->card_name, hdsp->card->number + 1);
3217 snd_iprintf(buffer, "Buffers: capture %p playback %p\n",
3218 hdsp->capture_buffer, hdsp->playback_buffer);
3219 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
3220 hdsp->irq, hdsp->port, (unsigned long)hdsp->iobase);
3221 snd_iprintf(buffer, "Control register: 0x%x\n", hdsp->control_register);
3222 snd_iprintf(buffer, "Control2 register: 0x%x\n", hdsp->control2_register);
3223 snd_iprintf(buffer, "Status register: 0x%x\n", status);
3224 snd_iprintf(buffer, "Status2 register: 0x%x\n", status2);
3225 snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff);
3226 snd_iprintf(buffer, "MIDI1 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut0));
3227 snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0));
3228 snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1));
3229 snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1));
3230 snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off");
3231
3232 snd_iprintf(buffer, "\n");
3233
3234 x = 1 << (6 + hdsp_decode_latency(hdsp->control_register & HDSP_LatencyMask));
3235
3236 snd_iprintf(buffer, "Buffer Size (Latency): %d samples (2 periods of %lu bytes)\n", x, (unsigned long) hdsp->period_bytes);
3237 snd_iprintf(buffer, "Hardware pointer (frames): %ld\n", hdsp_hw_pointer(hdsp));
3238 snd_iprintf(buffer, "Precise pointer: %s\n", hdsp->precise_ptr ? "on" : "off");
3239 snd_iprintf(buffer, "Line out: %s\n", (hdsp->control_register & HDSP_LineOut) ? "on" : "off");
3240
3241 snd_iprintf(buffer, "Firmware version: %d\n", (status2&HDSP_version0)|(status2&HDSP_version1)<<1|(status2&HDSP_version2)<<2);
3242
3243 snd_iprintf(buffer, "\n");
3244
3245
3246 switch (hdsp_clock_source(hdsp)) {
3247 case HDSP_CLOCK_SOURCE_AUTOSYNC:
3248 clock_source = "AutoSync";
3249 break;
3250 case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ:
3251 clock_source = "Internal 32 kHz";
3252 break;
3253 case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ:
3254 clock_source = "Internal 44.1 kHz";
3255 break;
3256 case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ:
3257 clock_source = "Internal 48 kHz";
3258 break;
3259 case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ:
3260 clock_source = "Internal 64 kHz";
3261 break;
3262 case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ:
3263 clock_source = "Internal 88.2 kHz";
3264 break;
3265 case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ:
3266 clock_source = "Internal 96 kHz";
3267 break;
3268 case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ:
3269 clock_source = "Internal 128 kHz";
3270 break;
3271 case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ:
3272 clock_source = "Internal 176.4 kHz";
3273 break;
3274 case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ:
3275 clock_source = "Internal 192 kHz";
3276 break;
3277 default:
3278 clock_source = "Error";
3279 }
3280 snd_iprintf (buffer, "Sample Clock Source: %s\n", clock_source);
3281
Takashi Iwaib0b98112005-10-20 18:29:58 +02003282 if (hdsp_system_clock_mode(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283 system_clock_mode = "Slave";
Takashi Iwaib0b98112005-10-20 18:29:58 +02003284 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285 system_clock_mode = "Master";
Linus Torvalds1da177e2005-04-16 15:20:36 -07003286
3287 switch (hdsp_pref_sync_ref (hdsp)) {
3288 case HDSP_SYNC_FROM_WORD:
3289 pref_sync_ref = "Word Clock";
3290 break;
3291 case HDSP_SYNC_FROM_ADAT_SYNC:
3292 pref_sync_ref = "ADAT Sync";
3293 break;
3294 case HDSP_SYNC_FROM_SPDIF:
3295 pref_sync_ref = "SPDIF";
3296 break;
3297 case HDSP_SYNC_FROM_ADAT1:
3298 pref_sync_ref = "ADAT1";
3299 break;
3300 case HDSP_SYNC_FROM_ADAT2:
3301 pref_sync_ref = "ADAT2";
3302 break;
3303 case HDSP_SYNC_FROM_ADAT3:
3304 pref_sync_ref = "ADAT3";
3305 break;
3306 default:
3307 pref_sync_ref = "Word Clock";
3308 break;
3309 }
3310 snd_iprintf (buffer, "Preferred Sync Reference: %s\n", pref_sync_ref);
3311
3312 switch (hdsp_autosync_ref (hdsp)) {
3313 case HDSP_AUTOSYNC_FROM_WORD:
3314 autosync_ref = "Word Clock";
3315 break;
3316 case HDSP_AUTOSYNC_FROM_ADAT_SYNC:
3317 autosync_ref = "ADAT Sync";
3318 break;
3319 case HDSP_AUTOSYNC_FROM_SPDIF:
3320 autosync_ref = "SPDIF";
3321 break;
3322 case HDSP_AUTOSYNC_FROM_NONE:
3323 autosync_ref = "None";
3324 break;
3325 case HDSP_AUTOSYNC_FROM_ADAT1:
3326 autosync_ref = "ADAT1";
3327 break;
3328 case HDSP_AUTOSYNC_FROM_ADAT2:
3329 autosync_ref = "ADAT2";
3330 break;
3331 case HDSP_AUTOSYNC_FROM_ADAT3:
3332 autosync_ref = "ADAT3";
3333 break;
3334 default:
3335 autosync_ref = "---";
3336 break;
3337 }
3338 snd_iprintf (buffer, "AutoSync Reference: %s\n", autosync_ref);
3339
3340 snd_iprintf (buffer, "AutoSync Frequency: %d\n", hdsp_external_sample_rate(hdsp));
3341
3342 snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode);
3343
3344 snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003345 snd_iprintf (buffer, "System Clock Locked: %s\n", hdsp->clock_source_locked ? "Yes" : "No");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346
3347 snd_iprintf(buffer, "\n");
3348
3349 switch (hdsp_spdif_in(hdsp)) {
3350 case HDSP_SPDIFIN_OPTICAL:
3351 snd_iprintf(buffer, "IEC958 input: Optical\n");
3352 break;
3353 case HDSP_SPDIFIN_COAXIAL:
3354 snd_iprintf(buffer, "IEC958 input: Coaxial\n");
3355 break;
3356 case HDSP_SPDIFIN_INTERNAL:
3357 snd_iprintf(buffer, "IEC958 input: Internal\n");
3358 break;
3359 case HDSP_SPDIFIN_AES:
3360 snd_iprintf(buffer, "IEC958 input: AES\n");
3361 break;
3362 default:
3363 snd_iprintf(buffer, "IEC958 input: ???\n");
3364 break;
3365 }
3366
Takashi Iwaib0b98112005-10-20 18:29:58 +02003367 if (hdsp->control_register & HDSP_SPDIFOpticalOut)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368 snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003369 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370 snd_iprintf(buffer, "IEC958 output: Coaxial only\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371
Takashi Iwaib0b98112005-10-20 18:29:58 +02003372 if (hdsp->control_register & HDSP_SPDIFProfessional)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373 snd_iprintf(buffer, "IEC958 quality: Professional\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003374 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375 snd_iprintf(buffer, "IEC958 quality: Consumer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376
Takashi Iwaib0b98112005-10-20 18:29:58 +02003377 if (hdsp->control_register & HDSP_SPDIFEmphasis)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378 snd_iprintf(buffer, "IEC958 emphasis: on\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003379 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380 snd_iprintf(buffer, "IEC958 emphasis: off\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381
Takashi Iwaib0b98112005-10-20 18:29:58 +02003382 if (hdsp->control_register & HDSP_SPDIFNonAudio)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383 snd_iprintf(buffer, "IEC958 NonAudio: on\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003384 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385 snd_iprintf(buffer, "IEC958 NonAudio: off\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003386 if ((x = hdsp_spdif_sample_rate (hdsp)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387 snd_iprintf (buffer, "IEC958 sample rate: %d\n", x);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003388 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389 snd_iprintf (buffer, "IEC958 sample rate: Error flag set\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390
3391 snd_iprintf(buffer, "\n");
3392
3393 /* Sync Check */
3394 x = status & HDSP_Sync0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003395 if (status & HDSP_Lock0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396 snd_iprintf(buffer, "ADAT1: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003397 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003398 snd_iprintf(buffer, "ADAT1: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399
3400 switch (hdsp->io_type) {
3401 case Digiface:
3402 case H9652:
3403 x = status & HDSP_Sync1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003404 if (status & HDSP_Lock1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405 snd_iprintf(buffer, "ADAT2: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003406 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407 snd_iprintf(buffer, "ADAT2: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408 x = status & HDSP_Sync2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003409 if (status & HDSP_Lock2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410 snd_iprintf(buffer, "ADAT3: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003411 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412 snd_iprintf(buffer, "ADAT3: No Lock\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003413 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414 default:
3415 /* relax */
3416 break;
3417 }
3418
3419 x = status & HDSP_SPDIFSync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003420 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421 snd_iprintf (buffer, "SPDIF: No Lock\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003422 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423 snd_iprintf (buffer, "SPDIF: %s\n", x ? "Sync" : "Lock");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003424
3425 x = status2 & HDSP_wc_sync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003426 if (status2 & HDSP_wc_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427 snd_iprintf (buffer, "Word Clock: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003428 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429 snd_iprintf (buffer, "Word Clock: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430
3431 x = status & HDSP_TimecodeSync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003432 if (status & HDSP_TimecodeLock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003433 snd_iprintf(buffer, "ADAT Sync: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003434 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435 snd_iprintf(buffer, "ADAT Sync: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436
3437 snd_iprintf(buffer, "\n");
3438
3439 /* Informations about H9632 specific controls */
3440 if (hdsp->io_type == H9632) {
3441 char *tmp;
3442
3443 switch (hdsp_ad_gain(hdsp)) {
3444 case 0:
3445 tmp = "-10 dBV";
3446 break;
3447 case 1:
3448 tmp = "+4 dBu";
3449 break;
3450 default:
3451 tmp = "Lo Gain";
3452 break;
3453 }
3454 snd_iprintf(buffer, "AD Gain : %s\n", tmp);
3455
3456 switch (hdsp_da_gain(hdsp)) {
3457 case 0:
3458 tmp = "Hi Gain";
3459 break;
3460 case 1:
3461 tmp = "+4 dBu";
3462 break;
3463 default:
3464 tmp = "-10 dBV";
3465 break;
3466 }
3467 snd_iprintf(buffer, "DA Gain : %s\n", tmp);
3468
3469 switch (hdsp_phone_gain(hdsp)) {
3470 case 0:
3471 tmp = "0 dB";
3472 break;
3473 case 1:
3474 tmp = "-6 dB";
3475 break;
3476 default:
3477 tmp = "-12 dB";
3478 break;
3479 }
3480 snd_iprintf(buffer, "Phones Gain : %s\n", tmp);
3481
3482 snd_iprintf(buffer, "XLR Breakout Cable : %s\n", hdsp_xlr_breakout_cable(hdsp) ? "yes" : "no");
3483
Takashi Iwaib0b98112005-10-20 18:29:58 +02003484 if (hdsp->control_register & HDSP_AnalogExtensionBoard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485 snd_iprintf(buffer, "AEB : on (ADAT1 internal)\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003486 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487 snd_iprintf(buffer, "AEB : off (ADAT1 external)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488 snd_iprintf(buffer, "\n");
3489 }
3490
3491}
3492
Takashi Iwai55e957d2005-11-17 14:52:13 +01003493static void __devinit snd_hdsp_proc_init(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003495 struct snd_info_entry *entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496
3497 if (! snd_card_proc_new(hdsp->card, "hdsp", &entry))
Takashi Iwaibf850202006-04-28 15:13:41 +02003498 snd_info_set_text_ops(entry, hdsp, snd_hdsp_proc_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499}
3500
Takashi Iwai55e957d2005-11-17 14:52:13 +01003501static void snd_hdsp_free_buffers(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502{
3503 snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci);
3504 snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
3505}
3506
Takashi Iwai55e957d2005-11-17 14:52:13 +01003507static int __devinit snd_hdsp_initialize_memory(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003508{
3509 unsigned long pb_bus, cb_bus;
3510
3511 if (snd_hammerfall_get_buffer(hdsp->pci, &hdsp->capture_dma_buf, HDSP_DMA_AREA_BYTES) < 0 ||
3512 snd_hammerfall_get_buffer(hdsp->pci, &hdsp->playback_dma_buf, HDSP_DMA_AREA_BYTES) < 0) {
3513 if (hdsp->capture_dma_buf.area)
3514 snd_dma_free_pages(&hdsp->capture_dma_buf);
3515 printk(KERN_ERR "%s: no buffers available\n", hdsp->card_name);
3516 return -ENOMEM;
3517 }
3518
3519 /* Align to bus-space 64K boundary */
3520
Clemens Ladisch7ab39922006-10-09 08:13:32 +02003521 cb_bus = ALIGN(hdsp->capture_dma_buf.addr, 0x10000ul);
3522 pb_bus = ALIGN(hdsp->playback_dma_buf.addr, 0x10000ul);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523
3524 /* Tell the card where it is */
3525
3526 hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus);
3527 hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus);
3528
3529 hdsp->capture_buffer = hdsp->capture_dma_buf.area + (cb_bus - hdsp->capture_dma_buf.addr);
3530 hdsp->playback_buffer = hdsp->playback_dma_buf.area + (pb_bus - hdsp->playback_dma_buf.addr);
3531
3532 return 0;
3533}
3534
Takashi Iwai55e957d2005-11-17 14:52:13 +01003535static int snd_hdsp_set_defaults(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003536{
3537 unsigned int i;
3538
3539 /* ASSUMPTION: hdsp->lock is either held, or
3540 there is no need to hold it (e.g. during module
3541 initalization).
3542 */
3543
3544 /* set defaults:
3545
3546 SPDIF Input via Coax
3547 Master clock mode
3548 maximum latency (7 => 2^7 = 8192 samples, 64Kbyte buffer,
3549 which implies 2 4096 sample, 32Kbyte periods).
3550 Enable line out.
3551 */
3552
3553 hdsp->control_register = HDSP_ClockModeMaster |
3554 HDSP_SPDIFInputCoaxial |
3555 hdsp_encode_latency(7) |
3556 HDSP_LineOut;
3557
3558
3559 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3560
3561#ifdef SNDRV_BIG_ENDIAN
3562 hdsp->control2_register = HDSP_BIGENDIAN_MODE;
3563#else
3564 hdsp->control2_register = 0;
3565#endif
Takashi Iwaib0b98112005-10-20 18:29:58 +02003566 if (hdsp->io_type == H9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003567 snd_hdsp_9652_enable_mixer (hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003568 else
3569 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003570
3571 hdsp_reset_hw_pointer(hdsp);
3572 hdsp_compute_period_size(hdsp);
3573
3574 /* silence everything */
3575
Takashi Iwaib0b98112005-10-20 18:29:58 +02003576 for (i = 0; i < HDSP_MATRIX_MIXER_SIZE; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577 hdsp->mixer_matrix[i] = MINUS_INFINITY_GAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578
3579 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 +02003580 if (hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582 }
3583
3584 /* H9632 specific defaults */
3585 if (hdsp->io_type == H9632) {
3586 hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB);
3587 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3588 }
3589
3590 /* set a default rate so that the channel map is set up.
3591 */
3592
3593 hdsp_set_rate(hdsp, 48000, 1);
3594
3595 return 0;
3596}
3597
3598static void hdsp_midi_tasklet(unsigned long arg)
3599{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003600 struct hdsp *hdsp = (struct hdsp *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601
Takashi Iwaib0b98112005-10-20 18:29:58 +02003602 if (hdsp->midi[0].pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603 snd_hdsp_midi_input_read (&hdsp->midi[0]);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003604 if (hdsp->midi[1].pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605 snd_hdsp_midi_input_read (&hdsp->midi[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606}
3607
David Howells7d12e782006-10-05 14:55:46 +01003608static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003610 struct hdsp *hdsp = (struct hdsp *) dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611 unsigned int status;
3612 int audio;
3613 int midi0;
3614 int midi1;
3615 unsigned int midi0status;
3616 unsigned int midi1status;
3617 int schedule = 0;
3618
3619 status = hdsp_read(hdsp, HDSP_statusRegister);
3620
3621 audio = status & HDSP_audioIRQPending;
3622 midi0 = status & HDSP_midi0IRQPending;
3623 midi1 = status & HDSP_midi1IRQPending;
3624
Takashi Iwaib0b98112005-10-20 18:29:58 +02003625 if (!audio && !midi0 && !midi1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626 return IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627
3628 hdsp_write(hdsp, HDSP_interruptConfirmation, 0);
3629
3630 midi0status = hdsp_read (hdsp, HDSP_midiStatusIn0) & 0xff;
3631 midi1status = hdsp_read (hdsp, HDSP_midiStatusIn1) & 0xff;
3632
3633 if (audio) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003634 if (hdsp->capture_substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635 snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636
Takashi Iwaib0b98112005-10-20 18:29:58 +02003637 if (hdsp->playback_substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638 snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639 }
3640
3641 if (midi0 && midi0status) {
3642 if (hdsp->use_midi_tasklet) {
3643 /* we disable interrupts for this input until processing is done */
3644 hdsp->control_register &= ~HDSP_Midi0InterruptEnable;
3645 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3646 hdsp->midi[0].pending = 1;
3647 schedule = 1;
3648 } else {
3649 snd_hdsp_midi_input_read (&hdsp->midi[0]);
3650 }
3651 }
3652 if (hdsp->io_type != Multiface && hdsp->io_type != H9632 && midi1 && midi1status) {
3653 if (hdsp->use_midi_tasklet) {
3654 /* we disable interrupts for this input until processing is done */
3655 hdsp->control_register &= ~HDSP_Midi1InterruptEnable;
3656 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3657 hdsp->midi[1].pending = 1;
3658 schedule = 1;
3659 } else {
3660 snd_hdsp_midi_input_read (&hdsp->midi[1]);
3661 }
3662 }
3663 if (hdsp->use_midi_tasklet && schedule)
3664 tasklet_hi_schedule(&hdsp->midi_tasklet);
3665 return IRQ_HANDLED;
3666}
3667
Takashi Iwai55e957d2005-11-17 14:52:13 +01003668static snd_pcm_uframes_t snd_hdsp_hw_pointer(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003670 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671 return hdsp_hw_pointer(hdsp);
3672}
3673
Takashi Iwai55e957d2005-11-17 14:52:13 +01003674static char *hdsp_channel_buffer_location(struct hdsp *hdsp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675 int stream,
3676 int channel)
3677
3678{
3679 int mapped_channel;
3680
3681 snd_assert(channel >= 0 && channel < hdsp->max_channels, return NULL);
3682
Takashi Iwaib0b98112005-10-20 18:29:58 +02003683 if ((mapped_channel = hdsp->channel_map[channel]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685
Takashi Iwaib0b98112005-10-20 18:29:58 +02003686 if (stream == SNDRV_PCM_STREAM_CAPTURE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687 return hdsp->capture_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003688 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689 return hdsp->playback_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690}
3691
Takashi Iwai55e957d2005-11-17 14:52:13 +01003692static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693 snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
3694{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003695 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696 char *channel_buf;
3697
3698 snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
3699
3700 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
3701 snd_assert(channel_buf != NULL, return -EIO);
3702 if (copy_from_user(channel_buf + pos * 4, src, count * 4))
3703 return -EFAULT;
3704 return count;
3705}
3706
Takashi Iwai55e957d2005-11-17 14:52:13 +01003707static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708 snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count)
3709{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003710 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711 char *channel_buf;
3712
3713 snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
3714
3715 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
3716 snd_assert(channel_buf != NULL, return -EIO);
3717 if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
3718 return -EFAULT;
3719 return count;
3720}
3721
Takashi Iwai55e957d2005-11-17 14:52:13 +01003722static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723 snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
3724{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003725 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726 char *channel_buf;
3727
3728 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
3729 snd_assert(channel_buf != NULL, return -EIO);
3730 memset(channel_buf + pos * 4, 0, count * 4);
3731 return count;
3732}
3733
Takashi Iwai55e957d2005-11-17 14:52:13 +01003734static int snd_hdsp_reset(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003736 struct snd_pcm_runtime *runtime = substream->runtime;
3737 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
3738 struct snd_pcm_substream *other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3740 other = hdsp->capture_substream;
3741 else
3742 other = hdsp->playback_substream;
3743 if (hdsp->running)
3744 runtime->status->hw_ptr = hdsp_hw_pointer(hdsp);
3745 else
3746 runtime->status->hw_ptr = 0;
3747 if (other) {
3748 struct list_head *pos;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003749 struct snd_pcm_substream *s;
3750 struct snd_pcm_runtime *oruntime = other->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751 snd_pcm_group_for_each(pos, substream) {
3752 s = snd_pcm_group_substream_entry(pos);
3753 if (s == other) {
3754 oruntime->status->hw_ptr = runtime->status->hw_ptr;
3755 break;
3756 }
3757 }
3758 }
3759 return 0;
3760}
3761
Takashi Iwai55e957d2005-11-17 14:52:13 +01003762static int snd_hdsp_hw_params(struct snd_pcm_substream *substream,
3763 struct snd_pcm_hw_params *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003765 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003766 int err;
3767 pid_t this_pid;
3768 pid_t other_pid;
3769
Takashi Iwaib0b98112005-10-20 18:29:58 +02003770 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772
Takashi Iwaib0b98112005-10-20 18:29:58 +02003773 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775
3776 spin_lock_irq(&hdsp->lock);
3777
3778 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3779 hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
3780 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= hdsp->creg_spdif_stream);
3781 this_pid = hdsp->playback_pid;
3782 other_pid = hdsp->capture_pid;
3783 } else {
3784 this_pid = hdsp->capture_pid;
3785 other_pid = hdsp->playback_pid;
3786 }
3787
3788 if ((other_pid > 0) && (this_pid != other_pid)) {
3789
3790 /* The other stream is open, and not by the same
3791 task as this one. Make sure that the parameters
3792 that matter are the same.
3793 */
3794
3795 if (params_rate(params) != hdsp->system_sample_rate) {
3796 spin_unlock_irq(&hdsp->lock);
3797 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
3798 return -EBUSY;
3799 }
3800
3801 if (params_period_size(params) != hdsp->period_bytes / 4) {
3802 spin_unlock_irq(&hdsp->lock);
3803 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
3804 return -EBUSY;
3805 }
3806
3807 /* We're fine. */
3808
3809 spin_unlock_irq(&hdsp->lock);
3810 return 0;
3811
3812 } else {
3813 spin_unlock_irq(&hdsp->lock);
3814 }
3815
3816 /* how to make sure that the rate matches an externally-set one ?
3817 */
3818
3819 spin_lock_irq(&hdsp->lock);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003820 if (! hdsp->clock_source_locked) {
3821 if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) {
3822 spin_unlock_irq(&hdsp->lock);
3823 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
3824 return err;
3825 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826 }
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003827 spin_unlock_irq(&hdsp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828
3829 if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) {
3830 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
3831 return err;
3832 }
3833
3834 return 0;
3835}
3836
Takashi Iwai55e957d2005-11-17 14:52:13 +01003837static int snd_hdsp_channel_info(struct snd_pcm_substream *substream,
3838 struct snd_pcm_channel_info *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003840 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 int mapped_channel;
3842
3843 snd_assert(info->channel < hdsp->max_channels, return -EINVAL);
3844
Takashi Iwaib0b98112005-10-20 18:29:58 +02003845 if ((mapped_channel = hdsp->channel_map[info->channel]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847
3848 info->offset = mapped_channel * HDSP_CHANNEL_BUFFER_BYTES;
3849 info->first = 0;
3850 info->step = 32;
3851 return 0;
3852}
3853
Takashi Iwai55e957d2005-11-17 14:52:13 +01003854static int snd_hdsp_ioctl(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855 unsigned int cmd, void *arg)
3856{
3857 switch (cmd) {
3858 case SNDRV_PCM_IOCTL1_RESET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859 return snd_hdsp_reset(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Takashi Iwaib0b98112005-10-20 18:29:58 +02003861 return snd_hdsp_channel_info(substream, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862 default:
3863 break;
3864 }
3865
3866 return snd_pcm_lib_ioctl(substream, cmd, arg);
3867}
3868
Takashi Iwai55e957d2005-11-17 14:52:13 +01003869static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003871 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
3872 struct snd_pcm_substream *other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873 int running;
3874
Takashi Iwaib0b98112005-10-20 18:29:58 +02003875 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877
Takashi Iwai311e70a2006-09-06 12:13:37 +02003878 if (hdsp_check_for_firmware(hdsp, 0)) /* no auto-loading in trigger */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880
3881 spin_lock(&hdsp->lock);
3882 running = hdsp->running;
3883 switch (cmd) {
3884 case SNDRV_PCM_TRIGGER_START:
3885 running |= 1 << substream->stream;
3886 break;
3887 case SNDRV_PCM_TRIGGER_STOP:
3888 running &= ~(1 << substream->stream);
3889 break;
3890 default:
3891 snd_BUG();
3892 spin_unlock(&hdsp->lock);
3893 return -EINVAL;
3894 }
3895 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3896 other = hdsp->capture_substream;
3897 else
3898 other = hdsp->playback_substream;
3899
3900 if (other) {
3901 struct list_head *pos;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003902 struct snd_pcm_substream *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903 snd_pcm_group_for_each(pos, substream) {
3904 s = snd_pcm_group_substream_entry(pos);
3905 if (s == other) {
3906 snd_pcm_trigger_done(s, substream);
3907 if (cmd == SNDRV_PCM_TRIGGER_START)
3908 running |= 1 << s->stream;
3909 else
3910 running &= ~(1 << s->stream);
3911 goto _ok;
3912 }
3913 }
3914 if (cmd == SNDRV_PCM_TRIGGER_START) {
3915 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) &&
3916 substream->stream == SNDRV_PCM_STREAM_CAPTURE)
3917 hdsp_silence_playback(hdsp);
3918 } else {
3919 if (running &&
3920 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3921 hdsp_silence_playback(hdsp);
3922 }
3923 } else {
3924 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
3925 hdsp_silence_playback(hdsp);
3926 }
3927 _ok:
3928 snd_pcm_trigger_done(substream, substream);
3929 if (!hdsp->running && running)
3930 hdsp_start_audio(hdsp);
3931 else if (hdsp->running && !running)
3932 hdsp_stop_audio(hdsp);
3933 hdsp->running = running;
3934 spin_unlock(&hdsp->lock);
3935
3936 return 0;
3937}
3938
Takashi Iwai55e957d2005-11-17 14:52:13 +01003939static int snd_hdsp_prepare(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003941 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 int result = 0;
3943
Takashi Iwaib0b98112005-10-20 18:29:58 +02003944 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946
Takashi Iwaib0b98112005-10-20 18:29:58 +02003947 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949
3950 spin_lock_irq(&hdsp->lock);
3951 if (!hdsp->running)
3952 hdsp_reset_hw_pointer(hdsp);
3953 spin_unlock_irq(&hdsp->lock);
3954 return result;
3955}
3956
Takashi Iwai55e957d2005-11-17 14:52:13 +01003957static struct snd_pcm_hardware snd_hdsp_playback_subinfo =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958{
3959 .info = (SNDRV_PCM_INFO_MMAP |
3960 SNDRV_PCM_INFO_MMAP_VALID |
3961 SNDRV_PCM_INFO_NONINTERLEAVED |
3962 SNDRV_PCM_INFO_SYNC_START |
3963 SNDRV_PCM_INFO_DOUBLE),
3964#ifdef SNDRV_BIG_ENDIAN
3965 .formats = SNDRV_PCM_FMTBIT_S32_BE,
3966#else
3967 .formats = SNDRV_PCM_FMTBIT_S32_LE,
3968#endif
3969 .rates = (SNDRV_PCM_RATE_32000 |
3970 SNDRV_PCM_RATE_44100 |
3971 SNDRV_PCM_RATE_48000 |
3972 SNDRV_PCM_RATE_64000 |
3973 SNDRV_PCM_RATE_88200 |
3974 SNDRV_PCM_RATE_96000),
3975 .rate_min = 32000,
3976 .rate_max = 96000,
3977 .channels_min = 14,
3978 .channels_max = HDSP_MAX_CHANNELS,
3979 .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS,
3980 .period_bytes_min = (64 * 4) * 10,
3981 .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS,
3982 .periods_min = 2,
3983 .periods_max = 2,
3984 .fifo_size = 0
3985};
3986
Takashi Iwai55e957d2005-11-17 14:52:13 +01003987static struct snd_pcm_hardware snd_hdsp_capture_subinfo =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003988{
3989 .info = (SNDRV_PCM_INFO_MMAP |
3990 SNDRV_PCM_INFO_MMAP_VALID |
3991 SNDRV_PCM_INFO_NONINTERLEAVED |
3992 SNDRV_PCM_INFO_SYNC_START),
3993#ifdef SNDRV_BIG_ENDIAN
3994 .formats = SNDRV_PCM_FMTBIT_S32_BE,
3995#else
3996 .formats = SNDRV_PCM_FMTBIT_S32_LE,
3997#endif
3998 .rates = (SNDRV_PCM_RATE_32000 |
3999 SNDRV_PCM_RATE_44100 |
4000 SNDRV_PCM_RATE_48000 |
4001 SNDRV_PCM_RATE_64000 |
4002 SNDRV_PCM_RATE_88200 |
4003 SNDRV_PCM_RATE_96000),
4004 .rate_min = 32000,
4005 .rate_max = 96000,
4006 .channels_min = 14,
4007 .channels_max = HDSP_MAX_CHANNELS,
4008 .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS,
4009 .period_bytes_min = (64 * 4) * 10,
4010 .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS,
4011 .periods_min = 2,
4012 .periods_max = 2,
4013 .fifo_size = 0
4014};
4015
4016static unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
4017
Takashi Iwai55e957d2005-11-17 14:52:13 +01004018static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_period_sizes = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019 .count = ARRAY_SIZE(hdsp_period_sizes),
4020 .list = hdsp_period_sizes,
4021 .mask = 0
4022};
4023
4024static unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 };
4025
Takashi Iwai55e957d2005-11-17 14:52:13 +01004026static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_9632_sample_rates = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027 .count = ARRAY_SIZE(hdsp_9632_sample_rates),
4028 .list = hdsp_9632_sample_rates,
4029 .mask = 0
4030};
4031
Takashi Iwai55e957d2005-11-17 14:52:13 +01004032static int snd_hdsp_hw_rule_in_channels(struct snd_pcm_hw_params *params,
4033 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004035 struct hdsp *hdsp = rule->private;
4036 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037 if (hdsp->io_type == H9632) {
4038 unsigned int list[3];
4039 list[0] = hdsp->qs_in_channels;
4040 list[1] = hdsp->ds_in_channels;
4041 list[2] = hdsp->ss_in_channels;
4042 return snd_interval_list(c, 3, list, 0);
4043 } else {
4044 unsigned int list[2];
4045 list[0] = hdsp->ds_in_channels;
4046 list[1] = hdsp->ss_in_channels;
4047 return snd_interval_list(c, 2, list, 0);
4048 }
4049}
4050
Takashi Iwai55e957d2005-11-17 14:52:13 +01004051static int snd_hdsp_hw_rule_out_channels(struct snd_pcm_hw_params *params,
4052 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053{
4054 unsigned int list[3];
Takashi Iwai55e957d2005-11-17 14:52:13 +01004055 struct hdsp *hdsp = rule->private;
4056 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057 if (hdsp->io_type == H9632) {
4058 list[0] = hdsp->qs_out_channels;
4059 list[1] = hdsp->ds_out_channels;
4060 list[2] = hdsp->ss_out_channels;
4061 return snd_interval_list(c, 3, list, 0);
4062 } else {
4063 list[0] = hdsp->ds_out_channels;
4064 list[1] = hdsp->ss_out_channels;
4065 }
4066 return snd_interval_list(c, 2, list, 0);
4067}
4068
Takashi Iwai55e957d2005-11-17 14:52:13 +01004069static int snd_hdsp_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
4070 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004072 struct hdsp *hdsp = rule->private;
4073 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4074 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 if (r->min > 96000 && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004076 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077 .min = hdsp->qs_in_channels,
4078 .max = hdsp->qs_in_channels,
4079 .integer = 1,
4080 };
4081 return snd_interval_refine(c, &t);
4082 } else if (r->min > 48000 && r->max <= 96000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004083 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084 .min = hdsp->ds_in_channels,
4085 .max = hdsp->ds_in_channels,
4086 .integer = 1,
4087 };
4088 return snd_interval_refine(c, &t);
4089 } else if (r->max < 64000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004090 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091 .min = hdsp->ss_in_channels,
4092 .max = hdsp->ss_in_channels,
4093 .integer = 1,
4094 };
4095 return snd_interval_refine(c, &t);
4096 }
4097 return 0;
4098}
4099
Takashi Iwai55e957d2005-11-17 14:52:13 +01004100static int snd_hdsp_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
4101 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004103 struct hdsp *hdsp = rule->private;
4104 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4105 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 if (r->min > 96000 && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004107 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108 .min = hdsp->qs_out_channels,
4109 .max = hdsp->qs_out_channels,
4110 .integer = 1,
4111 };
4112 return snd_interval_refine(c, &t);
4113 } else if (r->min > 48000 && r->max <= 96000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004114 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115 .min = hdsp->ds_out_channels,
4116 .max = hdsp->ds_out_channels,
4117 .integer = 1,
4118 };
4119 return snd_interval_refine(c, &t);
4120 } else if (r->max < 64000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004121 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122 .min = hdsp->ss_out_channels,
4123 .max = hdsp->ss_out_channels,
4124 .integer = 1,
4125 };
4126 return snd_interval_refine(c, &t);
4127 }
4128 return 0;
4129}
4130
Takashi Iwai55e957d2005-11-17 14:52:13 +01004131static int snd_hdsp_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
4132 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004134 struct hdsp *hdsp = rule->private;
4135 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4136 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137 if (c->min >= hdsp->ss_out_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004138 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139 .min = 32000,
4140 .max = 48000,
4141 .integer = 1,
4142 };
4143 return snd_interval_refine(r, &t);
4144 } else if (c->max <= hdsp->qs_out_channels && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004145 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146 .min = 128000,
4147 .max = 192000,
4148 .integer = 1,
4149 };
4150 return snd_interval_refine(r, &t);
4151 } else if (c->max <= hdsp->ds_out_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004152 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153 .min = 64000,
4154 .max = 96000,
4155 .integer = 1,
4156 };
4157 return snd_interval_refine(r, &t);
4158 }
4159 return 0;
4160}
4161
Takashi Iwai55e957d2005-11-17 14:52:13 +01004162static int snd_hdsp_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
4163 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004165 struct hdsp *hdsp = rule->private;
4166 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4167 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168 if (c->min >= hdsp->ss_in_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004169 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170 .min = 32000,
4171 .max = 48000,
4172 .integer = 1,
4173 };
4174 return snd_interval_refine(r, &t);
4175 } else if (c->max <= hdsp->qs_in_channels && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004176 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177 .min = 128000,
4178 .max = 192000,
4179 .integer = 1,
4180 };
4181 return snd_interval_refine(r, &t);
4182 } else if (c->max <= hdsp->ds_in_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004183 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184 .min = 64000,
4185 .max = 96000,
4186 .integer = 1,
4187 };
4188 return snd_interval_refine(r, &t);
4189 }
4190 return 0;
4191}
4192
Takashi Iwai55e957d2005-11-17 14:52:13 +01004193static int snd_hdsp_playback_open(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004195 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4196 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197
Takashi Iwaib0b98112005-10-20 18:29:58 +02004198 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200
Takashi Iwaib0b98112005-10-20 18:29:58 +02004201 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203
4204 spin_lock_irq(&hdsp->lock);
4205
4206 snd_pcm_set_sync(substream);
4207
4208 runtime->hw = snd_hdsp_playback_subinfo;
4209 runtime->dma_area = hdsp->playback_buffer;
4210 runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
4211
4212 hdsp->playback_pid = current->pid;
4213 hdsp->playback_substream = substream;
4214
4215 spin_unlock_irq(&hdsp->lock);
4216
4217 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4218 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 +02004219 if (hdsp->clock_source_locked) {
4220 runtime->hw.rate_min = runtime->hw.rate_max = hdsp->system_sample_rate;
4221 } else if (hdsp->io_type == H9632) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222 runtime->hw.rate_max = 192000;
4223 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
4224 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates);
4225 }
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02004226 if (hdsp->io_type == H9632) {
4227 runtime->hw.channels_min = hdsp->qs_out_channels;
4228 runtime->hw.channels_max = hdsp->ss_out_channels;
4229 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230
4231 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4232 snd_hdsp_hw_rule_out_channels, hdsp,
4233 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4234 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4235 snd_hdsp_hw_rule_out_channels_rate, hdsp,
4236 SNDRV_PCM_HW_PARAM_RATE, -1);
4237 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4238 snd_hdsp_hw_rule_rate_out_channels, hdsp,
4239 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4240
4241 hdsp->creg_spdif_stream = hdsp->creg_spdif;
4242 hdsp->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
4243 snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
4244 SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id);
4245 return 0;
4246}
4247
Takashi Iwai55e957d2005-11-17 14:52:13 +01004248static int snd_hdsp_playback_release(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004250 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251
4252 spin_lock_irq(&hdsp->lock);
4253
4254 hdsp->playback_pid = -1;
4255 hdsp->playback_substream = NULL;
4256
4257 spin_unlock_irq(&hdsp->lock);
4258
4259 hdsp->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
4260 snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
4261 SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id);
4262 return 0;
4263}
4264
4265
Takashi Iwai55e957d2005-11-17 14:52:13 +01004266static int snd_hdsp_capture_open(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004268 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4269 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270
Takashi Iwaib0b98112005-10-20 18:29:58 +02004271 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273
Takashi Iwaib0b98112005-10-20 18:29:58 +02004274 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004275 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276
4277 spin_lock_irq(&hdsp->lock);
4278
4279 snd_pcm_set_sync(substream);
4280
4281 runtime->hw = snd_hdsp_capture_subinfo;
4282 runtime->dma_area = hdsp->capture_buffer;
4283 runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
4284
4285 hdsp->capture_pid = current->pid;
4286 hdsp->capture_substream = substream;
4287
4288 spin_unlock_irq(&hdsp->lock);
4289
4290 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4291 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes);
4292 if (hdsp->io_type == H9632) {
4293 runtime->hw.channels_min = hdsp->qs_in_channels;
4294 runtime->hw.channels_max = hdsp->ss_in_channels;
4295 runtime->hw.rate_max = 192000;
4296 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
4297 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates);
4298 }
4299 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4300 snd_hdsp_hw_rule_in_channels, hdsp,
4301 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4302 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4303 snd_hdsp_hw_rule_in_channels_rate, hdsp,
4304 SNDRV_PCM_HW_PARAM_RATE, -1);
4305 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4306 snd_hdsp_hw_rule_rate_in_channels, hdsp,
4307 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4308 return 0;
4309}
4310
Takashi Iwai55e957d2005-11-17 14:52:13 +01004311static int snd_hdsp_capture_release(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004313 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314
4315 spin_lock_irq(&hdsp->lock);
4316
4317 hdsp->capture_pid = -1;
4318 hdsp->capture_substream = NULL;
4319
4320 spin_unlock_irq(&hdsp->lock);
4321 return 0;
4322}
4323
Takashi Iwai55e957d2005-11-17 14:52:13 +01004324static int snd_hdsp_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325{
4326 /* we have nothing to initialize but the call is required */
4327 return 0;
4328}
4329
4330
4331/* helper functions for copying meter values */
4332static inline int copy_u32_le(void __user *dest, void __iomem *src)
4333{
4334 u32 val = readl(src);
4335 return copy_to_user(dest, &val, 4);
4336}
4337
4338static inline int copy_u64_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
4339{
4340 u32 rms_low, rms_high;
4341 u64 rms;
4342 rms_low = readl(src_low);
4343 rms_high = readl(src_high);
4344 rms = ((u64)rms_high << 32) | rms_low;
4345 return copy_to_user(dest, &rms, 8);
4346}
4347
4348static inline int copy_u48_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
4349{
4350 u32 rms_low, rms_high;
4351 u64 rms;
4352 rms_low = readl(src_low) & 0xffffff00;
4353 rms_high = readl(src_high) & 0xffffff00;
4354 rms = ((u64)rms_high << 32) | rms_low;
4355 return copy_to_user(dest, &rms, 8);
4356}
4357
Takashi Iwai55e957d2005-11-17 14:52:13 +01004358static int hdsp_9652_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359{
4360 int doublespeed = 0;
4361 int i, j, channels, ofs;
4362
4363 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
4364 doublespeed = 1;
4365 channels = doublespeed ? 14 : 26;
4366 for (i = 0, j = 0; i < 26; ++i) {
4367 if (doublespeed && (i & 4))
4368 continue;
4369 ofs = HDSP_9652_peakBase - j * 4;
4370 if (copy_u32_le(&peak_rms->input_peaks[i], hdsp->iobase + ofs))
4371 return -EFAULT;
4372 ofs -= channels * 4;
4373 if (copy_u32_le(&peak_rms->playback_peaks[i], hdsp->iobase + ofs))
4374 return -EFAULT;
4375 ofs -= channels * 4;
4376 if (copy_u32_le(&peak_rms->output_peaks[i], hdsp->iobase + ofs))
4377 return -EFAULT;
4378 ofs = HDSP_9652_rmsBase + j * 8;
4379 if (copy_u48_le(&peak_rms->input_rms[i], hdsp->iobase + ofs,
4380 hdsp->iobase + ofs + 4))
4381 return -EFAULT;
4382 ofs += channels * 8;
4383 if (copy_u48_le(&peak_rms->playback_rms[i], hdsp->iobase + ofs,
4384 hdsp->iobase + ofs + 4))
4385 return -EFAULT;
4386 ofs += channels * 8;
4387 if (copy_u48_le(&peak_rms->output_rms[i], hdsp->iobase + ofs,
4388 hdsp->iobase + ofs + 4))
4389 return -EFAULT;
4390 j++;
4391 }
4392 return 0;
4393}
4394
Takashi Iwai55e957d2005-11-17 14:52:13 +01004395static int hdsp_9632_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396{
4397 int i, j;
Takashi Iwai55e957d2005-11-17 14:52:13 +01004398 struct hdsp_9632_meters __iomem *m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399 int doublespeed = 0;
4400
4401 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
4402 doublespeed = 1;
Takashi Iwai55e957d2005-11-17 14:52:13 +01004403 m = (struct hdsp_9632_meters __iomem *)(hdsp->iobase+HDSP_9632_metersBase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004404 for (i = 0, j = 0; i < 16; ++i, ++j) {
4405 if (copy_u32_le(&peak_rms->input_peaks[i], &m->input_peak[j]))
4406 return -EFAULT;
4407 if (copy_u32_le(&peak_rms->playback_peaks[i], &m->playback_peak[j]))
4408 return -EFAULT;
4409 if (copy_u32_le(&peak_rms->output_peaks[i], &m->output_peak[j]))
4410 return -EFAULT;
4411 if (copy_u64_le(&peak_rms->input_rms[i], &m->input_rms_low[j],
4412 &m->input_rms_high[j]))
4413 return -EFAULT;
4414 if (copy_u64_le(&peak_rms->playback_rms[i], &m->playback_rms_low[j],
4415 &m->playback_rms_high[j]))
4416 return -EFAULT;
4417 if (copy_u64_le(&peak_rms->output_rms[i], &m->output_rms_low[j],
4418 &m->output_rms_high[j]))
4419 return -EFAULT;
4420 if (doublespeed && i == 3) i += 4;
4421 }
4422 return 0;
4423}
4424
Takashi Iwai55e957d2005-11-17 14:52:13 +01004425static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426{
4427 int i;
4428
4429 for (i = 0; i < 26; i++) {
4430 if (copy_u32_le(&peak_rms->playback_peaks[i],
4431 hdsp->iobase + HDSP_playbackPeakLevel + i * 4))
4432 return -EFAULT;
4433 if (copy_u32_le(&peak_rms->input_peaks[i],
4434 hdsp->iobase + HDSP_inputPeakLevel + i * 4))
4435 return -EFAULT;
4436 }
4437 for (i = 0; i < 28; i++) {
4438 if (copy_u32_le(&peak_rms->output_peaks[i],
4439 hdsp->iobase + HDSP_outputPeakLevel + i * 4))
4440 return -EFAULT;
4441 }
4442 for (i = 0; i < 26; ++i) {
4443 if (copy_u64_le(&peak_rms->playback_rms[i],
4444 hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4,
4445 hdsp->iobase + HDSP_playbackRmsLevel + i * 8))
4446 return -EFAULT;
4447 if (copy_u64_le(&peak_rms->input_rms[i],
4448 hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4,
4449 hdsp->iobase + HDSP_inputRmsLevel + i * 8))
4450 return -EFAULT;
4451 }
4452 return 0;
4453}
4454
Takashi Iwai55e957d2005-11-17 14:52:13 +01004455static 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 -07004456{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004457 struct hdsp *hdsp = (struct hdsp *)hw->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004458 void __user *argp = (void __user *)arg;
4459
4460 switch (cmd) {
4461 case SNDRV_HDSP_IOCTL_GET_PEAK_RMS: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004462 struct hdsp_peak_rms __user *peak_rms = (struct hdsp_peak_rms __user *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004463
4464 if (!(hdsp->state & HDSP_FirmwareLoaded)) {
4465 snd_printk(KERN_ERR "Hammerfall-DSP: firmware needs to be uploaded to the card.\n");
4466 return -EINVAL;
4467 }
4468
4469 switch (hdsp->io_type) {
4470 case H9652:
4471 return hdsp_9652_get_peak(hdsp, peak_rms);
4472 case H9632:
4473 return hdsp_9632_get_peak(hdsp, peak_rms);
4474 default:
4475 return hdsp_get_peak(hdsp, peak_rms);
4476 }
4477 }
4478 case SNDRV_HDSP_IOCTL_GET_CONFIG_INFO: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004479 struct hdsp_config_info info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480 unsigned long flags;
4481 int i;
4482
4483 if (!(hdsp->state & HDSP_FirmwareLoaded)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004484 snd_printk(KERN_ERR "Hammerfall-DSP: Firmware needs to be uploaded to the card.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485 return -EINVAL;
4486 }
4487 spin_lock_irqsave(&hdsp->lock, flags);
4488 info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp);
4489 info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02004490 if (hdsp->io_type != H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491 info.adatsync_sync_check = (unsigned char)hdsp_adatsync_sync_check(hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 info.spdif_sync_check = (unsigned char)hdsp_spdif_sync_check(hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02004493 for (i = 0; i < ((hdsp->io_type != Multiface && hdsp->io_type != H9632) ? 3 : 1); ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494 info.adat_sync_check[i] = (unsigned char)hdsp_adat_sync_check(hdsp, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004495 info.spdif_in = (unsigned char)hdsp_spdif_in(hdsp);
4496 info.spdif_out = (unsigned char)hdsp_spdif_out(hdsp);
4497 info.spdif_professional = (unsigned char)hdsp_spdif_professional(hdsp);
4498 info.spdif_emphasis = (unsigned char)hdsp_spdif_emphasis(hdsp);
4499 info.spdif_nonaudio = (unsigned char)hdsp_spdif_nonaudio(hdsp);
4500 info.spdif_sample_rate = hdsp_spdif_sample_rate(hdsp);
4501 info.system_sample_rate = hdsp->system_sample_rate;
4502 info.autosync_sample_rate = hdsp_external_sample_rate(hdsp);
4503 info.system_clock_mode = (unsigned char)hdsp_system_clock_mode(hdsp);
4504 info.clock_source = (unsigned char)hdsp_clock_source(hdsp);
4505 info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp);
4506 info.line_out = (unsigned char)hdsp_line_out(hdsp);
4507 if (hdsp->io_type == H9632) {
4508 info.da_gain = (unsigned char)hdsp_da_gain(hdsp);
4509 info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp);
4510 info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp);
4511 info.xlr_breakout_cable = (unsigned char)hdsp_xlr_breakout_cable(hdsp);
4512
4513 }
Takashi Iwaib0b98112005-10-20 18:29:58 +02004514 if (hdsp->io_type == H9632 || hdsp->io_type == H9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515 info.analog_extension_board = (unsigned char)hdsp_aeb(hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004516 spin_unlock_irqrestore(&hdsp->lock, flags);
4517 if (copy_to_user(argp, &info, sizeof(info)))
4518 return -EFAULT;
4519 break;
4520 }
4521 case SNDRV_HDSP_IOCTL_GET_9632_AEB: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004522 struct hdsp_9632_aeb h9632_aeb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004523
4524 if (hdsp->io_type != H9632) return -EINVAL;
4525 h9632_aeb.aebi = hdsp->ss_in_channels - H9632_SS_CHANNELS;
4526 h9632_aeb.aebo = hdsp->ss_out_channels - H9632_SS_CHANNELS;
4527 if (copy_to_user(argp, &h9632_aeb, sizeof(h9632_aeb)))
4528 return -EFAULT;
4529 break;
4530 }
4531 case SNDRV_HDSP_IOCTL_GET_VERSION: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004532 struct hdsp_version hdsp_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004533 int err;
4534
4535 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
4536 if (hdsp->io_type == Undefined) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004537 if ((err = hdsp_get_iobox_version(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004538 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004539 }
4540 hdsp_version.io_type = hdsp->io_type;
4541 hdsp_version.firmware_rev = hdsp->firmware_rev;
Takashi Iwaib0b98112005-10-20 18:29:58 +02004542 if ((err = copy_to_user(argp, &hdsp_version, sizeof(hdsp_version))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004543 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004544 break;
4545 }
4546 case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004547 struct hdsp_firmware __user *firmware;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004548 u32 __user *firmware_data;
4549 int err;
4550
4551 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
4552 /* SNDRV_HDSP_IOCTL_GET_VERSION must have been called */
4553 if (hdsp->io_type == Undefined) return -EINVAL;
4554
4555 if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded))
4556 return -EBUSY;
4557
Takashi Iwaib0b98112005-10-20 18:29:58 +02004558 snd_printk(KERN_INFO "Hammerfall-DSP: initializing firmware upload\n");
Takashi Iwai55e957d2005-11-17 14:52:13 +01004559 firmware = (struct hdsp_firmware __user *)argp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004560
Takashi Iwaib0b98112005-10-20 18:29:58 +02004561 if (get_user(firmware_data, &firmware->firmware_data))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004562 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004563
Takashi Iwaib0b98112005-10-20 18:29:58 +02004564 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004565 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566
Takashi Iwaib0b98112005-10-20 18:29:58 +02004567 if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004568 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004569
4570 hdsp->state |= HDSP_FirmwareCached;
4571
Takashi Iwaib0b98112005-10-20 18:29:58 +02004572 if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004573 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004574
4575 if (!(hdsp->state & HDSP_InitializationComplete)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004576 if ((err = snd_hdsp_enable_io(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004578
4579 snd_hdsp_initialize_channels(hdsp);
4580 snd_hdsp_initialize_midi_flush(hdsp);
4581
4582 if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004583 snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n");
4584 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004585 }
4586 }
4587 break;
4588 }
4589 case SNDRV_HDSP_IOCTL_GET_MIXER: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004590 struct hdsp_mixer __user *mixer = (struct hdsp_mixer __user *)argp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004591 if (copy_to_user(mixer->matrix, hdsp->mixer_matrix, sizeof(unsigned short)*HDSP_MATRIX_MIXER_SIZE))
4592 return -EFAULT;
4593 break;
4594 }
4595 default:
4596 return -EINVAL;
4597 }
4598 return 0;
4599}
4600
Takashi Iwai55e957d2005-11-17 14:52:13 +01004601static struct snd_pcm_ops snd_hdsp_playback_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004602 .open = snd_hdsp_playback_open,
4603 .close = snd_hdsp_playback_release,
4604 .ioctl = snd_hdsp_ioctl,
4605 .hw_params = snd_hdsp_hw_params,
4606 .prepare = snd_hdsp_prepare,
4607 .trigger = snd_hdsp_trigger,
4608 .pointer = snd_hdsp_hw_pointer,
4609 .copy = snd_hdsp_playback_copy,
4610 .silence = snd_hdsp_hw_silence,
4611};
4612
Takashi Iwai55e957d2005-11-17 14:52:13 +01004613static struct snd_pcm_ops snd_hdsp_capture_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004614 .open = snd_hdsp_capture_open,
4615 .close = snd_hdsp_capture_release,
4616 .ioctl = snd_hdsp_ioctl,
4617 .hw_params = snd_hdsp_hw_params,
4618 .prepare = snd_hdsp_prepare,
4619 .trigger = snd_hdsp_trigger,
4620 .pointer = snd_hdsp_hw_pointer,
4621 .copy = snd_hdsp_capture_copy,
4622};
4623
Takashi Iwai55e957d2005-11-17 14:52:13 +01004624static int __devinit snd_hdsp_create_hwdep(struct snd_card *card,
4625 struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004626{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004627 struct snd_hwdep *hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004628 int err;
4629
4630 if ((err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw)) < 0)
4631 return err;
4632
4633 hdsp->hwdep = hw;
4634 hw->private_data = hdsp;
4635 strcpy(hw->name, "HDSP hwdep interface");
4636
4637 hw->ops.open = snd_hdsp_hwdep_dummy_op;
4638 hw->ops.ioctl = snd_hdsp_hwdep_ioctl;
4639 hw->ops.release = snd_hdsp_hwdep_dummy_op;
4640
4641 return 0;
4642}
4643
Takashi Iwai55e957d2005-11-17 14:52:13 +01004644static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004645{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004646 struct snd_pcm *pcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004647 int err;
4648
4649 if ((err = snd_pcm_new(card, hdsp->card_name, 0, 1, 1, &pcm)) < 0)
4650 return err;
4651
4652 hdsp->pcm = pcm;
4653 pcm->private_data = hdsp;
4654 strcpy(pcm->name, hdsp->card_name);
4655
4656 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_hdsp_playback_ops);
4657 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_hdsp_capture_ops);
4658
4659 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
4660
4661 return 0;
4662}
4663
Takashi Iwai55e957d2005-11-17 14:52:13 +01004664static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004665{
4666 hdsp->control2_register |= HDSP_9652_ENABLE_MIXER;
4667 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
4668}
4669
Takashi Iwai55e957d2005-11-17 14:52:13 +01004670static int snd_hdsp_enable_io (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004671{
4672 int i;
4673
4674 if (hdsp_fifo_wait (hdsp, 0, 100)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004675 snd_printk(KERN_ERR "Hammerfall-DSP: enable_io fifo_wait failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004676 return -EIO;
4677 }
4678
4679 for (i = 0; i < hdsp->max_channels; ++i) {
4680 hdsp_write (hdsp, HDSP_inputEnable + (4 * i), 1);
4681 hdsp_write (hdsp, HDSP_outputEnable + (4 * i), 1);
4682 }
4683
4684 return 0;
4685}
4686
Takashi Iwai55e957d2005-11-17 14:52:13 +01004687static void snd_hdsp_initialize_channels(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004688{
4689 int status, aebi_channels, aebo_channels;
4690
4691 switch (hdsp->io_type) {
4692 case Digiface:
4693 hdsp->card_name = "RME Hammerfall DSP + Digiface";
4694 hdsp->ss_in_channels = hdsp->ss_out_channels = DIGIFACE_SS_CHANNELS;
4695 hdsp->ds_in_channels = hdsp->ds_out_channels = DIGIFACE_DS_CHANNELS;
4696 break;
4697
4698 case H9652:
4699 hdsp->card_name = "RME Hammerfall HDSP 9652";
4700 hdsp->ss_in_channels = hdsp->ss_out_channels = H9652_SS_CHANNELS;
4701 hdsp->ds_in_channels = hdsp->ds_out_channels = H9652_DS_CHANNELS;
4702 break;
4703
4704 case H9632:
4705 status = hdsp_read(hdsp, HDSP_statusRegister);
4706 /* HDSP_AEBx bits are low when AEB are connected */
4707 aebi_channels = (status & HDSP_AEBI) ? 0 : 4;
4708 aebo_channels = (status & HDSP_AEBO) ? 0 : 4;
4709 hdsp->card_name = "RME Hammerfall HDSP 9632";
4710 hdsp->ss_in_channels = H9632_SS_CHANNELS+aebi_channels;
4711 hdsp->ds_in_channels = H9632_DS_CHANNELS+aebi_channels;
4712 hdsp->qs_in_channels = H9632_QS_CHANNELS+aebi_channels;
4713 hdsp->ss_out_channels = H9632_SS_CHANNELS+aebo_channels;
4714 hdsp->ds_out_channels = H9632_DS_CHANNELS+aebo_channels;
4715 hdsp->qs_out_channels = H9632_QS_CHANNELS+aebo_channels;
4716 break;
4717
4718 case Multiface:
4719 hdsp->card_name = "RME Hammerfall DSP + Multiface";
4720 hdsp->ss_in_channels = hdsp->ss_out_channels = MULTIFACE_SS_CHANNELS;
4721 hdsp->ds_in_channels = hdsp->ds_out_channels = MULTIFACE_DS_CHANNELS;
4722 break;
4723
4724 default:
4725 /* should never get here */
4726 break;
4727 }
4728}
4729
Takashi Iwai55e957d2005-11-17 14:52:13 +01004730static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004731{
4732 snd_hdsp_flush_midi_input (hdsp, 0);
4733 snd_hdsp_flush_midi_input (hdsp, 1);
4734}
4735
Takashi Iwai55e957d2005-11-17 14:52:13 +01004736static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004737{
4738 int err;
4739
4740 if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004741 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating pcm interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004742 return err;
4743 }
4744
4745
4746 if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004747 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating first midi interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004748 return err;
4749 }
4750
4751 if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
4752 if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004753 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating second midi interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004754 return err;
4755 }
4756 }
4757
4758 if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004759 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating ctl interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004760 return err;
4761 }
4762
4763 snd_hdsp_proc_init(hdsp);
4764
4765 hdsp->system_sample_rate = -1;
4766 hdsp->playback_pid = -1;
4767 hdsp->capture_pid = -1;
4768 hdsp->capture_substream = NULL;
4769 hdsp->playback_substream = NULL;
4770
4771 if ((err = snd_hdsp_set_defaults(hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004772 snd_printk(KERN_ERR "Hammerfall-DSP: Error setting default values\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004773 return err;
4774 }
4775
4776 if (!(hdsp->state & HDSP_InitializationComplete)) {
Clemens Ladischb73c1c12005-09-02 08:49:21 +02004777 strcpy(card->shortname, "Hammerfall DSP");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004778 sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
4779 hdsp->port, hdsp->irq);
4780
4781 if ((err = snd_card_register(card)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004782 snd_printk(KERN_ERR "Hammerfall-DSP: error registering card\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004783 return err;
4784 }
4785 hdsp->state |= HDSP_InitializationComplete;
4786 }
4787
4788 return 0;
4789}
4790
4791#ifdef HDSP_FW_LOADER
4792/* load firmware via hotplug fw loader */
Takashi Iwai55e957d2005-11-17 14:52:13 +01004793static int __devinit hdsp_request_fw_loader(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004794{
4795 const char *fwfile;
4796 const struct firmware *fw;
4797 int err;
4798
4799 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
4800 return 0;
4801 if (hdsp->io_type == Undefined) {
4802 if ((err = hdsp_get_iobox_version(hdsp)) < 0)
4803 return err;
4804 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
4805 return 0;
4806 }
4807
4808 /* caution: max length of firmware filename is 30! */
4809 switch (hdsp->io_type) {
4810 case Multiface:
4811 if (hdsp->firmware_rev == 0xa)
4812 fwfile = "multiface_firmware.bin";
4813 else
4814 fwfile = "multiface_firmware_rev11.bin";
4815 break;
4816 case Digiface:
4817 if (hdsp->firmware_rev == 0xa)
4818 fwfile = "digiface_firmware.bin";
4819 else
4820 fwfile = "digiface_firmware_rev11.bin";
4821 break;
4822 default:
4823 snd_printk(KERN_ERR "Hammerfall-DSP: invalid io_type %d\n", hdsp->io_type);
4824 return -EINVAL;
4825 }
4826
4827 if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) {
4828 snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile);
4829 return -ENOENT;
4830 }
4831 if (fw->size < sizeof(hdsp->firmware_cache)) {
4832 snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n",
4833 (int)fw->size, (int)sizeof(hdsp->firmware_cache));
4834 release_firmware(fw);
4835 return -EINVAL;
4836 }
Thomas Charbonnel7679a032005-04-25 11:35:29 +02004837
Linus Torvalds1da177e2005-04-16 15:20:36 -07004838 memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache));
Thomas Charbonnel7679a032005-04-25 11:35:29 +02004839
Linus Torvalds1da177e2005-04-16 15:20:36 -07004840 release_firmware(fw);
4841
4842 hdsp->state |= HDSP_FirmwareCached;
4843
4844 if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
4845 return err;
4846
4847 if (!(hdsp->state & HDSP_InitializationComplete)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004848 if ((err = snd_hdsp_enable_io(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004849 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004850
4851 if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004852 snd_printk(KERN_ERR "Hammerfall-DSP: error creating hwdep device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004853 return err;
4854 }
4855 snd_hdsp_initialize_channels(hdsp);
4856 snd_hdsp_initialize_midi_flush(hdsp);
4857 if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004858 snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004859 return err;
4860 }
4861 }
4862 return 0;
4863}
4864#endif
4865
Takashi Iwai55e957d2005-11-17 14:52:13 +01004866static int __devinit snd_hdsp_create(struct snd_card *card,
4867 struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004868{
4869 struct pci_dev *pci = hdsp->pci;
4870 int err;
4871 int is_9652 = 0;
4872 int is_9632 = 0;
4873
4874 hdsp->irq = -1;
4875 hdsp->state = 0;
4876 hdsp->midi[0].rmidi = NULL;
4877 hdsp->midi[1].rmidi = NULL;
4878 hdsp->midi[0].input = NULL;
4879 hdsp->midi[1].input = NULL;
4880 hdsp->midi[0].output = NULL;
4881 hdsp->midi[1].output = NULL;
4882 hdsp->midi[0].pending = 0;
4883 hdsp->midi[1].pending = 0;
4884 spin_lock_init(&hdsp->midi[0].lock);
4885 spin_lock_init(&hdsp->midi[1].lock);
4886 hdsp->iobase = NULL;
4887 hdsp->control_register = 0;
4888 hdsp->control2_register = 0;
4889 hdsp->io_type = Undefined;
4890 hdsp->max_channels = 26;
4891
4892 hdsp->card = card;
4893
4894 spin_lock_init(&hdsp->lock);
4895
4896 tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp);
4897
4898 pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev);
4899 hdsp->firmware_rev &= 0xff;
4900
4901 /* From Martin Bjoernsen :
4902 "It is important that the card's latency timer register in
4903 the PCI configuration space is set to a value much larger
4904 than 0 by the computer's BIOS or the driver.
4905 The windows driver always sets this 8 bit register [...]
4906 to its maximum 255 to avoid problems with some computers."
4907 */
4908 pci_write_config_byte(hdsp->pci, PCI_LATENCY_TIMER, 0xFF);
4909
4910 strcpy(card->driver, "H-DSP");
4911 strcpy(card->mixername, "Xilinx FPGA");
4912
Takashi Iwaib0b98112005-10-20 18:29:58 +02004913 if (hdsp->firmware_rev < 0xa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004914 return -ENODEV;
Takashi Iwaib0b98112005-10-20 18:29:58 +02004915 else if (hdsp->firmware_rev < 0x64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004916 hdsp->card_name = "RME Hammerfall DSP";
Takashi Iwaib0b98112005-10-20 18:29:58 +02004917 else if (hdsp->firmware_rev < 0x96) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004918 hdsp->card_name = "RME HDSP 9652";
4919 is_9652 = 1;
4920 } else {
4921 hdsp->card_name = "RME HDSP 9632";
4922 hdsp->max_channels = 16;
4923 is_9632 = 1;
4924 }
4925
Takashi Iwaib0b98112005-10-20 18:29:58 +02004926 if ((err = pci_enable_device(pci)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004927 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004928
4929 pci_set_master(hdsp->pci);
4930
4931 if ((err = pci_request_regions(pci, "hdsp")) < 0)
4932 return err;
4933 hdsp->port = pci_resource_start(pci, 0);
4934 if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004935 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 -07004936 return -EBUSY;
4937 }
4938
Takashi Iwai437a5a42006-11-21 12:14:23 +01004939 if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_SHARED,
4940 "hdsp", hdsp)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004941 snd_printk(KERN_ERR "Hammerfall-DSP: unable to use IRQ %d\n", pci->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004942 return -EBUSY;
4943 }
4944
4945 hdsp->irq = pci->irq;
Remy Bruno176546a2006-10-16 12:32:53 +02004946 hdsp->precise_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004947 hdsp->use_midi_tasklet = 1;
4948
Takashi Iwaib0b98112005-10-20 18:29:58 +02004949 if ((err = snd_hdsp_initialize_memory(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004950 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004951
4952 if (!is_9652 && !is_9632) {
4953 /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */
Takashi Iwaib0b98112005-10-20 18:29:58 +02004954 ssleep(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004955
4956 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
4957#ifdef HDSP_FW_LOADER
Takashi Iwaib0b98112005-10-20 18:29:58 +02004958 if ((err = hdsp_request_fw_loader(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004959 /* we don't fail as this can happen
4960 if userspace is not ready for
4961 firmware upload
4962 */
Takashi Iwaib0b98112005-10-20 18:29:58 +02004963 snd_printk(KERN_ERR "Hammerfall-DSP: couldn't get firmware from userspace. try using hdsploader\n");
4964 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004965 /* init is complete, we return */
4966 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004967#endif
4968 /* no iobox connected, we defer initialization */
Takashi Iwaib0b98112005-10-20 18:29:58 +02004969 snd_printk(KERN_INFO "Hammerfall-DSP: card initialization pending : waiting for firmware\n");
4970 if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004971 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004972 return 0;
4973 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004974 snd_printk(KERN_INFO "Hammerfall-DSP: Firmware already present, initializing card.\n");
4975 if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004976 hdsp->io_type = Multiface;
Takashi Iwaib0b98112005-10-20 18:29:58 +02004977 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004978 hdsp->io_type = Digiface;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004979 }
4980 }
4981
Takashi Iwaib0b98112005-10-20 18:29:58 +02004982 if ((err = snd_hdsp_enable_io(hdsp)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004983 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004984
Takashi Iwaib0b98112005-10-20 18:29:58 +02004985 if (is_9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004986 hdsp->io_type = H9652;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004987
Takashi Iwaib0b98112005-10-20 18:29:58 +02004988 if (is_9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004989 hdsp->io_type = H9632;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004990
Takashi Iwaib0b98112005-10-20 18:29:58 +02004991 if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004992 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004993
4994 snd_hdsp_initialize_channels(hdsp);
4995 snd_hdsp_initialize_midi_flush(hdsp);
4996
4997 hdsp->state |= HDSP_FirmwareLoaded;
4998
Takashi Iwaib0b98112005-10-20 18:29:58 +02004999 if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005000 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005001
5002 return 0;
5003}
5004
Takashi Iwai55e957d2005-11-17 14:52:13 +01005005static int snd_hdsp_free(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005006{
5007 if (hdsp->port) {
5008 /* stop the audio, and cancel all interrupts */
5009 tasklet_kill(&hdsp->midi_tasklet);
5010 hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable);
5011 hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
5012 }
5013
5014 if (hdsp->irq >= 0)
5015 free_irq(hdsp->irq, (void *)hdsp);
5016
5017 snd_hdsp_free_buffers(hdsp);
5018
5019 if (hdsp->iobase)
5020 iounmap(hdsp->iobase);
5021
5022 if (hdsp->port)
5023 pci_release_regions(hdsp->pci);
5024
5025 pci_disable_device(hdsp->pci);
5026 return 0;
5027}
5028
Takashi Iwai55e957d2005-11-17 14:52:13 +01005029static void snd_hdsp_card_free(struct snd_card *card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005030{
Takashi Iwai55e957d2005-11-17 14:52:13 +01005031 struct hdsp *hdsp = (struct hdsp *) card->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005032
5033 if (hdsp)
5034 snd_hdsp_free(hdsp);
5035}
5036
5037static int __devinit snd_hdsp_probe(struct pci_dev *pci,
5038 const struct pci_device_id *pci_id)
5039{
5040 static int dev;
Takashi Iwai55e957d2005-11-17 14:52:13 +01005041 struct hdsp *hdsp;
5042 struct snd_card *card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005043 int err;
5044
5045 if (dev >= SNDRV_CARDS)
5046 return -ENODEV;
5047 if (!enable[dev]) {
5048 dev++;
5049 return -ENOENT;
5050 }
5051
Takashi Iwai55e957d2005-11-17 14:52:13 +01005052 if (!(card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005053 return -ENOMEM;
5054
Takashi Iwai55e957d2005-11-17 14:52:13 +01005055 hdsp = (struct hdsp *) card->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005056 card->private_free = snd_hdsp_card_free;
5057 hdsp->dev = dev;
5058 hdsp->pci = pci;
5059 snd_card_set_dev(card, &pci->dev);
5060
5061 if ((err = snd_hdsp_create(card, hdsp)) < 0) {
5062 snd_card_free(card);
5063 return err;
5064 }
5065
5066 strcpy(card->shortname, "Hammerfall DSP");
5067 sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
5068 hdsp->port, hdsp->irq);
5069
5070 if ((err = snd_card_register(card)) < 0) {
5071 snd_card_free(card);
5072 return err;
5073 }
5074 pci_set_drvdata(pci, card);
5075 dev++;
5076 return 0;
5077}
5078
5079static void __devexit snd_hdsp_remove(struct pci_dev *pci)
5080{
5081 snd_card_free(pci_get_drvdata(pci));
5082 pci_set_drvdata(pci, NULL);
5083}
5084
5085static struct pci_driver driver = {
5086 .name = "RME Hammerfall DSP",
5087 .id_table = snd_hdsp_ids,
5088 .probe = snd_hdsp_probe,
5089 .remove = __devexit_p(snd_hdsp_remove),
5090};
5091
5092static int __init alsa_card_hdsp_init(void)
5093{
Takashi Iwai01d25d42005-04-11 16:58:24 +02005094 return pci_register_driver(&driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005095}
5096
5097static void __exit alsa_card_hdsp_exit(void)
5098{
5099 pci_unregister_driver(&driver);
5100}
5101
5102module_init(alsa_card_hdsp_init)
5103module_exit(alsa_card_hdsp_exit)