blob: af2e59e5edf2843c98d5d884c491db12ee740acb [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 Iwai311e70a2006-09-06 12:13:37 +0200729#ifdef HDSP_FW_LOADER
730static int __devinit hdsp_request_fw_loader(struct hdsp *hdsp);
731#endif
732
733static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734{
Takashi Iwai311e70a2006-09-06 12:13:37 +0200735 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
736 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 hdsp->state &= ~HDSP_FirmwareLoaded;
Takashi Iwai311e70a2006-09-06 12:13:37 +0200739 if (! load_on_demand)
Takashi Iwaib0b98112005-10-20 18:29:58 +0200740 return -EIO;
Takashi Iwai311e70a2006-09-06 12:13:37 +0200741 snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +0200742 /* try to load firmware */
Takashi Iwai311e70a2006-09-06 12:13:37 +0200743 if (! (hdsp->state & HDSP_FirmwareCached)) {
744#ifdef HDSP_FW_LOADER
745 if (! hdsp_request_fw_loader(hdsp))
746 return 0;
747#endif
748 snd_printk(KERN_ERR
749 "Hammerfall-DSP: No firmware loaded nor "
750 "cached, please upload firmware.\n");
751 return -EIO;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200752 }
Takashi Iwai311e70a2006-09-06 12:13:37 +0200753 if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
754 snd_printk(KERN_ERR
755 "Hammerfall-DSP: Firmware loading from "
756 "cache failed, please upload manually.\n");
757 return -EIO;
758 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 }
760 return 0;
761}
762
763
Takashi Iwai55e957d2005-11-17 14:52:13 +0100764static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765{
766 int i;
767
768 /* the fifoStatus registers reports on how many words
769 are available in the command FIFO.
770 */
771
772 for (i = 0; i < timeout; i++) {
773
774 if ((int)(hdsp_read (hdsp, HDSP_fifoStatus) & 0xff) <= count)
775 return 0;
776
777 /* not very friendly, but we only do this during a firmware
778 load and changing the mixer, so we just put up with it.
779 */
780
781 udelay (100);
782 }
783
784 snd_printk ("Hammerfall-DSP: wait for FIFO status <= %d failed after %d iterations\n",
785 count, timeout);
786 return -1;
787}
788
Takashi Iwai55e957d2005-11-17 14:52:13 +0100789static int hdsp_read_gain (struct hdsp *hdsp, unsigned int addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790{
Takashi Iwaib0b98112005-10-20 18:29:58 +0200791 if (addr >= HDSP_MATRIX_MIXER_SIZE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200793
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 return hdsp->mixer_matrix[addr];
795}
796
Takashi Iwai55e957d2005-11-17 14:52:13 +0100797static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798{
799 unsigned int ad;
800
801 if (addr >= HDSP_MATRIX_MIXER_SIZE)
802 return -1;
803
804 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) {
805
806 /* from martin bjornsen:
807
808 "You can only write dwords to the
809 mixer memory which contain two
810 mixer values in the low and high
811 word. So if you want to change
812 value 0 you have to read value 1
813 from the cache and write both to
814 the first dword in the mixer
815 memory."
816 */
817
Takashi Iwaib0b98112005-10-20 18:29:58 +0200818 if (hdsp->io_type == H9632 && addr >= 512)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820
Takashi Iwaib0b98112005-10-20 18:29:58 +0200821 if (hdsp->io_type == H9652 && addr >= 1352)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
824 hdsp->mixer_matrix[addr] = data;
825
826
827 /* `addr' addresses a 16-bit wide address, but
828 the address space accessed via hdsp_write
829 uses byte offsets. put another way, addr
830 varies from 0 to 1351, but to access the
831 corresponding memory location, we need
832 to access 0 to 2703 ...
833 */
834 ad = addr/2;
835
836 hdsp_write (hdsp, 4096 + (ad*4),
837 (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) +
838 hdsp->mixer_matrix[addr&0x7fe]);
839
840 return 0;
841
842 } else {
843
844 ad = (addr << 16) + data;
845
Takashi Iwaib0b98112005-10-20 18:29:58 +0200846 if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848
849 hdsp_write (hdsp, HDSP_fifoData, ad);
850 hdsp->mixer_matrix[addr] = data;
851
852 }
853
854 return 0;
855}
856
Takashi Iwai55e957d2005-11-17 14:52:13 +0100857static int snd_hdsp_use_is_exclusive(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858{
859 unsigned long flags;
860 int ret = 1;
861
862 spin_lock_irqsave(&hdsp->lock, flags);
863 if ((hdsp->playback_pid != hdsp->capture_pid) &&
Takashi Iwaib0b98112005-10-20 18:29:58 +0200864 (hdsp->playback_pid >= 0) && (hdsp->capture_pid >= 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 spin_unlock_irqrestore(&hdsp->lock, flags);
867 return ret;
868}
869
Takashi Iwai55e957d2005-11-17 14:52:13 +0100870static int hdsp_external_sample_rate (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871{
872 unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
873 unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
874
875 switch (rate_bits) {
876 case HDSP_systemFrequency32: return 32000;
877 case HDSP_systemFrequency44_1: return 44100;
878 case HDSP_systemFrequency48: return 48000;
879 case HDSP_systemFrequency64: return 64000;
880 case HDSP_systemFrequency88_2: return 88200;
881 case HDSP_systemFrequency96: return 96000;
882 default:
883 return 0;
884 }
885}
886
Takashi Iwai55e957d2005-11-17 14:52:13 +0100887static int hdsp_spdif_sample_rate(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888{
889 unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);
890 unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);
891
Takashi Iwaib0b98112005-10-20 18:29:58 +0200892 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894
895 switch (rate_bits) {
896 case HDSP_spdifFrequency32KHz: return 32000;
897 case HDSP_spdifFrequency44_1KHz: return 44100;
898 case HDSP_spdifFrequency48KHz: return 48000;
899 case HDSP_spdifFrequency64KHz: return 64000;
900 case HDSP_spdifFrequency88_2KHz: return 88200;
901 case HDSP_spdifFrequency96KHz: return 96000;
902 case HDSP_spdifFrequency128KHz:
903 if (hdsp->io_type == H9632) return 128000;
904 break;
905 case HDSP_spdifFrequency176_4KHz:
906 if (hdsp->io_type == H9632) return 176400;
907 break;
908 case HDSP_spdifFrequency192KHz:
909 if (hdsp->io_type == H9632) return 192000;
910 break;
911 default:
912 break;
913 }
914 snd_printk ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status);
915 return 0;
916}
917
Takashi Iwai55e957d2005-11-17 14:52:13 +0100918static void hdsp_compute_period_size(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919{
920 hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));
921}
922
Takashi Iwai55e957d2005-11-17 14:52:13 +0100923static snd_pcm_uframes_t hdsp_hw_pointer(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924{
925 int position;
926
927 position = hdsp_read(hdsp, HDSP_statusRegister);
928
Takashi Iwaib0b98112005-10-20 18:29:58 +0200929 if (!hdsp->precise_ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 return (position & HDSP_BufferID) ? (hdsp->period_bytes / 4) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931
932 position &= HDSP_BufferPositionMask;
933 position /= 4;
934 position &= (hdsp->period_bytes/2) - 1;
935 return position;
936}
937
Takashi Iwai55e957d2005-11-17 14:52:13 +0100938static void hdsp_reset_hw_pointer(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939{
940 hdsp_write (hdsp, HDSP_resetPointer, 0);
941}
942
Takashi Iwai55e957d2005-11-17 14:52:13 +0100943static void hdsp_start_audio(struct hdsp *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944{
945 s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start);
946 hdsp_write(s, HDSP_controlRegister, s->control_register);
947}
948
Takashi Iwai55e957d2005-11-17 14:52:13 +0100949static void hdsp_stop_audio(struct hdsp *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950{
951 s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable);
952 hdsp_write(s, HDSP_controlRegister, s->control_register);
953}
954
Takashi Iwai55e957d2005-11-17 14:52:13 +0100955static void hdsp_silence_playback(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956{
957 memset(hdsp->playback_buffer, 0, HDSP_DMA_AREA_BYTES);
958}
959
Takashi Iwai55e957d2005-11-17 14:52:13 +0100960static int hdsp_set_interrupt_interval(struct hdsp *s, unsigned int frames)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961{
962 int n;
963
964 spin_lock_irq(&s->lock);
965
966 frames >>= 7;
967 n = 0;
968 while (frames) {
969 n++;
970 frames >>= 1;
971 }
972
973 s->control_register &= ~HDSP_LatencyMask;
974 s->control_register |= hdsp_encode_latency(n);
975
976 hdsp_write(s, HDSP_controlRegister, s->control_register);
977
978 hdsp_compute_period_size(s);
979
980 spin_unlock_irq(&s->lock);
981
982 return 0;
983}
984
Takashi Iwai55e957d2005-11-17 14:52:13 +0100985static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986{
987 int reject_if_open = 0;
988 int current_rate;
989 int rate_bits;
990
991 /* ASSUMPTION: hdsp->lock is either held, or
992 there is no need for it (e.g. during module
993 initialization).
994 */
995
996 if (!(hdsp->control_register & HDSP_ClockModeMaster)) {
997 if (called_internally) {
998 /* request from ctl or card initialization */
Takashi Iwaib0b98112005-10-20 18:29:58 +0200999 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 -07001000 return -1;
1001 } else {
1002 /* hw_param request while in AutoSync mode */
1003 int external_freq = hdsp_external_sample_rate(hdsp);
1004 int spdif_freq = hdsp_spdif_sample_rate(hdsp);
1005
Takashi Iwaib0b98112005-10-20 18:29:58 +02001006 if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1))
1007 snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in double speed mode\n");
1008 else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1))
1009 snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in quad speed mode\n");
1010 else if (rate != external_freq) {
1011 snd_printk(KERN_INFO "Hammerfall-DSP: No AutoSync source for requested rate\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 return -1;
1013 }
1014 }
1015 }
1016
1017 current_rate = hdsp->system_sample_rate;
1018
1019 /* Changing from a "single speed" to a "double speed" rate is
1020 not allowed if any substreams are open. This is because
1021 such a change causes a shift in the location of
1022 the DMA buffers and a reduction in the number of available
1023 buffers.
1024
1025 Note that a similar but essentially insoluble problem
1026 exists for externally-driven rate changes. All we can do
1027 is to flag rate changes in the read/write routines. */
1028
Takashi Iwaib0b98112005-10-20 18:29:58 +02001029 if (rate > 96000 && hdsp->io_type != H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031
1032 switch (rate) {
1033 case 32000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001034 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 rate_bits = HDSP_Frequency32KHz;
1037 break;
1038 case 44100:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001039 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 rate_bits = HDSP_Frequency44_1KHz;
1042 break;
1043 case 48000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001044 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 rate_bits = HDSP_Frequency48KHz;
1047 break;
1048 case 64000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001049 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 rate_bits = HDSP_Frequency64KHz;
1052 break;
1053 case 88200:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001054 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 rate_bits = HDSP_Frequency88_2KHz;
1057 break;
1058 case 96000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001059 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 rate_bits = HDSP_Frequency96KHz;
1062 break;
1063 case 128000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001064 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 rate_bits = HDSP_Frequency128KHz;
1067 break;
1068 case 176400:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001069 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 rate_bits = HDSP_Frequency176_4KHz;
1072 break;
1073 case 192000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001074 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 rate_bits = HDSP_Frequency192KHz;
1077 break;
1078 default:
1079 return -EINVAL;
1080 }
1081
1082 if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) {
1083 snd_printk ("Hammerfall-DSP: cannot change speed mode (capture PID = %d, playback PID = %d)\n",
1084 hdsp->capture_pid,
1085 hdsp->playback_pid);
1086 return -EBUSY;
1087 }
1088
1089 hdsp->control_register &= ~HDSP_FrequencyMask;
1090 hdsp->control_register |= rate_bits;
1091 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1092
1093 if (rate >= 128000) {
1094 hdsp->channel_map = channel_map_H9632_qs;
1095 } else if (rate > 48000) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001096 if (hdsp->io_type == H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 hdsp->channel_map = channel_map_H9632_ds;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001098 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 hdsp->channel_map = channel_map_ds;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 } else {
1101 switch (hdsp->io_type) {
1102 case Multiface:
1103 hdsp->channel_map = channel_map_mf_ss;
1104 break;
1105 case Digiface:
1106 case H9652:
1107 hdsp->channel_map = channel_map_df_ss;
1108 break;
1109 case H9632:
1110 hdsp->channel_map = channel_map_H9632_ss;
1111 break;
1112 default:
1113 /* should never happen */
1114 break;
1115 }
1116 }
1117
1118 hdsp->system_sample_rate = rate;
1119
1120 return 0;
1121}
1122
1123/*----------------------------------------------------------------------------
1124 MIDI
1125 ----------------------------------------------------------------------------*/
1126
Takashi Iwai55e957d2005-11-17 14:52:13 +01001127static unsigned char snd_hdsp_midi_read_byte (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128{
1129 /* the hardware already does the relevant bit-mask with 0xff */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001130 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 return hdsp_read(hdsp, HDSP_midiDataIn1);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001132 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 return hdsp_read(hdsp, HDSP_midiDataIn0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134}
1135
Takashi Iwai55e957d2005-11-17 14:52:13 +01001136static void snd_hdsp_midi_write_byte (struct hdsp *hdsp, int id, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137{
1138 /* the hardware already does the relevant bit-mask with 0xff */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001139 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 hdsp_write(hdsp, HDSP_midiDataOut1, val);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001141 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 hdsp_write(hdsp, HDSP_midiDataOut0, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143}
1144
Takashi Iwai55e957d2005-11-17 14:52:13 +01001145static int snd_hdsp_midi_input_available (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001147 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 return (hdsp_read(hdsp, HDSP_midiStatusIn1) & 0xff);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001149 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 return (hdsp_read(hdsp, HDSP_midiStatusIn0) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151}
1152
Takashi Iwai55e957d2005-11-17 14:52:13 +01001153static int snd_hdsp_midi_output_possible (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154{
1155 int fifo_bytes_used;
1156
Takashi Iwaib0b98112005-10-20 18:29:58 +02001157 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut1) & 0xff;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001159 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut0) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161
Takashi Iwaib0b98112005-10-20 18:29:58 +02001162 if (fifo_bytes_used < 128)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 return 128 - fifo_bytes_used;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001164 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166}
1167
Takashi Iwai55e957d2005-11-17 14:52:13 +01001168static void snd_hdsp_flush_midi_input (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001170 while (snd_hdsp_midi_input_available (hdsp, id))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 snd_hdsp_midi_read_byte (hdsp, id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172}
1173
Takashi Iwai55e957d2005-11-17 14:52:13 +01001174static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175{
1176 unsigned long flags;
1177 int n_pending;
1178 int to_write;
1179 int i;
1180 unsigned char buf[128];
1181
1182 /* Output is not interrupt driven */
1183
1184 spin_lock_irqsave (&hmidi->lock, flags);
1185 if (hmidi->output) {
1186 if (!snd_rawmidi_transmit_empty (hmidi->output)) {
1187 if ((n_pending = snd_hdsp_midi_output_possible (hmidi->hdsp, hmidi->id)) > 0) {
1188 if (n_pending > (int)sizeof (buf))
1189 n_pending = sizeof (buf);
1190
1191 if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {
1192 for (i = 0; i < to_write; ++i)
1193 snd_hdsp_midi_write_byte (hmidi->hdsp, hmidi->id, buf[i]);
1194 }
1195 }
1196 }
1197 }
1198 spin_unlock_irqrestore (&hmidi->lock, flags);
1199 return 0;
1200}
1201
Takashi Iwai55e957d2005-11-17 14:52:13 +01001202static int snd_hdsp_midi_input_read (struct hdsp_midi *hmidi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203{
1204 unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
1205 unsigned long flags;
1206 int n_pending;
1207 int i;
1208
1209 spin_lock_irqsave (&hmidi->lock, flags);
1210 if ((n_pending = snd_hdsp_midi_input_available (hmidi->hdsp, hmidi->id)) > 0) {
1211 if (hmidi->input) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001212 if (n_pending > (int)sizeof (buf))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 n_pending = sizeof (buf);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001214 for (i = 0; i < n_pending; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 buf[i] = snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001216 if (n_pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 snd_rawmidi_receive (hmidi->input, buf, n_pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 } else {
1219 /* flush the MIDI input FIFO */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001220 while (--n_pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 }
1223 }
1224 hmidi->pending = 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001225 if (hmidi->id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 hmidi->hdsp->control_register |= HDSP_Midi1InterruptEnable;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001227 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 hmidi->hdsp->control_register |= HDSP_Midi0InterruptEnable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 hdsp_write(hmidi->hdsp, HDSP_controlRegister, hmidi->hdsp->control_register);
1230 spin_unlock_irqrestore (&hmidi->lock, flags);
1231 return snd_hdsp_midi_output_write (hmidi);
1232}
1233
Takashi Iwai55e957d2005-11-17 14:52:13 +01001234static void snd_hdsp_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001236 struct hdsp *hdsp;
1237 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 unsigned long flags;
1239 u32 ie;
1240
Takashi Iwai55e957d2005-11-17 14:52:13 +01001241 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 hdsp = hmidi->hdsp;
1243 ie = hmidi->id ? HDSP_Midi1InterruptEnable : HDSP_Midi0InterruptEnable;
1244 spin_lock_irqsave (&hdsp->lock, flags);
1245 if (up) {
1246 if (!(hdsp->control_register & ie)) {
1247 snd_hdsp_flush_midi_input (hdsp, hmidi->id);
1248 hdsp->control_register |= ie;
1249 }
1250 } else {
1251 hdsp->control_register &= ~ie;
1252 tasklet_kill(&hdsp->midi_tasklet);
1253 }
1254
1255 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1256 spin_unlock_irqrestore (&hdsp->lock, flags);
1257}
1258
1259static void snd_hdsp_midi_output_timer(unsigned long data)
1260{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001261 struct hdsp_midi *hmidi = (struct hdsp_midi *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 unsigned long flags;
1263
1264 snd_hdsp_midi_output_write(hmidi);
1265 spin_lock_irqsave (&hmidi->lock, flags);
1266
1267 /* this does not bump hmidi->istimer, because the
1268 kernel automatically removed the timer when it
1269 expired, and we are now adding it back, thus
1270 leaving istimer wherever it was set before.
1271 */
1272
1273 if (hmidi->istimer) {
1274 hmidi->timer.expires = 1 + jiffies;
1275 add_timer(&hmidi->timer);
1276 }
1277
1278 spin_unlock_irqrestore (&hmidi->lock, flags);
1279}
1280
Takashi Iwai55e957d2005-11-17 14:52:13 +01001281static void snd_hdsp_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001283 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 unsigned long flags;
1285
Takashi Iwai55e957d2005-11-17 14:52:13 +01001286 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 spin_lock_irqsave (&hmidi->lock, flags);
1288 if (up) {
1289 if (!hmidi->istimer) {
1290 init_timer(&hmidi->timer);
1291 hmidi->timer.function = snd_hdsp_midi_output_timer;
1292 hmidi->timer.data = (unsigned long) hmidi;
1293 hmidi->timer.expires = 1 + jiffies;
1294 add_timer(&hmidi->timer);
1295 hmidi->istimer++;
1296 }
1297 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001298 if (hmidi->istimer && --hmidi->istimer <= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 del_timer (&hmidi->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 }
1301 spin_unlock_irqrestore (&hmidi->lock, flags);
1302 if (up)
1303 snd_hdsp_midi_output_write(hmidi);
1304}
1305
Takashi Iwai55e957d2005-11-17 14:52:13 +01001306static int snd_hdsp_midi_input_open(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001308 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309
Takashi Iwai55e957d2005-11-17 14:52:13 +01001310 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 spin_lock_irq (&hmidi->lock);
1312 snd_hdsp_flush_midi_input (hmidi->hdsp, hmidi->id);
1313 hmidi->input = substream;
1314 spin_unlock_irq (&hmidi->lock);
1315
1316 return 0;
1317}
1318
Takashi Iwai55e957d2005-11-17 14:52:13 +01001319static int snd_hdsp_midi_output_open(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001321 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
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->output = substream;
1326 spin_unlock_irq (&hmidi->lock);
1327
1328 return 0;
1329}
1330
Takashi Iwai55e957d2005-11-17 14:52:13 +01001331static int snd_hdsp_midi_input_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_input_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->input = NULL;
1340 spin_unlock_irq (&hmidi->lock);
1341
1342 return 0;
1343}
1344
Takashi Iwai55e957d2005-11-17 14:52:13 +01001345static int snd_hdsp_midi_output_close(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001347 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348
1349 snd_hdsp_midi_output_trigger (substream, 0);
1350
Takashi Iwai55e957d2005-11-17 14:52:13 +01001351 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 spin_lock_irq (&hmidi->lock);
1353 hmidi->output = NULL;
1354 spin_unlock_irq (&hmidi->lock);
1355
1356 return 0;
1357}
1358
Takashi Iwai55e957d2005-11-17 14:52:13 +01001359static struct snd_rawmidi_ops snd_hdsp_midi_output =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360{
1361 .open = snd_hdsp_midi_output_open,
1362 .close = snd_hdsp_midi_output_close,
1363 .trigger = snd_hdsp_midi_output_trigger,
1364};
1365
Takashi Iwai55e957d2005-11-17 14:52:13 +01001366static struct snd_rawmidi_ops snd_hdsp_midi_input =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367{
1368 .open = snd_hdsp_midi_input_open,
1369 .close = snd_hdsp_midi_input_close,
1370 .trigger = snd_hdsp_midi_input_trigger,
1371};
1372
Takashi Iwaif40b6892006-07-05 16:51:05 +02001373static int snd_hdsp_create_midi (struct snd_card *card, struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374{
1375 char buf[32];
1376
1377 hdsp->midi[id].id = id;
1378 hdsp->midi[id].rmidi = NULL;
1379 hdsp->midi[id].input = NULL;
1380 hdsp->midi[id].output = NULL;
1381 hdsp->midi[id].hdsp = hdsp;
1382 hdsp->midi[id].istimer = 0;
1383 hdsp->midi[id].pending = 0;
1384 spin_lock_init (&hdsp->midi[id].lock);
1385
1386 sprintf (buf, "%s MIDI %d", card->shortname, id+1);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001387 if (snd_rawmidi_new (card, buf, id, 1, 1, &hdsp->midi[id].rmidi) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
1390 sprintf (hdsp->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);
1391 hdsp->midi[id].rmidi->private_data = &hdsp->midi[id];
1392
1393 snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdsp_midi_output);
1394 snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdsp_midi_input);
1395
1396 hdsp->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
1397 SNDRV_RAWMIDI_INFO_INPUT |
1398 SNDRV_RAWMIDI_INFO_DUPLEX;
1399
1400 return 0;
1401}
1402
1403/*-----------------------------------------------------------------------------
1404 Control Interface
1405 ----------------------------------------------------------------------------*/
1406
Takashi Iwai55e957d2005-11-17 14:52:13 +01001407static u32 snd_hdsp_convert_from_aes(struct snd_aes_iec958 *aes)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408{
1409 u32 val = 0;
1410 val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? HDSP_SPDIFProfessional : 0;
1411 val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? HDSP_SPDIFNonAudio : 0;
1412 if (val & HDSP_SPDIFProfessional)
1413 val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0;
1414 else
1415 val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0;
1416 return val;
1417}
1418
Takashi Iwai55e957d2005-11-17 14:52:13 +01001419static void snd_hdsp_convert_to_aes(struct snd_aes_iec958 *aes, u32 val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420{
1421 aes->status[0] = ((val & HDSP_SPDIFProfessional) ? IEC958_AES0_PROFESSIONAL : 0) |
1422 ((val & HDSP_SPDIFNonAudio) ? IEC958_AES0_NONAUDIO : 0);
1423 if (val & HDSP_SPDIFProfessional)
1424 aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0;
1425 else
1426 aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_CON_EMPHASIS_5015 : 0;
1427}
1428
Takashi Iwai55e957d2005-11-17 14:52:13 +01001429static int snd_hdsp_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430{
1431 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1432 uinfo->count = 1;
1433 return 0;
1434}
1435
Takashi Iwai55e957d2005-11-17 14:52:13 +01001436static int snd_hdsp_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001438 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439
1440 snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif);
1441 return 0;
1442}
1443
Takashi Iwai55e957d2005-11-17 14:52:13 +01001444static int snd_hdsp_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001446 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 int change;
1448 u32 val;
1449
1450 val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
1451 spin_lock_irq(&hdsp->lock);
1452 change = val != hdsp->creg_spdif;
1453 hdsp->creg_spdif = val;
1454 spin_unlock_irq(&hdsp->lock);
1455 return change;
1456}
1457
Takashi Iwai55e957d2005-11-17 14:52:13 +01001458static int snd_hdsp_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459{
1460 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1461 uinfo->count = 1;
1462 return 0;
1463}
1464
Takashi Iwai55e957d2005-11-17 14:52:13 +01001465static int snd_hdsp_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001467 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
1469 snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream);
1470 return 0;
1471}
1472
Takashi Iwai55e957d2005-11-17 14:52:13 +01001473static int snd_hdsp_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001475 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 int change;
1477 u32 val;
1478
1479 val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
1480 spin_lock_irq(&hdsp->lock);
1481 change = val != hdsp->creg_spdif_stream;
1482 hdsp->creg_spdif_stream = val;
1483 hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
1484 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= val);
1485 spin_unlock_irq(&hdsp->lock);
1486 return change;
1487}
1488
Takashi Iwai55e957d2005-11-17 14:52:13 +01001489static int snd_hdsp_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490{
1491 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1492 uinfo->count = 1;
1493 return 0;
1494}
1495
Takashi Iwai55e957d2005-11-17 14:52:13 +01001496static int snd_hdsp_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497{
1498 ucontrol->value.iec958.status[0] = kcontrol->private_value;
1499 return 0;
1500}
1501
1502#define HDSP_SPDIF_IN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001503{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 .name = xname, \
1505 .index = xindex, \
1506 .info = snd_hdsp_info_spdif_in, \
1507 .get = snd_hdsp_get_spdif_in, \
1508 .put = snd_hdsp_put_spdif_in }
1509
Takashi Iwai55e957d2005-11-17 14:52:13 +01001510static unsigned int hdsp_spdif_in(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511{
1512 return hdsp_decode_spdif_in(hdsp->control_register & HDSP_SPDIFInputMask);
1513}
1514
Takashi Iwai55e957d2005-11-17 14:52:13 +01001515static int hdsp_set_spdif_input(struct hdsp *hdsp, int in)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516{
1517 hdsp->control_register &= ~HDSP_SPDIFInputMask;
1518 hdsp->control_register |= hdsp_encode_spdif_in(in);
1519 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1520 return 0;
1521}
1522
Takashi Iwai55e957d2005-11-17 14:52:13 +01001523static int snd_hdsp_info_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524{
1525 static char *texts[4] = {"Optical", "Coaxial", "Internal", "AES"};
Takashi Iwai55e957d2005-11-17 14:52:13 +01001526 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527
1528 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1529 uinfo->count = 1;
1530 uinfo->value.enumerated.items = ((hdsp->io_type == H9632) ? 4 : 3);
1531 if (uinfo->value.enumerated.item > ((hdsp->io_type == H9632) ? 3 : 2))
1532 uinfo->value.enumerated.item = ((hdsp->io_type == H9632) ? 3 : 2);
1533 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1534 return 0;
1535}
1536
Takashi Iwai55e957d2005-11-17 14:52:13 +01001537static int snd_hdsp_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001539 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540
1541 ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp);
1542 return 0;
1543}
1544
Takashi Iwai55e957d2005-11-17 14:52:13 +01001545static int snd_hdsp_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001547 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 int change;
1549 unsigned int val;
1550
1551 if (!snd_hdsp_use_is_exclusive(hdsp))
1552 return -EBUSY;
1553 val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3);
1554 spin_lock_irq(&hdsp->lock);
1555 change = val != hdsp_spdif_in(hdsp);
1556 if (change)
1557 hdsp_set_spdif_input(hdsp, val);
1558 spin_unlock_irq(&hdsp->lock);
1559 return change;
1560}
1561
1562#define HDSP_SPDIF_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001563{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 .info = snd_hdsp_info_spdif_bits, \
1565 .get = snd_hdsp_get_spdif_out, .put = snd_hdsp_put_spdif_out }
1566
Takashi Iwai55e957d2005-11-17 14:52:13 +01001567static int hdsp_spdif_out(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568{
1569 return (hdsp->control_register & HDSP_SPDIFOpticalOut) ? 1 : 0;
1570}
1571
Takashi Iwai55e957d2005-11-17 14:52:13 +01001572static int hdsp_set_spdif_output(struct hdsp *hdsp, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001574 if (out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 hdsp->control_register |= HDSP_SPDIFOpticalOut;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001576 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 hdsp->control_register &= ~HDSP_SPDIFOpticalOut;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1579 return 0;
1580}
1581
Takashi Iwai55e957d2005-11-17 14:52:13 +01001582static int snd_hdsp_info_spdif_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583{
1584 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1585 uinfo->count = 1;
1586 uinfo->value.integer.min = 0;
1587 uinfo->value.integer.max = 1;
1588 return 0;
1589}
1590
Takashi Iwai55e957d2005-11-17 14:52:13 +01001591static int snd_hdsp_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001593 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594
1595 ucontrol->value.integer.value[0] = hdsp_spdif_out(hdsp);
1596 return 0;
1597}
1598
Takashi Iwai55e957d2005-11-17 14:52:13 +01001599static int snd_hdsp_put_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001601 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 int change;
1603 unsigned int val;
1604
1605 if (!snd_hdsp_use_is_exclusive(hdsp))
1606 return -EBUSY;
1607 val = ucontrol->value.integer.value[0] & 1;
1608 spin_lock_irq(&hdsp->lock);
1609 change = (int)val != hdsp_spdif_out(hdsp);
1610 hdsp_set_spdif_output(hdsp, val);
1611 spin_unlock_irq(&hdsp->lock);
1612 return change;
1613}
1614
1615#define HDSP_SPDIF_PROFESSIONAL(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001616{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 .info = snd_hdsp_info_spdif_bits, \
1618 .get = snd_hdsp_get_spdif_professional, .put = snd_hdsp_put_spdif_professional }
1619
Takashi Iwai55e957d2005-11-17 14:52:13 +01001620static int hdsp_spdif_professional(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621{
1622 return (hdsp->control_register & HDSP_SPDIFProfessional) ? 1 : 0;
1623}
1624
Takashi Iwai55e957d2005-11-17 14:52:13 +01001625static int hdsp_set_spdif_professional(struct hdsp *hdsp, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001627 if (val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 hdsp->control_register |= HDSP_SPDIFProfessional;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001629 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 hdsp->control_register &= ~HDSP_SPDIFProfessional;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1632 return 0;
1633}
1634
Takashi Iwai55e957d2005-11-17 14:52:13 +01001635static int snd_hdsp_get_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001637 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638
1639 ucontrol->value.integer.value[0] = hdsp_spdif_professional(hdsp);
1640 return 0;
1641}
1642
Takashi Iwai55e957d2005-11-17 14:52:13 +01001643static int snd_hdsp_put_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001645 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 int change;
1647 unsigned int val;
1648
1649 if (!snd_hdsp_use_is_exclusive(hdsp))
1650 return -EBUSY;
1651 val = ucontrol->value.integer.value[0] & 1;
1652 spin_lock_irq(&hdsp->lock);
1653 change = (int)val != hdsp_spdif_professional(hdsp);
1654 hdsp_set_spdif_professional(hdsp, val);
1655 spin_unlock_irq(&hdsp->lock);
1656 return change;
1657}
1658
1659#define HDSP_SPDIF_EMPHASIS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001660{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 .info = snd_hdsp_info_spdif_bits, \
1662 .get = snd_hdsp_get_spdif_emphasis, .put = snd_hdsp_put_spdif_emphasis }
1663
Takashi Iwai55e957d2005-11-17 14:52:13 +01001664static int hdsp_spdif_emphasis(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665{
1666 return (hdsp->control_register & HDSP_SPDIFEmphasis) ? 1 : 0;
1667}
1668
Takashi Iwai55e957d2005-11-17 14:52:13 +01001669static int hdsp_set_spdif_emphasis(struct hdsp *hdsp, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001671 if (val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 hdsp->control_register |= HDSP_SPDIFEmphasis;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001673 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 hdsp->control_register &= ~HDSP_SPDIFEmphasis;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1676 return 0;
1677}
1678
Takashi Iwai55e957d2005-11-17 14:52:13 +01001679static int snd_hdsp_get_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001681 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682
1683 ucontrol->value.integer.value[0] = hdsp_spdif_emphasis(hdsp);
1684 return 0;
1685}
1686
Takashi Iwai55e957d2005-11-17 14:52:13 +01001687static int snd_hdsp_put_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001689 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 int change;
1691 unsigned int val;
1692
1693 if (!snd_hdsp_use_is_exclusive(hdsp))
1694 return -EBUSY;
1695 val = ucontrol->value.integer.value[0] & 1;
1696 spin_lock_irq(&hdsp->lock);
1697 change = (int)val != hdsp_spdif_emphasis(hdsp);
1698 hdsp_set_spdif_emphasis(hdsp, val);
1699 spin_unlock_irq(&hdsp->lock);
1700 return change;
1701}
1702
1703#define HDSP_SPDIF_NON_AUDIO(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001704{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 .info = snd_hdsp_info_spdif_bits, \
1706 .get = snd_hdsp_get_spdif_nonaudio, .put = snd_hdsp_put_spdif_nonaudio }
1707
Takashi Iwai55e957d2005-11-17 14:52:13 +01001708static int hdsp_spdif_nonaudio(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709{
1710 return (hdsp->control_register & HDSP_SPDIFNonAudio) ? 1 : 0;
1711}
1712
Takashi Iwai55e957d2005-11-17 14:52:13 +01001713static int hdsp_set_spdif_nonaudio(struct hdsp *hdsp, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001715 if (val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 hdsp->control_register |= HDSP_SPDIFNonAudio;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001717 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 hdsp->control_register &= ~HDSP_SPDIFNonAudio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1720 return 0;
1721}
1722
Takashi Iwai55e957d2005-11-17 14:52:13 +01001723static int snd_hdsp_get_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001725 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726
1727 ucontrol->value.integer.value[0] = hdsp_spdif_nonaudio(hdsp);
1728 return 0;
1729}
1730
Takashi Iwai55e957d2005-11-17 14:52:13 +01001731static int snd_hdsp_put_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001733 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 int change;
1735 unsigned int val;
1736
1737 if (!snd_hdsp_use_is_exclusive(hdsp))
1738 return -EBUSY;
1739 val = ucontrol->value.integer.value[0] & 1;
1740 spin_lock_irq(&hdsp->lock);
1741 change = (int)val != hdsp_spdif_nonaudio(hdsp);
1742 hdsp_set_spdif_nonaudio(hdsp, val);
1743 spin_unlock_irq(&hdsp->lock);
1744 return change;
1745}
1746
1747#define HDSP_SPDIF_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001748{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 .name = xname, \
1750 .index = xindex, \
1751 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1752 .info = snd_hdsp_info_spdif_sample_rate, \
1753 .get = snd_hdsp_get_spdif_sample_rate \
1754}
1755
Takashi Iwai55e957d2005-11-17 14:52:13 +01001756static int snd_hdsp_info_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757{
1758 static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
Takashi Iwai55e957d2005-11-17 14:52:13 +01001759 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760
1761 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1762 uinfo->count = 1;
1763 uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7;
1764 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1765 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1766 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1767 return 0;
1768}
1769
Takashi Iwai55e957d2005-11-17 14:52:13 +01001770static int snd_hdsp_get_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001772 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773
1774 switch (hdsp_spdif_sample_rate(hdsp)) {
1775 case 32000:
1776 ucontrol->value.enumerated.item[0] = 0;
1777 break;
1778 case 44100:
1779 ucontrol->value.enumerated.item[0] = 1;
1780 break;
1781 case 48000:
1782 ucontrol->value.enumerated.item[0] = 2;
1783 break;
1784 case 64000:
1785 ucontrol->value.enumerated.item[0] = 3;
1786 break;
1787 case 88200:
1788 ucontrol->value.enumerated.item[0] = 4;
1789 break;
1790 case 96000:
1791 ucontrol->value.enumerated.item[0] = 5;
1792 break;
1793 case 128000:
1794 ucontrol->value.enumerated.item[0] = 7;
1795 break;
1796 case 176400:
1797 ucontrol->value.enumerated.item[0] = 8;
1798 break;
1799 case 192000:
1800 ucontrol->value.enumerated.item[0] = 9;
1801 break;
1802 default:
1803 ucontrol->value.enumerated.item[0] = 6;
1804 }
1805 return 0;
1806}
1807
1808#define HDSP_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001809{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 .name = xname, \
1811 .index = xindex, \
1812 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1813 .info = snd_hdsp_info_system_sample_rate, \
1814 .get = snd_hdsp_get_system_sample_rate \
1815}
1816
Takashi Iwai55e957d2005-11-17 14:52:13 +01001817static int snd_hdsp_info_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818{
1819 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1820 uinfo->count = 1;
1821 return 0;
1822}
1823
Takashi Iwai55e957d2005-11-17 14:52:13 +01001824static int snd_hdsp_get_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001826 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827
1828 ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate;
1829 return 0;
1830}
1831
1832#define HDSP_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001833{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 .name = xname, \
1835 .index = xindex, \
1836 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1837 .info = snd_hdsp_info_autosync_sample_rate, \
1838 .get = snd_hdsp_get_autosync_sample_rate \
1839}
1840
Takashi Iwai55e957d2005-11-17 14:52:13 +01001841static int snd_hdsp_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001843 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
1845 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1846 uinfo->count = 1;
1847 uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7 ;
1848 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1849 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1850 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1851 return 0;
1852}
1853
Takashi Iwai55e957d2005-11-17 14:52:13 +01001854static int snd_hdsp_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001856 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857
1858 switch (hdsp_external_sample_rate(hdsp)) {
1859 case 32000:
1860 ucontrol->value.enumerated.item[0] = 0;
1861 break;
1862 case 44100:
1863 ucontrol->value.enumerated.item[0] = 1;
1864 break;
1865 case 48000:
1866 ucontrol->value.enumerated.item[0] = 2;
1867 break;
1868 case 64000:
1869 ucontrol->value.enumerated.item[0] = 3;
1870 break;
1871 case 88200:
1872 ucontrol->value.enumerated.item[0] = 4;
1873 break;
1874 case 96000:
1875 ucontrol->value.enumerated.item[0] = 5;
1876 break;
1877 case 128000:
1878 ucontrol->value.enumerated.item[0] = 7;
1879 break;
1880 case 176400:
1881 ucontrol->value.enumerated.item[0] = 8;
1882 break;
1883 case 192000:
1884 ucontrol->value.enumerated.item[0] = 9;
1885 break;
1886 default:
1887 ucontrol->value.enumerated.item[0] = 6;
1888 }
1889 return 0;
1890}
1891
1892#define HDSP_SYSTEM_CLOCK_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001893{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 .name = xname, \
1895 .index = xindex, \
1896 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1897 .info = snd_hdsp_info_system_clock_mode, \
1898 .get = snd_hdsp_get_system_clock_mode \
1899}
1900
Takashi Iwai55e957d2005-11-17 14:52:13 +01001901static int hdsp_system_clock_mode(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001903 if (hdsp->control_register & HDSP_ClockModeMaster)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001905 else if (hdsp_external_sample_rate(hdsp) != hdsp->system_sample_rate)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 return 1;
1908}
1909
Takashi Iwai55e957d2005-11-17 14:52:13 +01001910static int snd_hdsp_info_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911{
1912 static char *texts[] = {"Master", "Slave" };
1913
1914 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1915 uinfo->count = 1;
1916 uinfo->value.enumerated.items = 2;
1917 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1918 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1919 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1920 return 0;
1921}
1922
Takashi Iwai55e957d2005-11-17 14:52:13 +01001923static int snd_hdsp_get_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001925 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926
1927 ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp);
1928 return 0;
1929}
1930
1931#define HDSP_CLOCK_SOURCE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001932{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 .name = xname, \
1934 .index = xindex, \
1935 .info = snd_hdsp_info_clock_source, \
1936 .get = snd_hdsp_get_clock_source, \
1937 .put = snd_hdsp_put_clock_source \
1938}
1939
Takashi Iwai55e957d2005-11-17 14:52:13 +01001940static int hdsp_clock_source(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941{
1942 if (hdsp->control_register & HDSP_ClockModeMaster) {
1943 switch (hdsp->system_sample_rate) {
1944 case 32000:
1945 return 1;
1946 case 44100:
1947 return 2;
1948 case 48000:
1949 return 3;
1950 case 64000:
1951 return 4;
1952 case 88200:
1953 return 5;
1954 case 96000:
1955 return 6;
1956 case 128000:
1957 return 7;
1958 case 176400:
1959 return 8;
1960 case 192000:
1961 return 9;
1962 default:
1963 return 3;
1964 }
1965 } else {
1966 return 0;
1967 }
1968}
1969
Takashi Iwai55e957d2005-11-17 14:52:13 +01001970static int hdsp_set_clock_source(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971{
1972 int rate;
1973 switch (mode) {
1974 case HDSP_CLOCK_SOURCE_AUTOSYNC:
1975 if (hdsp_external_sample_rate(hdsp) != 0) {
1976 if (!hdsp_set_rate(hdsp, hdsp_external_sample_rate(hdsp), 1)) {
1977 hdsp->control_register &= ~HDSP_ClockModeMaster;
1978 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1979 return 0;
1980 }
1981 }
1982 return -1;
1983 case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ:
1984 rate = 32000;
1985 break;
1986 case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ:
1987 rate = 44100;
1988 break;
1989 case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ:
1990 rate = 48000;
1991 break;
1992 case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ:
1993 rate = 64000;
1994 break;
1995 case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ:
1996 rate = 88200;
1997 break;
1998 case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ:
1999 rate = 96000;
2000 break;
2001 case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ:
2002 rate = 128000;
2003 break;
2004 case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ:
2005 rate = 176400;
2006 break;
2007 case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ:
2008 rate = 192000;
2009 break;
2010 default:
2011 rate = 48000;
2012 }
2013 hdsp->control_register |= HDSP_ClockModeMaster;
2014 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2015 hdsp_set_rate(hdsp, rate, 1);
2016 return 0;
2017}
2018
Takashi Iwai55e957d2005-11-17 14:52:13 +01002019static int snd_hdsp_info_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020{
2021 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 +01002022 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023
2024 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2025 uinfo->count = 1;
2026 if (hdsp->io_type == H9632)
2027 uinfo->value.enumerated.items = 10;
2028 else
2029 uinfo->value.enumerated.items = 7;
2030 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2031 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2032 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2033 return 0;
2034}
2035
Takashi Iwai55e957d2005-11-17 14:52:13 +01002036static int snd_hdsp_get_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002038 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039
2040 ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp);
2041 return 0;
2042}
2043
Takashi Iwai55e957d2005-11-17 14:52:13 +01002044static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002046 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 int change;
2048 int val;
2049
2050 if (!snd_hdsp_use_is_exclusive(hdsp))
2051 return -EBUSY;
2052 val = ucontrol->value.enumerated.item[0];
2053 if (val < 0) val = 0;
2054 if (hdsp->io_type == H9632) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002055 if (val > 9)
2056 val = 9;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002058 if (val > 6)
2059 val = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 }
2061 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002062 if (val != hdsp_clock_source(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 change = (hdsp_set_clock_source(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002064 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066 spin_unlock_irq(&hdsp->lock);
2067 return change;
2068}
2069
Takashi Iwai55e957d2005-11-17 14:52:13 +01002070static int snd_hdsp_info_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002071{
2072 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2073 uinfo->count = 1;
2074 uinfo->value.integer.min = 0;
2075 uinfo->value.integer.max = 1;
2076 return 0;
2077}
2078
Takashi Iwai55e957d2005-11-17 14:52:13 +01002079static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002080{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002081 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002082
2083 ucontrol->value.integer.value[0] = hdsp->clock_source_locked;
2084 return 0;
2085}
2086
Takashi Iwai55e957d2005-11-17 14:52:13 +01002087static int snd_hdsp_put_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002088{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002089 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002090 int change;
2091
2092 change = (int)ucontrol->value.integer.value[0] != hdsp->clock_source_locked;
2093 if (change)
2094 hdsp->clock_source_locked = ucontrol->value.integer.value[0];
2095 return change;
2096}
2097
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098#define HDSP_DA_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002099{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 .name = xname, \
2101 .index = xindex, \
2102 .info = snd_hdsp_info_da_gain, \
2103 .get = snd_hdsp_get_da_gain, \
2104 .put = snd_hdsp_put_da_gain \
2105}
2106
Takashi Iwai55e957d2005-11-17 14:52:13 +01002107static int hdsp_da_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108{
2109 switch (hdsp->control_register & HDSP_DAGainMask) {
2110 case HDSP_DAGainHighGain:
2111 return 0;
2112 case HDSP_DAGainPlus4dBu:
2113 return 1;
2114 case HDSP_DAGainMinus10dBV:
2115 return 2;
2116 default:
2117 return 1;
2118 }
2119}
2120
Takashi Iwai55e957d2005-11-17 14:52:13 +01002121static int hdsp_set_da_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122{
2123 hdsp->control_register &= ~HDSP_DAGainMask;
2124 switch (mode) {
2125 case 0:
2126 hdsp->control_register |= HDSP_DAGainHighGain;
2127 break;
2128 case 1:
2129 hdsp->control_register |= HDSP_DAGainPlus4dBu;
2130 break;
2131 case 2:
2132 hdsp->control_register |= HDSP_DAGainMinus10dBV;
2133 break;
2134 default:
2135 return -1;
2136
2137 }
2138 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2139 return 0;
2140}
2141
Takashi Iwai55e957d2005-11-17 14:52:13 +01002142static int snd_hdsp_info_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143{
2144 static char *texts[] = {"Hi Gain", "+4 dBu", "-10 dbV"};
2145
2146 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2147 uinfo->count = 1;
2148 uinfo->value.enumerated.items = 3;
2149 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2150 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2151 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2152 return 0;
2153}
2154
Takashi Iwai55e957d2005-11-17 14:52:13 +01002155static int snd_hdsp_get_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002157 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158
2159 ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp);
2160 return 0;
2161}
2162
Takashi Iwai55e957d2005-11-17 14:52:13 +01002163static int snd_hdsp_put_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002165 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 int change;
2167 int val;
2168
2169 if (!snd_hdsp_use_is_exclusive(hdsp))
2170 return -EBUSY;
2171 val = ucontrol->value.enumerated.item[0];
2172 if (val < 0) val = 0;
2173 if (val > 2) val = 2;
2174 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002175 if (val != hdsp_da_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 change = (hdsp_set_da_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002177 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 spin_unlock_irq(&hdsp->lock);
2180 return change;
2181}
2182
2183#define HDSP_AD_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002184{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 .name = xname, \
2186 .index = xindex, \
2187 .info = snd_hdsp_info_ad_gain, \
2188 .get = snd_hdsp_get_ad_gain, \
2189 .put = snd_hdsp_put_ad_gain \
2190}
2191
Takashi Iwai55e957d2005-11-17 14:52:13 +01002192static int hdsp_ad_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193{
2194 switch (hdsp->control_register & HDSP_ADGainMask) {
2195 case HDSP_ADGainMinus10dBV:
2196 return 0;
2197 case HDSP_ADGainPlus4dBu:
2198 return 1;
2199 case HDSP_ADGainLowGain:
2200 return 2;
2201 default:
2202 return 1;
2203 }
2204}
2205
Takashi Iwai55e957d2005-11-17 14:52:13 +01002206static int hdsp_set_ad_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207{
2208 hdsp->control_register &= ~HDSP_ADGainMask;
2209 switch (mode) {
2210 case 0:
2211 hdsp->control_register |= HDSP_ADGainMinus10dBV;
2212 break;
2213 case 1:
2214 hdsp->control_register |= HDSP_ADGainPlus4dBu;
2215 break;
2216 case 2:
2217 hdsp->control_register |= HDSP_ADGainLowGain;
2218 break;
2219 default:
2220 return -1;
2221
2222 }
2223 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2224 return 0;
2225}
2226
Takashi Iwai55e957d2005-11-17 14:52:13 +01002227static int snd_hdsp_info_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228{
2229 static char *texts[] = {"-10 dBV", "+4 dBu", "Lo Gain"};
2230
2231 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2232 uinfo->count = 1;
2233 uinfo->value.enumerated.items = 3;
2234 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2235 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2236 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2237 return 0;
2238}
2239
Takashi Iwai55e957d2005-11-17 14:52:13 +01002240static int snd_hdsp_get_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002242 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243
2244 ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp);
2245 return 0;
2246}
2247
Takashi Iwai55e957d2005-11-17 14:52:13 +01002248static int snd_hdsp_put_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002250 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 int change;
2252 int val;
2253
2254 if (!snd_hdsp_use_is_exclusive(hdsp))
2255 return -EBUSY;
2256 val = ucontrol->value.enumerated.item[0];
2257 if (val < 0) val = 0;
2258 if (val > 2) val = 2;
2259 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002260 if (val != hdsp_ad_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 change = (hdsp_set_ad_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002262 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264 spin_unlock_irq(&hdsp->lock);
2265 return change;
2266}
2267
2268#define HDSP_PHONE_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002269{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 .name = xname, \
2271 .index = xindex, \
2272 .info = snd_hdsp_info_phone_gain, \
2273 .get = snd_hdsp_get_phone_gain, \
2274 .put = snd_hdsp_put_phone_gain \
2275}
2276
Takashi Iwai55e957d2005-11-17 14:52:13 +01002277static int hdsp_phone_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278{
2279 switch (hdsp->control_register & HDSP_PhoneGainMask) {
2280 case HDSP_PhoneGain0dB:
2281 return 0;
2282 case HDSP_PhoneGainMinus6dB:
2283 return 1;
2284 case HDSP_PhoneGainMinus12dB:
2285 return 2;
2286 default:
2287 return 0;
2288 }
2289}
2290
Takashi Iwai55e957d2005-11-17 14:52:13 +01002291static int hdsp_set_phone_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292{
2293 hdsp->control_register &= ~HDSP_PhoneGainMask;
2294 switch (mode) {
2295 case 0:
2296 hdsp->control_register |= HDSP_PhoneGain0dB;
2297 break;
2298 case 1:
2299 hdsp->control_register |= HDSP_PhoneGainMinus6dB;
2300 break;
2301 case 2:
2302 hdsp->control_register |= HDSP_PhoneGainMinus12dB;
2303 break;
2304 default:
2305 return -1;
2306
2307 }
2308 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2309 return 0;
2310}
2311
Takashi Iwai55e957d2005-11-17 14:52:13 +01002312static int snd_hdsp_info_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313{
2314 static char *texts[] = {"0 dB", "-6 dB", "-12 dB"};
2315
2316 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2317 uinfo->count = 1;
2318 uinfo->value.enumerated.items = 3;
2319 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2320 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2321 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2322 return 0;
2323}
2324
Takashi Iwai55e957d2005-11-17 14:52:13 +01002325static int snd_hdsp_get_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002327 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328
2329 ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp);
2330 return 0;
2331}
2332
Takashi Iwai55e957d2005-11-17 14:52:13 +01002333static int snd_hdsp_put_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002335 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 int change;
2337 int val;
2338
2339 if (!snd_hdsp_use_is_exclusive(hdsp))
2340 return -EBUSY;
2341 val = ucontrol->value.enumerated.item[0];
2342 if (val < 0) val = 0;
2343 if (val > 2) val = 2;
2344 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002345 if (val != hdsp_phone_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 change = (hdsp_set_phone_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002347 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 spin_unlock_irq(&hdsp->lock);
2350 return change;
2351}
2352
2353#define HDSP_XLR_BREAKOUT_CABLE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002354{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 .name = xname, \
2356 .index = xindex, \
2357 .info = snd_hdsp_info_xlr_breakout_cable, \
2358 .get = snd_hdsp_get_xlr_breakout_cable, \
2359 .put = snd_hdsp_put_xlr_breakout_cable \
2360}
2361
Takashi Iwai55e957d2005-11-17 14:52:13 +01002362static int hdsp_xlr_breakout_cable(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002364 if (hdsp->control_register & HDSP_XLRBreakoutCable)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 return 0;
2367}
2368
Takashi Iwai55e957d2005-11-17 14:52:13 +01002369static int hdsp_set_xlr_breakout_cable(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002371 if (mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 hdsp->control_register |= HDSP_XLRBreakoutCable;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002373 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 hdsp->control_register &= ~HDSP_XLRBreakoutCable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2376 return 0;
2377}
2378
Takashi Iwai55e957d2005-11-17 14:52:13 +01002379static int snd_hdsp_info_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380{
2381 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2382 uinfo->count = 1;
2383 uinfo->value.integer.min = 0;
2384 uinfo->value.integer.max = 1;
2385 return 0;
2386}
2387
Takashi Iwai55e957d2005-11-17 14:52:13 +01002388static int snd_hdsp_get_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002390 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391
2392 ucontrol->value.enumerated.item[0] = hdsp_xlr_breakout_cable(hdsp);
2393 return 0;
2394}
2395
Takashi Iwai55e957d2005-11-17 14:52:13 +01002396static int snd_hdsp_put_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002398 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 int change;
2400 int val;
2401
2402 if (!snd_hdsp_use_is_exclusive(hdsp))
2403 return -EBUSY;
2404 val = ucontrol->value.integer.value[0] & 1;
2405 spin_lock_irq(&hdsp->lock);
2406 change = (int)val != hdsp_xlr_breakout_cable(hdsp);
2407 hdsp_set_xlr_breakout_cable(hdsp, val);
2408 spin_unlock_irq(&hdsp->lock);
2409 return change;
2410}
2411
2412/* (De)activates old RME Analog Extension Board
2413 These are connected to the internal ADAT connector
2414 Switching this on desactivates external ADAT
2415*/
2416#define HDSP_AEB(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002417{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 .name = xname, \
2419 .index = xindex, \
2420 .info = snd_hdsp_info_aeb, \
2421 .get = snd_hdsp_get_aeb, \
2422 .put = snd_hdsp_put_aeb \
2423}
2424
Takashi Iwai55e957d2005-11-17 14:52:13 +01002425static int hdsp_aeb(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002427 if (hdsp->control_register & HDSP_AnalogExtensionBoard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 return 0;
2430}
2431
Takashi Iwai55e957d2005-11-17 14:52:13 +01002432static int hdsp_set_aeb(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002434 if (mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 hdsp->control_register |= HDSP_AnalogExtensionBoard;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002436 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 hdsp->control_register &= ~HDSP_AnalogExtensionBoard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2439 return 0;
2440}
2441
Takashi Iwai55e957d2005-11-17 14:52:13 +01002442static int snd_hdsp_info_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443{
2444 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2445 uinfo->count = 1;
2446 uinfo->value.integer.min = 0;
2447 uinfo->value.integer.max = 1;
2448 return 0;
2449}
2450
Takashi Iwai55e957d2005-11-17 14:52:13 +01002451static int snd_hdsp_get_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002453 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454
2455 ucontrol->value.enumerated.item[0] = hdsp_aeb(hdsp);
2456 return 0;
2457}
2458
Takashi Iwai55e957d2005-11-17 14:52:13 +01002459static int snd_hdsp_put_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002461 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 int change;
2463 int val;
2464
2465 if (!snd_hdsp_use_is_exclusive(hdsp))
2466 return -EBUSY;
2467 val = ucontrol->value.integer.value[0] & 1;
2468 spin_lock_irq(&hdsp->lock);
2469 change = (int)val != hdsp_aeb(hdsp);
2470 hdsp_set_aeb(hdsp, val);
2471 spin_unlock_irq(&hdsp->lock);
2472 return change;
2473}
2474
2475#define HDSP_PREF_SYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002476{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 .name = xname, \
2478 .index = xindex, \
2479 .info = snd_hdsp_info_pref_sync_ref, \
2480 .get = snd_hdsp_get_pref_sync_ref, \
2481 .put = snd_hdsp_put_pref_sync_ref \
2482}
2483
Takashi Iwai55e957d2005-11-17 14:52:13 +01002484static int hdsp_pref_sync_ref(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485{
2486 /* Notice that this looks at the requested sync source,
2487 not the one actually in use.
2488 */
2489
2490 switch (hdsp->control_register & HDSP_SyncRefMask) {
2491 case HDSP_SyncRef_ADAT1:
2492 return HDSP_SYNC_FROM_ADAT1;
2493 case HDSP_SyncRef_ADAT2:
2494 return HDSP_SYNC_FROM_ADAT2;
2495 case HDSP_SyncRef_ADAT3:
2496 return HDSP_SYNC_FROM_ADAT3;
2497 case HDSP_SyncRef_SPDIF:
2498 return HDSP_SYNC_FROM_SPDIF;
2499 case HDSP_SyncRef_WORD:
2500 return HDSP_SYNC_FROM_WORD;
2501 case HDSP_SyncRef_ADAT_SYNC:
2502 return HDSP_SYNC_FROM_ADAT_SYNC;
2503 default:
2504 return HDSP_SYNC_FROM_WORD;
2505 }
2506 return 0;
2507}
2508
Takashi Iwai55e957d2005-11-17 14:52:13 +01002509static int hdsp_set_pref_sync_ref(struct hdsp *hdsp, int pref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510{
2511 hdsp->control_register &= ~HDSP_SyncRefMask;
2512 switch (pref) {
2513 case HDSP_SYNC_FROM_ADAT1:
2514 hdsp->control_register &= ~HDSP_SyncRefMask; /* clear SyncRef bits */
2515 break;
2516 case HDSP_SYNC_FROM_ADAT2:
2517 hdsp->control_register |= HDSP_SyncRef_ADAT2;
2518 break;
2519 case HDSP_SYNC_FROM_ADAT3:
2520 hdsp->control_register |= HDSP_SyncRef_ADAT3;
2521 break;
2522 case HDSP_SYNC_FROM_SPDIF:
2523 hdsp->control_register |= HDSP_SyncRef_SPDIF;
2524 break;
2525 case HDSP_SYNC_FROM_WORD:
2526 hdsp->control_register |= HDSP_SyncRef_WORD;
2527 break;
2528 case HDSP_SYNC_FROM_ADAT_SYNC:
2529 hdsp->control_register |= HDSP_SyncRef_ADAT_SYNC;
2530 break;
2531 default:
2532 return -1;
2533 }
2534 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2535 return 0;
2536}
2537
Takashi Iwai55e957d2005-11-17 14:52:13 +01002538static int snd_hdsp_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539{
2540 static char *texts[] = {"Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3" };
Takashi Iwai55e957d2005-11-17 14:52:13 +01002541 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542
2543 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2544 uinfo->count = 1;
2545
2546 switch (hdsp->io_type) {
2547 case Digiface:
2548 case H9652:
2549 uinfo->value.enumerated.items = 6;
2550 break;
2551 case Multiface:
2552 uinfo->value.enumerated.items = 4;
2553 break;
2554 case H9632:
2555 uinfo->value.enumerated.items = 3;
2556 break;
2557 default:
2558 uinfo->value.enumerated.items = 0;
2559 break;
2560 }
2561
2562 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2563 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2564 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2565 return 0;
2566}
2567
Takashi Iwai55e957d2005-11-17 14:52:13 +01002568static int snd_hdsp_get_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002570 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571
2572 ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp);
2573 return 0;
2574}
2575
Takashi Iwai55e957d2005-11-17 14:52:13 +01002576static int snd_hdsp_put_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002578 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579 int change, max;
2580 unsigned int val;
2581
2582 if (!snd_hdsp_use_is_exclusive(hdsp))
2583 return -EBUSY;
2584
2585 switch (hdsp->io_type) {
2586 case Digiface:
2587 case H9652:
2588 max = 6;
2589 break;
2590 case Multiface:
2591 max = 4;
2592 break;
2593 case H9632:
2594 max = 3;
2595 break;
2596 default:
2597 return -EIO;
2598 }
2599
2600 val = ucontrol->value.enumerated.item[0] % max;
2601 spin_lock_irq(&hdsp->lock);
2602 change = (int)val != hdsp_pref_sync_ref(hdsp);
2603 hdsp_set_pref_sync_ref(hdsp, val);
2604 spin_unlock_irq(&hdsp->lock);
2605 return change;
2606}
2607
2608#define HDSP_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002609{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610 .name = xname, \
2611 .index = xindex, \
2612 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2613 .info = snd_hdsp_info_autosync_ref, \
2614 .get = snd_hdsp_get_autosync_ref, \
2615}
2616
Takashi Iwai55e957d2005-11-17 14:52:13 +01002617static int hdsp_autosync_ref(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618{
2619 /* This looks at the autosync selected sync reference */
2620 unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
2621
2622 switch (status2 & HDSP_SelSyncRefMask) {
2623 case HDSP_SelSyncRef_WORD:
2624 return HDSP_AUTOSYNC_FROM_WORD;
2625 case HDSP_SelSyncRef_ADAT_SYNC:
2626 return HDSP_AUTOSYNC_FROM_ADAT_SYNC;
2627 case HDSP_SelSyncRef_SPDIF:
2628 return HDSP_AUTOSYNC_FROM_SPDIF;
2629 case HDSP_SelSyncRefMask:
2630 return HDSP_AUTOSYNC_FROM_NONE;
2631 case HDSP_SelSyncRef_ADAT1:
2632 return HDSP_AUTOSYNC_FROM_ADAT1;
2633 case HDSP_SelSyncRef_ADAT2:
2634 return HDSP_AUTOSYNC_FROM_ADAT2;
2635 case HDSP_SelSyncRef_ADAT3:
2636 return HDSP_AUTOSYNC_FROM_ADAT3;
2637 default:
2638 return HDSP_AUTOSYNC_FROM_WORD;
2639 }
2640 return 0;
2641}
2642
Takashi Iwai55e957d2005-11-17 14:52:13 +01002643static int snd_hdsp_info_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644{
2645 static char *texts[] = {"Word", "ADAT Sync", "IEC958", "None", "ADAT1", "ADAT2", "ADAT3" };
2646
2647 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2648 uinfo->count = 1;
2649 uinfo->value.enumerated.items = 7;
2650 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2651 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2652 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2653 return 0;
2654}
2655
Takashi Iwai55e957d2005-11-17 14:52:13 +01002656static int snd_hdsp_get_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002658 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659
2660 ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp);
2661 return 0;
2662}
2663
2664#define HDSP_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002665{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666 .name = xname, \
2667 .index = xindex, \
2668 .info = snd_hdsp_info_line_out, \
2669 .get = snd_hdsp_get_line_out, \
2670 .put = snd_hdsp_put_line_out \
2671}
2672
Takashi Iwai55e957d2005-11-17 14:52:13 +01002673static int hdsp_line_out(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674{
2675 return (hdsp->control_register & HDSP_LineOut) ? 1 : 0;
2676}
2677
Takashi Iwai55e957d2005-11-17 14:52:13 +01002678static int hdsp_set_line_output(struct hdsp *hdsp, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002680 if (out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681 hdsp->control_register |= HDSP_LineOut;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002682 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 hdsp->control_register &= ~HDSP_LineOut;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2685 return 0;
2686}
2687
Takashi Iwai55e957d2005-11-17 14:52:13 +01002688static int snd_hdsp_info_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689{
2690 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2691 uinfo->count = 1;
2692 uinfo->value.integer.min = 0;
2693 uinfo->value.integer.max = 1;
2694 return 0;
2695}
2696
Takashi Iwai55e957d2005-11-17 14:52:13 +01002697static int snd_hdsp_get_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002699 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700
2701 spin_lock_irq(&hdsp->lock);
2702 ucontrol->value.integer.value[0] = hdsp_line_out(hdsp);
2703 spin_unlock_irq(&hdsp->lock);
2704 return 0;
2705}
2706
Takashi Iwai55e957d2005-11-17 14:52:13 +01002707static int snd_hdsp_put_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002709 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710 int change;
2711 unsigned int val;
2712
2713 if (!snd_hdsp_use_is_exclusive(hdsp))
2714 return -EBUSY;
2715 val = ucontrol->value.integer.value[0] & 1;
2716 spin_lock_irq(&hdsp->lock);
2717 change = (int)val != hdsp_line_out(hdsp);
2718 hdsp_set_line_output(hdsp, val);
2719 spin_unlock_irq(&hdsp->lock);
2720 return change;
2721}
2722
2723#define HDSP_PRECISE_POINTER(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002724{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725 .name = xname, \
2726 .index = xindex, \
2727 .info = snd_hdsp_info_precise_pointer, \
2728 .get = snd_hdsp_get_precise_pointer, \
2729 .put = snd_hdsp_put_precise_pointer \
2730}
2731
Takashi Iwai55e957d2005-11-17 14:52:13 +01002732static int hdsp_set_precise_pointer(struct hdsp *hdsp, int precise)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002734 if (precise)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735 hdsp->precise_ptr = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002736 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 hdsp->precise_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738 return 0;
2739}
2740
Takashi Iwai55e957d2005-11-17 14:52:13 +01002741static int snd_hdsp_info_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002742{
2743 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2744 uinfo->count = 1;
2745 uinfo->value.integer.min = 0;
2746 uinfo->value.integer.max = 1;
2747 return 0;
2748}
2749
Takashi Iwai55e957d2005-11-17 14:52:13 +01002750static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002752 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753
2754 spin_lock_irq(&hdsp->lock);
2755 ucontrol->value.integer.value[0] = hdsp->precise_ptr;
2756 spin_unlock_irq(&hdsp->lock);
2757 return 0;
2758}
2759
Takashi Iwai55e957d2005-11-17 14:52:13 +01002760static int snd_hdsp_put_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002762 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 int change;
2764 unsigned int val;
2765
2766 if (!snd_hdsp_use_is_exclusive(hdsp))
2767 return -EBUSY;
2768 val = ucontrol->value.integer.value[0] & 1;
2769 spin_lock_irq(&hdsp->lock);
2770 change = (int)val != hdsp->precise_ptr;
2771 hdsp_set_precise_pointer(hdsp, val);
2772 spin_unlock_irq(&hdsp->lock);
2773 return change;
2774}
2775
2776#define HDSP_USE_MIDI_TASKLET(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002777{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 .name = xname, \
2779 .index = xindex, \
2780 .info = snd_hdsp_info_use_midi_tasklet, \
2781 .get = snd_hdsp_get_use_midi_tasklet, \
2782 .put = snd_hdsp_put_use_midi_tasklet \
2783}
2784
Takashi Iwai55e957d2005-11-17 14:52:13 +01002785static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002787 if (use_tasklet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788 hdsp->use_midi_tasklet = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002789 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790 hdsp->use_midi_tasklet = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 return 0;
2792}
2793
Takashi Iwai55e957d2005-11-17 14:52:13 +01002794static int snd_hdsp_info_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795{
2796 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2797 uinfo->count = 1;
2798 uinfo->value.integer.min = 0;
2799 uinfo->value.integer.max = 1;
2800 return 0;
2801}
2802
Takashi Iwai55e957d2005-11-17 14:52:13 +01002803static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002805 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806
2807 spin_lock_irq(&hdsp->lock);
2808 ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet;
2809 spin_unlock_irq(&hdsp->lock);
2810 return 0;
2811}
2812
Takashi Iwai55e957d2005-11-17 14:52:13 +01002813static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002815 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 int change;
2817 unsigned int val;
2818
2819 if (!snd_hdsp_use_is_exclusive(hdsp))
2820 return -EBUSY;
2821 val = ucontrol->value.integer.value[0] & 1;
2822 spin_lock_irq(&hdsp->lock);
2823 change = (int)val != hdsp->use_midi_tasklet;
2824 hdsp_set_use_midi_tasklet(hdsp, val);
2825 spin_unlock_irq(&hdsp->lock);
2826 return change;
2827}
2828
2829#define HDSP_MIXER(xname, xindex) \
2830{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
2831 .name = xname, \
2832 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002833 .device = 0, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2835 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2836 .info = snd_hdsp_info_mixer, \
2837 .get = snd_hdsp_get_mixer, \
2838 .put = snd_hdsp_put_mixer \
2839}
2840
Takashi Iwai55e957d2005-11-17 14:52:13 +01002841static int snd_hdsp_info_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842{
2843 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2844 uinfo->count = 3;
2845 uinfo->value.integer.min = 0;
2846 uinfo->value.integer.max = 65536;
2847 uinfo->value.integer.step = 1;
2848 return 0;
2849}
2850
Takashi Iwai55e957d2005-11-17 14:52:13 +01002851static int snd_hdsp_get_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002853 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854 int source;
2855 int destination;
2856 int addr;
2857
2858 source = ucontrol->value.integer.value[0];
2859 destination = ucontrol->value.integer.value[1];
2860
Takashi Iwaib0b98112005-10-20 18:29:58 +02002861 if (source >= hdsp->max_channels)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels,destination);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002863 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864 addr = hdsp_input_to_output_key(hdsp,source, destination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865
2866 spin_lock_irq(&hdsp->lock);
2867 ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr);
2868 spin_unlock_irq(&hdsp->lock);
2869 return 0;
2870}
2871
Takashi Iwai55e957d2005-11-17 14:52:13 +01002872static int snd_hdsp_put_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002874 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875 int change;
2876 int source;
2877 int destination;
2878 int gain;
2879 int addr;
2880
2881 if (!snd_hdsp_use_is_exclusive(hdsp))
2882 return -EBUSY;
2883
2884 source = ucontrol->value.integer.value[0];
2885 destination = ucontrol->value.integer.value[1];
2886
Takashi Iwaib0b98112005-10-20 18:29:58 +02002887 if (source >= hdsp->max_channels)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888 addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels, destination);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002889 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890 addr = hdsp_input_to_output_key(hdsp,source, destination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891
2892 gain = ucontrol->value.integer.value[2];
2893
2894 spin_lock_irq(&hdsp->lock);
2895 change = gain != hdsp_read_gain(hdsp, addr);
2896 if (change)
2897 hdsp_write_gain(hdsp, addr, gain);
2898 spin_unlock_irq(&hdsp->lock);
2899 return change;
2900}
2901
2902#define HDSP_WC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002903{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002904 .name = xname, \
2905 .index = xindex, \
2906 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2907 .info = snd_hdsp_info_sync_check, \
2908 .get = snd_hdsp_get_wc_sync_check \
2909}
2910
Takashi Iwai55e957d2005-11-17 14:52:13 +01002911static int snd_hdsp_info_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912{
2913 static char *texts[] = {"No Lock", "Lock", "Sync" };
2914 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2915 uinfo->count = 1;
2916 uinfo->value.enumerated.items = 3;
2917 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2918 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2919 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2920 return 0;
2921}
2922
Takashi Iwai55e957d2005-11-17 14:52:13 +01002923static int hdsp_wc_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924{
2925 int status2 = hdsp_read(hdsp, HDSP_status2Register);
2926 if (status2 & HDSP_wc_lock) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002927 if (status2 & HDSP_wc_sync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002929 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002931 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933 return 0;
2934}
2935
Takashi Iwai55e957d2005-11-17 14:52:13 +01002936static int snd_hdsp_get_wc_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002938 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939
2940 ucontrol->value.enumerated.item[0] = hdsp_wc_sync_check(hdsp);
2941 return 0;
2942}
2943
2944#define HDSP_SPDIF_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002945{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946 .name = xname, \
2947 .index = xindex, \
2948 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2949 .info = snd_hdsp_info_sync_check, \
2950 .get = snd_hdsp_get_spdif_sync_check \
2951}
2952
Takashi Iwai55e957d2005-11-17 14:52:13 +01002953static int hdsp_spdif_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954{
2955 int status = hdsp_read(hdsp, HDSP_statusRegister);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002956 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002958 else {
2959 if (status & HDSP_SPDIFSync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002961 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963 }
2964 return 0;
2965}
2966
Takashi Iwai55e957d2005-11-17 14:52:13 +01002967static int snd_hdsp_get_spdif_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002969 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970
2971 ucontrol->value.enumerated.item[0] = hdsp_spdif_sync_check(hdsp);
2972 return 0;
2973}
2974
2975#define HDSP_ADATSYNC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002976{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 .name = xname, \
2978 .index = xindex, \
2979 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2980 .info = snd_hdsp_info_sync_check, \
2981 .get = snd_hdsp_get_adatsync_sync_check \
2982}
2983
Takashi Iwai55e957d2005-11-17 14:52:13 +01002984static int hdsp_adatsync_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985{
2986 int status = hdsp_read(hdsp, HDSP_statusRegister);
2987 if (status & HDSP_TimecodeLock) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002988 if (status & HDSP_TimecodeSync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002990 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002992 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994}
2995
Takashi Iwai55e957d2005-11-17 14:52:13 +01002996static int snd_hdsp_get_adatsync_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002998 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999
3000 ucontrol->value.enumerated.item[0] = hdsp_adatsync_sync_check(hdsp);
3001 return 0;
3002}
3003
3004#define HDSP_ADAT_SYNC_CHECK \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003005{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3007 .info = snd_hdsp_info_sync_check, \
3008 .get = snd_hdsp_get_adat_sync_check \
3009}
3010
Takashi Iwai55e957d2005-11-17 14:52:13 +01003011static int hdsp_adat_sync_check(struct hdsp *hdsp, int idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012{
3013 int status = hdsp_read(hdsp, HDSP_statusRegister);
3014
3015 if (status & (HDSP_Lock0>>idx)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003016 if (status & (HDSP_Sync0>>idx))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003018 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003020 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022}
3023
Takashi Iwai55e957d2005-11-17 14:52:13 +01003024static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025{
3026 int offset;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003027 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028
3029 offset = ucontrol->id.index - 1;
3030 snd_assert(offset >= 0);
3031
3032 switch (hdsp->io_type) {
3033 case Digiface:
3034 case H9652:
3035 if (offset >= 3)
3036 return -EINVAL;
3037 break;
3038 case Multiface:
3039 case H9632:
3040 if (offset >= 1)
3041 return -EINVAL;
3042 break;
3043 default:
3044 return -EIO;
3045 }
3046
3047 ucontrol->value.enumerated.item[0] = hdsp_adat_sync_check(hdsp, offset);
3048 return 0;
3049}
3050
Takashi Iwai55e957d2005-11-17 14:52:13 +01003051static struct snd_kcontrol_new snd_hdsp_9632_controls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052HDSP_DA_GAIN("DA Gain", 0),
3053HDSP_AD_GAIN("AD Gain", 0),
3054HDSP_PHONE_GAIN("Phones Gain", 0),
3055HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0)
3056};
3057
Takashi Iwai55e957d2005-11-17 14:52:13 +01003058static struct snd_kcontrol_new snd_hdsp_controls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059{
Clemens Ladisch5549d542005-08-03 13:50:30 +02003060 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
3062 .info = snd_hdsp_control_spdif_info,
3063 .get = snd_hdsp_control_spdif_get,
3064 .put = snd_hdsp_control_spdif_put,
3065},
3066{
3067 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch5549d542005-08-03 13:50:30 +02003068 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
3070 .info = snd_hdsp_control_spdif_stream_info,
3071 .get = snd_hdsp_control_spdif_stream_get,
3072 .put = snd_hdsp_control_spdif_stream_put,
3073},
3074{
3075 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +02003076 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
3078 .info = snd_hdsp_control_spdif_mask_info,
3079 .get = snd_hdsp_control_spdif_mask_get,
3080 .private_value = IEC958_AES0_NONAUDIO |
3081 IEC958_AES0_PROFESSIONAL |
3082 IEC958_AES0_CON_EMPHASIS,
3083},
3084{
3085 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +02003086 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
3088 .info = snd_hdsp_control_spdif_mask_info,
3089 .get = snd_hdsp_control_spdif_mask_get,
3090 .private_value = IEC958_AES0_NONAUDIO |
3091 IEC958_AES0_PROFESSIONAL |
3092 IEC958_AES0_PRO_EMPHASIS,
3093},
3094HDSP_MIXER("Mixer", 0),
3095HDSP_SPDIF_IN("IEC958 Input Connector", 0),
3096HDSP_SPDIF_OUT("IEC958 Output also on ADAT1", 0),
3097HDSP_SPDIF_PROFESSIONAL("IEC958 Professional Bit", 0),
3098HDSP_SPDIF_EMPHASIS("IEC958 Emphasis Bit", 0),
3099HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0),
3100/* 'Sample Clock Source' complies with the alsa control naming scheme */
3101HDSP_CLOCK_SOURCE("Sample Clock Source", 0),
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003102{
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003103 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3104 .name = "Sample Clock Source Locking",
3105 .info = snd_hdsp_info_clock_source_lock,
3106 .get = snd_hdsp_get_clock_source_lock,
3107 .put = snd_hdsp_put_clock_source_lock,
3108},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109HDSP_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
3110HDSP_PREF_SYNC_REF("Preferred Sync Reference", 0),
3111HDSP_AUTOSYNC_REF("AutoSync Reference", 0),
3112HDSP_SPDIF_SAMPLE_RATE("SPDIF Sample Rate", 0),
3113HDSP_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
3114/* 'External Rate' complies with the alsa control naming scheme */
3115HDSP_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
3116HDSP_WC_SYNC_CHECK("Word Clock Lock Status", 0),
3117HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0),
3118HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0),
3119HDSP_LINE_OUT("Line Out", 0),
3120HDSP_PRECISE_POINTER("Precise Pointer", 0),
3121HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0),
3122};
3123
Takashi Iwai55e957d2005-11-17 14:52:13 +01003124static struct snd_kcontrol_new snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0);
3125static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126
Takashi Iwai55e957d2005-11-17 14:52:13 +01003127static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128{
3129 unsigned int idx;
3130 int err;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003131 struct snd_kcontrol *kctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132
3133 for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003134 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 if (idx == 1) /* IEC958 (S/PDIF) Stream */
3137 hdsp->spdif_ctl = kctl;
3138 }
3139
3140 /* ADAT SyncCheck status */
3141 snd_hdsp_adat_sync_check.name = "ADAT Lock Status";
3142 snd_hdsp_adat_sync_check.index = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003143 if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145 if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
3146 for (idx = 1; idx < 3; ++idx) {
3147 snd_hdsp_adat_sync_check.index = idx+1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003148 if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 }
3151 }
3152
3153 /* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */
3154 if (hdsp->io_type == H9632) {
3155 for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003156 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158 }
3159 }
3160
3161 /* AEB control for H96xx card */
3162 if (hdsp->io_type == H9632 || hdsp->io_type == H9652) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003163 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165 }
3166
3167 return 0;
3168}
3169
3170/*------------------------------------------------------------
3171 /proc interface
3172 ------------------------------------------------------------*/
3173
3174static void
Takashi Iwai55e957d2005-11-17 14:52:13 +01003175snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003177 struct hdsp *hdsp = (struct hdsp *) entry->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 unsigned int status;
3179 unsigned int status2;
3180 char *pref_sync_ref;
3181 char *autosync_ref;
3182 char *system_clock_mode;
3183 char *clock_source;
3184 int x;
3185
Remy Brunoecb594e2006-06-12 09:25:22 +02003186 if (hdsp_check_for_iobox (hdsp)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187 snd_iprintf(buffer, "No I/O box connected.\nPlease connect one and upload firmware.\n");
3188 return;
Remy Brunoecb594e2006-06-12 09:25:22 +02003189 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190
Takashi Iwaib0b98112005-10-20 18:29:58 +02003191 if (hdsp_check_for_firmware(hdsp, 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192 if (hdsp->state & HDSP_FirmwareCached) {
3193 if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
3194 snd_iprintf(buffer, "Firmware loading from cache failed, please upload manually.\n");
3195 return;
3196 }
3197 } else {
Takashi Iwai311e70a2006-09-06 12:13:37 +02003198 int err = -EINVAL;
3199#ifdef HDSP_FW_LOADER
3200 err = hdsp_request_fw_loader(hdsp);
3201#endif
3202 if (err < 0) {
3203 snd_iprintf(buffer,
3204 "No firmware loaded nor cached, "
3205 "please upload firmware.\n");
3206 return;
3207 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208 }
3209 }
3210
3211 status = hdsp_read(hdsp, HDSP_statusRegister);
3212 status2 = hdsp_read(hdsp, HDSP_status2Register);
3213
3214 snd_iprintf(buffer, "%s (Card #%d)\n", hdsp->card_name, hdsp->card->number + 1);
3215 snd_iprintf(buffer, "Buffers: capture %p playback %p\n",
3216 hdsp->capture_buffer, hdsp->playback_buffer);
3217 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
3218 hdsp->irq, hdsp->port, (unsigned long)hdsp->iobase);
3219 snd_iprintf(buffer, "Control register: 0x%x\n", hdsp->control_register);
3220 snd_iprintf(buffer, "Control2 register: 0x%x\n", hdsp->control2_register);
3221 snd_iprintf(buffer, "Status register: 0x%x\n", status);
3222 snd_iprintf(buffer, "Status2 register: 0x%x\n", status2);
3223 snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff);
3224 snd_iprintf(buffer, "MIDI1 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut0));
3225 snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0));
3226 snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1));
3227 snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1));
3228 snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off");
3229
3230 snd_iprintf(buffer, "\n");
3231
3232 x = 1 << (6 + hdsp_decode_latency(hdsp->control_register & HDSP_LatencyMask));
3233
3234 snd_iprintf(buffer, "Buffer Size (Latency): %d samples (2 periods of %lu bytes)\n", x, (unsigned long) hdsp->period_bytes);
3235 snd_iprintf(buffer, "Hardware pointer (frames): %ld\n", hdsp_hw_pointer(hdsp));
3236 snd_iprintf(buffer, "Precise pointer: %s\n", hdsp->precise_ptr ? "on" : "off");
3237 snd_iprintf(buffer, "Line out: %s\n", (hdsp->control_register & HDSP_LineOut) ? "on" : "off");
3238
3239 snd_iprintf(buffer, "Firmware version: %d\n", (status2&HDSP_version0)|(status2&HDSP_version1)<<1|(status2&HDSP_version2)<<2);
3240
3241 snd_iprintf(buffer, "\n");
3242
3243
3244 switch (hdsp_clock_source(hdsp)) {
3245 case HDSP_CLOCK_SOURCE_AUTOSYNC:
3246 clock_source = "AutoSync";
3247 break;
3248 case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ:
3249 clock_source = "Internal 32 kHz";
3250 break;
3251 case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ:
3252 clock_source = "Internal 44.1 kHz";
3253 break;
3254 case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ:
3255 clock_source = "Internal 48 kHz";
3256 break;
3257 case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ:
3258 clock_source = "Internal 64 kHz";
3259 break;
3260 case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ:
3261 clock_source = "Internal 88.2 kHz";
3262 break;
3263 case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ:
3264 clock_source = "Internal 96 kHz";
3265 break;
3266 case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ:
3267 clock_source = "Internal 128 kHz";
3268 break;
3269 case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ:
3270 clock_source = "Internal 176.4 kHz";
3271 break;
3272 case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ:
3273 clock_source = "Internal 192 kHz";
3274 break;
3275 default:
3276 clock_source = "Error";
3277 }
3278 snd_iprintf (buffer, "Sample Clock Source: %s\n", clock_source);
3279
Takashi Iwaib0b98112005-10-20 18:29:58 +02003280 if (hdsp_system_clock_mode(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281 system_clock_mode = "Slave";
Takashi Iwaib0b98112005-10-20 18:29:58 +02003282 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283 system_clock_mode = "Master";
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284
3285 switch (hdsp_pref_sync_ref (hdsp)) {
3286 case HDSP_SYNC_FROM_WORD:
3287 pref_sync_ref = "Word Clock";
3288 break;
3289 case HDSP_SYNC_FROM_ADAT_SYNC:
3290 pref_sync_ref = "ADAT Sync";
3291 break;
3292 case HDSP_SYNC_FROM_SPDIF:
3293 pref_sync_ref = "SPDIF";
3294 break;
3295 case HDSP_SYNC_FROM_ADAT1:
3296 pref_sync_ref = "ADAT1";
3297 break;
3298 case HDSP_SYNC_FROM_ADAT2:
3299 pref_sync_ref = "ADAT2";
3300 break;
3301 case HDSP_SYNC_FROM_ADAT3:
3302 pref_sync_ref = "ADAT3";
3303 break;
3304 default:
3305 pref_sync_ref = "Word Clock";
3306 break;
3307 }
3308 snd_iprintf (buffer, "Preferred Sync Reference: %s\n", pref_sync_ref);
3309
3310 switch (hdsp_autosync_ref (hdsp)) {
3311 case HDSP_AUTOSYNC_FROM_WORD:
3312 autosync_ref = "Word Clock";
3313 break;
3314 case HDSP_AUTOSYNC_FROM_ADAT_SYNC:
3315 autosync_ref = "ADAT Sync";
3316 break;
3317 case HDSP_AUTOSYNC_FROM_SPDIF:
3318 autosync_ref = "SPDIF";
3319 break;
3320 case HDSP_AUTOSYNC_FROM_NONE:
3321 autosync_ref = "None";
3322 break;
3323 case HDSP_AUTOSYNC_FROM_ADAT1:
3324 autosync_ref = "ADAT1";
3325 break;
3326 case HDSP_AUTOSYNC_FROM_ADAT2:
3327 autosync_ref = "ADAT2";
3328 break;
3329 case HDSP_AUTOSYNC_FROM_ADAT3:
3330 autosync_ref = "ADAT3";
3331 break;
3332 default:
3333 autosync_ref = "---";
3334 break;
3335 }
3336 snd_iprintf (buffer, "AutoSync Reference: %s\n", autosync_ref);
3337
3338 snd_iprintf (buffer, "AutoSync Frequency: %d\n", hdsp_external_sample_rate(hdsp));
3339
3340 snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode);
3341
3342 snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003343 snd_iprintf (buffer, "System Clock Locked: %s\n", hdsp->clock_source_locked ? "Yes" : "No");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344
3345 snd_iprintf(buffer, "\n");
3346
3347 switch (hdsp_spdif_in(hdsp)) {
3348 case HDSP_SPDIFIN_OPTICAL:
3349 snd_iprintf(buffer, "IEC958 input: Optical\n");
3350 break;
3351 case HDSP_SPDIFIN_COAXIAL:
3352 snd_iprintf(buffer, "IEC958 input: Coaxial\n");
3353 break;
3354 case HDSP_SPDIFIN_INTERNAL:
3355 snd_iprintf(buffer, "IEC958 input: Internal\n");
3356 break;
3357 case HDSP_SPDIFIN_AES:
3358 snd_iprintf(buffer, "IEC958 input: AES\n");
3359 break;
3360 default:
3361 snd_iprintf(buffer, "IEC958 input: ???\n");
3362 break;
3363 }
3364
Takashi Iwaib0b98112005-10-20 18:29:58 +02003365 if (hdsp->control_register & HDSP_SPDIFOpticalOut)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366 snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003367 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368 snd_iprintf(buffer, "IEC958 output: Coaxial only\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369
Takashi Iwaib0b98112005-10-20 18:29:58 +02003370 if (hdsp->control_register & HDSP_SPDIFProfessional)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371 snd_iprintf(buffer, "IEC958 quality: Professional\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003372 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373 snd_iprintf(buffer, "IEC958 quality: Consumer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374
Takashi Iwaib0b98112005-10-20 18:29:58 +02003375 if (hdsp->control_register & HDSP_SPDIFEmphasis)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376 snd_iprintf(buffer, "IEC958 emphasis: on\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003377 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378 snd_iprintf(buffer, "IEC958 emphasis: off\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379
Takashi Iwaib0b98112005-10-20 18:29:58 +02003380 if (hdsp->control_register & HDSP_SPDIFNonAudio)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381 snd_iprintf(buffer, "IEC958 NonAudio: on\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003382 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383 snd_iprintf(buffer, "IEC958 NonAudio: off\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003384 if ((x = hdsp_spdif_sample_rate (hdsp)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385 snd_iprintf (buffer, "IEC958 sample rate: %d\n", x);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003386 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387 snd_iprintf (buffer, "IEC958 sample rate: Error flag set\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388
3389 snd_iprintf(buffer, "\n");
3390
3391 /* Sync Check */
3392 x = status & HDSP_Sync0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003393 if (status & HDSP_Lock0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394 snd_iprintf(buffer, "ADAT1: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003395 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396 snd_iprintf(buffer, "ADAT1: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003397
3398 switch (hdsp->io_type) {
3399 case Digiface:
3400 case H9652:
3401 x = status & HDSP_Sync1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003402 if (status & HDSP_Lock1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003403 snd_iprintf(buffer, "ADAT2: %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, "ADAT2: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406 x = status & HDSP_Sync2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003407 if (status & HDSP_Lock2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408 snd_iprintf(buffer, "ADAT3: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003409 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410 snd_iprintf(buffer, "ADAT3: No Lock\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003411 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412 default:
3413 /* relax */
3414 break;
3415 }
3416
3417 x = status & HDSP_SPDIFSync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003418 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419 snd_iprintf (buffer, "SPDIF: No Lock\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003420 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421 snd_iprintf (buffer, "SPDIF: %s\n", x ? "Sync" : "Lock");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422
3423 x = status2 & HDSP_wc_sync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003424 if (status2 & HDSP_wc_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425 snd_iprintf (buffer, "Word Clock: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003426 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427 snd_iprintf (buffer, "Word Clock: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428
3429 x = status & HDSP_TimecodeSync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003430 if (status & HDSP_TimecodeLock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431 snd_iprintf(buffer, "ADAT Sync: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003432 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003433 snd_iprintf(buffer, "ADAT Sync: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434
3435 snd_iprintf(buffer, "\n");
3436
3437 /* Informations about H9632 specific controls */
3438 if (hdsp->io_type == H9632) {
3439 char *tmp;
3440
3441 switch (hdsp_ad_gain(hdsp)) {
3442 case 0:
3443 tmp = "-10 dBV";
3444 break;
3445 case 1:
3446 tmp = "+4 dBu";
3447 break;
3448 default:
3449 tmp = "Lo Gain";
3450 break;
3451 }
3452 snd_iprintf(buffer, "AD Gain : %s\n", tmp);
3453
3454 switch (hdsp_da_gain(hdsp)) {
3455 case 0:
3456 tmp = "Hi Gain";
3457 break;
3458 case 1:
3459 tmp = "+4 dBu";
3460 break;
3461 default:
3462 tmp = "-10 dBV";
3463 break;
3464 }
3465 snd_iprintf(buffer, "DA Gain : %s\n", tmp);
3466
3467 switch (hdsp_phone_gain(hdsp)) {
3468 case 0:
3469 tmp = "0 dB";
3470 break;
3471 case 1:
3472 tmp = "-6 dB";
3473 break;
3474 default:
3475 tmp = "-12 dB";
3476 break;
3477 }
3478 snd_iprintf(buffer, "Phones Gain : %s\n", tmp);
3479
3480 snd_iprintf(buffer, "XLR Breakout Cable : %s\n", hdsp_xlr_breakout_cable(hdsp) ? "yes" : "no");
3481
Takashi Iwaib0b98112005-10-20 18:29:58 +02003482 if (hdsp->control_register & HDSP_AnalogExtensionBoard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483 snd_iprintf(buffer, "AEB : on (ADAT1 internal)\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003484 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485 snd_iprintf(buffer, "AEB : off (ADAT1 external)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486 snd_iprintf(buffer, "\n");
3487 }
3488
3489}
3490
Takashi Iwai55e957d2005-11-17 14:52:13 +01003491static void __devinit snd_hdsp_proc_init(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003493 struct snd_info_entry *entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494
3495 if (! snd_card_proc_new(hdsp->card, "hdsp", &entry))
Takashi Iwaibf850202006-04-28 15:13:41 +02003496 snd_info_set_text_ops(entry, hdsp, snd_hdsp_proc_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003497}
3498
Takashi Iwai55e957d2005-11-17 14:52:13 +01003499static void snd_hdsp_free_buffers(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500{
3501 snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci);
3502 snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
3503}
3504
Takashi Iwai55e957d2005-11-17 14:52:13 +01003505static int __devinit snd_hdsp_initialize_memory(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506{
3507 unsigned long pb_bus, cb_bus;
3508
3509 if (snd_hammerfall_get_buffer(hdsp->pci, &hdsp->capture_dma_buf, HDSP_DMA_AREA_BYTES) < 0 ||
3510 snd_hammerfall_get_buffer(hdsp->pci, &hdsp->playback_dma_buf, HDSP_DMA_AREA_BYTES) < 0) {
3511 if (hdsp->capture_dma_buf.area)
3512 snd_dma_free_pages(&hdsp->capture_dma_buf);
3513 printk(KERN_ERR "%s: no buffers available\n", hdsp->card_name);
3514 return -ENOMEM;
3515 }
3516
3517 /* Align to bus-space 64K boundary */
3518
Clemens Ladisch7ab39922006-10-09 08:13:32 +02003519 cb_bus = ALIGN(hdsp->capture_dma_buf.addr, 0x10000ul);
3520 pb_bus = ALIGN(hdsp->playback_dma_buf.addr, 0x10000ul);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521
3522 /* Tell the card where it is */
3523
3524 hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus);
3525 hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus);
3526
3527 hdsp->capture_buffer = hdsp->capture_dma_buf.area + (cb_bus - hdsp->capture_dma_buf.addr);
3528 hdsp->playback_buffer = hdsp->playback_dma_buf.area + (pb_bus - hdsp->playback_dma_buf.addr);
3529
3530 return 0;
3531}
3532
Takashi Iwai55e957d2005-11-17 14:52:13 +01003533static int snd_hdsp_set_defaults(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534{
3535 unsigned int i;
3536
3537 /* ASSUMPTION: hdsp->lock is either held, or
3538 there is no need to hold it (e.g. during module
3539 initalization).
3540 */
3541
3542 /* set defaults:
3543
3544 SPDIF Input via Coax
3545 Master clock mode
3546 maximum latency (7 => 2^7 = 8192 samples, 64Kbyte buffer,
3547 which implies 2 4096 sample, 32Kbyte periods).
3548 Enable line out.
3549 */
3550
3551 hdsp->control_register = HDSP_ClockModeMaster |
3552 HDSP_SPDIFInputCoaxial |
3553 hdsp_encode_latency(7) |
3554 HDSP_LineOut;
3555
3556
3557 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3558
3559#ifdef SNDRV_BIG_ENDIAN
3560 hdsp->control2_register = HDSP_BIGENDIAN_MODE;
3561#else
3562 hdsp->control2_register = 0;
3563#endif
Takashi Iwaib0b98112005-10-20 18:29:58 +02003564 if (hdsp->io_type == H9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565 snd_hdsp_9652_enable_mixer (hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003566 else
3567 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568
3569 hdsp_reset_hw_pointer(hdsp);
3570 hdsp_compute_period_size(hdsp);
3571
3572 /* silence everything */
3573
Takashi Iwaib0b98112005-10-20 18:29:58 +02003574 for (i = 0; i < HDSP_MATRIX_MIXER_SIZE; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003575 hdsp->mixer_matrix[i] = MINUS_INFINITY_GAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003576
3577 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 +02003578 if (hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003580 }
3581
3582 /* H9632 specific defaults */
3583 if (hdsp->io_type == H9632) {
3584 hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB);
3585 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3586 }
3587
3588 /* set a default rate so that the channel map is set up.
3589 */
3590
3591 hdsp_set_rate(hdsp, 48000, 1);
3592
3593 return 0;
3594}
3595
3596static void hdsp_midi_tasklet(unsigned long arg)
3597{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003598 struct hdsp *hdsp = (struct hdsp *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599
Takashi Iwaib0b98112005-10-20 18:29:58 +02003600 if (hdsp->midi[0].pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601 snd_hdsp_midi_input_read (&hdsp->midi[0]);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003602 if (hdsp->midi[1].pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603 snd_hdsp_midi_input_read (&hdsp->midi[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003604}
3605
David Howells7d12e782006-10-05 14:55:46 +01003606static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003608 struct hdsp *hdsp = (struct hdsp *) dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609 unsigned int status;
3610 int audio;
3611 int midi0;
3612 int midi1;
3613 unsigned int midi0status;
3614 unsigned int midi1status;
3615 int schedule = 0;
3616
3617 status = hdsp_read(hdsp, HDSP_statusRegister);
3618
3619 audio = status & HDSP_audioIRQPending;
3620 midi0 = status & HDSP_midi0IRQPending;
3621 midi1 = status & HDSP_midi1IRQPending;
3622
Takashi Iwaib0b98112005-10-20 18:29:58 +02003623 if (!audio && !midi0 && !midi1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 return IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625
3626 hdsp_write(hdsp, HDSP_interruptConfirmation, 0);
3627
3628 midi0status = hdsp_read (hdsp, HDSP_midiStatusIn0) & 0xff;
3629 midi1status = hdsp_read (hdsp, HDSP_midiStatusIn1) & 0xff;
3630
3631 if (audio) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003632 if (hdsp->capture_substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633 snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634
Takashi Iwaib0b98112005-10-20 18:29:58 +02003635 if (hdsp->playback_substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636 snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637 }
3638
3639 if (midi0 && midi0status) {
3640 if (hdsp->use_midi_tasklet) {
3641 /* we disable interrupts for this input until processing is done */
3642 hdsp->control_register &= ~HDSP_Midi0InterruptEnable;
3643 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3644 hdsp->midi[0].pending = 1;
3645 schedule = 1;
3646 } else {
3647 snd_hdsp_midi_input_read (&hdsp->midi[0]);
3648 }
3649 }
3650 if (hdsp->io_type != Multiface && hdsp->io_type != H9632 && midi1 && midi1status) {
3651 if (hdsp->use_midi_tasklet) {
3652 /* we disable interrupts for this input until processing is done */
3653 hdsp->control_register &= ~HDSP_Midi1InterruptEnable;
3654 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3655 hdsp->midi[1].pending = 1;
3656 schedule = 1;
3657 } else {
3658 snd_hdsp_midi_input_read (&hdsp->midi[1]);
3659 }
3660 }
3661 if (hdsp->use_midi_tasklet && schedule)
3662 tasklet_hi_schedule(&hdsp->midi_tasklet);
3663 return IRQ_HANDLED;
3664}
3665
Takashi Iwai55e957d2005-11-17 14:52:13 +01003666static snd_pcm_uframes_t snd_hdsp_hw_pointer(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003667{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003668 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669 return hdsp_hw_pointer(hdsp);
3670}
3671
Takashi Iwai55e957d2005-11-17 14:52:13 +01003672static char *hdsp_channel_buffer_location(struct hdsp *hdsp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673 int stream,
3674 int channel)
3675
3676{
3677 int mapped_channel;
3678
3679 snd_assert(channel >= 0 && channel < hdsp->max_channels, return NULL);
3680
Takashi Iwaib0b98112005-10-20 18:29:58 +02003681 if ((mapped_channel = hdsp->channel_map[channel]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683
Takashi Iwaib0b98112005-10-20 18:29:58 +02003684 if (stream == SNDRV_PCM_STREAM_CAPTURE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685 return hdsp->capture_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003686 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687 return hdsp->playback_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003688}
3689
Takashi Iwai55e957d2005-11-17 14:52:13 +01003690static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003691 snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
3692{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003693 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694 char *channel_buf;
3695
3696 snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
3697
3698 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
3699 snd_assert(channel_buf != NULL, return -EIO);
3700 if (copy_from_user(channel_buf + pos * 4, src, count * 4))
3701 return -EFAULT;
3702 return count;
3703}
3704
Takashi Iwai55e957d2005-11-17 14:52:13 +01003705static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count)
3707{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003708 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709 char *channel_buf;
3710
3711 snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
3712
3713 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
3714 snd_assert(channel_buf != NULL, return -EIO);
3715 if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
3716 return -EFAULT;
3717 return count;
3718}
3719
Takashi Iwai55e957d2005-11-17 14:52:13 +01003720static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721 snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
3722{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003723 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724 char *channel_buf;
3725
3726 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
3727 snd_assert(channel_buf != NULL, return -EIO);
3728 memset(channel_buf + pos * 4, 0, count * 4);
3729 return count;
3730}
3731
Takashi Iwai55e957d2005-11-17 14:52:13 +01003732static int snd_hdsp_reset(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003734 struct snd_pcm_runtime *runtime = substream->runtime;
3735 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
3736 struct snd_pcm_substream *other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3738 other = hdsp->capture_substream;
3739 else
3740 other = hdsp->playback_substream;
3741 if (hdsp->running)
3742 runtime->status->hw_ptr = hdsp_hw_pointer(hdsp);
3743 else
3744 runtime->status->hw_ptr = 0;
3745 if (other) {
3746 struct list_head *pos;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003747 struct snd_pcm_substream *s;
3748 struct snd_pcm_runtime *oruntime = other->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749 snd_pcm_group_for_each(pos, substream) {
3750 s = snd_pcm_group_substream_entry(pos);
3751 if (s == other) {
3752 oruntime->status->hw_ptr = runtime->status->hw_ptr;
3753 break;
3754 }
3755 }
3756 }
3757 return 0;
3758}
3759
Takashi Iwai55e957d2005-11-17 14:52:13 +01003760static int snd_hdsp_hw_params(struct snd_pcm_substream *substream,
3761 struct snd_pcm_hw_params *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003762{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003763 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764 int err;
3765 pid_t this_pid;
3766 pid_t other_pid;
3767
Takashi Iwaib0b98112005-10-20 18:29:58 +02003768 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770
Takashi Iwaib0b98112005-10-20 18:29:58 +02003771 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773
3774 spin_lock_irq(&hdsp->lock);
3775
3776 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3777 hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
3778 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= hdsp->creg_spdif_stream);
3779 this_pid = hdsp->playback_pid;
3780 other_pid = hdsp->capture_pid;
3781 } else {
3782 this_pid = hdsp->capture_pid;
3783 other_pid = hdsp->playback_pid;
3784 }
3785
3786 if ((other_pid > 0) && (this_pid != other_pid)) {
3787
3788 /* The other stream is open, and not by the same
3789 task as this one. Make sure that the parameters
3790 that matter are the same.
3791 */
3792
3793 if (params_rate(params) != hdsp->system_sample_rate) {
3794 spin_unlock_irq(&hdsp->lock);
3795 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
3796 return -EBUSY;
3797 }
3798
3799 if (params_period_size(params) != hdsp->period_bytes / 4) {
3800 spin_unlock_irq(&hdsp->lock);
3801 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
3802 return -EBUSY;
3803 }
3804
3805 /* We're fine. */
3806
3807 spin_unlock_irq(&hdsp->lock);
3808 return 0;
3809
3810 } else {
3811 spin_unlock_irq(&hdsp->lock);
3812 }
3813
3814 /* how to make sure that the rate matches an externally-set one ?
3815 */
3816
3817 spin_lock_irq(&hdsp->lock);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003818 if (! hdsp->clock_source_locked) {
3819 if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) {
3820 spin_unlock_irq(&hdsp->lock);
3821 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
3822 return err;
3823 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824 }
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003825 spin_unlock_irq(&hdsp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826
3827 if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) {
3828 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
3829 return err;
3830 }
3831
3832 return 0;
3833}
3834
Takashi Iwai55e957d2005-11-17 14:52:13 +01003835static int snd_hdsp_channel_info(struct snd_pcm_substream *substream,
3836 struct snd_pcm_channel_info *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003838 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839 int mapped_channel;
3840
3841 snd_assert(info->channel < hdsp->max_channels, return -EINVAL);
3842
Takashi Iwaib0b98112005-10-20 18:29:58 +02003843 if ((mapped_channel = hdsp->channel_map[info->channel]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845
3846 info->offset = mapped_channel * HDSP_CHANNEL_BUFFER_BYTES;
3847 info->first = 0;
3848 info->step = 32;
3849 return 0;
3850}
3851
Takashi Iwai55e957d2005-11-17 14:52:13 +01003852static int snd_hdsp_ioctl(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853 unsigned int cmd, void *arg)
3854{
3855 switch (cmd) {
3856 case SNDRV_PCM_IOCTL1_RESET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857 return snd_hdsp_reset(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Takashi Iwaib0b98112005-10-20 18:29:58 +02003859 return snd_hdsp_channel_info(substream, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860 default:
3861 break;
3862 }
3863
3864 return snd_pcm_lib_ioctl(substream, cmd, arg);
3865}
3866
Takashi Iwai55e957d2005-11-17 14:52:13 +01003867static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003869 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
3870 struct snd_pcm_substream *other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871 int running;
3872
Takashi Iwaib0b98112005-10-20 18:29:58 +02003873 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875
Takashi Iwai311e70a2006-09-06 12:13:37 +02003876 if (hdsp_check_for_firmware(hdsp, 0)) /* no auto-loading in trigger */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878
3879 spin_lock(&hdsp->lock);
3880 running = hdsp->running;
3881 switch (cmd) {
3882 case SNDRV_PCM_TRIGGER_START:
3883 running |= 1 << substream->stream;
3884 break;
3885 case SNDRV_PCM_TRIGGER_STOP:
3886 running &= ~(1 << substream->stream);
3887 break;
3888 default:
3889 snd_BUG();
3890 spin_unlock(&hdsp->lock);
3891 return -EINVAL;
3892 }
3893 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3894 other = hdsp->capture_substream;
3895 else
3896 other = hdsp->playback_substream;
3897
3898 if (other) {
3899 struct list_head *pos;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003900 struct snd_pcm_substream *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901 snd_pcm_group_for_each(pos, substream) {
3902 s = snd_pcm_group_substream_entry(pos);
3903 if (s == other) {
3904 snd_pcm_trigger_done(s, substream);
3905 if (cmd == SNDRV_PCM_TRIGGER_START)
3906 running |= 1 << s->stream;
3907 else
3908 running &= ~(1 << s->stream);
3909 goto _ok;
3910 }
3911 }
3912 if (cmd == SNDRV_PCM_TRIGGER_START) {
3913 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) &&
3914 substream->stream == SNDRV_PCM_STREAM_CAPTURE)
3915 hdsp_silence_playback(hdsp);
3916 } else {
3917 if (running &&
3918 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3919 hdsp_silence_playback(hdsp);
3920 }
3921 } else {
3922 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
3923 hdsp_silence_playback(hdsp);
3924 }
3925 _ok:
3926 snd_pcm_trigger_done(substream, substream);
3927 if (!hdsp->running && running)
3928 hdsp_start_audio(hdsp);
3929 else if (hdsp->running && !running)
3930 hdsp_stop_audio(hdsp);
3931 hdsp->running = running;
3932 spin_unlock(&hdsp->lock);
3933
3934 return 0;
3935}
3936
Takashi Iwai55e957d2005-11-17 14:52:13 +01003937static int snd_hdsp_prepare(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003939 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940 int result = 0;
3941
Takashi Iwaib0b98112005-10-20 18:29:58 +02003942 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944
Takashi Iwaib0b98112005-10-20 18:29:58 +02003945 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947
3948 spin_lock_irq(&hdsp->lock);
3949 if (!hdsp->running)
3950 hdsp_reset_hw_pointer(hdsp);
3951 spin_unlock_irq(&hdsp->lock);
3952 return result;
3953}
3954
Takashi Iwai55e957d2005-11-17 14:52:13 +01003955static struct snd_pcm_hardware snd_hdsp_playback_subinfo =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956{
3957 .info = (SNDRV_PCM_INFO_MMAP |
3958 SNDRV_PCM_INFO_MMAP_VALID |
3959 SNDRV_PCM_INFO_NONINTERLEAVED |
3960 SNDRV_PCM_INFO_SYNC_START |
3961 SNDRV_PCM_INFO_DOUBLE),
3962#ifdef SNDRV_BIG_ENDIAN
3963 .formats = SNDRV_PCM_FMTBIT_S32_BE,
3964#else
3965 .formats = SNDRV_PCM_FMTBIT_S32_LE,
3966#endif
3967 .rates = (SNDRV_PCM_RATE_32000 |
3968 SNDRV_PCM_RATE_44100 |
3969 SNDRV_PCM_RATE_48000 |
3970 SNDRV_PCM_RATE_64000 |
3971 SNDRV_PCM_RATE_88200 |
3972 SNDRV_PCM_RATE_96000),
3973 .rate_min = 32000,
3974 .rate_max = 96000,
3975 .channels_min = 14,
3976 .channels_max = HDSP_MAX_CHANNELS,
3977 .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS,
3978 .period_bytes_min = (64 * 4) * 10,
3979 .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS,
3980 .periods_min = 2,
3981 .periods_max = 2,
3982 .fifo_size = 0
3983};
3984
Takashi Iwai55e957d2005-11-17 14:52:13 +01003985static struct snd_pcm_hardware snd_hdsp_capture_subinfo =
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986{
3987 .info = (SNDRV_PCM_INFO_MMAP |
3988 SNDRV_PCM_INFO_MMAP_VALID |
3989 SNDRV_PCM_INFO_NONINTERLEAVED |
3990 SNDRV_PCM_INFO_SYNC_START),
3991#ifdef SNDRV_BIG_ENDIAN
3992 .formats = SNDRV_PCM_FMTBIT_S32_BE,
3993#else
3994 .formats = SNDRV_PCM_FMTBIT_S32_LE,
3995#endif
3996 .rates = (SNDRV_PCM_RATE_32000 |
3997 SNDRV_PCM_RATE_44100 |
3998 SNDRV_PCM_RATE_48000 |
3999 SNDRV_PCM_RATE_64000 |
4000 SNDRV_PCM_RATE_88200 |
4001 SNDRV_PCM_RATE_96000),
4002 .rate_min = 32000,
4003 .rate_max = 96000,
4004 .channels_min = 14,
4005 .channels_max = HDSP_MAX_CHANNELS,
4006 .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS,
4007 .period_bytes_min = (64 * 4) * 10,
4008 .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS,
4009 .periods_min = 2,
4010 .periods_max = 2,
4011 .fifo_size = 0
4012};
4013
4014static unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
4015
Takashi Iwai55e957d2005-11-17 14:52:13 +01004016static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_period_sizes = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017 .count = ARRAY_SIZE(hdsp_period_sizes),
4018 .list = hdsp_period_sizes,
4019 .mask = 0
4020};
4021
4022static unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 };
4023
Takashi Iwai55e957d2005-11-17 14:52:13 +01004024static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_9632_sample_rates = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025 .count = ARRAY_SIZE(hdsp_9632_sample_rates),
4026 .list = hdsp_9632_sample_rates,
4027 .mask = 0
4028};
4029
Takashi Iwai55e957d2005-11-17 14:52:13 +01004030static int snd_hdsp_hw_rule_in_channels(struct snd_pcm_hw_params *params,
4031 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004033 struct hdsp *hdsp = rule->private;
4034 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035 if (hdsp->io_type == H9632) {
4036 unsigned int list[3];
4037 list[0] = hdsp->qs_in_channels;
4038 list[1] = hdsp->ds_in_channels;
4039 list[2] = hdsp->ss_in_channels;
4040 return snd_interval_list(c, 3, list, 0);
4041 } else {
4042 unsigned int list[2];
4043 list[0] = hdsp->ds_in_channels;
4044 list[1] = hdsp->ss_in_channels;
4045 return snd_interval_list(c, 2, list, 0);
4046 }
4047}
4048
Takashi Iwai55e957d2005-11-17 14:52:13 +01004049static int snd_hdsp_hw_rule_out_channels(struct snd_pcm_hw_params *params,
4050 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051{
4052 unsigned int list[3];
Takashi Iwai55e957d2005-11-17 14:52:13 +01004053 struct hdsp *hdsp = rule->private;
4054 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055 if (hdsp->io_type == H9632) {
4056 list[0] = hdsp->qs_out_channels;
4057 list[1] = hdsp->ds_out_channels;
4058 list[2] = hdsp->ss_out_channels;
4059 return snd_interval_list(c, 3, list, 0);
4060 } else {
4061 list[0] = hdsp->ds_out_channels;
4062 list[1] = hdsp->ss_out_channels;
4063 }
4064 return snd_interval_list(c, 2, list, 0);
4065}
4066
Takashi Iwai55e957d2005-11-17 14:52:13 +01004067static int snd_hdsp_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
4068 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004070 struct hdsp *hdsp = rule->private;
4071 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4072 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073 if (r->min > 96000 && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004074 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 .min = hdsp->qs_in_channels,
4076 .max = hdsp->qs_in_channels,
4077 .integer = 1,
4078 };
4079 return snd_interval_refine(c, &t);
4080 } else if (r->min > 48000 && r->max <= 96000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004081 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082 .min = hdsp->ds_in_channels,
4083 .max = hdsp->ds_in_channels,
4084 .integer = 1,
4085 };
4086 return snd_interval_refine(c, &t);
4087 } else if (r->max < 64000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004088 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089 .min = hdsp->ss_in_channels,
4090 .max = hdsp->ss_in_channels,
4091 .integer = 1,
4092 };
4093 return snd_interval_refine(c, &t);
4094 }
4095 return 0;
4096}
4097
Takashi Iwai55e957d2005-11-17 14:52:13 +01004098static int snd_hdsp_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
4099 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004101 struct hdsp *hdsp = rule->private;
4102 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4103 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104 if (r->min > 96000 && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004105 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 .min = hdsp->qs_out_channels,
4107 .max = hdsp->qs_out_channels,
4108 .integer = 1,
4109 };
4110 return snd_interval_refine(c, &t);
4111 } else if (r->min > 48000 && r->max <= 96000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004112 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113 .min = hdsp->ds_out_channels,
4114 .max = hdsp->ds_out_channels,
4115 .integer = 1,
4116 };
4117 return snd_interval_refine(c, &t);
4118 } else if (r->max < 64000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004119 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120 .min = hdsp->ss_out_channels,
4121 .max = hdsp->ss_out_channels,
4122 .integer = 1,
4123 };
4124 return snd_interval_refine(c, &t);
4125 }
4126 return 0;
4127}
4128
Takashi Iwai55e957d2005-11-17 14:52:13 +01004129static int snd_hdsp_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
4130 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004132 struct hdsp *hdsp = rule->private;
4133 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4134 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135 if (c->min >= hdsp->ss_out_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004136 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137 .min = 32000,
4138 .max = 48000,
4139 .integer = 1,
4140 };
4141 return snd_interval_refine(r, &t);
4142 } else if (c->max <= hdsp->qs_out_channels && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004143 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144 .min = 128000,
4145 .max = 192000,
4146 .integer = 1,
4147 };
4148 return snd_interval_refine(r, &t);
4149 } else if (c->max <= hdsp->ds_out_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004150 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 .min = 64000,
4152 .max = 96000,
4153 .integer = 1,
4154 };
4155 return snd_interval_refine(r, &t);
4156 }
4157 return 0;
4158}
4159
Takashi Iwai55e957d2005-11-17 14:52:13 +01004160static int snd_hdsp_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
4161 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004163 struct hdsp *hdsp = rule->private;
4164 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4165 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166 if (c->min >= hdsp->ss_in_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004167 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168 .min = 32000,
4169 .max = 48000,
4170 .integer = 1,
4171 };
4172 return snd_interval_refine(r, &t);
4173 } else if (c->max <= hdsp->qs_in_channels && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004174 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 .min = 128000,
4176 .max = 192000,
4177 .integer = 1,
4178 };
4179 return snd_interval_refine(r, &t);
4180 } else if (c->max <= hdsp->ds_in_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004181 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182 .min = 64000,
4183 .max = 96000,
4184 .integer = 1,
4185 };
4186 return snd_interval_refine(r, &t);
4187 }
4188 return 0;
4189}
4190
Takashi Iwai55e957d2005-11-17 14:52:13 +01004191static int snd_hdsp_playback_open(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004193 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4194 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195
Takashi Iwaib0b98112005-10-20 18:29:58 +02004196 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198
Takashi Iwaib0b98112005-10-20 18:29:58 +02004199 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004201
4202 spin_lock_irq(&hdsp->lock);
4203
4204 snd_pcm_set_sync(substream);
4205
4206 runtime->hw = snd_hdsp_playback_subinfo;
4207 runtime->dma_area = hdsp->playback_buffer;
4208 runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
4209
4210 hdsp->playback_pid = current->pid;
4211 hdsp->playback_substream = substream;
4212
4213 spin_unlock_irq(&hdsp->lock);
4214
4215 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4216 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 +02004217 if (hdsp->clock_source_locked) {
4218 runtime->hw.rate_min = runtime->hw.rate_max = hdsp->system_sample_rate;
4219 } else if (hdsp->io_type == H9632) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004220 runtime->hw.rate_max = 192000;
4221 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
4222 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates);
4223 }
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02004224 if (hdsp->io_type == H9632) {
4225 runtime->hw.channels_min = hdsp->qs_out_channels;
4226 runtime->hw.channels_max = hdsp->ss_out_channels;
4227 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228
4229 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4230 snd_hdsp_hw_rule_out_channels, hdsp,
4231 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4232 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4233 snd_hdsp_hw_rule_out_channels_rate, hdsp,
4234 SNDRV_PCM_HW_PARAM_RATE, -1);
4235 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4236 snd_hdsp_hw_rule_rate_out_channels, hdsp,
4237 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4238
4239 hdsp->creg_spdif_stream = hdsp->creg_spdif;
4240 hdsp->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
4241 snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
4242 SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id);
4243 return 0;
4244}
4245
Takashi Iwai55e957d2005-11-17 14:52:13 +01004246static int snd_hdsp_playback_release(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004248 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249
4250 spin_lock_irq(&hdsp->lock);
4251
4252 hdsp->playback_pid = -1;
4253 hdsp->playback_substream = NULL;
4254
4255 spin_unlock_irq(&hdsp->lock);
4256
4257 hdsp->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
4258 snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
4259 SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id);
4260 return 0;
4261}
4262
4263
Takashi Iwai55e957d2005-11-17 14:52:13 +01004264static int snd_hdsp_capture_open(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004266 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4267 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268
Takashi Iwaib0b98112005-10-20 18:29:58 +02004269 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271
Takashi Iwaib0b98112005-10-20 18:29:58 +02004272 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274
4275 spin_lock_irq(&hdsp->lock);
4276
4277 snd_pcm_set_sync(substream);
4278
4279 runtime->hw = snd_hdsp_capture_subinfo;
4280 runtime->dma_area = hdsp->capture_buffer;
4281 runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
4282
4283 hdsp->capture_pid = current->pid;
4284 hdsp->capture_substream = substream;
4285
4286 spin_unlock_irq(&hdsp->lock);
4287
4288 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4289 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes);
4290 if (hdsp->io_type == H9632) {
4291 runtime->hw.channels_min = hdsp->qs_in_channels;
4292 runtime->hw.channels_max = hdsp->ss_in_channels;
4293 runtime->hw.rate_max = 192000;
4294 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
4295 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates);
4296 }
4297 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4298 snd_hdsp_hw_rule_in_channels, hdsp,
4299 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4300 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4301 snd_hdsp_hw_rule_in_channels_rate, hdsp,
4302 SNDRV_PCM_HW_PARAM_RATE, -1);
4303 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4304 snd_hdsp_hw_rule_rate_in_channels, hdsp,
4305 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4306 return 0;
4307}
4308
Takashi Iwai55e957d2005-11-17 14:52:13 +01004309static int snd_hdsp_capture_release(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004311 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312
4313 spin_lock_irq(&hdsp->lock);
4314
4315 hdsp->capture_pid = -1;
4316 hdsp->capture_substream = NULL;
4317
4318 spin_unlock_irq(&hdsp->lock);
4319 return 0;
4320}
4321
Takashi Iwai55e957d2005-11-17 14:52:13 +01004322static int snd_hdsp_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323{
4324 /* we have nothing to initialize but the call is required */
4325 return 0;
4326}
4327
4328
4329/* helper functions for copying meter values */
4330static inline int copy_u32_le(void __user *dest, void __iomem *src)
4331{
4332 u32 val = readl(src);
4333 return copy_to_user(dest, &val, 4);
4334}
4335
4336static inline int copy_u64_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
4337{
4338 u32 rms_low, rms_high;
4339 u64 rms;
4340 rms_low = readl(src_low);
4341 rms_high = readl(src_high);
4342 rms = ((u64)rms_high << 32) | rms_low;
4343 return copy_to_user(dest, &rms, 8);
4344}
4345
4346static inline int copy_u48_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
4347{
4348 u32 rms_low, rms_high;
4349 u64 rms;
4350 rms_low = readl(src_low) & 0xffffff00;
4351 rms_high = readl(src_high) & 0xffffff00;
4352 rms = ((u64)rms_high << 32) | rms_low;
4353 return copy_to_user(dest, &rms, 8);
4354}
4355
Takashi Iwai55e957d2005-11-17 14:52:13 +01004356static int hdsp_9652_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357{
4358 int doublespeed = 0;
4359 int i, j, channels, ofs;
4360
4361 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
4362 doublespeed = 1;
4363 channels = doublespeed ? 14 : 26;
4364 for (i = 0, j = 0; i < 26; ++i) {
4365 if (doublespeed && (i & 4))
4366 continue;
4367 ofs = HDSP_9652_peakBase - j * 4;
4368 if (copy_u32_le(&peak_rms->input_peaks[i], hdsp->iobase + ofs))
4369 return -EFAULT;
4370 ofs -= channels * 4;
4371 if (copy_u32_le(&peak_rms->playback_peaks[i], hdsp->iobase + ofs))
4372 return -EFAULT;
4373 ofs -= channels * 4;
4374 if (copy_u32_le(&peak_rms->output_peaks[i], hdsp->iobase + ofs))
4375 return -EFAULT;
4376 ofs = HDSP_9652_rmsBase + j * 8;
4377 if (copy_u48_le(&peak_rms->input_rms[i], hdsp->iobase + ofs,
4378 hdsp->iobase + ofs + 4))
4379 return -EFAULT;
4380 ofs += channels * 8;
4381 if (copy_u48_le(&peak_rms->playback_rms[i], hdsp->iobase + ofs,
4382 hdsp->iobase + ofs + 4))
4383 return -EFAULT;
4384 ofs += channels * 8;
4385 if (copy_u48_le(&peak_rms->output_rms[i], hdsp->iobase + ofs,
4386 hdsp->iobase + ofs + 4))
4387 return -EFAULT;
4388 j++;
4389 }
4390 return 0;
4391}
4392
Takashi Iwai55e957d2005-11-17 14:52:13 +01004393static int hdsp_9632_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394{
4395 int i, j;
Takashi Iwai55e957d2005-11-17 14:52:13 +01004396 struct hdsp_9632_meters __iomem *m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397 int doublespeed = 0;
4398
4399 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
4400 doublespeed = 1;
Takashi Iwai55e957d2005-11-17 14:52:13 +01004401 m = (struct hdsp_9632_meters __iomem *)(hdsp->iobase+HDSP_9632_metersBase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402 for (i = 0, j = 0; i < 16; ++i, ++j) {
4403 if (copy_u32_le(&peak_rms->input_peaks[i], &m->input_peak[j]))
4404 return -EFAULT;
4405 if (copy_u32_le(&peak_rms->playback_peaks[i], &m->playback_peak[j]))
4406 return -EFAULT;
4407 if (copy_u32_le(&peak_rms->output_peaks[i], &m->output_peak[j]))
4408 return -EFAULT;
4409 if (copy_u64_le(&peak_rms->input_rms[i], &m->input_rms_low[j],
4410 &m->input_rms_high[j]))
4411 return -EFAULT;
4412 if (copy_u64_le(&peak_rms->playback_rms[i], &m->playback_rms_low[j],
4413 &m->playback_rms_high[j]))
4414 return -EFAULT;
4415 if (copy_u64_le(&peak_rms->output_rms[i], &m->output_rms_low[j],
4416 &m->output_rms_high[j]))
4417 return -EFAULT;
4418 if (doublespeed && i == 3) i += 4;
4419 }
4420 return 0;
4421}
4422
Takashi Iwai55e957d2005-11-17 14:52:13 +01004423static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424{
4425 int i;
4426
4427 for (i = 0; i < 26; i++) {
4428 if (copy_u32_le(&peak_rms->playback_peaks[i],
4429 hdsp->iobase + HDSP_playbackPeakLevel + i * 4))
4430 return -EFAULT;
4431 if (copy_u32_le(&peak_rms->input_peaks[i],
4432 hdsp->iobase + HDSP_inputPeakLevel + i * 4))
4433 return -EFAULT;
4434 }
4435 for (i = 0; i < 28; i++) {
4436 if (copy_u32_le(&peak_rms->output_peaks[i],
4437 hdsp->iobase + HDSP_outputPeakLevel + i * 4))
4438 return -EFAULT;
4439 }
4440 for (i = 0; i < 26; ++i) {
4441 if (copy_u64_le(&peak_rms->playback_rms[i],
4442 hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4,
4443 hdsp->iobase + HDSP_playbackRmsLevel + i * 8))
4444 return -EFAULT;
4445 if (copy_u64_le(&peak_rms->input_rms[i],
4446 hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4,
4447 hdsp->iobase + HDSP_inputRmsLevel + i * 8))
4448 return -EFAULT;
4449 }
4450 return 0;
4451}
4452
Takashi Iwai55e957d2005-11-17 14:52:13 +01004453static 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 -07004454{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004455 struct hdsp *hdsp = (struct hdsp *)hw->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456 void __user *argp = (void __user *)arg;
4457
4458 switch (cmd) {
4459 case SNDRV_HDSP_IOCTL_GET_PEAK_RMS: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004460 struct hdsp_peak_rms __user *peak_rms = (struct hdsp_peak_rms __user *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004461
4462 if (!(hdsp->state & HDSP_FirmwareLoaded)) {
4463 snd_printk(KERN_ERR "Hammerfall-DSP: firmware needs to be uploaded to the card.\n");
4464 return -EINVAL;
4465 }
4466
4467 switch (hdsp->io_type) {
4468 case H9652:
4469 return hdsp_9652_get_peak(hdsp, peak_rms);
4470 case H9632:
4471 return hdsp_9632_get_peak(hdsp, peak_rms);
4472 default:
4473 return hdsp_get_peak(hdsp, peak_rms);
4474 }
4475 }
4476 case SNDRV_HDSP_IOCTL_GET_CONFIG_INFO: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004477 struct hdsp_config_info info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004478 unsigned long flags;
4479 int i;
4480
4481 if (!(hdsp->state & HDSP_FirmwareLoaded)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004482 snd_printk(KERN_ERR "Hammerfall-DSP: Firmware needs to be uploaded to the card.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004483 return -EINVAL;
4484 }
4485 spin_lock_irqsave(&hdsp->lock, flags);
4486 info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp);
4487 info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02004488 if (hdsp->io_type != H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004489 info.adatsync_sync_check = (unsigned char)hdsp_adatsync_sync_check(hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490 info.spdif_sync_check = (unsigned char)hdsp_spdif_sync_check(hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02004491 for (i = 0; i < ((hdsp->io_type != Multiface && hdsp->io_type != H9632) ? 3 : 1); ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 info.adat_sync_check[i] = (unsigned char)hdsp_adat_sync_check(hdsp, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493 info.spdif_in = (unsigned char)hdsp_spdif_in(hdsp);
4494 info.spdif_out = (unsigned char)hdsp_spdif_out(hdsp);
4495 info.spdif_professional = (unsigned char)hdsp_spdif_professional(hdsp);
4496 info.spdif_emphasis = (unsigned char)hdsp_spdif_emphasis(hdsp);
4497 info.spdif_nonaudio = (unsigned char)hdsp_spdif_nonaudio(hdsp);
4498 info.spdif_sample_rate = hdsp_spdif_sample_rate(hdsp);
4499 info.system_sample_rate = hdsp->system_sample_rate;
4500 info.autosync_sample_rate = hdsp_external_sample_rate(hdsp);
4501 info.system_clock_mode = (unsigned char)hdsp_system_clock_mode(hdsp);
4502 info.clock_source = (unsigned char)hdsp_clock_source(hdsp);
4503 info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp);
4504 info.line_out = (unsigned char)hdsp_line_out(hdsp);
4505 if (hdsp->io_type == H9632) {
4506 info.da_gain = (unsigned char)hdsp_da_gain(hdsp);
4507 info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp);
4508 info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp);
4509 info.xlr_breakout_cable = (unsigned char)hdsp_xlr_breakout_cable(hdsp);
4510
4511 }
Takashi Iwaib0b98112005-10-20 18:29:58 +02004512 if (hdsp->io_type == H9632 || hdsp->io_type == H9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004513 info.analog_extension_board = (unsigned char)hdsp_aeb(hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514 spin_unlock_irqrestore(&hdsp->lock, flags);
4515 if (copy_to_user(argp, &info, sizeof(info)))
4516 return -EFAULT;
4517 break;
4518 }
4519 case SNDRV_HDSP_IOCTL_GET_9632_AEB: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004520 struct hdsp_9632_aeb h9632_aeb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004521
4522 if (hdsp->io_type != H9632) return -EINVAL;
4523 h9632_aeb.aebi = hdsp->ss_in_channels - H9632_SS_CHANNELS;
4524 h9632_aeb.aebo = hdsp->ss_out_channels - H9632_SS_CHANNELS;
4525 if (copy_to_user(argp, &h9632_aeb, sizeof(h9632_aeb)))
4526 return -EFAULT;
4527 break;
4528 }
4529 case SNDRV_HDSP_IOCTL_GET_VERSION: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004530 struct hdsp_version hdsp_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004531 int err;
4532
4533 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
4534 if (hdsp->io_type == Undefined) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004535 if ((err = hdsp_get_iobox_version(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004536 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004537 }
4538 hdsp_version.io_type = hdsp->io_type;
4539 hdsp_version.firmware_rev = hdsp->firmware_rev;
Takashi Iwaib0b98112005-10-20 18:29:58 +02004540 if ((err = copy_to_user(argp, &hdsp_version, sizeof(hdsp_version))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004542 break;
4543 }
4544 case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004545 struct hdsp_firmware __user *firmware;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004546 u32 __user *firmware_data;
4547 int err;
4548
4549 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
4550 /* SNDRV_HDSP_IOCTL_GET_VERSION must have been called */
4551 if (hdsp->io_type == Undefined) return -EINVAL;
4552
4553 if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded))
4554 return -EBUSY;
4555
Takashi Iwaib0b98112005-10-20 18:29:58 +02004556 snd_printk(KERN_INFO "Hammerfall-DSP: initializing firmware upload\n");
Takashi Iwai55e957d2005-11-17 14:52:13 +01004557 firmware = (struct hdsp_firmware __user *)argp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558
Takashi Iwaib0b98112005-10-20 18:29:58 +02004559 if (get_user(firmware_data, &firmware->firmware_data))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004560 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004561
Takashi Iwaib0b98112005-10-20 18:29:58 +02004562 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004563 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564
Takashi Iwaib0b98112005-10-20 18:29:58 +02004565 if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004567
4568 hdsp->state |= HDSP_FirmwareCached;
4569
Takashi Iwaib0b98112005-10-20 18:29:58 +02004570 if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004571 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004572
4573 if (!(hdsp->state & HDSP_InitializationComplete)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004574 if ((err = snd_hdsp_enable_io(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004575 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004576
4577 snd_hdsp_initialize_channels(hdsp);
4578 snd_hdsp_initialize_midi_flush(hdsp);
4579
4580 if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004581 snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n");
4582 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004583 }
4584 }
4585 break;
4586 }
4587 case SNDRV_HDSP_IOCTL_GET_MIXER: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004588 struct hdsp_mixer __user *mixer = (struct hdsp_mixer __user *)argp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004589 if (copy_to_user(mixer->matrix, hdsp->mixer_matrix, sizeof(unsigned short)*HDSP_MATRIX_MIXER_SIZE))
4590 return -EFAULT;
4591 break;
4592 }
4593 default:
4594 return -EINVAL;
4595 }
4596 return 0;
4597}
4598
Takashi Iwai55e957d2005-11-17 14:52:13 +01004599static struct snd_pcm_ops snd_hdsp_playback_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004600 .open = snd_hdsp_playback_open,
4601 .close = snd_hdsp_playback_release,
4602 .ioctl = snd_hdsp_ioctl,
4603 .hw_params = snd_hdsp_hw_params,
4604 .prepare = snd_hdsp_prepare,
4605 .trigger = snd_hdsp_trigger,
4606 .pointer = snd_hdsp_hw_pointer,
4607 .copy = snd_hdsp_playback_copy,
4608 .silence = snd_hdsp_hw_silence,
4609};
4610
Takashi Iwai55e957d2005-11-17 14:52:13 +01004611static struct snd_pcm_ops snd_hdsp_capture_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004612 .open = snd_hdsp_capture_open,
4613 .close = snd_hdsp_capture_release,
4614 .ioctl = snd_hdsp_ioctl,
4615 .hw_params = snd_hdsp_hw_params,
4616 .prepare = snd_hdsp_prepare,
4617 .trigger = snd_hdsp_trigger,
4618 .pointer = snd_hdsp_hw_pointer,
4619 .copy = snd_hdsp_capture_copy,
4620};
4621
Takashi Iwai55e957d2005-11-17 14:52:13 +01004622static int __devinit snd_hdsp_create_hwdep(struct snd_card *card,
4623 struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004624{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004625 struct snd_hwdep *hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004626 int err;
4627
4628 if ((err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw)) < 0)
4629 return err;
4630
4631 hdsp->hwdep = hw;
4632 hw->private_data = hdsp;
4633 strcpy(hw->name, "HDSP hwdep interface");
4634
4635 hw->ops.open = snd_hdsp_hwdep_dummy_op;
4636 hw->ops.ioctl = snd_hdsp_hwdep_ioctl;
4637 hw->ops.release = snd_hdsp_hwdep_dummy_op;
4638
4639 return 0;
4640}
4641
Takashi Iwai55e957d2005-11-17 14:52:13 +01004642static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004643{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004644 struct snd_pcm *pcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004645 int err;
4646
4647 if ((err = snd_pcm_new(card, hdsp->card_name, 0, 1, 1, &pcm)) < 0)
4648 return err;
4649
4650 hdsp->pcm = pcm;
4651 pcm->private_data = hdsp;
4652 strcpy(pcm->name, hdsp->card_name);
4653
4654 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_hdsp_playback_ops);
4655 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_hdsp_capture_ops);
4656
4657 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
4658
4659 return 0;
4660}
4661
Takashi Iwai55e957d2005-11-17 14:52:13 +01004662static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004663{
4664 hdsp->control2_register |= HDSP_9652_ENABLE_MIXER;
4665 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
4666}
4667
Takashi Iwai55e957d2005-11-17 14:52:13 +01004668static int snd_hdsp_enable_io (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004669{
4670 int i;
4671
4672 if (hdsp_fifo_wait (hdsp, 0, 100)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004673 snd_printk(KERN_ERR "Hammerfall-DSP: enable_io fifo_wait failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004674 return -EIO;
4675 }
4676
4677 for (i = 0; i < hdsp->max_channels; ++i) {
4678 hdsp_write (hdsp, HDSP_inputEnable + (4 * i), 1);
4679 hdsp_write (hdsp, HDSP_outputEnable + (4 * i), 1);
4680 }
4681
4682 return 0;
4683}
4684
Takashi Iwai55e957d2005-11-17 14:52:13 +01004685static void snd_hdsp_initialize_channels(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004686{
4687 int status, aebi_channels, aebo_channels;
4688
4689 switch (hdsp->io_type) {
4690 case Digiface:
4691 hdsp->card_name = "RME Hammerfall DSP + Digiface";
4692 hdsp->ss_in_channels = hdsp->ss_out_channels = DIGIFACE_SS_CHANNELS;
4693 hdsp->ds_in_channels = hdsp->ds_out_channels = DIGIFACE_DS_CHANNELS;
4694 break;
4695
4696 case H9652:
4697 hdsp->card_name = "RME Hammerfall HDSP 9652";
4698 hdsp->ss_in_channels = hdsp->ss_out_channels = H9652_SS_CHANNELS;
4699 hdsp->ds_in_channels = hdsp->ds_out_channels = H9652_DS_CHANNELS;
4700 break;
4701
4702 case H9632:
4703 status = hdsp_read(hdsp, HDSP_statusRegister);
4704 /* HDSP_AEBx bits are low when AEB are connected */
4705 aebi_channels = (status & HDSP_AEBI) ? 0 : 4;
4706 aebo_channels = (status & HDSP_AEBO) ? 0 : 4;
4707 hdsp->card_name = "RME Hammerfall HDSP 9632";
4708 hdsp->ss_in_channels = H9632_SS_CHANNELS+aebi_channels;
4709 hdsp->ds_in_channels = H9632_DS_CHANNELS+aebi_channels;
4710 hdsp->qs_in_channels = H9632_QS_CHANNELS+aebi_channels;
4711 hdsp->ss_out_channels = H9632_SS_CHANNELS+aebo_channels;
4712 hdsp->ds_out_channels = H9632_DS_CHANNELS+aebo_channels;
4713 hdsp->qs_out_channels = H9632_QS_CHANNELS+aebo_channels;
4714 break;
4715
4716 case Multiface:
4717 hdsp->card_name = "RME Hammerfall DSP + Multiface";
4718 hdsp->ss_in_channels = hdsp->ss_out_channels = MULTIFACE_SS_CHANNELS;
4719 hdsp->ds_in_channels = hdsp->ds_out_channels = MULTIFACE_DS_CHANNELS;
4720 break;
4721
4722 default:
4723 /* should never get here */
4724 break;
4725 }
4726}
4727
Takashi Iwai55e957d2005-11-17 14:52:13 +01004728static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004729{
4730 snd_hdsp_flush_midi_input (hdsp, 0);
4731 snd_hdsp_flush_midi_input (hdsp, 1);
4732}
4733
Takashi Iwai55e957d2005-11-17 14:52:13 +01004734static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004735{
4736 int err;
4737
4738 if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004739 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating pcm interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004740 return err;
4741 }
4742
4743
4744 if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004745 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating first midi interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004746 return err;
4747 }
4748
4749 if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
4750 if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004751 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating second midi interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004752 return err;
4753 }
4754 }
4755
4756 if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004757 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating ctl interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004758 return err;
4759 }
4760
4761 snd_hdsp_proc_init(hdsp);
4762
4763 hdsp->system_sample_rate = -1;
4764 hdsp->playback_pid = -1;
4765 hdsp->capture_pid = -1;
4766 hdsp->capture_substream = NULL;
4767 hdsp->playback_substream = NULL;
4768
4769 if ((err = snd_hdsp_set_defaults(hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004770 snd_printk(KERN_ERR "Hammerfall-DSP: Error setting default values\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004771 return err;
4772 }
4773
4774 if (!(hdsp->state & HDSP_InitializationComplete)) {
Clemens Ladischb73c1c12005-09-02 08:49:21 +02004775 strcpy(card->shortname, "Hammerfall DSP");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004776 sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
4777 hdsp->port, hdsp->irq);
4778
4779 if ((err = snd_card_register(card)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004780 snd_printk(KERN_ERR "Hammerfall-DSP: error registering card\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004781 return err;
4782 }
4783 hdsp->state |= HDSP_InitializationComplete;
4784 }
4785
4786 return 0;
4787}
4788
4789#ifdef HDSP_FW_LOADER
4790/* load firmware via hotplug fw loader */
Takashi Iwai55e957d2005-11-17 14:52:13 +01004791static int __devinit hdsp_request_fw_loader(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004792{
4793 const char *fwfile;
4794 const struct firmware *fw;
4795 int err;
4796
4797 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
4798 return 0;
4799 if (hdsp->io_type == Undefined) {
4800 if ((err = hdsp_get_iobox_version(hdsp)) < 0)
4801 return err;
4802 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
4803 return 0;
4804 }
4805
4806 /* caution: max length of firmware filename is 30! */
4807 switch (hdsp->io_type) {
4808 case Multiface:
4809 if (hdsp->firmware_rev == 0xa)
4810 fwfile = "multiface_firmware.bin";
4811 else
4812 fwfile = "multiface_firmware_rev11.bin";
4813 break;
4814 case Digiface:
4815 if (hdsp->firmware_rev == 0xa)
4816 fwfile = "digiface_firmware.bin";
4817 else
4818 fwfile = "digiface_firmware_rev11.bin";
4819 break;
4820 default:
4821 snd_printk(KERN_ERR "Hammerfall-DSP: invalid io_type %d\n", hdsp->io_type);
4822 return -EINVAL;
4823 }
4824
4825 if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) {
4826 snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile);
4827 return -ENOENT;
4828 }
4829 if (fw->size < sizeof(hdsp->firmware_cache)) {
4830 snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n",
4831 (int)fw->size, (int)sizeof(hdsp->firmware_cache));
4832 release_firmware(fw);
4833 return -EINVAL;
4834 }
Thomas Charbonnel7679a032005-04-25 11:35:29 +02004835
Linus Torvalds1da177e2005-04-16 15:20:36 -07004836 memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache));
Thomas Charbonnel7679a032005-04-25 11:35:29 +02004837
Linus Torvalds1da177e2005-04-16 15:20:36 -07004838 release_firmware(fw);
4839
4840 hdsp->state |= HDSP_FirmwareCached;
4841
4842 if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
4843 return err;
4844
4845 if (!(hdsp->state & HDSP_InitializationComplete)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004846 if ((err = snd_hdsp_enable_io(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004847 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004848
4849 if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004850 snd_printk(KERN_ERR "Hammerfall-DSP: error creating hwdep device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004851 return err;
4852 }
4853 snd_hdsp_initialize_channels(hdsp);
4854 snd_hdsp_initialize_midi_flush(hdsp);
4855 if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004856 snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004857 return err;
4858 }
4859 }
4860 return 0;
4861}
4862#endif
4863
Takashi Iwai55e957d2005-11-17 14:52:13 +01004864static int __devinit snd_hdsp_create(struct snd_card *card,
4865 struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004866{
4867 struct pci_dev *pci = hdsp->pci;
4868 int err;
4869 int is_9652 = 0;
4870 int is_9632 = 0;
4871
4872 hdsp->irq = -1;
4873 hdsp->state = 0;
4874 hdsp->midi[0].rmidi = NULL;
4875 hdsp->midi[1].rmidi = NULL;
4876 hdsp->midi[0].input = NULL;
4877 hdsp->midi[1].input = NULL;
4878 hdsp->midi[0].output = NULL;
4879 hdsp->midi[1].output = NULL;
4880 hdsp->midi[0].pending = 0;
4881 hdsp->midi[1].pending = 0;
4882 spin_lock_init(&hdsp->midi[0].lock);
4883 spin_lock_init(&hdsp->midi[1].lock);
4884 hdsp->iobase = NULL;
4885 hdsp->control_register = 0;
4886 hdsp->control2_register = 0;
4887 hdsp->io_type = Undefined;
4888 hdsp->max_channels = 26;
4889
4890 hdsp->card = card;
4891
4892 spin_lock_init(&hdsp->lock);
4893
4894 tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp);
4895
4896 pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev);
4897 hdsp->firmware_rev &= 0xff;
4898
4899 /* From Martin Bjoernsen :
4900 "It is important that the card's latency timer register in
4901 the PCI configuration space is set to a value much larger
4902 than 0 by the computer's BIOS or the driver.
4903 The windows driver always sets this 8 bit register [...]
4904 to its maximum 255 to avoid problems with some computers."
4905 */
4906 pci_write_config_byte(hdsp->pci, PCI_LATENCY_TIMER, 0xFF);
4907
4908 strcpy(card->driver, "H-DSP");
4909 strcpy(card->mixername, "Xilinx FPGA");
4910
Takashi Iwaib0b98112005-10-20 18:29:58 +02004911 if (hdsp->firmware_rev < 0xa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004912 return -ENODEV;
Takashi Iwaib0b98112005-10-20 18:29:58 +02004913 else if (hdsp->firmware_rev < 0x64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004914 hdsp->card_name = "RME Hammerfall DSP";
Takashi Iwaib0b98112005-10-20 18:29:58 +02004915 else if (hdsp->firmware_rev < 0x96) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004916 hdsp->card_name = "RME HDSP 9652";
4917 is_9652 = 1;
4918 } else {
4919 hdsp->card_name = "RME HDSP 9632";
4920 hdsp->max_channels = 16;
4921 is_9632 = 1;
4922 }
4923
Takashi Iwaib0b98112005-10-20 18:29:58 +02004924 if ((err = pci_enable_device(pci)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004925 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004926
4927 pci_set_master(hdsp->pci);
4928
4929 if ((err = pci_request_regions(pci, "hdsp")) < 0)
4930 return err;
4931 hdsp->port = pci_resource_start(pci, 0);
4932 if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004933 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 -07004934 return -EBUSY;
4935 }
4936
Thomas Gleixner65ca68b2006-07-01 19:29:46 -07004937 if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_DISABLED|IRQF_SHARED, "hdsp", (void *)hdsp)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004938 snd_printk(KERN_ERR "Hammerfall-DSP: unable to use IRQ %d\n", pci->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004939 return -EBUSY;
4940 }
4941
4942 hdsp->irq = pci->irq;
Remy Bruno176546a2006-10-16 12:32:53 +02004943 hdsp->precise_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004944 hdsp->use_midi_tasklet = 1;
4945
Takashi Iwaib0b98112005-10-20 18:29:58 +02004946 if ((err = snd_hdsp_initialize_memory(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004947 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004948
4949 if (!is_9652 && !is_9632) {
4950 /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */
Takashi Iwaib0b98112005-10-20 18:29:58 +02004951 ssleep(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004952
4953 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
4954#ifdef HDSP_FW_LOADER
Takashi Iwaib0b98112005-10-20 18:29:58 +02004955 if ((err = hdsp_request_fw_loader(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004956 /* we don't fail as this can happen
4957 if userspace is not ready for
4958 firmware upload
4959 */
Takashi Iwaib0b98112005-10-20 18:29:58 +02004960 snd_printk(KERN_ERR "Hammerfall-DSP: couldn't get firmware from userspace. try using hdsploader\n");
4961 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004962 /* init is complete, we return */
4963 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004964#endif
4965 /* no iobox connected, we defer initialization */
Takashi Iwaib0b98112005-10-20 18:29:58 +02004966 snd_printk(KERN_INFO "Hammerfall-DSP: card initialization pending : waiting for firmware\n");
4967 if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004968 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004969 return 0;
4970 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004971 snd_printk(KERN_INFO "Hammerfall-DSP: Firmware already present, initializing card.\n");
4972 if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004973 hdsp->io_type = Multiface;
Takashi Iwaib0b98112005-10-20 18:29:58 +02004974 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07004975 hdsp->io_type = Digiface;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004976 }
4977 }
4978
Takashi Iwaib0b98112005-10-20 18:29:58 +02004979 if ((err = snd_hdsp_enable_io(hdsp)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004980 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004981
Takashi Iwaib0b98112005-10-20 18:29:58 +02004982 if (is_9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004983 hdsp->io_type = H9652;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004984
Takashi Iwaib0b98112005-10-20 18:29:58 +02004985 if (is_9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004986 hdsp->io_type = H9632;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004987
Takashi Iwaib0b98112005-10-20 18:29:58 +02004988 if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004989 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004990
4991 snd_hdsp_initialize_channels(hdsp);
4992 snd_hdsp_initialize_midi_flush(hdsp);
4993
4994 hdsp->state |= HDSP_FirmwareLoaded;
4995
Takashi Iwaib0b98112005-10-20 18:29:58 +02004996 if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004997 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004998
4999 return 0;
5000}
5001
Takashi Iwai55e957d2005-11-17 14:52:13 +01005002static int snd_hdsp_free(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005003{
5004 if (hdsp->port) {
5005 /* stop the audio, and cancel all interrupts */
5006 tasklet_kill(&hdsp->midi_tasklet);
5007 hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable);
5008 hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
5009 }
5010
5011 if (hdsp->irq >= 0)
5012 free_irq(hdsp->irq, (void *)hdsp);
5013
5014 snd_hdsp_free_buffers(hdsp);
5015
5016 if (hdsp->iobase)
5017 iounmap(hdsp->iobase);
5018
5019 if (hdsp->port)
5020 pci_release_regions(hdsp->pci);
5021
5022 pci_disable_device(hdsp->pci);
5023 return 0;
5024}
5025
Takashi Iwai55e957d2005-11-17 14:52:13 +01005026static void snd_hdsp_card_free(struct snd_card *card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005027{
Takashi Iwai55e957d2005-11-17 14:52:13 +01005028 struct hdsp *hdsp = (struct hdsp *) card->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005029
5030 if (hdsp)
5031 snd_hdsp_free(hdsp);
5032}
5033
5034static int __devinit snd_hdsp_probe(struct pci_dev *pci,
5035 const struct pci_device_id *pci_id)
5036{
5037 static int dev;
Takashi Iwai55e957d2005-11-17 14:52:13 +01005038 struct hdsp *hdsp;
5039 struct snd_card *card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040 int err;
5041
5042 if (dev >= SNDRV_CARDS)
5043 return -ENODEV;
5044 if (!enable[dev]) {
5045 dev++;
5046 return -ENOENT;
5047 }
5048
Takashi Iwai55e957d2005-11-17 14:52:13 +01005049 if (!(card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005050 return -ENOMEM;
5051
Takashi Iwai55e957d2005-11-17 14:52:13 +01005052 hdsp = (struct hdsp *) card->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005053 card->private_free = snd_hdsp_card_free;
5054 hdsp->dev = dev;
5055 hdsp->pci = pci;
5056 snd_card_set_dev(card, &pci->dev);
5057
5058 if ((err = snd_hdsp_create(card, hdsp)) < 0) {
5059 snd_card_free(card);
5060 return err;
5061 }
5062
5063 strcpy(card->shortname, "Hammerfall DSP");
5064 sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
5065 hdsp->port, hdsp->irq);
5066
5067 if ((err = snd_card_register(card)) < 0) {
5068 snd_card_free(card);
5069 return err;
5070 }
5071 pci_set_drvdata(pci, card);
5072 dev++;
5073 return 0;
5074}
5075
5076static void __devexit snd_hdsp_remove(struct pci_dev *pci)
5077{
5078 snd_card_free(pci_get_drvdata(pci));
5079 pci_set_drvdata(pci, NULL);
5080}
5081
5082static struct pci_driver driver = {
5083 .name = "RME Hammerfall DSP",
5084 .id_table = snd_hdsp_ids,
5085 .probe = snd_hdsp_probe,
5086 .remove = __devexit_p(snd_hdsp_remove),
5087};
5088
5089static int __init alsa_card_hdsp_init(void)
5090{
Takashi Iwai01d25d42005-04-11 16:58:24 +02005091 return pci_register_driver(&driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005092}
5093
5094static void __exit alsa_card_hdsp_exit(void)
5095{
5096 pci_unregister_driver(&driver);
5097}
5098
5099module_init(alsa_card_hdsp_init)
5100module_exit(alsa_card_hdsp_exit)