blob: e5a52da77b85d89669cb2cc0c559579e36a9439f [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:
601 return (32 * out) + (16 + (in));
602 default:
603 return (52 * out) + (26 + (in));
604 }
605}
606
Takashi Iwai55e957d2005-11-17 14:52:13 +0100607static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608{
609 switch (hdsp->firmware_rev) {
610 case 0xa:
611 return (64 * out) + in;
612 case 0x96:
613 case 0x97:
614 return (32 * out) + in;
615 default:
616 return (52 * out) + in;
617 }
618}
619
Takashi Iwai55e957d2005-11-17 14:52:13 +0100620static void hdsp_write(struct hdsp *hdsp, int reg, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621{
622 writel(val, hdsp->iobase + reg);
623}
624
Takashi Iwai55e957d2005-11-17 14:52:13 +0100625static unsigned int hdsp_read(struct hdsp *hdsp, int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626{
627 return readl (hdsp->iobase + reg);
628}
629
Takashi Iwai55e957d2005-11-17 14:52:13 +0100630static int hdsp_check_for_iobox (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631{
632
633 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
634 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_ConfigError) {
635 snd_printk ("Hammerfall-DSP: no Digiface or Multiface connected!\n");
636 hdsp->state &= ~HDSP_FirmwareLoaded;
637 return -EIO;
638 }
639 return 0;
640
641}
642
Takashi Iwai55e957d2005-11-17 14:52:13 +0100643static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
645 int i;
646 unsigned long flags;
647
648 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
649
650 snd_printk ("Hammerfall-DSP: loading firmware\n");
651
652 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM);
653 hdsp_write (hdsp, HDSP_fifoData, 0);
654
655 if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
656 snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n");
657 return -EIO;
658 }
659
660 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
661
662 for (i = 0; i < 24413; ++i) {
663 hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]);
664 if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) {
665 snd_printk ("Hammerfall-DSP: timeout during firmware loading\n");
666 return -EIO;
667 }
668 }
669
Takashi Iwaib0b98112005-10-20 18:29:58 +0200670 ssleep(3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671
672 if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
673 snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n");
674 return -EIO;
675 }
676
677#ifdef SNDRV_BIG_ENDIAN
678 hdsp->control2_register = HDSP_BIGENDIAN_MODE;
679#else
680 hdsp->control2_register = 0;
681#endif
682 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
683 snd_printk ("Hammerfall-DSP: finished firmware loading\n");
684
685 }
686 if (hdsp->state & HDSP_InitializationComplete) {
Takashi Iwaib0b98112005-10-20 18:29:58 +0200687 snd_printk(KERN_INFO "Hammerfall-DSP: firmware loaded from cache, restoring defaults\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 spin_lock_irqsave(&hdsp->lock, flags);
689 snd_hdsp_set_defaults(hdsp);
690 spin_unlock_irqrestore(&hdsp->lock, flags);
691 }
692
693 hdsp->state |= HDSP_FirmwareLoaded;
694
695 return 0;
696}
697
Takashi Iwai55e957d2005-11-17 14:52:13 +0100698static int hdsp_get_iobox_version (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699{
700 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
701
702 hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM);
703 hdsp_write (hdsp, HDSP_fifoData, 0);
Takashi Iwaib0b98112005-10-20 18:29:58 +0200704 if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
707 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
708 hdsp_write (hdsp, HDSP_fifoData, 0);
709
710 if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT)) {
711 hdsp->io_type = Multiface;
712 hdsp_write (hdsp, HDSP_control2Reg, HDSP_VERSION_BIT);
713 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
714 hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT);
715 } else {
716 hdsp->io_type = Digiface;
717 }
718 } else {
719 /* firmware was already loaded, get iobox type */
Takashi Iwaib0b98112005-10-20 18:29:58 +0200720 if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 hdsp->io_type = Multiface;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200722 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 hdsp->io_type = Digiface;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 }
725 return 0;
726}
727
728
Takashi Iwai55e957d2005-11-17 14:52:13 +0100729static int hdsp_check_for_firmware (struct hdsp *hdsp, int show_err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730{
731 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
732 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +0200733 snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 hdsp->state &= ~HDSP_FirmwareLoaded;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200735 if (! show_err)
736 return -EIO;
737 /* try to load firmware */
738 if (hdsp->state & HDSP_FirmwareCached) {
739 if (snd_hdsp_load_firmware_from_cache(hdsp) != 0)
740 snd_printk(KERN_ERR "Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n");
741 } else {
742 snd_printk(KERN_ERR "Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n");
743 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 return -EIO;
745 }
746 return 0;
747}
748
749
Takashi Iwai55e957d2005-11-17 14:52:13 +0100750static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751{
752 int i;
753
754 /* the fifoStatus registers reports on how many words
755 are available in the command FIFO.
756 */
757
758 for (i = 0; i < timeout; i++) {
759
760 if ((int)(hdsp_read (hdsp, HDSP_fifoStatus) & 0xff) <= count)
761 return 0;
762
763 /* not very friendly, but we only do this during a firmware
764 load and changing the mixer, so we just put up with it.
765 */
766
767 udelay (100);
768 }
769
770 snd_printk ("Hammerfall-DSP: wait for FIFO status <= %d failed after %d iterations\n",
771 count, timeout);
772 return -1;
773}
774
Takashi Iwai55e957d2005-11-17 14:52:13 +0100775static int hdsp_read_gain (struct hdsp *hdsp, unsigned int addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776{
Takashi Iwaib0b98112005-10-20 18:29:58 +0200777 if (addr >= HDSP_MATRIX_MIXER_SIZE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200779
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 return hdsp->mixer_matrix[addr];
781}
782
Takashi Iwai55e957d2005-11-17 14:52:13 +0100783static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784{
785 unsigned int ad;
786
787 if (addr >= HDSP_MATRIX_MIXER_SIZE)
788 return -1;
789
790 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) {
791
792 /* from martin bjornsen:
793
794 "You can only write dwords to the
795 mixer memory which contain two
796 mixer values in the low and high
797 word. So if you want to change
798 value 0 you have to read value 1
799 from the cache and write both to
800 the first dword in the mixer
801 memory."
802 */
803
Takashi Iwaib0b98112005-10-20 18:29:58 +0200804 if (hdsp->io_type == H9632 && addr >= 512)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806
Takashi Iwaib0b98112005-10-20 18:29:58 +0200807 if (hdsp->io_type == H9652 && addr >= 1352)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809
810 hdsp->mixer_matrix[addr] = data;
811
812
813 /* `addr' addresses a 16-bit wide address, but
814 the address space accessed via hdsp_write
815 uses byte offsets. put another way, addr
816 varies from 0 to 1351, but to access the
817 corresponding memory location, we need
818 to access 0 to 2703 ...
819 */
820 ad = addr/2;
821
822 hdsp_write (hdsp, 4096 + (ad*4),
823 (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) +
824 hdsp->mixer_matrix[addr&0x7fe]);
825
826 return 0;
827
828 } else {
829
830 ad = (addr << 16) + data;
831
Takashi Iwaib0b98112005-10-20 18:29:58 +0200832 if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834
835 hdsp_write (hdsp, HDSP_fifoData, ad);
836 hdsp->mixer_matrix[addr] = data;
837
838 }
839
840 return 0;
841}
842
Takashi Iwai55e957d2005-11-17 14:52:13 +0100843static int snd_hdsp_use_is_exclusive(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844{
845 unsigned long flags;
846 int ret = 1;
847
848 spin_lock_irqsave(&hdsp->lock, flags);
849 if ((hdsp->playback_pid != hdsp->capture_pid) &&
Takashi Iwaib0b98112005-10-20 18:29:58 +0200850 (hdsp->playback_pid >= 0) && (hdsp->capture_pid >= 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 spin_unlock_irqrestore(&hdsp->lock, flags);
853 return ret;
854}
855
Takashi Iwai55e957d2005-11-17 14:52:13 +0100856static int hdsp_external_sample_rate (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857{
858 unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
859 unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
860
861 switch (rate_bits) {
862 case HDSP_systemFrequency32: return 32000;
863 case HDSP_systemFrequency44_1: return 44100;
864 case HDSP_systemFrequency48: return 48000;
865 case HDSP_systemFrequency64: return 64000;
866 case HDSP_systemFrequency88_2: return 88200;
867 case HDSP_systemFrequency96: return 96000;
868 default:
869 return 0;
870 }
871}
872
Takashi Iwai55e957d2005-11-17 14:52:13 +0100873static int hdsp_spdif_sample_rate(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874{
875 unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);
876 unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);
877
Takashi Iwaib0b98112005-10-20 18:29:58 +0200878 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880
881 switch (rate_bits) {
882 case HDSP_spdifFrequency32KHz: return 32000;
883 case HDSP_spdifFrequency44_1KHz: return 44100;
884 case HDSP_spdifFrequency48KHz: return 48000;
885 case HDSP_spdifFrequency64KHz: return 64000;
886 case HDSP_spdifFrequency88_2KHz: return 88200;
887 case HDSP_spdifFrequency96KHz: return 96000;
888 case HDSP_spdifFrequency128KHz:
889 if (hdsp->io_type == H9632) return 128000;
890 break;
891 case HDSP_spdifFrequency176_4KHz:
892 if (hdsp->io_type == H9632) return 176400;
893 break;
894 case HDSP_spdifFrequency192KHz:
895 if (hdsp->io_type == H9632) return 192000;
896 break;
897 default:
898 break;
899 }
900 snd_printk ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status);
901 return 0;
902}
903
Takashi Iwai55e957d2005-11-17 14:52:13 +0100904static void hdsp_compute_period_size(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905{
906 hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));
907}
908
Takashi Iwai55e957d2005-11-17 14:52:13 +0100909static snd_pcm_uframes_t hdsp_hw_pointer(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910{
911 int position;
912
913 position = hdsp_read(hdsp, HDSP_statusRegister);
914
Takashi Iwaib0b98112005-10-20 18:29:58 +0200915 if (!hdsp->precise_ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 return (position & HDSP_BufferID) ? (hdsp->period_bytes / 4) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917
918 position &= HDSP_BufferPositionMask;
919 position /= 4;
920 position &= (hdsp->period_bytes/2) - 1;
921 return position;
922}
923
Takashi Iwai55e957d2005-11-17 14:52:13 +0100924static void hdsp_reset_hw_pointer(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925{
926 hdsp_write (hdsp, HDSP_resetPointer, 0);
927}
928
Takashi Iwai55e957d2005-11-17 14:52:13 +0100929static void hdsp_start_audio(struct hdsp *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930{
931 s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start);
932 hdsp_write(s, HDSP_controlRegister, s->control_register);
933}
934
Takashi Iwai55e957d2005-11-17 14:52:13 +0100935static void hdsp_stop_audio(struct hdsp *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936{
937 s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable);
938 hdsp_write(s, HDSP_controlRegister, s->control_register);
939}
940
Takashi Iwai55e957d2005-11-17 14:52:13 +0100941static void hdsp_silence_playback(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942{
943 memset(hdsp->playback_buffer, 0, HDSP_DMA_AREA_BYTES);
944}
945
Takashi Iwai55e957d2005-11-17 14:52:13 +0100946static int hdsp_set_interrupt_interval(struct hdsp *s, unsigned int frames)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947{
948 int n;
949
950 spin_lock_irq(&s->lock);
951
952 frames >>= 7;
953 n = 0;
954 while (frames) {
955 n++;
956 frames >>= 1;
957 }
958
959 s->control_register &= ~HDSP_LatencyMask;
960 s->control_register |= hdsp_encode_latency(n);
961
962 hdsp_write(s, HDSP_controlRegister, s->control_register);
963
964 hdsp_compute_period_size(s);
965
966 spin_unlock_irq(&s->lock);
967
968 return 0;
969}
970
Takashi Iwai55e957d2005-11-17 14:52:13 +0100971static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972{
973 int reject_if_open = 0;
974 int current_rate;
975 int rate_bits;
976
977 /* ASSUMPTION: hdsp->lock is either held, or
978 there is no need for it (e.g. during module
979 initialization).
980 */
981
982 if (!(hdsp->control_register & HDSP_ClockModeMaster)) {
983 if (called_internally) {
984 /* request from ctl or card initialization */
Takashi Iwaib0b98112005-10-20 18:29:58 +0200985 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 -0700986 return -1;
987 } else {
988 /* hw_param request while in AutoSync mode */
989 int external_freq = hdsp_external_sample_rate(hdsp);
990 int spdif_freq = hdsp_spdif_sample_rate(hdsp);
991
Takashi Iwaib0b98112005-10-20 18:29:58 +0200992 if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1))
993 snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in double speed mode\n");
994 else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1))
995 snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in quad speed mode\n");
996 else if (rate != external_freq) {
997 snd_printk(KERN_INFO "Hammerfall-DSP: No AutoSync source for requested rate\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 return -1;
999 }
1000 }
1001 }
1002
1003 current_rate = hdsp->system_sample_rate;
1004
1005 /* Changing from a "single speed" to a "double speed" rate is
1006 not allowed if any substreams are open. This is because
1007 such a change causes a shift in the location of
1008 the DMA buffers and a reduction in the number of available
1009 buffers.
1010
1011 Note that a similar but essentially insoluble problem
1012 exists for externally-driven rate changes. All we can do
1013 is to flag rate changes in the read/write routines. */
1014
Takashi Iwaib0b98112005-10-20 18:29:58 +02001015 if (rate > 96000 && hdsp->io_type != H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017
1018 switch (rate) {
1019 case 32000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001020 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 rate_bits = HDSP_Frequency32KHz;
1023 break;
1024 case 44100:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001025 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 rate_bits = HDSP_Frequency44_1KHz;
1028 break;
1029 case 48000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001030 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 rate_bits = HDSP_Frequency48KHz;
1033 break;
1034 case 64000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001035 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 rate_bits = HDSP_Frequency64KHz;
1038 break;
1039 case 88200:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001040 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 rate_bits = HDSP_Frequency88_2KHz;
1043 break;
1044 case 96000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001045 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 rate_bits = HDSP_Frequency96KHz;
1048 break;
1049 case 128000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001050 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 rate_bits = HDSP_Frequency128KHz;
1053 break;
1054 case 176400:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001055 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 rate_bits = HDSP_Frequency176_4KHz;
1058 break;
1059 case 192000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001060 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 rate_bits = HDSP_Frequency192KHz;
1063 break;
1064 default:
1065 return -EINVAL;
1066 }
1067
1068 if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) {
1069 snd_printk ("Hammerfall-DSP: cannot change speed mode (capture PID = %d, playback PID = %d)\n",
1070 hdsp->capture_pid,
1071 hdsp->playback_pid);
1072 return -EBUSY;
1073 }
1074
1075 hdsp->control_register &= ~HDSP_FrequencyMask;
1076 hdsp->control_register |= rate_bits;
1077 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1078
1079 if (rate >= 128000) {
1080 hdsp->channel_map = channel_map_H9632_qs;
1081 } else if (rate > 48000) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001082 if (hdsp->io_type == H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 hdsp->channel_map = channel_map_H9632_ds;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001084 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 hdsp->channel_map = channel_map_ds;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 } else {
1087 switch (hdsp->io_type) {
1088 case Multiface:
1089 hdsp->channel_map = channel_map_mf_ss;
1090 break;
1091 case Digiface:
1092 case H9652:
1093 hdsp->channel_map = channel_map_df_ss;
1094 break;
1095 case H9632:
1096 hdsp->channel_map = channel_map_H9632_ss;
1097 break;
1098 default:
1099 /* should never happen */
1100 break;
1101 }
1102 }
1103
1104 hdsp->system_sample_rate = rate;
1105
1106 return 0;
1107}
1108
1109/*----------------------------------------------------------------------------
1110 MIDI
1111 ----------------------------------------------------------------------------*/
1112
Takashi Iwai55e957d2005-11-17 14:52:13 +01001113static unsigned char snd_hdsp_midi_read_byte (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114{
1115 /* the hardware already does the relevant bit-mask with 0xff */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001116 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 return hdsp_read(hdsp, HDSP_midiDataIn1);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001118 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 return hdsp_read(hdsp, HDSP_midiDataIn0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120}
1121
Takashi Iwai55e957d2005-11-17 14:52:13 +01001122static void snd_hdsp_midi_write_byte (struct hdsp *hdsp, int id, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123{
1124 /* the hardware already does the relevant bit-mask with 0xff */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001125 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 hdsp_write(hdsp, HDSP_midiDataOut1, val);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001127 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 hdsp_write(hdsp, HDSP_midiDataOut0, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129}
1130
Takashi Iwai55e957d2005-11-17 14:52:13 +01001131static int snd_hdsp_midi_input_available (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001133 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 return (hdsp_read(hdsp, HDSP_midiStatusIn1) & 0xff);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001135 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 return (hdsp_read(hdsp, HDSP_midiStatusIn0) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137}
1138
Takashi Iwai55e957d2005-11-17 14:52:13 +01001139static int snd_hdsp_midi_output_possible (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140{
1141 int fifo_bytes_used;
1142
Takashi Iwaib0b98112005-10-20 18:29:58 +02001143 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut1) & 0xff;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001145 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut0) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147
Takashi Iwaib0b98112005-10-20 18:29:58 +02001148 if (fifo_bytes_used < 128)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 return 128 - fifo_bytes_used;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001150 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152}
1153
Takashi Iwai55e957d2005-11-17 14:52:13 +01001154static void snd_hdsp_flush_midi_input (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001156 while (snd_hdsp_midi_input_available (hdsp, id))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 snd_hdsp_midi_read_byte (hdsp, id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158}
1159
Takashi Iwai55e957d2005-11-17 14:52:13 +01001160static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161{
1162 unsigned long flags;
1163 int n_pending;
1164 int to_write;
1165 int i;
1166 unsigned char buf[128];
1167
1168 /* Output is not interrupt driven */
1169
1170 spin_lock_irqsave (&hmidi->lock, flags);
1171 if (hmidi->output) {
1172 if (!snd_rawmidi_transmit_empty (hmidi->output)) {
1173 if ((n_pending = snd_hdsp_midi_output_possible (hmidi->hdsp, hmidi->id)) > 0) {
1174 if (n_pending > (int)sizeof (buf))
1175 n_pending = sizeof (buf);
1176
1177 if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {
1178 for (i = 0; i < to_write; ++i)
1179 snd_hdsp_midi_write_byte (hmidi->hdsp, hmidi->id, buf[i]);
1180 }
1181 }
1182 }
1183 }
1184 spin_unlock_irqrestore (&hmidi->lock, flags);
1185 return 0;
1186}
1187
Takashi Iwai55e957d2005-11-17 14:52:13 +01001188static int snd_hdsp_midi_input_read (struct hdsp_midi *hmidi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189{
1190 unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
1191 unsigned long flags;
1192 int n_pending;
1193 int i;
1194
1195 spin_lock_irqsave (&hmidi->lock, flags);
1196 if ((n_pending = snd_hdsp_midi_input_available (hmidi->hdsp, hmidi->id)) > 0) {
1197 if (hmidi->input) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001198 if (n_pending > (int)sizeof (buf))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 n_pending = sizeof (buf);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001200 for (i = 0; i < n_pending; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 buf[i] = snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001202 if (n_pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 snd_rawmidi_receive (hmidi->input, buf, n_pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 } else {
1205 /* flush the MIDI input FIFO */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001206 while (--n_pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 }
1209 }
1210 hmidi->pending = 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001211 if (hmidi->id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 hmidi->hdsp->control_register |= HDSP_Midi1InterruptEnable;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001213 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 hmidi->hdsp->control_register |= HDSP_Midi0InterruptEnable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 hdsp_write(hmidi->hdsp, HDSP_controlRegister, hmidi->hdsp->control_register);
1216 spin_unlock_irqrestore (&hmidi->lock, flags);
1217 return snd_hdsp_midi_output_write (hmidi);
1218}
1219
Takashi Iwai55e957d2005-11-17 14:52:13 +01001220static void snd_hdsp_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001222 struct hdsp *hdsp;
1223 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 unsigned long flags;
1225 u32 ie;
1226
Takashi Iwai55e957d2005-11-17 14:52:13 +01001227 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 hdsp = hmidi->hdsp;
1229 ie = hmidi->id ? HDSP_Midi1InterruptEnable : HDSP_Midi0InterruptEnable;
1230 spin_lock_irqsave (&hdsp->lock, flags);
1231 if (up) {
1232 if (!(hdsp->control_register & ie)) {
1233 snd_hdsp_flush_midi_input (hdsp, hmidi->id);
1234 hdsp->control_register |= ie;
1235 }
1236 } else {
1237 hdsp->control_register &= ~ie;
1238 tasklet_kill(&hdsp->midi_tasklet);
1239 }
1240
1241 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1242 spin_unlock_irqrestore (&hdsp->lock, flags);
1243}
1244
1245static void snd_hdsp_midi_output_timer(unsigned long data)
1246{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001247 struct hdsp_midi *hmidi = (struct hdsp_midi *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 unsigned long flags;
1249
1250 snd_hdsp_midi_output_write(hmidi);
1251 spin_lock_irqsave (&hmidi->lock, flags);
1252
1253 /* this does not bump hmidi->istimer, because the
1254 kernel automatically removed the timer when it
1255 expired, and we are now adding it back, thus
1256 leaving istimer wherever it was set before.
1257 */
1258
1259 if (hmidi->istimer) {
1260 hmidi->timer.expires = 1 + jiffies;
1261 add_timer(&hmidi->timer);
1262 }
1263
1264 spin_unlock_irqrestore (&hmidi->lock, flags);
1265}
1266
Takashi Iwai55e957d2005-11-17 14:52:13 +01001267static void snd_hdsp_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001269 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 unsigned long flags;
1271
Takashi Iwai55e957d2005-11-17 14:52:13 +01001272 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 spin_lock_irqsave (&hmidi->lock, flags);
1274 if (up) {
1275 if (!hmidi->istimer) {
1276 init_timer(&hmidi->timer);
1277 hmidi->timer.function = snd_hdsp_midi_output_timer;
1278 hmidi->timer.data = (unsigned long) hmidi;
1279 hmidi->timer.expires = 1 + jiffies;
1280 add_timer(&hmidi->timer);
1281 hmidi->istimer++;
1282 }
1283 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001284 if (hmidi->istimer && --hmidi->istimer <= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 del_timer (&hmidi->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 }
1287 spin_unlock_irqrestore (&hmidi->lock, flags);
1288 if (up)
1289 snd_hdsp_midi_output_write(hmidi);
1290}
1291
Takashi Iwai55e957d2005-11-17 14:52:13 +01001292static int snd_hdsp_midi_input_open(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001294 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
Takashi Iwai55e957d2005-11-17 14:52:13 +01001296 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 spin_lock_irq (&hmidi->lock);
1298 snd_hdsp_flush_midi_input (hmidi->hdsp, hmidi->id);
1299 hmidi->input = substream;
1300 spin_unlock_irq (&hmidi->lock);
1301
1302 return 0;
1303}
1304
Takashi Iwai55e957d2005-11-17 14:52:13 +01001305static int snd_hdsp_midi_output_open(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001307 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308
Takashi Iwai55e957d2005-11-17 14:52:13 +01001309 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 spin_lock_irq (&hmidi->lock);
1311 hmidi->output = substream;
1312 spin_unlock_irq (&hmidi->lock);
1313
1314 return 0;
1315}
1316
Takashi Iwai55e957d2005-11-17 14:52:13 +01001317static int snd_hdsp_midi_input_close(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001319 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320
1321 snd_hdsp_midi_input_trigger (substream, 0);
1322
Takashi Iwai55e957d2005-11-17 14:52:13 +01001323 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 spin_lock_irq (&hmidi->lock);
1325 hmidi->input = NULL;
1326 spin_unlock_irq (&hmidi->lock);
1327
1328 return 0;
1329}
1330
Takashi Iwai55e957d2005-11-17 14:52:13 +01001331static int snd_hdsp_midi_output_close(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001333 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
1335 snd_hdsp_midi_output_trigger (substream, 0);
1336
Takashi Iwai55e957d2005-11-17 14:52:13 +01001337 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 spin_lock_irq (&hmidi->lock);
1339 hmidi->output = NULL;
1340 spin_unlock_irq (&hmidi->lock);
1341
1342 return 0;
1343}
1344
Takashi Iwai55e957d2005-11-17 14:52:13 +01001345static struct snd_rawmidi_ops snd_hdsp_midi_output =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346{
1347 .open = snd_hdsp_midi_output_open,
1348 .close = snd_hdsp_midi_output_close,
1349 .trigger = snd_hdsp_midi_output_trigger,
1350};
1351
Takashi Iwai55e957d2005-11-17 14:52:13 +01001352static struct snd_rawmidi_ops snd_hdsp_midi_input =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353{
1354 .open = snd_hdsp_midi_input_open,
1355 .close = snd_hdsp_midi_input_close,
1356 .trigger = snd_hdsp_midi_input_trigger,
1357};
1358
Takashi Iwaif40b6892006-07-05 16:51:05 +02001359static int snd_hdsp_create_midi (struct snd_card *card, struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360{
1361 char buf[32];
1362
1363 hdsp->midi[id].id = id;
1364 hdsp->midi[id].rmidi = NULL;
1365 hdsp->midi[id].input = NULL;
1366 hdsp->midi[id].output = NULL;
1367 hdsp->midi[id].hdsp = hdsp;
1368 hdsp->midi[id].istimer = 0;
1369 hdsp->midi[id].pending = 0;
1370 spin_lock_init (&hdsp->midi[id].lock);
1371
1372 sprintf (buf, "%s MIDI %d", card->shortname, id+1);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001373 if (snd_rawmidi_new (card, buf, id, 1, 1, &hdsp->midi[id].rmidi) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
1376 sprintf (hdsp->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);
1377 hdsp->midi[id].rmidi->private_data = &hdsp->midi[id];
1378
1379 snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdsp_midi_output);
1380 snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdsp_midi_input);
1381
1382 hdsp->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
1383 SNDRV_RAWMIDI_INFO_INPUT |
1384 SNDRV_RAWMIDI_INFO_DUPLEX;
1385
1386 return 0;
1387}
1388
1389/*-----------------------------------------------------------------------------
1390 Control Interface
1391 ----------------------------------------------------------------------------*/
1392
Takashi Iwai55e957d2005-11-17 14:52:13 +01001393static u32 snd_hdsp_convert_from_aes(struct snd_aes_iec958 *aes)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394{
1395 u32 val = 0;
1396 val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? HDSP_SPDIFProfessional : 0;
1397 val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? HDSP_SPDIFNonAudio : 0;
1398 if (val & HDSP_SPDIFProfessional)
1399 val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0;
1400 else
1401 val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0;
1402 return val;
1403}
1404
Takashi Iwai55e957d2005-11-17 14:52:13 +01001405static void snd_hdsp_convert_to_aes(struct snd_aes_iec958 *aes, u32 val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406{
1407 aes->status[0] = ((val & HDSP_SPDIFProfessional) ? IEC958_AES0_PROFESSIONAL : 0) |
1408 ((val & HDSP_SPDIFNonAudio) ? IEC958_AES0_NONAUDIO : 0);
1409 if (val & HDSP_SPDIFProfessional)
1410 aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0;
1411 else
1412 aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_CON_EMPHASIS_5015 : 0;
1413}
1414
Takashi Iwai55e957d2005-11-17 14:52:13 +01001415static int snd_hdsp_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416{
1417 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1418 uinfo->count = 1;
1419 return 0;
1420}
1421
Takashi Iwai55e957d2005-11-17 14:52:13 +01001422static int snd_hdsp_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001424 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425
1426 snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif);
1427 return 0;
1428}
1429
Takashi Iwai55e957d2005-11-17 14:52:13 +01001430static int snd_hdsp_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001432 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 int change;
1434 u32 val;
1435
1436 val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
1437 spin_lock_irq(&hdsp->lock);
1438 change = val != hdsp->creg_spdif;
1439 hdsp->creg_spdif = val;
1440 spin_unlock_irq(&hdsp->lock);
1441 return change;
1442}
1443
Takashi Iwai55e957d2005-11-17 14:52:13 +01001444static int snd_hdsp_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445{
1446 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1447 uinfo->count = 1;
1448 return 0;
1449}
1450
Takashi Iwai55e957d2005-11-17 14:52:13 +01001451static int snd_hdsp_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001453 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454
1455 snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream);
1456 return 0;
1457}
1458
Takashi Iwai55e957d2005-11-17 14:52:13 +01001459static int snd_hdsp_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001461 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 int change;
1463 u32 val;
1464
1465 val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
1466 spin_lock_irq(&hdsp->lock);
1467 change = val != hdsp->creg_spdif_stream;
1468 hdsp->creg_spdif_stream = val;
1469 hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
1470 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= val);
1471 spin_unlock_irq(&hdsp->lock);
1472 return change;
1473}
1474
Takashi Iwai55e957d2005-11-17 14:52:13 +01001475static int snd_hdsp_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476{
1477 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1478 uinfo->count = 1;
1479 return 0;
1480}
1481
Takashi Iwai55e957d2005-11-17 14:52:13 +01001482static int snd_hdsp_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483{
1484 ucontrol->value.iec958.status[0] = kcontrol->private_value;
1485 return 0;
1486}
1487
1488#define HDSP_SPDIF_IN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001489{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 .name = xname, \
1491 .index = xindex, \
1492 .info = snd_hdsp_info_spdif_in, \
1493 .get = snd_hdsp_get_spdif_in, \
1494 .put = snd_hdsp_put_spdif_in }
1495
Takashi Iwai55e957d2005-11-17 14:52:13 +01001496static unsigned int hdsp_spdif_in(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497{
1498 return hdsp_decode_spdif_in(hdsp->control_register & HDSP_SPDIFInputMask);
1499}
1500
Takashi Iwai55e957d2005-11-17 14:52:13 +01001501static int hdsp_set_spdif_input(struct hdsp *hdsp, int in)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502{
1503 hdsp->control_register &= ~HDSP_SPDIFInputMask;
1504 hdsp->control_register |= hdsp_encode_spdif_in(in);
1505 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1506 return 0;
1507}
1508
Takashi Iwai55e957d2005-11-17 14:52:13 +01001509static int snd_hdsp_info_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510{
1511 static char *texts[4] = {"Optical", "Coaxial", "Internal", "AES"};
Takashi Iwai55e957d2005-11-17 14:52:13 +01001512 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513
1514 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1515 uinfo->count = 1;
1516 uinfo->value.enumerated.items = ((hdsp->io_type == H9632) ? 4 : 3);
1517 if (uinfo->value.enumerated.item > ((hdsp->io_type == H9632) ? 3 : 2))
1518 uinfo->value.enumerated.item = ((hdsp->io_type == H9632) ? 3 : 2);
1519 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1520 return 0;
1521}
1522
Takashi Iwai55e957d2005-11-17 14:52:13 +01001523static int snd_hdsp_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001525 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526
1527 ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp);
1528 return 0;
1529}
1530
Takashi Iwai55e957d2005-11-17 14:52:13 +01001531static int snd_hdsp_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001533 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 int change;
1535 unsigned int val;
1536
1537 if (!snd_hdsp_use_is_exclusive(hdsp))
1538 return -EBUSY;
1539 val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3);
1540 spin_lock_irq(&hdsp->lock);
1541 change = val != hdsp_spdif_in(hdsp);
1542 if (change)
1543 hdsp_set_spdif_input(hdsp, val);
1544 spin_unlock_irq(&hdsp->lock);
1545 return change;
1546}
1547
1548#define HDSP_SPDIF_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001549{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 .info = snd_hdsp_info_spdif_bits, \
1551 .get = snd_hdsp_get_spdif_out, .put = snd_hdsp_put_spdif_out }
1552
Takashi Iwai55e957d2005-11-17 14:52:13 +01001553static int hdsp_spdif_out(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554{
1555 return (hdsp->control_register & HDSP_SPDIFOpticalOut) ? 1 : 0;
1556}
1557
Takashi Iwai55e957d2005-11-17 14:52:13 +01001558static int hdsp_set_spdif_output(struct hdsp *hdsp, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001560 if (out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 hdsp->control_register |= HDSP_SPDIFOpticalOut;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001562 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 hdsp->control_register &= ~HDSP_SPDIFOpticalOut;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1565 return 0;
1566}
1567
Takashi Iwai55e957d2005-11-17 14:52:13 +01001568static int snd_hdsp_info_spdif_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569{
1570 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1571 uinfo->count = 1;
1572 uinfo->value.integer.min = 0;
1573 uinfo->value.integer.max = 1;
1574 return 0;
1575}
1576
Takashi Iwai55e957d2005-11-17 14:52:13 +01001577static int snd_hdsp_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001579 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580
1581 ucontrol->value.integer.value[0] = hdsp_spdif_out(hdsp);
1582 return 0;
1583}
1584
Takashi Iwai55e957d2005-11-17 14:52:13 +01001585static int snd_hdsp_put_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001587 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 int change;
1589 unsigned int val;
1590
1591 if (!snd_hdsp_use_is_exclusive(hdsp))
1592 return -EBUSY;
1593 val = ucontrol->value.integer.value[0] & 1;
1594 spin_lock_irq(&hdsp->lock);
1595 change = (int)val != hdsp_spdif_out(hdsp);
1596 hdsp_set_spdif_output(hdsp, val);
1597 spin_unlock_irq(&hdsp->lock);
1598 return change;
1599}
1600
1601#define HDSP_SPDIF_PROFESSIONAL(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001602{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 .info = snd_hdsp_info_spdif_bits, \
1604 .get = snd_hdsp_get_spdif_professional, .put = snd_hdsp_put_spdif_professional }
1605
Takashi Iwai55e957d2005-11-17 14:52:13 +01001606static int hdsp_spdif_professional(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607{
1608 return (hdsp->control_register & HDSP_SPDIFProfessional) ? 1 : 0;
1609}
1610
Takashi Iwai55e957d2005-11-17 14:52:13 +01001611static int hdsp_set_spdif_professional(struct hdsp *hdsp, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001613 if (val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 hdsp->control_register |= HDSP_SPDIFProfessional;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001615 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 hdsp->control_register &= ~HDSP_SPDIFProfessional;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1618 return 0;
1619}
1620
Takashi Iwai55e957d2005-11-17 14:52:13 +01001621static int snd_hdsp_get_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001623 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624
1625 ucontrol->value.integer.value[0] = hdsp_spdif_professional(hdsp);
1626 return 0;
1627}
1628
Takashi Iwai55e957d2005-11-17 14:52:13 +01001629static int snd_hdsp_put_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001631 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 int change;
1633 unsigned int val;
1634
1635 if (!snd_hdsp_use_is_exclusive(hdsp))
1636 return -EBUSY;
1637 val = ucontrol->value.integer.value[0] & 1;
1638 spin_lock_irq(&hdsp->lock);
1639 change = (int)val != hdsp_spdif_professional(hdsp);
1640 hdsp_set_spdif_professional(hdsp, val);
1641 spin_unlock_irq(&hdsp->lock);
1642 return change;
1643}
1644
1645#define HDSP_SPDIF_EMPHASIS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001646{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 .info = snd_hdsp_info_spdif_bits, \
1648 .get = snd_hdsp_get_spdif_emphasis, .put = snd_hdsp_put_spdif_emphasis }
1649
Takashi Iwai55e957d2005-11-17 14:52:13 +01001650static int hdsp_spdif_emphasis(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651{
1652 return (hdsp->control_register & HDSP_SPDIFEmphasis) ? 1 : 0;
1653}
1654
Takashi Iwai55e957d2005-11-17 14:52:13 +01001655static int hdsp_set_spdif_emphasis(struct hdsp *hdsp, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001657 if (val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 hdsp->control_register |= HDSP_SPDIFEmphasis;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001659 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 hdsp->control_register &= ~HDSP_SPDIFEmphasis;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1662 return 0;
1663}
1664
Takashi Iwai55e957d2005-11-17 14:52:13 +01001665static int snd_hdsp_get_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001667 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668
1669 ucontrol->value.integer.value[0] = hdsp_spdif_emphasis(hdsp);
1670 return 0;
1671}
1672
Takashi Iwai55e957d2005-11-17 14:52:13 +01001673static int snd_hdsp_put_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001675 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 int change;
1677 unsigned int val;
1678
1679 if (!snd_hdsp_use_is_exclusive(hdsp))
1680 return -EBUSY;
1681 val = ucontrol->value.integer.value[0] & 1;
1682 spin_lock_irq(&hdsp->lock);
1683 change = (int)val != hdsp_spdif_emphasis(hdsp);
1684 hdsp_set_spdif_emphasis(hdsp, val);
1685 spin_unlock_irq(&hdsp->lock);
1686 return change;
1687}
1688
1689#define HDSP_SPDIF_NON_AUDIO(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001690{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 .info = snd_hdsp_info_spdif_bits, \
1692 .get = snd_hdsp_get_spdif_nonaudio, .put = snd_hdsp_put_spdif_nonaudio }
1693
Takashi Iwai55e957d2005-11-17 14:52:13 +01001694static int hdsp_spdif_nonaudio(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695{
1696 return (hdsp->control_register & HDSP_SPDIFNonAudio) ? 1 : 0;
1697}
1698
Takashi Iwai55e957d2005-11-17 14:52:13 +01001699static int hdsp_set_spdif_nonaudio(struct hdsp *hdsp, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001701 if (val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 hdsp->control_register |= HDSP_SPDIFNonAudio;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001703 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 hdsp->control_register &= ~HDSP_SPDIFNonAudio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1706 return 0;
1707}
1708
Takashi Iwai55e957d2005-11-17 14:52:13 +01001709static int snd_hdsp_get_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001711 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712
1713 ucontrol->value.integer.value[0] = hdsp_spdif_nonaudio(hdsp);
1714 return 0;
1715}
1716
Takashi Iwai55e957d2005-11-17 14:52:13 +01001717static int snd_hdsp_put_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001719 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 int change;
1721 unsigned int val;
1722
1723 if (!snd_hdsp_use_is_exclusive(hdsp))
1724 return -EBUSY;
1725 val = ucontrol->value.integer.value[0] & 1;
1726 spin_lock_irq(&hdsp->lock);
1727 change = (int)val != hdsp_spdif_nonaudio(hdsp);
1728 hdsp_set_spdif_nonaudio(hdsp, val);
1729 spin_unlock_irq(&hdsp->lock);
1730 return change;
1731}
1732
1733#define HDSP_SPDIF_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001734{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 .name = xname, \
1736 .index = xindex, \
1737 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1738 .info = snd_hdsp_info_spdif_sample_rate, \
1739 .get = snd_hdsp_get_spdif_sample_rate \
1740}
1741
Takashi Iwai55e957d2005-11-17 14:52:13 +01001742static int snd_hdsp_info_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743{
1744 static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
Takashi Iwai55e957d2005-11-17 14:52:13 +01001745 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746
1747 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1748 uinfo->count = 1;
1749 uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7;
1750 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1751 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1752 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1753 return 0;
1754}
1755
Takashi Iwai55e957d2005-11-17 14:52:13 +01001756static int snd_hdsp_get_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001758 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759
1760 switch (hdsp_spdif_sample_rate(hdsp)) {
1761 case 32000:
1762 ucontrol->value.enumerated.item[0] = 0;
1763 break;
1764 case 44100:
1765 ucontrol->value.enumerated.item[0] = 1;
1766 break;
1767 case 48000:
1768 ucontrol->value.enumerated.item[0] = 2;
1769 break;
1770 case 64000:
1771 ucontrol->value.enumerated.item[0] = 3;
1772 break;
1773 case 88200:
1774 ucontrol->value.enumerated.item[0] = 4;
1775 break;
1776 case 96000:
1777 ucontrol->value.enumerated.item[0] = 5;
1778 break;
1779 case 128000:
1780 ucontrol->value.enumerated.item[0] = 7;
1781 break;
1782 case 176400:
1783 ucontrol->value.enumerated.item[0] = 8;
1784 break;
1785 case 192000:
1786 ucontrol->value.enumerated.item[0] = 9;
1787 break;
1788 default:
1789 ucontrol->value.enumerated.item[0] = 6;
1790 }
1791 return 0;
1792}
1793
1794#define HDSP_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001795{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 .name = xname, \
1797 .index = xindex, \
1798 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1799 .info = snd_hdsp_info_system_sample_rate, \
1800 .get = snd_hdsp_get_system_sample_rate \
1801}
1802
Takashi Iwai55e957d2005-11-17 14:52:13 +01001803static int snd_hdsp_info_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804{
1805 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1806 uinfo->count = 1;
1807 return 0;
1808}
1809
Takashi Iwai55e957d2005-11-17 14:52:13 +01001810static int snd_hdsp_get_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001812 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813
1814 ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate;
1815 return 0;
1816}
1817
1818#define HDSP_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001819{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 .name = xname, \
1821 .index = xindex, \
1822 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1823 .info = snd_hdsp_info_autosync_sample_rate, \
1824 .get = snd_hdsp_get_autosync_sample_rate \
1825}
1826
Takashi Iwai55e957d2005-11-17 14:52:13 +01001827static int snd_hdsp_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001829 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
1831 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1832 uinfo->count = 1;
1833 uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7 ;
1834 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1835 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1836 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1837 return 0;
1838}
1839
Takashi Iwai55e957d2005-11-17 14:52:13 +01001840static int snd_hdsp_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001842 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843
1844 switch (hdsp_external_sample_rate(hdsp)) {
1845 case 32000:
1846 ucontrol->value.enumerated.item[0] = 0;
1847 break;
1848 case 44100:
1849 ucontrol->value.enumerated.item[0] = 1;
1850 break;
1851 case 48000:
1852 ucontrol->value.enumerated.item[0] = 2;
1853 break;
1854 case 64000:
1855 ucontrol->value.enumerated.item[0] = 3;
1856 break;
1857 case 88200:
1858 ucontrol->value.enumerated.item[0] = 4;
1859 break;
1860 case 96000:
1861 ucontrol->value.enumerated.item[0] = 5;
1862 break;
1863 case 128000:
1864 ucontrol->value.enumerated.item[0] = 7;
1865 break;
1866 case 176400:
1867 ucontrol->value.enumerated.item[0] = 8;
1868 break;
1869 case 192000:
1870 ucontrol->value.enumerated.item[0] = 9;
1871 break;
1872 default:
1873 ucontrol->value.enumerated.item[0] = 6;
1874 }
1875 return 0;
1876}
1877
1878#define HDSP_SYSTEM_CLOCK_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001879{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 .name = xname, \
1881 .index = xindex, \
1882 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1883 .info = snd_hdsp_info_system_clock_mode, \
1884 .get = snd_hdsp_get_system_clock_mode \
1885}
1886
Takashi Iwai55e957d2005-11-17 14:52:13 +01001887static int hdsp_system_clock_mode(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001889 if (hdsp->control_register & HDSP_ClockModeMaster)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001891 else if (hdsp_external_sample_rate(hdsp) != hdsp->system_sample_rate)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 return 1;
1894}
1895
Takashi Iwai55e957d2005-11-17 14:52:13 +01001896static int snd_hdsp_info_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897{
1898 static char *texts[] = {"Master", "Slave" };
1899
1900 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1901 uinfo->count = 1;
1902 uinfo->value.enumerated.items = 2;
1903 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1904 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1905 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1906 return 0;
1907}
1908
Takashi Iwai55e957d2005-11-17 14:52:13 +01001909static int snd_hdsp_get_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001911 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912
1913 ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp);
1914 return 0;
1915}
1916
1917#define HDSP_CLOCK_SOURCE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001918{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 .name = xname, \
1920 .index = xindex, \
1921 .info = snd_hdsp_info_clock_source, \
1922 .get = snd_hdsp_get_clock_source, \
1923 .put = snd_hdsp_put_clock_source \
1924}
1925
Takashi Iwai55e957d2005-11-17 14:52:13 +01001926static int hdsp_clock_source(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927{
1928 if (hdsp->control_register & HDSP_ClockModeMaster) {
1929 switch (hdsp->system_sample_rate) {
1930 case 32000:
1931 return 1;
1932 case 44100:
1933 return 2;
1934 case 48000:
1935 return 3;
1936 case 64000:
1937 return 4;
1938 case 88200:
1939 return 5;
1940 case 96000:
1941 return 6;
1942 case 128000:
1943 return 7;
1944 case 176400:
1945 return 8;
1946 case 192000:
1947 return 9;
1948 default:
1949 return 3;
1950 }
1951 } else {
1952 return 0;
1953 }
1954}
1955
Takashi Iwai55e957d2005-11-17 14:52:13 +01001956static int hdsp_set_clock_source(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001957{
1958 int rate;
1959 switch (mode) {
1960 case HDSP_CLOCK_SOURCE_AUTOSYNC:
1961 if (hdsp_external_sample_rate(hdsp) != 0) {
1962 if (!hdsp_set_rate(hdsp, hdsp_external_sample_rate(hdsp), 1)) {
1963 hdsp->control_register &= ~HDSP_ClockModeMaster;
1964 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1965 return 0;
1966 }
1967 }
1968 return -1;
1969 case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ:
1970 rate = 32000;
1971 break;
1972 case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ:
1973 rate = 44100;
1974 break;
1975 case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ:
1976 rate = 48000;
1977 break;
1978 case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ:
1979 rate = 64000;
1980 break;
1981 case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ:
1982 rate = 88200;
1983 break;
1984 case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ:
1985 rate = 96000;
1986 break;
1987 case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ:
1988 rate = 128000;
1989 break;
1990 case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ:
1991 rate = 176400;
1992 break;
1993 case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ:
1994 rate = 192000;
1995 break;
1996 default:
1997 rate = 48000;
1998 }
1999 hdsp->control_register |= HDSP_ClockModeMaster;
2000 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2001 hdsp_set_rate(hdsp, rate, 1);
2002 return 0;
2003}
2004
Takashi Iwai55e957d2005-11-17 14:52:13 +01002005static int snd_hdsp_info_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006{
2007 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 +01002008 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009
2010 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2011 uinfo->count = 1;
2012 if (hdsp->io_type == H9632)
2013 uinfo->value.enumerated.items = 10;
2014 else
2015 uinfo->value.enumerated.items = 7;
2016 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2017 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2018 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2019 return 0;
2020}
2021
Takashi Iwai55e957d2005-11-17 14:52:13 +01002022static int snd_hdsp_get_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002024 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025
2026 ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp);
2027 return 0;
2028}
2029
Takashi Iwai55e957d2005-11-17 14:52:13 +01002030static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002032 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 int change;
2034 int val;
2035
2036 if (!snd_hdsp_use_is_exclusive(hdsp))
2037 return -EBUSY;
2038 val = ucontrol->value.enumerated.item[0];
2039 if (val < 0) val = 0;
2040 if (hdsp->io_type == H9632) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002041 if (val > 9)
2042 val = 9;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002044 if (val > 6)
2045 val = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 }
2047 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002048 if (val != hdsp_clock_source(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049 change = (hdsp_set_clock_source(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002050 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 spin_unlock_irq(&hdsp->lock);
2053 return change;
2054}
2055
Takashi Iwai55e957d2005-11-17 14:52:13 +01002056static int snd_hdsp_info_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002057{
2058 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2059 uinfo->count = 1;
2060 uinfo->value.integer.min = 0;
2061 uinfo->value.integer.max = 1;
2062 return 0;
2063}
2064
Takashi Iwai55e957d2005-11-17 14:52:13 +01002065static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002066{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002067 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002068
2069 ucontrol->value.integer.value[0] = hdsp->clock_source_locked;
2070 return 0;
2071}
2072
Takashi Iwai55e957d2005-11-17 14:52:13 +01002073static int snd_hdsp_put_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002074{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002075 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002076 int change;
2077
2078 change = (int)ucontrol->value.integer.value[0] != hdsp->clock_source_locked;
2079 if (change)
2080 hdsp->clock_source_locked = ucontrol->value.integer.value[0];
2081 return change;
2082}
2083
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084#define HDSP_DA_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002085{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 .name = xname, \
2087 .index = xindex, \
2088 .info = snd_hdsp_info_da_gain, \
2089 .get = snd_hdsp_get_da_gain, \
2090 .put = snd_hdsp_put_da_gain \
2091}
2092
Takashi Iwai55e957d2005-11-17 14:52:13 +01002093static int hdsp_da_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094{
2095 switch (hdsp->control_register & HDSP_DAGainMask) {
2096 case HDSP_DAGainHighGain:
2097 return 0;
2098 case HDSP_DAGainPlus4dBu:
2099 return 1;
2100 case HDSP_DAGainMinus10dBV:
2101 return 2;
2102 default:
2103 return 1;
2104 }
2105}
2106
Takashi Iwai55e957d2005-11-17 14:52:13 +01002107static int hdsp_set_da_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108{
2109 hdsp->control_register &= ~HDSP_DAGainMask;
2110 switch (mode) {
2111 case 0:
2112 hdsp->control_register |= HDSP_DAGainHighGain;
2113 break;
2114 case 1:
2115 hdsp->control_register |= HDSP_DAGainPlus4dBu;
2116 break;
2117 case 2:
2118 hdsp->control_register |= HDSP_DAGainMinus10dBV;
2119 break;
2120 default:
2121 return -1;
2122
2123 }
2124 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2125 return 0;
2126}
2127
Takashi Iwai55e957d2005-11-17 14:52:13 +01002128static int snd_hdsp_info_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129{
2130 static char *texts[] = {"Hi Gain", "+4 dBu", "-10 dbV"};
2131
2132 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2133 uinfo->count = 1;
2134 uinfo->value.enumerated.items = 3;
2135 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2136 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2137 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2138 return 0;
2139}
2140
Takashi Iwai55e957d2005-11-17 14:52:13 +01002141static int snd_hdsp_get_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002143 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144
2145 ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp);
2146 return 0;
2147}
2148
Takashi Iwai55e957d2005-11-17 14:52:13 +01002149static int snd_hdsp_put_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002151 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 int change;
2153 int val;
2154
2155 if (!snd_hdsp_use_is_exclusive(hdsp))
2156 return -EBUSY;
2157 val = ucontrol->value.enumerated.item[0];
2158 if (val < 0) val = 0;
2159 if (val > 2) val = 2;
2160 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002161 if (val != hdsp_da_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 change = (hdsp_set_da_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002163 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 spin_unlock_irq(&hdsp->lock);
2166 return change;
2167}
2168
2169#define HDSP_AD_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002170{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 .name = xname, \
2172 .index = xindex, \
2173 .info = snd_hdsp_info_ad_gain, \
2174 .get = snd_hdsp_get_ad_gain, \
2175 .put = snd_hdsp_put_ad_gain \
2176}
2177
Takashi Iwai55e957d2005-11-17 14:52:13 +01002178static int hdsp_ad_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179{
2180 switch (hdsp->control_register & HDSP_ADGainMask) {
2181 case HDSP_ADGainMinus10dBV:
2182 return 0;
2183 case HDSP_ADGainPlus4dBu:
2184 return 1;
2185 case HDSP_ADGainLowGain:
2186 return 2;
2187 default:
2188 return 1;
2189 }
2190}
2191
Takashi Iwai55e957d2005-11-17 14:52:13 +01002192static int hdsp_set_ad_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193{
2194 hdsp->control_register &= ~HDSP_ADGainMask;
2195 switch (mode) {
2196 case 0:
2197 hdsp->control_register |= HDSP_ADGainMinus10dBV;
2198 break;
2199 case 1:
2200 hdsp->control_register |= HDSP_ADGainPlus4dBu;
2201 break;
2202 case 2:
2203 hdsp->control_register |= HDSP_ADGainLowGain;
2204 break;
2205 default:
2206 return -1;
2207
2208 }
2209 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2210 return 0;
2211}
2212
Takashi Iwai55e957d2005-11-17 14:52:13 +01002213static int snd_hdsp_info_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214{
2215 static char *texts[] = {"-10 dBV", "+4 dBu", "Lo Gain"};
2216
2217 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2218 uinfo->count = 1;
2219 uinfo->value.enumerated.items = 3;
2220 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2221 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2222 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2223 return 0;
2224}
2225
Takashi Iwai55e957d2005-11-17 14:52:13 +01002226static int snd_hdsp_get_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002228 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229
2230 ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp);
2231 return 0;
2232}
2233
Takashi Iwai55e957d2005-11-17 14:52:13 +01002234static int snd_hdsp_put_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002236 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 int change;
2238 int val;
2239
2240 if (!snd_hdsp_use_is_exclusive(hdsp))
2241 return -EBUSY;
2242 val = ucontrol->value.enumerated.item[0];
2243 if (val < 0) val = 0;
2244 if (val > 2) val = 2;
2245 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002246 if (val != hdsp_ad_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 change = (hdsp_set_ad_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002248 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 spin_unlock_irq(&hdsp->lock);
2251 return change;
2252}
2253
2254#define HDSP_PHONE_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002255{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 .name = xname, \
2257 .index = xindex, \
2258 .info = snd_hdsp_info_phone_gain, \
2259 .get = snd_hdsp_get_phone_gain, \
2260 .put = snd_hdsp_put_phone_gain \
2261}
2262
Takashi Iwai55e957d2005-11-17 14:52:13 +01002263static int hdsp_phone_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264{
2265 switch (hdsp->control_register & HDSP_PhoneGainMask) {
2266 case HDSP_PhoneGain0dB:
2267 return 0;
2268 case HDSP_PhoneGainMinus6dB:
2269 return 1;
2270 case HDSP_PhoneGainMinus12dB:
2271 return 2;
2272 default:
2273 return 0;
2274 }
2275}
2276
Takashi Iwai55e957d2005-11-17 14:52:13 +01002277static int hdsp_set_phone_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278{
2279 hdsp->control_register &= ~HDSP_PhoneGainMask;
2280 switch (mode) {
2281 case 0:
2282 hdsp->control_register |= HDSP_PhoneGain0dB;
2283 break;
2284 case 1:
2285 hdsp->control_register |= HDSP_PhoneGainMinus6dB;
2286 break;
2287 case 2:
2288 hdsp->control_register |= HDSP_PhoneGainMinus12dB;
2289 break;
2290 default:
2291 return -1;
2292
2293 }
2294 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2295 return 0;
2296}
2297
Takashi Iwai55e957d2005-11-17 14:52:13 +01002298static int snd_hdsp_info_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299{
2300 static char *texts[] = {"0 dB", "-6 dB", "-12 dB"};
2301
2302 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2303 uinfo->count = 1;
2304 uinfo->value.enumerated.items = 3;
2305 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2306 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2307 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2308 return 0;
2309}
2310
Takashi Iwai55e957d2005-11-17 14:52:13 +01002311static int snd_hdsp_get_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002313 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314
2315 ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp);
2316 return 0;
2317}
2318
Takashi Iwai55e957d2005-11-17 14:52:13 +01002319static int snd_hdsp_put_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002321 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 int change;
2323 int val;
2324
2325 if (!snd_hdsp_use_is_exclusive(hdsp))
2326 return -EBUSY;
2327 val = ucontrol->value.enumerated.item[0];
2328 if (val < 0) val = 0;
2329 if (val > 2) val = 2;
2330 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002331 if (val != hdsp_phone_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 change = (hdsp_set_phone_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002333 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 spin_unlock_irq(&hdsp->lock);
2336 return change;
2337}
2338
2339#define HDSP_XLR_BREAKOUT_CABLE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002340{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 .name = xname, \
2342 .index = xindex, \
2343 .info = snd_hdsp_info_xlr_breakout_cable, \
2344 .get = snd_hdsp_get_xlr_breakout_cable, \
2345 .put = snd_hdsp_put_xlr_breakout_cable \
2346}
2347
Takashi Iwai55e957d2005-11-17 14:52:13 +01002348static int hdsp_xlr_breakout_cable(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002350 if (hdsp->control_register & HDSP_XLRBreakoutCable)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 return 0;
2353}
2354
Takashi Iwai55e957d2005-11-17 14:52:13 +01002355static int hdsp_set_xlr_breakout_cable(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002357 if (mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 hdsp->control_register |= HDSP_XLRBreakoutCable;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002359 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 hdsp->control_register &= ~HDSP_XLRBreakoutCable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2362 return 0;
2363}
2364
Takashi Iwai55e957d2005-11-17 14:52:13 +01002365static int snd_hdsp_info_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366{
2367 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2368 uinfo->count = 1;
2369 uinfo->value.integer.min = 0;
2370 uinfo->value.integer.max = 1;
2371 return 0;
2372}
2373
Takashi Iwai55e957d2005-11-17 14:52:13 +01002374static int snd_hdsp_get_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002376 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377
2378 ucontrol->value.enumerated.item[0] = hdsp_xlr_breakout_cable(hdsp);
2379 return 0;
2380}
2381
Takashi Iwai55e957d2005-11-17 14:52:13 +01002382static int snd_hdsp_put_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002384 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385 int change;
2386 int val;
2387
2388 if (!snd_hdsp_use_is_exclusive(hdsp))
2389 return -EBUSY;
2390 val = ucontrol->value.integer.value[0] & 1;
2391 spin_lock_irq(&hdsp->lock);
2392 change = (int)val != hdsp_xlr_breakout_cable(hdsp);
2393 hdsp_set_xlr_breakout_cable(hdsp, val);
2394 spin_unlock_irq(&hdsp->lock);
2395 return change;
2396}
2397
2398/* (De)activates old RME Analog Extension Board
2399 These are connected to the internal ADAT connector
2400 Switching this on desactivates external ADAT
2401*/
2402#define HDSP_AEB(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002403{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 .name = xname, \
2405 .index = xindex, \
2406 .info = snd_hdsp_info_aeb, \
2407 .get = snd_hdsp_get_aeb, \
2408 .put = snd_hdsp_put_aeb \
2409}
2410
Takashi Iwai55e957d2005-11-17 14:52:13 +01002411static int hdsp_aeb(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002413 if (hdsp->control_register & HDSP_AnalogExtensionBoard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415 return 0;
2416}
2417
Takashi Iwai55e957d2005-11-17 14:52:13 +01002418static int hdsp_set_aeb(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002420 if (mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 hdsp->control_register |= HDSP_AnalogExtensionBoard;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002422 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 hdsp->control_register &= ~HDSP_AnalogExtensionBoard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2425 return 0;
2426}
2427
Takashi Iwai55e957d2005-11-17 14:52:13 +01002428static int snd_hdsp_info_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429{
2430 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2431 uinfo->count = 1;
2432 uinfo->value.integer.min = 0;
2433 uinfo->value.integer.max = 1;
2434 return 0;
2435}
2436
Takashi Iwai55e957d2005-11-17 14:52:13 +01002437static int snd_hdsp_get_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002439 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440
2441 ucontrol->value.enumerated.item[0] = hdsp_aeb(hdsp);
2442 return 0;
2443}
2444
Takashi Iwai55e957d2005-11-17 14:52:13 +01002445static int snd_hdsp_put_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002447 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 int change;
2449 int val;
2450
2451 if (!snd_hdsp_use_is_exclusive(hdsp))
2452 return -EBUSY;
2453 val = ucontrol->value.integer.value[0] & 1;
2454 spin_lock_irq(&hdsp->lock);
2455 change = (int)val != hdsp_aeb(hdsp);
2456 hdsp_set_aeb(hdsp, val);
2457 spin_unlock_irq(&hdsp->lock);
2458 return change;
2459}
2460
2461#define HDSP_PREF_SYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002462{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 .name = xname, \
2464 .index = xindex, \
2465 .info = snd_hdsp_info_pref_sync_ref, \
2466 .get = snd_hdsp_get_pref_sync_ref, \
2467 .put = snd_hdsp_put_pref_sync_ref \
2468}
2469
Takashi Iwai55e957d2005-11-17 14:52:13 +01002470static int hdsp_pref_sync_ref(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471{
2472 /* Notice that this looks at the requested sync source,
2473 not the one actually in use.
2474 */
2475
2476 switch (hdsp->control_register & HDSP_SyncRefMask) {
2477 case HDSP_SyncRef_ADAT1:
2478 return HDSP_SYNC_FROM_ADAT1;
2479 case HDSP_SyncRef_ADAT2:
2480 return HDSP_SYNC_FROM_ADAT2;
2481 case HDSP_SyncRef_ADAT3:
2482 return HDSP_SYNC_FROM_ADAT3;
2483 case HDSP_SyncRef_SPDIF:
2484 return HDSP_SYNC_FROM_SPDIF;
2485 case HDSP_SyncRef_WORD:
2486 return HDSP_SYNC_FROM_WORD;
2487 case HDSP_SyncRef_ADAT_SYNC:
2488 return HDSP_SYNC_FROM_ADAT_SYNC;
2489 default:
2490 return HDSP_SYNC_FROM_WORD;
2491 }
2492 return 0;
2493}
2494
Takashi Iwai55e957d2005-11-17 14:52:13 +01002495static int hdsp_set_pref_sync_ref(struct hdsp *hdsp, int pref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496{
2497 hdsp->control_register &= ~HDSP_SyncRefMask;
2498 switch (pref) {
2499 case HDSP_SYNC_FROM_ADAT1:
2500 hdsp->control_register &= ~HDSP_SyncRefMask; /* clear SyncRef bits */
2501 break;
2502 case HDSP_SYNC_FROM_ADAT2:
2503 hdsp->control_register |= HDSP_SyncRef_ADAT2;
2504 break;
2505 case HDSP_SYNC_FROM_ADAT3:
2506 hdsp->control_register |= HDSP_SyncRef_ADAT3;
2507 break;
2508 case HDSP_SYNC_FROM_SPDIF:
2509 hdsp->control_register |= HDSP_SyncRef_SPDIF;
2510 break;
2511 case HDSP_SYNC_FROM_WORD:
2512 hdsp->control_register |= HDSP_SyncRef_WORD;
2513 break;
2514 case HDSP_SYNC_FROM_ADAT_SYNC:
2515 hdsp->control_register |= HDSP_SyncRef_ADAT_SYNC;
2516 break;
2517 default:
2518 return -1;
2519 }
2520 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2521 return 0;
2522}
2523
Takashi Iwai55e957d2005-11-17 14:52:13 +01002524static int snd_hdsp_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525{
2526 static char *texts[] = {"Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3" };
Takashi Iwai55e957d2005-11-17 14:52:13 +01002527 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528
2529 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2530 uinfo->count = 1;
2531
2532 switch (hdsp->io_type) {
2533 case Digiface:
2534 case H9652:
2535 uinfo->value.enumerated.items = 6;
2536 break;
2537 case Multiface:
2538 uinfo->value.enumerated.items = 4;
2539 break;
2540 case H9632:
2541 uinfo->value.enumerated.items = 3;
2542 break;
2543 default:
2544 uinfo->value.enumerated.items = 0;
2545 break;
2546 }
2547
2548 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2549 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2550 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2551 return 0;
2552}
2553
Takashi Iwai55e957d2005-11-17 14:52:13 +01002554static int snd_hdsp_get_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002556 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557
2558 ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp);
2559 return 0;
2560}
2561
Takashi Iwai55e957d2005-11-17 14:52:13 +01002562static int snd_hdsp_put_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002564 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 int change, max;
2566 unsigned int val;
2567
2568 if (!snd_hdsp_use_is_exclusive(hdsp))
2569 return -EBUSY;
2570
2571 switch (hdsp->io_type) {
2572 case Digiface:
2573 case H9652:
2574 max = 6;
2575 break;
2576 case Multiface:
2577 max = 4;
2578 break;
2579 case H9632:
2580 max = 3;
2581 break;
2582 default:
2583 return -EIO;
2584 }
2585
2586 val = ucontrol->value.enumerated.item[0] % max;
2587 spin_lock_irq(&hdsp->lock);
2588 change = (int)val != hdsp_pref_sync_ref(hdsp);
2589 hdsp_set_pref_sync_ref(hdsp, val);
2590 spin_unlock_irq(&hdsp->lock);
2591 return change;
2592}
2593
2594#define HDSP_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002595{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 .name = xname, \
2597 .index = xindex, \
2598 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2599 .info = snd_hdsp_info_autosync_ref, \
2600 .get = snd_hdsp_get_autosync_ref, \
2601}
2602
Takashi Iwai55e957d2005-11-17 14:52:13 +01002603static int hdsp_autosync_ref(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604{
2605 /* This looks at the autosync selected sync reference */
2606 unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
2607
2608 switch (status2 & HDSP_SelSyncRefMask) {
2609 case HDSP_SelSyncRef_WORD:
2610 return HDSP_AUTOSYNC_FROM_WORD;
2611 case HDSP_SelSyncRef_ADAT_SYNC:
2612 return HDSP_AUTOSYNC_FROM_ADAT_SYNC;
2613 case HDSP_SelSyncRef_SPDIF:
2614 return HDSP_AUTOSYNC_FROM_SPDIF;
2615 case HDSP_SelSyncRefMask:
2616 return HDSP_AUTOSYNC_FROM_NONE;
2617 case HDSP_SelSyncRef_ADAT1:
2618 return HDSP_AUTOSYNC_FROM_ADAT1;
2619 case HDSP_SelSyncRef_ADAT2:
2620 return HDSP_AUTOSYNC_FROM_ADAT2;
2621 case HDSP_SelSyncRef_ADAT3:
2622 return HDSP_AUTOSYNC_FROM_ADAT3;
2623 default:
2624 return HDSP_AUTOSYNC_FROM_WORD;
2625 }
2626 return 0;
2627}
2628
Takashi Iwai55e957d2005-11-17 14:52:13 +01002629static int snd_hdsp_info_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630{
2631 static char *texts[] = {"Word", "ADAT Sync", "IEC958", "None", "ADAT1", "ADAT2", "ADAT3" };
2632
2633 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2634 uinfo->count = 1;
2635 uinfo->value.enumerated.items = 7;
2636 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2637 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2638 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2639 return 0;
2640}
2641
Takashi Iwai55e957d2005-11-17 14:52:13 +01002642static int snd_hdsp_get_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002644 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645
2646 ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp);
2647 return 0;
2648}
2649
2650#define HDSP_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002651{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652 .name = xname, \
2653 .index = xindex, \
2654 .info = snd_hdsp_info_line_out, \
2655 .get = snd_hdsp_get_line_out, \
2656 .put = snd_hdsp_put_line_out \
2657}
2658
Takashi Iwai55e957d2005-11-17 14:52:13 +01002659static int hdsp_line_out(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660{
2661 return (hdsp->control_register & HDSP_LineOut) ? 1 : 0;
2662}
2663
Takashi Iwai55e957d2005-11-17 14:52:13 +01002664static int hdsp_set_line_output(struct hdsp *hdsp, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002666 if (out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 hdsp->control_register |= HDSP_LineOut;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002668 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669 hdsp->control_register &= ~HDSP_LineOut;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2671 return 0;
2672}
2673
Takashi Iwai55e957d2005-11-17 14:52:13 +01002674static int snd_hdsp_info_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675{
2676 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2677 uinfo->count = 1;
2678 uinfo->value.integer.min = 0;
2679 uinfo->value.integer.max = 1;
2680 return 0;
2681}
2682
Takashi Iwai55e957d2005-11-17 14:52:13 +01002683static int snd_hdsp_get_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002685 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686
2687 spin_lock_irq(&hdsp->lock);
2688 ucontrol->value.integer.value[0] = hdsp_line_out(hdsp);
2689 spin_unlock_irq(&hdsp->lock);
2690 return 0;
2691}
2692
Takashi Iwai55e957d2005-11-17 14:52:13 +01002693static int snd_hdsp_put_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002695 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696 int change;
2697 unsigned int val;
2698
2699 if (!snd_hdsp_use_is_exclusive(hdsp))
2700 return -EBUSY;
2701 val = ucontrol->value.integer.value[0] & 1;
2702 spin_lock_irq(&hdsp->lock);
2703 change = (int)val != hdsp_line_out(hdsp);
2704 hdsp_set_line_output(hdsp, val);
2705 spin_unlock_irq(&hdsp->lock);
2706 return change;
2707}
2708
2709#define HDSP_PRECISE_POINTER(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002710{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711 .name = xname, \
2712 .index = xindex, \
2713 .info = snd_hdsp_info_precise_pointer, \
2714 .get = snd_hdsp_get_precise_pointer, \
2715 .put = snd_hdsp_put_precise_pointer \
2716}
2717
Takashi Iwai55e957d2005-11-17 14:52:13 +01002718static int hdsp_set_precise_pointer(struct hdsp *hdsp, int precise)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002720 if (precise)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721 hdsp->precise_ptr = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002722 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 hdsp->precise_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 return 0;
2725}
2726
Takashi Iwai55e957d2005-11-17 14:52:13 +01002727static int snd_hdsp_info_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728{
2729 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2730 uinfo->count = 1;
2731 uinfo->value.integer.min = 0;
2732 uinfo->value.integer.max = 1;
2733 return 0;
2734}
2735
Takashi Iwai55e957d2005-11-17 14:52:13 +01002736static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002738 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739
2740 spin_lock_irq(&hdsp->lock);
2741 ucontrol->value.integer.value[0] = hdsp->precise_ptr;
2742 spin_unlock_irq(&hdsp->lock);
2743 return 0;
2744}
2745
Takashi Iwai55e957d2005-11-17 14:52:13 +01002746static int snd_hdsp_put_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002748 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749 int change;
2750 unsigned int val;
2751
2752 if (!snd_hdsp_use_is_exclusive(hdsp))
2753 return -EBUSY;
2754 val = ucontrol->value.integer.value[0] & 1;
2755 spin_lock_irq(&hdsp->lock);
2756 change = (int)val != hdsp->precise_ptr;
2757 hdsp_set_precise_pointer(hdsp, val);
2758 spin_unlock_irq(&hdsp->lock);
2759 return change;
2760}
2761
2762#define HDSP_USE_MIDI_TASKLET(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002763{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 .name = xname, \
2765 .index = xindex, \
2766 .info = snd_hdsp_info_use_midi_tasklet, \
2767 .get = snd_hdsp_get_use_midi_tasklet, \
2768 .put = snd_hdsp_put_use_midi_tasklet \
2769}
2770
Takashi Iwai55e957d2005-11-17 14:52:13 +01002771static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002773 if (use_tasklet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774 hdsp->use_midi_tasklet = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002775 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776 hdsp->use_midi_tasklet = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777 return 0;
2778}
2779
Takashi Iwai55e957d2005-11-17 14:52:13 +01002780static int snd_hdsp_info_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781{
2782 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2783 uinfo->count = 1;
2784 uinfo->value.integer.min = 0;
2785 uinfo->value.integer.max = 1;
2786 return 0;
2787}
2788
Takashi Iwai55e957d2005-11-17 14:52:13 +01002789static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002791 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792
2793 spin_lock_irq(&hdsp->lock);
2794 ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet;
2795 spin_unlock_irq(&hdsp->lock);
2796 return 0;
2797}
2798
Takashi Iwai55e957d2005-11-17 14:52:13 +01002799static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002801 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802 int change;
2803 unsigned int val;
2804
2805 if (!snd_hdsp_use_is_exclusive(hdsp))
2806 return -EBUSY;
2807 val = ucontrol->value.integer.value[0] & 1;
2808 spin_lock_irq(&hdsp->lock);
2809 change = (int)val != hdsp->use_midi_tasklet;
2810 hdsp_set_use_midi_tasklet(hdsp, val);
2811 spin_unlock_irq(&hdsp->lock);
2812 return change;
2813}
2814
2815#define HDSP_MIXER(xname, xindex) \
2816{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
2817 .name = xname, \
2818 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002819 .device = 0, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2821 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2822 .info = snd_hdsp_info_mixer, \
2823 .get = snd_hdsp_get_mixer, \
2824 .put = snd_hdsp_put_mixer \
2825}
2826
Takashi Iwai55e957d2005-11-17 14:52:13 +01002827static int snd_hdsp_info_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828{
2829 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2830 uinfo->count = 3;
2831 uinfo->value.integer.min = 0;
2832 uinfo->value.integer.max = 65536;
2833 uinfo->value.integer.step = 1;
2834 return 0;
2835}
2836
Takashi Iwai55e957d2005-11-17 14:52:13 +01002837static int snd_hdsp_get_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002839 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840 int source;
2841 int destination;
2842 int addr;
2843
2844 source = ucontrol->value.integer.value[0];
2845 destination = ucontrol->value.integer.value[1];
2846
Takashi Iwaib0b98112005-10-20 18:29:58 +02002847 if (source >= hdsp->max_channels)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848 addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels,destination);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002849 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850 addr = hdsp_input_to_output_key(hdsp,source, destination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851
2852 spin_lock_irq(&hdsp->lock);
2853 ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr);
2854 spin_unlock_irq(&hdsp->lock);
2855 return 0;
2856}
2857
Takashi Iwai55e957d2005-11-17 14:52:13 +01002858static int snd_hdsp_put_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002860 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861 int change;
2862 int source;
2863 int destination;
2864 int gain;
2865 int addr;
2866
2867 if (!snd_hdsp_use_is_exclusive(hdsp))
2868 return -EBUSY;
2869
2870 source = ucontrol->value.integer.value[0];
2871 destination = ucontrol->value.integer.value[1];
2872
Takashi Iwaib0b98112005-10-20 18:29:58 +02002873 if (source >= hdsp->max_channels)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874 addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels, destination);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002875 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002876 addr = hdsp_input_to_output_key(hdsp,source, destination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877
2878 gain = ucontrol->value.integer.value[2];
2879
2880 spin_lock_irq(&hdsp->lock);
2881 change = gain != hdsp_read_gain(hdsp, addr);
2882 if (change)
2883 hdsp_write_gain(hdsp, addr, gain);
2884 spin_unlock_irq(&hdsp->lock);
2885 return change;
2886}
2887
2888#define HDSP_WC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002889{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890 .name = xname, \
2891 .index = xindex, \
2892 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2893 .info = snd_hdsp_info_sync_check, \
2894 .get = snd_hdsp_get_wc_sync_check \
2895}
2896
Takashi Iwai55e957d2005-11-17 14:52:13 +01002897static int snd_hdsp_info_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898{
2899 static char *texts[] = {"No Lock", "Lock", "Sync" };
2900 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2901 uinfo->count = 1;
2902 uinfo->value.enumerated.items = 3;
2903 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2904 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2905 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2906 return 0;
2907}
2908
Takashi Iwai55e957d2005-11-17 14:52:13 +01002909static int hdsp_wc_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910{
2911 int status2 = hdsp_read(hdsp, HDSP_status2Register);
2912 if (status2 & HDSP_wc_lock) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002913 if (status2 & HDSP_wc_sync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002915 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002917 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919 return 0;
2920}
2921
Takashi Iwai55e957d2005-11-17 14:52:13 +01002922static int snd_hdsp_get_wc_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002923{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002924 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925
2926 ucontrol->value.enumerated.item[0] = hdsp_wc_sync_check(hdsp);
2927 return 0;
2928}
2929
2930#define HDSP_SPDIF_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002931{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932 .name = xname, \
2933 .index = xindex, \
2934 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2935 .info = snd_hdsp_info_sync_check, \
2936 .get = snd_hdsp_get_spdif_sync_check \
2937}
2938
Takashi Iwai55e957d2005-11-17 14:52:13 +01002939static int hdsp_spdif_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940{
2941 int status = hdsp_read(hdsp, HDSP_statusRegister);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002942 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002944 else {
2945 if (status & HDSP_SPDIFSync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002947 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949 }
2950 return 0;
2951}
2952
Takashi Iwai55e957d2005-11-17 14:52:13 +01002953static int snd_hdsp_get_spdif_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002955 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956
2957 ucontrol->value.enumerated.item[0] = hdsp_spdif_sync_check(hdsp);
2958 return 0;
2959}
2960
2961#define HDSP_ADATSYNC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002962{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963 .name = xname, \
2964 .index = xindex, \
2965 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2966 .info = snd_hdsp_info_sync_check, \
2967 .get = snd_hdsp_get_adatsync_sync_check \
2968}
2969
Takashi Iwai55e957d2005-11-17 14:52:13 +01002970static int hdsp_adatsync_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971{
2972 int status = hdsp_read(hdsp, HDSP_statusRegister);
2973 if (status & HDSP_TimecodeLock) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002974 if (status & HDSP_TimecodeSync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002976 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002978 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980}
2981
Takashi Iwai55e957d2005-11-17 14:52:13 +01002982static int snd_hdsp_get_adatsync_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002984 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985
2986 ucontrol->value.enumerated.item[0] = hdsp_adatsync_sync_check(hdsp);
2987 return 0;
2988}
2989
2990#define HDSP_ADAT_SYNC_CHECK \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002991{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2993 .info = snd_hdsp_info_sync_check, \
2994 .get = snd_hdsp_get_adat_sync_check \
2995}
2996
Takashi Iwai55e957d2005-11-17 14:52:13 +01002997static int hdsp_adat_sync_check(struct hdsp *hdsp, int idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998{
2999 int status = hdsp_read(hdsp, HDSP_statusRegister);
3000
3001 if (status & (HDSP_Lock0>>idx)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003002 if (status & (HDSP_Sync0>>idx))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003004 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003006 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008}
3009
Takashi Iwai55e957d2005-11-17 14:52:13 +01003010static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011{
3012 int offset;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003013 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014
3015 offset = ucontrol->id.index - 1;
3016 snd_assert(offset >= 0);
3017
3018 switch (hdsp->io_type) {
3019 case Digiface:
3020 case H9652:
3021 if (offset >= 3)
3022 return -EINVAL;
3023 break;
3024 case Multiface:
3025 case H9632:
3026 if (offset >= 1)
3027 return -EINVAL;
3028 break;
3029 default:
3030 return -EIO;
3031 }
3032
3033 ucontrol->value.enumerated.item[0] = hdsp_adat_sync_check(hdsp, offset);
3034 return 0;
3035}
3036
Takashi Iwai55e957d2005-11-17 14:52:13 +01003037static struct snd_kcontrol_new snd_hdsp_9632_controls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038HDSP_DA_GAIN("DA Gain", 0),
3039HDSP_AD_GAIN("AD Gain", 0),
3040HDSP_PHONE_GAIN("Phones Gain", 0),
3041HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0)
3042};
3043
Takashi Iwai55e957d2005-11-17 14:52:13 +01003044static struct snd_kcontrol_new snd_hdsp_controls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045{
Clemens Ladisch5549d542005-08-03 13:50:30 +02003046 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
3048 .info = snd_hdsp_control_spdif_info,
3049 .get = snd_hdsp_control_spdif_get,
3050 .put = snd_hdsp_control_spdif_put,
3051},
3052{
3053 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch5549d542005-08-03 13:50:30 +02003054 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
3056 .info = snd_hdsp_control_spdif_stream_info,
3057 .get = snd_hdsp_control_spdif_stream_get,
3058 .put = snd_hdsp_control_spdif_stream_put,
3059},
3060{
3061 .access = SNDRV_CTL_ELEM_ACCESS_READ,
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,CON_MASK),
3064 .info = snd_hdsp_control_spdif_mask_info,
3065 .get = snd_hdsp_control_spdif_mask_get,
3066 .private_value = IEC958_AES0_NONAUDIO |
3067 IEC958_AES0_PROFESSIONAL |
3068 IEC958_AES0_CON_EMPHASIS,
3069},
3070{
3071 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +02003072 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
3074 .info = snd_hdsp_control_spdif_mask_info,
3075 .get = snd_hdsp_control_spdif_mask_get,
3076 .private_value = IEC958_AES0_NONAUDIO |
3077 IEC958_AES0_PROFESSIONAL |
3078 IEC958_AES0_PRO_EMPHASIS,
3079},
3080HDSP_MIXER("Mixer", 0),
3081HDSP_SPDIF_IN("IEC958 Input Connector", 0),
3082HDSP_SPDIF_OUT("IEC958 Output also on ADAT1", 0),
3083HDSP_SPDIF_PROFESSIONAL("IEC958 Professional Bit", 0),
3084HDSP_SPDIF_EMPHASIS("IEC958 Emphasis Bit", 0),
3085HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0),
3086/* 'Sample Clock Source' complies with the alsa control naming scheme */
3087HDSP_CLOCK_SOURCE("Sample Clock Source", 0),
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003088{
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003089 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3090 .name = "Sample Clock Source Locking",
3091 .info = snd_hdsp_info_clock_source_lock,
3092 .get = snd_hdsp_get_clock_source_lock,
3093 .put = snd_hdsp_put_clock_source_lock,
3094},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095HDSP_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
3096HDSP_PREF_SYNC_REF("Preferred Sync Reference", 0),
3097HDSP_AUTOSYNC_REF("AutoSync Reference", 0),
3098HDSP_SPDIF_SAMPLE_RATE("SPDIF Sample Rate", 0),
3099HDSP_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
3100/* 'External Rate' complies with the alsa control naming scheme */
3101HDSP_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
3102HDSP_WC_SYNC_CHECK("Word Clock Lock Status", 0),
3103HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0),
3104HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0),
3105HDSP_LINE_OUT("Line Out", 0),
3106HDSP_PRECISE_POINTER("Precise Pointer", 0),
3107HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0),
3108};
3109
Takashi Iwai55e957d2005-11-17 14:52:13 +01003110static struct snd_kcontrol_new snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0);
3111static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112
Takashi Iwai55e957d2005-11-17 14:52:13 +01003113static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114{
3115 unsigned int idx;
3116 int err;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003117 struct snd_kcontrol *kctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118
3119 for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003120 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122 if (idx == 1) /* IEC958 (S/PDIF) Stream */
3123 hdsp->spdif_ctl = kctl;
3124 }
3125
3126 /* ADAT SyncCheck status */
3127 snd_hdsp_adat_sync_check.name = "ADAT Lock Status";
3128 snd_hdsp_adat_sync_check.index = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003129 if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131 if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
3132 for (idx = 1; idx < 3; ++idx) {
3133 snd_hdsp_adat_sync_check.index = idx+1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003134 if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 }
3137 }
3138
3139 /* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */
3140 if (hdsp->io_type == H9632) {
3141 for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003142 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 }
3145 }
3146
3147 /* AEB control for H96xx card */
3148 if (hdsp->io_type == H9632 || hdsp->io_type == H9652) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003149 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151 }
3152
3153 return 0;
3154}
3155
3156/*------------------------------------------------------------
3157 /proc interface
3158 ------------------------------------------------------------*/
3159
3160static void
Takashi Iwai55e957d2005-11-17 14:52:13 +01003161snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003163 struct hdsp *hdsp = (struct hdsp *) entry->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164 unsigned int status;
3165 unsigned int status2;
3166 char *pref_sync_ref;
3167 char *autosync_ref;
3168 char *system_clock_mode;
3169 char *clock_source;
3170 int x;
3171
Remy Brunoecb594e2006-06-12 09:25:22 +02003172 if (hdsp_check_for_iobox (hdsp)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173 snd_iprintf(buffer, "No I/O box connected.\nPlease connect one and upload firmware.\n");
3174 return;
Remy Brunoecb594e2006-06-12 09:25:22 +02003175 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176
Takashi Iwaib0b98112005-10-20 18:29:58 +02003177 if (hdsp_check_for_firmware(hdsp, 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 if (hdsp->state & HDSP_FirmwareCached) {
3179 if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
3180 snd_iprintf(buffer, "Firmware loading from cache failed, please upload manually.\n");
3181 return;
3182 }
3183 } else {
3184 snd_iprintf(buffer, "No firmware loaded nor cached, please upload firmware.\n");
3185 return;
3186 }
3187 }
3188
3189 status = hdsp_read(hdsp, HDSP_statusRegister);
3190 status2 = hdsp_read(hdsp, HDSP_status2Register);
3191
3192 snd_iprintf(buffer, "%s (Card #%d)\n", hdsp->card_name, hdsp->card->number + 1);
3193 snd_iprintf(buffer, "Buffers: capture %p playback %p\n",
3194 hdsp->capture_buffer, hdsp->playback_buffer);
3195 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
3196 hdsp->irq, hdsp->port, (unsigned long)hdsp->iobase);
3197 snd_iprintf(buffer, "Control register: 0x%x\n", hdsp->control_register);
3198 snd_iprintf(buffer, "Control2 register: 0x%x\n", hdsp->control2_register);
3199 snd_iprintf(buffer, "Status register: 0x%x\n", status);
3200 snd_iprintf(buffer, "Status2 register: 0x%x\n", status2);
3201 snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff);
3202 snd_iprintf(buffer, "MIDI1 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut0));
3203 snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0));
3204 snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1));
3205 snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1));
3206 snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off");
3207
3208 snd_iprintf(buffer, "\n");
3209
3210 x = 1 << (6 + hdsp_decode_latency(hdsp->control_register & HDSP_LatencyMask));
3211
3212 snd_iprintf(buffer, "Buffer Size (Latency): %d samples (2 periods of %lu bytes)\n", x, (unsigned long) hdsp->period_bytes);
3213 snd_iprintf(buffer, "Hardware pointer (frames): %ld\n", hdsp_hw_pointer(hdsp));
3214 snd_iprintf(buffer, "Precise pointer: %s\n", hdsp->precise_ptr ? "on" : "off");
3215 snd_iprintf(buffer, "Line out: %s\n", (hdsp->control_register & HDSP_LineOut) ? "on" : "off");
3216
3217 snd_iprintf(buffer, "Firmware version: %d\n", (status2&HDSP_version0)|(status2&HDSP_version1)<<1|(status2&HDSP_version2)<<2);
3218
3219 snd_iprintf(buffer, "\n");
3220
3221
3222 switch (hdsp_clock_source(hdsp)) {
3223 case HDSP_CLOCK_SOURCE_AUTOSYNC:
3224 clock_source = "AutoSync";
3225 break;
3226 case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ:
3227 clock_source = "Internal 32 kHz";
3228 break;
3229 case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ:
3230 clock_source = "Internal 44.1 kHz";
3231 break;
3232 case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ:
3233 clock_source = "Internal 48 kHz";
3234 break;
3235 case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ:
3236 clock_source = "Internal 64 kHz";
3237 break;
3238 case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ:
3239 clock_source = "Internal 88.2 kHz";
3240 break;
3241 case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ:
3242 clock_source = "Internal 96 kHz";
3243 break;
3244 case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ:
3245 clock_source = "Internal 128 kHz";
3246 break;
3247 case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ:
3248 clock_source = "Internal 176.4 kHz";
3249 break;
3250 case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ:
3251 clock_source = "Internal 192 kHz";
3252 break;
3253 default:
3254 clock_source = "Error";
3255 }
3256 snd_iprintf (buffer, "Sample Clock Source: %s\n", clock_source);
3257
Takashi Iwaib0b98112005-10-20 18:29:58 +02003258 if (hdsp_system_clock_mode(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259 system_clock_mode = "Slave";
Takashi Iwaib0b98112005-10-20 18:29:58 +02003260 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261 system_clock_mode = "Master";
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262
3263 switch (hdsp_pref_sync_ref (hdsp)) {
3264 case HDSP_SYNC_FROM_WORD:
3265 pref_sync_ref = "Word Clock";
3266 break;
3267 case HDSP_SYNC_FROM_ADAT_SYNC:
3268 pref_sync_ref = "ADAT Sync";
3269 break;
3270 case HDSP_SYNC_FROM_SPDIF:
3271 pref_sync_ref = "SPDIF";
3272 break;
3273 case HDSP_SYNC_FROM_ADAT1:
3274 pref_sync_ref = "ADAT1";
3275 break;
3276 case HDSP_SYNC_FROM_ADAT2:
3277 pref_sync_ref = "ADAT2";
3278 break;
3279 case HDSP_SYNC_FROM_ADAT3:
3280 pref_sync_ref = "ADAT3";
3281 break;
3282 default:
3283 pref_sync_ref = "Word Clock";
3284 break;
3285 }
3286 snd_iprintf (buffer, "Preferred Sync Reference: %s\n", pref_sync_ref);
3287
3288 switch (hdsp_autosync_ref (hdsp)) {
3289 case HDSP_AUTOSYNC_FROM_WORD:
3290 autosync_ref = "Word Clock";
3291 break;
3292 case HDSP_AUTOSYNC_FROM_ADAT_SYNC:
3293 autosync_ref = "ADAT Sync";
3294 break;
3295 case HDSP_AUTOSYNC_FROM_SPDIF:
3296 autosync_ref = "SPDIF";
3297 break;
3298 case HDSP_AUTOSYNC_FROM_NONE:
3299 autosync_ref = "None";
3300 break;
3301 case HDSP_AUTOSYNC_FROM_ADAT1:
3302 autosync_ref = "ADAT1";
3303 break;
3304 case HDSP_AUTOSYNC_FROM_ADAT2:
3305 autosync_ref = "ADAT2";
3306 break;
3307 case HDSP_AUTOSYNC_FROM_ADAT3:
3308 autosync_ref = "ADAT3";
3309 break;
3310 default:
3311 autosync_ref = "---";
3312 break;
3313 }
3314 snd_iprintf (buffer, "AutoSync Reference: %s\n", autosync_ref);
3315
3316 snd_iprintf (buffer, "AutoSync Frequency: %d\n", hdsp_external_sample_rate(hdsp));
3317
3318 snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode);
3319
3320 snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003321 snd_iprintf (buffer, "System Clock Locked: %s\n", hdsp->clock_source_locked ? "Yes" : "No");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003322
3323 snd_iprintf(buffer, "\n");
3324
3325 switch (hdsp_spdif_in(hdsp)) {
3326 case HDSP_SPDIFIN_OPTICAL:
3327 snd_iprintf(buffer, "IEC958 input: Optical\n");
3328 break;
3329 case HDSP_SPDIFIN_COAXIAL:
3330 snd_iprintf(buffer, "IEC958 input: Coaxial\n");
3331 break;
3332 case HDSP_SPDIFIN_INTERNAL:
3333 snd_iprintf(buffer, "IEC958 input: Internal\n");
3334 break;
3335 case HDSP_SPDIFIN_AES:
3336 snd_iprintf(buffer, "IEC958 input: AES\n");
3337 break;
3338 default:
3339 snd_iprintf(buffer, "IEC958 input: ???\n");
3340 break;
3341 }
3342
Takashi Iwaib0b98112005-10-20 18:29:58 +02003343 if (hdsp->control_register & HDSP_SPDIFOpticalOut)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344 snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003345 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346 snd_iprintf(buffer, "IEC958 output: Coaxial only\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003347
Takashi Iwaib0b98112005-10-20 18:29:58 +02003348 if (hdsp->control_register & HDSP_SPDIFProfessional)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003349 snd_iprintf(buffer, "IEC958 quality: Professional\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003350 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351 snd_iprintf(buffer, "IEC958 quality: Consumer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352
Takashi Iwaib0b98112005-10-20 18:29:58 +02003353 if (hdsp->control_register & HDSP_SPDIFEmphasis)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354 snd_iprintf(buffer, "IEC958 emphasis: on\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003355 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356 snd_iprintf(buffer, "IEC958 emphasis: off\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357
Takashi Iwaib0b98112005-10-20 18:29:58 +02003358 if (hdsp->control_register & HDSP_SPDIFNonAudio)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359 snd_iprintf(buffer, "IEC958 NonAudio: on\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003360 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361 snd_iprintf(buffer, "IEC958 NonAudio: off\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003362 if ((x = hdsp_spdif_sample_rate (hdsp)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363 snd_iprintf (buffer, "IEC958 sample rate: %d\n", x);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003364 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365 snd_iprintf (buffer, "IEC958 sample rate: Error flag set\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366
3367 snd_iprintf(buffer, "\n");
3368
3369 /* Sync Check */
3370 x = status & HDSP_Sync0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003371 if (status & HDSP_Lock0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372 snd_iprintf(buffer, "ADAT1: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003373 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374 snd_iprintf(buffer, "ADAT1: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375
3376 switch (hdsp->io_type) {
3377 case Digiface:
3378 case H9652:
3379 x = status & HDSP_Sync1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003380 if (status & HDSP_Lock1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381 snd_iprintf(buffer, "ADAT2: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003382 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383 snd_iprintf(buffer, "ADAT2: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003384 x = status & HDSP_Sync2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003385 if (status & HDSP_Lock2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386 snd_iprintf(buffer, "ADAT3: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003387 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388 snd_iprintf(buffer, "ADAT3: No Lock\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003389 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390 default:
3391 /* relax */
3392 break;
3393 }
3394
3395 x = status & HDSP_SPDIFSync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003396 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003397 snd_iprintf (buffer, "SPDIF: No Lock\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003398 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003399 snd_iprintf (buffer, "SPDIF: %s\n", x ? "Sync" : "Lock");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400
3401 x = status2 & HDSP_wc_sync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003402 if (status2 & HDSP_wc_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003403 snd_iprintf (buffer, "Word Clock: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003404 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405 snd_iprintf (buffer, "Word Clock: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406
3407 x = status & HDSP_TimecodeSync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003408 if (status & HDSP_TimecodeLock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409 snd_iprintf(buffer, "ADAT Sync: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003410 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411 snd_iprintf(buffer, "ADAT Sync: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412
3413 snd_iprintf(buffer, "\n");
3414
3415 /* Informations about H9632 specific controls */
3416 if (hdsp->io_type == H9632) {
3417 char *tmp;
3418
3419 switch (hdsp_ad_gain(hdsp)) {
3420 case 0:
3421 tmp = "-10 dBV";
3422 break;
3423 case 1:
3424 tmp = "+4 dBu";
3425 break;
3426 default:
3427 tmp = "Lo Gain";
3428 break;
3429 }
3430 snd_iprintf(buffer, "AD Gain : %s\n", tmp);
3431
3432 switch (hdsp_da_gain(hdsp)) {
3433 case 0:
3434 tmp = "Hi Gain";
3435 break;
3436 case 1:
3437 tmp = "+4 dBu";
3438 break;
3439 default:
3440 tmp = "-10 dBV";
3441 break;
3442 }
3443 snd_iprintf(buffer, "DA Gain : %s\n", tmp);
3444
3445 switch (hdsp_phone_gain(hdsp)) {
3446 case 0:
3447 tmp = "0 dB";
3448 break;
3449 case 1:
3450 tmp = "-6 dB";
3451 break;
3452 default:
3453 tmp = "-12 dB";
3454 break;
3455 }
3456 snd_iprintf(buffer, "Phones Gain : %s\n", tmp);
3457
3458 snd_iprintf(buffer, "XLR Breakout Cable : %s\n", hdsp_xlr_breakout_cable(hdsp) ? "yes" : "no");
3459
Takashi Iwaib0b98112005-10-20 18:29:58 +02003460 if (hdsp->control_register & HDSP_AnalogExtensionBoard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461 snd_iprintf(buffer, "AEB : on (ADAT1 internal)\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003462 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003463 snd_iprintf(buffer, "AEB : off (ADAT1 external)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003464 snd_iprintf(buffer, "\n");
3465 }
3466
3467}
3468
Takashi Iwai55e957d2005-11-17 14:52:13 +01003469static void __devinit snd_hdsp_proc_init(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003471 struct snd_info_entry *entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472
3473 if (! snd_card_proc_new(hdsp->card, "hdsp", &entry))
Takashi Iwaibf850202006-04-28 15:13:41 +02003474 snd_info_set_text_ops(entry, hdsp, snd_hdsp_proc_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475}
3476
Takashi Iwai55e957d2005-11-17 14:52:13 +01003477static void snd_hdsp_free_buffers(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478{
3479 snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci);
3480 snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
3481}
3482
Takashi Iwai55e957d2005-11-17 14:52:13 +01003483static int __devinit snd_hdsp_initialize_memory(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484{
3485 unsigned long pb_bus, cb_bus;
3486
3487 if (snd_hammerfall_get_buffer(hdsp->pci, &hdsp->capture_dma_buf, HDSP_DMA_AREA_BYTES) < 0 ||
3488 snd_hammerfall_get_buffer(hdsp->pci, &hdsp->playback_dma_buf, HDSP_DMA_AREA_BYTES) < 0) {
3489 if (hdsp->capture_dma_buf.area)
3490 snd_dma_free_pages(&hdsp->capture_dma_buf);
3491 printk(KERN_ERR "%s: no buffers available\n", hdsp->card_name);
3492 return -ENOMEM;
3493 }
3494
3495 /* Align to bus-space 64K boundary */
3496
3497 cb_bus = (hdsp->capture_dma_buf.addr + 0xFFFF) & ~0xFFFFl;
3498 pb_bus = (hdsp->playback_dma_buf.addr + 0xFFFF) & ~0xFFFFl;
3499
3500 /* Tell the card where it is */
3501
3502 hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus);
3503 hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus);
3504
3505 hdsp->capture_buffer = hdsp->capture_dma_buf.area + (cb_bus - hdsp->capture_dma_buf.addr);
3506 hdsp->playback_buffer = hdsp->playback_dma_buf.area + (pb_bus - hdsp->playback_dma_buf.addr);
3507
3508 return 0;
3509}
3510
Takashi Iwai55e957d2005-11-17 14:52:13 +01003511static int snd_hdsp_set_defaults(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512{
3513 unsigned int i;
3514
3515 /* ASSUMPTION: hdsp->lock is either held, or
3516 there is no need to hold it (e.g. during module
3517 initalization).
3518 */
3519
3520 /* set defaults:
3521
3522 SPDIF Input via Coax
3523 Master clock mode
3524 maximum latency (7 => 2^7 = 8192 samples, 64Kbyte buffer,
3525 which implies 2 4096 sample, 32Kbyte periods).
3526 Enable line out.
3527 */
3528
3529 hdsp->control_register = HDSP_ClockModeMaster |
3530 HDSP_SPDIFInputCoaxial |
3531 hdsp_encode_latency(7) |
3532 HDSP_LineOut;
3533
3534
3535 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3536
3537#ifdef SNDRV_BIG_ENDIAN
3538 hdsp->control2_register = HDSP_BIGENDIAN_MODE;
3539#else
3540 hdsp->control2_register = 0;
3541#endif
Takashi Iwaib0b98112005-10-20 18:29:58 +02003542 if (hdsp->io_type == H9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003543 snd_hdsp_9652_enable_mixer (hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003544 else
3545 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003546
3547 hdsp_reset_hw_pointer(hdsp);
3548 hdsp_compute_period_size(hdsp);
3549
3550 /* silence everything */
3551
Takashi Iwaib0b98112005-10-20 18:29:58 +02003552 for (i = 0; i < HDSP_MATRIX_MIXER_SIZE; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003553 hdsp->mixer_matrix[i] = MINUS_INFINITY_GAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003554
3555 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 +02003556 if (hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558 }
3559
3560 /* H9632 specific defaults */
3561 if (hdsp->io_type == H9632) {
3562 hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB);
3563 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3564 }
3565
3566 /* set a default rate so that the channel map is set up.
3567 */
3568
3569 hdsp_set_rate(hdsp, 48000, 1);
3570
3571 return 0;
3572}
3573
3574static void hdsp_midi_tasklet(unsigned long arg)
3575{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003576 struct hdsp *hdsp = (struct hdsp *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577
Takashi Iwaib0b98112005-10-20 18:29:58 +02003578 if (hdsp->midi[0].pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579 snd_hdsp_midi_input_read (&hdsp->midi[0]);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003580 if (hdsp->midi[1].pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581 snd_hdsp_midi_input_read (&hdsp->midi[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582}
3583
3584static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
3585{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003586 struct hdsp *hdsp = (struct hdsp *) dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587 unsigned int status;
3588 int audio;
3589 int midi0;
3590 int midi1;
3591 unsigned int midi0status;
3592 unsigned int midi1status;
3593 int schedule = 0;
3594
3595 status = hdsp_read(hdsp, HDSP_statusRegister);
3596
3597 audio = status & HDSP_audioIRQPending;
3598 midi0 = status & HDSP_midi0IRQPending;
3599 midi1 = status & HDSP_midi1IRQPending;
3600
Takashi Iwaib0b98112005-10-20 18:29:58 +02003601 if (!audio && !midi0 && !midi1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003602 return IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603
3604 hdsp_write(hdsp, HDSP_interruptConfirmation, 0);
3605
3606 midi0status = hdsp_read (hdsp, HDSP_midiStatusIn0) & 0xff;
3607 midi1status = hdsp_read (hdsp, HDSP_midiStatusIn1) & 0xff;
3608
3609 if (audio) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003610 if (hdsp->capture_substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611 snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612
Takashi Iwaib0b98112005-10-20 18:29:58 +02003613 if (hdsp->playback_substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614 snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615 }
3616
3617 if (midi0 && midi0status) {
3618 if (hdsp->use_midi_tasklet) {
3619 /* we disable interrupts for this input until processing is done */
3620 hdsp->control_register &= ~HDSP_Midi0InterruptEnable;
3621 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3622 hdsp->midi[0].pending = 1;
3623 schedule = 1;
3624 } else {
3625 snd_hdsp_midi_input_read (&hdsp->midi[0]);
3626 }
3627 }
3628 if (hdsp->io_type != Multiface && hdsp->io_type != H9632 && midi1 && midi1status) {
3629 if (hdsp->use_midi_tasklet) {
3630 /* we disable interrupts for this input until processing is done */
3631 hdsp->control_register &= ~HDSP_Midi1InterruptEnable;
3632 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3633 hdsp->midi[1].pending = 1;
3634 schedule = 1;
3635 } else {
3636 snd_hdsp_midi_input_read (&hdsp->midi[1]);
3637 }
3638 }
3639 if (hdsp->use_midi_tasklet && schedule)
3640 tasklet_hi_schedule(&hdsp->midi_tasklet);
3641 return IRQ_HANDLED;
3642}
3643
Takashi Iwai55e957d2005-11-17 14:52:13 +01003644static snd_pcm_uframes_t snd_hdsp_hw_pointer(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003646 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647 return hdsp_hw_pointer(hdsp);
3648}
3649
Takashi Iwai55e957d2005-11-17 14:52:13 +01003650static char *hdsp_channel_buffer_location(struct hdsp *hdsp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651 int stream,
3652 int channel)
3653
3654{
3655 int mapped_channel;
3656
3657 snd_assert(channel >= 0 && channel < hdsp->max_channels, return NULL);
3658
Takashi Iwaib0b98112005-10-20 18:29:58 +02003659 if ((mapped_channel = hdsp->channel_map[channel]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661
Takashi Iwaib0b98112005-10-20 18:29:58 +02003662 if (stream == SNDRV_PCM_STREAM_CAPTURE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003663 return hdsp->capture_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003664 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665 return hdsp->playback_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666}
3667
Takashi Iwai55e957d2005-11-17 14:52:13 +01003668static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669 snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
3670{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003671 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672 char *channel_buf;
3673
3674 snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
3675
3676 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
3677 snd_assert(channel_buf != NULL, return -EIO);
3678 if (copy_from_user(channel_buf + pos * 4, src, count * 4))
3679 return -EFAULT;
3680 return count;
3681}
3682
Takashi Iwai55e957d2005-11-17 14:52:13 +01003683static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684 snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count)
3685{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003686 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687 char *channel_buf;
3688
3689 snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
3690
3691 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
3692 snd_assert(channel_buf != NULL, return -EIO);
3693 if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
3694 return -EFAULT;
3695 return count;
3696}
3697
Takashi Iwai55e957d2005-11-17 14:52:13 +01003698static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003699 snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
3700{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003701 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702 char *channel_buf;
3703
3704 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
3705 snd_assert(channel_buf != NULL, return -EIO);
3706 memset(channel_buf + pos * 4, 0, count * 4);
3707 return count;
3708}
3709
Takashi Iwai55e957d2005-11-17 14:52:13 +01003710static int snd_hdsp_reset(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003712 struct snd_pcm_runtime *runtime = substream->runtime;
3713 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
3714 struct snd_pcm_substream *other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3716 other = hdsp->capture_substream;
3717 else
3718 other = hdsp->playback_substream;
3719 if (hdsp->running)
3720 runtime->status->hw_ptr = hdsp_hw_pointer(hdsp);
3721 else
3722 runtime->status->hw_ptr = 0;
3723 if (other) {
3724 struct list_head *pos;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003725 struct snd_pcm_substream *s;
3726 struct snd_pcm_runtime *oruntime = other->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727 snd_pcm_group_for_each(pos, substream) {
3728 s = snd_pcm_group_substream_entry(pos);
3729 if (s == other) {
3730 oruntime->status->hw_ptr = runtime->status->hw_ptr;
3731 break;
3732 }
3733 }
3734 }
3735 return 0;
3736}
3737
Takashi Iwai55e957d2005-11-17 14:52:13 +01003738static int snd_hdsp_hw_params(struct snd_pcm_substream *substream,
3739 struct snd_pcm_hw_params *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003741 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742 int err;
3743 pid_t this_pid;
3744 pid_t other_pid;
3745
Takashi Iwaib0b98112005-10-20 18:29:58 +02003746 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748
Takashi Iwaib0b98112005-10-20 18:29:58 +02003749 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751
3752 spin_lock_irq(&hdsp->lock);
3753
3754 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3755 hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
3756 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= hdsp->creg_spdif_stream);
3757 this_pid = hdsp->playback_pid;
3758 other_pid = hdsp->capture_pid;
3759 } else {
3760 this_pid = hdsp->capture_pid;
3761 other_pid = hdsp->playback_pid;
3762 }
3763
3764 if ((other_pid > 0) && (this_pid != other_pid)) {
3765
3766 /* The other stream is open, and not by the same
3767 task as this one. Make sure that the parameters
3768 that matter are the same.
3769 */
3770
3771 if (params_rate(params) != hdsp->system_sample_rate) {
3772 spin_unlock_irq(&hdsp->lock);
3773 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
3774 return -EBUSY;
3775 }
3776
3777 if (params_period_size(params) != hdsp->period_bytes / 4) {
3778 spin_unlock_irq(&hdsp->lock);
3779 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
3780 return -EBUSY;
3781 }
3782
3783 /* We're fine. */
3784
3785 spin_unlock_irq(&hdsp->lock);
3786 return 0;
3787
3788 } else {
3789 spin_unlock_irq(&hdsp->lock);
3790 }
3791
3792 /* how to make sure that the rate matches an externally-set one ?
3793 */
3794
3795 spin_lock_irq(&hdsp->lock);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003796 if (! hdsp->clock_source_locked) {
3797 if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) {
3798 spin_unlock_irq(&hdsp->lock);
3799 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
3800 return err;
3801 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802 }
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003803 spin_unlock_irq(&hdsp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804
3805 if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) {
3806 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
3807 return err;
3808 }
3809
3810 return 0;
3811}
3812
Takashi Iwai55e957d2005-11-17 14:52:13 +01003813static int snd_hdsp_channel_info(struct snd_pcm_substream *substream,
3814 struct snd_pcm_channel_info *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003816 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817 int mapped_channel;
3818
3819 snd_assert(info->channel < hdsp->max_channels, return -EINVAL);
3820
Takashi Iwaib0b98112005-10-20 18:29:58 +02003821 if ((mapped_channel = hdsp->channel_map[info->channel]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003823
3824 info->offset = mapped_channel * HDSP_CHANNEL_BUFFER_BYTES;
3825 info->first = 0;
3826 info->step = 32;
3827 return 0;
3828}
3829
Takashi Iwai55e957d2005-11-17 14:52:13 +01003830static int snd_hdsp_ioctl(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831 unsigned int cmd, void *arg)
3832{
3833 switch (cmd) {
3834 case SNDRV_PCM_IOCTL1_RESET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835 return snd_hdsp_reset(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Takashi Iwaib0b98112005-10-20 18:29:58 +02003837 return snd_hdsp_channel_info(substream, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838 default:
3839 break;
3840 }
3841
3842 return snd_pcm_lib_ioctl(substream, cmd, arg);
3843}
3844
Takashi Iwai55e957d2005-11-17 14:52:13 +01003845static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003847 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
3848 struct snd_pcm_substream *other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849 int running;
3850
Takashi Iwaib0b98112005-10-20 18:29:58 +02003851 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003852 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853
Takashi Iwaib0b98112005-10-20 18:29:58 +02003854 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856
3857 spin_lock(&hdsp->lock);
3858 running = hdsp->running;
3859 switch (cmd) {
3860 case SNDRV_PCM_TRIGGER_START:
3861 running |= 1 << substream->stream;
3862 break;
3863 case SNDRV_PCM_TRIGGER_STOP:
3864 running &= ~(1 << substream->stream);
3865 break;
3866 default:
3867 snd_BUG();
3868 spin_unlock(&hdsp->lock);
3869 return -EINVAL;
3870 }
3871 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3872 other = hdsp->capture_substream;
3873 else
3874 other = hdsp->playback_substream;
3875
3876 if (other) {
3877 struct list_head *pos;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003878 struct snd_pcm_substream *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879 snd_pcm_group_for_each(pos, substream) {
3880 s = snd_pcm_group_substream_entry(pos);
3881 if (s == other) {
3882 snd_pcm_trigger_done(s, substream);
3883 if (cmd == SNDRV_PCM_TRIGGER_START)
3884 running |= 1 << s->stream;
3885 else
3886 running &= ~(1 << s->stream);
3887 goto _ok;
3888 }
3889 }
3890 if (cmd == SNDRV_PCM_TRIGGER_START) {
3891 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) &&
3892 substream->stream == SNDRV_PCM_STREAM_CAPTURE)
3893 hdsp_silence_playback(hdsp);
3894 } else {
3895 if (running &&
3896 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3897 hdsp_silence_playback(hdsp);
3898 }
3899 } else {
3900 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
3901 hdsp_silence_playback(hdsp);
3902 }
3903 _ok:
3904 snd_pcm_trigger_done(substream, substream);
3905 if (!hdsp->running && running)
3906 hdsp_start_audio(hdsp);
3907 else if (hdsp->running && !running)
3908 hdsp_stop_audio(hdsp);
3909 hdsp->running = running;
3910 spin_unlock(&hdsp->lock);
3911
3912 return 0;
3913}
3914
Takashi Iwai55e957d2005-11-17 14:52:13 +01003915static int snd_hdsp_prepare(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003917 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918 int result = 0;
3919
Takashi Iwaib0b98112005-10-20 18:29:58 +02003920 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922
Takashi Iwaib0b98112005-10-20 18:29:58 +02003923 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925
3926 spin_lock_irq(&hdsp->lock);
3927 if (!hdsp->running)
3928 hdsp_reset_hw_pointer(hdsp);
3929 spin_unlock_irq(&hdsp->lock);
3930 return result;
3931}
3932
Takashi Iwai55e957d2005-11-17 14:52:13 +01003933static struct snd_pcm_hardware snd_hdsp_playback_subinfo =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934{
3935 .info = (SNDRV_PCM_INFO_MMAP |
3936 SNDRV_PCM_INFO_MMAP_VALID |
3937 SNDRV_PCM_INFO_NONINTERLEAVED |
3938 SNDRV_PCM_INFO_SYNC_START |
3939 SNDRV_PCM_INFO_DOUBLE),
3940#ifdef SNDRV_BIG_ENDIAN
3941 .formats = SNDRV_PCM_FMTBIT_S32_BE,
3942#else
3943 .formats = SNDRV_PCM_FMTBIT_S32_LE,
3944#endif
3945 .rates = (SNDRV_PCM_RATE_32000 |
3946 SNDRV_PCM_RATE_44100 |
3947 SNDRV_PCM_RATE_48000 |
3948 SNDRV_PCM_RATE_64000 |
3949 SNDRV_PCM_RATE_88200 |
3950 SNDRV_PCM_RATE_96000),
3951 .rate_min = 32000,
3952 .rate_max = 96000,
3953 .channels_min = 14,
3954 .channels_max = HDSP_MAX_CHANNELS,
3955 .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS,
3956 .period_bytes_min = (64 * 4) * 10,
3957 .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS,
3958 .periods_min = 2,
3959 .periods_max = 2,
3960 .fifo_size = 0
3961};
3962
Takashi Iwai55e957d2005-11-17 14:52:13 +01003963static struct snd_pcm_hardware snd_hdsp_capture_subinfo =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964{
3965 .info = (SNDRV_PCM_INFO_MMAP |
3966 SNDRV_PCM_INFO_MMAP_VALID |
3967 SNDRV_PCM_INFO_NONINTERLEAVED |
3968 SNDRV_PCM_INFO_SYNC_START),
3969#ifdef SNDRV_BIG_ENDIAN
3970 .formats = SNDRV_PCM_FMTBIT_S32_BE,
3971#else
3972 .formats = SNDRV_PCM_FMTBIT_S32_LE,
3973#endif
3974 .rates = (SNDRV_PCM_RATE_32000 |
3975 SNDRV_PCM_RATE_44100 |
3976 SNDRV_PCM_RATE_48000 |
3977 SNDRV_PCM_RATE_64000 |
3978 SNDRV_PCM_RATE_88200 |
3979 SNDRV_PCM_RATE_96000),
3980 .rate_min = 32000,
3981 .rate_max = 96000,
3982 .channels_min = 14,
3983 .channels_max = HDSP_MAX_CHANNELS,
3984 .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS,
3985 .period_bytes_min = (64 * 4) * 10,
3986 .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS,
3987 .periods_min = 2,
3988 .periods_max = 2,
3989 .fifo_size = 0
3990};
3991
3992static unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
3993
Takashi Iwai55e957d2005-11-17 14:52:13 +01003994static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_period_sizes = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995 .count = ARRAY_SIZE(hdsp_period_sizes),
3996 .list = hdsp_period_sizes,
3997 .mask = 0
3998};
3999
4000static unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 };
4001
Takashi Iwai55e957d2005-11-17 14:52:13 +01004002static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_9632_sample_rates = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003 .count = ARRAY_SIZE(hdsp_9632_sample_rates),
4004 .list = hdsp_9632_sample_rates,
4005 .mask = 0
4006};
4007
Takashi Iwai55e957d2005-11-17 14:52:13 +01004008static int snd_hdsp_hw_rule_in_channels(struct snd_pcm_hw_params *params,
4009 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004011 struct hdsp *hdsp = rule->private;
4012 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013 if (hdsp->io_type == H9632) {
4014 unsigned int list[3];
4015 list[0] = hdsp->qs_in_channels;
4016 list[1] = hdsp->ds_in_channels;
4017 list[2] = hdsp->ss_in_channels;
4018 return snd_interval_list(c, 3, list, 0);
4019 } else {
4020 unsigned int list[2];
4021 list[0] = hdsp->ds_in_channels;
4022 list[1] = hdsp->ss_in_channels;
4023 return snd_interval_list(c, 2, list, 0);
4024 }
4025}
4026
Takashi Iwai55e957d2005-11-17 14:52:13 +01004027static int snd_hdsp_hw_rule_out_channels(struct snd_pcm_hw_params *params,
4028 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029{
4030 unsigned int list[3];
Takashi Iwai55e957d2005-11-17 14:52:13 +01004031 struct hdsp *hdsp = rule->private;
4032 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033 if (hdsp->io_type == H9632) {
4034 list[0] = hdsp->qs_out_channels;
4035 list[1] = hdsp->ds_out_channels;
4036 list[2] = hdsp->ss_out_channels;
4037 return snd_interval_list(c, 3, list, 0);
4038 } else {
4039 list[0] = hdsp->ds_out_channels;
4040 list[1] = hdsp->ss_out_channels;
4041 }
4042 return snd_interval_list(c, 2, list, 0);
4043}
4044
Takashi Iwai55e957d2005-11-17 14:52:13 +01004045static int snd_hdsp_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
4046 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004048 struct hdsp *hdsp = rule->private;
4049 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4050 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 if (r->min > 96000 && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004052 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053 .min = hdsp->qs_in_channels,
4054 .max = hdsp->qs_in_channels,
4055 .integer = 1,
4056 };
4057 return snd_interval_refine(c, &t);
4058 } else if (r->min > 48000 && r->max <= 96000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004059 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 .min = hdsp->ds_in_channels,
4061 .max = hdsp->ds_in_channels,
4062 .integer = 1,
4063 };
4064 return snd_interval_refine(c, &t);
4065 } else if (r->max < 64000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004066 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067 .min = hdsp->ss_in_channels,
4068 .max = hdsp->ss_in_channels,
4069 .integer = 1,
4070 };
4071 return snd_interval_refine(c, &t);
4072 }
4073 return 0;
4074}
4075
Takashi Iwai55e957d2005-11-17 14:52:13 +01004076static int snd_hdsp_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
4077 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004079 struct hdsp *hdsp = rule->private;
4080 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4081 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082 if (r->min > 96000 && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004083 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084 .min = hdsp->qs_out_channels,
4085 .max = hdsp->qs_out_channels,
4086 .integer = 1,
4087 };
4088 return snd_interval_refine(c, &t);
4089 } else if (r->min > 48000 && r->max <= 96000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004090 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091 .min = hdsp->ds_out_channels,
4092 .max = hdsp->ds_out_channels,
4093 .integer = 1,
4094 };
4095 return snd_interval_refine(c, &t);
4096 } else if (r->max < 64000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004097 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098 .min = hdsp->ss_out_channels,
4099 .max = hdsp->ss_out_channels,
4100 .integer = 1,
4101 };
4102 return snd_interval_refine(c, &t);
4103 }
4104 return 0;
4105}
4106
Takashi Iwai55e957d2005-11-17 14:52:13 +01004107static int snd_hdsp_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
4108 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004110 struct hdsp *hdsp = rule->private;
4111 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4112 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113 if (c->min >= hdsp->ss_out_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004114 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115 .min = 32000,
4116 .max = 48000,
4117 .integer = 1,
4118 };
4119 return snd_interval_refine(r, &t);
4120 } else if (c->max <= hdsp->qs_out_channels && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004121 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122 .min = 128000,
4123 .max = 192000,
4124 .integer = 1,
4125 };
4126 return snd_interval_refine(r, &t);
4127 } else if (c->max <= hdsp->ds_out_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004128 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129 .min = 64000,
4130 .max = 96000,
4131 .integer = 1,
4132 };
4133 return snd_interval_refine(r, &t);
4134 }
4135 return 0;
4136}
4137
Takashi Iwai55e957d2005-11-17 14:52:13 +01004138static int snd_hdsp_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
4139 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004141 struct hdsp *hdsp = rule->private;
4142 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4143 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144 if (c->min >= hdsp->ss_in_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004145 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146 .min = 32000,
4147 .max = 48000,
4148 .integer = 1,
4149 };
4150 return snd_interval_refine(r, &t);
4151 } else if (c->max <= hdsp->qs_in_channels && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004152 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153 .min = 128000,
4154 .max = 192000,
4155 .integer = 1,
4156 };
4157 return snd_interval_refine(r, &t);
4158 } else if (c->max <= hdsp->ds_in_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004159 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160 .min = 64000,
4161 .max = 96000,
4162 .integer = 1,
4163 };
4164 return snd_interval_refine(r, &t);
4165 }
4166 return 0;
4167}
4168
Takashi Iwai55e957d2005-11-17 14:52:13 +01004169static int snd_hdsp_playback_open(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004171 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4172 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173
Takashi Iwaib0b98112005-10-20 18:29:58 +02004174 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176
Takashi Iwaib0b98112005-10-20 18:29:58 +02004177 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179
4180 spin_lock_irq(&hdsp->lock);
4181
4182 snd_pcm_set_sync(substream);
4183
4184 runtime->hw = snd_hdsp_playback_subinfo;
4185 runtime->dma_area = hdsp->playback_buffer;
4186 runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
4187
4188 hdsp->playback_pid = current->pid;
4189 hdsp->playback_substream = substream;
4190
4191 spin_unlock_irq(&hdsp->lock);
4192
4193 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4194 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 +02004195 if (hdsp->clock_source_locked) {
4196 runtime->hw.rate_min = runtime->hw.rate_max = hdsp->system_sample_rate;
4197 } else if (hdsp->io_type == H9632) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198 runtime->hw.rate_max = 192000;
4199 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
4200 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates);
4201 }
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02004202 if (hdsp->io_type == H9632) {
4203 runtime->hw.channels_min = hdsp->qs_out_channels;
4204 runtime->hw.channels_max = hdsp->ss_out_channels;
4205 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206
4207 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4208 snd_hdsp_hw_rule_out_channels, hdsp,
4209 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4210 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4211 snd_hdsp_hw_rule_out_channels_rate, hdsp,
4212 SNDRV_PCM_HW_PARAM_RATE, -1);
4213 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4214 snd_hdsp_hw_rule_rate_out_channels, hdsp,
4215 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4216
4217 hdsp->creg_spdif_stream = hdsp->creg_spdif;
4218 hdsp->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
4219 snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
4220 SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id);
4221 return 0;
4222}
4223
Takashi Iwai55e957d2005-11-17 14:52:13 +01004224static int snd_hdsp_playback_release(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004226 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227
4228 spin_lock_irq(&hdsp->lock);
4229
4230 hdsp->playback_pid = -1;
4231 hdsp->playback_substream = NULL;
4232
4233 spin_unlock_irq(&hdsp->lock);
4234
4235 hdsp->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
4236 snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
4237 SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id);
4238 return 0;
4239}
4240
4241
Takashi Iwai55e957d2005-11-17 14:52:13 +01004242static int snd_hdsp_capture_open(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004243{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004244 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4245 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246
Takashi Iwaib0b98112005-10-20 18:29:58 +02004247 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249
Takashi Iwaib0b98112005-10-20 18:29:58 +02004250 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252
4253 spin_lock_irq(&hdsp->lock);
4254
4255 snd_pcm_set_sync(substream);
4256
4257 runtime->hw = snd_hdsp_capture_subinfo;
4258 runtime->dma_area = hdsp->capture_buffer;
4259 runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
4260
4261 hdsp->capture_pid = current->pid;
4262 hdsp->capture_substream = substream;
4263
4264 spin_unlock_irq(&hdsp->lock);
4265
4266 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4267 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes);
4268 if (hdsp->io_type == H9632) {
4269 runtime->hw.channels_min = hdsp->qs_in_channels;
4270 runtime->hw.channels_max = hdsp->ss_in_channels;
4271 runtime->hw.rate_max = 192000;
4272 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
4273 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates);
4274 }
4275 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4276 snd_hdsp_hw_rule_in_channels, hdsp,
4277 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4278 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4279 snd_hdsp_hw_rule_in_channels_rate, hdsp,
4280 SNDRV_PCM_HW_PARAM_RATE, -1);
4281 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4282 snd_hdsp_hw_rule_rate_in_channels, hdsp,
4283 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4284 return 0;
4285}
4286
Takashi Iwai55e957d2005-11-17 14:52:13 +01004287static int snd_hdsp_capture_release(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004289 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004290
4291 spin_lock_irq(&hdsp->lock);
4292
4293 hdsp->capture_pid = -1;
4294 hdsp->capture_substream = NULL;
4295
4296 spin_unlock_irq(&hdsp->lock);
4297 return 0;
4298}
4299
Takashi Iwai55e957d2005-11-17 14:52:13 +01004300static int snd_hdsp_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301{
4302 /* we have nothing to initialize but the call is required */
4303 return 0;
4304}
4305
4306
4307/* helper functions for copying meter values */
4308static inline int copy_u32_le(void __user *dest, void __iomem *src)
4309{
4310 u32 val = readl(src);
4311 return copy_to_user(dest, &val, 4);
4312}
4313
4314static inline int copy_u64_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
4315{
4316 u32 rms_low, rms_high;
4317 u64 rms;
4318 rms_low = readl(src_low);
4319 rms_high = readl(src_high);
4320 rms = ((u64)rms_high << 32) | rms_low;
4321 return copy_to_user(dest, &rms, 8);
4322}
4323
4324static inline int copy_u48_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
4325{
4326 u32 rms_low, rms_high;
4327 u64 rms;
4328 rms_low = readl(src_low) & 0xffffff00;
4329 rms_high = readl(src_high) & 0xffffff00;
4330 rms = ((u64)rms_high << 32) | rms_low;
4331 return copy_to_user(dest, &rms, 8);
4332}
4333
Takashi Iwai55e957d2005-11-17 14:52:13 +01004334static int hdsp_9652_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004335{
4336 int doublespeed = 0;
4337 int i, j, channels, ofs;
4338
4339 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
4340 doublespeed = 1;
4341 channels = doublespeed ? 14 : 26;
4342 for (i = 0, j = 0; i < 26; ++i) {
4343 if (doublespeed && (i & 4))
4344 continue;
4345 ofs = HDSP_9652_peakBase - j * 4;
4346 if (copy_u32_le(&peak_rms->input_peaks[i], hdsp->iobase + ofs))
4347 return -EFAULT;
4348 ofs -= channels * 4;
4349 if (copy_u32_le(&peak_rms->playback_peaks[i], hdsp->iobase + ofs))
4350 return -EFAULT;
4351 ofs -= channels * 4;
4352 if (copy_u32_le(&peak_rms->output_peaks[i], hdsp->iobase + ofs))
4353 return -EFAULT;
4354 ofs = HDSP_9652_rmsBase + j * 8;
4355 if (copy_u48_le(&peak_rms->input_rms[i], hdsp->iobase + ofs,
4356 hdsp->iobase + ofs + 4))
4357 return -EFAULT;
4358 ofs += channels * 8;
4359 if (copy_u48_le(&peak_rms->playback_rms[i], hdsp->iobase + ofs,
4360 hdsp->iobase + ofs + 4))
4361 return -EFAULT;
4362 ofs += channels * 8;
4363 if (copy_u48_le(&peak_rms->output_rms[i], hdsp->iobase + ofs,
4364 hdsp->iobase + ofs + 4))
4365 return -EFAULT;
4366 j++;
4367 }
4368 return 0;
4369}
4370
Takashi Iwai55e957d2005-11-17 14:52:13 +01004371static int hdsp_9632_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372{
4373 int i, j;
Takashi Iwai55e957d2005-11-17 14:52:13 +01004374 struct hdsp_9632_meters __iomem *m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375 int doublespeed = 0;
4376
4377 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
4378 doublespeed = 1;
Takashi Iwai55e957d2005-11-17 14:52:13 +01004379 m = (struct hdsp_9632_meters __iomem *)(hdsp->iobase+HDSP_9632_metersBase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380 for (i = 0, j = 0; i < 16; ++i, ++j) {
4381 if (copy_u32_le(&peak_rms->input_peaks[i], &m->input_peak[j]))
4382 return -EFAULT;
4383 if (copy_u32_le(&peak_rms->playback_peaks[i], &m->playback_peak[j]))
4384 return -EFAULT;
4385 if (copy_u32_le(&peak_rms->output_peaks[i], &m->output_peak[j]))
4386 return -EFAULT;
4387 if (copy_u64_le(&peak_rms->input_rms[i], &m->input_rms_low[j],
4388 &m->input_rms_high[j]))
4389 return -EFAULT;
4390 if (copy_u64_le(&peak_rms->playback_rms[i], &m->playback_rms_low[j],
4391 &m->playback_rms_high[j]))
4392 return -EFAULT;
4393 if (copy_u64_le(&peak_rms->output_rms[i], &m->output_rms_low[j],
4394 &m->output_rms_high[j]))
4395 return -EFAULT;
4396 if (doublespeed && i == 3) i += 4;
4397 }
4398 return 0;
4399}
4400
Takashi Iwai55e957d2005-11-17 14:52:13 +01004401static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402{
4403 int i;
4404
4405 for (i = 0; i < 26; i++) {
4406 if (copy_u32_le(&peak_rms->playback_peaks[i],
4407 hdsp->iobase + HDSP_playbackPeakLevel + i * 4))
4408 return -EFAULT;
4409 if (copy_u32_le(&peak_rms->input_peaks[i],
4410 hdsp->iobase + HDSP_inputPeakLevel + i * 4))
4411 return -EFAULT;
4412 }
4413 for (i = 0; i < 28; i++) {
4414 if (copy_u32_le(&peak_rms->output_peaks[i],
4415 hdsp->iobase + HDSP_outputPeakLevel + i * 4))
4416 return -EFAULT;
4417 }
4418 for (i = 0; i < 26; ++i) {
4419 if (copy_u64_le(&peak_rms->playback_rms[i],
4420 hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4,
4421 hdsp->iobase + HDSP_playbackRmsLevel + i * 8))
4422 return -EFAULT;
4423 if (copy_u64_le(&peak_rms->input_rms[i],
4424 hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4,
4425 hdsp->iobase + HDSP_inputRmsLevel + i * 8))
4426 return -EFAULT;
4427 }
4428 return 0;
4429}
4430
Takashi Iwai55e957d2005-11-17 14:52:13 +01004431static 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 -07004432{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004433 struct hdsp *hdsp = (struct hdsp *)hw->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434 void __user *argp = (void __user *)arg;
4435
4436 switch (cmd) {
4437 case SNDRV_HDSP_IOCTL_GET_PEAK_RMS: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004438 struct hdsp_peak_rms __user *peak_rms = (struct hdsp_peak_rms __user *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439
4440 if (!(hdsp->state & HDSP_FirmwareLoaded)) {
4441 snd_printk(KERN_ERR "Hammerfall-DSP: firmware needs to be uploaded to the card.\n");
4442 return -EINVAL;
4443 }
4444
4445 switch (hdsp->io_type) {
4446 case H9652:
4447 return hdsp_9652_get_peak(hdsp, peak_rms);
4448 case H9632:
4449 return hdsp_9632_get_peak(hdsp, peak_rms);
4450 default:
4451 return hdsp_get_peak(hdsp, peak_rms);
4452 }
4453 }
4454 case SNDRV_HDSP_IOCTL_GET_CONFIG_INFO: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004455 struct hdsp_config_info info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456 unsigned long flags;
4457 int i;
4458
4459 if (!(hdsp->state & HDSP_FirmwareLoaded)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004460 snd_printk(KERN_ERR "Hammerfall-DSP: Firmware needs to be uploaded to the card.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004461 return -EINVAL;
4462 }
4463 spin_lock_irqsave(&hdsp->lock, flags);
4464 info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp);
4465 info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02004466 if (hdsp->io_type != H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467 info.adatsync_sync_check = (unsigned char)hdsp_adatsync_sync_check(hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004468 info.spdif_sync_check = (unsigned char)hdsp_spdif_sync_check(hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02004469 for (i = 0; i < ((hdsp->io_type != Multiface && hdsp->io_type != H9632) ? 3 : 1); ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470 info.adat_sync_check[i] = (unsigned char)hdsp_adat_sync_check(hdsp, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004471 info.spdif_in = (unsigned char)hdsp_spdif_in(hdsp);
4472 info.spdif_out = (unsigned char)hdsp_spdif_out(hdsp);
4473 info.spdif_professional = (unsigned char)hdsp_spdif_professional(hdsp);
4474 info.spdif_emphasis = (unsigned char)hdsp_spdif_emphasis(hdsp);
4475 info.spdif_nonaudio = (unsigned char)hdsp_spdif_nonaudio(hdsp);
4476 info.spdif_sample_rate = hdsp_spdif_sample_rate(hdsp);
4477 info.system_sample_rate = hdsp->system_sample_rate;
4478 info.autosync_sample_rate = hdsp_external_sample_rate(hdsp);
4479 info.system_clock_mode = (unsigned char)hdsp_system_clock_mode(hdsp);
4480 info.clock_source = (unsigned char)hdsp_clock_source(hdsp);
4481 info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp);
4482 info.line_out = (unsigned char)hdsp_line_out(hdsp);
4483 if (hdsp->io_type == H9632) {
4484 info.da_gain = (unsigned char)hdsp_da_gain(hdsp);
4485 info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp);
4486 info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp);
4487 info.xlr_breakout_cable = (unsigned char)hdsp_xlr_breakout_cable(hdsp);
4488
4489 }
Takashi Iwaib0b98112005-10-20 18:29:58 +02004490 if (hdsp->io_type == H9632 || hdsp->io_type == H9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491 info.analog_extension_board = (unsigned char)hdsp_aeb(hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 spin_unlock_irqrestore(&hdsp->lock, flags);
4493 if (copy_to_user(argp, &info, sizeof(info)))
4494 return -EFAULT;
4495 break;
4496 }
4497 case SNDRV_HDSP_IOCTL_GET_9632_AEB: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004498 struct hdsp_9632_aeb h9632_aeb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004499
4500 if (hdsp->io_type != H9632) return -EINVAL;
4501 h9632_aeb.aebi = hdsp->ss_in_channels - H9632_SS_CHANNELS;
4502 h9632_aeb.aebo = hdsp->ss_out_channels - H9632_SS_CHANNELS;
4503 if (copy_to_user(argp, &h9632_aeb, sizeof(h9632_aeb)))
4504 return -EFAULT;
4505 break;
4506 }
4507 case SNDRV_HDSP_IOCTL_GET_VERSION: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004508 struct hdsp_version hdsp_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004509 int err;
4510
4511 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
4512 if (hdsp->io_type == Undefined) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004513 if ((err = hdsp_get_iobox_version(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515 }
4516 hdsp_version.io_type = hdsp->io_type;
4517 hdsp_version.firmware_rev = hdsp->firmware_rev;
Takashi Iwaib0b98112005-10-20 18:29:58 +02004518 if ((err = copy_to_user(argp, &hdsp_version, sizeof(hdsp_version))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004519 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520 break;
4521 }
4522 case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004523 struct hdsp_firmware __user *firmware;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004524 u32 __user *firmware_data;
4525 int err;
4526
4527 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
4528 /* SNDRV_HDSP_IOCTL_GET_VERSION must have been called */
4529 if (hdsp->io_type == Undefined) return -EINVAL;
4530
4531 if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded))
4532 return -EBUSY;
4533
Takashi Iwaib0b98112005-10-20 18:29:58 +02004534 snd_printk(KERN_INFO "Hammerfall-DSP: initializing firmware upload\n");
Takashi Iwai55e957d2005-11-17 14:52:13 +01004535 firmware = (struct hdsp_firmware __user *)argp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004536
Takashi Iwaib0b98112005-10-20 18:29:58 +02004537 if (get_user(firmware_data, &firmware->firmware_data))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004538 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004539
Takashi Iwaib0b98112005-10-20 18:29:58 +02004540 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004542
Takashi Iwaib0b98112005-10-20 18:29:58 +02004543 if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004544 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004545
4546 hdsp->state |= HDSP_FirmwareCached;
4547
Takashi Iwaib0b98112005-10-20 18:29:58 +02004548 if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004549 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550
4551 if (!(hdsp->state & HDSP_InitializationComplete)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004552 if ((err = snd_hdsp_enable_io(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004553 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554
4555 snd_hdsp_initialize_channels(hdsp);
4556 snd_hdsp_initialize_midi_flush(hdsp);
4557
4558 if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004559 snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n");
4560 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004561 }
4562 }
4563 break;
4564 }
4565 case SNDRV_HDSP_IOCTL_GET_MIXER: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004566 struct hdsp_mixer __user *mixer = (struct hdsp_mixer __user *)argp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004567 if (copy_to_user(mixer->matrix, hdsp->mixer_matrix, sizeof(unsigned short)*HDSP_MATRIX_MIXER_SIZE))
4568 return -EFAULT;
4569 break;
4570 }
4571 default:
4572 return -EINVAL;
4573 }
4574 return 0;
4575}
4576
Takashi Iwai55e957d2005-11-17 14:52:13 +01004577static struct snd_pcm_ops snd_hdsp_playback_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004578 .open = snd_hdsp_playback_open,
4579 .close = snd_hdsp_playback_release,
4580 .ioctl = snd_hdsp_ioctl,
4581 .hw_params = snd_hdsp_hw_params,
4582 .prepare = snd_hdsp_prepare,
4583 .trigger = snd_hdsp_trigger,
4584 .pointer = snd_hdsp_hw_pointer,
4585 .copy = snd_hdsp_playback_copy,
4586 .silence = snd_hdsp_hw_silence,
4587};
4588
Takashi Iwai55e957d2005-11-17 14:52:13 +01004589static struct snd_pcm_ops snd_hdsp_capture_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004590 .open = snd_hdsp_capture_open,
4591 .close = snd_hdsp_capture_release,
4592 .ioctl = snd_hdsp_ioctl,
4593 .hw_params = snd_hdsp_hw_params,
4594 .prepare = snd_hdsp_prepare,
4595 .trigger = snd_hdsp_trigger,
4596 .pointer = snd_hdsp_hw_pointer,
4597 .copy = snd_hdsp_capture_copy,
4598};
4599
Takashi Iwai55e957d2005-11-17 14:52:13 +01004600static int __devinit snd_hdsp_create_hwdep(struct snd_card *card,
4601 struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004602{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004603 struct snd_hwdep *hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004604 int err;
4605
4606 if ((err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw)) < 0)
4607 return err;
4608
4609 hdsp->hwdep = hw;
4610 hw->private_data = hdsp;
4611 strcpy(hw->name, "HDSP hwdep interface");
4612
4613 hw->ops.open = snd_hdsp_hwdep_dummy_op;
4614 hw->ops.ioctl = snd_hdsp_hwdep_ioctl;
4615 hw->ops.release = snd_hdsp_hwdep_dummy_op;
4616
4617 return 0;
4618}
4619
Takashi Iwai55e957d2005-11-17 14:52:13 +01004620static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004621{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004622 struct snd_pcm *pcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004623 int err;
4624
4625 if ((err = snd_pcm_new(card, hdsp->card_name, 0, 1, 1, &pcm)) < 0)
4626 return err;
4627
4628 hdsp->pcm = pcm;
4629 pcm->private_data = hdsp;
4630 strcpy(pcm->name, hdsp->card_name);
4631
4632 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_hdsp_playback_ops);
4633 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_hdsp_capture_ops);
4634
4635 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
4636
4637 return 0;
4638}
4639
Takashi Iwai55e957d2005-11-17 14:52:13 +01004640static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004641{
4642 hdsp->control2_register |= HDSP_9652_ENABLE_MIXER;
4643 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
4644}
4645
Takashi Iwai55e957d2005-11-17 14:52:13 +01004646static int snd_hdsp_enable_io (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004647{
4648 int i;
4649
4650 if (hdsp_fifo_wait (hdsp, 0, 100)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004651 snd_printk(KERN_ERR "Hammerfall-DSP: enable_io fifo_wait failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004652 return -EIO;
4653 }
4654
4655 for (i = 0; i < hdsp->max_channels; ++i) {
4656 hdsp_write (hdsp, HDSP_inputEnable + (4 * i), 1);
4657 hdsp_write (hdsp, HDSP_outputEnable + (4 * i), 1);
4658 }
4659
4660 return 0;
4661}
4662
Takashi Iwai55e957d2005-11-17 14:52:13 +01004663static void snd_hdsp_initialize_channels(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004664{
4665 int status, aebi_channels, aebo_channels;
4666
4667 switch (hdsp->io_type) {
4668 case Digiface:
4669 hdsp->card_name = "RME Hammerfall DSP + Digiface";
4670 hdsp->ss_in_channels = hdsp->ss_out_channels = DIGIFACE_SS_CHANNELS;
4671 hdsp->ds_in_channels = hdsp->ds_out_channels = DIGIFACE_DS_CHANNELS;
4672 break;
4673
4674 case H9652:
4675 hdsp->card_name = "RME Hammerfall HDSP 9652";
4676 hdsp->ss_in_channels = hdsp->ss_out_channels = H9652_SS_CHANNELS;
4677 hdsp->ds_in_channels = hdsp->ds_out_channels = H9652_DS_CHANNELS;
4678 break;
4679
4680 case H9632:
4681 status = hdsp_read(hdsp, HDSP_statusRegister);
4682 /* HDSP_AEBx bits are low when AEB are connected */
4683 aebi_channels = (status & HDSP_AEBI) ? 0 : 4;
4684 aebo_channels = (status & HDSP_AEBO) ? 0 : 4;
4685 hdsp->card_name = "RME Hammerfall HDSP 9632";
4686 hdsp->ss_in_channels = H9632_SS_CHANNELS+aebi_channels;
4687 hdsp->ds_in_channels = H9632_DS_CHANNELS+aebi_channels;
4688 hdsp->qs_in_channels = H9632_QS_CHANNELS+aebi_channels;
4689 hdsp->ss_out_channels = H9632_SS_CHANNELS+aebo_channels;
4690 hdsp->ds_out_channels = H9632_DS_CHANNELS+aebo_channels;
4691 hdsp->qs_out_channels = H9632_QS_CHANNELS+aebo_channels;
4692 break;
4693
4694 case Multiface:
4695 hdsp->card_name = "RME Hammerfall DSP + Multiface";
4696 hdsp->ss_in_channels = hdsp->ss_out_channels = MULTIFACE_SS_CHANNELS;
4697 hdsp->ds_in_channels = hdsp->ds_out_channels = MULTIFACE_DS_CHANNELS;
4698 break;
4699
4700 default:
4701 /* should never get here */
4702 break;
4703 }
4704}
4705
Takashi Iwai55e957d2005-11-17 14:52:13 +01004706static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004707{
4708 snd_hdsp_flush_midi_input (hdsp, 0);
4709 snd_hdsp_flush_midi_input (hdsp, 1);
4710}
4711
Takashi Iwai55e957d2005-11-17 14:52:13 +01004712static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004713{
4714 int err;
4715
4716 if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004717 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating pcm interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004718 return err;
4719 }
4720
4721
4722 if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004723 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating first midi interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004724 return err;
4725 }
4726
4727 if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
4728 if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004729 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating second midi interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004730 return err;
4731 }
4732 }
4733
4734 if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004735 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating ctl interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004736 return err;
4737 }
4738
4739 snd_hdsp_proc_init(hdsp);
4740
4741 hdsp->system_sample_rate = -1;
4742 hdsp->playback_pid = -1;
4743 hdsp->capture_pid = -1;
4744 hdsp->capture_substream = NULL;
4745 hdsp->playback_substream = NULL;
4746
4747 if ((err = snd_hdsp_set_defaults(hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004748 snd_printk(KERN_ERR "Hammerfall-DSP: Error setting default values\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004749 return err;
4750 }
4751
4752 if (!(hdsp->state & HDSP_InitializationComplete)) {
Clemens Ladischb73c1c12005-09-02 08:49:21 +02004753 strcpy(card->shortname, "Hammerfall DSP");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004754 sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
4755 hdsp->port, hdsp->irq);
4756
4757 if ((err = snd_card_register(card)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004758 snd_printk(KERN_ERR "Hammerfall-DSP: error registering card\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004759 return err;
4760 }
4761 hdsp->state |= HDSP_InitializationComplete;
4762 }
4763
4764 return 0;
4765}
4766
4767#ifdef HDSP_FW_LOADER
4768/* load firmware via hotplug fw loader */
Takashi Iwai55e957d2005-11-17 14:52:13 +01004769static int __devinit hdsp_request_fw_loader(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004770{
4771 const char *fwfile;
4772 const struct firmware *fw;
4773 int err;
4774
4775 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
4776 return 0;
4777 if (hdsp->io_type == Undefined) {
4778 if ((err = hdsp_get_iobox_version(hdsp)) < 0)
4779 return err;
4780 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
4781 return 0;
4782 }
4783
4784 /* caution: max length of firmware filename is 30! */
4785 switch (hdsp->io_type) {
4786 case Multiface:
4787 if (hdsp->firmware_rev == 0xa)
4788 fwfile = "multiface_firmware.bin";
4789 else
4790 fwfile = "multiface_firmware_rev11.bin";
4791 break;
4792 case Digiface:
4793 if (hdsp->firmware_rev == 0xa)
4794 fwfile = "digiface_firmware.bin";
4795 else
4796 fwfile = "digiface_firmware_rev11.bin";
4797 break;
4798 default:
4799 snd_printk(KERN_ERR "Hammerfall-DSP: invalid io_type %d\n", hdsp->io_type);
4800 return -EINVAL;
4801 }
4802
4803 if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) {
4804 snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile);
4805 return -ENOENT;
4806 }
4807 if (fw->size < sizeof(hdsp->firmware_cache)) {
4808 snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n",
4809 (int)fw->size, (int)sizeof(hdsp->firmware_cache));
4810 release_firmware(fw);
4811 return -EINVAL;
4812 }
Thomas Charbonnel7679a032005-04-25 11:35:29 +02004813
Linus Torvalds1da177e2005-04-16 15:20:36 -07004814 memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache));
Thomas Charbonnel7679a032005-04-25 11:35:29 +02004815
Linus Torvalds1da177e2005-04-16 15:20:36 -07004816 release_firmware(fw);
4817
4818 hdsp->state |= HDSP_FirmwareCached;
4819
4820 if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
4821 return err;
4822
4823 if (!(hdsp->state & HDSP_InitializationComplete)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004824 if ((err = snd_hdsp_enable_io(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004825 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004826
4827 if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004828 snd_printk(KERN_ERR "Hammerfall-DSP: error creating hwdep device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004829 return err;
4830 }
4831 snd_hdsp_initialize_channels(hdsp);
4832 snd_hdsp_initialize_midi_flush(hdsp);
4833 if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004834 snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004835 return err;
4836 }
4837 }
4838 return 0;
4839}
4840#endif
4841
Takashi Iwai55e957d2005-11-17 14:52:13 +01004842static int __devinit snd_hdsp_create(struct snd_card *card,
4843 struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004844{
4845 struct pci_dev *pci = hdsp->pci;
4846 int err;
4847 int is_9652 = 0;
4848 int is_9632 = 0;
4849
4850 hdsp->irq = -1;
4851 hdsp->state = 0;
4852 hdsp->midi[0].rmidi = NULL;
4853 hdsp->midi[1].rmidi = NULL;
4854 hdsp->midi[0].input = NULL;
4855 hdsp->midi[1].input = NULL;
4856 hdsp->midi[0].output = NULL;
4857 hdsp->midi[1].output = NULL;
4858 hdsp->midi[0].pending = 0;
4859 hdsp->midi[1].pending = 0;
4860 spin_lock_init(&hdsp->midi[0].lock);
4861 spin_lock_init(&hdsp->midi[1].lock);
4862 hdsp->iobase = NULL;
4863 hdsp->control_register = 0;
4864 hdsp->control2_register = 0;
4865 hdsp->io_type = Undefined;
4866 hdsp->max_channels = 26;
4867
4868 hdsp->card = card;
4869
4870 spin_lock_init(&hdsp->lock);
4871
4872 tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp);
4873
4874 pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev);
4875 hdsp->firmware_rev &= 0xff;
4876
4877 /* From Martin Bjoernsen :
4878 "It is important that the card's latency timer register in
4879 the PCI configuration space is set to a value much larger
4880 than 0 by the computer's BIOS or the driver.
4881 The windows driver always sets this 8 bit register [...]
4882 to its maximum 255 to avoid problems with some computers."
4883 */
4884 pci_write_config_byte(hdsp->pci, PCI_LATENCY_TIMER, 0xFF);
4885
4886 strcpy(card->driver, "H-DSP");
4887 strcpy(card->mixername, "Xilinx FPGA");
4888
Takashi Iwaib0b98112005-10-20 18:29:58 +02004889 if (hdsp->firmware_rev < 0xa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004890 return -ENODEV;
Takashi Iwaib0b98112005-10-20 18:29:58 +02004891 else if (hdsp->firmware_rev < 0x64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004892 hdsp->card_name = "RME Hammerfall DSP";
Takashi Iwaib0b98112005-10-20 18:29:58 +02004893 else if (hdsp->firmware_rev < 0x96) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004894 hdsp->card_name = "RME HDSP 9652";
4895 is_9652 = 1;
4896 } else {
4897 hdsp->card_name = "RME HDSP 9632";
4898 hdsp->max_channels = 16;
4899 is_9632 = 1;
4900 }
4901
Takashi Iwaib0b98112005-10-20 18:29:58 +02004902 if ((err = pci_enable_device(pci)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004903 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004904
4905 pci_set_master(hdsp->pci);
4906
4907 if ((err = pci_request_regions(pci, "hdsp")) < 0)
4908 return err;
4909 hdsp->port = pci_resource_start(pci, 0);
4910 if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004911 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 -07004912 return -EBUSY;
4913 }
4914
Thomas Gleixner65ca68b2006-07-01 19:29:46 -07004915 if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_DISABLED|IRQF_SHARED, "hdsp", (void *)hdsp)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004916 snd_printk(KERN_ERR "Hammerfall-DSP: unable to use IRQ %d\n", pci->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004917 return -EBUSY;
4918 }
4919
4920 hdsp->irq = pci->irq;
4921 hdsp->precise_ptr = 1;
4922 hdsp->use_midi_tasklet = 1;
4923
Takashi Iwaib0b98112005-10-20 18:29:58 +02004924 if ((err = snd_hdsp_initialize_memory(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004925 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004926
4927 if (!is_9652 && !is_9632) {
4928 /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */
Takashi Iwaib0b98112005-10-20 18:29:58 +02004929 ssleep(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004930
4931 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
4932#ifdef HDSP_FW_LOADER
Takashi Iwaib0b98112005-10-20 18:29:58 +02004933 if ((err = hdsp_request_fw_loader(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004934 /* we don't fail as this can happen
4935 if userspace is not ready for
4936 firmware upload
4937 */
Takashi Iwaib0b98112005-10-20 18:29:58 +02004938 snd_printk(KERN_ERR "Hammerfall-DSP: couldn't get firmware from userspace. try using hdsploader\n");
4939 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004940 /* init is complete, we return */
4941 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004942#endif
4943 /* no iobox connected, we defer initialization */
Takashi Iwaib0b98112005-10-20 18:29:58 +02004944 snd_printk(KERN_INFO "Hammerfall-DSP: card initialization pending : waiting for firmware\n");
4945 if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004946 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004947 return 0;
4948 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004949 snd_printk(KERN_INFO "Hammerfall-DSP: Firmware already present, initializing card.\n");
4950 if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004951 hdsp->io_type = Multiface;
Takashi Iwaib0b98112005-10-20 18:29:58 +02004952 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004953 hdsp->io_type = Digiface;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004954 }
4955 }
4956
Takashi Iwaib0b98112005-10-20 18:29:58 +02004957 if ((err = snd_hdsp_enable_io(hdsp)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004958 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004959
Takashi Iwaib0b98112005-10-20 18:29:58 +02004960 if (is_9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004961 hdsp->io_type = H9652;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004962
Takashi Iwaib0b98112005-10-20 18:29:58 +02004963 if (is_9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004964 hdsp->io_type = H9632;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004965
Takashi Iwaib0b98112005-10-20 18:29:58 +02004966 if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004967 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004968
4969 snd_hdsp_initialize_channels(hdsp);
4970 snd_hdsp_initialize_midi_flush(hdsp);
4971
4972 hdsp->state |= HDSP_FirmwareLoaded;
4973
Takashi Iwaib0b98112005-10-20 18:29:58 +02004974 if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004975 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004976
4977 return 0;
4978}
4979
Takashi Iwai55e957d2005-11-17 14:52:13 +01004980static int snd_hdsp_free(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004981{
4982 if (hdsp->port) {
4983 /* stop the audio, and cancel all interrupts */
4984 tasklet_kill(&hdsp->midi_tasklet);
4985 hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable);
4986 hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
4987 }
4988
4989 if (hdsp->irq >= 0)
4990 free_irq(hdsp->irq, (void *)hdsp);
4991
4992 snd_hdsp_free_buffers(hdsp);
4993
4994 if (hdsp->iobase)
4995 iounmap(hdsp->iobase);
4996
4997 if (hdsp->port)
4998 pci_release_regions(hdsp->pci);
4999
5000 pci_disable_device(hdsp->pci);
5001 return 0;
5002}
5003
Takashi Iwai55e957d2005-11-17 14:52:13 +01005004static void snd_hdsp_card_free(struct snd_card *card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005005{
Takashi Iwai55e957d2005-11-17 14:52:13 +01005006 struct hdsp *hdsp = (struct hdsp *) card->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005007
5008 if (hdsp)
5009 snd_hdsp_free(hdsp);
5010}
5011
5012static int __devinit snd_hdsp_probe(struct pci_dev *pci,
5013 const struct pci_device_id *pci_id)
5014{
5015 static int dev;
Takashi Iwai55e957d2005-11-17 14:52:13 +01005016 struct hdsp *hdsp;
5017 struct snd_card *card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005018 int err;
5019
5020 if (dev >= SNDRV_CARDS)
5021 return -ENODEV;
5022 if (!enable[dev]) {
5023 dev++;
5024 return -ENOENT;
5025 }
5026
Takashi Iwai55e957d2005-11-17 14:52:13 +01005027 if (!(card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005028 return -ENOMEM;
5029
Takashi Iwai55e957d2005-11-17 14:52:13 +01005030 hdsp = (struct hdsp *) card->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005031 card->private_free = snd_hdsp_card_free;
5032 hdsp->dev = dev;
5033 hdsp->pci = pci;
5034 snd_card_set_dev(card, &pci->dev);
5035
5036 if ((err = snd_hdsp_create(card, hdsp)) < 0) {
5037 snd_card_free(card);
5038 return err;
5039 }
5040
5041 strcpy(card->shortname, "Hammerfall DSP");
5042 sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
5043 hdsp->port, hdsp->irq);
5044
5045 if ((err = snd_card_register(card)) < 0) {
5046 snd_card_free(card);
5047 return err;
5048 }
5049 pci_set_drvdata(pci, card);
5050 dev++;
5051 return 0;
5052}
5053
5054static void __devexit snd_hdsp_remove(struct pci_dev *pci)
5055{
5056 snd_card_free(pci_get_drvdata(pci));
5057 pci_set_drvdata(pci, NULL);
5058}
5059
5060static struct pci_driver driver = {
5061 .name = "RME Hammerfall DSP",
5062 .id_table = snd_hdsp_ids,
5063 .probe = snd_hdsp_probe,
5064 .remove = __devexit_p(snd_hdsp_remove),
5065};
5066
5067static int __init alsa_card_hdsp_init(void)
5068{
Takashi Iwai01d25d42005-04-11 16:58:24 +02005069 return pci_register_driver(&driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005070}
5071
5072static void __exit alsa_card_hdsp_exit(void)
5073{
5074 pci_unregister_driver(&driver);
5075}
5076
5077module_init(alsa_card_hdsp_init)
5078module_exit(alsa_card_hdsp_exit)