blob: c2bd4384316a8ad4ccf509dce009b62c241da335 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * ALSA driver for RME Hammerfall DSP audio interface(s)
3 *
4 * Copyright (c) 2002 Paul Davis
5 * Marcus Andersson
6 * Thomas Charbonnel
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/init.h>
25#include <linux/delay.h>
26#include <linux/interrupt.h>
27#include <linux/slab.h>
28#include <linux/pci.h>
29#include <linux/firmware.h>
30#include <linux/moduleparam.h>
31
32#include <sound/core.h>
33#include <sound/control.h>
34#include <sound/pcm.h>
35#include <sound/info.h>
36#include <sound/asoundef.h>
37#include <sound/rawmidi.h>
38#include <sound/hwdep.h>
39#include <sound/initval.h>
40#include <sound/hdsp.h>
41
42#include <asm/byteorder.h>
43#include <asm/current.h>
44#include <asm/io.h>
45
46static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
47static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
48static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
49
50module_param_array(index, int, NULL, 0444);
51MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface.");
52module_param_array(id, charp, NULL, 0444);
53MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface.");
54module_param_array(enable, bool, NULL, 0444);
55MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards.");
56MODULE_AUTHOR("Paul Davis <paul@linuxaudiosystems.com>, Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
57MODULE_DESCRIPTION("RME Hammerfall DSP");
58MODULE_LICENSE("GPL");
59MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
60 "{RME HDSP-9652},"
61 "{RME HDSP-9632}}");
Clemens Ladisch7e0af292007-05-03 17:59:54 +020062#ifdef HDSP_FW_LOADER
63MODULE_FIRMWARE("multiface_firmware.bin");
64MODULE_FIRMWARE("multiface_firmware_rev11.bin");
65MODULE_FIRMWARE("digiface_firmware.bin");
66MODULE_FIRMWARE("digiface_firmware_rev11.bin");
67#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070068
69#define HDSP_MAX_CHANNELS 26
70#define HDSP_MAX_DS_CHANNELS 14
71#define HDSP_MAX_QS_CHANNELS 8
72#define DIGIFACE_SS_CHANNELS 26
73#define DIGIFACE_DS_CHANNELS 14
74#define MULTIFACE_SS_CHANNELS 18
75#define MULTIFACE_DS_CHANNELS 14
76#define H9652_SS_CHANNELS 26
77#define H9652_DS_CHANNELS 14
78/* This does not include possible Analog Extension Boards
79 AEBs are detected at card initialization
80*/
81#define H9632_SS_CHANNELS 12
82#define H9632_DS_CHANNELS 8
83#define H9632_QS_CHANNELS 4
84
85/* Write registers. These are defined as byte-offsets from the iobase value.
86 */
87#define HDSP_resetPointer 0
Remy Brunod7923b22006-10-17 12:41:56 +020088#define HDSP_freqReg 0
Linus Torvalds1da177e2005-04-16 15:20:36 -070089#define HDSP_outputBufferAddress 32
90#define HDSP_inputBufferAddress 36
91#define HDSP_controlRegister 64
92#define HDSP_interruptConfirmation 96
93#define HDSP_outputEnable 128
94#define HDSP_control2Reg 256
95#define HDSP_midiDataOut0 352
96#define HDSP_midiDataOut1 356
97#define HDSP_fifoData 368
98#define HDSP_inputEnable 384
99
100/* Read registers. These are defined as byte-offsets from the iobase value
101 */
102
103#define HDSP_statusRegister 0
104#define HDSP_timecode 128
105#define HDSP_status2Register 192
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106#define HDSP_midiDataIn0 360
107#define HDSP_midiDataIn1 364
108#define HDSP_midiStatusOut0 384
109#define HDSP_midiStatusOut1 388
110#define HDSP_midiStatusIn0 392
111#define HDSP_midiStatusIn1 396
112#define HDSP_fifoStatus 400
113
114/* the meters are regular i/o-mapped registers, but offset
115 considerably from the rest. the peak registers are reset
116 when read; the least-significant 4 bits are full-scale counters;
117 the actual peak value is in the most-significant 24 bits.
118*/
119
120#define HDSP_playbackPeakLevel 4096 /* 26 * 32 bit values */
121#define HDSP_inputPeakLevel 4224 /* 26 * 32 bit values */
122#define HDSP_outputPeakLevel 4352 /* (26+2) * 32 bit values */
123#define HDSP_playbackRmsLevel 4612 /* 26 * 64 bit values */
124#define HDSP_inputRmsLevel 4868 /* 26 * 64 bit values */
125
126
127/* This is for H9652 cards
128 Peak values are read downward from the base
129 Rms values are read upward
130 There are rms values for the outputs too
131 26*3 values are read in ss mode
132 14*3 in ds mode, with no gap between values
133*/
134#define HDSP_9652_peakBase 7164
135#define HDSP_9652_rmsBase 4096
136
137/* c.f. the hdsp_9632_meters_t struct */
138#define HDSP_9632_metersBase 4096
139
140#define HDSP_IO_EXTENT 7168
141
142/* control2 register bits */
143
144#define HDSP_TMS 0x01
145#define HDSP_TCK 0x02
146#define HDSP_TDI 0x04
147#define HDSP_JTAG 0x08
148#define HDSP_PWDN 0x10
149#define HDSP_PROGRAM 0x020
150#define HDSP_CONFIG_MODE_0 0x040
151#define HDSP_CONFIG_MODE_1 0x080
152#define HDSP_VERSION_BIT 0x100
153#define HDSP_BIGENDIAN_MODE 0x200
154#define HDSP_RD_MULTIPLE 0x400
155#define HDSP_9652_ENABLE_MIXER 0x800
156#define HDSP_TDO 0x10000000
157
158#define HDSP_S_PROGRAM (HDSP_PROGRAM|HDSP_CONFIG_MODE_0)
159#define HDSP_S_LOAD (HDSP_PROGRAM|HDSP_CONFIG_MODE_1)
160
161/* Control Register bits */
162
163#define HDSP_Start (1<<0) /* start engine */
164#define HDSP_Latency0 (1<<1) /* buffer size = 2^n where n is defined by Latency{2,1,0} */
165#define HDSP_Latency1 (1<<2) /* [ see above ] */
166#define HDSP_Latency2 (1<<3) /* [ see above ] */
167#define HDSP_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */
168#define HDSP_AudioInterruptEnable (1<<5) /* what do you think ? */
169#define HDSP_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz/176.4kHz 1=48kHz/96kHz/192kHz */
170#define HDSP_Frequency1 (1<<7) /* 0=32kHz/64kHz/128kHz */
171#define HDSP_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
172#define HDSP_SPDIFProfessional (1<<9) /* 0=consumer, 1=professional */
173#define HDSP_SPDIFEmphasis (1<<10) /* 0=none, 1=on */
174#define HDSP_SPDIFNonAudio (1<<11) /* 0=off, 1=on */
175#define HDSP_SPDIFOpticalOut (1<<12) /* 1=use 1st ADAT connector for SPDIF, 0=do not */
176#define HDSP_SyncRef2 (1<<13)
177#define HDSP_SPDIFInputSelect0 (1<<14)
178#define HDSP_SPDIFInputSelect1 (1<<15)
179#define HDSP_SyncRef0 (1<<16)
180#define HDSP_SyncRef1 (1<<17)
181#define HDSP_AnalogExtensionBoard (1<<18) /* For H9632 cards */
182#define HDSP_XLRBreakoutCable (1<<20) /* For H9632 cards */
183#define HDSP_Midi0InterruptEnable (1<<22)
184#define HDSP_Midi1InterruptEnable (1<<23)
185#define HDSP_LineOut (1<<24)
186#define HDSP_ADGain0 (1<<25) /* From here : H9632 specific */
187#define HDSP_ADGain1 (1<<26)
188#define HDSP_DAGain0 (1<<27)
189#define HDSP_DAGain1 (1<<28)
190#define HDSP_PhoneGain0 (1<<29)
191#define HDSP_PhoneGain1 (1<<30)
192#define HDSP_QuadSpeed (1<<31)
193
194#define HDSP_ADGainMask (HDSP_ADGain0|HDSP_ADGain1)
195#define HDSP_ADGainMinus10dBV HDSP_ADGainMask
196#define HDSP_ADGainPlus4dBu (HDSP_ADGain0)
197#define HDSP_ADGainLowGain 0
198
199#define HDSP_DAGainMask (HDSP_DAGain0|HDSP_DAGain1)
200#define HDSP_DAGainHighGain HDSP_DAGainMask
201#define HDSP_DAGainPlus4dBu (HDSP_DAGain0)
202#define HDSP_DAGainMinus10dBV 0
203
204#define HDSP_PhoneGainMask (HDSP_PhoneGain0|HDSP_PhoneGain1)
205#define HDSP_PhoneGain0dB HDSP_PhoneGainMask
206#define HDSP_PhoneGainMinus6dB (HDSP_PhoneGain0)
207#define HDSP_PhoneGainMinus12dB 0
208
209#define HDSP_LatencyMask (HDSP_Latency0|HDSP_Latency1|HDSP_Latency2)
210#define HDSP_FrequencyMask (HDSP_Frequency0|HDSP_Frequency1|HDSP_DoubleSpeed|HDSP_QuadSpeed)
211
212#define HDSP_SPDIFInputMask (HDSP_SPDIFInputSelect0|HDSP_SPDIFInputSelect1)
213#define HDSP_SPDIFInputADAT1 0
214#define HDSP_SPDIFInputCoaxial (HDSP_SPDIFInputSelect0)
215#define HDSP_SPDIFInputCdrom (HDSP_SPDIFInputSelect1)
216#define HDSP_SPDIFInputAES (HDSP_SPDIFInputSelect0|HDSP_SPDIFInputSelect1)
217
218#define HDSP_SyncRefMask (HDSP_SyncRef0|HDSP_SyncRef1|HDSP_SyncRef2)
219#define HDSP_SyncRef_ADAT1 0
220#define HDSP_SyncRef_ADAT2 (HDSP_SyncRef0)
221#define HDSP_SyncRef_ADAT3 (HDSP_SyncRef1)
222#define HDSP_SyncRef_SPDIF (HDSP_SyncRef0|HDSP_SyncRef1)
223#define HDSP_SyncRef_WORD (HDSP_SyncRef2)
224#define HDSP_SyncRef_ADAT_SYNC (HDSP_SyncRef0|HDSP_SyncRef2)
225
226/* Sample Clock Sources */
227
228#define HDSP_CLOCK_SOURCE_AUTOSYNC 0
229#define HDSP_CLOCK_SOURCE_INTERNAL_32KHZ 1
230#define HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ 2
231#define HDSP_CLOCK_SOURCE_INTERNAL_48KHZ 3
232#define HDSP_CLOCK_SOURCE_INTERNAL_64KHZ 4
233#define HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ 5
234#define HDSP_CLOCK_SOURCE_INTERNAL_96KHZ 6
235#define HDSP_CLOCK_SOURCE_INTERNAL_128KHZ 7
236#define HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ 8
237#define HDSP_CLOCK_SOURCE_INTERNAL_192KHZ 9
238
239/* Preferred sync reference choices - used by "pref_sync_ref" control switch */
240
241#define HDSP_SYNC_FROM_WORD 0
242#define HDSP_SYNC_FROM_SPDIF 1
243#define HDSP_SYNC_FROM_ADAT1 2
244#define HDSP_SYNC_FROM_ADAT_SYNC 3
245#define HDSP_SYNC_FROM_ADAT2 4
246#define HDSP_SYNC_FROM_ADAT3 5
247
248/* SyncCheck status */
249
250#define HDSP_SYNC_CHECK_NO_LOCK 0
251#define HDSP_SYNC_CHECK_LOCK 1
252#define HDSP_SYNC_CHECK_SYNC 2
253
254/* AutoSync references - used by "autosync_ref" control switch */
255
256#define HDSP_AUTOSYNC_FROM_WORD 0
257#define HDSP_AUTOSYNC_FROM_ADAT_SYNC 1
258#define HDSP_AUTOSYNC_FROM_SPDIF 2
259#define HDSP_AUTOSYNC_FROM_NONE 3
260#define HDSP_AUTOSYNC_FROM_ADAT1 4
261#define HDSP_AUTOSYNC_FROM_ADAT2 5
262#define HDSP_AUTOSYNC_FROM_ADAT3 6
263
264/* Possible sources of S/PDIF input */
265
266#define HDSP_SPDIFIN_OPTICAL 0 /* optical (ADAT1) */
267#define HDSP_SPDIFIN_COAXIAL 1 /* coaxial (RCA) */
268#define HDSP_SPDIFIN_INTERNAL 2 /* internal (CDROM) */
269#define HDSP_SPDIFIN_AES 3 /* xlr for H9632 (AES)*/
270
271#define HDSP_Frequency32KHz HDSP_Frequency0
272#define HDSP_Frequency44_1KHz HDSP_Frequency1
273#define HDSP_Frequency48KHz (HDSP_Frequency1|HDSP_Frequency0)
274#define HDSP_Frequency64KHz (HDSP_DoubleSpeed|HDSP_Frequency0)
275#define HDSP_Frequency88_2KHz (HDSP_DoubleSpeed|HDSP_Frequency1)
276#define HDSP_Frequency96KHz (HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0)
277/* For H9632 cards */
278#define HDSP_Frequency128KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency0)
279#define HDSP_Frequency176_4KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1)
280#define HDSP_Frequency192KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0)
Julian Cablee4b60882007-03-19 11:44:40 +0100281/* RME says n = 104857600000000, but in the windows MADI driver, I see:
282 return 104857600000000 / rate; // 100 MHz
283 return 110100480000000 / rate; // 105 MHz
284*/
285#define DDS_NUMERATOR 104857600000000ULL; /* = 2^20 * 10^8 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
287#define hdsp_encode_latency(x) (((x)<<1) & HDSP_LatencyMask)
288#define hdsp_decode_latency(x) (((x) & HDSP_LatencyMask)>>1)
289
290#define hdsp_encode_spdif_in(x) (((x)&0x3)<<14)
291#define hdsp_decode_spdif_in(x) (((x)>>14)&0x3)
292
293/* Status Register bits */
294
295#define HDSP_audioIRQPending (1<<0)
296#define HDSP_Lock2 (1<<1) /* this is for Digiface and H9652 */
297#define HDSP_spdifFrequency3 HDSP_Lock2 /* this is for H9632 only */
298#define HDSP_Lock1 (1<<2)
299#define HDSP_Lock0 (1<<3)
300#define HDSP_SPDIFSync (1<<4)
301#define HDSP_TimecodeLock (1<<5)
302#define HDSP_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
303#define HDSP_Sync2 (1<<16)
304#define HDSP_Sync1 (1<<17)
305#define HDSP_Sync0 (1<<18)
306#define HDSP_DoubleSpeedStatus (1<<19)
307#define HDSP_ConfigError (1<<20)
308#define HDSP_DllError (1<<21)
309#define HDSP_spdifFrequency0 (1<<22)
310#define HDSP_spdifFrequency1 (1<<23)
311#define HDSP_spdifFrequency2 (1<<24)
312#define HDSP_SPDIFErrorFlag (1<<25)
313#define HDSP_BufferID (1<<26)
314#define HDSP_TimecodeSync (1<<27)
315#define HDSP_AEBO (1<<28) /* H9632 specific Analog Extension Boards */
316#define HDSP_AEBI (1<<29) /* 0 = present, 1 = absent */
317#define HDSP_midi0IRQPending (1<<30)
318#define HDSP_midi1IRQPending (1<<31)
319
320#define HDSP_spdifFrequencyMask (HDSP_spdifFrequency0|HDSP_spdifFrequency1|HDSP_spdifFrequency2)
321
322#define HDSP_spdifFrequency32KHz (HDSP_spdifFrequency0)
323#define HDSP_spdifFrequency44_1KHz (HDSP_spdifFrequency1)
324#define HDSP_spdifFrequency48KHz (HDSP_spdifFrequency0|HDSP_spdifFrequency1)
325
326#define HDSP_spdifFrequency64KHz (HDSP_spdifFrequency2)
327#define HDSP_spdifFrequency88_2KHz (HDSP_spdifFrequency0|HDSP_spdifFrequency2)
328#define HDSP_spdifFrequency96KHz (HDSP_spdifFrequency2|HDSP_spdifFrequency1)
329
330/* This is for H9632 cards */
331#define HDSP_spdifFrequency128KHz HDSP_spdifFrequencyMask
332#define HDSP_spdifFrequency176_4KHz HDSP_spdifFrequency3
333#define HDSP_spdifFrequency192KHz (HDSP_spdifFrequency3|HDSP_spdifFrequency0)
334
335/* Status2 Register bits */
336
337#define HDSP_version0 (1<<0)
338#define HDSP_version1 (1<<1)
339#define HDSP_version2 (1<<2)
340#define HDSP_wc_lock (1<<3)
341#define HDSP_wc_sync (1<<4)
342#define HDSP_inp_freq0 (1<<5)
343#define HDSP_inp_freq1 (1<<6)
344#define HDSP_inp_freq2 (1<<7)
345#define HDSP_SelSyncRef0 (1<<8)
346#define HDSP_SelSyncRef1 (1<<9)
347#define HDSP_SelSyncRef2 (1<<10)
348
349#define HDSP_wc_valid (HDSP_wc_lock|HDSP_wc_sync)
350
351#define HDSP_systemFrequencyMask (HDSP_inp_freq0|HDSP_inp_freq1|HDSP_inp_freq2)
352#define HDSP_systemFrequency32 (HDSP_inp_freq0)
353#define HDSP_systemFrequency44_1 (HDSP_inp_freq1)
354#define HDSP_systemFrequency48 (HDSP_inp_freq0|HDSP_inp_freq1)
355#define HDSP_systemFrequency64 (HDSP_inp_freq2)
356#define HDSP_systemFrequency88_2 (HDSP_inp_freq0|HDSP_inp_freq2)
357#define HDSP_systemFrequency96 (HDSP_inp_freq1|HDSP_inp_freq2)
358/* FIXME : more values for 9632 cards ? */
359
360#define HDSP_SelSyncRefMask (HDSP_SelSyncRef0|HDSP_SelSyncRef1|HDSP_SelSyncRef2)
361#define HDSP_SelSyncRef_ADAT1 0
362#define HDSP_SelSyncRef_ADAT2 (HDSP_SelSyncRef0)
363#define HDSP_SelSyncRef_ADAT3 (HDSP_SelSyncRef1)
364#define HDSP_SelSyncRef_SPDIF (HDSP_SelSyncRef0|HDSP_SelSyncRef1)
365#define HDSP_SelSyncRef_WORD (HDSP_SelSyncRef2)
366#define HDSP_SelSyncRef_ADAT_SYNC (HDSP_SelSyncRef0|HDSP_SelSyncRef2)
367
368/* Card state flags */
369
370#define HDSP_InitializationComplete (1<<0)
371#define HDSP_FirmwareLoaded (1<<1)
372#define HDSP_FirmwareCached (1<<2)
373
374/* FIFO wait times, defined in terms of 1/10ths of msecs */
375
376#define HDSP_LONG_WAIT 5000
377#define HDSP_SHORT_WAIT 30
378
379#define UNITY_GAIN 32768
380#define MINUS_INFINITY_GAIN 0
381
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382/* the size of a substream (1 mono data stream) */
383
384#define HDSP_CHANNEL_BUFFER_SAMPLES (16*1024)
385#define HDSP_CHANNEL_BUFFER_BYTES (4*HDSP_CHANNEL_BUFFER_SAMPLES)
386
387/* the size of the area we need to allocate for DMA transfers. the
388 size is the same regardless of the number of channels - the
389 Multiface still uses the same memory area.
390
391 Note that we allocate 1 more channel than is apparently needed
392 because the h/w seems to write 1 byte beyond the end of the last
393 page. Sigh.
394*/
395
396#define HDSP_DMA_AREA_BYTES ((HDSP_MAX_CHANNELS+1) * HDSP_CHANNEL_BUFFER_BYTES)
397#define HDSP_DMA_AREA_KILOBYTES (HDSP_DMA_AREA_BYTES/1024)
398
399/* use hotplug firmeare loader? */
400#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
Takashi Iwai140432f2006-05-22 14:31:57 +0200401#if !defined(HDSP_USE_HWDEP_LOADER) && !defined(CONFIG_SND_HDSP)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402#define HDSP_FW_LOADER
403#endif
404#endif
405
Takashi Iwai55e957d2005-11-17 14:52:13 +0100406struct hdsp_9632_meters {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 u32 input_peak[16];
408 u32 playback_peak[16];
409 u32 output_peak[16];
410 u32 xxx_peak[16];
411 u32 padding[64];
412 u32 input_rms_low[16];
413 u32 playback_rms_low[16];
414 u32 output_rms_low[16];
415 u32 xxx_rms_low[16];
416 u32 input_rms_high[16];
417 u32 playback_rms_high[16];
418 u32 output_rms_high[16];
419 u32 xxx_rms_high[16];
420};
421
Takashi Iwai55e957d2005-11-17 14:52:13 +0100422struct hdsp_midi {
423 struct hdsp *hdsp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 int id;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100425 struct snd_rawmidi *rmidi;
426 struct snd_rawmidi_substream *input;
427 struct snd_rawmidi_substream *output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 char istimer; /* timer in use */
429 struct timer_list timer;
430 spinlock_t lock;
431 int pending;
432};
433
Takashi Iwai55e957d2005-11-17 14:52:13 +0100434struct hdsp {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 spinlock_t lock;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100436 struct snd_pcm_substream *capture_substream;
437 struct snd_pcm_substream *playback_substream;
438 struct hdsp_midi midi[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 struct tasklet_struct midi_tasklet;
440 int use_midi_tasklet;
441 int precise_ptr;
442 u32 control_register; /* cached value */
443 u32 control2_register; /* cached value */
444 u32 creg_spdif;
445 u32 creg_spdif_stream;
Takashi Iwaie3ea4d82005-07-04 18:12:39 +0200446 int clock_source_locked;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 char *card_name; /* digiface/multiface */
Takashi Iwai55e957d2005-11-17 14:52:13 +0100448 enum HDSP_IO_Type io_type; /* ditto, but for code use */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 unsigned short firmware_rev;
450 unsigned short state; /* stores state bits */
451 u32 firmware_cache[24413]; /* this helps recover from accidental iobox power failure */
452 size_t period_bytes; /* guess what this is */
453 unsigned char max_channels;
454 unsigned char qs_in_channels; /* quad speed mode for H9632 */
455 unsigned char ds_in_channels;
456 unsigned char ss_in_channels; /* different for multiface/digiface */
457 unsigned char qs_out_channels;
458 unsigned char ds_out_channels;
459 unsigned char ss_out_channels;
460
461 struct snd_dma_buffer capture_dma_buf;
462 struct snd_dma_buffer playback_dma_buf;
463 unsigned char *capture_buffer; /* suitably aligned address */
464 unsigned char *playback_buffer; /* suitably aligned address */
465
466 pid_t capture_pid;
467 pid_t playback_pid;
468 int running;
469 int system_sample_rate;
470 char *channel_map;
471 int dev;
472 int irq;
473 unsigned long port;
474 void __iomem *iobase;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100475 struct snd_card *card;
476 struct snd_pcm *pcm;
477 struct snd_hwdep *hwdep;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 struct pci_dev *pci;
Takashi Iwai55e957d2005-11-17 14:52:13 +0100479 struct snd_kcontrol *spdif_ctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE];
Remy Brunod7923b22006-10-17 12:41:56 +0200481 unsigned int dds_value; /* last value written to freq register */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482};
483
484/* These tables map the ALSA channels 1..N to the channels that we
485 need to use in order to find the relevant channel buffer. RME
486 refer to this kind of mapping as between "the ADAT channel and
487 the DMA channel." We index it using the logical audio channel,
488 and the value is the DMA channel (i.e. channel buffer number)
489 where the data for that channel can be read/written from/to.
490*/
491
492static char channel_map_df_ss[HDSP_MAX_CHANNELS] = {
493 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
494 18, 19, 20, 21, 22, 23, 24, 25
495};
496
497static char channel_map_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */
498 /* Analog */
499 0, 1, 2, 3, 4, 5, 6, 7,
500 /* ADAT 2 */
501 16, 17, 18, 19, 20, 21, 22, 23,
502 /* SPDIF */
503 24, 25,
504 -1, -1, -1, -1, -1, -1, -1, -1
505};
506
507static char channel_map_ds[HDSP_MAX_CHANNELS] = {
508 /* ADAT channels are remapped */
509 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23,
510 /* channels 12 and 13 are S/PDIF */
511 24, 25,
512 /* others don't exist */
513 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
514};
515
516static char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = {
517 /* ADAT channels */
518 0, 1, 2, 3, 4, 5, 6, 7,
519 /* SPDIF */
520 8, 9,
521 /* Analog */
522 10, 11,
523 /* AO4S-192 and AI4S-192 extension boards */
524 12, 13, 14, 15,
525 /* others don't exist */
526 -1, -1, -1, -1, -1, -1, -1, -1,
527 -1, -1
528};
529
530static char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = {
531 /* ADAT */
532 1, 3, 5, 7,
533 /* SPDIF */
534 8, 9,
535 /* Analog */
536 10, 11,
537 /* AO4S-192 and AI4S-192 extension boards */
538 12, 13, 14, 15,
539 /* others don't exist */
540 -1, -1, -1, -1, -1, -1, -1, -1,
541 -1, -1, -1, -1, -1, -1
542};
543
544static char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = {
545 /* ADAT is disabled in this mode */
546 /* SPDIF */
547 8, 9,
548 /* Analog */
549 10, 11,
550 /* AO4S-192 and AI4S-192 extension boards */
551 12, 13, 14, 15,
552 /* others don't exist */
553 -1, -1, -1, -1, -1, -1, -1, -1,
554 -1, -1, -1, -1, -1, -1, -1, -1,
555 -1, -1
556};
557
558static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
559{
560 dmab->dev.type = SNDRV_DMA_TYPE_DEV;
561 dmab->dev.dev = snd_dma_pci_data(pci);
Takashi Iwaib6a96912005-05-30 18:27:03 +0200562 if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
563 if (dmab->bytes >= size)
564 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 }
Takashi Iwaib6a96912005-05-30 18:27:03 +0200566 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
567 size, dmab) < 0)
568 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 return 0;
570}
571
572static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
573{
Takashi Iwaib6a96912005-05-30 18:27:03 +0200574 if (dmab->area) {
575 dmab->dev.dev = NULL; /* make it anonymous */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
Takashi Iwaib6a96912005-05-30 18:27:03 +0200577 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578}
579
580
Takashi Iwaif40b6892006-07-05 16:51:05 +0200581static struct pci_device_id snd_hdsp_ids[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 {
583 .vendor = PCI_VENDOR_ID_XILINX,
584 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP,
585 .subvendor = PCI_ANY_ID,
586 .subdevice = PCI_ANY_ID,
587 }, /* RME Hammerfall-DSP */
588 { 0, },
589};
590
591MODULE_DEVICE_TABLE(pci, snd_hdsp_ids);
592
593/* prototypes */
Takashi Iwai55e957d2005-11-17 14:52:13 +0100594static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp);
595static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp);
596static int snd_hdsp_enable_io (struct hdsp *hdsp);
597static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp);
598static void snd_hdsp_initialize_channels (struct hdsp *hdsp);
599static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout);
600static int hdsp_autosync_ref(struct hdsp *hdsp);
601static int snd_hdsp_set_defaults(struct hdsp *hdsp);
602static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603
Takashi Iwai55e957d2005-11-17 14:52:13 +0100604static int hdsp_playback_to_output_key (struct hdsp *hdsp, int in, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605{
Remy Brunoa3a68c82007-08-31 12:33:54 +0200606 switch (hdsp->io_type) {
607 case Multiface:
608 case Digiface:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 default:
Andreas Degert192b8e32008-01-16 15:59:48 +0100610 if (hdsp->firmware_rev == 0xa)
611 return (64 * out) + (32 + (in));
612 else
613 return (52 * out) + (26 + (in));
Remy Brunoa3a68c82007-08-31 12:33:54 +0200614 case H9632:
615 return (32 * out) + (16 + (in));
616 case H9652:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 return (52 * out) + (26 + (in));
618 }
619}
620
Takashi Iwai55e957d2005-11-17 14:52:13 +0100621static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622{
Remy Brunoa3a68c82007-08-31 12:33:54 +0200623 switch (hdsp->io_type) {
624 case Multiface:
625 case Digiface:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 default:
Andreas Degert192b8e32008-01-16 15:59:48 +0100627 if (hdsp->firmware_rev == 0xa)
628 return (64 * out) + in;
629 else
630 return (52 * out) + in;
Remy Brunoa3a68c82007-08-31 12:33:54 +0200631 case H9632:
632 return (32 * out) + in;
633 case H9652:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 return (52 * out) + in;
635 }
636}
637
Takashi Iwai55e957d2005-11-17 14:52:13 +0100638static void hdsp_write(struct hdsp *hdsp, int reg, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639{
640 writel(val, hdsp->iobase + reg);
641}
642
Takashi Iwai55e957d2005-11-17 14:52:13 +0100643static unsigned int hdsp_read(struct hdsp *hdsp, int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644{
645 return readl (hdsp->iobase + reg);
646}
647
Takashi Iwai55e957d2005-11-17 14:52:13 +0100648static int hdsp_check_for_iobox (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649{
650
651 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
652 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_ConfigError) {
653 snd_printk ("Hammerfall-DSP: no Digiface or Multiface connected!\n");
654 hdsp->state &= ~HDSP_FirmwareLoaded;
655 return -EIO;
656 }
657 return 0;
658
659}
660
Takashi Iwai55e957d2005-11-17 14:52:13 +0100661static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662
663 int i;
664 unsigned long flags;
665
666 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
667
668 snd_printk ("Hammerfall-DSP: loading firmware\n");
669
670 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM);
671 hdsp_write (hdsp, HDSP_fifoData, 0);
672
673 if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
674 snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n");
675 return -EIO;
676 }
677
678 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
679
680 for (i = 0; i < 24413; ++i) {
681 hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]);
682 if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) {
683 snd_printk ("Hammerfall-DSP: timeout during firmware loading\n");
684 return -EIO;
685 }
686 }
687
Takashi Iwaib0b98112005-10-20 18:29:58 +0200688 ssleep(3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689
690 if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
691 snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n");
692 return -EIO;
693 }
694
695#ifdef SNDRV_BIG_ENDIAN
696 hdsp->control2_register = HDSP_BIGENDIAN_MODE;
697#else
698 hdsp->control2_register = 0;
699#endif
700 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
701 snd_printk ("Hammerfall-DSP: finished firmware loading\n");
702
703 }
704 if (hdsp->state & HDSP_InitializationComplete) {
Takashi Iwaib0b98112005-10-20 18:29:58 +0200705 snd_printk(KERN_INFO "Hammerfall-DSP: firmware loaded from cache, restoring defaults\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 spin_lock_irqsave(&hdsp->lock, flags);
707 snd_hdsp_set_defaults(hdsp);
708 spin_unlock_irqrestore(&hdsp->lock, flags);
709 }
710
711 hdsp->state |= HDSP_FirmwareLoaded;
712
713 return 0;
714}
715
Takashi Iwai55e957d2005-11-17 14:52:13 +0100716static int hdsp_get_iobox_version (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717{
718 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
719
720 hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM);
721 hdsp_write (hdsp, HDSP_fifoData, 0);
Takashi Iwaib0b98112005-10-20 18:29:58 +0200722 if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
725 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
726 hdsp_write (hdsp, HDSP_fifoData, 0);
727
728 if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT)) {
729 hdsp->io_type = Multiface;
730 hdsp_write (hdsp, HDSP_control2Reg, HDSP_VERSION_BIT);
731 hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_LOAD);
732 hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT);
733 } else {
734 hdsp->io_type = Digiface;
735 }
736 } else {
737 /* firmware was already loaded, get iobox type */
Takashi Iwaib0b98112005-10-20 18:29:58 +0200738 if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 hdsp->io_type = Multiface;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200740 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 hdsp->io_type = Digiface;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 }
743 return 0;
744}
745
746
Takashi Iwai311e70a2006-09-06 12:13:37 +0200747#ifdef HDSP_FW_LOADER
748static int __devinit hdsp_request_fw_loader(struct hdsp *hdsp);
749#endif
750
751static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752{
Takashi Iwai311e70a2006-09-06 12:13:37 +0200753 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
754 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 hdsp->state &= ~HDSP_FirmwareLoaded;
Takashi Iwai311e70a2006-09-06 12:13:37 +0200757 if (! load_on_demand)
Takashi Iwaib0b98112005-10-20 18:29:58 +0200758 return -EIO;
Takashi Iwai311e70a2006-09-06 12:13:37 +0200759 snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +0200760 /* try to load firmware */
Takashi Iwai311e70a2006-09-06 12:13:37 +0200761 if (! (hdsp->state & HDSP_FirmwareCached)) {
762#ifdef HDSP_FW_LOADER
763 if (! hdsp_request_fw_loader(hdsp))
764 return 0;
765#endif
766 snd_printk(KERN_ERR
767 "Hammerfall-DSP: No firmware loaded nor "
768 "cached, please upload firmware.\n");
769 return -EIO;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200770 }
Takashi Iwai311e70a2006-09-06 12:13:37 +0200771 if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
772 snd_printk(KERN_ERR
773 "Hammerfall-DSP: Firmware loading from "
774 "cache failed, please upload manually.\n");
775 return -EIO;
776 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 }
778 return 0;
779}
780
781
Takashi Iwai55e957d2005-11-17 14:52:13 +0100782static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783{
784 int i;
785
786 /* the fifoStatus registers reports on how many words
787 are available in the command FIFO.
788 */
789
790 for (i = 0; i < timeout; i++) {
791
792 if ((int)(hdsp_read (hdsp, HDSP_fifoStatus) & 0xff) <= count)
793 return 0;
794
795 /* not very friendly, but we only do this during a firmware
796 load and changing the mixer, so we just put up with it.
797 */
798
799 udelay (100);
800 }
801
802 snd_printk ("Hammerfall-DSP: wait for FIFO status <= %d failed after %d iterations\n",
803 count, timeout);
804 return -1;
805}
806
Takashi Iwai55e957d2005-11-17 14:52:13 +0100807static int hdsp_read_gain (struct hdsp *hdsp, unsigned int addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808{
Takashi Iwaib0b98112005-10-20 18:29:58 +0200809 if (addr >= HDSP_MATRIX_MIXER_SIZE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +0200811
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 return hdsp->mixer_matrix[addr];
813}
814
Takashi Iwai55e957d2005-11-17 14:52:13 +0100815static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816{
817 unsigned int ad;
818
819 if (addr >= HDSP_MATRIX_MIXER_SIZE)
820 return -1;
821
822 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) {
823
824 /* from martin bjornsen:
825
826 "You can only write dwords to the
827 mixer memory which contain two
828 mixer values in the low and high
829 word. So if you want to change
830 value 0 you have to read value 1
831 from the cache and write both to
832 the first dword in the mixer
833 memory."
834 */
835
Takashi Iwaib0b98112005-10-20 18:29:58 +0200836 if (hdsp->io_type == H9632 && addr >= 512)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838
Takashi Iwaib0b98112005-10-20 18:29:58 +0200839 if (hdsp->io_type == H9652 && addr >= 1352)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
842 hdsp->mixer_matrix[addr] = data;
843
844
845 /* `addr' addresses a 16-bit wide address, but
846 the address space accessed via hdsp_write
847 uses byte offsets. put another way, addr
848 varies from 0 to 1351, but to access the
849 corresponding memory location, we need
850 to access 0 to 2703 ...
851 */
852 ad = addr/2;
853
854 hdsp_write (hdsp, 4096 + (ad*4),
855 (hdsp->mixer_matrix[(addr&0x7fe)+1] << 16) +
856 hdsp->mixer_matrix[addr&0x7fe]);
857
858 return 0;
859
860 } else {
861
862 ad = (addr << 16) + data;
863
Takashi Iwaib0b98112005-10-20 18:29:58 +0200864 if (hdsp_fifo_wait(hdsp, 127, HDSP_LONG_WAIT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866
867 hdsp_write (hdsp, HDSP_fifoData, ad);
868 hdsp->mixer_matrix[addr] = data;
869
870 }
871
872 return 0;
873}
874
Takashi Iwai55e957d2005-11-17 14:52:13 +0100875static int snd_hdsp_use_is_exclusive(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876{
877 unsigned long flags;
878 int ret = 1;
879
880 spin_lock_irqsave(&hdsp->lock, flags);
881 if ((hdsp->playback_pid != hdsp->capture_pid) &&
Takashi Iwaib0b98112005-10-20 18:29:58 +0200882 (hdsp->playback_pid >= 0) && (hdsp->capture_pid >= 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 spin_unlock_irqrestore(&hdsp->lock, flags);
885 return ret;
886}
887
Takashi Iwai55e957d2005-11-17 14:52:13 +0100888static int hdsp_external_sample_rate (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889{
890 unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
891 unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
892
893 switch (rate_bits) {
894 case HDSP_systemFrequency32: return 32000;
895 case HDSP_systemFrequency44_1: return 44100;
896 case HDSP_systemFrequency48: return 48000;
897 case HDSP_systemFrequency64: return 64000;
898 case HDSP_systemFrequency88_2: return 88200;
899 case HDSP_systemFrequency96: return 96000;
900 default:
901 return 0;
902 }
903}
904
Takashi Iwai55e957d2005-11-17 14:52:13 +0100905static int hdsp_spdif_sample_rate(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906{
907 unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);
908 unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);
909
Takashi Iwaib0b98112005-10-20 18:29:58 +0200910 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912
913 switch (rate_bits) {
914 case HDSP_spdifFrequency32KHz: return 32000;
915 case HDSP_spdifFrequency44_1KHz: return 44100;
916 case HDSP_spdifFrequency48KHz: return 48000;
917 case HDSP_spdifFrequency64KHz: return 64000;
918 case HDSP_spdifFrequency88_2KHz: return 88200;
919 case HDSP_spdifFrequency96KHz: return 96000;
920 case HDSP_spdifFrequency128KHz:
921 if (hdsp->io_type == H9632) return 128000;
922 break;
923 case HDSP_spdifFrequency176_4KHz:
924 if (hdsp->io_type == H9632) return 176400;
925 break;
926 case HDSP_spdifFrequency192KHz:
927 if (hdsp->io_type == H9632) return 192000;
928 break;
929 default:
930 break;
931 }
932 snd_printk ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status);
933 return 0;
934}
935
Takashi Iwai55e957d2005-11-17 14:52:13 +0100936static void hdsp_compute_period_size(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937{
938 hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));
939}
940
Takashi Iwai55e957d2005-11-17 14:52:13 +0100941static snd_pcm_uframes_t hdsp_hw_pointer(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942{
943 int position;
944
945 position = hdsp_read(hdsp, HDSP_statusRegister);
946
Takashi Iwaib0b98112005-10-20 18:29:58 +0200947 if (!hdsp->precise_ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 return (position & HDSP_BufferID) ? (hdsp->period_bytes / 4) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949
950 position &= HDSP_BufferPositionMask;
951 position /= 4;
952 position &= (hdsp->period_bytes/2) - 1;
953 return position;
954}
955
Takashi Iwai55e957d2005-11-17 14:52:13 +0100956static void hdsp_reset_hw_pointer(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957{
958 hdsp_write (hdsp, HDSP_resetPointer, 0);
Remy Brunod7923b22006-10-17 12:41:56 +0200959 if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152)
960 /* HDSP_resetPointer = HDSP_freqReg, which is strange and
961 * requires (?) to write again DDS value after a reset pointer
962 * (at least, it works like this) */
963 hdsp_write (hdsp, HDSP_freqReg, hdsp->dds_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964}
965
Takashi Iwai55e957d2005-11-17 14:52:13 +0100966static void hdsp_start_audio(struct hdsp *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967{
968 s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start);
969 hdsp_write(s, HDSP_controlRegister, s->control_register);
970}
971
Takashi Iwai55e957d2005-11-17 14:52:13 +0100972static void hdsp_stop_audio(struct hdsp *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973{
974 s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable);
975 hdsp_write(s, HDSP_controlRegister, s->control_register);
976}
977
Takashi Iwai55e957d2005-11-17 14:52:13 +0100978static void hdsp_silence_playback(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979{
980 memset(hdsp->playback_buffer, 0, HDSP_DMA_AREA_BYTES);
981}
982
Takashi Iwai55e957d2005-11-17 14:52:13 +0100983static int hdsp_set_interrupt_interval(struct hdsp *s, unsigned int frames)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984{
985 int n;
986
987 spin_lock_irq(&s->lock);
988
989 frames >>= 7;
990 n = 0;
991 while (frames) {
992 n++;
993 frames >>= 1;
994 }
995
996 s->control_register &= ~HDSP_LatencyMask;
997 s->control_register |= hdsp_encode_latency(n);
998
999 hdsp_write(s, HDSP_controlRegister, s->control_register);
1000
1001 hdsp_compute_period_size(s);
1002
1003 spin_unlock_irq(&s->lock);
1004
1005 return 0;
1006}
1007
Remy Brunod7923b22006-10-17 12:41:56 +02001008static void hdsp_set_dds_value(struct hdsp *hdsp, int rate)
1009{
1010 u64 n;
1011 u32 r;
1012
1013 if (rate >= 112000)
1014 rate /= 4;
1015 else if (rate >= 56000)
1016 rate /= 2;
1017
Julian Cablee4b60882007-03-19 11:44:40 +01001018 n = DDS_NUMERATOR;
Remy Brunod7923b22006-10-17 12:41:56 +02001019 div64_32(&n, rate, &r);
1020 /* n should be less than 2^32 for being written to FREQ register */
1021 snd_assert((n >> 32) == 0);
1022 /* HDSP_freqReg and HDSP_resetPointer are the same, so keep the DDS
1023 value to write it after a reset */
1024 hdsp->dds_value = n;
1025 hdsp_write(hdsp, HDSP_freqReg, hdsp->dds_value);
1026}
1027
Takashi Iwai55e957d2005-11-17 14:52:13 +01001028static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029{
1030 int reject_if_open = 0;
1031 int current_rate;
1032 int rate_bits;
1033
1034 /* ASSUMPTION: hdsp->lock is either held, or
1035 there is no need for it (e.g. during module
1036 initialization).
1037 */
1038
1039 if (!(hdsp->control_register & HDSP_ClockModeMaster)) {
1040 if (called_internally) {
1041 /* request from ctl or card initialization */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001042 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 -07001043 return -1;
1044 } else {
1045 /* hw_param request while in AutoSync mode */
1046 int external_freq = hdsp_external_sample_rate(hdsp);
1047 int spdif_freq = hdsp_spdif_sample_rate(hdsp);
1048
Takashi Iwaib0b98112005-10-20 18:29:58 +02001049 if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1))
1050 snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in double speed mode\n");
1051 else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1))
1052 snd_printk(KERN_INFO "Hammerfall-DSP: Detected ADAT in quad speed mode\n");
1053 else if (rate != external_freq) {
1054 snd_printk(KERN_INFO "Hammerfall-DSP: No AutoSync source for requested rate\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 return -1;
1056 }
1057 }
1058 }
1059
1060 current_rate = hdsp->system_sample_rate;
1061
1062 /* Changing from a "single speed" to a "double speed" rate is
1063 not allowed if any substreams are open. This is because
1064 such a change causes a shift in the location of
1065 the DMA buffers and a reduction in the number of available
1066 buffers.
1067
1068 Note that a similar but essentially insoluble problem
1069 exists for externally-driven rate changes. All we can do
1070 is to flag rate changes in the read/write routines. */
1071
Takashi Iwaib0b98112005-10-20 18:29:58 +02001072 if (rate > 96000 && hdsp->io_type != H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074
1075 switch (rate) {
1076 case 32000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001077 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 rate_bits = HDSP_Frequency32KHz;
1080 break;
1081 case 44100:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001082 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 rate_bits = HDSP_Frequency44_1KHz;
1085 break;
1086 case 48000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001087 if (current_rate > 48000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 rate_bits = HDSP_Frequency48KHz;
1090 break;
1091 case 64000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001092 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 rate_bits = HDSP_Frequency64KHz;
1095 break;
1096 case 88200:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001097 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 rate_bits = HDSP_Frequency88_2KHz;
1100 break;
1101 case 96000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001102 if (current_rate <= 48000 || current_rate > 96000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 rate_bits = HDSP_Frequency96KHz;
1105 break;
1106 case 128000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001107 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 rate_bits = HDSP_Frequency128KHz;
1110 break;
1111 case 176400:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001112 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 rate_bits = HDSP_Frequency176_4KHz;
1115 break;
1116 case 192000:
Takashi Iwaib0b98112005-10-20 18:29:58 +02001117 if (current_rate < 128000)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 reject_if_open = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 rate_bits = HDSP_Frequency192KHz;
1120 break;
1121 default:
1122 return -EINVAL;
1123 }
1124
1125 if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) {
1126 snd_printk ("Hammerfall-DSP: cannot change speed mode (capture PID = %d, playback PID = %d)\n",
1127 hdsp->capture_pid,
1128 hdsp->playback_pid);
1129 return -EBUSY;
1130 }
1131
1132 hdsp->control_register &= ~HDSP_FrequencyMask;
1133 hdsp->control_register |= rate_bits;
1134 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1135
Remy Brunod7923b22006-10-17 12:41:56 +02001136 /* For HDSP9632 rev 152, need to set DDS value in FREQ register */
1137 if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152)
1138 hdsp_set_dds_value(hdsp, rate);
1139
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 if (rate >= 128000) {
1141 hdsp->channel_map = channel_map_H9632_qs;
1142 } else if (rate > 48000) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001143 if (hdsp->io_type == H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 hdsp->channel_map = channel_map_H9632_ds;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001145 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 hdsp->channel_map = channel_map_ds;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 } else {
1148 switch (hdsp->io_type) {
1149 case Multiface:
1150 hdsp->channel_map = channel_map_mf_ss;
1151 break;
1152 case Digiface:
1153 case H9652:
1154 hdsp->channel_map = channel_map_df_ss;
1155 break;
1156 case H9632:
1157 hdsp->channel_map = channel_map_H9632_ss;
1158 break;
1159 default:
1160 /* should never happen */
1161 break;
1162 }
1163 }
1164
1165 hdsp->system_sample_rate = rate;
1166
1167 return 0;
1168}
1169
1170/*----------------------------------------------------------------------------
1171 MIDI
1172 ----------------------------------------------------------------------------*/
1173
Takashi Iwai55e957d2005-11-17 14:52:13 +01001174static unsigned char snd_hdsp_midi_read_byte (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175{
1176 /* the hardware already does the relevant bit-mask with 0xff */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001177 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 return hdsp_read(hdsp, HDSP_midiDataIn1);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001179 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 return hdsp_read(hdsp, HDSP_midiDataIn0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181}
1182
Takashi Iwai55e957d2005-11-17 14:52:13 +01001183static void snd_hdsp_midi_write_byte (struct hdsp *hdsp, int id, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184{
1185 /* the hardware already does the relevant bit-mask with 0xff */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001186 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 hdsp_write(hdsp, HDSP_midiDataOut1, val);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001188 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 hdsp_write(hdsp, HDSP_midiDataOut0, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190}
1191
Takashi Iwai55e957d2005-11-17 14:52:13 +01001192static int snd_hdsp_midi_input_available (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001194 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 return (hdsp_read(hdsp, HDSP_midiStatusIn1) & 0xff);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001196 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 return (hdsp_read(hdsp, HDSP_midiStatusIn0) & 0xff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198}
1199
Takashi Iwai55e957d2005-11-17 14:52:13 +01001200static int snd_hdsp_midi_output_possible (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201{
1202 int fifo_bytes_used;
1203
Takashi Iwaib0b98112005-10-20 18:29:58 +02001204 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut1) & 0xff;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001206 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 fifo_bytes_used = hdsp_read(hdsp, HDSP_midiStatusOut0) & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208
Takashi Iwaib0b98112005-10-20 18:29:58 +02001209 if (fifo_bytes_used < 128)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 return 128 - fifo_bytes_used;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001211 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213}
1214
Takashi Iwai55e957d2005-11-17 14:52:13 +01001215static void snd_hdsp_flush_midi_input (struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001217 while (snd_hdsp_midi_input_available (hdsp, id))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 snd_hdsp_midi_read_byte (hdsp, id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219}
1220
Takashi Iwai55e957d2005-11-17 14:52:13 +01001221static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222{
1223 unsigned long flags;
1224 int n_pending;
1225 int to_write;
1226 int i;
1227 unsigned char buf[128];
1228
1229 /* Output is not interrupt driven */
1230
1231 spin_lock_irqsave (&hmidi->lock, flags);
1232 if (hmidi->output) {
1233 if (!snd_rawmidi_transmit_empty (hmidi->output)) {
1234 if ((n_pending = snd_hdsp_midi_output_possible (hmidi->hdsp, hmidi->id)) > 0) {
1235 if (n_pending > (int)sizeof (buf))
1236 n_pending = sizeof (buf);
1237
1238 if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {
1239 for (i = 0; i < to_write; ++i)
1240 snd_hdsp_midi_write_byte (hmidi->hdsp, hmidi->id, buf[i]);
1241 }
1242 }
1243 }
1244 }
1245 spin_unlock_irqrestore (&hmidi->lock, flags);
1246 return 0;
1247}
1248
Takashi Iwai55e957d2005-11-17 14:52:13 +01001249static int snd_hdsp_midi_input_read (struct hdsp_midi *hmidi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250{
1251 unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
1252 unsigned long flags;
1253 int n_pending;
1254 int i;
1255
1256 spin_lock_irqsave (&hmidi->lock, flags);
1257 if ((n_pending = snd_hdsp_midi_input_available (hmidi->hdsp, hmidi->id)) > 0) {
1258 if (hmidi->input) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001259 if (n_pending > (int)sizeof (buf))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 n_pending = sizeof (buf);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001261 for (i = 0; i < n_pending; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 buf[i] = snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001263 if (n_pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 snd_rawmidi_receive (hmidi->input, buf, n_pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 } else {
1266 /* flush the MIDI input FIFO */
Takashi Iwaib0b98112005-10-20 18:29:58 +02001267 while (--n_pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 snd_hdsp_midi_read_byte (hmidi->hdsp, hmidi->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269 }
1270 }
1271 hmidi->pending = 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001272 if (hmidi->id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 hmidi->hdsp->control_register |= HDSP_Midi1InterruptEnable;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001274 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 hmidi->hdsp->control_register |= HDSP_Midi0InterruptEnable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 hdsp_write(hmidi->hdsp, HDSP_controlRegister, hmidi->hdsp->control_register);
1277 spin_unlock_irqrestore (&hmidi->lock, flags);
1278 return snd_hdsp_midi_output_write (hmidi);
1279}
1280
Takashi Iwai55e957d2005-11-17 14:52:13 +01001281static void snd_hdsp_midi_input_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 *hdsp;
1284 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 unsigned long flags;
1286 u32 ie;
1287
Takashi Iwai55e957d2005-11-17 14:52:13 +01001288 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 hdsp = hmidi->hdsp;
1290 ie = hmidi->id ? HDSP_Midi1InterruptEnable : HDSP_Midi0InterruptEnable;
1291 spin_lock_irqsave (&hdsp->lock, flags);
1292 if (up) {
1293 if (!(hdsp->control_register & ie)) {
1294 snd_hdsp_flush_midi_input (hdsp, hmidi->id);
1295 hdsp->control_register |= ie;
1296 }
1297 } else {
1298 hdsp->control_register &= ~ie;
1299 tasklet_kill(&hdsp->midi_tasklet);
1300 }
1301
1302 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1303 spin_unlock_irqrestore (&hdsp->lock, flags);
1304}
1305
1306static void snd_hdsp_midi_output_timer(unsigned long data)
1307{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001308 struct hdsp_midi *hmidi = (struct hdsp_midi *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 unsigned long flags;
1310
1311 snd_hdsp_midi_output_write(hmidi);
1312 spin_lock_irqsave (&hmidi->lock, flags);
1313
1314 /* this does not bump hmidi->istimer, because the
1315 kernel automatically removed the timer when it
1316 expired, and we are now adding it back, thus
1317 leaving istimer wherever it was set before.
1318 */
1319
1320 if (hmidi->istimer) {
1321 hmidi->timer.expires = 1 + jiffies;
1322 add_timer(&hmidi->timer);
1323 }
1324
1325 spin_unlock_irqrestore (&hmidi->lock, flags);
1326}
1327
Takashi Iwai55e957d2005-11-17 14:52:13 +01001328static void snd_hdsp_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001330 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 unsigned long flags;
1332
Takashi Iwai55e957d2005-11-17 14:52:13 +01001333 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 spin_lock_irqsave (&hmidi->lock, flags);
1335 if (up) {
1336 if (!hmidi->istimer) {
1337 init_timer(&hmidi->timer);
1338 hmidi->timer.function = snd_hdsp_midi_output_timer;
1339 hmidi->timer.data = (unsigned long) hmidi;
1340 hmidi->timer.expires = 1 + jiffies;
1341 add_timer(&hmidi->timer);
1342 hmidi->istimer++;
1343 }
1344 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02001345 if (hmidi->istimer && --hmidi->istimer <= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 del_timer (&hmidi->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 }
1348 spin_unlock_irqrestore (&hmidi->lock, flags);
1349 if (up)
1350 snd_hdsp_midi_output_write(hmidi);
1351}
1352
Takashi Iwai55e957d2005-11-17 14:52:13 +01001353static int snd_hdsp_midi_input_open(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001355 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Takashi Iwai55e957d2005-11-17 14:52:13 +01001357 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 spin_lock_irq (&hmidi->lock);
1359 snd_hdsp_flush_midi_input (hmidi->hdsp, hmidi->id);
1360 hmidi->input = substream;
1361 spin_unlock_irq (&hmidi->lock);
1362
1363 return 0;
1364}
1365
Takashi Iwai55e957d2005-11-17 14:52:13 +01001366static int snd_hdsp_midi_output_open(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001368 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369
Takashi Iwai55e957d2005-11-17 14:52:13 +01001370 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 spin_lock_irq (&hmidi->lock);
1372 hmidi->output = substream;
1373 spin_unlock_irq (&hmidi->lock);
1374
1375 return 0;
1376}
1377
Takashi Iwai55e957d2005-11-17 14:52:13 +01001378static int snd_hdsp_midi_input_close(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001380 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381
1382 snd_hdsp_midi_input_trigger (substream, 0);
1383
Takashi Iwai55e957d2005-11-17 14:52:13 +01001384 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 spin_lock_irq (&hmidi->lock);
1386 hmidi->input = NULL;
1387 spin_unlock_irq (&hmidi->lock);
1388
1389 return 0;
1390}
1391
Takashi Iwai55e957d2005-11-17 14:52:13 +01001392static int snd_hdsp_midi_output_close(struct snd_rawmidi_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001394 struct hdsp_midi *hmidi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395
1396 snd_hdsp_midi_output_trigger (substream, 0);
1397
Takashi Iwai55e957d2005-11-17 14:52:13 +01001398 hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 spin_lock_irq (&hmidi->lock);
1400 hmidi->output = NULL;
1401 spin_unlock_irq (&hmidi->lock);
1402
1403 return 0;
1404}
1405
Takashi Iwai55e957d2005-11-17 14:52:13 +01001406static struct snd_rawmidi_ops snd_hdsp_midi_output =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407{
1408 .open = snd_hdsp_midi_output_open,
1409 .close = snd_hdsp_midi_output_close,
1410 .trigger = snd_hdsp_midi_output_trigger,
1411};
1412
Takashi Iwai55e957d2005-11-17 14:52:13 +01001413static struct snd_rawmidi_ops snd_hdsp_midi_input =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414{
1415 .open = snd_hdsp_midi_input_open,
1416 .close = snd_hdsp_midi_input_close,
1417 .trigger = snd_hdsp_midi_input_trigger,
1418};
1419
Takashi Iwaif40b6892006-07-05 16:51:05 +02001420static int snd_hdsp_create_midi (struct snd_card *card, struct hdsp *hdsp, int id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421{
1422 char buf[32];
1423
1424 hdsp->midi[id].id = id;
1425 hdsp->midi[id].rmidi = NULL;
1426 hdsp->midi[id].input = NULL;
1427 hdsp->midi[id].output = NULL;
1428 hdsp->midi[id].hdsp = hdsp;
1429 hdsp->midi[id].istimer = 0;
1430 hdsp->midi[id].pending = 0;
1431 spin_lock_init (&hdsp->midi[id].lock);
1432
1433 sprintf (buf, "%s MIDI %d", card->shortname, id+1);
Takashi Iwaib0b98112005-10-20 18:29:58 +02001434 if (snd_rawmidi_new (card, buf, id, 1, 1, &hdsp->midi[id].rmidi) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436
1437 sprintf (hdsp->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);
1438 hdsp->midi[id].rmidi->private_data = &hdsp->midi[id];
1439
1440 snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdsp_midi_output);
1441 snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdsp_midi_input);
1442
1443 hdsp->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
1444 SNDRV_RAWMIDI_INFO_INPUT |
1445 SNDRV_RAWMIDI_INFO_DUPLEX;
1446
1447 return 0;
1448}
1449
1450/*-----------------------------------------------------------------------------
1451 Control Interface
1452 ----------------------------------------------------------------------------*/
1453
Takashi Iwai55e957d2005-11-17 14:52:13 +01001454static u32 snd_hdsp_convert_from_aes(struct snd_aes_iec958 *aes)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455{
1456 u32 val = 0;
1457 val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? HDSP_SPDIFProfessional : 0;
1458 val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? HDSP_SPDIFNonAudio : 0;
1459 if (val & HDSP_SPDIFProfessional)
1460 val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0;
1461 else
1462 val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? HDSP_SPDIFEmphasis : 0;
1463 return val;
1464}
1465
Takashi Iwai55e957d2005-11-17 14:52:13 +01001466static void snd_hdsp_convert_to_aes(struct snd_aes_iec958 *aes, u32 val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467{
1468 aes->status[0] = ((val & HDSP_SPDIFProfessional) ? IEC958_AES0_PROFESSIONAL : 0) |
1469 ((val & HDSP_SPDIFNonAudio) ? IEC958_AES0_NONAUDIO : 0);
1470 if (val & HDSP_SPDIFProfessional)
1471 aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0;
1472 else
1473 aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_CON_EMPHASIS_5015 : 0;
1474}
1475
Takashi Iwai55e957d2005-11-17 14:52:13 +01001476static int snd_hdsp_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477{
1478 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1479 uinfo->count = 1;
1480 return 0;
1481}
1482
Takashi Iwai55e957d2005-11-17 14:52:13 +01001483static int snd_hdsp_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001485 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486
1487 snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif);
1488 return 0;
1489}
1490
Takashi Iwai55e957d2005-11-17 14:52:13 +01001491static int snd_hdsp_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001493 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 int change;
1495 u32 val;
1496
1497 val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
1498 spin_lock_irq(&hdsp->lock);
1499 change = val != hdsp->creg_spdif;
1500 hdsp->creg_spdif = val;
1501 spin_unlock_irq(&hdsp->lock);
1502 return change;
1503}
1504
Takashi Iwai55e957d2005-11-17 14:52:13 +01001505static int snd_hdsp_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506{
1507 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1508 uinfo->count = 1;
1509 return 0;
1510}
1511
Takashi Iwai55e957d2005-11-17 14:52:13 +01001512static int snd_hdsp_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001514 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515
1516 snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream);
1517 return 0;
1518}
1519
Takashi Iwai55e957d2005-11-17 14:52:13 +01001520static int snd_hdsp_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001522 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 int change;
1524 u32 val;
1525
1526 val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
1527 spin_lock_irq(&hdsp->lock);
1528 change = val != hdsp->creg_spdif_stream;
1529 hdsp->creg_spdif_stream = val;
1530 hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
1531 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= val);
1532 spin_unlock_irq(&hdsp->lock);
1533 return change;
1534}
1535
Takashi Iwai55e957d2005-11-17 14:52:13 +01001536static int snd_hdsp_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537{
1538 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1539 uinfo->count = 1;
1540 return 0;
1541}
1542
Takashi Iwai55e957d2005-11-17 14:52:13 +01001543static int snd_hdsp_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544{
1545 ucontrol->value.iec958.status[0] = kcontrol->private_value;
1546 return 0;
1547}
1548
1549#define HDSP_SPDIF_IN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001550{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 .name = xname, \
1552 .index = xindex, \
1553 .info = snd_hdsp_info_spdif_in, \
1554 .get = snd_hdsp_get_spdif_in, \
1555 .put = snd_hdsp_put_spdif_in }
1556
Takashi Iwai55e957d2005-11-17 14:52:13 +01001557static unsigned int hdsp_spdif_in(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558{
1559 return hdsp_decode_spdif_in(hdsp->control_register & HDSP_SPDIFInputMask);
1560}
1561
Takashi Iwai55e957d2005-11-17 14:52:13 +01001562static int hdsp_set_spdif_input(struct hdsp *hdsp, int in)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563{
1564 hdsp->control_register &= ~HDSP_SPDIFInputMask;
1565 hdsp->control_register |= hdsp_encode_spdif_in(in);
1566 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1567 return 0;
1568}
1569
Takashi Iwai55e957d2005-11-17 14:52:13 +01001570static int snd_hdsp_info_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571{
1572 static char *texts[4] = {"Optical", "Coaxial", "Internal", "AES"};
Takashi Iwai55e957d2005-11-17 14:52:13 +01001573 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574
1575 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1576 uinfo->count = 1;
1577 uinfo->value.enumerated.items = ((hdsp->io_type == H9632) ? 4 : 3);
1578 if (uinfo->value.enumerated.item > ((hdsp->io_type == H9632) ? 3 : 2))
1579 uinfo->value.enumerated.item = ((hdsp->io_type == H9632) ? 3 : 2);
1580 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1581 return 0;
1582}
1583
Takashi Iwai55e957d2005-11-17 14:52:13 +01001584static int snd_hdsp_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001586 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587
1588 ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp);
1589 return 0;
1590}
1591
Takashi Iwai55e957d2005-11-17 14:52:13 +01001592static int snd_hdsp_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001594 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 int change;
1596 unsigned int val;
1597
1598 if (!snd_hdsp_use_is_exclusive(hdsp))
1599 return -EBUSY;
1600 val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3);
1601 spin_lock_irq(&hdsp->lock);
1602 change = val != hdsp_spdif_in(hdsp);
1603 if (change)
1604 hdsp_set_spdif_input(hdsp, val);
1605 spin_unlock_irq(&hdsp->lock);
1606 return change;
1607}
1608
1609#define HDSP_SPDIF_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001610{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 .info = snd_hdsp_info_spdif_bits, \
1612 .get = snd_hdsp_get_spdif_out, .put = snd_hdsp_put_spdif_out }
1613
Takashi Iwai55e957d2005-11-17 14:52:13 +01001614static int hdsp_spdif_out(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615{
1616 return (hdsp->control_register & HDSP_SPDIFOpticalOut) ? 1 : 0;
1617}
1618
Takashi Iwai55e957d2005-11-17 14:52:13 +01001619static int hdsp_set_spdif_output(struct hdsp *hdsp, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001621 if (out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 hdsp->control_register |= HDSP_SPDIFOpticalOut;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001623 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 hdsp->control_register &= ~HDSP_SPDIFOpticalOut;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1626 return 0;
1627}
1628
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001629#define snd_hdsp_info_spdif_bits snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630
Takashi Iwai55e957d2005-11-17 14:52:13 +01001631static int snd_hdsp_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001633 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634
1635 ucontrol->value.integer.value[0] = hdsp_spdif_out(hdsp);
1636 return 0;
1637}
1638
Takashi Iwai55e957d2005-11-17 14:52:13 +01001639static int snd_hdsp_put_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001641 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 int change;
1643 unsigned int val;
1644
1645 if (!snd_hdsp_use_is_exclusive(hdsp))
1646 return -EBUSY;
1647 val = ucontrol->value.integer.value[0] & 1;
1648 spin_lock_irq(&hdsp->lock);
1649 change = (int)val != hdsp_spdif_out(hdsp);
1650 hdsp_set_spdif_output(hdsp, val);
1651 spin_unlock_irq(&hdsp->lock);
1652 return change;
1653}
1654
1655#define HDSP_SPDIF_PROFESSIONAL(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001656{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 .info = snd_hdsp_info_spdif_bits, \
1658 .get = snd_hdsp_get_spdif_professional, .put = snd_hdsp_put_spdif_professional }
1659
Takashi Iwai55e957d2005-11-17 14:52:13 +01001660static int hdsp_spdif_professional(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661{
1662 return (hdsp->control_register & HDSP_SPDIFProfessional) ? 1 : 0;
1663}
1664
Takashi Iwai55e957d2005-11-17 14:52:13 +01001665static int hdsp_set_spdif_professional(struct hdsp *hdsp, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001667 if (val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 hdsp->control_register |= HDSP_SPDIFProfessional;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001669 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 hdsp->control_register &= ~HDSP_SPDIFProfessional;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1672 return 0;
1673}
1674
Takashi Iwai55e957d2005-11-17 14:52:13 +01001675static int snd_hdsp_get_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001677 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678
1679 ucontrol->value.integer.value[0] = hdsp_spdif_professional(hdsp);
1680 return 0;
1681}
1682
Takashi Iwai55e957d2005-11-17 14:52:13 +01001683static int snd_hdsp_put_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001685 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 int change;
1687 unsigned int val;
1688
1689 if (!snd_hdsp_use_is_exclusive(hdsp))
1690 return -EBUSY;
1691 val = ucontrol->value.integer.value[0] & 1;
1692 spin_lock_irq(&hdsp->lock);
1693 change = (int)val != hdsp_spdif_professional(hdsp);
1694 hdsp_set_spdif_professional(hdsp, val);
1695 spin_unlock_irq(&hdsp->lock);
1696 return change;
1697}
1698
1699#define HDSP_SPDIF_EMPHASIS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001700{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 .info = snd_hdsp_info_spdif_bits, \
1702 .get = snd_hdsp_get_spdif_emphasis, .put = snd_hdsp_put_spdif_emphasis }
1703
Takashi Iwai55e957d2005-11-17 14:52:13 +01001704static int hdsp_spdif_emphasis(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705{
1706 return (hdsp->control_register & HDSP_SPDIFEmphasis) ? 1 : 0;
1707}
1708
Takashi Iwai55e957d2005-11-17 14:52:13 +01001709static int hdsp_set_spdif_emphasis(struct hdsp *hdsp, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001711 if (val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 hdsp->control_register |= HDSP_SPDIFEmphasis;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001713 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 hdsp->control_register &= ~HDSP_SPDIFEmphasis;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1716 return 0;
1717}
1718
Takashi Iwai55e957d2005-11-17 14:52:13 +01001719static int snd_hdsp_get_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001721 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722
1723 ucontrol->value.integer.value[0] = hdsp_spdif_emphasis(hdsp);
1724 return 0;
1725}
1726
Takashi Iwai55e957d2005-11-17 14:52:13 +01001727static int snd_hdsp_put_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001729 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 int change;
1731 unsigned int val;
1732
1733 if (!snd_hdsp_use_is_exclusive(hdsp))
1734 return -EBUSY;
1735 val = ucontrol->value.integer.value[0] & 1;
1736 spin_lock_irq(&hdsp->lock);
1737 change = (int)val != hdsp_spdif_emphasis(hdsp);
1738 hdsp_set_spdif_emphasis(hdsp, val);
1739 spin_unlock_irq(&hdsp->lock);
1740 return change;
1741}
1742
1743#define HDSP_SPDIF_NON_AUDIO(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001744{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 .info = snd_hdsp_info_spdif_bits, \
1746 .get = snd_hdsp_get_spdif_nonaudio, .put = snd_hdsp_put_spdif_nonaudio }
1747
Takashi Iwai55e957d2005-11-17 14:52:13 +01001748static int hdsp_spdif_nonaudio(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749{
1750 return (hdsp->control_register & HDSP_SPDIFNonAudio) ? 1 : 0;
1751}
1752
Takashi Iwai55e957d2005-11-17 14:52:13 +01001753static int hdsp_set_spdif_nonaudio(struct hdsp *hdsp, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001755 if (val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 hdsp->control_register |= HDSP_SPDIFNonAudio;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001757 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 hdsp->control_register &= ~HDSP_SPDIFNonAudio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1760 return 0;
1761}
1762
Takashi Iwai55e957d2005-11-17 14:52:13 +01001763static int snd_hdsp_get_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001765 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766
1767 ucontrol->value.integer.value[0] = hdsp_spdif_nonaudio(hdsp);
1768 return 0;
1769}
1770
Takashi Iwai55e957d2005-11-17 14:52:13 +01001771static int snd_hdsp_put_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001773 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 int change;
1775 unsigned int val;
1776
1777 if (!snd_hdsp_use_is_exclusive(hdsp))
1778 return -EBUSY;
1779 val = ucontrol->value.integer.value[0] & 1;
1780 spin_lock_irq(&hdsp->lock);
1781 change = (int)val != hdsp_spdif_nonaudio(hdsp);
1782 hdsp_set_spdif_nonaudio(hdsp, val);
1783 spin_unlock_irq(&hdsp->lock);
1784 return change;
1785}
1786
1787#define HDSP_SPDIF_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001788{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 .name = xname, \
1790 .index = xindex, \
1791 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1792 .info = snd_hdsp_info_spdif_sample_rate, \
1793 .get = snd_hdsp_get_spdif_sample_rate \
1794}
1795
Takashi Iwai55e957d2005-11-17 14:52:13 +01001796static int snd_hdsp_info_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797{
1798 static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
Takashi Iwai55e957d2005-11-17 14:52:13 +01001799 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800
1801 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1802 uinfo->count = 1;
1803 uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7;
1804 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1805 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1806 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1807 return 0;
1808}
1809
Takashi Iwai55e957d2005-11-17 14:52:13 +01001810static int snd_hdsp_get_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001812 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813
1814 switch (hdsp_spdif_sample_rate(hdsp)) {
1815 case 32000:
1816 ucontrol->value.enumerated.item[0] = 0;
1817 break;
1818 case 44100:
1819 ucontrol->value.enumerated.item[0] = 1;
1820 break;
1821 case 48000:
1822 ucontrol->value.enumerated.item[0] = 2;
1823 break;
1824 case 64000:
1825 ucontrol->value.enumerated.item[0] = 3;
1826 break;
1827 case 88200:
1828 ucontrol->value.enumerated.item[0] = 4;
1829 break;
1830 case 96000:
1831 ucontrol->value.enumerated.item[0] = 5;
1832 break;
1833 case 128000:
1834 ucontrol->value.enumerated.item[0] = 7;
1835 break;
1836 case 176400:
1837 ucontrol->value.enumerated.item[0] = 8;
1838 break;
1839 case 192000:
1840 ucontrol->value.enumerated.item[0] = 9;
1841 break;
1842 default:
1843 ucontrol->value.enumerated.item[0] = 6;
1844 }
1845 return 0;
1846}
1847
1848#define HDSP_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001849{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 .name = xname, \
1851 .index = xindex, \
1852 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1853 .info = snd_hdsp_info_system_sample_rate, \
1854 .get = snd_hdsp_get_system_sample_rate \
1855}
1856
Takashi Iwai55e957d2005-11-17 14:52:13 +01001857static int snd_hdsp_info_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858{
1859 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1860 uinfo->count = 1;
1861 return 0;
1862}
1863
Takashi Iwai55e957d2005-11-17 14:52:13 +01001864static int snd_hdsp_get_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001866 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867
1868 ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate;
1869 return 0;
1870}
1871
1872#define HDSP_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001873{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 .name = xname, \
1875 .index = xindex, \
1876 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1877 .info = snd_hdsp_info_autosync_sample_rate, \
1878 .get = snd_hdsp_get_autosync_sample_rate \
1879}
1880
Takashi Iwai55e957d2005-11-17 14:52:13 +01001881static int snd_hdsp_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001883 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884 static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
1885 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1886 uinfo->count = 1;
1887 uinfo->value.enumerated.items = (hdsp->io_type == H9632) ? 10 : 7 ;
1888 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1889 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1890 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1891 return 0;
1892}
1893
Takashi Iwai55e957d2005-11-17 14:52:13 +01001894static int snd_hdsp_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001896 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897
1898 switch (hdsp_external_sample_rate(hdsp)) {
1899 case 32000:
1900 ucontrol->value.enumerated.item[0] = 0;
1901 break;
1902 case 44100:
1903 ucontrol->value.enumerated.item[0] = 1;
1904 break;
1905 case 48000:
1906 ucontrol->value.enumerated.item[0] = 2;
1907 break;
1908 case 64000:
1909 ucontrol->value.enumerated.item[0] = 3;
1910 break;
1911 case 88200:
1912 ucontrol->value.enumerated.item[0] = 4;
1913 break;
1914 case 96000:
1915 ucontrol->value.enumerated.item[0] = 5;
1916 break;
1917 case 128000:
1918 ucontrol->value.enumerated.item[0] = 7;
1919 break;
1920 case 176400:
1921 ucontrol->value.enumerated.item[0] = 8;
1922 break;
1923 case 192000:
1924 ucontrol->value.enumerated.item[0] = 9;
1925 break;
1926 default:
1927 ucontrol->value.enumerated.item[0] = 6;
1928 }
1929 return 0;
1930}
1931
1932#define HDSP_SYSTEM_CLOCK_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001933{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 .name = xname, \
1935 .index = xindex, \
1936 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1937 .info = snd_hdsp_info_system_clock_mode, \
1938 .get = snd_hdsp_get_system_clock_mode \
1939}
1940
Takashi Iwai55e957d2005-11-17 14:52:13 +01001941static int hdsp_system_clock_mode(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942{
Takashi Iwaib0b98112005-10-20 18:29:58 +02001943 if (hdsp->control_register & HDSP_ClockModeMaster)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02001945 else if (hdsp_external_sample_rate(hdsp) != hdsp->system_sample_rate)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947 return 1;
1948}
1949
Takashi Iwai55e957d2005-11-17 14:52:13 +01001950static int snd_hdsp_info_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951{
1952 static char *texts[] = {"Master", "Slave" };
1953
1954 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1955 uinfo->count = 1;
1956 uinfo->value.enumerated.items = 2;
1957 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1958 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1959 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1960 return 0;
1961}
1962
Takashi Iwai55e957d2005-11-17 14:52:13 +01001963static int snd_hdsp_get_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964{
Takashi Iwai55e957d2005-11-17 14:52:13 +01001965 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966
1967 ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp);
1968 return 0;
1969}
1970
1971#define HDSP_CLOCK_SOURCE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001972{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973 .name = xname, \
1974 .index = xindex, \
1975 .info = snd_hdsp_info_clock_source, \
1976 .get = snd_hdsp_get_clock_source, \
1977 .put = snd_hdsp_put_clock_source \
1978}
1979
Takashi Iwai55e957d2005-11-17 14:52:13 +01001980static int hdsp_clock_source(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981{
1982 if (hdsp->control_register & HDSP_ClockModeMaster) {
1983 switch (hdsp->system_sample_rate) {
1984 case 32000:
1985 return 1;
1986 case 44100:
1987 return 2;
1988 case 48000:
1989 return 3;
1990 case 64000:
1991 return 4;
1992 case 88200:
1993 return 5;
1994 case 96000:
1995 return 6;
1996 case 128000:
1997 return 7;
1998 case 176400:
1999 return 8;
2000 case 192000:
2001 return 9;
2002 default:
2003 return 3;
2004 }
2005 } else {
2006 return 0;
2007 }
2008}
2009
Takashi Iwai55e957d2005-11-17 14:52:13 +01002010static int hdsp_set_clock_source(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011{
2012 int rate;
2013 switch (mode) {
2014 case HDSP_CLOCK_SOURCE_AUTOSYNC:
2015 if (hdsp_external_sample_rate(hdsp) != 0) {
2016 if (!hdsp_set_rate(hdsp, hdsp_external_sample_rate(hdsp), 1)) {
2017 hdsp->control_register &= ~HDSP_ClockModeMaster;
2018 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2019 return 0;
2020 }
2021 }
2022 return -1;
2023 case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ:
2024 rate = 32000;
2025 break;
2026 case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ:
2027 rate = 44100;
2028 break;
2029 case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ:
2030 rate = 48000;
2031 break;
2032 case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ:
2033 rate = 64000;
2034 break;
2035 case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ:
2036 rate = 88200;
2037 break;
2038 case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ:
2039 rate = 96000;
2040 break;
2041 case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ:
2042 rate = 128000;
2043 break;
2044 case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ:
2045 rate = 176400;
2046 break;
2047 case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ:
2048 rate = 192000;
2049 break;
2050 default:
2051 rate = 48000;
2052 }
2053 hdsp->control_register |= HDSP_ClockModeMaster;
2054 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2055 hdsp_set_rate(hdsp, rate, 1);
2056 return 0;
2057}
2058
Takashi Iwai55e957d2005-11-17 14:52:13 +01002059static int snd_hdsp_info_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060{
2061 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 +01002062 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063
2064 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2065 uinfo->count = 1;
2066 if (hdsp->io_type == H9632)
2067 uinfo->value.enumerated.items = 10;
2068 else
2069 uinfo->value.enumerated.items = 7;
2070 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2071 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2072 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2073 return 0;
2074}
2075
Takashi Iwai55e957d2005-11-17 14:52:13 +01002076static int snd_hdsp_get_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002078 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079
2080 ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp);
2081 return 0;
2082}
2083
Takashi Iwai55e957d2005-11-17 14:52:13 +01002084static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002086 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 int change;
2088 int val;
2089
2090 if (!snd_hdsp_use_is_exclusive(hdsp))
2091 return -EBUSY;
2092 val = ucontrol->value.enumerated.item[0];
2093 if (val < 0) val = 0;
2094 if (hdsp->io_type == H9632) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002095 if (val > 9)
2096 val = 9;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002098 if (val > 6)
2099 val = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 }
2101 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002102 if (val != hdsp_clock_source(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 change = (hdsp_set_clock_source(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002104 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 spin_unlock_irq(&hdsp->lock);
2107 return change;
2108}
2109
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002110#define snd_hdsp_info_clock_source_lock snd_ctl_boolean_mono_info
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002111
Takashi Iwai55e957d2005-11-17 14:52:13 +01002112static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002113{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002114 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002115
2116 ucontrol->value.integer.value[0] = hdsp->clock_source_locked;
2117 return 0;
2118}
2119
Takashi Iwai55e957d2005-11-17 14:52:13 +01002120static int snd_hdsp_put_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002121{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002122 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002123 int change;
2124
2125 change = (int)ucontrol->value.integer.value[0] != hdsp->clock_source_locked;
2126 if (change)
Takashi Iwai4e98d6a2007-11-15 15:58:13 +01002127 hdsp->clock_source_locked = !!ucontrol->value.integer.value[0];
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02002128 return change;
2129}
2130
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131#define HDSP_DA_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002132{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 .name = xname, \
2134 .index = xindex, \
2135 .info = snd_hdsp_info_da_gain, \
2136 .get = snd_hdsp_get_da_gain, \
2137 .put = snd_hdsp_put_da_gain \
2138}
2139
Takashi Iwai55e957d2005-11-17 14:52:13 +01002140static int hdsp_da_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141{
2142 switch (hdsp->control_register & HDSP_DAGainMask) {
2143 case HDSP_DAGainHighGain:
2144 return 0;
2145 case HDSP_DAGainPlus4dBu:
2146 return 1;
2147 case HDSP_DAGainMinus10dBV:
2148 return 2;
2149 default:
2150 return 1;
2151 }
2152}
2153
Takashi Iwai55e957d2005-11-17 14:52:13 +01002154static int hdsp_set_da_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155{
2156 hdsp->control_register &= ~HDSP_DAGainMask;
2157 switch (mode) {
2158 case 0:
2159 hdsp->control_register |= HDSP_DAGainHighGain;
2160 break;
2161 case 1:
2162 hdsp->control_register |= HDSP_DAGainPlus4dBu;
2163 break;
2164 case 2:
2165 hdsp->control_register |= HDSP_DAGainMinus10dBV;
2166 break;
2167 default:
2168 return -1;
2169
2170 }
2171 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2172 return 0;
2173}
2174
Takashi Iwai55e957d2005-11-17 14:52:13 +01002175static int snd_hdsp_info_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176{
2177 static char *texts[] = {"Hi Gain", "+4 dBu", "-10 dbV"};
2178
2179 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2180 uinfo->count = 1;
2181 uinfo->value.enumerated.items = 3;
2182 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2183 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2184 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2185 return 0;
2186}
2187
Takashi Iwai55e957d2005-11-17 14:52:13 +01002188static int snd_hdsp_get_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002190 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191
2192 ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp);
2193 return 0;
2194}
2195
Takashi Iwai55e957d2005-11-17 14:52:13 +01002196static int snd_hdsp_put_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002198 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 int change;
2200 int val;
2201
2202 if (!snd_hdsp_use_is_exclusive(hdsp))
2203 return -EBUSY;
2204 val = ucontrol->value.enumerated.item[0];
2205 if (val < 0) val = 0;
2206 if (val > 2) val = 2;
2207 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002208 if (val != hdsp_da_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 change = (hdsp_set_da_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002210 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212 spin_unlock_irq(&hdsp->lock);
2213 return change;
2214}
2215
2216#define HDSP_AD_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002217{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 .name = xname, \
2219 .index = xindex, \
2220 .info = snd_hdsp_info_ad_gain, \
2221 .get = snd_hdsp_get_ad_gain, \
2222 .put = snd_hdsp_put_ad_gain \
2223}
2224
Takashi Iwai55e957d2005-11-17 14:52:13 +01002225static int hdsp_ad_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226{
2227 switch (hdsp->control_register & HDSP_ADGainMask) {
2228 case HDSP_ADGainMinus10dBV:
2229 return 0;
2230 case HDSP_ADGainPlus4dBu:
2231 return 1;
2232 case HDSP_ADGainLowGain:
2233 return 2;
2234 default:
2235 return 1;
2236 }
2237}
2238
Takashi Iwai55e957d2005-11-17 14:52:13 +01002239static int hdsp_set_ad_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240{
2241 hdsp->control_register &= ~HDSP_ADGainMask;
2242 switch (mode) {
2243 case 0:
2244 hdsp->control_register |= HDSP_ADGainMinus10dBV;
2245 break;
2246 case 1:
2247 hdsp->control_register |= HDSP_ADGainPlus4dBu;
2248 break;
2249 case 2:
2250 hdsp->control_register |= HDSP_ADGainLowGain;
2251 break;
2252 default:
2253 return -1;
2254
2255 }
2256 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2257 return 0;
2258}
2259
Takashi Iwai55e957d2005-11-17 14:52:13 +01002260static int snd_hdsp_info_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261{
2262 static char *texts[] = {"-10 dBV", "+4 dBu", "Lo Gain"};
2263
2264 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2265 uinfo->count = 1;
2266 uinfo->value.enumerated.items = 3;
2267 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2268 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2269 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2270 return 0;
2271}
2272
Takashi Iwai55e957d2005-11-17 14:52:13 +01002273static int snd_hdsp_get_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002275 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276
2277 ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp);
2278 return 0;
2279}
2280
Takashi Iwai55e957d2005-11-17 14:52:13 +01002281static int snd_hdsp_put_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002283 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 int change;
2285 int val;
2286
2287 if (!snd_hdsp_use_is_exclusive(hdsp))
2288 return -EBUSY;
2289 val = ucontrol->value.enumerated.item[0];
2290 if (val < 0) val = 0;
2291 if (val > 2) val = 2;
2292 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002293 if (val != hdsp_ad_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 change = (hdsp_set_ad_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002295 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 spin_unlock_irq(&hdsp->lock);
2298 return change;
2299}
2300
2301#define HDSP_PHONE_GAIN(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002302{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 .name = xname, \
2304 .index = xindex, \
2305 .info = snd_hdsp_info_phone_gain, \
2306 .get = snd_hdsp_get_phone_gain, \
2307 .put = snd_hdsp_put_phone_gain \
2308}
2309
Takashi Iwai55e957d2005-11-17 14:52:13 +01002310static int hdsp_phone_gain(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311{
2312 switch (hdsp->control_register & HDSP_PhoneGainMask) {
2313 case HDSP_PhoneGain0dB:
2314 return 0;
2315 case HDSP_PhoneGainMinus6dB:
2316 return 1;
2317 case HDSP_PhoneGainMinus12dB:
2318 return 2;
2319 default:
2320 return 0;
2321 }
2322}
2323
Takashi Iwai55e957d2005-11-17 14:52:13 +01002324static int hdsp_set_phone_gain(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325{
2326 hdsp->control_register &= ~HDSP_PhoneGainMask;
2327 switch (mode) {
2328 case 0:
2329 hdsp->control_register |= HDSP_PhoneGain0dB;
2330 break;
2331 case 1:
2332 hdsp->control_register |= HDSP_PhoneGainMinus6dB;
2333 break;
2334 case 2:
2335 hdsp->control_register |= HDSP_PhoneGainMinus12dB;
2336 break;
2337 default:
2338 return -1;
2339
2340 }
2341 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2342 return 0;
2343}
2344
Takashi Iwai55e957d2005-11-17 14:52:13 +01002345static int snd_hdsp_info_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346{
2347 static char *texts[] = {"0 dB", "-6 dB", "-12 dB"};
2348
2349 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2350 uinfo->count = 1;
2351 uinfo->value.enumerated.items = 3;
2352 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2353 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2354 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2355 return 0;
2356}
2357
Takashi Iwai55e957d2005-11-17 14:52:13 +01002358static int snd_hdsp_get_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002360 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361
2362 ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp);
2363 return 0;
2364}
2365
Takashi Iwai55e957d2005-11-17 14:52:13 +01002366static int snd_hdsp_put_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002368 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 int change;
2370 int val;
2371
2372 if (!snd_hdsp_use_is_exclusive(hdsp))
2373 return -EBUSY;
2374 val = ucontrol->value.enumerated.item[0];
2375 if (val < 0) val = 0;
2376 if (val > 2) val = 2;
2377 spin_lock_irq(&hdsp->lock);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002378 if (val != hdsp_phone_gain(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 change = (hdsp_set_phone_gain(hdsp, val) == 0) ? 1 : 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002380 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 change = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382 spin_unlock_irq(&hdsp->lock);
2383 return change;
2384}
2385
2386#define HDSP_XLR_BREAKOUT_CABLE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002387{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 .name = xname, \
2389 .index = xindex, \
2390 .info = snd_hdsp_info_xlr_breakout_cable, \
2391 .get = snd_hdsp_get_xlr_breakout_cable, \
2392 .put = snd_hdsp_put_xlr_breakout_cable \
2393}
2394
Takashi Iwai55e957d2005-11-17 14:52:13 +01002395static int hdsp_xlr_breakout_cable(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002397 if (hdsp->control_register & HDSP_XLRBreakoutCable)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 return 0;
2400}
2401
Takashi Iwai55e957d2005-11-17 14:52:13 +01002402static int hdsp_set_xlr_breakout_cable(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002404 if (mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 hdsp->control_register |= HDSP_XLRBreakoutCable;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002406 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 hdsp->control_register &= ~HDSP_XLRBreakoutCable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2409 return 0;
2410}
2411
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002412#define snd_hdsp_info_xlr_breakout_cable snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413
Takashi Iwai55e957d2005-11-17 14:52:13 +01002414static int snd_hdsp_get_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002416 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417
2418 ucontrol->value.enumerated.item[0] = hdsp_xlr_breakout_cable(hdsp);
2419 return 0;
2420}
2421
Takashi Iwai55e957d2005-11-17 14:52:13 +01002422static int snd_hdsp_put_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002424 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425 int change;
2426 int val;
2427
2428 if (!snd_hdsp_use_is_exclusive(hdsp))
2429 return -EBUSY;
2430 val = ucontrol->value.integer.value[0] & 1;
2431 spin_lock_irq(&hdsp->lock);
2432 change = (int)val != hdsp_xlr_breakout_cable(hdsp);
2433 hdsp_set_xlr_breakout_cable(hdsp, val);
2434 spin_unlock_irq(&hdsp->lock);
2435 return change;
2436}
2437
2438/* (De)activates old RME Analog Extension Board
2439 These are connected to the internal ADAT connector
2440 Switching this on desactivates external ADAT
2441*/
2442#define HDSP_AEB(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002443{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 .name = xname, \
2445 .index = xindex, \
2446 .info = snd_hdsp_info_aeb, \
2447 .get = snd_hdsp_get_aeb, \
2448 .put = snd_hdsp_put_aeb \
2449}
2450
Takashi Iwai55e957d2005-11-17 14:52:13 +01002451static int hdsp_aeb(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002453 if (hdsp->control_register & HDSP_AnalogExtensionBoard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 return 0;
2456}
2457
Takashi Iwai55e957d2005-11-17 14:52:13 +01002458static int hdsp_set_aeb(struct hdsp *hdsp, int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002460 if (mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 hdsp->control_register |= HDSP_AnalogExtensionBoard;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002462 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 hdsp->control_register &= ~HDSP_AnalogExtensionBoard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2465 return 0;
2466}
2467
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002468#define snd_hdsp_info_aeb snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469
Takashi Iwai55e957d2005-11-17 14:52:13 +01002470static int snd_hdsp_get_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002472 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473
2474 ucontrol->value.enumerated.item[0] = hdsp_aeb(hdsp);
2475 return 0;
2476}
2477
Takashi Iwai55e957d2005-11-17 14:52:13 +01002478static int snd_hdsp_put_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002480 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481 int change;
2482 int val;
2483
2484 if (!snd_hdsp_use_is_exclusive(hdsp))
2485 return -EBUSY;
2486 val = ucontrol->value.integer.value[0] & 1;
2487 spin_lock_irq(&hdsp->lock);
2488 change = (int)val != hdsp_aeb(hdsp);
2489 hdsp_set_aeb(hdsp, val);
2490 spin_unlock_irq(&hdsp->lock);
2491 return change;
2492}
2493
2494#define HDSP_PREF_SYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002495{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496 .name = xname, \
2497 .index = xindex, \
2498 .info = snd_hdsp_info_pref_sync_ref, \
2499 .get = snd_hdsp_get_pref_sync_ref, \
2500 .put = snd_hdsp_put_pref_sync_ref \
2501}
2502
Takashi Iwai55e957d2005-11-17 14:52:13 +01002503static int hdsp_pref_sync_ref(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504{
2505 /* Notice that this looks at the requested sync source,
2506 not the one actually in use.
2507 */
2508
2509 switch (hdsp->control_register & HDSP_SyncRefMask) {
2510 case HDSP_SyncRef_ADAT1:
2511 return HDSP_SYNC_FROM_ADAT1;
2512 case HDSP_SyncRef_ADAT2:
2513 return HDSP_SYNC_FROM_ADAT2;
2514 case HDSP_SyncRef_ADAT3:
2515 return HDSP_SYNC_FROM_ADAT3;
2516 case HDSP_SyncRef_SPDIF:
2517 return HDSP_SYNC_FROM_SPDIF;
2518 case HDSP_SyncRef_WORD:
2519 return HDSP_SYNC_FROM_WORD;
2520 case HDSP_SyncRef_ADAT_SYNC:
2521 return HDSP_SYNC_FROM_ADAT_SYNC;
2522 default:
2523 return HDSP_SYNC_FROM_WORD;
2524 }
2525 return 0;
2526}
2527
Takashi Iwai55e957d2005-11-17 14:52:13 +01002528static int hdsp_set_pref_sync_ref(struct hdsp *hdsp, int pref)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529{
2530 hdsp->control_register &= ~HDSP_SyncRefMask;
2531 switch (pref) {
2532 case HDSP_SYNC_FROM_ADAT1:
2533 hdsp->control_register &= ~HDSP_SyncRefMask; /* clear SyncRef bits */
2534 break;
2535 case HDSP_SYNC_FROM_ADAT2:
2536 hdsp->control_register |= HDSP_SyncRef_ADAT2;
2537 break;
2538 case HDSP_SYNC_FROM_ADAT3:
2539 hdsp->control_register |= HDSP_SyncRef_ADAT3;
2540 break;
2541 case HDSP_SYNC_FROM_SPDIF:
2542 hdsp->control_register |= HDSP_SyncRef_SPDIF;
2543 break;
2544 case HDSP_SYNC_FROM_WORD:
2545 hdsp->control_register |= HDSP_SyncRef_WORD;
2546 break;
2547 case HDSP_SYNC_FROM_ADAT_SYNC:
2548 hdsp->control_register |= HDSP_SyncRef_ADAT_SYNC;
2549 break;
2550 default:
2551 return -1;
2552 }
2553 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2554 return 0;
2555}
2556
Takashi Iwai55e957d2005-11-17 14:52:13 +01002557static int snd_hdsp_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558{
2559 static char *texts[] = {"Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3" };
Takashi Iwai55e957d2005-11-17 14:52:13 +01002560 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561
2562 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2563 uinfo->count = 1;
2564
2565 switch (hdsp->io_type) {
2566 case Digiface:
2567 case H9652:
2568 uinfo->value.enumerated.items = 6;
2569 break;
2570 case Multiface:
2571 uinfo->value.enumerated.items = 4;
2572 break;
2573 case H9632:
2574 uinfo->value.enumerated.items = 3;
2575 break;
2576 default:
2577 uinfo->value.enumerated.items = 0;
2578 break;
2579 }
2580
2581 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2582 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2583 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2584 return 0;
2585}
2586
Takashi Iwai55e957d2005-11-17 14:52:13 +01002587static int snd_hdsp_get_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002589 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590
2591 ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp);
2592 return 0;
2593}
2594
Takashi Iwai55e957d2005-11-17 14:52:13 +01002595static int snd_hdsp_put_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002597 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 int change, max;
2599 unsigned int val;
2600
2601 if (!snd_hdsp_use_is_exclusive(hdsp))
2602 return -EBUSY;
2603
2604 switch (hdsp->io_type) {
2605 case Digiface:
2606 case H9652:
2607 max = 6;
2608 break;
2609 case Multiface:
2610 max = 4;
2611 break;
2612 case H9632:
2613 max = 3;
2614 break;
2615 default:
2616 return -EIO;
2617 }
2618
2619 val = ucontrol->value.enumerated.item[0] % max;
2620 spin_lock_irq(&hdsp->lock);
2621 change = (int)val != hdsp_pref_sync_ref(hdsp);
2622 hdsp_set_pref_sync_ref(hdsp, val);
2623 spin_unlock_irq(&hdsp->lock);
2624 return change;
2625}
2626
2627#define HDSP_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002628{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 .name = xname, \
2630 .index = xindex, \
2631 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2632 .info = snd_hdsp_info_autosync_ref, \
2633 .get = snd_hdsp_get_autosync_ref, \
2634}
2635
Takashi Iwai55e957d2005-11-17 14:52:13 +01002636static int hdsp_autosync_ref(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637{
2638 /* This looks at the autosync selected sync reference */
2639 unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
2640
2641 switch (status2 & HDSP_SelSyncRefMask) {
2642 case HDSP_SelSyncRef_WORD:
2643 return HDSP_AUTOSYNC_FROM_WORD;
2644 case HDSP_SelSyncRef_ADAT_SYNC:
2645 return HDSP_AUTOSYNC_FROM_ADAT_SYNC;
2646 case HDSP_SelSyncRef_SPDIF:
2647 return HDSP_AUTOSYNC_FROM_SPDIF;
2648 case HDSP_SelSyncRefMask:
2649 return HDSP_AUTOSYNC_FROM_NONE;
2650 case HDSP_SelSyncRef_ADAT1:
2651 return HDSP_AUTOSYNC_FROM_ADAT1;
2652 case HDSP_SelSyncRef_ADAT2:
2653 return HDSP_AUTOSYNC_FROM_ADAT2;
2654 case HDSP_SelSyncRef_ADAT3:
2655 return HDSP_AUTOSYNC_FROM_ADAT3;
2656 default:
2657 return HDSP_AUTOSYNC_FROM_WORD;
2658 }
2659 return 0;
2660}
2661
Takashi Iwai55e957d2005-11-17 14:52:13 +01002662static int snd_hdsp_info_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663{
2664 static char *texts[] = {"Word", "ADAT Sync", "IEC958", "None", "ADAT1", "ADAT2", "ADAT3" };
2665
2666 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2667 uinfo->count = 1;
2668 uinfo->value.enumerated.items = 7;
2669 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2670 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2671 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2672 return 0;
2673}
2674
Takashi Iwai55e957d2005-11-17 14:52:13 +01002675static int snd_hdsp_get_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002677 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678
2679 ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp);
2680 return 0;
2681}
2682
2683#define HDSP_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002684{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 .name = xname, \
2686 .index = xindex, \
2687 .info = snd_hdsp_info_line_out, \
2688 .get = snd_hdsp_get_line_out, \
2689 .put = snd_hdsp_put_line_out \
2690}
2691
Takashi Iwai55e957d2005-11-17 14:52:13 +01002692static int hdsp_line_out(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693{
2694 return (hdsp->control_register & HDSP_LineOut) ? 1 : 0;
2695}
2696
Takashi Iwai55e957d2005-11-17 14:52:13 +01002697static int hdsp_set_line_output(struct hdsp *hdsp, int out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002699 if (out)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 hdsp->control_register |= HDSP_LineOut;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002701 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 hdsp->control_register &= ~HDSP_LineOut;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
2704 return 0;
2705}
2706
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002707#define snd_hdsp_info_line_out snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708
Takashi Iwai55e957d2005-11-17 14:52:13 +01002709static int snd_hdsp_get_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002711 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712
2713 spin_lock_irq(&hdsp->lock);
2714 ucontrol->value.integer.value[0] = hdsp_line_out(hdsp);
2715 spin_unlock_irq(&hdsp->lock);
2716 return 0;
2717}
2718
Takashi Iwai55e957d2005-11-17 14:52:13 +01002719static int snd_hdsp_put_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002721 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 int change;
2723 unsigned int val;
2724
2725 if (!snd_hdsp_use_is_exclusive(hdsp))
2726 return -EBUSY;
2727 val = ucontrol->value.integer.value[0] & 1;
2728 spin_lock_irq(&hdsp->lock);
2729 change = (int)val != hdsp_line_out(hdsp);
2730 hdsp_set_line_output(hdsp, val);
2731 spin_unlock_irq(&hdsp->lock);
2732 return change;
2733}
2734
2735#define HDSP_PRECISE_POINTER(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002736{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 .name = xname, \
2738 .index = xindex, \
2739 .info = snd_hdsp_info_precise_pointer, \
2740 .get = snd_hdsp_get_precise_pointer, \
2741 .put = snd_hdsp_put_precise_pointer \
2742}
2743
Takashi Iwai55e957d2005-11-17 14:52:13 +01002744static int hdsp_set_precise_pointer(struct hdsp *hdsp, int precise)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002746 if (precise)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 hdsp->precise_ptr = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002748 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749 hdsp->precise_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 return 0;
2751}
2752
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002753#define snd_hdsp_info_precise_pointer snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754
Takashi Iwai55e957d2005-11-17 14:52:13 +01002755static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002757 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758
2759 spin_lock_irq(&hdsp->lock);
2760 ucontrol->value.integer.value[0] = hdsp->precise_ptr;
2761 spin_unlock_irq(&hdsp->lock);
2762 return 0;
2763}
2764
Takashi Iwai55e957d2005-11-17 14:52:13 +01002765static int snd_hdsp_put_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002767 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768 int change;
2769 unsigned int val;
2770
2771 if (!snd_hdsp_use_is_exclusive(hdsp))
2772 return -EBUSY;
2773 val = ucontrol->value.integer.value[0] & 1;
2774 spin_lock_irq(&hdsp->lock);
2775 change = (int)val != hdsp->precise_ptr;
2776 hdsp_set_precise_pointer(hdsp, val);
2777 spin_unlock_irq(&hdsp->lock);
2778 return change;
2779}
2780
2781#define HDSP_USE_MIDI_TASKLET(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002782{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783 .name = xname, \
2784 .index = xindex, \
2785 .info = snd_hdsp_info_use_midi_tasklet, \
2786 .get = snd_hdsp_get_use_midi_tasklet, \
2787 .put = snd_hdsp_put_use_midi_tasklet \
2788}
2789
Takashi Iwai55e957d2005-11-17 14:52:13 +01002790static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791{
Takashi Iwaib0b98112005-10-20 18:29:58 +02002792 if (use_tasklet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 hdsp->use_midi_tasklet = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002794 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795 hdsp->use_midi_tasklet = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796 return 0;
2797}
2798
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002799#define snd_hdsp_info_use_midi_tasklet snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800
Takashi Iwai55e957d2005-11-17 14:52:13 +01002801static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002803 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804
2805 spin_lock_irq(&hdsp->lock);
2806 ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet;
2807 spin_unlock_irq(&hdsp->lock);
2808 return 0;
2809}
2810
Takashi Iwai55e957d2005-11-17 14:52:13 +01002811static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002813 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814 int change;
2815 unsigned int val;
2816
2817 if (!snd_hdsp_use_is_exclusive(hdsp))
2818 return -EBUSY;
2819 val = ucontrol->value.integer.value[0] & 1;
2820 spin_lock_irq(&hdsp->lock);
2821 change = (int)val != hdsp->use_midi_tasklet;
2822 hdsp_set_use_midi_tasklet(hdsp, val);
2823 spin_unlock_irq(&hdsp->lock);
2824 return change;
2825}
2826
2827#define HDSP_MIXER(xname, xindex) \
2828{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
2829 .name = xname, \
2830 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002831 .device = 0, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2833 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2834 .info = snd_hdsp_info_mixer, \
2835 .get = snd_hdsp_get_mixer, \
2836 .put = snd_hdsp_put_mixer \
2837}
2838
Takashi Iwai55e957d2005-11-17 14:52:13 +01002839static int snd_hdsp_info_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840{
2841 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2842 uinfo->count = 3;
2843 uinfo->value.integer.min = 0;
2844 uinfo->value.integer.max = 65536;
2845 uinfo->value.integer.step = 1;
2846 return 0;
2847}
2848
Takashi Iwai55e957d2005-11-17 14:52:13 +01002849static int snd_hdsp_get_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002851 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852 int source;
2853 int destination;
2854 int addr;
2855
2856 source = ucontrol->value.integer.value[0];
2857 destination = ucontrol->value.integer.value[1];
2858
Takashi Iwaib0b98112005-10-20 18:29:58 +02002859 if (source >= hdsp->max_channels)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels,destination);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002861 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 addr = hdsp_input_to_output_key(hdsp,source, destination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863
2864 spin_lock_irq(&hdsp->lock);
2865 ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr);
2866 spin_unlock_irq(&hdsp->lock);
2867 return 0;
2868}
2869
Takashi Iwai55e957d2005-11-17 14:52:13 +01002870static int snd_hdsp_put_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002872 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873 int change;
2874 int source;
2875 int destination;
2876 int gain;
2877 int addr;
2878
2879 if (!snd_hdsp_use_is_exclusive(hdsp))
2880 return -EBUSY;
2881
2882 source = ucontrol->value.integer.value[0];
2883 destination = ucontrol->value.integer.value[1];
2884
Takashi Iwaib0b98112005-10-20 18:29:58 +02002885 if (source >= hdsp->max_channels)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886 addr = hdsp_playback_to_output_key(hdsp,source-hdsp->max_channels, destination);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002887 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888 addr = hdsp_input_to_output_key(hdsp,source, destination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889
2890 gain = ucontrol->value.integer.value[2];
2891
2892 spin_lock_irq(&hdsp->lock);
2893 change = gain != hdsp_read_gain(hdsp, addr);
2894 if (change)
2895 hdsp_write_gain(hdsp, addr, gain);
2896 spin_unlock_irq(&hdsp->lock);
2897 return change;
2898}
2899
2900#define HDSP_WC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002901{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902 .name = xname, \
2903 .index = xindex, \
2904 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2905 .info = snd_hdsp_info_sync_check, \
2906 .get = snd_hdsp_get_wc_sync_check \
2907}
2908
Takashi Iwai55e957d2005-11-17 14:52:13 +01002909static int snd_hdsp_info_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910{
2911 static char *texts[] = {"No Lock", "Lock", "Sync" };
2912 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2913 uinfo->count = 1;
2914 uinfo->value.enumerated.items = 3;
2915 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2916 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2917 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
2918 return 0;
2919}
2920
Takashi Iwai55e957d2005-11-17 14:52:13 +01002921static int hdsp_wc_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922{
2923 int status2 = hdsp_read(hdsp, HDSP_status2Register);
2924 if (status2 & HDSP_wc_lock) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002925 if (status2 & HDSP_wc_sync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002927 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002929 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002931 return 0;
2932}
2933
Takashi Iwai55e957d2005-11-17 14:52:13 +01002934static int snd_hdsp_get_wc_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002936 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937
2938 ucontrol->value.enumerated.item[0] = hdsp_wc_sync_check(hdsp);
2939 return 0;
2940}
2941
2942#define HDSP_SPDIF_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002943{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944 .name = xname, \
2945 .index = xindex, \
2946 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2947 .info = snd_hdsp_info_sync_check, \
2948 .get = snd_hdsp_get_spdif_sync_check \
2949}
2950
Takashi Iwai55e957d2005-11-17 14:52:13 +01002951static int hdsp_spdif_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952{
2953 int status = hdsp_read(hdsp, HDSP_statusRegister);
Takashi Iwaib0b98112005-10-20 18:29:58 +02002954 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955 return 0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002956 else {
2957 if (status & HDSP_SPDIFSync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002959 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961 }
2962 return 0;
2963}
2964
Takashi Iwai55e957d2005-11-17 14:52:13 +01002965static int snd_hdsp_get_spdif_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002967 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968
2969 ucontrol->value.enumerated.item[0] = hdsp_spdif_sync_check(hdsp);
2970 return 0;
2971}
2972
2973#define HDSP_ADATSYNC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002974{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975 .name = xname, \
2976 .index = xindex, \
2977 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2978 .info = snd_hdsp_info_sync_check, \
2979 .get = snd_hdsp_get_adatsync_sync_check \
2980}
2981
Takashi Iwai55e957d2005-11-17 14:52:13 +01002982static int hdsp_adatsync_sync_check(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983{
2984 int status = hdsp_read(hdsp, HDSP_statusRegister);
2985 if (status & HDSP_TimecodeLock) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02002986 if (status & HDSP_TimecodeSync)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002988 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02002990 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992}
2993
Takashi Iwai55e957d2005-11-17 14:52:13 +01002994static int snd_hdsp_get_adatsync_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995{
Takashi Iwai55e957d2005-11-17 14:52:13 +01002996 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997
2998 ucontrol->value.enumerated.item[0] = hdsp_adatsync_sync_check(hdsp);
2999 return 0;
3000}
3001
3002#define HDSP_ADAT_SYNC_CHECK \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003003{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3005 .info = snd_hdsp_info_sync_check, \
3006 .get = snd_hdsp_get_adat_sync_check \
3007}
3008
Takashi Iwai55e957d2005-11-17 14:52:13 +01003009static int hdsp_adat_sync_check(struct hdsp *hdsp, int idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010{
3011 int status = hdsp_read(hdsp, HDSP_statusRegister);
3012
3013 if (status & (HDSP_Lock0>>idx)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003014 if (status & (HDSP_Sync0>>idx))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 return 2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003016 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 return 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003018 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020}
3021
Takashi Iwai55e957d2005-11-17 14:52:13 +01003022static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023{
3024 int offset;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003025 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026
3027 offset = ucontrol->id.index - 1;
3028 snd_assert(offset >= 0);
3029
3030 switch (hdsp->io_type) {
3031 case Digiface:
3032 case H9652:
3033 if (offset >= 3)
3034 return -EINVAL;
3035 break;
3036 case Multiface:
3037 case H9632:
3038 if (offset >= 1)
3039 return -EINVAL;
3040 break;
3041 default:
3042 return -EIO;
3043 }
3044
3045 ucontrol->value.enumerated.item[0] = hdsp_adat_sync_check(hdsp, offset);
3046 return 0;
3047}
3048
Julian Cablee4b60882007-03-19 11:44:40 +01003049#define HDSP_DDS_OFFSET(xname, xindex) \
3050{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3051 .name = xname, \
3052 .index = xindex, \
3053 .info = snd_hdsp_info_dds_offset, \
3054 .get = snd_hdsp_get_dds_offset, \
3055 .put = snd_hdsp_put_dds_offset \
3056}
3057
3058static int hdsp_dds_offset(struct hdsp *hdsp)
3059{
3060 u64 n;
3061 u32 r;
3062 unsigned int dds_value = hdsp->dds_value;
3063 int system_sample_rate = hdsp->system_sample_rate;
3064
Takashi Iwai2a3988f2007-10-16 14:26:32 +02003065 if (!dds_value)
3066 return 0;
3067
Julian Cablee4b60882007-03-19 11:44:40 +01003068 n = DDS_NUMERATOR;
3069 /*
3070 * dds_value = n / rate
3071 * rate = n / dds_value
3072 */
3073 div64_32(&n, dds_value, &r);
3074 if (system_sample_rate >= 112000)
3075 n *= 4;
3076 else if (system_sample_rate >= 56000)
3077 n *= 2;
3078 return ((int)n) - system_sample_rate;
3079}
3080
3081static int hdsp_set_dds_offset(struct hdsp *hdsp, int offset_hz)
3082{
3083 int rate = hdsp->system_sample_rate + offset_hz;
3084 hdsp_set_dds_value(hdsp, rate);
3085 return 0;
3086}
3087
3088static int snd_hdsp_info_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
3089{
3090 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3091 uinfo->count = 1;
3092 uinfo->value.integer.min = -5000;
3093 uinfo->value.integer.max = 5000;
3094 return 0;
3095}
3096
3097static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3098{
3099 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3100
3101 ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp);
3102 return 0;
3103}
3104
3105static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
3106{
3107 struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
3108 int change;
3109 int val;
3110
3111 if (!snd_hdsp_use_is_exclusive(hdsp))
3112 return -EBUSY;
3113 val = ucontrol->value.enumerated.item[0];
3114 spin_lock_irq(&hdsp->lock);
3115 if (val != hdsp_dds_offset(hdsp))
3116 change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0;
3117 else
3118 change = 0;
3119 spin_unlock_irq(&hdsp->lock);
3120 return change;
3121}
3122
Takashi Iwai55e957d2005-11-17 14:52:13 +01003123static struct snd_kcontrol_new snd_hdsp_9632_controls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124HDSP_DA_GAIN("DA Gain", 0),
3125HDSP_AD_GAIN("AD Gain", 0),
3126HDSP_PHONE_GAIN("Phones Gain", 0),
Julian Cablee4b60882007-03-19 11:44:40 +01003127HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0),
3128HDSP_DDS_OFFSET("DDS Sample Rate Offset", 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129};
3130
Takashi Iwai55e957d2005-11-17 14:52:13 +01003131static struct snd_kcontrol_new snd_hdsp_controls[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132{
Clemens Ladisch5549d542005-08-03 13:50:30 +02003133 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
3135 .info = snd_hdsp_control_spdif_info,
3136 .get = snd_hdsp_control_spdif_get,
3137 .put = snd_hdsp_control_spdif_put,
3138},
3139{
3140 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch5549d542005-08-03 13:50:30 +02003141 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
3143 .info = snd_hdsp_control_spdif_stream_info,
3144 .get = snd_hdsp_control_spdif_stream_get,
3145 .put = snd_hdsp_control_spdif_stream_put,
3146},
3147{
3148 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +02003149 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
3151 .info = snd_hdsp_control_spdif_mask_info,
3152 .get = snd_hdsp_control_spdif_mask_get,
3153 .private_value = IEC958_AES0_NONAUDIO |
3154 IEC958_AES0_PROFESSIONAL |
3155 IEC958_AES0_CON_EMPHASIS,
3156},
3157{
3158 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +02003159 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
3161 .info = snd_hdsp_control_spdif_mask_info,
3162 .get = snd_hdsp_control_spdif_mask_get,
3163 .private_value = IEC958_AES0_NONAUDIO |
3164 IEC958_AES0_PROFESSIONAL |
3165 IEC958_AES0_PRO_EMPHASIS,
3166},
3167HDSP_MIXER("Mixer", 0),
3168HDSP_SPDIF_IN("IEC958 Input Connector", 0),
3169HDSP_SPDIF_OUT("IEC958 Output also on ADAT1", 0),
3170HDSP_SPDIF_PROFESSIONAL("IEC958 Professional Bit", 0),
3171HDSP_SPDIF_EMPHASIS("IEC958 Emphasis Bit", 0),
3172HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0),
3173/* 'Sample Clock Source' complies with the alsa control naming scheme */
3174HDSP_CLOCK_SOURCE("Sample Clock Source", 0),
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003175{
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003176 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3177 .name = "Sample Clock Source Locking",
3178 .info = snd_hdsp_info_clock_source_lock,
3179 .get = snd_hdsp_get_clock_source_lock,
3180 .put = snd_hdsp_put_clock_source_lock,
3181},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182HDSP_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
3183HDSP_PREF_SYNC_REF("Preferred Sync Reference", 0),
3184HDSP_AUTOSYNC_REF("AutoSync Reference", 0),
3185HDSP_SPDIF_SAMPLE_RATE("SPDIF Sample Rate", 0),
3186HDSP_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
3187/* 'External Rate' complies with the alsa control naming scheme */
3188HDSP_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
3189HDSP_WC_SYNC_CHECK("Word Clock Lock Status", 0),
3190HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0),
3191HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0),
3192HDSP_LINE_OUT("Line Out", 0),
3193HDSP_PRECISE_POINTER("Precise Pointer", 0),
3194HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0),
3195};
3196
Takashi Iwai55e957d2005-11-17 14:52:13 +01003197static struct snd_kcontrol_new snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0);
3198static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003199
Takashi Iwai55e957d2005-11-17 14:52:13 +01003200static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201{
3202 unsigned int idx;
3203 int err;
Takashi Iwai55e957d2005-11-17 14:52:13 +01003204 struct snd_kcontrol *kctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205
3206 for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003207 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003209 if (idx == 1) /* IEC958 (S/PDIF) Stream */
3210 hdsp->spdif_ctl = kctl;
3211 }
3212
3213 /* ADAT SyncCheck status */
3214 snd_hdsp_adat_sync_check.name = "ADAT Lock Status";
3215 snd_hdsp_adat_sync_check.index = 1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003216 if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218 if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
3219 for (idx = 1; idx < 3; ++idx) {
3220 snd_hdsp_adat_sync_check.index = idx+1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003221 if ((err = snd_ctl_add (card, kctl = snd_ctl_new1(&snd_hdsp_adat_sync_check, hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003223 }
3224 }
3225
3226 /* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */
3227 if (hdsp->io_type == H9632) {
3228 for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003229 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231 }
3232 }
3233
3234 /* AEB control for H96xx card */
3235 if (hdsp->io_type == H9632 || hdsp->io_type == H9652) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003236 if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp))) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238 }
3239
3240 return 0;
3241}
3242
3243/*------------------------------------------------------------
3244 /proc interface
3245 ------------------------------------------------------------*/
3246
3247static void
Takashi Iwai55e957d2005-11-17 14:52:13 +01003248snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003250 struct hdsp *hdsp = (struct hdsp *) entry->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251 unsigned int status;
3252 unsigned int status2;
3253 char *pref_sync_ref;
3254 char *autosync_ref;
3255 char *system_clock_mode;
3256 char *clock_source;
3257 int x;
3258
Remy Brunoecb594e2006-06-12 09:25:22 +02003259 if (hdsp_check_for_iobox (hdsp)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260 snd_iprintf(buffer, "No I/O box connected.\nPlease connect one and upload firmware.\n");
3261 return;
Remy Brunoecb594e2006-06-12 09:25:22 +02003262 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263
Takashi Iwaib0b98112005-10-20 18:29:58 +02003264 if (hdsp_check_for_firmware(hdsp, 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265 if (hdsp->state & HDSP_FirmwareCached) {
3266 if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
3267 snd_iprintf(buffer, "Firmware loading from cache failed, please upload manually.\n");
3268 return;
3269 }
3270 } else {
Takashi Iwai311e70a2006-09-06 12:13:37 +02003271 int err = -EINVAL;
3272#ifdef HDSP_FW_LOADER
3273 err = hdsp_request_fw_loader(hdsp);
3274#endif
3275 if (err < 0) {
3276 snd_iprintf(buffer,
3277 "No firmware loaded nor cached, "
3278 "please upload firmware.\n");
3279 return;
3280 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281 }
3282 }
3283
3284 status = hdsp_read(hdsp, HDSP_statusRegister);
3285 status2 = hdsp_read(hdsp, HDSP_status2Register);
3286
3287 snd_iprintf(buffer, "%s (Card #%d)\n", hdsp->card_name, hdsp->card->number + 1);
3288 snd_iprintf(buffer, "Buffers: capture %p playback %p\n",
3289 hdsp->capture_buffer, hdsp->playback_buffer);
3290 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
3291 hdsp->irq, hdsp->port, (unsigned long)hdsp->iobase);
3292 snd_iprintf(buffer, "Control register: 0x%x\n", hdsp->control_register);
3293 snd_iprintf(buffer, "Control2 register: 0x%x\n", hdsp->control2_register);
3294 snd_iprintf(buffer, "Status register: 0x%x\n", status);
3295 snd_iprintf(buffer, "Status2 register: 0x%x\n", status2);
3296 snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff);
3297 snd_iprintf(buffer, "MIDI1 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut0));
3298 snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0));
3299 snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1));
3300 snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1));
3301 snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off");
3302
3303 snd_iprintf(buffer, "\n");
3304
3305 x = 1 << (6 + hdsp_decode_latency(hdsp->control_register & HDSP_LatencyMask));
3306
3307 snd_iprintf(buffer, "Buffer Size (Latency): %d samples (2 periods of %lu bytes)\n", x, (unsigned long) hdsp->period_bytes);
3308 snd_iprintf(buffer, "Hardware pointer (frames): %ld\n", hdsp_hw_pointer(hdsp));
3309 snd_iprintf(buffer, "Precise pointer: %s\n", hdsp->precise_ptr ? "on" : "off");
3310 snd_iprintf(buffer, "Line out: %s\n", (hdsp->control_register & HDSP_LineOut) ? "on" : "off");
3311
3312 snd_iprintf(buffer, "Firmware version: %d\n", (status2&HDSP_version0)|(status2&HDSP_version1)<<1|(status2&HDSP_version2)<<2);
3313
3314 snd_iprintf(buffer, "\n");
3315
3316
3317 switch (hdsp_clock_source(hdsp)) {
3318 case HDSP_CLOCK_SOURCE_AUTOSYNC:
3319 clock_source = "AutoSync";
3320 break;
3321 case HDSP_CLOCK_SOURCE_INTERNAL_32KHZ:
3322 clock_source = "Internal 32 kHz";
3323 break;
3324 case HDSP_CLOCK_SOURCE_INTERNAL_44_1KHZ:
3325 clock_source = "Internal 44.1 kHz";
3326 break;
3327 case HDSP_CLOCK_SOURCE_INTERNAL_48KHZ:
3328 clock_source = "Internal 48 kHz";
3329 break;
3330 case HDSP_CLOCK_SOURCE_INTERNAL_64KHZ:
3331 clock_source = "Internal 64 kHz";
3332 break;
3333 case HDSP_CLOCK_SOURCE_INTERNAL_88_2KHZ:
3334 clock_source = "Internal 88.2 kHz";
3335 break;
3336 case HDSP_CLOCK_SOURCE_INTERNAL_96KHZ:
3337 clock_source = "Internal 96 kHz";
3338 break;
3339 case HDSP_CLOCK_SOURCE_INTERNAL_128KHZ:
3340 clock_source = "Internal 128 kHz";
3341 break;
3342 case HDSP_CLOCK_SOURCE_INTERNAL_176_4KHZ:
3343 clock_source = "Internal 176.4 kHz";
3344 break;
3345 case HDSP_CLOCK_SOURCE_INTERNAL_192KHZ:
3346 clock_source = "Internal 192 kHz";
3347 break;
3348 default:
3349 clock_source = "Error";
3350 }
3351 snd_iprintf (buffer, "Sample Clock Source: %s\n", clock_source);
3352
Takashi Iwaib0b98112005-10-20 18:29:58 +02003353 if (hdsp_system_clock_mode(hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354 system_clock_mode = "Slave";
Takashi Iwaib0b98112005-10-20 18:29:58 +02003355 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356 system_clock_mode = "Master";
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357
3358 switch (hdsp_pref_sync_ref (hdsp)) {
3359 case HDSP_SYNC_FROM_WORD:
3360 pref_sync_ref = "Word Clock";
3361 break;
3362 case HDSP_SYNC_FROM_ADAT_SYNC:
3363 pref_sync_ref = "ADAT Sync";
3364 break;
3365 case HDSP_SYNC_FROM_SPDIF:
3366 pref_sync_ref = "SPDIF";
3367 break;
3368 case HDSP_SYNC_FROM_ADAT1:
3369 pref_sync_ref = "ADAT1";
3370 break;
3371 case HDSP_SYNC_FROM_ADAT2:
3372 pref_sync_ref = "ADAT2";
3373 break;
3374 case HDSP_SYNC_FROM_ADAT3:
3375 pref_sync_ref = "ADAT3";
3376 break;
3377 default:
3378 pref_sync_ref = "Word Clock";
3379 break;
3380 }
3381 snd_iprintf (buffer, "Preferred Sync Reference: %s\n", pref_sync_ref);
3382
3383 switch (hdsp_autosync_ref (hdsp)) {
3384 case HDSP_AUTOSYNC_FROM_WORD:
3385 autosync_ref = "Word Clock";
3386 break;
3387 case HDSP_AUTOSYNC_FROM_ADAT_SYNC:
3388 autosync_ref = "ADAT Sync";
3389 break;
3390 case HDSP_AUTOSYNC_FROM_SPDIF:
3391 autosync_ref = "SPDIF";
3392 break;
3393 case HDSP_AUTOSYNC_FROM_NONE:
3394 autosync_ref = "None";
3395 break;
3396 case HDSP_AUTOSYNC_FROM_ADAT1:
3397 autosync_ref = "ADAT1";
3398 break;
3399 case HDSP_AUTOSYNC_FROM_ADAT2:
3400 autosync_ref = "ADAT2";
3401 break;
3402 case HDSP_AUTOSYNC_FROM_ADAT3:
3403 autosync_ref = "ADAT3";
3404 break;
3405 default:
3406 autosync_ref = "---";
3407 break;
3408 }
3409 snd_iprintf (buffer, "AutoSync Reference: %s\n", autosync_ref);
3410
3411 snd_iprintf (buffer, "AutoSync Frequency: %d\n", hdsp_external_sample_rate(hdsp));
3412
3413 snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode);
3414
3415 snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003416 snd_iprintf (buffer, "System Clock Locked: %s\n", hdsp->clock_source_locked ? "Yes" : "No");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417
3418 snd_iprintf(buffer, "\n");
3419
3420 switch (hdsp_spdif_in(hdsp)) {
3421 case HDSP_SPDIFIN_OPTICAL:
3422 snd_iprintf(buffer, "IEC958 input: Optical\n");
3423 break;
3424 case HDSP_SPDIFIN_COAXIAL:
3425 snd_iprintf(buffer, "IEC958 input: Coaxial\n");
3426 break;
3427 case HDSP_SPDIFIN_INTERNAL:
3428 snd_iprintf(buffer, "IEC958 input: Internal\n");
3429 break;
3430 case HDSP_SPDIFIN_AES:
3431 snd_iprintf(buffer, "IEC958 input: AES\n");
3432 break;
3433 default:
3434 snd_iprintf(buffer, "IEC958 input: ???\n");
3435 break;
3436 }
3437
Takashi Iwaib0b98112005-10-20 18:29:58 +02003438 if (hdsp->control_register & HDSP_SPDIFOpticalOut)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439 snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003440 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441 snd_iprintf(buffer, "IEC958 output: Coaxial only\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003442
Takashi Iwaib0b98112005-10-20 18:29:58 +02003443 if (hdsp->control_register & HDSP_SPDIFProfessional)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444 snd_iprintf(buffer, "IEC958 quality: Professional\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003445 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446 snd_iprintf(buffer, "IEC958 quality: Consumer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447
Takashi Iwaib0b98112005-10-20 18:29:58 +02003448 if (hdsp->control_register & HDSP_SPDIFEmphasis)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449 snd_iprintf(buffer, "IEC958 emphasis: on\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003450 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451 snd_iprintf(buffer, "IEC958 emphasis: off\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452
Takashi Iwaib0b98112005-10-20 18:29:58 +02003453 if (hdsp->control_register & HDSP_SPDIFNonAudio)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454 snd_iprintf(buffer, "IEC958 NonAudio: on\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003455 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456 snd_iprintf(buffer, "IEC958 NonAudio: off\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003457 if ((x = hdsp_spdif_sample_rate (hdsp)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458 snd_iprintf (buffer, "IEC958 sample rate: %d\n", x);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003459 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460 snd_iprintf (buffer, "IEC958 sample rate: Error flag set\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461
3462 snd_iprintf(buffer, "\n");
3463
3464 /* Sync Check */
3465 x = status & HDSP_Sync0;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003466 if (status & HDSP_Lock0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467 snd_iprintf(buffer, "ADAT1: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003468 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469 snd_iprintf(buffer, "ADAT1: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470
3471 switch (hdsp->io_type) {
3472 case Digiface:
3473 case H9652:
3474 x = status & HDSP_Sync1;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003475 if (status & HDSP_Lock1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476 snd_iprintf(buffer, "ADAT2: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003477 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478 snd_iprintf(buffer, "ADAT2: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479 x = status & HDSP_Sync2;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003480 if (status & HDSP_Lock2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481 snd_iprintf(buffer, "ADAT3: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003482 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483 snd_iprintf(buffer, "ADAT3: No Lock\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003484 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485 default:
3486 /* relax */
3487 break;
3488 }
3489
3490 x = status & HDSP_SPDIFSync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003491 if (status & HDSP_SPDIFErrorFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492 snd_iprintf (buffer, "SPDIF: No Lock\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003493 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494 snd_iprintf (buffer, "SPDIF: %s\n", x ? "Sync" : "Lock");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003495
3496 x = status2 & HDSP_wc_sync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003497 if (status2 & HDSP_wc_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498 snd_iprintf (buffer, "Word Clock: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003499 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 snd_iprintf (buffer, "Word Clock: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501
3502 x = status & HDSP_TimecodeSync;
Takashi Iwaib0b98112005-10-20 18:29:58 +02003503 if (status & HDSP_TimecodeLock)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504 snd_iprintf(buffer, "ADAT Sync: %s\n", x ? "Sync" : "Lock");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003505 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 snd_iprintf(buffer, "ADAT Sync: No Lock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507
3508 snd_iprintf(buffer, "\n");
3509
3510 /* Informations about H9632 specific controls */
3511 if (hdsp->io_type == H9632) {
3512 char *tmp;
3513
3514 switch (hdsp_ad_gain(hdsp)) {
3515 case 0:
3516 tmp = "-10 dBV";
3517 break;
3518 case 1:
3519 tmp = "+4 dBu";
3520 break;
3521 default:
3522 tmp = "Lo Gain";
3523 break;
3524 }
3525 snd_iprintf(buffer, "AD Gain : %s\n", tmp);
3526
3527 switch (hdsp_da_gain(hdsp)) {
3528 case 0:
3529 tmp = "Hi Gain";
3530 break;
3531 case 1:
3532 tmp = "+4 dBu";
3533 break;
3534 default:
3535 tmp = "-10 dBV";
3536 break;
3537 }
3538 snd_iprintf(buffer, "DA Gain : %s\n", tmp);
3539
3540 switch (hdsp_phone_gain(hdsp)) {
3541 case 0:
3542 tmp = "0 dB";
3543 break;
3544 case 1:
3545 tmp = "-6 dB";
3546 break;
3547 default:
3548 tmp = "-12 dB";
3549 break;
3550 }
3551 snd_iprintf(buffer, "Phones Gain : %s\n", tmp);
3552
3553 snd_iprintf(buffer, "XLR Breakout Cable : %s\n", hdsp_xlr_breakout_cable(hdsp) ? "yes" : "no");
3554
Takashi Iwaib0b98112005-10-20 18:29:58 +02003555 if (hdsp->control_register & HDSP_AnalogExtensionBoard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003556 snd_iprintf(buffer, "AEB : on (ADAT1 internal)\n");
Takashi Iwaib0b98112005-10-20 18:29:58 +02003557 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558 snd_iprintf(buffer, "AEB : off (ADAT1 external)\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003559 snd_iprintf(buffer, "\n");
3560 }
3561
3562}
3563
Randy Dunlap1374f8c2008-01-16 14:55:42 +01003564static void snd_hdsp_proc_init(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003566 struct snd_info_entry *entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003567
3568 if (! snd_card_proc_new(hdsp->card, "hdsp", &entry))
Takashi Iwaibf850202006-04-28 15:13:41 +02003569 snd_info_set_text_ops(entry, hdsp, snd_hdsp_proc_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003570}
3571
Takashi Iwai55e957d2005-11-17 14:52:13 +01003572static void snd_hdsp_free_buffers(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573{
3574 snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci);
3575 snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
3576}
3577
Takashi Iwai55e957d2005-11-17 14:52:13 +01003578static int __devinit snd_hdsp_initialize_memory(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579{
3580 unsigned long pb_bus, cb_bus;
3581
3582 if (snd_hammerfall_get_buffer(hdsp->pci, &hdsp->capture_dma_buf, HDSP_DMA_AREA_BYTES) < 0 ||
3583 snd_hammerfall_get_buffer(hdsp->pci, &hdsp->playback_dma_buf, HDSP_DMA_AREA_BYTES) < 0) {
3584 if (hdsp->capture_dma_buf.area)
3585 snd_dma_free_pages(&hdsp->capture_dma_buf);
3586 printk(KERN_ERR "%s: no buffers available\n", hdsp->card_name);
3587 return -ENOMEM;
3588 }
3589
3590 /* Align to bus-space 64K boundary */
3591
Clemens Ladisch7ab39922006-10-09 08:13:32 +02003592 cb_bus = ALIGN(hdsp->capture_dma_buf.addr, 0x10000ul);
3593 pb_bus = ALIGN(hdsp->playback_dma_buf.addr, 0x10000ul);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003594
3595 /* Tell the card where it is */
3596
3597 hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus);
3598 hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus);
3599
3600 hdsp->capture_buffer = hdsp->capture_dma_buf.area + (cb_bus - hdsp->capture_dma_buf.addr);
3601 hdsp->playback_buffer = hdsp->playback_dma_buf.area + (pb_bus - hdsp->playback_dma_buf.addr);
3602
3603 return 0;
3604}
3605
Takashi Iwai55e957d2005-11-17 14:52:13 +01003606static int snd_hdsp_set_defaults(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607{
3608 unsigned int i;
3609
3610 /* ASSUMPTION: hdsp->lock is either held, or
3611 there is no need to hold it (e.g. during module
Joe Perches561de312007-12-18 13:13:47 +01003612 initialization).
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613 */
3614
3615 /* set defaults:
3616
3617 SPDIF Input via Coax
3618 Master clock mode
3619 maximum latency (7 => 2^7 = 8192 samples, 64Kbyte buffer,
3620 which implies 2 4096 sample, 32Kbyte periods).
3621 Enable line out.
3622 */
3623
3624 hdsp->control_register = HDSP_ClockModeMaster |
3625 HDSP_SPDIFInputCoaxial |
3626 hdsp_encode_latency(7) |
3627 HDSP_LineOut;
3628
3629
3630 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3631
3632#ifdef SNDRV_BIG_ENDIAN
3633 hdsp->control2_register = HDSP_BIGENDIAN_MODE;
3634#else
3635 hdsp->control2_register = 0;
3636#endif
Takashi Iwaib0b98112005-10-20 18:29:58 +02003637 if (hdsp->io_type == H9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638 snd_hdsp_9652_enable_mixer (hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003639 else
3640 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641
3642 hdsp_reset_hw_pointer(hdsp);
3643 hdsp_compute_period_size(hdsp);
3644
3645 /* silence everything */
3646
Takashi Iwaib0b98112005-10-20 18:29:58 +02003647 for (i = 0; i < HDSP_MATRIX_MIXER_SIZE; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648 hdsp->mixer_matrix[i] = MINUS_INFINITY_GAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649
3650 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 +02003651 if (hdsp_write_gain (hdsp, i, MINUS_INFINITY_GAIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003652 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653 }
3654
3655 /* H9632 specific defaults */
3656 if (hdsp->io_type == H9632) {
3657 hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB);
3658 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3659 }
3660
3661 /* set a default rate so that the channel map is set up.
3662 */
3663
3664 hdsp_set_rate(hdsp, 48000, 1);
3665
3666 return 0;
3667}
3668
3669static void hdsp_midi_tasklet(unsigned long arg)
3670{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003671 struct hdsp *hdsp = (struct hdsp *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672
Takashi Iwaib0b98112005-10-20 18:29:58 +02003673 if (hdsp->midi[0].pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674 snd_hdsp_midi_input_read (&hdsp->midi[0]);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003675 if (hdsp->midi[1].pending)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003676 snd_hdsp_midi_input_read (&hdsp->midi[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677}
3678
David Howells7d12e782006-10-05 14:55:46 +01003679static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003681 struct hdsp *hdsp = (struct hdsp *) dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682 unsigned int status;
3683 int audio;
3684 int midi0;
3685 int midi1;
3686 unsigned int midi0status;
3687 unsigned int midi1status;
3688 int schedule = 0;
3689
3690 status = hdsp_read(hdsp, HDSP_statusRegister);
3691
3692 audio = status & HDSP_audioIRQPending;
3693 midi0 = status & HDSP_midi0IRQPending;
3694 midi1 = status & HDSP_midi1IRQPending;
3695
Takashi Iwaib0b98112005-10-20 18:29:58 +02003696 if (!audio && !midi0 && !midi1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697 return IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698
3699 hdsp_write(hdsp, HDSP_interruptConfirmation, 0);
3700
3701 midi0status = hdsp_read (hdsp, HDSP_midiStatusIn0) & 0xff;
3702 midi1status = hdsp_read (hdsp, HDSP_midiStatusIn1) & 0xff;
3703
3704 if (audio) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02003705 if (hdsp->capture_substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707
Takashi Iwaib0b98112005-10-20 18:29:58 +02003708 if (hdsp->playback_substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709 snd_pcm_period_elapsed(hdsp->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710 }
3711
3712 if (midi0 && midi0status) {
3713 if (hdsp->use_midi_tasklet) {
3714 /* we disable interrupts for this input until processing is done */
3715 hdsp->control_register &= ~HDSP_Midi0InterruptEnable;
3716 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3717 hdsp->midi[0].pending = 1;
3718 schedule = 1;
3719 } else {
3720 snd_hdsp_midi_input_read (&hdsp->midi[0]);
3721 }
3722 }
3723 if (hdsp->io_type != Multiface && hdsp->io_type != H9632 && midi1 && midi1status) {
3724 if (hdsp->use_midi_tasklet) {
3725 /* we disable interrupts for this input until processing is done */
3726 hdsp->control_register &= ~HDSP_Midi1InterruptEnable;
3727 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
3728 hdsp->midi[1].pending = 1;
3729 schedule = 1;
3730 } else {
3731 snd_hdsp_midi_input_read (&hdsp->midi[1]);
3732 }
3733 }
3734 if (hdsp->use_midi_tasklet && schedule)
3735 tasklet_hi_schedule(&hdsp->midi_tasklet);
3736 return IRQ_HANDLED;
3737}
3738
Takashi Iwai55e957d2005-11-17 14:52:13 +01003739static snd_pcm_uframes_t snd_hdsp_hw_pointer(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003741 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742 return hdsp_hw_pointer(hdsp);
3743}
3744
Takashi Iwai55e957d2005-11-17 14:52:13 +01003745static char *hdsp_channel_buffer_location(struct hdsp *hdsp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746 int stream,
3747 int channel)
3748
3749{
3750 int mapped_channel;
3751
3752 snd_assert(channel >= 0 && channel < hdsp->max_channels, return NULL);
3753
Takashi Iwaib0b98112005-10-20 18:29:58 +02003754 if ((mapped_channel = hdsp->channel_map[channel]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003756
Takashi Iwaib0b98112005-10-20 18:29:58 +02003757 if (stream == SNDRV_PCM_STREAM_CAPTURE)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758 return hdsp->capture_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
Takashi Iwaib0b98112005-10-20 18:29:58 +02003759 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 return hdsp->playback_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003761}
3762
Takashi Iwai55e957d2005-11-17 14:52:13 +01003763static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764 snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
3765{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003766 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003767 char *channel_buf;
3768
3769 snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
3770
3771 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
3772 snd_assert(channel_buf != NULL, return -EIO);
3773 if (copy_from_user(channel_buf + pos * 4, src, count * 4))
3774 return -EFAULT;
3775 return count;
3776}
3777
Takashi Iwai55e957d2005-11-17 14:52:13 +01003778static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779 snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count)
3780{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003781 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782 char *channel_buf;
3783
3784 snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
3785
3786 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
3787 snd_assert(channel_buf != NULL, return -EIO);
3788 if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
3789 return -EFAULT;
3790 return count;
3791}
3792
Takashi Iwai55e957d2005-11-17 14:52:13 +01003793static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794 snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
3795{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003796 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797 char *channel_buf;
3798
3799 channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
3800 snd_assert(channel_buf != NULL, return -EIO);
3801 memset(channel_buf + pos * 4, 0, count * 4);
3802 return count;
3803}
3804
Takashi Iwai55e957d2005-11-17 14:52:13 +01003805static int snd_hdsp_reset(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003807 struct snd_pcm_runtime *runtime = substream->runtime;
3808 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
3809 struct snd_pcm_substream *other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3811 other = hdsp->capture_substream;
3812 else
3813 other = hdsp->playback_substream;
3814 if (hdsp->running)
3815 runtime->status->hw_ptr = hdsp_hw_pointer(hdsp);
3816 else
3817 runtime->status->hw_ptr = 0;
3818 if (other) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01003819 struct snd_pcm_substream *s;
3820 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01003821 snd_pcm_group_for_each_entry(s, substream) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822 if (s == other) {
3823 oruntime->status->hw_ptr = runtime->status->hw_ptr;
3824 break;
3825 }
3826 }
3827 }
3828 return 0;
3829}
3830
Takashi Iwai55e957d2005-11-17 14:52:13 +01003831static int snd_hdsp_hw_params(struct snd_pcm_substream *substream,
3832 struct snd_pcm_hw_params *params)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003834 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835 int err;
3836 pid_t this_pid;
3837 pid_t other_pid;
3838
Takashi Iwaib0b98112005-10-20 18:29:58 +02003839 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841
Takashi Iwaib0b98112005-10-20 18:29:58 +02003842 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844
3845 spin_lock_irq(&hdsp->lock);
3846
3847 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3848 hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
3849 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= hdsp->creg_spdif_stream);
3850 this_pid = hdsp->playback_pid;
3851 other_pid = hdsp->capture_pid;
3852 } else {
3853 this_pid = hdsp->capture_pid;
3854 other_pid = hdsp->playback_pid;
3855 }
3856
3857 if ((other_pid > 0) && (this_pid != other_pid)) {
3858
3859 /* The other stream is open, and not by the same
3860 task as this one. Make sure that the parameters
3861 that matter are the same.
3862 */
3863
3864 if (params_rate(params) != hdsp->system_sample_rate) {
3865 spin_unlock_irq(&hdsp->lock);
3866 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
3867 return -EBUSY;
3868 }
3869
3870 if (params_period_size(params) != hdsp->period_bytes / 4) {
3871 spin_unlock_irq(&hdsp->lock);
3872 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
3873 return -EBUSY;
3874 }
3875
3876 /* We're fine. */
3877
3878 spin_unlock_irq(&hdsp->lock);
3879 return 0;
3880
3881 } else {
3882 spin_unlock_irq(&hdsp->lock);
3883 }
3884
3885 /* how to make sure that the rate matches an externally-set one ?
3886 */
3887
3888 spin_lock_irq(&hdsp->lock);
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003889 if (! hdsp->clock_source_locked) {
3890 if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) {
3891 spin_unlock_irq(&hdsp->lock);
3892 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
3893 return err;
3894 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 }
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02003896 spin_unlock_irq(&hdsp->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897
3898 if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) {
3899 _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
3900 return err;
3901 }
3902
3903 return 0;
3904}
3905
Takashi Iwai55e957d2005-11-17 14:52:13 +01003906static int snd_hdsp_channel_info(struct snd_pcm_substream *substream,
3907 struct snd_pcm_channel_info *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003909 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910 int mapped_channel;
3911
3912 snd_assert(info->channel < hdsp->max_channels, return -EINVAL);
3913
Takashi Iwaib0b98112005-10-20 18:29:58 +02003914 if ((mapped_channel = hdsp->channel_map[info->channel]) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916
3917 info->offset = mapped_channel * HDSP_CHANNEL_BUFFER_BYTES;
3918 info->first = 0;
3919 info->step = 32;
3920 return 0;
3921}
3922
Takashi Iwai55e957d2005-11-17 14:52:13 +01003923static int snd_hdsp_ioctl(struct snd_pcm_substream *substream,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924 unsigned int cmd, void *arg)
3925{
3926 switch (cmd) {
3927 case SNDRV_PCM_IOCTL1_RESET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928 return snd_hdsp_reset(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Takashi Iwaib0b98112005-10-20 18:29:58 +02003930 return snd_hdsp_channel_info(substream, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931 default:
3932 break;
3933 }
3934
3935 return snd_pcm_lib_ioctl(substream, cmd, arg);
3936}
3937
Takashi Iwai55e957d2005-11-17 14:52:13 +01003938static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939{
Takashi Iwai55e957d2005-11-17 14:52:13 +01003940 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
3941 struct snd_pcm_substream *other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 int running;
3943
Takashi Iwaib0b98112005-10-20 18:29:58 +02003944 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946
Takashi Iwai311e70a2006-09-06 12:13:37 +02003947 if (hdsp_check_for_firmware(hdsp, 0)) /* no auto-loading in trigger */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949
3950 spin_lock(&hdsp->lock);
3951 running = hdsp->running;
3952 switch (cmd) {
3953 case SNDRV_PCM_TRIGGER_START:
3954 running |= 1 << substream->stream;
3955 break;
3956 case SNDRV_PCM_TRIGGER_STOP:
3957 running &= ~(1 << substream->stream);
3958 break;
3959 default:
3960 snd_BUG();
3961 spin_unlock(&hdsp->lock);
3962 return -EINVAL;
3963 }
3964 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3965 other = hdsp->capture_substream;
3966 else
3967 other = hdsp->playback_substream;
3968
3969 if (other) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01003970 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01003971 snd_pcm_group_for_each_entry(s, substream) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972 if (s == other) {
3973 snd_pcm_trigger_done(s, substream);
3974 if (cmd == SNDRV_PCM_TRIGGER_START)
3975 running |= 1 << s->stream;
3976 else
3977 running &= ~(1 << s->stream);
3978 goto _ok;
3979 }
3980 }
3981 if (cmd == SNDRV_PCM_TRIGGER_START) {
3982 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) &&
3983 substream->stream == SNDRV_PCM_STREAM_CAPTURE)
3984 hdsp_silence_playback(hdsp);
3985 } else {
3986 if (running &&
3987 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3988 hdsp_silence_playback(hdsp);
3989 }
3990 } else {
3991 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
3992 hdsp_silence_playback(hdsp);
3993 }
3994 _ok:
3995 snd_pcm_trigger_done(substream, substream);
3996 if (!hdsp->running && running)
3997 hdsp_start_audio(hdsp);
3998 else if (hdsp->running && !running)
3999 hdsp_stop_audio(hdsp);
4000 hdsp->running = running;
4001 spin_unlock(&hdsp->lock);
4002
4003 return 0;
4004}
4005
Takashi Iwai55e957d2005-11-17 14:52:13 +01004006static int snd_hdsp_prepare(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004008 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 int result = 0;
4010
Takashi Iwaib0b98112005-10-20 18:29:58 +02004011 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013
Takashi Iwaib0b98112005-10-20 18:29:58 +02004014 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016
4017 spin_lock_irq(&hdsp->lock);
4018 if (!hdsp->running)
4019 hdsp_reset_hw_pointer(hdsp);
4020 spin_unlock_irq(&hdsp->lock);
4021 return result;
4022}
4023
Takashi Iwai55e957d2005-11-17 14:52:13 +01004024static struct snd_pcm_hardware snd_hdsp_playback_subinfo =
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025{
4026 .info = (SNDRV_PCM_INFO_MMAP |
4027 SNDRV_PCM_INFO_MMAP_VALID |
4028 SNDRV_PCM_INFO_NONINTERLEAVED |
4029 SNDRV_PCM_INFO_SYNC_START |
4030 SNDRV_PCM_INFO_DOUBLE),
4031#ifdef SNDRV_BIG_ENDIAN
4032 .formats = SNDRV_PCM_FMTBIT_S32_BE,
4033#else
4034 .formats = SNDRV_PCM_FMTBIT_S32_LE,
4035#endif
4036 .rates = (SNDRV_PCM_RATE_32000 |
4037 SNDRV_PCM_RATE_44100 |
4038 SNDRV_PCM_RATE_48000 |
4039 SNDRV_PCM_RATE_64000 |
4040 SNDRV_PCM_RATE_88200 |
4041 SNDRV_PCM_RATE_96000),
4042 .rate_min = 32000,
4043 .rate_max = 96000,
4044 .channels_min = 14,
4045 .channels_max = HDSP_MAX_CHANNELS,
4046 .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS,
4047 .period_bytes_min = (64 * 4) * 10,
4048 .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS,
4049 .periods_min = 2,
4050 .periods_max = 2,
4051 .fifo_size = 0
4052};
4053
Takashi Iwai55e957d2005-11-17 14:52:13 +01004054static struct snd_pcm_hardware snd_hdsp_capture_subinfo =
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055{
4056 .info = (SNDRV_PCM_INFO_MMAP |
4057 SNDRV_PCM_INFO_MMAP_VALID |
4058 SNDRV_PCM_INFO_NONINTERLEAVED |
4059 SNDRV_PCM_INFO_SYNC_START),
4060#ifdef SNDRV_BIG_ENDIAN
4061 .formats = SNDRV_PCM_FMTBIT_S32_BE,
4062#else
4063 .formats = SNDRV_PCM_FMTBIT_S32_LE,
4064#endif
4065 .rates = (SNDRV_PCM_RATE_32000 |
4066 SNDRV_PCM_RATE_44100 |
4067 SNDRV_PCM_RATE_48000 |
4068 SNDRV_PCM_RATE_64000 |
4069 SNDRV_PCM_RATE_88200 |
4070 SNDRV_PCM_RATE_96000),
4071 .rate_min = 32000,
4072 .rate_max = 96000,
4073 .channels_min = 14,
4074 .channels_max = HDSP_MAX_CHANNELS,
4075 .buffer_bytes_max = HDSP_CHANNEL_BUFFER_BYTES * HDSP_MAX_CHANNELS,
4076 .period_bytes_min = (64 * 4) * 10,
4077 .period_bytes_max = (8192 * 4) * HDSP_MAX_CHANNELS,
4078 .periods_min = 2,
4079 .periods_max = 2,
4080 .fifo_size = 0
4081};
4082
4083static unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
4084
Takashi Iwai55e957d2005-11-17 14:52:13 +01004085static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_period_sizes = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086 .count = ARRAY_SIZE(hdsp_period_sizes),
4087 .list = hdsp_period_sizes,
4088 .mask = 0
4089};
4090
4091static unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 };
4092
Takashi Iwai55e957d2005-11-17 14:52:13 +01004093static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_9632_sample_rates = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094 .count = ARRAY_SIZE(hdsp_9632_sample_rates),
4095 .list = hdsp_9632_sample_rates,
4096 .mask = 0
4097};
4098
Takashi Iwai55e957d2005-11-17 14:52:13 +01004099static int snd_hdsp_hw_rule_in_channels(struct snd_pcm_hw_params *params,
4100 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004102 struct hdsp *hdsp = rule->private;
4103 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104 if (hdsp->io_type == H9632) {
4105 unsigned int list[3];
4106 list[0] = hdsp->qs_in_channels;
4107 list[1] = hdsp->ds_in_channels;
4108 list[2] = hdsp->ss_in_channels;
4109 return snd_interval_list(c, 3, list, 0);
4110 } else {
4111 unsigned int list[2];
4112 list[0] = hdsp->ds_in_channels;
4113 list[1] = hdsp->ss_in_channels;
4114 return snd_interval_list(c, 2, list, 0);
4115 }
4116}
4117
Takashi Iwai55e957d2005-11-17 14:52:13 +01004118static int snd_hdsp_hw_rule_out_channels(struct snd_pcm_hw_params *params,
4119 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120{
4121 unsigned int list[3];
Takashi Iwai55e957d2005-11-17 14:52:13 +01004122 struct hdsp *hdsp = rule->private;
4123 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124 if (hdsp->io_type == H9632) {
4125 list[0] = hdsp->qs_out_channels;
4126 list[1] = hdsp->ds_out_channels;
4127 list[2] = hdsp->ss_out_channels;
4128 return snd_interval_list(c, 3, list, 0);
4129 } else {
4130 list[0] = hdsp->ds_out_channels;
4131 list[1] = hdsp->ss_out_channels;
4132 }
4133 return snd_interval_list(c, 2, list, 0);
4134}
4135
Takashi Iwai55e957d2005-11-17 14:52:13 +01004136static int snd_hdsp_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
4137 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004139 struct hdsp *hdsp = rule->private;
4140 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4141 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004142 if (r->min > 96000 && 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 = hdsp->qs_in_channels,
4145 .max = hdsp->qs_in_channels,
4146 .integer = 1,
4147 };
4148 return snd_interval_refine(c, &t);
4149 } else if (r->min > 48000 && r->max <= 96000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004150 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151 .min = hdsp->ds_in_channels,
4152 .max = hdsp->ds_in_channels,
4153 .integer = 1,
4154 };
4155 return snd_interval_refine(c, &t);
4156 } else if (r->max < 64000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004157 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158 .min = hdsp->ss_in_channels,
4159 .max = hdsp->ss_in_channels,
4160 .integer = 1,
4161 };
4162 return snd_interval_refine(c, &t);
4163 }
4164 return 0;
4165}
4166
Takashi Iwai55e957d2005-11-17 14:52:13 +01004167static int snd_hdsp_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
4168 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004170 struct hdsp *hdsp = rule->private;
4171 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4172 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 if (r->min > 96000 && 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 = hdsp->qs_out_channels,
4176 .max = hdsp->qs_out_channels,
4177 .integer = 1,
4178 };
4179 return snd_interval_refine(c, &t);
4180 } else if (r->min > 48000 && r->max <= 96000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004181 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182 .min = hdsp->ds_out_channels,
4183 .max = hdsp->ds_out_channels,
4184 .integer = 1,
4185 };
4186 return snd_interval_refine(c, &t);
4187 } else if (r->max < 64000) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004188 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189 .min = hdsp->ss_out_channels,
4190 .max = hdsp->ss_out_channels,
4191 .integer = 1,
4192 };
4193 return snd_interval_refine(c, &t);
4194 }
4195 return 0;
4196}
4197
Takashi Iwai55e957d2005-11-17 14:52:13 +01004198static int snd_hdsp_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
4199 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004201 struct hdsp *hdsp = rule->private;
4202 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4203 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204 if (c->min >= hdsp->ss_out_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004205 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206 .min = 32000,
4207 .max = 48000,
4208 .integer = 1,
4209 };
4210 return snd_interval_refine(r, &t);
4211 } else if (c->max <= hdsp->qs_out_channels && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004212 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213 .min = 128000,
4214 .max = 192000,
4215 .integer = 1,
4216 };
4217 return snd_interval_refine(r, &t);
4218 } else if (c->max <= hdsp->ds_out_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004219 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004220 .min = 64000,
4221 .max = 96000,
4222 .integer = 1,
4223 };
4224 return snd_interval_refine(r, &t);
4225 }
4226 return 0;
4227}
4228
Takashi Iwai55e957d2005-11-17 14:52:13 +01004229static int snd_hdsp_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
4230 struct snd_pcm_hw_rule *rule)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004232 struct hdsp *hdsp = rule->private;
4233 struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
4234 struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235 if (c->min >= hdsp->ss_in_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004236 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237 .min = 32000,
4238 .max = 48000,
4239 .integer = 1,
4240 };
4241 return snd_interval_refine(r, &t);
4242 } else if (c->max <= hdsp->qs_in_channels && hdsp->io_type == H9632) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004243 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244 .min = 128000,
4245 .max = 192000,
4246 .integer = 1,
4247 };
4248 return snd_interval_refine(r, &t);
4249 } else if (c->max <= hdsp->ds_in_channels) {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004250 struct snd_interval t = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251 .min = 64000,
4252 .max = 96000,
4253 .integer = 1,
4254 };
4255 return snd_interval_refine(r, &t);
4256 }
4257 return 0;
4258}
4259
Takashi Iwai55e957d2005-11-17 14:52:13 +01004260static int snd_hdsp_playback_open(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004262 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4263 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264
Takashi Iwaib0b98112005-10-20 18:29:58 +02004265 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267
Takashi Iwaib0b98112005-10-20 18:29:58 +02004268 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270
4271 spin_lock_irq(&hdsp->lock);
4272
4273 snd_pcm_set_sync(substream);
4274
4275 runtime->hw = snd_hdsp_playback_subinfo;
4276 runtime->dma_area = hdsp->playback_buffer;
4277 runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
4278
4279 hdsp->playback_pid = current->pid;
4280 hdsp->playback_substream = substream;
4281
4282 spin_unlock_irq(&hdsp->lock);
4283
4284 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4285 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 +02004286 if (hdsp->clock_source_locked) {
4287 runtime->hw.rate_min = runtime->hw.rate_max = hdsp->system_sample_rate;
4288 } else if (hdsp->io_type == H9632) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289 runtime->hw.rate_max = 192000;
4290 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
4291 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates);
4292 }
Takashi Iwaie3ea4d82005-07-04 18:12:39 +02004293 if (hdsp->io_type == H9632) {
4294 runtime->hw.channels_min = hdsp->qs_out_channels;
4295 runtime->hw.channels_max = hdsp->ss_out_channels;
4296 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297
4298 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4299 snd_hdsp_hw_rule_out_channels, hdsp,
4300 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4301 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4302 snd_hdsp_hw_rule_out_channels_rate, hdsp,
4303 SNDRV_PCM_HW_PARAM_RATE, -1);
4304 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4305 snd_hdsp_hw_rule_rate_out_channels, hdsp,
4306 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4307
4308 hdsp->creg_spdif_stream = hdsp->creg_spdif;
4309 hdsp->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
4310 snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
4311 SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id);
4312 return 0;
4313}
4314
Takashi Iwai55e957d2005-11-17 14:52:13 +01004315static int snd_hdsp_playback_release(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004317 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318
4319 spin_lock_irq(&hdsp->lock);
4320
4321 hdsp->playback_pid = -1;
4322 hdsp->playback_substream = NULL;
4323
4324 spin_unlock_irq(&hdsp->lock);
4325
4326 hdsp->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
4327 snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
4328 SNDRV_CTL_EVENT_MASK_INFO, &hdsp->spdif_ctl->id);
4329 return 0;
4330}
4331
4332
Takashi Iwai55e957d2005-11-17 14:52:13 +01004333static int snd_hdsp_capture_open(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004335 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
4336 struct snd_pcm_runtime *runtime = substream->runtime;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337
Takashi Iwaib0b98112005-10-20 18:29:58 +02004338 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340
Takashi Iwaib0b98112005-10-20 18:29:58 +02004341 if (hdsp_check_for_firmware(hdsp, 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343
4344 spin_lock_irq(&hdsp->lock);
4345
4346 snd_pcm_set_sync(substream);
4347
4348 runtime->hw = snd_hdsp_capture_subinfo;
4349 runtime->dma_area = hdsp->capture_buffer;
4350 runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
4351
4352 hdsp->capture_pid = current->pid;
4353 hdsp->capture_substream = substream;
4354
4355 spin_unlock_irq(&hdsp->lock);
4356
4357 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4358 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes);
4359 if (hdsp->io_type == H9632) {
4360 runtime->hw.channels_min = hdsp->qs_in_channels;
4361 runtime->hw.channels_max = hdsp->ss_in_channels;
4362 runtime->hw.rate_max = 192000;
4363 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
4364 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates);
4365 }
4366 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4367 snd_hdsp_hw_rule_in_channels, hdsp,
4368 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4369 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4370 snd_hdsp_hw_rule_in_channels_rate, hdsp,
4371 SNDRV_PCM_HW_PARAM_RATE, -1);
4372 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4373 snd_hdsp_hw_rule_rate_in_channels, hdsp,
4374 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4375 return 0;
4376}
4377
Takashi Iwai55e957d2005-11-17 14:52:13 +01004378static int snd_hdsp_capture_release(struct snd_pcm_substream *substream)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004380 struct hdsp *hdsp = snd_pcm_substream_chip(substream);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004381
4382 spin_lock_irq(&hdsp->lock);
4383
4384 hdsp->capture_pid = -1;
4385 hdsp->capture_substream = NULL;
4386
4387 spin_unlock_irq(&hdsp->lock);
4388 return 0;
4389}
4390
Takashi Iwai55e957d2005-11-17 14:52:13 +01004391static int snd_hdsp_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004392{
4393 /* we have nothing to initialize but the call is required */
4394 return 0;
4395}
4396
4397
4398/* helper functions for copying meter values */
4399static inline int copy_u32_le(void __user *dest, void __iomem *src)
4400{
4401 u32 val = readl(src);
4402 return copy_to_user(dest, &val, 4);
4403}
4404
4405static inline int copy_u64_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
4406{
4407 u32 rms_low, rms_high;
4408 u64 rms;
4409 rms_low = readl(src_low);
4410 rms_high = readl(src_high);
4411 rms = ((u64)rms_high << 32) | rms_low;
4412 return copy_to_user(dest, &rms, 8);
4413}
4414
4415static inline int copy_u48_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
4416{
4417 u32 rms_low, rms_high;
4418 u64 rms;
4419 rms_low = readl(src_low) & 0xffffff00;
4420 rms_high = readl(src_high) & 0xffffff00;
4421 rms = ((u64)rms_high << 32) | rms_low;
4422 return copy_to_user(dest, &rms, 8);
4423}
4424
Takashi Iwai55e957d2005-11-17 14:52:13 +01004425static int hdsp_9652_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426{
4427 int doublespeed = 0;
4428 int i, j, channels, ofs;
4429
4430 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
4431 doublespeed = 1;
4432 channels = doublespeed ? 14 : 26;
4433 for (i = 0, j = 0; i < 26; ++i) {
4434 if (doublespeed && (i & 4))
4435 continue;
4436 ofs = HDSP_9652_peakBase - j * 4;
4437 if (copy_u32_le(&peak_rms->input_peaks[i], hdsp->iobase + ofs))
4438 return -EFAULT;
4439 ofs -= channels * 4;
4440 if (copy_u32_le(&peak_rms->playback_peaks[i], hdsp->iobase + ofs))
4441 return -EFAULT;
4442 ofs -= channels * 4;
4443 if (copy_u32_le(&peak_rms->output_peaks[i], hdsp->iobase + ofs))
4444 return -EFAULT;
4445 ofs = HDSP_9652_rmsBase + j * 8;
4446 if (copy_u48_le(&peak_rms->input_rms[i], hdsp->iobase + ofs,
4447 hdsp->iobase + ofs + 4))
4448 return -EFAULT;
4449 ofs += channels * 8;
4450 if (copy_u48_le(&peak_rms->playback_rms[i], hdsp->iobase + ofs,
4451 hdsp->iobase + ofs + 4))
4452 return -EFAULT;
4453 ofs += channels * 8;
4454 if (copy_u48_le(&peak_rms->output_rms[i], hdsp->iobase + ofs,
4455 hdsp->iobase + ofs + 4))
4456 return -EFAULT;
4457 j++;
4458 }
4459 return 0;
4460}
4461
Takashi Iwai55e957d2005-11-17 14:52:13 +01004462static int hdsp_9632_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004463{
4464 int i, j;
Takashi Iwai55e957d2005-11-17 14:52:13 +01004465 struct hdsp_9632_meters __iomem *m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466 int doublespeed = 0;
4467
4468 if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
4469 doublespeed = 1;
Takashi Iwai55e957d2005-11-17 14:52:13 +01004470 m = (struct hdsp_9632_meters __iomem *)(hdsp->iobase+HDSP_9632_metersBase);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004471 for (i = 0, j = 0; i < 16; ++i, ++j) {
4472 if (copy_u32_le(&peak_rms->input_peaks[i], &m->input_peak[j]))
4473 return -EFAULT;
4474 if (copy_u32_le(&peak_rms->playback_peaks[i], &m->playback_peak[j]))
4475 return -EFAULT;
4476 if (copy_u32_le(&peak_rms->output_peaks[i], &m->output_peak[j]))
4477 return -EFAULT;
4478 if (copy_u64_le(&peak_rms->input_rms[i], &m->input_rms_low[j],
4479 &m->input_rms_high[j]))
4480 return -EFAULT;
4481 if (copy_u64_le(&peak_rms->playback_rms[i], &m->playback_rms_low[j],
4482 &m->playback_rms_high[j]))
4483 return -EFAULT;
4484 if (copy_u64_le(&peak_rms->output_rms[i], &m->output_rms_low[j],
4485 &m->output_rms_high[j]))
4486 return -EFAULT;
4487 if (doublespeed && i == 3) i += 4;
4488 }
4489 return 0;
4490}
4491
Takashi Iwai55e957d2005-11-17 14:52:13 +01004492static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493{
4494 int i;
4495
4496 for (i = 0; i < 26; i++) {
4497 if (copy_u32_le(&peak_rms->playback_peaks[i],
4498 hdsp->iobase + HDSP_playbackPeakLevel + i * 4))
4499 return -EFAULT;
4500 if (copy_u32_le(&peak_rms->input_peaks[i],
4501 hdsp->iobase + HDSP_inputPeakLevel + i * 4))
4502 return -EFAULT;
4503 }
4504 for (i = 0; i < 28; i++) {
4505 if (copy_u32_le(&peak_rms->output_peaks[i],
4506 hdsp->iobase + HDSP_outputPeakLevel + i * 4))
4507 return -EFAULT;
4508 }
4509 for (i = 0; i < 26; ++i) {
4510 if (copy_u64_le(&peak_rms->playback_rms[i],
4511 hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4,
4512 hdsp->iobase + HDSP_playbackRmsLevel + i * 8))
4513 return -EFAULT;
4514 if (copy_u64_le(&peak_rms->input_rms[i],
4515 hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4,
4516 hdsp->iobase + HDSP_inputRmsLevel + i * 8))
4517 return -EFAULT;
4518 }
4519 return 0;
4520}
4521
Takashi Iwai55e957d2005-11-17 14:52:13 +01004522static 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 -07004523{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004524 struct hdsp *hdsp = (struct hdsp *)hw->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525 void __user *argp = (void __user *)arg;
4526
4527 switch (cmd) {
4528 case SNDRV_HDSP_IOCTL_GET_PEAK_RMS: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004529 struct hdsp_peak_rms __user *peak_rms = (struct hdsp_peak_rms __user *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530
4531 if (!(hdsp->state & HDSP_FirmwareLoaded)) {
4532 snd_printk(KERN_ERR "Hammerfall-DSP: firmware needs to be uploaded to the card.\n");
4533 return -EINVAL;
4534 }
4535
4536 switch (hdsp->io_type) {
4537 case H9652:
4538 return hdsp_9652_get_peak(hdsp, peak_rms);
4539 case H9632:
4540 return hdsp_9632_get_peak(hdsp, peak_rms);
4541 default:
4542 return hdsp_get_peak(hdsp, peak_rms);
4543 }
4544 }
4545 case SNDRV_HDSP_IOCTL_GET_CONFIG_INFO: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004546 struct hdsp_config_info info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004547 unsigned long flags;
4548 int i;
4549
4550 if (!(hdsp->state & HDSP_FirmwareLoaded)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004551 snd_printk(KERN_ERR "Hammerfall-DSP: Firmware needs to be uploaded to the card.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004552 return -EINVAL;
4553 }
4554 spin_lock_irqsave(&hdsp->lock, flags);
4555 info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp);
4556 info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02004557 if (hdsp->io_type != H9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558 info.adatsync_sync_check = (unsigned char)hdsp_adatsync_sync_check(hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004559 info.spdif_sync_check = (unsigned char)hdsp_spdif_sync_check(hdsp);
Takashi Iwaib0b98112005-10-20 18:29:58 +02004560 for (i = 0; i < ((hdsp->io_type != Multiface && hdsp->io_type != H9632) ? 3 : 1); ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004561 info.adat_sync_check[i] = (unsigned char)hdsp_adat_sync_check(hdsp, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004562 info.spdif_in = (unsigned char)hdsp_spdif_in(hdsp);
4563 info.spdif_out = (unsigned char)hdsp_spdif_out(hdsp);
4564 info.spdif_professional = (unsigned char)hdsp_spdif_professional(hdsp);
4565 info.spdif_emphasis = (unsigned char)hdsp_spdif_emphasis(hdsp);
4566 info.spdif_nonaudio = (unsigned char)hdsp_spdif_nonaudio(hdsp);
4567 info.spdif_sample_rate = hdsp_spdif_sample_rate(hdsp);
4568 info.system_sample_rate = hdsp->system_sample_rate;
4569 info.autosync_sample_rate = hdsp_external_sample_rate(hdsp);
4570 info.system_clock_mode = (unsigned char)hdsp_system_clock_mode(hdsp);
4571 info.clock_source = (unsigned char)hdsp_clock_source(hdsp);
4572 info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp);
4573 info.line_out = (unsigned char)hdsp_line_out(hdsp);
4574 if (hdsp->io_type == H9632) {
4575 info.da_gain = (unsigned char)hdsp_da_gain(hdsp);
4576 info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp);
4577 info.phone_gain = (unsigned char)hdsp_phone_gain(hdsp);
4578 info.xlr_breakout_cable = (unsigned char)hdsp_xlr_breakout_cable(hdsp);
4579
4580 }
Takashi Iwaib0b98112005-10-20 18:29:58 +02004581 if (hdsp->io_type == H9632 || hdsp->io_type == H9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004582 info.analog_extension_board = (unsigned char)hdsp_aeb(hdsp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004583 spin_unlock_irqrestore(&hdsp->lock, flags);
4584 if (copy_to_user(argp, &info, sizeof(info)))
4585 return -EFAULT;
4586 break;
4587 }
4588 case SNDRV_HDSP_IOCTL_GET_9632_AEB: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004589 struct hdsp_9632_aeb h9632_aeb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004590
4591 if (hdsp->io_type != H9632) return -EINVAL;
4592 h9632_aeb.aebi = hdsp->ss_in_channels - H9632_SS_CHANNELS;
4593 h9632_aeb.aebo = hdsp->ss_out_channels - H9632_SS_CHANNELS;
4594 if (copy_to_user(argp, &h9632_aeb, sizeof(h9632_aeb)))
4595 return -EFAULT;
4596 break;
4597 }
4598 case SNDRV_HDSP_IOCTL_GET_VERSION: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004599 struct hdsp_version hdsp_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004600 int err;
4601
4602 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
4603 if (hdsp->io_type == Undefined) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004604 if ((err = hdsp_get_iobox_version(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004605 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004606 }
4607 hdsp_version.io_type = hdsp->io_type;
4608 hdsp_version.firmware_rev = hdsp->firmware_rev;
Takashi Iwaib0b98112005-10-20 18:29:58 +02004609 if ((err = copy_to_user(argp, &hdsp_version, sizeof(hdsp_version))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004610 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004611 break;
4612 }
4613 case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004614 struct hdsp_firmware __user *firmware;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004615 u32 __user *firmware_data;
4616 int err;
4617
4618 if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
4619 /* SNDRV_HDSP_IOCTL_GET_VERSION must have been called */
4620 if (hdsp->io_type == Undefined) return -EINVAL;
4621
4622 if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded))
4623 return -EBUSY;
4624
Takashi Iwaib0b98112005-10-20 18:29:58 +02004625 snd_printk(KERN_INFO "Hammerfall-DSP: initializing firmware upload\n");
Takashi Iwai55e957d2005-11-17 14:52:13 +01004626 firmware = (struct hdsp_firmware __user *)argp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004627
Takashi Iwaib0b98112005-10-20 18:29:58 +02004628 if (get_user(firmware_data, &firmware->firmware_data))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004629 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004630
Takashi Iwaib0b98112005-10-20 18:29:58 +02004631 if (hdsp_check_for_iobox (hdsp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004632 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004633
Takashi Iwaib0b98112005-10-20 18:29:58 +02004634 if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004635 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004636
4637 hdsp->state |= HDSP_FirmwareCached;
4638
Takashi Iwaib0b98112005-10-20 18:29:58 +02004639 if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004640 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004641
4642 if (!(hdsp->state & HDSP_InitializationComplete)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004643 if ((err = snd_hdsp_enable_io(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004644 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004645
4646 snd_hdsp_initialize_channels(hdsp);
4647 snd_hdsp_initialize_midi_flush(hdsp);
4648
4649 if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004650 snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n");
4651 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004652 }
4653 }
4654 break;
4655 }
4656 case SNDRV_HDSP_IOCTL_GET_MIXER: {
Takashi Iwai55e957d2005-11-17 14:52:13 +01004657 struct hdsp_mixer __user *mixer = (struct hdsp_mixer __user *)argp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004658 if (copy_to_user(mixer->matrix, hdsp->mixer_matrix, sizeof(unsigned short)*HDSP_MATRIX_MIXER_SIZE))
4659 return -EFAULT;
4660 break;
4661 }
4662 default:
4663 return -EINVAL;
4664 }
4665 return 0;
4666}
4667
Takashi Iwai55e957d2005-11-17 14:52:13 +01004668static struct snd_pcm_ops snd_hdsp_playback_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004669 .open = snd_hdsp_playback_open,
4670 .close = snd_hdsp_playback_release,
4671 .ioctl = snd_hdsp_ioctl,
4672 .hw_params = snd_hdsp_hw_params,
4673 .prepare = snd_hdsp_prepare,
4674 .trigger = snd_hdsp_trigger,
4675 .pointer = snd_hdsp_hw_pointer,
4676 .copy = snd_hdsp_playback_copy,
4677 .silence = snd_hdsp_hw_silence,
4678};
4679
Takashi Iwai55e957d2005-11-17 14:52:13 +01004680static struct snd_pcm_ops snd_hdsp_capture_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004681 .open = snd_hdsp_capture_open,
4682 .close = snd_hdsp_capture_release,
4683 .ioctl = snd_hdsp_ioctl,
4684 .hw_params = snd_hdsp_hw_params,
4685 .prepare = snd_hdsp_prepare,
4686 .trigger = snd_hdsp_trigger,
4687 .pointer = snd_hdsp_hw_pointer,
4688 .copy = snd_hdsp_capture_copy,
4689};
4690
Takashi Iwai55e957d2005-11-17 14:52:13 +01004691static int __devinit snd_hdsp_create_hwdep(struct snd_card *card,
4692 struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004693{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004694 struct snd_hwdep *hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004695 int err;
4696
4697 if ((err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw)) < 0)
4698 return err;
4699
4700 hdsp->hwdep = hw;
4701 hw->private_data = hdsp;
4702 strcpy(hw->name, "HDSP hwdep interface");
4703
4704 hw->ops.open = snd_hdsp_hwdep_dummy_op;
4705 hw->ops.ioctl = snd_hdsp_hwdep_ioctl;
4706 hw->ops.release = snd_hdsp_hwdep_dummy_op;
4707
4708 return 0;
4709}
4710
Takashi Iwai55e957d2005-11-17 14:52:13 +01004711static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004712{
Takashi Iwai55e957d2005-11-17 14:52:13 +01004713 struct snd_pcm *pcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004714 int err;
4715
4716 if ((err = snd_pcm_new(card, hdsp->card_name, 0, 1, 1, &pcm)) < 0)
4717 return err;
4718
4719 hdsp->pcm = pcm;
4720 pcm->private_data = hdsp;
4721 strcpy(pcm->name, hdsp->card_name);
4722
4723 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_hdsp_playback_ops);
4724 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_hdsp_capture_ops);
4725
4726 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
4727
4728 return 0;
4729}
4730
Takashi Iwai55e957d2005-11-17 14:52:13 +01004731static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004732{
4733 hdsp->control2_register |= HDSP_9652_ENABLE_MIXER;
4734 hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
4735}
4736
Takashi Iwai55e957d2005-11-17 14:52:13 +01004737static int snd_hdsp_enable_io (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004738{
4739 int i;
4740
4741 if (hdsp_fifo_wait (hdsp, 0, 100)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004742 snd_printk(KERN_ERR "Hammerfall-DSP: enable_io fifo_wait failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004743 return -EIO;
4744 }
4745
4746 for (i = 0; i < hdsp->max_channels; ++i) {
4747 hdsp_write (hdsp, HDSP_inputEnable + (4 * i), 1);
4748 hdsp_write (hdsp, HDSP_outputEnable + (4 * i), 1);
4749 }
4750
4751 return 0;
4752}
4753
Takashi Iwai55e957d2005-11-17 14:52:13 +01004754static void snd_hdsp_initialize_channels(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004755{
4756 int status, aebi_channels, aebo_channels;
4757
4758 switch (hdsp->io_type) {
4759 case Digiface:
4760 hdsp->card_name = "RME Hammerfall DSP + Digiface";
4761 hdsp->ss_in_channels = hdsp->ss_out_channels = DIGIFACE_SS_CHANNELS;
4762 hdsp->ds_in_channels = hdsp->ds_out_channels = DIGIFACE_DS_CHANNELS;
4763 break;
4764
4765 case H9652:
4766 hdsp->card_name = "RME Hammerfall HDSP 9652";
4767 hdsp->ss_in_channels = hdsp->ss_out_channels = H9652_SS_CHANNELS;
4768 hdsp->ds_in_channels = hdsp->ds_out_channels = H9652_DS_CHANNELS;
4769 break;
4770
4771 case H9632:
4772 status = hdsp_read(hdsp, HDSP_statusRegister);
4773 /* HDSP_AEBx bits are low when AEB are connected */
4774 aebi_channels = (status & HDSP_AEBI) ? 0 : 4;
4775 aebo_channels = (status & HDSP_AEBO) ? 0 : 4;
4776 hdsp->card_name = "RME Hammerfall HDSP 9632";
4777 hdsp->ss_in_channels = H9632_SS_CHANNELS+aebi_channels;
4778 hdsp->ds_in_channels = H9632_DS_CHANNELS+aebi_channels;
4779 hdsp->qs_in_channels = H9632_QS_CHANNELS+aebi_channels;
4780 hdsp->ss_out_channels = H9632_SS_CHANNELS+aebo_channels;
4781 hdsp->ds_out_channels = H9632_DS_CHANNELS+aebo_channels;
4782 hdsp->qs_out_channels = H9632_QS_CHANNELS+aebo_channels;
4783 break;
4784
4785 case Multiface:
4786 hdsp->card_name = "RME Hammerfall DSP + Multiface";
4787 hdsp->ss_in_channels = hdsp->ss_out_channels = MULTIFACE_SS_CHANNELS;
4788 hdsp->ds_in_channels = hdsp->ds_out_channels = MULTIFACE_DS_CHANNELS;
4789 break;
4790
4791 default:
4792 /* should never get here */
4793 break;
4794 }
4795}
4796
Takashi Iwai55e957d2005-11-17 14:52:13 +01004797static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004798{
4799 snd_hdsp_flush_midi_input (hdsp, 0);
4800 snd_hdsp_flush_midi_input (hdsp, 1);
4801}
4802
Takashi Iwai55e957d2005-11-17 14:52:13 +01004803static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004804{
4805 int err;
4806
4807 if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004808 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating pcm interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004809 return err;
4810 }
4811
4812
4813 if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004814 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating first midi interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004815 return err;
4816 }
4817
4818 if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
4819 if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004820 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating second midi interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004821 return err;
4822 }
4823 }
4824
4825 if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004826 snd_printk(KERN_ERR "Hammerfall-DSP: Error creating ctl interface\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004827 return err;
4828 }
4829
4830 snd_hdsp_proc_init(hdsp);
4831
4832 hdsp->system_sample_rate = -1;
4833 hdsp->playback_pid = -1;
4834 hdsp->capture_pid = -1;
4835 hdsp->capture_substream = NULL;
4836 hdsp->playback_substream = NULL;
4837
4838 if ((err = snd_hdsp_set_defaults(hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004839 snd_printk(KERN_ERR "Hammerfall-DSP: Error setting default values\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004840 return err;
4841 }
4842
4843 if (!(hdsp->state & HDSP_InitializationComplete)) {
Clemens Ladischb73c1c12005-09-02 08:49:21 +02004844 strcpy(card->shortname, "Hammerfall DSP");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004845 sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
4846 hdsp->port, hdsp->irq);
4847
4848 if ((err = snd_card_register(card)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004849 snd_printk(KERN_ERR "Hammerfall-DSP: error registering card\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004850 return err;
4851 }
4852 hdsp->state |= HDSP_InitializationComplete;
4853 }
4854
4855 return 0;
4856}
4857
4858#ifdef HDSP_FW_LOADER
4859/* load firmware via hotplug fw loader */
Takashi Iwai55e957d2005-11-17 14:52:13 +01004860static int __devinit hdsp_request_fw_loader(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004861{
4862 const char *fwfile;
4863 const struct firmware *fw;
4864 int err;
4865
4866 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
4867 return 0;
4868 if (hdsp->io_type == Undefined) {
4869 if ((err = hdsp_get_iobox_version(hdsp)) < 0)
4870 return err;
4871 if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
4872 return 0;
4873 }
4874
4875 /* caution: max length of firmware filename is 30! */
4876 switch (hdsp->io_type) {
4877 case Multiface:
4878 if (hdsp->firmware_rev == 0xa)
4879 fwfile = "multiface_firmware.bin";
4880 else
4881 fwfile = "multiface_firmware_rev11.bin";
4882 break;
4883 case Digiface:
4884 if (hdsp->firmware_rev == 0xa)
4885 fwfile = "digiface_firmware.bin";
4886 else
4887 fwfile = "digiface_firmware_rev11.bin";
4888 break;
4889 default:
4890 snd_printk(KERN_ERR "Hammerfall-DSP: invalid io_type %d\n", hdsp->io_type);
4891 return -EINVAL;
4892 }
4893
4894 if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) {
4895 snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile);
4896 return -ENOENT;
4897 }
4898 if (fw->size < sizeof(hdsp->firmware_cache)) {
4899 snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n",
4900 (int)fw->size, (int)sizeof(hdsp->firmware_cache));
4901 release_firmware(fw);
4902 return -EINVAL;
4903 }
Thomas Charbonnel7679a032005-04-25 11:35:29 +02004904
Linus Torvalds1da177e2005-04-16 15:20:36 -07004905 memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache));
Thomas Charbonnel7679a032005-04-25 11:35:29 +02004906
Linus Torvalds1da177e2005-04-16 15:20:36 -07004907 release_firmware(fw);
4908
4909 hdsp->state |= HDSP_FirmwareCached;
4910
4911 if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
4912 return err;
4913
4914 if (!(hdsp->state & HDSP_InitializationComplete)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004915 if ((err = snd_hdsp_enable_io(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004916 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004917
4918 if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004919 snd_printk(KERN_ERR "Hammerfall-DSP: error creating hwdep device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004920 return err;
4921 }
4922 snd_hdsp_initialize_channels(hdsp);
4923 snd_hdsp_initialize_midi_flush(hdsp);
4924 if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02004925 snd_printk(KERN_ERR "Hammerfall-DSP: error creating alsa devices\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004926 return err;
4927 }
4928 }
4929 return 0;
4930}
4931#endif
4932
Takashi Iwai55e957d2005-11-17 14:52:13 +01004933static int __devinit snd_hdsp_create(struct snd_card *card,
4934 struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004935{
4936 struct pci_dev *pci = hdsp->pci;
4937 int err;
4938 int is_9652 = 0;
4939 int is_9632 = 0;
4940
4941 hdsp->irq = -1;
4942 hdsp->state = 0;
4943 hdsp->midi[0].rmidi = NULL;
4944 hdsp->midi[1].rmidi = NULL;
4945 hdsp->midi[0].input = NULL;
4946 hdsp->midi[1].input = NULL;
4947 hdsp->midi[0].output = NULL;
4948 hdsp->midi[1].output = NULL;
4949 hdsp->midi[0].pending = 0;
4950 hdsp->midi[1].pending = 0;
4951 spin_lock_init(&hdsp->midi[0].lock);
4952 spin_lock_init(&hdsp->midi[1].lock);
4953 hdsp->iobase = NULL;
4954 hdsp->control_register = 0;
4955 hdsp->control2_register = 0;
4956 hdsp->io_type = Undefined;
4957 hdsp->max_channels = 26;
4958
4959 hdsp->card = card;
4960
4961 spin_lock_init(&hdsp->lock);
4962
4963 tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp);
4964
4965 pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev);
4966 hdsp->firmware_rev &= 0xff;
4967
4968 /* From Martin Bjoernsen :
4969 "It is important that the card's latency timer register in
4970 the PCI configuration space is set to a value much larger
4971 than 0 by the computer's BIOS or the driver.
4972 The windows driver always sets this 8 bit register [...]
4973 to its maximum 255 to avoid problems with some computers."
4974 */
4975 pci_write_config_byte(hdsp->pci, PCI_LATENCY_TIMER, 0xFF);
4976
4977 strcpy(card->driver, "H-DSP");
4978 strcpy(card->mixername, "Xilinx FPGA");
4979
Takashi Iwaib0b98112005-10-20 18:29:58 +02004980 if (hdsp->firmware_rev < 0xa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004981 return -ENODEV;
Takashi Iwaib0b98112005-10-20 18:29:58 +02004982 else if (hdsp->firmware_rev < 0x64)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004983 hdsp->card_name = "RME Hammerfall DSP";
Takashi Iwaib0b98112005-10-20 18:29:58 +02004984 else if (hdsp->firmware_rev < 0x96) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004985 hdsp->card_name = "RME HDSP 9652";
4986 is_9652 = 1;
4987 } else {
4988 hdsp->card_name = "RME HDSP 9632";
4989 hdsp->max_channels = 16;
4990 is_9632 = 1;
4991 }
4992
Takashi Iwaib0b98112005-10-20 18:29:58 +02004993 if ((err = pci_enable_device(pci)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004994 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004995
4996 pci_set_master(hdsp->pci);
4997
4998 if ((err = pci_request_regions(pci, "hdsp")) < 0)
4999 return err;
5000 hdsp->port = pci_resource_start(pci, 0);
5001 if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02005002 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 -07005003 return -EBUSY;
5004 }
5005
Takashi Iwai437a5a42006-11-21 12:14:23 +01005006 if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_SHARED,
5007 "hdsp", hdsp)) {
Takashi Iwaib0b98112005-10-20 18:29:58 +02005008 snd_printk(KERN_ERR "Hammerfall-DSP: unable to use IRQ %d\n", pci->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005009 return -EBUSY;
5010 }
5011
5012 hdsp->irq = pci->irq;
Remy Bruno176546a2006-10-16 12:32:53 +02005013 hdsp->precise_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005014 hdsp->use_midi_tasklet = 1;
Remy Brunod7923b22006-10-17 12:41:56 +02005015 hdsp->dds_value = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005016
Takashi Iwaib0b98112005-10-20 18:29:58 +02005017 if ((err = snd_hdsp_initialize_memory(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005018 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005019
5020 if (!is_9652 && !is_9632) {
5021 /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */
Takashi Iwaib0b98112005-10-20 18:29:58 +02005022 ssleep(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005023
5024 if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
5025#ifdef HDSP_FW_LOADER
Takashi Iwaib0b98112005-10-20 18:29:58 +02005026 if ((err = hdsp_request_fw_loader(hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005027 /* we don't fail as this can happen
5028 if userspace is not ready for
5029 firmware upload
5030 */
Takashi Iwaib0b98112005-10-20 18:29:58 +02005031 snd_printk(KERN_ERR "Hammerfall-DSP: couldn't get firmware from userspace. try using hdsploader\n");
5032 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07005033 /* init is complete, we return */
5034 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005035#endif
5036 /* no iobox connected, we defer initialization */
Takashi Iwaib0b98112005-10-20 18:29:58 +02005037 snd_printk(KERN_INFO "Hammerfall-DSP: card initialization pending : waiting for firmware\n");
5038 if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005039 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040 return 0;
5041 } else {
Takashi Iwaib0b98112005-10-20 18:29:58 +02005042 snd_printk(KERN_INFO "Hammerfall-DSP: Firmware already present, initializing card.\n");
5043 if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005044 hdsp->io_type = Multiface;
Takashi Iwaib0b98112005-10-20 18:29:58 +02005045 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07005046 hdsp->io_type = Digiface;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005047 }
5048 }
5049
Takashi Iwaib0b98112005-10-20 18:29:58 +02005050 if ((err = snd_hdsp_enable_io(hdsp)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005051 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052
Takashi Iwaib0b98112005-10-20 18:29:58 +02005053 if (is_9652)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005054 hdsp->io_type = H9652;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005055
Takashi Iwaib0b98112005-10-20 18:29:58 +02005056 if (is_9632)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005057 hdsp->io_type = H9632;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005058
Takashi Iwaib0b98112005-10-20 18:29:58 +02005059 if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005060 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005061
5062 snd_hdsp_initialize_channels(hdsp);
5063 snd_hdsp_initialize_midi_flush(hdsp);
5064
5065 hdsp->state |= HDSP_FirmwareLoaded;
5066
Takashi Iwaib0b98112005-10-20 18:29:58 +02005067 if ((err = snd_hdsp_create_alsa_devices(card, hdsp)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005068 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069
5070 return 0;
5071}
5072
Takashi Iwai55e957d2005-11-17 14:52:13 +01005073static int snd_hdsp_free(struct hdsp *hdsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005074{
5075 if (hdsp->port) {
5076 /* stop the audio, and cancel all interrupts */
5077 tasklet_kill(&hdsp->midi_tasklet);
5078 hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable);
5079 hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
5080 }
5081
5082 if (hdsp->irq >= 0)
5083 free_irq(hdsp->irq, (void *)hdsp);
5084
5085 snd_hdsp_free_buffers(hdsp);
5086
5087 if (hdsp->iobase)
5088 iounmap(hdsp->iobase);
5089
5090 if (hdsp->port)
5091 pci_release_regions(hdsp->pci);
5092
5093 pci_disable_device(hdsp->pci);
5094 return 0;
5095}
5096
Takashi Iwai55e957d2005-11-17 14:52:13 +01005097static void snd_hdsp_card_free(struct snd_card *card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005098{
Takashi Iwai55e957d2005-11-17 14:52:13 +01005099 struct hdsp *hdsp = (struct hdsp *) card->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005100
5101 if (hdsp)
5102 snd_hdsp_free(hdsp);
5103}
5104
5105static int __devinit snd_hdsp_probe(struct pci_dev *pci,
5106 const struct pci_device_id *pci_id)
5107{
5108 static int dev;
Takashi Iwai55e957d2005-11-17 14:52:13 +01005109 struct hdsp *hdsp;
5110 struct snd_card *card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005111 int err;
5112
5113 if (dev >= SNDRV_CARDS)
5114 return -ENODEV;
5115 if (!enable[dev]) {
5116 dev++;
5117 return -ENOENT;
5118 }
5119
Takashi Iwai55e957d2005-11-17 14:52:13 +01005120 if (!(card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct hdsp))))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005121 return -ENOMEM;
5122
Takashi Iwai55e957d2005-11-17 14:52:13 +01005123 hdsp = (struct hdsp *) card->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005124 card->private_free = snd_hdsp_card_free;
5125 hdsp->dev = dev;
5126 hdsp->pci = pci;
5127 snd_card_set_dev(card, &pci->dev);
5128
5129 if ((err = snd_hdsp_create(card, hdsp)) < 0) {
5130 snd_card_free(card);
5131 return err;
5132 }
5133
5134 strcpy(card->shortname, "Hammerfall DSP");
5135 sprintf(card->longname, "%s at 0x%lx, irq %d", hdsp->card_name,
5136 hdsp->port, hdsp->irq);
5137
5138 if ((err = snd_card_register(card)) < 0) {
5139 snd_card_free(card);
5140 return err;
5141 }
5142 pci_set_drvdata(pci, card);
5143 dev++;
5144 return 0;
5145}
5146
5147static void __devexit snd_hdsp_remove(struct pci_dev *pci)
5148{
5149 snd_card_free(pci_get_drvdata(pci));
5150 pci_set_drvdata(pci, NULL);
5151}
5152
5153static struct pci_driver driver = {
5154 .name = "RME Hammerfall DSP",
5155 .id_table = snd_hdsp_ids,
5156 .probe = snd_hdsp_probe,
5157 .remove = __devexit_p(snd_hdsp_remove),
5158};
5159
5160static int __init alsa_card_hdsp_init(void)
5161{
Takashi Iwai01d25d42005-04-11 16:58:24 +02005162 return pci_register_driver(&driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005163}
5164
5165static void __exit alsa_card_hdsp_exit(void)
5166{
5167 pci_unregister_driver(&driver);
5168}
5169
5170module_init(alsa_card_hdsp_init)
5171module_exit(alsa_card_hdsp_exit)