blob: 143185e7e4dc0881b6aac43eb91afe5164b2bde6 [file] [log] [blame]
Takashi Iwai763f3562005-06-03 11:25:34 +02001/* -*- linux-c -*-
2 *
3 * ALSA driver for RME Hammerfall DSP MADI audio interface(s)
4 *
5 * Copyright (c) 2003 Winfried Ritsch (IEM)
6 * code based on hdsp.c Paul Davis
7 * Marcus Andersson
8 * Thomas Charbonnel
Remy Bruno3cee5a62006-10-16 12:46:32 +02009 * Modified 2006-06-01 for AES32 support by Remy Bruno
10 * <remy.bruno@trinnov.com>
Takashi Iwai763f3562005-06-03 11:25:34 +020011 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 */
27#include <sound/driver.h>
28#include <linux/init.h>
29#include <linux/delay.h>
30#include <linux/interrupt.h>
31#include <linux/moduleparam.h>
32#include <linux/slab.h>
33#include <linux/pci.h>
34#include <asm/io.h>
35
36#include <sound/core.h>
37#include <sound/control.h>
38#include <sound/pcm.h>
39#include <sound/info.h>
40#include <sound/asoundef.h>
41#include <sound/rawmidi.h>
42#include <sound/hwdep.h>
43#include <sound/initval.h>
44
45#include <sound/hdspm.h>
46
47static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
48static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
49static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
50
51/* Disable precise pointer at start */
52static int precise_ptr[SNDRV_CARDS];
53
54/* Send all playback to line outs */
55static int line_outs_monitor[SNDRV_CARDS];
56
57/* Enable Analog Outs on Channel 63/64 by default */
58static int enable_monitor[SNDRV_CARDS];
59
60module_param_array(index, int, NULL, 0444);
61MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
62
63module_param_array(id, charp, NULL, 0444);
64MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
65
66module_param_array(enable, bool, NULL, 0444);
67MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
68
69module_param_array(precise_ptr, bool, NULL, 0444);
Takashi Iwaie8da2fb2005-08-16 16:55:13 +020070MODULE_PARM_DESC(precise_ptr, "Enable or disable precise pointer.");
Takashi Iwai763f3562005-06-03 11:25:34 +020071
72module_param_array(line_outs_monitor, bool, NULL, 0444);
73MODULE_PARM_DESC(line_outs_monitor,
74 "Send playback streams to analog outs by default.");
75
76module_param_array(enable_monitor, bool, NULL, 0444);
77MODULE_PARM_DESC(enable_monitor,
78 "Enable Analog Out on Channel 63/64 by default.");
79
80MODULE_AUTHOR
81 ("Winfried Ritsch <ritsch_AT_iem.at>, Paul Davis <paul@linuxaudiosystems.com>, "
Remy Bruno3cee5a62006-10-16 12:46:32 +020082 "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
83 "Remy Bruno <remy.bruno@trinnov.com>");
Takashi Iwai763f3562005-06-03 11:25:34 +020084MODULE_DESCRIPTION("RME HDSPM");
85MODULE_LICENSE("GPL");
86MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
87
88/* --- Write registers. ---
89 These are defined as byte-offsets from the iobase value. */
90
91#define HDSPM_controlRegister 64
92#define HDSPM_interruptConfirmation 96
93#define HDSPM_control2Reg 256 /* not in specs ???????? */
Remy Brunoffb2c3c2007-03-07 19:08:46 +010094#define HDSPM_freqReg 256 /* for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +020095#define HDSPM_midiDataOut0 352 /* just believe in old code */
96#define HDSPM_midiDataOut1 356
Remy Brunoffb2c3c2007-03-07 19:08:46 +010097#define HDSPM_eeprom_wr 384 /* for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +020098
99/* DMA enable for 64 channels, only Bit 0 is relevant */
100#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */
101#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */
102
103/* 16 page addresses for each of the 64 channels DMA buffer in and out
104 (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
105#define HDSPM_pageAddressBufferOut 8192
106#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)
107
108#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */
109
110#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */
111
112/* --- Read registers. ---
113 These are defined as byte-offsets from the iobase value */
114#define HDSPM_statusRegister 0
Remy Bruno3cee5a62006-10-16 12:46:32 +0200115/*#define HDSPM_statusRegister2 96 */
116/* after RME Windows driver sources, status2 is 4-byte word # 48 = word at
117 * offset 192, for AES32 *and* MADI
118 * => need to check that offset 192 is working on MADI */
119#define HDSPM_statusRegister2 192
120#define HDSPM_timecodeRegister 128
Takashi Iwai763f3562005-06-03 11:25:34 +0200121
122#define HDSPM_midiDataIn0 360
123#define HDSPM_midiDataIn1 364
124
125/* status is data bytes in MIDI-FIFO (0-128) */
126#define HDSPM_midiStatusOut0 384
127#define HDSPM_midiStatusOut1 388
128#define HDSPM_midiStatusIn0 392
129#define HDSPM_midiStatusIn1 396
130
131
132/* the meters are regular i/o-mapped registers, but offset
133 considerably from the rest. the peak registers are reset
134 when read; the least-significant 4 bits are full-scale counters;
135 the actual peak value is in the most-significant 24 bits.
136*/
137#define HDSPM_MADI_peakrmsbase 4096 /* 4096-8191 2x64x32Bit Meters */
138
139/* --- Control Register bits --------- */
140#define HDSPM_Start (1<<0) /* start engine */
141
142#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */
143#define HDSPM_Latency1 (1<<2) /* where n is defined */
144#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */
145
146#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */
147
148#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
149
150#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
151#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
152#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200153#define HDSPM_QuadSpeed (1<<31) /* quad speed bit */
Takashi Iwai763f3562005-06-03 11:25:34 +0200154
Remy Bruno3cee5a62006-10-16 12:46:32 +0200155#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200156#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200157 56channelMODE=0 */ /* MADI ONLY*/
158#define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200159
160#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200161 0=off, 1=on */ /* MADI ONLY */
162#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200163
Remy Bruno3cee5a62006-10-16 12:46:32 +0200164#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */ /* MADI ONLY*/
Takashi Iwai763f3562005-06-03 11:25:34 +0200165#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
166
167#define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200168#define HDSPM_SyncRef1 (1<<17) /* for AES32: SyncRefN codes the AES # */
169#define HDSPM_SyncRef2 (1<<13)
170#define HDSPM_SyncRef3 (1<<25)
Takashi Iwai763f3562005-06-03 11:25:34 +0200171
Remy Bruno3cee5a62006-10-16 12:46:32 +0200172#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200173#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
174 AES additional bits in
175 lower 5 Audiodatabits ??? */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200176#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */
177#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200178
179#define HDSPM_Midi0InterruptEnable (1<<22)
180#define HDSPM_Midi1InterruptEnable (1<<23)
181
182#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
183
Remy Bruno3cee5a62006-10-16 12:46:32 +0200184#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
185#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
186#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */
187
188#define HDSPM_wclk_sel (1<<30)
Takashi Iwai763f3562005-06-03 11:25:34 +0200189
190/* --- bit helper defines */
191#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200192#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
Takashi Iwai763f3562005-06-03 11:25:34 +0200193#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
194#define HDSPM_InputOptical 0
195#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200196#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|HDSPM_SyncRef2|HDSPM_SyncRef3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200197#define HDSPM_SyncRef_Word 0
198#define HDSPM_SyncRef_MADI (HDSPM_SyncRef0)
199
200#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
201#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
202
203#define HDSPM_Frequency32KHz HDSPM_Frequency0
204#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
205#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
206#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
207#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
208#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200209#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)
210#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)
211#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|HDSPM_Frequency0)
Takashi Iwai763f3562005-06-03 11:25:34 +0200212
213/* --- for internal discrimination */
214#define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */
215#define HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ 1
216#define HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ 2
217#define HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ 3
218#define HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ 4
219#define HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ 5
220#define HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ 6
221#define HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ 7
222#define HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ 8
223#define HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ 9
224
225/* Synccheck Status */
226#define HDSPM_SYNC_CHECK_NO_LOCK 0
227#define HDSPM_SYNC_CHECK_LOCK 1
228#define HDSPM_SYNC_CHECK_SYNC 2
229
230/* AutoSync References - used by "autosync_ref" control switch */
231#define HDSPM_AUTOSYNC_FROM_WORD 0
232#define HDSPM_AUTOSYNC_FROM_MADI 1
233#define HDSPM_AUTOSYNC_FROM_NONE 2
234
235/* Possible sources of MADI input */
236#define HDSPM_OPTICAL 0 /* optical */
237#define HDSPM_COAXIAL 1 /* BNC */
238
239#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
240#define hdspm_decode_latency(x) (((x) & HDSPM_LatencyMask)>>1)
241
242#define hdspm_encode_in(x) (((x)&0x3)<<14)
243#define hdspm_decode_in(x) (((x)>>14)&0x3)
244
245/* --- control2 register bits --- */
246#define HDSPM_TMS (1<<0)
247#define HDSPM_TCK (1<<1)
248#define HDSPM_TDI (1<<2)
249#define HDSPM_JTAG (1<<3)
250#define HDSPM_PWDN (1<<4)
251#define HDSPM_PROGRAM (1<<5)
252#define HDSPM_CONFIG_MODE_0 (1<<6)
253#define HDSPM_CONFIG_MODE_1 (1<<7)
254/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
255#define HDSPM_BIGENDIAN_MODE (1<<9)
256#define HDSPM_RD_MULTIPLE (1<<10)
257
Remy Bruno3cee5a62006-10-16 12:46:32 +0200258/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
259 that do not conflict with specific bits for AES32 seem to be valid also for the AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200260#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
261#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn. MODE=0 */
262#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 (like inp0) */
263#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
264
265#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
266 /* since 64byte accurate last 6 bits
267 are not used */
268
269#define HDSPM_madiSync (1<<18) /* MADI is in sync */
270#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
271
272#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
273#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
274#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
275#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
276
277#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with Interrupt */
278#define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */
279#define HDSPM_midi1IRQPending (1<<31) /* and aktiv */
280
281/* --- status bit helpers */
282#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2|HDSPM_madiFreq3)
283#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
284#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
285#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
286#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
287#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
288#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
289#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
290#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
291#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
292
Remy Bruno3cee5a62006-10-16 12:46:32 +0200293/* Status2 Register bits */ /* MADI ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200294
295#define HDSPM_version0 (1<<0) /* not realy defined but I guess */
296#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
297#define HDSPM_version2 (1<<2)
298
299#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */
300#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */
301
302#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */
303#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */
304#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */
305/* missing Bit for 111=128, 1000=176.4, 1001=192 */
306
307#define HDSPM_SelSyncRef0 (1<<8) /* Sync Source in slave mode */
308#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */
309#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */
310
311#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
312
313#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
314#define HDSPM_wcFreq32 (HDSPM_wc_freq0)
315#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)
316#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)
317#define HDSPM_wcFreq64 (HDSPM_wc_freq2)
318#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)
319#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
320
321
322#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
323#define HDSPM_SelSyncRef_WORD 0
324#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
325#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
326
Remy Bruno3cee5a62006-10-16 12:46:32 +0200327/*
328 For AES32, bits for status, status2 and timecode are different
329*/
330/* status */
331#define HDSPM_AES32_wcLock 0x0200000
332#define HDSPM_AES32_wcFreq_bit 22
333/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
334 HDSPM_bit2freq */
335#define HDSPM_AES32_syncref_bit 16
336/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
337
338#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
339#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
340#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
341#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
342#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
343#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
344#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
345#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
346#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
347#define HDSPM_AES32_AUTOSYNC_FROM_NONE -1
348
349/* status2 */
350/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
351#define HDSPM_LockAES 0x80
352#define HDSPM_LockAES1 0x80
353#define HDSPM_LockAES2 0x40
354#define HDSPM_LockAES3 0x20
355#define HDSPM_LockAES4 0x10
356#define HDSPM_LockAES5 0x8
357#define HDSPM_LockAES6 0x4
358#define HDSPM_LockAES7 0x2
359#define HDSPM_LockAES8 0x1
360/*
361 Timecode
362 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
363 AES i+1
364 bits 3210
365 0001 32kHz
366 0010 44.1kHz
367 0011 48kHz
368 0100 64kHz
369 0101 88.2kHz
370 0110 96kHz
371 0111 128kHz
372 1000 176.4kHz
373 1001 192kHz
374 NB: Timecode register doesn't seem to work on AES32 card revision 230
375*/
376
Takashi Iwai763f3562005-06-03 11:25:34 +0200377/* Mixer Values */
378#define UNITY_GAIN 32768 /* = 65536/2 */
379#define MINUS_INFINITY_GAIN 0
380
Takashi Iwai763f3562005-06-03 11:25:34 +0200381/* Number of channels for different Speed Modes */
382#define MADI_SS_CHANNELS 64
383#define MADI_DS_CHANNELS 32
384#define MADI_QS_CHANNELS 16
385
386/* the size of a substream (1 mono data stream) */
387#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
388#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
389
390/* the size of the area we need to allocate for DMA transfers. the
391 size is the same regardless of the number of channels, and
392 also the latency to use.
393 for one direction !!!
394*/
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100395#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
Takashi Iwai763f3562005-06-03 11:25:34 +0200396#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
397
Remy Bruno3cee5a62006-10-16 12:46:32 +0200398/* revisions >= 230 indicate AES32 card */
399#define HDSPM_AESREVISION 230
400
Takashi Iwai98274f02005-11-17 14:52:34 +0100401struct hdspm_midi {
402 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200403 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100404 struct snd_rawmidi *rmidi;
405 struct snd_rawmidi_substream *input;
406 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200407 char istimer; /* timer in use */
408 struct timer_list timer;
409 spinlock_t lock;
410 int pending;
411};
412
Takashi Iwai98274f02005-11-17 14:52:34 +0100413struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200414 spinlock_t lock;
Takashi Iwai98274f02005-11-17 14:52:34 +0100415 struct snd_pcm_substream *capture_substream; /* only one playback */
416 struct snd_pcm_substream *playback_substream; /* and/or capture stream */
Takashi Iwai763f3562005-06-03 11:25:34 +0200417
418 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200419 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
420
421 unsigned char is_aes32; /* indicates if card is AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200422
423 int precise_ptr; /* use precise pointers, to be tested */
424 int monitor_outs; /* set up monitoring outs init flag */
425
426 u32 control_register; /* cached value */
427 u32 control2_register; /* cached value */
428
Takashi Iwai98274f02005-11-17 14:52:34 +0100429 struct hdspm_midi midi[2];
Takashi Iwai763f3562005-06-03 11:25:34 +0200430 struct tasklet_struct midi_tasklet;
431
432 size_t period_bytes;
433 unsigned char ss_channels; /* channels of card in single speed */
434 unsigned char ds_channels; /* Double Speed */
435 unsigned char qs_channels; /* Quad Speed */
436
437 unsigned char *playback_buffer; /* suitably aligned address */
438 unsigned char *capture_buffer; /* suitably aligned address */
439
440 pid_t capture_pid; /* process id which uses capture */
441 pid_t playback_pid; /* process id which uses capture */
442 int running; /* running status */
443
444 int last_external_sample_rate; /* samplerate mystic ... */
445 int last_internal_sample_rate;
446 int system_sample_rate;
447
448 char *channel_map; /* channel map for DS and Quadspeed */
449
450 int dev; /* Hardware vars... */
451 int irq;
452 unsigned long port;
453 void __iomem *iobase;
454
455 int irq_count; /* for debug */
456
Takashi Iwai98274f02005-11-17 14:52:34 +0100457 struct snd_card *card; /* one card */
458 struct snd_pcm *pcm; /* has one pcm */
459 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +0200460 struct pci_dev *pci; /* and an pci info */
461
462 /* Mixer vars */
Takashi Iwai98274f02005-11-17 14:52:34 +0100463 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; /* fast alsa mixer */
464 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS]; /* but input to much, so not used */
465 struct hdspm_mixer *mixer; /* full mixer accessable over mixer ioctl or hwdep-device */
Takashi Iwai763f3562005-06-03 11:25:34 +0200466
467};
468
469/* These tables map the ALSA channels 1..N to the channels that we
470 need to use in order to find the relevant channel buffer. RME
471 refer to this kind of mapping as between "the ADAT channel and
472 the DMA channel." We index it using the logical audio channel,
473 and the value is the DMA channel (i.e. channel buffer number)
474 where the data for that channel can be read/written from/to.
475*/
476
477static char channel_map_madi_ss[HDSPM_MAX_CHANNELS] = {
478 0, 1, 2, 3, 4, 5, 6, 7,
479 8, 9, 10, 11, 12, 13, 14, 15,
480 16, 17, 18, 19, 20, 21, 22, 23,
481 24, 25, 26, 27, 28, 29, 30, 31,
482 32, 33, 34, 35, 36, 37, 38, 39,
483 40, 41, 42, 43, 44, 45, 46, 47,
484 48, 49, 50, 51, 52, 53, 54, 55,
485 56, 57, 58, 59, 60, 61, 62, 63
486};
487
Takashi Iwai763f3562005-06-03 11:25:34 +0200488
Henrik Kretzschmar396c9b92006-04-24 15:59:04 +0200489static struct pci_device_id snd_hdspm_ids[] __devinitdata = {
Takashi Iwai763f3562005-06-03 11:25:34 +0200490 {
491 .vendor = PCI_VENDOR_ID_XILINX,
492 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
493 .subvendor = PCI_ANY_ID,
494 .subdevice = PCI_ANY_ID,
495 .class = 0,
496 .class_mask = 0,
497 .driver_data = 0},
498 {0,}
499};
500
501MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
502
503/* prototypes */
Takashi Iwai98274f02005-11-17 14:52:34 +0100504static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
505 struct hdspm * hdspm);
506static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
507 struct hdspm * hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200508
Takashi Iwai98274f02005-11-17 14:52:34 +0100509static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm);
510static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm);
511static int hdspm_autosync_ref(struct hdspm * hdspm);
512static int snd_hdspm_set_defaults(struct hdspm * hdspm);
513static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
Takashi Iwai763f3562005-06-03 11:25:34 +0200514 unsigned int reg, int channels);
515
Remy Bruno3cee5a62006-10-16 12:46:32 +0200516static inline int HDSPM_bit2freq(int n)
517{
518 static int bit2freq_tab[] = { 0, 32000, 44100, 48000, 64000, 88200,
519 96000, 128000, 176400, 192000 };
520 if (n < 1 || n > 9)
521 return 0;
522 return bit2freq_tab[n];
523}
524
Takashi Iwai763f3562005-06-03 11:25:34 +0200525/* Write/read to/from HDSPM with Adresses in Bytes
526 not words but only 32Bit writes are allowed */
527
Takashi Iwai98274f02005-11-17 14:52:34 +0100528static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +0200529 unsigned int val)
530{
531 writel(val, hdspm->iobase + reg);
532}
533
Takashi Iwai98274f02005-11-17 14:52:34 +0100534static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +0200535{
536 return readl(hdspm->iobase + reg);
537}
538
539/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
540 mixer is write only on hardware so we have to cache him for read
541 each fader is a u32, but uses only the first 16 bit */
542
Takashi Iwai98274f02005-11-17 14:52:34 +0100543static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200544 unsigned int in)
545{
Adrian Bunk5bab24822006-03-13 14:15:04 +0100546 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +0200547 return 0;
548
549 return hdspm->mixer->ch[chan].in[in];
550}
551
Takashi Iwai98274f02005-11-17 14:52:34 +0100552static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200553 unsigned int pb)
554{
Adrian Bunk5bab24822006-03-13 14:15:04 +0100555 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +0200556 return 0;
557 return hdspm->mixer->ch[chan].pb[pb];
558}
559
Takashi Iwai98274f02005-11-17 14:52:34 +0100560static inline int hdspm_write_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200561 unsigned int in, unsigned short data)
562{
563 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
564 return -1;
565
566 hdspm_write(hdspm,
567 HDSPM_MADI_mixerBase +
568 ((in + 128 * chan) * sizeof(u32)),
569 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
570 return 0;
571}
572
Takashi Iwai98274f02005-11-17 14:52:34 +0100573static inline int hdspm_write_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200574 unsigned int pb, unsigned short data)
575{
576 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
577 return -1;
578
579 hdspm_write(hdspm,
580 HDSPM_MADI_mixerBase +
581 ((64 + pb + 128 * chan) * sizeof(u32)),
582 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
583 return 0;
584}
585
586
587/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +0100588static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +0200589{
590 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
591}
592
Takashi Iwai98274f02005-11-17 14:52:34 +0100593static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +0200594{
595 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
596}
597
598/* check if same process is writing and reading */
Takashi Iwai98274f02005-11-17 14:52:34 +0100599static inline int snd_hdspm_use_is_exclusive(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200600{
601 unsigned long flags;
602 int ret = 1;
603
604 spin_lock_irqsave(&hdspm->lock, flags);
605 if ((hdspm->playback_pid != hdspm->capture_pid) &&
606 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
607 ret = 0;
608 }
609 spin_unlock_irqrestore(&hdspm->lock, flags);
610 return ret;
611}
612
613/* check for external sample rate */
Takashi Iwai98274f02005-11-17 14:52:34 +0100614static inline int hdspm_external_sample_rate(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200615{
Remy Bruno3cee5a62006-10-16 12:46:32 +0200616 if (hdspm->is_aes32) {
617 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
618 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
619 unsigned int timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +0200620
Remy Bruno3cee5a62006-10-16 12:46:32 +0200621 int syncref = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200622
Remy Bruno3cee5a62006-10-16 12:46:32 +0200623 if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
624 status & HDSPM_AES32_wcLock)
625 return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
626 if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
627 syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
628 status2 & (HDSPM_LockAES >>
629 (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
630 return HDSPM_bit2freq((timecode >>
631 (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
632 return 0;
633 } else {
634 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
635 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
636 unsigned int rate_bits;
637 int rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +0200638
Remy Bruno3cee5a62006-10-16 12:46:32 +0200639 /* if wordclock has synced freq and wordclock is valid */
640 if ((status2 & HDSPM_wcLock) != 0 &&
641 (status & HDSPM_SelSyncRef0) == 0) {
642
643 rate_bits = status2 & HDSPM_wcFreqMask;
644
645 switch (rate_bits) {
646 case HDSPM_wcFreq32:
647 rate = 32000;
648 break;
649 case HDSPM_wcFreq44_1:
650 rate = 44100;
651 break;
652 case HDSPM_wcFreq48:
653 rate = 48000;
654 break;
655 case HDSPM_wcFreq64:
656 rate = 64000;
657 break;
658 case HDSPM_wcFreq88_2:
659 rate = 88200;
660 break;
661 case HDSPM_wcFreq96:
662 rate = 96000;
663 break;
664 /* Quadspeed Bit missing ???? */
665 default:
666 rate = 0;
667 break;
668 }
Takashi Iwai763f3562005-06-03 11:25:34 +0200669 }
Takashi Iwai763f3562005-06-03 11:25:34 +0200670
Remy Bruno3cee5a62006-10-16 12:46:32 +0200671 /* if rate detected and Syncref is Word than have it, word has priority to MADI */
672 if (rate != 0 &&
673 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
674 return rate;
675
676 /* maby a madi input (which is taken if sel sync is madi) */
677 if (status & HDSPM_madiLock) {
678 rate_bits = status & HDSPM_madiFreqMask;
679
680 switch (rate_bits) {
681 case HDSPM_madiFreq32:
682 rate = 32000;
683 break;
684 case HDSPM_madiFreq44_1:
685 rate = 44100;
686 break;
687 case HDSPM_madiFreq48:
688 rate = 48000;
689 break;
690 case HDSPM_madiFreq64:
691 rate = 64000;
692 break;
693 case HDSPM_madiFreq88_2:
694 rate = 88200;
695 break;
696 case HDSPM_madiFreq96:
697 rate = 96000;
698 break;
699 case HDSPM_madiFreq128:
700 rate = 128000;
701 break;
702 case HDSPM_madiFreq176_4:
703 rate = 176400;
704 break;
705 case HDSPM_madiFreq192:
706 rate = 192000;
707 break;
708 default:
709 rate = 0;
710 break;
711 }
712 }
Takashi Iwai763f3562005-06-03 11:25:34 +0200713 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +0200714 }
Takashi Iwai763f3562005-06-03 11:25:34 +0200715}
716
717/* Latency function */
Takashi Iwai98274f02005-11-17 14:52:34 +0100718static inline void hdspm_compute_period_size(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200719{
720 hdspm->period_bytes =
721 1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
722}
723
Takashi Iwai98274f02005-11-17 14:52:34 +0100724static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200725{
726 int position;
727
728 position = hdspm_read(hdspm, HDSPM_statusRegister);
729
730 if (!hdspm->precise_ptr) {
731 return (position & HDSPM_BufferID) ? (hdspm->period_bytes /
732 4) : 0;
733 }
734
735 /* hwpointer comes in bytes and is 64Bytes accurate (by docu since PCI Burst)
736 i have experimented that it is at most 64 Byte to much for playing
737 so substraction of 64 byte should be ok for ALSA, but use it only
738 for application where you know what you do since if you come to
739 near with record pointer it can be a disaster */
740
741 position &= HDSPM_BufferPositionMask;
742 position = ((position - 64) % (2 * hdspm->period_bytes)) / 4;
743
744 return position;
745}
746
747
Takashi Iwai98274f02005-11-17 14:52:34 +0100748static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +0200749{
750 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
751 hdspm_write(s, HDSPM_controlRegister, s->control_register);
752}
753
Takashi Iwai98274f02005-11-17 14:52:34 +0100754static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +0200755{
756 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
757 hdspm_write(s, HDSPM_controlRegister, s->control_register);
758}
759
760/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Takashi Iwai98274f02005-11-17 14:52:34 +0100761static inline void hdspm_silence_playback(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200762{
763 int i;
764 int n = hdspm->period_bytes;
765 void *buf = hdspm->playback_buffer;
766
Remy Bruno3cee5a62006-10-16 12:46:32 +0200767 if (buf == NULL)
768 return;
Takashi Iwai763f3562005-06-03 11:25:34 +0200769
770 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
771 memset(buf, 0, n);
772 buf += HDSPM_CHANNEL_BUFFER_BYTES;
773 }
774}
775
Takashi Iwai98274f02005-11-17 14:52:34 +0100776static int hdspm_set_interrupt_interval(struct hdspm * s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +0200777{
778 int n;
779
780 spin_lock_irq(&s->lock);
781
782 frames >>= 7;
783 n = 0;
784 while (frames) {
785 n++;
786 frames >>= 1;
787 }
788 s->control_register &= ~HDSPM_LatencyMask;
789 s->control_register |= hdspm_encode_latency(n);
790
791 hdspm_write(s, HDSPM_controlRegister, s->control_register);
792
793 hdspm_compute_period_size(s);
794
795 spin_unlock_irq(&s->lock);
796
797 return 0;
798}
799
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100800static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
801{
802 u64 n;
803 u32 r;
804
805 if (rate >= 112000)
806 rate /= 4;
807 else if (rate >= 56000)
808 rate /= 2;
809
810 /* RME says n = 104857600000000, but in the windows MADI driver, I see:
811// return 104857600000000 / rate; // 100 MHz
812 return 110100480000000 / rate; // 105 MHz
813 */
814 //n = 104857600000000ULL; /* = 2^20 * 10^8 */
815 n = 110100480000000ULL; /* Value checked for AES32 and MADI */
816 div64_32(&n, rate, &r);
817 /* n should be less than 2^32 for being written to FREQ register */
818 snd_assert((n >> 32) == 0);
819 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
820}
Takashi Iwai763f3562005-06-03 11:25:34 +0200821
822/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +0100823static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +0200824{
825 int reject_if_open = 0;
826 int current_rate;
827 int rate_bits;
828 int not_set = 0;
Remy Bruno3cee5a62006-10-16 12:46:32 +0200829 int is_single, is_double, is_quad;
Takashi Iwai763f3562005-06-03 11:25:34 +0200830
831 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
832 it (e.g. during module initialization).
833 */
834
835 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
836
837 /* SLAVE --- */
838 if (called_internally) {
839
840 /* request from ctl or card initialization
841 just make a warning an remember setting
842 for future master mode switching */
843
844 snd_printk
845 (KERN_WARNING "HDSPM: Warning: device is not running as a clock master.\n");
846 not_set = 1;
847 } else {
848
849 /* hw_param request while in AutoSync mode */
850 int external_freq =
851 hdspm_external_sample_rate(hdspm);
852
853 if ((hdspm_autosync_ref(hdspm) ==
854 HDSPM_AUTOSYNC_FROM_NONE)) {
855
856 snd_printk(KERN_WARNING "HDSPM: Detected no Externel Sync \n");
857 not_set = 1;
858
859 } else if (rate != external_freq) {
860
861 snd_printk
862 (KERN_WARNING "HDSPM: Warning: No AutoSync source for requested rate\n");
863 not_set = 1;
864 }
865 }
866 }
867
868 current_rate = hdspm->system_sample_rate;
869
870 /* Changing between Singe, Double and Quad speed is not
871 allowed if any substreams are open. This is because such a change
872 causes a shift in the location of the DMA buffers and a reduction
873 in the number of available buffers.
874
875 Note that a similar but essentially insoluble problem exists for
876 externally-driven rate changes. All we can do is to flag rate
877 changes in the read/write routines.
878 */
879
Remy Bruno3cee5a62006-10-16 12:46:32 +0200880 is_single = (current_rate <= 48000);
881 is_double = (current_rate > 48000 && current_rate <= 96000);
882 is_quad = (current_rate > 96000);
883
Takashi Iwai763f3562005-06-03 11:25:34 +0200884 switch (rate) {
885 case 32000:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200886 if (!is_single)
Takashi Iwai763f3562005-06-03 11:25:34 +0200887 reject_if_open = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +0200888 rate_bits = HDSPM_Frequency32KHz;
889 break;
890 case 44100:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200891 if (!is_single)
Takashi Iwai763f3562005-06-03 11:25:34 +0200892 reject_if_open = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +0200893 rate_bits = HDSPM_Frequency44_1KHz;
894 break;
895 case 48000:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200896 if (!is_single)
Takashi Iwai763f3562005-06-03 11:25:34 +0200897 reject_if_open = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +0200898 rate_bits = HDSPM_Frequency48KHz;
899 break;
900 case 64000:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200901 if (!is_double)
Takashi Iwai763f3562005-06-03 11:25:34 +0200902 reject_if_open = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +0200903 rate_bits = HDSPM_Frequency64KHz;
904 break;
905 case 88200:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200906 if (!is_double)
Takashi Iwai763f3562005-06-03 11:25:34 +0200907 reject_if_open = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +0200908 rate_bits = HDSPM_Frequency88_2KHz;
909 break;
910 case 96000:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200911 if (!is_double)
Takashi Iwai763f3562005-06-03 11:25:34 +0200912 reject_if_open = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +0200913 rate_bits = HDSPM_Frequency96KHz;
914 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +0200915 case 128000:
916 if (!is_quad)
917 reject_if_open = 1;
918 rate_bits = HDSPM_Frequency128KHz;
919 break;
920 case 176400:
921 if (!is_quad)
922 reject_if_open = 1;
923 rate_bits = HDSPM_Frequency176_4KHz;
924 break;
925 case 192000:
926 if (!is_quad)
927 reject_if_open = 1;
928 rate_bits = HDSPM_Frequency192KHz;
929 break;
Takashi Iwai763f3562005-06-03 11:25:34 +0200930 default:
931 return -EINVAL;
932 }
933
934 if (reject_if_open
935 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
936 snd_printk
937 (KERN_ERR "HDSPM: cannot change between single- and double-speed mode (capture PID = %d, playback PID = %d)\n",
938 hdspm->capture_pid, hdspm->playback_pid);
939 return -EBUSY;
940 }
941
942 hdspm->control_register &= ~HDSPM_FrequencyMask;
943 hdspm->control_register |= rate_bits;
944 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
945
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100946 /* For AES32, need to set DDS value in FREQ register
947 For MADI, also apparently */
948 hdspm_set_dds_value(hdspm, rate);
949
950 if (hdspm->is_aes32 && rate != current_rate)
951 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
952
953 /* For AES32 and for MADI (at least rev 204), channel_map needs to
954 * always be channel_map_madi_ss, whatever the sample rate */
955 hdspm->channel_map = channel_map_madi_ss;
Takashi Iwai763f3562005-06-03 11:25:34 +0200956
957 hdspm->system_sample_rate = rate;
958
959 if (not_set != 0)
960 return -1;
961
962 return 0;
963}
964
965/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +0100966static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +0200967{
968 int i, j;
969 unsigned int gain =
970 (sgain > UNITY_GAIN) ? UNITY_GAIN : (sgain < 0) ? 0 : sgain;
971
972 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
973 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
974 hdspm_write_in_gain(hdspm, i, j, gain);
975 hdspm_write_pb_gain(hdspm, i, j, gain);
976 }
977}
978
979/*----------------------------------------------------------------------------
980 MIDI
981 ----------------------------------------------------------------------------*/
982
Takashi Iwai98274f02005-11-17 14:52:34 +0100983static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +0200984{
985 /* the hardware already does the relevant bit-mask with 0xff */
986 if (id)
987 return hdspm_read(hdspm, HDSPM_midiDataIn1);
988 else
989 return hdspm_read(hdspm, HDSPM_midiDataIn0);
990}
991
Takashi Iwai98274f02005-11-17 14:52:34 +0100992static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id, int val)
Takashi Iwai763f3562005-06-03 11:25:34 +0200993{
994 /* the hardware already does the relevant bit-mask with 0xff */
995 if (id)
996 return hdspm_write(hdspm, HDSPM_midiDataOut1, val);
997 else
998 return hdspm_write(hdspm, HDSPM_midiDataOut0, val);
999}
1000
Takashi Iwai98274f02005-11-17 14:52:34 +01001001static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001002{
1003 if (id)
1004 return (hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff);
1005 else
1006 return (hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff);
1007}
1008
Takashi Iwai98274f02005-11-17 14:52:34 +01001009static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001010{
1011 int fifo_bytes_used;
1012
1013 if (id)
1014 fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xff;
1015 else
1016 fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xff;
1017
1018 if (fifo_bytes_used < 128)
1019 return 128 - fifo_bytes_used;
1020 else
1021 return 0;
1022}
1023
Takashi Iwai98274f02005-11-17 14:52:34 +01001024static inline void snd_hdspm_flush_midi_input (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001025{
1026 while (snd_hdspm_midi_input_available (hdspm, id))
1027 snd_hdspm_midi_read_byte (hdspm, id);
1028}
1029
Takashi Iwai98274f02005-11-17 14:52:34 +01001030static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001031{
1032 unsigned long flags;
1033 int n_pending;
1034 int to_write;
1035 int i;
1036 unsigned char buf[128];
1037
1038 /* Output is not interrupt driven */
1039
1040 spin_lock_irqsave (&hmidi->lock, flags);
1041 if (hmidi->output) {
1042 if (!snd_rawmidi_transmit_empty (hmidi->output)) {
1043 if ((n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, hmidi->id)) > 0) {
1044 if (n_pending > (int)sizeof (buf))
1045 n_pending = sizeof (buf);
1046
1047 if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {
1048 for (i = 0; i < to_write; ++i)
1049 snd_hdspm_midi_write_byte (hmidi->hdspm, hmidi->id, buf[i]);
1050 }
1051 }
1052 }
1053 }
1054 spin_unlock_irqrestore (&hmidi->lock, flags);
1055 return 0;
1056}
1057
Takashi Iwai98274f02005-11-17 14:52:34 +01001058static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001059{
1060 unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
1061 unsigned long flags;
1062 int n_pending;
1063 int i;
1064
1065 spin_lock_irqsave (&hmidi->lock, flags);
1066 if ((n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id)) > 0) {
1067 if (hmidi->input) {
1068 if (n_pending > (int)sizeof (buf)) {
1069 n_pending = sizeof (buf);
1070 }
1071 for (i = 0; i < n_pending; ++i) {
1072 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id);
1073 }
1074 if (n_pending) {
1075 snd_rawmidi_receive (hmidi->input, buf, n_pending);
1076 }
1077 } else {
1078 /* flush the MIDI input FIFO */
1079 while (n_pending--) {
1080 snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id);
1081 }
1082 }
1083 }
1084 hmidi->pending = 0;
1085 if (hmidi->id) {
1086 hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable;
1087 } else {
1088 hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable;
1089 }
1090 hdspm_write(hmidi->hdspm, HDSPM_controlRegister, hmidi->hdspm->control_register);
1091 spin_unlock_irqrestore (&hmidi->lock, flags);
1092 return snd_hdspm_midi_output_write (hmidi);
1093}
1094
Takashi Iwai98274f02005-11-17 14:52:34 +01001095static void snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001096{
Takashi Iwai98274f02005-11-17 14:52:34 +01001097 struct hdspm *hdspm;
1098 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001099 unsigned long flags;
1100 u32 ie;
1101
Takashi Iwai98274f02005-11-17 14:52:34 +01001102 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001103 hdspm = hmidi->hdspm;
1104 ie = hmidi->id ? HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable;
1105 spin_lock_irqsave (&hdspm->lock, flags);
1106 if (up) {
1107 if (!(hdspm->control_register & ie)) {
1108 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
1109 hdspm->control_register |= ie;
1110 }
1111 } else {
1112 hdspm->control_register &= ~ie;
1113 }
1114
1115 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1116 spin_unlock_irqrestore (&hdspm->lock, flags);
1117}
1118
1119static void snd_hdspm_midi_output_timer(unsigned long data)
1120{
Takashi Iwai98274f02005-11-17 14:52:34 +01001121 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001122 unsigned long flags;
1123
1124 snd_hdspm_midi_output_write(hmidi);
1125 spin_lock_irqsave (&hmidi->lock, flags);
1126
1127 /* this does not bump hmidi->istimer, because the
1128 kernel automatically removed the timer when it
1129 expired, and we are now adding it back, thus
1130 leaving istimer wherever it was set before.
1131 */
1132
1133 if (hmidi->istimer) {
1134 hmidi->timer.expires = 1 + jiffies;
1135 add_timer(&hmidi->timer);
1136 }
1137
1138 spin_unlock_irqrestore (&hmidi->lock, flags);
1139}
1140
Takashi Iwai98274f02005-11-17 14:52:34 +01001141static void snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001142{
Takashi Iwai98274f02005-11-17 14:52:34 +01001143 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001144 unsigned long flags;
1145
Takashi Iwai98274f02005-11-17 14:52:34 +01001146 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001147 spin_lock_irqsave (&hmidi->lock, flags);
1148 if (up) {
1149 if (!hmidi->istimer) {
1150 init_timer(&hmidi->timer);
1151 hmidi->timer.function = snd_hdspm_midi_output_timer;
1152 hmidi->timer.data = (unsigned long) hmidi;
1153 hmidi->timer.expires = 1 + jiffies;
1154 add_timer(&hmidi->timer);
1155 hmidi->istimer++;
1156 }
1157 } else {
1158 if (hmidi->istimer && --hmidi->istimer <= 0) {
1159 del_timer (&hmidi->timer);
1160 }
1161 }
1162 spin_unlock_irqrestore (&hmidi->lock, flags);
1163 if (up)
1164 snd_hdspm_midi_output_write(hmidi);
1165}
1166
Takashi Iwai98274f02005-11-17 14:52:34 +01001167static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001168{
Takashi Iwai98274f02005-11-17 14:52:34 +01001169 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001170
Takashi Iwai98274f02005-11-17 14:52:34 +01001171 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001172 spin_lock_irq (&hmidi->lock);
1173 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1174 hmidi->input = substream;
1175 spin_unlock_irq (&hmidi->lock);
1176
1177 return 0;
1178}
1179
Takashi Iwai98274f02005-11-17 14:52:34 +01001180static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001181{
Takashi Iwai98274f02005-11-17 14:52:34 +01001182 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001183
Takashi Iwai98274f02005-11-17 14:52:34 +01001184 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001185 spin_lock_irq (&hmidi->lock);
1186 hmidi->output = substream;
1187 spin_unlock_irq (&hmidi->lock);
1188
1189 return 0;
1190}
1191
Takashi Iwai98274f02005-11-17 14:52:34 +01001192static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001193{
Takashi Iwai98274f02005-11-17 14:52:34 +01001194 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001195
1196 snd_hdspm_midi_input_trigger (substream, 0);
1197
Takashi Iwai98274f02005-11-17 14:52:34 +01001198 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001199 spin_lock_irq (&hmidi->lock);
1200 hmidi->input = NULL;
1201 spin_unlock_irq (&hmidi->lock);
1202
1203 return 0;
1204}
1205
Takashi Iwai98274f02005-11-17 14:52:34 +01001206static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001207{
Takashi Iwai98274f02005-11-17 14:52:34 +01001208 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001209
1210 snd_hdspm_midi_output_trigger (substream, 0);
1211
Takashi Iwai98274f02005-11-17 14:52:34 +01001212 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001213 spin_lock_irq (&hmidi->lock);
1214 hmidi->output = NULL;
1215 spin_unlock_irq (&hmidi->lock);
1216
1217 return 0;
1218}
1219
Takashi Iwai98274f02005-11-17 14:52:34 +01001220static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001221{
1222 .open = snd_hdspm_midi_output_open,
1223 .close = snd_hdspm_midi_output_close,
1224 .trigger = snd_hdspm_midi_output_trigger,
1225};
1226
Takashi Iwai98274f02005-11-17 14:52:34 +01001227static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001228{
1229 .open = snd_hdspm_midi_input_open,
1230 .close = snd_hdspm_midi_input_close,
1231 .trigger = snd_hdspm_midi_input_trigger,
1232};
1233
Takashi Iwai98274f02005-11-17 14:52:34 +01001234static int __devinit snd_hdspm_create_midi (struct snd_card *card, struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001235{
1236 int err;
1237 char buf[32];
1238
1239 hdspm->midi[id].id = id;
1240 hdspm->midi[id].rmidi = NULL;
1241 hdspm->midi[id].input = NULL;
1242 hdspm->midi[id].output = NULL;
1243 hdspm->midi[id].hdspm = hdspm;
1244 hdspm->midi[id].istimer = 0;
1245 hdspm->midi[id].pending = 0;
1246 spin_lock_init (&hdspm->midi[id].lock);
1247
1248 sprintf (buf, "%s MIDI %d", card->shortname, id+1);
1249 if ((err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi)) < 0)
1250 return err;
1251
1252 sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);
1253 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
1254
1255 snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdspm_midi_output);
1256 snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdspm_midi_input);
1257
1258 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
1259 SNDRV_RAWMIDI_INFO_INPUT |
1260 SNDRV_RAWMIDI_INFO_DUPLEX;
1261
1262 return 0;
1263}
1264
1265
1266static void hdspm_midi_tasklet(unsigned long arg)
1267{
Takashi Iwai98274f02005-11-17 14:52:34 +01001268 struct hdspm *hdspm = (struct hdspm *)arg;
Takashi Iwai763f3562005-06-03 11:25:34 +02001269
1270 if (hdspm->midi[0].pending)
1271 snd_hdspm_midi_input_read (&hdspm->midi[0]);
1272 if (hdspm->midi[1].pending)
1273 snd_hdspm_midi_input_read (&hdspm->midi[1]);
1274}
1275
1276
1277/*-----------------------------------------------------------------------------
1278 Status Interface
1279 ----------------------------------------------------------------------------*/
1280
1281/* get the system sample rate which is set */
1282
1283#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001284{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001285 .name = xname, \
1286 .index = xindex, \
1287 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1288 .info = snd_hdspm_info_system_sample_rate, \
1289 .get = snd_hdspm_get_system_sample_rate \
1290}
1291
Takashi Iwai98274f02005-11-17 14:52:34 +01001292static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
1293 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001294{
1295 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1296 uinfo->count = 1;
1297 return 0;
1298}
1299
Takashi Iwai98274f02005-11-17 14:52:34 +01001300static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
1301 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02001302 ucontrol)
1303{
Takashi Iwai98274f02005-11-17 14:52:34 +01001304 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001305
1306 ucontrol->value.enumerated.item[0] = hdspm->system_sample_rate;
1307 return 0;
1308}
1309
1310#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001311{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001312 .name = xname, \
1313 .index = xindex, \
1314 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1315 .info = snd_hdspm_info_autosync_sample_rate, \
1316 .get = snd_hdspm_get_autosync_sample_rate \
1317}
1318
Takashi Iwai98274f02005-11-17 14:52:34 +01001319static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
1320 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001321{
1322 static char *texts[] = { "32000", "44100", "48000",
1323 "64000", "88200", "96000",
1324 "128000", "176400", "192000",
1325 "None"
1326 };
1327 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1328 uinfo->count = 1;
1329 uinfo->value.enumerated.items = 10;
1330 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1331 uinfo->value.enumerated.item =
1332 uinfo->value.enumerated.items - 1;
1333 strcpy(uinfo->value.enumerated.name,
1334 texts[uinfo->value.enumerated.item]);
1335 return 0;
1336}
1337
Takashi Iwai98274f02005-11-17 14:52:34 +01001338static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
1339 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02001340 ucontrol)
1341{
Takashi Iwai98274f02005-11-17 14:52:34 +01001342 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001343
1344 switch (hdspm_external_sample_rate(hdspm)) {
1345 case 32000:
1346 ucontrol->value.enumerated.item[0] = 0;
1347 break;
1348 case 44100:
1349 ucontrol->value.enumerated.item[0] = 1;
1350 break;
1351 case 48000:
1352 ucontrol->value.enumerated.item[0] = 2;
1353 break;
1354 case 64000:
1355 ucontrol->value.enumerated.item[0] = 3;
1356 break;
1357 case 88200:
1358 ucontrol->value.enumerated.item[0] = 4;
1359 break;
1360 case 96000:
1361 ucontrol->value.enumerated.item[0] = 5;
1362 break;
1363 case 128000:
1364 ucontrol->value.enumerated.item[0] = 6;
1365 break;
1366 case 176400:
1367 ucontrol->value.enumerated.item[0] = 7;
1368 break;
1369 case 192000:
1370 ucontrol->value.enumerated.item[0] = 8;
1371 break;
1372
1373 default:
1374 ucontrol->value.enumerated.item[0] = 9;
1375 }
1376 return 0;
1377}
1378
1379#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001380{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001381 .name = xname, \
1382 .index = xindex, \
1383 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1384 .info = snd_hdspm_info_system_clock_mode, \
1385 .get = snd_hdspm_get_system_clock_mode, \
1386}
1387
1388
1389
Takashi Iwai98274f02005-11-17 14:52:34 +01001390static int hdspm_system_clock_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001391{
1392 /* Always reflect the hardware info, rme is never wrong !!!! */
1393
1394 if (hdspm->control_register & HDSPM_ClockModeMaster)
1395 return 0;
1396 return 1;
1397}
1398
Takashi Iwai98274f02005-11-17 14:52:34 +01001399static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
1400 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001401{
1402 static char *texts[] = { "Master", "Slave" };
1403
1404 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1405 uinfo->count = 1;
1406 uinfo->value.enumerated.items = 2;
1407 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1408 uinfo->value.enumerated.item =
1409 uinfo->value.enumerated.items - 1;
1410 strcpy(uinfo->value.enumerated.name,
1411 texts[uinfo->value.enumerated.item]);
1412 return 0;
1413}
1414
Takashi Iwai98274f02005-11-17 14:52:34 +01001415static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
1416 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001417{
Takashi Iwai98274f02005-11-17 14:52:34 +01001418 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001419
1420 ucontrol->value.enumerated.item[0] =
1421 hdspm_system_clock_mode(hdspm);
1422 return 0;
1423}
1424
1425#define HDSPM_CLOCK_SOURCE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001426{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001427 .name = xname, \
1428 .index = xindex, \
1429 .info = snd_hdspm_info_clock_source, \
1430 .get = snd_hdspm_get_clock_source, \
1431 .put = snd_hdspm_put_clock_source \
1432}
1433
Takashi Iwai98274f02005-11-17 14:52:34 +01001434static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001435{
1436 if (hdspm->control_register & HDSPM_ClockModeMaster) {
1437 switch (hdspm->system_sample_rate) {
1438 case 32000:
1439 return 1;
1440 case 44100:
1441 return 2;
1442 case 48000:
1443 return 3;
1444 case 64000:
1445 return 4;
1446 case 88200:
1447 return 5;
1448 case 96000:
1449 return 6;
1450 case 128000:
1451 return 7;
1452 case 176400:
1453 return 8;
1454 case 192000:
1455 return 9;
1456 default:
1457 return 3;
1458 }
1459 } else {
1460 return 0;
1461 }
1462}
1463
Takashi Iwai98274f02005-11-17 14:52:34 +01001464static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02001465{
1466 int rate;
1467 switch (mode) {
1468
1469 case HDSPM_CLOCK_SOURCE_AUTOSYNC:
1470 if (hdspm_external_sample_rate(hdspm) != 0) {
1471 hdspm->control_register &= ~HDSPM_ClockModeMaster;
1472 hdspm_write(hdspm, HDSPM_controlRegister,
1473 hdspm->control_register);
1474 return 0;
1475 }
1476 return -1;
1477 case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
1478 rate = 32000;
1479 break;
1480 case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
1481 rate = 44100;
1482 break;
1483 case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
1484 rate = 48000;
1485 break;
1486 case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
1487 rate = 64000;
1488 break;
1489 case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
1490 rate = 88200;
1491 break;
1492 case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
1493 rate = 96000;
1494 break;
1495 case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
1496 rate = 128000;
1497 break;
1498 case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
1499 rate = 176400;
1500 break;
1501 case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
1502 rate = 192000;
1503 break;
1504
1505 default:
1506 rate = 44100;
1507 }
1508 hdspm->control_register |= HDSPM_ClockModeMaster;
1509 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1510 hdspm_set_rate(hdspm, rate, 1);
1511 return 0;
1512}
1513
Takashi Iwai98274f02005-11-17 14:52:34 +01001514static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
1515 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001516{
1517 static char *texts[] = { "AutoSync",
1518 "Internal 32.0 kHz", "Internal 44.1 kHz",
1519 "Internal 48.0 kHz",
1520 "Internal 64.0 kHz", "Internal 88.2 kHz",
1521 "Internal 96.0 kHz",
1522 "Internal 128.0 kHz", "Internal 176.4 kHz",
1523 "Internal 192.0 kHz"
1524 };
1525
1526 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1527 uinfo->count = 1;
1528 uinfo->value.enumerated.items = 10;
1529
1530 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1531 uinfo->value.enumerated.item =
1532 uinfo->value.enumerated.items - 1;
1533
1534 strcpy(uinfo->value.enumerated.name,
1535 texts[uinfo->value.enumerated.item]);
1536
1537 return 0;
1538}
1539
Takashi Iwai98274f02005-11-17 14:52:34 +01001540static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
1541 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001542{
Takashi Iwai98274f02005-11-17 14:52:34 +01001543 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001544
1545 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
1546 return 0;
1547}
1548
Takashi Iwai98274f02005-11-17 14:52:34 +01001549static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
1550 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001551{
Takashi Iwai98274f02005-11-17 14:52:34 +01001552 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001553 int change;
1554 int val;
1555
1556 if (!snd_hdspm_use_is_exclusive(hdspm))
1557 return -EBUSY;
1558 val = ucontrol->value.enumerated.item[0];
1559 if (val < 0)
1560 val = 0;
1561 if (val > 6)
1562 val = 6;
1563 spin_lock_irq(&hdspm->lock);
1564 if (val != hdspm_clock_source(hdspm))
1565 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
1566 else
1567 change = 0;
1568 spin_unlock_irq(&hdspm->lock);
1569 return change;
1570}
1571
1572#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001573{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001574 .name = xname, \
1575 .index = xindex, \
1576 .info = snd_hdspm_info_pref_sync_ref, \
1577 .get = snd_hdspm_get_pref_sync_ref, \
1578 .put = snd_hdspm_put_pref_sync_ref \
1579}
1580
Takashi Iwai98274f02005-11-17 14:52:34 +01001581static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001582{
1583 /* Notice that this looks at the requested sync source,
1584 not the one actually in use.
1585 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001586 if (hdspm->is_aes32) {
1587 switch (hdspm->control_register & HDSPM_SyncRefMask) {
1588 /* number gives AES index, except for 0 which
1589 corresponds to WordClock */
1590 case 0: return 0;
1591 case HDSPM_SyncRef0: return 1;
1592 case HDSPM_SyncRef1: return 2;
1593 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3;
1594 case HDSPM_SyncRef2: return 4;
1595 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5;
1596 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6;
1597 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0: return 7;
1598 case HDSPM_SyncRef3: return 8;
1599 }
1600 } else {
1601 switch (hdspm->control_register & HDSPM_SyncRefMask) {
1602 case HDSPM_SyncRef_Word:
1603 return HDSPM_SYNC_FROM_WORD;
1604 case HDSPM_SyncRef_MADI:
1605 return HDSPM_SYNC_FROM_MADI;
1606 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001607 }
1608
1609 return HDSPM_SYNC_FROM_WORD;
1610}
1611
Takashi Iwai98274f02005-11-17 14:52:34 +01001612static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02001613{
1614 hdspm->control_register &= ~HDSPM_SyncRefMask;
1615
Remy Bruno3cee5a62006-10-16 12:46:32 +02001616 if (hdspm->is_aes32) {
1617 switch (pref) {
1618 case 0:
1619 hdspm->control_register |= 0;
1620 break;
1621 case 1:
1622 hdspm->control_register |= HDSPM_SyncRef0;
1623 break;
1624 case 2:
1625 hdspm->control_register |= HDSPM_SyncRef1;
1626 break;
1627 case 3:
1628 hdspm->control_register |= HDSPM_SyncRef1+HDSPM_SyncRef0;
1629 break;
1630 case 4:
1631 hdspm->control_register |= HDSPM_SyncRef2;
1632 break;
1633 case 5:
1634 hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef0;
1635 break;
1636 case 6:
1637 hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1;
1638 break;
1639 case 7:
1640 hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
1641 break;
1642 case 8:
1643 hdspm->control_register |= HDSPM_SyncRef3;
1644 break;
1645 default:
1646 return -1;
1647 }
1648 } else {
1649 switch (pref) {
1650 case HDSPM_SYNC_FROM_MADI:
1651 hdspm->control_register |= HDSPM_SyncRef_MADI;
1652 break;
1653 case HDSPM_SYNC_FROM_WORD:
1654 hdspm->control_register |= HDSPM_SyncRef_Word;
1655 break;
1656 default:
1657 return -1;
1658 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001659 }
1660 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1661 return 0;
1662}
1663
Takashi Iwai98274f02005-11-17 14:52:34 +01001664static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
1665 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001666{
Remy Bruno3cee5a62006-10-16 12:46:32 +02001667 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001668
Remy Bruno3cee5a62006-10-16 12:46:32 +02001669 if (hdspm->is_aes32) {
1670 static char *texts[] = { "Word", "AES1", "AES2", "AES3",
1671 "AES4", "AES5", "AES6", "AES7", "AES8" };
Takashi Iwai763f3562005-06-03 11:25:34 +02001672
Remy Bruno3cee5a62006-10-16 12:46:32 +02001673 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1674 uinfo->count = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02001675
Remy Bruno3cee5a62006-10-16 12:46:32 +02001676 uinfo->value.enumerated.items = 9;
1677
1678 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1679 uinfo->value.enumerated.item =
1680 uinfo->value.enumerated.items - 1;
1681 strcpy(uinfo->value.enumerated.name,
1682 texts[uinfo->value.enumerated.item]);
1683 } else {
1684 static char *texts[] = { "Word", "MADI" };
1685
1686 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1687 uinfo->count = 1;
1688
1689 uinfo->value.enumerated.items = 2;
1690
1691 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1692 uinfo->value.enumerated.item =
1693 uinfo->value.enumerated.items - 1;
1694 strcpy(uinfo->value.enumerated.name,
1695 texts[uinfo->value.enumerated.item]);
1696 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001697 return 0;
1698}
1699
Takashi Iwai98274f02005-11-17 14:52:34 +01001700static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
1701 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001702{
Takashi Iwai98274f02005-11-17 14:52:34 +01001703 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001704
1705 ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
1706 return 0;
1707}
1708
Takashi Iwai98274f02005-11-17 14:52:34 +01001709static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
1710 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001711{
Takashi Iwai98274f02005-11-17 14:52:34 +01001712 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001713 int change, max;
1714 unsigned int val;
1715
Remy Bruno3cee5a62006-10-16 12:46:32 +02001716 max = hdspm->is_aes32 ? 9 : 2;
Takashi Iwai763f3562005-06-03 11:25:34 +02001717
1718 if (!snd_hdspm_use_is_exclusive(hdspm))
1719 return -EBUSY;
1720
1721 val = ucontrol->value.enumerated.item[0] % max;
1722
1723 spin_lock_irq(&hdspm->lock);
1724 change = (int) val != hdspm_pref_sync_ref(hdspm);
1725 hdspm_set_pref_sync_ref(hdspm, val);
1726 spin_unlock_irq(&hdspm->lock);
1727 return change;
1728}
1729
1730#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001731{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001732 .name = xname, \
1733 .index = xindex, \
1734 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1735 .info = snd_hdspm_info_autosync_ref, \
1736 .get = snd_hdspm_get_autosync_ref, \
1737}
1738
Takashi Iwai98274f02005-11-17 14:52:34 +01001739static int hdspm_autosync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001740{
Remy Bruno3cee5a62006-10-16 12:46:32 +02001741 if (hdspm->is_aes32) {
1742 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
1743 unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & 0xF;
1744 if (syncref == 0)
1745 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
1746 if (syncref <= 8)
1747 return syncref;
1748 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
1749 } else {
1750 /* This looks at the autosync selected sync reference */
1751 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Takashi Iwai763f3562005-06-03 11:25:34 +02001752
Remy Bruno3cee5a62006-10-16 12:46:32 +02001753 switch (status2 & HDSPM_SelSyncRefMask) {
1754 case HDSPM_SelSyncRef_WORD:
1755 return HDSPM_AUTOSYNC_FROM_WORD;
1756 case HDSPM_SelSyncRef_MADI:
1757 return HDSPM_AUTOSYNC_FROM_MADI;
1758 case HDSPM_SelSyncRef_NVALID:
1759 return HDSPM_AUTOSYNC_FROM_NONE;
1760 default:
1761 return 0;
1762 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001763
Takashi Iwai763f3562005-06-03 11:25:34 +02001764 return 0;
1765 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001766}
1767
Takashi Iwai98274f02005-11-17 14:52:34 +01001768static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
1769 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001770{
Remy Bruno3cee5a62006-10-16 12:46:32 +02001771 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001772
Remy Bruno3cee5a62006-10-16 12:46:32 +02001773 if (hdspm->is_aes32) {
1774 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
1775 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
1776
1777 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1778 uinfo->count = 1;
1779 uinfo->value.enumerated.items = 10;
1780 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1781 uinfo->value.enumerated.item =
1782 uinfo->value.enumerated.items - 1;
1783 strcpy(uinfo->value.enumerated.name,
1784 texts[uinfo->value.enumerated.item]);
1785 }
1786 else
1787 {
1788 static char *texts[] = { "WordClock", "MADI", "None" };
1789
1790 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1791 uinfo->count = 1;
1792 uinfo->value.enumerated.items = 3;
1793 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1794 uinfo->value.enumerated.item =
1795 uinfo->value.enumerated.items - 1;
1796 strcpy(uinfo->value.enumerated.name,
1797 texts[uinfo->value.enumerated.item]);
1798 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001799 return 0;
1800}
1801
Takashi Iwai98274f02005-11-17 14:52:34 +01001802static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
1803 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001804{
Takashi Iwai98274f02005-11-17 14:52:34 +01001805 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001806
1807 ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
1808 return 0;
1809}
1810
1811#define HDSPM_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001812{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001813 .name = xname, \
1814 .index = xindex, \
1815 .info = snd_hdspm_info_line_out, \
1816 .get = snd_hdspm_get_line_out, \
1817 .put = snd_hdspm_put_line_out \
1818}
1819
Takashi Iwai98274f02005-11-17 14:52:34 +01001820static int hdspm_line_out(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001821{
1822 return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
1823}
1824
1825
Takashi Iwai98274f02005-11-17 14:52:34 +01001826static int hdspm_set_line_output(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001827{
1828 if (out)
1829 hdspm->control_register |= HDSPM_LineOut;
1830 else
1831 hdspm->control_register &= ~HDSPM_LineOut;
1832 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1833
1834 return 0;
1835}
1836
Takashi Iwai98274f02005-11-17 14:52:34 +01001837static int snd_hdspm_info_line_out(struct snd_kcontrol *kcontrol,
1838 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001839{
1840 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1841 uinfo->count = 1;
1842 uinfo->value.integer.min = 0;
1843 uinfo->value.integer.max = 1;
1844 return 0;
1845}
1846
Takashi Iwai98274f02005-11-17 14:52:34 +01001847static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
1848 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001849{
Takashi Iwai98274f02005-11-17 14:52:34 +01001850 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001851
1852 spin_lock_irq(&hdspm->lock);
1853 ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
1854 spin_unlock_irq(&hdspm->lock);
1855 return 0;
1856}
1857
Takashi Iwai98274f02005-11-17 14:52:34 +01001858static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
1859 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001860{
Takashi Iwai98274f02005-11-17 14:52:34 +01001861 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001862 int change;
1863 unsigned int val;
1864
1865 if (!snd_hdspm_use_is_exclusive(hdspm))
1866 return -EBUSY;
1867 val = ucontrol->value.integer.value[0] & 1;
1868 spin_lock_irq(&hdspm->lock);
1869 change = (int) val != hdspm_line_out(hdspm);
1870 hdspm_set_line_output(hdspm, val);
1871 spin_unlock_irq(&hdspm->lock);
1872 return change;
1873}
1874
1875#define HDSPM_TX_64(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001876{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001877 .name = xname, \
1878 .index = xindex, \
1879 .info = snd_hdspm_info_tx_64, \
1880 .get = snd_hdspm_get_tx_64, \
1881 .put = snd_hdspm_put_tx_64 \
1882}
1883
Takashi Iwai98274f02005-11-17 14:52:34 +01001884static int hdspm_tx_64(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001885{
1886 return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
1887}
1888
Takashi Iwai98274f02005-11-17 14:52:34 +01001889static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001890{
1891 if (out)
1892 hdspm->control_register |= HDSPM_TX_64ch;
1893 else
1894 hdspm->control_register &= ~HDSPM_TX_64ch;
1895 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1896
1897 return 0;
1898}
1899
Takashi Iwai98274f02005-11-17 14:52:34 +01001900static int snd_hdspm_info_tx_64(struct snd_kcontrol *kcontrol,
1901 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001902{
1903 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1904 uinfo->count = 1;
1905 uinfo->value.integer.min = 0;
1906 uinfo->value.integer.max = 1;
1907 return 0;
1908}
1909
Takashi Iwai98274f02005-11-17 14:52:34 +01001910static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
1911 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001912{
Takashi Iwai98274f02005-11-17 14:52:34 +01001913 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001914
1915 spin_lock_irq(&hdspm->lock);
1916 ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
1917 spin_unlock_irq(&hdspm->lock);
1918 return 0;
1919}
1920
Takashi Iwai98274f02005-11-17 14:52:34 +01001921static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
1922 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001923{
Takashi Iwai98274f02005-11-17 14:52:34 +01001924 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001925 int change;
1926 unsigned int val;
1927
1928 if (!snd_hdspm_use_is_exclusive(hdspm))
1929 return -EBUSY;
1930 val = ucontrol->value.integer.value[0] & 1;
1931 spin_lock_irq(&hdspm->lock);
1932 change = (int) val != hdspm_tx_64(hdspm);
1933 hdspm_set_tx_64(hdspm, val);
1934 spin_unlock_irq(&hdspm->lock);
1935 return change;
1936}
1937
1938#define HDSPM_C_TMS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001939{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001940 .name = xname, \
1941 .index = xindex, \
1942 .info = snd_hdspm_info_c_tms, \
1943 .get = snd_hdspm_get_c_tms, \
1944 .put = snd_hdspm_put_c_tms \
1945}
1946
Takashi Iwai98274f02005-11-17 14:52:34 +01001947static int hdspm_c_tms(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001948{
1949 return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
1950}
1951
Takashi Iwai98274f02005-11-17 14:52:34 +01001952static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001953{
1954 if (out)
1955 hdspm->control_register |= HDSPM_clr_tms;
1956 else
1957 hdspm->control_register &= ~HDSPM_clr_tms;
1958 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1959
1960 return 0;
1961}
1962
Takashi Iwai98274f02005-11-17 14:52:34 +01001963static int snd_hdspm_info_c_tms(struct snd_kcontrol *kcontrol,
1964 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001965{
1966 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1967 uinfo->count = 1;
1968 uinfo->value.integer.min = 0;
1969 uinfo->value.integer.max = 1;
1970 return 0;
1971}
1972
Takashi Iwai98274f02005-11-17 14:52:34 +01001973static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
1974 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001975{
Takashi Iwai98274f02005-11-17 14:52:34 +01001976 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001977
1978 spin_lock_irq(&hdspm->lock);
1979 ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
1980 spin_unlock_irq(&hdspm->lock);
1981 return 0;
1982}
1983
Takashi Iwai98274f02005-11-17 14:52:34 +01001984static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
1985 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001986{
Takashi Iwai98274f02005-11-17 14:52:34 +01001987 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001988 int change;
1989 unsigned int val;
1990
1991 if (!snd_hdspm_use_is_exclusive(hdspm))
1992 return -EBUSY;
1993 val = ucontrol->value.integer.value[0] & 1;
1994 spin_lock_irq(&hdspm->lock);
1995 change = (int) val != hdspm_c_tms(hdspm);
1996 hdspm_set_c_tms(hdspm, val);
1997 spin_unlock_irq(&hdspm->lock);
1998 return change;
1999}
2000
2001#define HDSPM_SAFE_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002002{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002003 .name = xname, \
2004 .index = xindex, \
2005 .info = snd_hdspm_info_safe_mode, \
2006 .get = snd_hdspm_get_safe_mode, \
2007 .put = snd_hdspm_put_safe_mode \
2008}
2009
Takashi Iwai98274f02005-11-17 14:52:34 +01002010static int hdspm_safe_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002011{
2012 return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
2013}
2014
Takashi Iwai98274f02005-11-17 14:52:34 +01002015static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002016{
2017 if (out)
2018 hdspm->control_register |= HDSPM_AutoInp;
2019 else
2020 hdspm->control_register &= ~HDSPM_AutoInp;
2021 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2022
2023 return 0;
2024}
2025
Takashi Iwai98274f02005-11-17 14:52:34 +01002026static int snd_hdspm_info_safe_mode(struct snd_kcontrol *kcontrol,
2027 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002028{
2029 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2030 uinfo->count = 1;
2031 uinfo->value.integer.min = 0;
2032 uinfo->value.integer.max = 1;
2033 return 0;
2034}
2035
Takashi Iwai98274f02005-11-17 14:52:34 +01002036static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
2037 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002038{
Takashi Iwai98274f02005-11-17 14:52:34 +01002039 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002040
2041 spin_lock_irq(&hdspm->lock);
2042 ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
2043 spin_unlock_irq(&hdspm->lock);
2044 return 0;
2045}
2046
Takashi Iwai98274f02005-11-17 14:52:34 +01002047static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
2048 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002049{
Takashi Iwai98274f02005-11-17 14:52:34 +01002050 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002051 int change;
2052 unsigned int val;
2053
2054 if (!snd_hdspm_use_is_exclusive(hdspm))
2055 return -EBUSY;
2056 val = ucontrol->value.integer.value[0] & 1;
2057 spin_lock_irq(&hdspm->lock);
2058 change = (int) val != hdspm_safe_mode(hdspm);
2059 hdspm_set_safe_mode(hdspm, val);
2060 spin_unlock_irq(&hdspm->lock);
2061 return change;
2062}
2063
Remy Bruno3cee5a62006-10-16 12:46:32 +02002064#define HDSPM_EMPHASIS(xname, xindex) \
2065{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2066 .name = xname, \
2067 .index = xindex, \
2068 .info = snd_hdspm_info_emphasis, \
2069 .get = snd_hdspm_get_emphasis, \
2070 .put = snd_hdspm_put_emphasis \
2071}
2072
2073static int hdspm_emphasis(struct hdspm * hdspm)
2074{
2075 return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0;
2076}
2077
2078static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
2079{
2080 if (emp)
2081 hdspm->control_register |= HDSPM_Emphasis;
2082 else
2083 hdspm->control_register &= ~HDSPM_Emphasis;
2084 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2085
2086 return 0;
2087}
2088
2089static int snd_hdspm_info_emphasis(struct snd_kcontrol *kcontrol,
2090 struct snd_ctl_elem_info *uinfo)
2091{
2092 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2093 uinfo->count = 1;
2094 uinfo->value.integer.min = 0;
2095 uinfo->value.integer.max = 1;
2096 return 0;
2097}
2098
2099static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
2100 struct snd_ctl_elem_value *ucontrol)
2101{
2102 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2103
2104 spin_lock_irq(&hdspm->lock);
2105 ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm);
2106 spin_unlock_irq(&hdspm->lock);
2107 return 0;
2108}
2109
2110static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
2111 struct snd_ctl_elem_value *ucontrol)
2112{
2113 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2114 int change;
2115 unsigned int val;
2116
2117 if (!snd_hdspm_use_is_exclusive(hdspm))
2118 return -EBUSY;
2119 val = ucontrol->value.integer.value[0] & 1;
2120 spin_lock_irq(&hdspm->lock);
2121 change = (int) val != hdspm_emphasis(hdspm);
2122 hdspm_set_emphasis(hdspm, val);
2123 spin_unlock_irq(&hdspm->lock);
2124 return change;
2125}
2126
2127#define HDSPM_DOLBY(xname, xindex) \
2128{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2129 .name = xname, \
2130 .index = xindex, \
2131 .info = snd_hdspm_info_dolby, \
2132 .get = snd_hdspm_get_dolby, \
2133 .put = snd_hdspm_put_dolby \
2134}
2135
2136static int hdspm_dolby(struct hdspm * hdspm)
2137{
2138 return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0;
2139}
2140
2141static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
2142{
2143 if (dol)
2144 hdspm->control_register |= HDSPM_Dolby;
2145 else
2146 hdspm->control_register &= ~HDSPM_Dolby;
2147 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2148
2149 return 0;
2150}
2151
2152static int snd_hdspm_info_dolby(struct snd_kcontrol *kcontrol,
2153 struct snd_ctl_elem_info *uinfo)
2154{
2155 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2156 uinfo->count = 1;
2157 uinfo->value.integer.min = 0;
2158 uinfo->value.integer.max = 1;
2159 return 0;
2160}
2161
2162static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
2163 struct snd_ctl_elem_value *ucontrol)
2164{
2165 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2166
2167 spin_lock_irq(&hdspm->lock);
2168 ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm);
2169 spin_unlock_irq(&hdspm->lock);
2170 return 0;
2171}
2172
2173static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
2174 struct snd_ctl_elem_value *ucontrol)
2175{
2176 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2177 int change;
2178 unsigned int val;
2179
2180 if (!snd_hdspm_use_is_exclusive(hdspm))
2181 return -EBUSY;
2182 val = ucontrol->value.integer.value[0] & 1;
2183 spin_lock_irq(&hdspm->lock);
2184 change = (int) val != hdspm_dolby(hdspm);
2185 hdspm_set_dolby(hdspm, val);
2186 spin_unlock_irq(&hdspm->lock);
2187 return change;
2188}
2189
2190#define HDSPM_PROFESSIONAL(xname, xindex) \
2191{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2192 .name = xname, \
2193 .index = xindex, \
2194 .info = snd_hdspm_info_professional, \
2195 .get = snd_hdspm_get_professional, \
2196 .put = snd_hdspm_put_professional \
2197}
2198
2199static int hdspm_professional(struct hdspm * hdspm)
2200{
2201 return (hdspm->control_register & HDSPM_Professional) ? 1 : 0;
2202}
2203
2204static int hdspm_set_professional(struct hdspm * hdspm, int dol)
2205{
2206 if (dol)
2207 hdspm->control_register |= HDSPM_Professional;
2208 else
2209 hdspm->control_register &= ~HDSPM_Professional;
2210 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2211
2212 return 0;
2213}
2214
2215static int snd_hdspm_info_professional(struct snd_kcontrol *kcontrol,
2216 struct snd_ctl_elem_info *uinfo)
2217{
2218 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2219 uinfo->count = 1;
2220 uinfo->value.integer.min = 0;
2221 uinfo->value.integer.max = 1;
2222 return 0;
2223}
2224
2225static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
2226 struct snd_ctl_elem_value *ucontrol)
2227{
2228 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2229
2230 spin_lock_irq(&hdspm->lock);
2231 ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm);
2232 spin_unlock_irq(&hdspm->lock);
2233 return 0;
2234}
2235
2236static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
2237 struct snd_ctl_elem_value *ucontrol)
2238{
2239 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2240 int change;
2241 unsigned int val;
2242
2243 if (!snd_hdspm_use_is_exclusive(hdspm))
2244 return -EBUSY;
2245 val = ucontrol->value.integer.value[0] & 1;
2246 spin_lock_irq(&hdspm->lock);
2247 change = (int) val != hdspm_professional(hdspm);
2248 hdspm_set_professional(hdspm, val);
2249 spin_unlock_irq(&hdspm->lock);
2250 return change;
2251}
2252
Takashi Iwai763f3562005-06-03 11:25:34 +02002253#define HDSPM_INPUT_SELECT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002254{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002255 .name = xname, \
2256 .index = xindex, \
2257 .info = snd_hdspm_info_input_select, \
2258 .get = snd_hdspm_get_input_select, \
2259 .put = snd_hdspm_put_input_select \
2260}
2261
Takashi Iwai98274f02005-11-17 14:52:34 +01002262static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002263{
2264 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
2265}
2266
Takashi Iwai98274f02005-11-17 14:52:34 +01002267static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002268{
2269 if (out)
2270 hdspm->control_register |= HDSPM_InputSelect0;
2271 else
2272 hdspm->control_register &= ~HDSPM_InputSelect0;
2273 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2274
2275 return 0;
2276}
2277
Takashi Iwai98274f02005-11-17 14:52:34 +01002278static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
2279 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002280{
2281 static char *texts[] = { "optical", "coaxial" };
2282
2283 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2284 uinfo->count = 1;
2285 uinfo->value.enumerated.items = 2;
2286
2287 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2288 uinfo->value.enumerated.item =
2289 uinfo->value.enumerated.items - 1;
2290 strcpy(uinfo->value.enumerated.name,
2291 texts[uinfo->value.enumerated.item]);
2292
2293 return 0;
2294}
2295
Takashi Iwai98274f02005-11-17 14:52:34 +01002296static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
2297 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002298{
Takashi Iwai98274f02005-11-17 14:52:34 +01002299 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002300
2301 spin_lock_irq(&hdspm->lock);
2302 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
2303 spin_unlock_irq(&hdspm->lock);
2304 return 0;
2305}
2306
Takashi Iwai98274f02005-11-17 14:52:34 +01002307static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
2308 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002309{
Takashi Iwai98274f02005-11-17 14:52:34 +01002310 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002311 int change;
2312 unsigned int val;
2313
2314 if (!snd_hdspm_use_is_exclusive(hdspm))
2315 return -EBUSY;
2316 val = ucontrol->value.integer.value[0] & 1;
2317 spin_lock_irq(&hdspm->lock);
2318 change = (int) val != hdspm_input_select(hdspm);
2319 hdspm_set_input_select(hdspm, val);
2320 spin_unlock_irq(&hdspm->lock);
2321 return change;
2322}
2323
Remy Bruno3cee5a62006-10-16 12:46:32 +02002324#define HDSPM_DS_WIRE(xname, xindex) \
2325{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2326 .name = xname, \
2327 .index = xindex, \
2328 .info = snd_hdspm_info_ds_wire, \
2329 .get = snd_hdspm_get_ds_wire, \
2330 .put = snd_hdspm_put_ds_wire \
2331}
2332
2333static int hdspm_ds_wire(struct hdspm * hdspm)
2334{
2335 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
2336}
2337
2338static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
2339{
2340 if (ds)
2341 hdspm->control_register |= HDSPM_DS_DoubleWire;
2342 else
2343 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
2344 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2345
2346 return 0;
2347}
2348
2349static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
2350 struct snd_ctl_elem_info *uinfo)
2351{
2352 static char *texts[] = { "Single", "Double" };
2353
2354 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2355 uinfo->count = 1;
2356 uinfo->value.enumerated.items = 2;
2357
2358 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2359 uinfo->value.enumerated.item =
2360 uinfo->value.enumerated.items - 1;
2361 strcpy(uinfo->value.enumerated.name,
2362 texts[uinfo->value.enumerated.item]);
2363
2364 return 0;
2365}
2366
2367static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
2368 struct snd_ctl_elem_value *ucontrol)
2369{
2370 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2371
2372 spin_lock_irq(&hdspm->lock);
2373 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
2374 spin_unlock_irq(&hdspm->lock);
2375 return 0;
2376}
2377
2378static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
2379 struct snd_ctl_elem_value *ucontrol)
2380{
2381 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2382 int change;
2383 unsigned int val;
2384
2385 if (!snd_hdspm_use_is_exclusive(hdspm))
2386 return -EBUSY;
2387 val = ucontrol->value.integer.value[0] & 1;
2388 spin_lock_irq(&hdspm->lock);
2389 change = (int) val != hdspm_ds_wire(hdspm);
2390 hdspm_set_ds_wire(hdspm, val);
2391 spin_unlock_irq(&hdspm->lock);
2392 return change;
2393}
2394
2395#define HDSPM_QS_WIRE(xname, xindex) \
2396{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2397 .name = xname, \
2398 .index = xindex, \
2399 .info = snd_hdspm_info_qs_wire, \
2400 .get = snd_hdspm_get_qs_wire, \
2401 .put = snd_hdspm_put_qs_wire \
2402}
2403
2404static int hdspm_qs_wire(struct hdspm * hdspm)
2405{
2406 if (hdspm->control_register & HDSPM_QS_DoubleWire)
2407 return 1;
2408 if (hdspm->control_register & HDSPM_QS_QuadWire)
2409 return 2;
2410 return 0;
2411}
2412
2413static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
2414{
2415 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
2416 switch (mode) {
2417 case 0:
2418 break;
2419 case 1:
2420 hdspm->control_register |= HDSPM_QS_DoubleWire;
2421 break;
2422 case 2:
2423 hdspm->control_register |= HDSPM_QS_QuadWire;
2424 break;
2425 }
2426 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2427
2428 return 0;
2429}
2430
2431static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
2432 struct snd_ctl_elem_info *uinfo)
2433{
2434 static char *texts[] = { "Single", "Double", "Quad" };
2435
2436 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2437 uinfo->count = 1;
2438 uinfo->value.enumerated.items = 3;
2439
2440 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2441 uinfo->value.enumerated.item =
2442 uinfo->value.enumerated.items - 1;
2443 strcpy(uinfo->value.enumerated.name,
2444 texts[uinfo->value.enumerated.item]);
2445
2446 return 0;
2447}
2448
2449static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
2450 struct snd_ctl_elem_value *ucontrol)
2451{
2452 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2453
2454 spin_lock_irq(&hdspm->lock);
2455 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
2456 spin_unlock_irq(&hdspm->lock);
2457 return 0;
2458}
2459
2460static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
2461 struct snd_ctl_elem_value *ucontrol)
2462{
2463 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2464 int change;
2465 int val;
2466
2467 if (!snd_hdspm_use_is_exclusive(hdspm))
2468 return -EBUSY;
2469 val = ucontrol->value.integer.value[0];
2470 if (val < 0)
2471 val = 0;
2472 if (val > 2)
2473 val = 2;
2474 spin_lock_irq(&hdspm->lock);
2475 change = (int) val != hdspm_qs_wire(hdspm);
2476 hdspm_set_qs_wire(hdspm, val);
2477 spin_unlock_irq(&hdspm->lock);
2478 return change;
2479}
2480
Takashi Iwai763f3562005-06-03 11:25:34 +02002481/* Simple Mixer
2482 deprecated since to much faders ???
2483 MIXER interface says output (source, destination, value)
2484 where source > MAX_channels are playback channels
2485 on MADICARD
2486 - playback mixer matrix: [channelout+64] [output] [value]
2487 - input(thru) mixer matrix: [channelin] [output] [value]
2488 (better do 2 kontrols for seperation ?)
2489*/
2490
2491#define HDSPM_MIXER(xname, xindex) \
2492{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
2493 .name = xname, \
2494 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002495 .device = 0, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002496 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2497 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2498 .info = snd_hdspm_info_mixer, \
2499 .get = snd_hdspm_get_mixer, \
2500 .put = snd_hdspm_put_mixer \
2501}
2502
Takashi Iwai98274f02005-11-17 14:52:34 +01002503static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
2504 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002505{
2506 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2507 uinfo->count = 3;
2508 uinfo->value.integer.min = 0;
2509 uinfo->value.integer.max = 65535;
2510 uinfo->value.integer.step = 1;
2511 return 0;
2512}
2513
Takashi Iwai98274f02005-11-17 14:52:34 +01002514static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
2515 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002516{
Takashi Iwai98274f02005-11-17 14:52:34 +01002517 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002518 int source;
2519 int destination;
2520
2521 source = ucontrol->value.integer.value[0];
2522 if (source < 0)
2523 source = 0;
2524 else if (source >= 2 * HDSPM_MAX_CHANNELS)
2525 source = 2 * HDSPM_MAX_CHANNELS - 1;
2526
2527 destination = ucontrol->value.integer.value[1];
2528 if (destination < 0)
2529 destination = 0;
2530 else if (destination >= HDSPM_MAX_CHANNELS)
2531 destination = HDSPM_MAX_CHANNELS - 1;
2532
2533 spin_lock_irq(&hdspm->lock);
2534 if (source >= HDSPM_MAX_CHANNELS)
2535 ucontrol->value.integer.value[2] =
2536 hdspm_read_pb_gain(hdspm, destination,
2537 source - HDSPM_MAX_CHANNELS);
2538 else
2539 ucontrol->value.integer.value[2] =
2540 hdspm_read_in_gain(hdspm, destination, source);
2541
2542 spin_unlock_irq(&hdspm->lock);
2543
2544 return 0;
2545}
2546
Takashi Iwai98274f02005-11-17 14:52:34 +01002547static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
2548 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002549{
Takashi Iwai98274f02005-11-17 14:52:34 +01002550 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002551 int change;
2552 int source;
2553 int destination;
2554 int gain;
2555
2556 if (!snd_hdspm_use_is_exclusive(hdspm))
2557 return -EBUSY;
2558
2559 source = ucontrol->value.integer.value[0];
2560 destination = ucontrol->value.integer.value[1];
2561
2562 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
2563 return -1;
2564 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
2565 return -1;
2566
2567 gain = ucontrol->value.integer.value[2];
2568
2569 spin_lock_irq(&hdspm->lock);
2570
2571 if (source >= HDSPM_MAX_CHANNELS)
2572 change = gain != hdspm_read_pb_gain(hdspm, destination,
2573 source -
2574 HDSPM_MAX_CHANNELS);
2575 else
2576 change =
2577 gain != hdspm_read_in_gain(hdspm, destination, source);
2578
2579 if (change) {
2580 if (source >= HDSPM_MAX_CHANNELS)
2581 hdspm_write_pb_gain(hdspm, destination,
2582 source - HDSPM_MAX_CHANNELS,
2583 gain);
2584 else
2585 hdspm_write_in_gain(hdspm, destination, source,
2586 gain);
2587 }
2588 spin_unlock_irq(&hdspm->lock);
2589
2590 return change;
2591}
2592
2593/* The simple mixer control(s) provide gain control for the
2594 basic 1:1 mappings of playback streams to output
2595 streams.
2596*/
2597
2598#define HDSPM_PLAYBACK_MIXER \
2599{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2600 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
2601 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2602 .info = snd_hdspm_info_playback_mixer, \
2603 .get = snd_hdspm_get_playback_mixer, \
2604 .put = snd_hdspm_put_playback_mixer \
2605}
2606
Takashi Iwai98274f02005-11-17 14:52:34 +01002607static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
2608 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002609{
2610 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2611 uinfo->count = 1;
2612 uinfo->value.integer.min = 0;
2613 uinfo->value.integer.max = 65536;
2614 uinfo->value.integer.step = 1;
2615 return 0;
2616}
2617
Takashi Iwai98274f02005-11-17 14:52:34 +01002618static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
2619 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002620{
Takashi Iwai98274f02005-11-17 14:52:34 +01002621 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002622 int channel;
2623 int mapped_channel;
2624
2625 channel = ucontrol->id.index - 1;
2626
2627 snd_assert(channel >= 0
2628 || channel < HDSPM_MAX_CHANNELS, return -EINVAL);
2629
2630 if ((mapped_channel = hdspm->channel_map[channel]) < 0)
2631 return -EINVAL;
2632
2633 spin_lock_irq(&hdspm->lock);
2634 ucontrol->value.integer.value[0] =
2635 hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel);
2636 spin_unlock_irq(&hdspm->lock);
2637
2638 /* snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, value %d\n",
2639 ucontrol->id.index, channel, mapped_channel, ucontrol->value.integer.value[0]);
2640 */
2641
2642 return 0;
2643}
2644
Takashi Iwai98274f02005-11-17 14:52:34 +01002645static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
2646 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002647{
Takashi Iwai98274f02005-11-17 14:52:34 +01002648 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002649 int change;
2650 int channel;
2651 int mapped_channel;
2652 int gain;
2653
2654 if (!snd_hdspm_use_is_exclusive(hdspm))
2655 return -EBUSY;
2656
2657 channel = ucontrol->id.index - 1;
2658
2659 snd_assert(channel >= 0
2660 || channel < HDSPM_MAX_CHANNELS, return -EINVAL);
2661
2662 if ((mapped_channel = hdspm->channel_map[channel]) < 0)
2663 return -EINVAL;
2664
2665 gain = ucontrol->value.integer.value[0];
2666
2667 spin_lock_irq(&hdspm->lock);
2668 change =
2669 gain != hdspm_read_pb_gain(hdspm, mapped_channel,
2670 mapped_channel);
2671 if (change)
2672 hdspm_write_pb_gain(hdspm, mapped_channel, mapped_channel,
2673 gain);
2674 spin_unlock_irq(&hdspm->lock);
2675 return change;
2676}
2677
2678#define HDSPM_WC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002679{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002680 .name = xname, \
2681 .index = xindex, \
2682 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2683 .info = snd_hdspm_info_sync_check, \
2684 .get = snd_hdspm_get_wc_sync_check \
2685}
2686
Takashi Iwai98274f02005-11-17 14:52:34 +01002687static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
2688 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002689{
2690 static char *texts[] = { "No Lock", "Lock", "Sync" };
2691 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2692 uinfo->count = 1;
2693 uinfo->value.enumerated.items = 3;
2694 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2695 uinfo->value.enumerated.item =
2696 uinfo->value.enumerated.items - 1;
2697 strcpy(uinfo->value.enumerated.name,
2698 texts[uinfo->value.enumerated.item]);
2699 return 0;
2700}
2701
Takashi Iwai98274f02005-11-17 14:52:34 +01002702static int hdspm_wc_sync_check(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002703{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002704 if (hdspm->is_aes32) {
2705 int status = hdspm_read(hdspm, HDSPM_statusRegister);
2706 if (status & HDSPM_AES32_wcLock) {
2707 /* I don't know how to differenciate sync from lock.
2708 Doing as if sync for now */
Takashi Iwai763f3562005-06-03 11:25:34 +02002709 return 2;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002710 }
2711 return 0;
2712 } else {
2713 int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
2714 if (status2 & HDSPM_wcLock) {
2715 if (status2 & HDSPM_wcSync)
2716 return 2;
2717 else
2718 return 1;
2719 }
2720 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002721 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002722}
2723
Takashi Iwai98274f02005-11-17 14:52:34 +01002724static int snd_hdspm_get_wc_sync_check(struct snd_kcontrol *kcontrol,
2725 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002726{
Takashi Iwai98274f02005-11-17 14:52:34 +01002727 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002728
2729 ucontrol->value.enumerated.item[0] = hdspm_wc_sync_check(hdspm);
2730 return 0;
2731}
2732
2733
2734#define HDSPM_MADI_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002735{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002736 .name = xname, \
2737 .index = xindex, \
2738 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2739 .info = snd_hdspm_info_sync_check, \
2740 .get = snd_hdspm_get_madisync_sync_check \
2741}
2742
Takashi Iwai98274f02005-11-17 14:52:34 +01002743static int hdspm_madisync_sync_check(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002744{
2745 int status = hdspm_read(hdspm, HDSPM_statusRegister);
2746 if (status & HDSPM_madiLock) {
2747 if (status & HDSPM_madiSync)
2748 return 2;
2749 else
2750 return 1;
2751 }
2752 return 0;
2753}
2754
Takashi Iwai98274f02005-11-17 14:52:34 +01002755static int snd_hdspm_get_madisync_sync_check(struct snd_kcontrol *kcontrol,
2756 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002757 ucontrol)
2758{
Takashi Iwai98274f02005-11-17 14:52:34 +01002759 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002760
2761 ucontrol->value.enumerated.item[0] =
2762 hdspm_madisync_sync_check(hdspm);
2763 return 0;
2764}
2765
2766
Remy Bruno3cee5a62006-10-16 12:46:32 +02002767#define HDSPM_AES_SYNC_CHECK(xname, xindex) \
2768{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2769 .name = xname, \
2770 .index = xindex, \
2771 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2772 .info = snd_hdspm_info_sync_check, \
2773 .get = snd_hdspm_get_aes_sync_check \
2774}
2775
2776static int hdspm_aes_sync_check(struct hdspm * hdspm, int idx)
2777{
2778 int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
2779 if (status2 & (HDSPM_LockAES >> idx)) {
2780 /* I don't know how to differenciate sync from lock.
2781 Doing as if sync for now */
2782 return 2;
2783 }
2784 return 0;
2785}
2786
2787static int snd_hdspm_get_aes_sync_check(struct snd_kcontrol *kcontrol,
2788 struct snd_ctl_elem_value *ucontrol)
2789{
2790 int offset;
2791 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2792
2793 offset = ucontrol->id.index - 1;
2794 if (offset < 0 || offset >= 8)
2795 return -EINVAL;
2796
2797 ucontrol->value.enumerated.item[0] =
2798 hdspm_aes_sync_check(hdspm, offset);
2799 return 0;
2800}
Takashi Iwai763f3562005-06-03 11:25:34 +02002801
2802
Remy Bruno3cee5a62006-10-16 12:46:32 +02002803static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02002804
2805 HDSPM_MIXER("Mixer", 0),
2806/* 'Sample Clock Source' complies with the alsa control naming scheme */
2807 HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
2808
2809 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
2810 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
2811 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
2812 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
2813/* 'External Rate' complies with the alsa control naming scheme */
2814 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
2815 HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
2816 HDSPM_MADI_SYNC_CHECK("MADI Sync Lock Status", 0),
2817 HDSPM_LINE_OUT("Line Out", 0),
2818 HDSPM_TX_64("TX 64 channels mode", 0),
2819 HDSPM_C_TMS("Clear Track Marker", 0),
2820 HDSPM_SAFE_MODE("Safe Mode", 0),
2821 HDSPM_INPUT_SELECT("Input Select", 0),
2822};
2823
Remy Bruno3cee5a62006-10-16 12:46:32 +02002824static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
2825
2826 HDSPM_MIXER("Mixer", 0),
2827/* 'Sample Clock Source' complies with the alsa control naming scheme */
2828 HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
2829
2830 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
2831 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
2832 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
2833 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
2834/* 'External Rate' complies with the alsa control naming scheme */
2835 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
2836 HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
2837/* HDSPM_AES_SYNC_CHECK("AES Lock Status", 0),*/ /* created in snd_hdspm_create_controls() */
2838 HDSPM_LINE_OUT("Line Out", 0),
2839 HDSPM_EMPHASIS("Emphasis", 0),
2840 HDSPM_DOLBY("Non Audio", 0),
2841 HDSPM_PROFESSIONAL("Professional", 0),
2842 HDSPM_C_TMS("Clear Track Marker", 0),
2843 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
2844 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
2845};
2846
Takashi Iwai98274f02005-11-17 14:52:34 +01002847static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02002848
2849
Takashi Iwai98274f02005-11-17 14:52:34 +01002850static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002851{
2852 int i;
2853
2854 for (i = hdspm->ds_channels; i < hdspm->ss_channels; ++i) {
2855 if (hdspm->system_sample_rate > 48000) {
2856 hdspm->playback_mixer_ctls[i]->vd[0].access =
2857 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
2858 SNDRV_CTL_ELEM_ACCESS_READ |
2859 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
2860 } else {
2861 hdspm->playback_mixer_ctls[i]->vd[0].access =
2862 SNDRV_CTL_ELEM_ACCESS_READWRITE |
2863 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
2864 }
2865 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
2866 SNDRV_CTL_EVENT_MASK_INFO,
2867 &hdspm->playback_mixer_ctls[i]->id);
2868 }
2869
2870 return 0;
2871}
2872
2873
Takashi Iwai98274f02005-11-17 14:52:34 +01002874static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002875{
2876 unsigned int idx, limit;
2877 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01002878 struct snd_kcontrol *kctl;
Takashi Iwai763f3562005-06-03 11:25:34 +02002879
2880 /* add control list first */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002881 if (hdspm->is_aes32) {
2882 struct snd_kcontrol_new aes_sync_ctl =
2883 HDSPM_AES_SYNC_CHECK("AES Lock Status", 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02002884
Remy Bruno3cee5a62006-10-16 12:46:32 +02002885 for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_aes32);
2886 idx++) {
2887 err = snd_ctl_add(card,
2888 snd_ctl_new1(&snd_hdspm_controls_aes32[idx],
2889 hdspm));
2890 if (err < 0)
2891 return err;
2892 }
2893 for (idx = 1; idx <= 8; idx++) {
2894 aes_sync_ctl.index = idx;
2895 err = snd_ctl_add(card,
2896 snd_ctl_new1(&aes_sync_ctl, hdspm));
2897 if (err < 0)
2898 return err;
2899 }
2900 } else {
2901 for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_madi);
2902 idx++) {
2903 err = snd_ctl_add(card,
2904 snd_ctl_new1(&snd_hdspm_controls_madi[idx],
2905 hdspm));
2906 if (err < 0)
2907 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02002908 }
2909 }
2910
2911 /* Channel playback mixer as default control
Remy Bruno3cee5a62006-10-16 12:46:32 +02002912Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats too big for any alsamixer
2913they are accesible via special IOCTL on hwdep
2914and the mixer 2dimensional mixer control */
Takashi Iwai763f3562005-06-03 11:25:34 +02002915
2916 snd_hdspm_playback_mixer.name = "Chn";
2917 limit = HDSPM_MAX_CHANNELS;
2918
2919 /* The index values are one greater than the channel ID so that alsamixer
2920 will display them correctly. We want to use the index for fast lookup
2921 of the relevant channel, but if we use it at all, most ALSA software
2922 does the wrong thing with it ...
2923 */
2924
2925 for (idx = 0; idx < limit; ++idx) {
2926 snd_hdspm_playback_mixer.index = idx + 1;
2927 if ((err = snd_ctl_add(card,
2928 kctl =
2929 snd_ctl_new1
2930 (&snd_hdspm_playback_mixer,
2931 hdspm)))) {
2932 return err;
2933 }
2934 hdspm->playback_mixer_ctls[idx] = kctl;
2935 }
2936
2937 return 0;
2938}
2939
2940/*------------------------------------------------------------
2941 /proc interface
2942 ------------------------------------------------------------*/
2943
2944static void
Remy Bruno3cee5a62006-10-16 12:46:32 +02002945snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
2946 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02002947{
Takashi Iwai98274f02005-11-17 14:52:34 +01002948 struct hdspm *hdspm = (struct hdspm *) entry->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02002949 unsigned int status;
2950 unsigned int status2;
2951 char *pref_sync_ref;
2952 char *autosync_ref;
2953 char *system_clock_mode;
2954 char *clock_source;
2955 char *insel;
2956 char *syncref;
2957 int x, x2;
2958
2959 status = hdspm_read(hdspm, HDSPM_statusRegister);
2960 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
2961
2962 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
2963 hdspm->card_name, hdspm->card->number + 1,
2964 hdspm->firmware_rev,
2965 (status2 & HDSPM_version0) |
2966 (status2 & HDSPM_version1) | (status2 &
2967 HDSPM_version2));
2968
2969 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
2970 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
2971
2972 snd_iprintf(buffer, "--- System ---\n");
2973
2974 snd_iprintf(buffer,
2975 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
2976 status & HDSPM_audioIRQPending,
2977 (status & HDSPM_midi0IRQPending) ? 1 : 0,
2978 (status & HDSPM_midi1IRQPending) ? 1 : 0,
2979 hdspm->irq_count);
2980 snd_iprintf(buffer,
2981 "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n",
2982 ((status & HDSPM_BufferID) ? 1 : 0),
2983 (status & HDSPM_BufferPositionMask),
2984 (status & HDSPM_BufferPositionMask) % (2 *
2985 (int)hdspm->
2986 period_bytes),
2987 ((status & HDSPM_BufferPositionMask) -
2988 64) % (2 * (int)hdspm->period_bytes),
2989 (long) hdspm_hw_pointer(hdspm) * 4);
2990
2991 snd_iprintf(buffer,
2992 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
2993 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
2994 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
2995 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
2996 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
2997 snd_iprintf(buffer,
2998 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x\n",
2999 hdspm->control_register, hdspm->control2_register,
3000 status, status2);
3001
3002 snd_iprintf(buffer, "--- Settings ---\n");
3003
3004 x = 1 << (6 +
3005 hdspm_decode_latency(hdspm->
3006 control_register &
3007 HDSPM_LatencyMask));
3008
3009 snd_iprintf(buffer,
3010 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
3011 x, (unsigned long) hdspm->period_bytes);
3012
3013 snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n",
3014 (hdspm->
3015 control_register & HDSPM_LineOut) ? "on " : "off",
3016 (hdspm->precise_ptr) ? "on" : "off");
3017
3018 switch (hdspm->control_register & HDSPM_InputMask) {
3019 case HDSPM_InputOptical:
3020 insel = "Optical";
3021 break;
3022 case HDSPM_InputCoaxial:
3023 insel = "Coaxial";
3024 break;
3025 default:
3026 insel = "Unkown";
3027 }
3028
3029 switch (hdspm->control_register & HDSPM_SyncRefMask) {
3030 case HDSPM_SyncRef_Word:
3031 syncref = "WordClock";
3032 break;
3033 case HDSPM_SyncRef_MADI:
3034 syncref = "MADI";
3035 break;
3036 default:
3037 syncref = "Unkown";
3038 }
3039 snd_iprintf(buffer, "Inputsel = %s, SyncRef = %s\n", insel,
3040 syncref);
3041
3042 snd_iprintf(buffer,
3043 "ClearTrackMarker = %s, Transmit in %s Channel Mode, Auto Input %s\n",
3044 (hdspm->
3045 control_register & HDSPM_clr_tms) ? "on" : "off",
3046 (hdspm->
3047 control_register & HDSPM_TX_64ch) ? "64" : "56",
3048 (hdspm->
3049 control_register & HDSPM_AutoInp) ? "on" : "off");
3050
3051 switch (hdspm_clock_source(hdspm)) {
3052 case HDSPM_CLOCK_SOURCE_AUTOSYNC:
3053 clock_source = "AutoSync";
3054 break;
3055 case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
3056 clock_source = "Internal 32 kHz";
3057 break;
3058 case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
3059 clock_source = "Internal 44.1 kHz";
3060 break;
3061 case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
3062 clock_source = "Internal 48 kHz";
3063 break;
3064 case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
3065 clock_source = "Internal 64 kHz";
3066 break;
3067 case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
3068 clock_source = "Internal 88.2 kHz";
3069 break;
3070 case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
3071 clock_source = "Internal 96 kHz";
3072 break;
3073 default:
3074 clock_source = "Error";
3075 }
3076 snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003077 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Takashi Iwai763f3562005-06-03 11:25:34 +02003078 system_clock_mode = "Slave";
Remy Bruno3cee5a62006-10-16 12:46:32 +02003079 else
Takashi Iwai763f3562005-06-03 11:25:34 +02003080 system_clock_mode = "Master";
Takashi Iwai763f3562005-06-03 11:25:34 +02003081 snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
3082
3083 switch (hdspm_pref_sync_ref(hdspm)) {
3084 case HDSPM_SYNC_FROM_WORD:
3085 pref_sync_ref = "Word Clock";
3086 break;
3087 case HDSPM_SYNC_FROM_MADI:
3088 pref_sync_ref = "MADI Sync";
3089 break;
3090 default:
3091 pref_sync_ref = "XXXX Clock";
3092 break;
3093 }
3094 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
3095 pref_sync_ref);
3096
3097 snd_iprintf(buffer, "System Clock Frequency: %d\n",
3098 hdspm->system_sample_rate);
3099
3100
3101 snd_iprintf(buffer, "--- Status:\n");
3102
3103 x = status & HDSPM_madiSync;
3104 x2 = status2 & HDSPM_wcSync;
3105
3106 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
3107 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
3108 "NoLock",
3109 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
3110 "NoLock");
3111
3112 switch (hdspm_autosync_ref(hdspm)) {
3113 case HDSPM_AUTOSYNC_FROM_WORD:
3114 autosync_ref = "Word Clock";
3115 break;
3116 case HDSPM_AUTOSYNC_FROM_MADI:
3117 autosync_ref = "MADI Sync";
3118 break;
3119 case HDSPM_AUTOSYNC_FROM_NONE:
3120 autosync_ref = "Input not valid";
3121 break;
3122 default:
3123 autosync_ref = "---";
3124 break;
3125 }
3126 snd_iprintf(buffer,
3127 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
3128 autosync_ref, hdspm_external_sample_rate(hdspm),
3129 (status & HDSPM_madiFreqMask) >> 22,
3130 (status2 & HDSPM_wcFreqMask) >> 5);
3131
3132 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
3133 (status & HDSPM_AB_int) ? "Coax" : "Optical",
3134 (status & HDSPM_RX_64ch) ? "64 channels" :
3135 "56 channels");
3136
3137 snd_iprintf(buffer, "\n");
3138}
3139
Remy Bruno3cee5a62006-10-16 12:46:32 +02003140static void
3141snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
3142 struct snd_info_buffer *buffer)
3143{
3144 struct hdspm *hdspm = (struct hdspm *) entry->private_data;
3145 unsigned int status;
3146 unsigned int status2;
3147 unsigned int timecode;
3148 int pref_syncref;
3149 char *autosync_ref;
3150 char *system_clock_mode;
3151 char *clock_source;
3152 int x;
3153
3154 status = hdspm_read(hdspm, HDSPM_statusRegister);
3155 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3156 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
3157
3158 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
3159 hdspm->card_name, hdspm->card->number + 1,
3160 hdspm->firmware_rev);
3161
3162 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
3163 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
3164
3165 snd_iprintf(buffer, "--- System ---\n");
3166
3167 snd_iprintf(buffer,
3168 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
3169 status & HDSPM_audioIRQPending,
3170 (status & HDSPM_midi0IRQPending) ? 1 : 0,
3171 (status & HDSPM_midi1IRQPending) ? 1 : 0,
3172 hdspm->irq_count);
3173 snd_iprintf(buffer,
3174 "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n",
3175 ((status & HDSPM_BufferID) ? 1 : 0),
3176 (status & HDSPM_BufferPositionMask),
3177 (status & HDSPM_BufferPositionMask) % (2 *
3178 (int)hdspm->
3179 period_bytes),
3180 ((status & HDSPM_BufferPositionMask) -
3181 64) % (2 * (int)hdspm->period_bytes),
3182 (long) hdspm_hw_pointer(hdspm) * 4);
3183
3184 snd_iprintf(buffer,
3185 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
3186 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
3187 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
3188 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
3189 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
3190 snd_iprintf(buffer,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003191 "Register: ctrl1=0x%x, status1=0x%x, status2=0x%x, timecode=0x%x\n",
3192 hdspm->control_register,
Remy Bruno3cee5a62006-10-16 12:46:32 +02003193 status, status2, timecode);
3194
3195 snd_iprintf(buffer, "--- Settings ---\n");
3196
3197 x = 1 << (6 +
3198 hdspm_decode_latency(hdspm->
3199 control_register &
3200 HDSPM_LatencyMask));
3201
3202 snd_iprintf(buffer,
3203 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
3204 x, (unsigned long) hdspm->period_bytes);
3205
3206 snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n",
3207 (hdspm->
3208 control_register & HDSPM_LineOut) ? "on " : "off",
3209 (hdspm->precise_ptr) ? "on" : "off");
3210
3211 snd_iprintf(buffer,
3212 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
3213 (hdspm->
3214 control_register & HDSPM_clr_tms) ? "on" : "off",
3215 (hdspm->
3216 control_register & HDSPM_Emphasis) ? "on" : "off",
3217 (hdspm->
3218 control_register & HDSPM_Dolby) ? "on" : "off");
3219
3220 switch (hdspm_clock_source(hdspm)) {
3221 case HDSPM_CLOCK_SOURCE_AUTOSYNC:
3222 clock_source = "AutoSync";
3223 break;
3224 case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
3225 clock_source = "Internal 32 kHz";
3226 break;
3227 case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
3228 clock_source = "Internal 44.1 kHz";
3229 break;
3230 case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
3231 clock_source = "Internal 48 kHz";
3232 break;
3233 case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
3234 clock_source = "Internal 64 kHz";
3235 break;
3236 case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
3237 clock_source = "Internal 88.2 kHz";
3238 break;
3239 case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
3240 clock_source = "Internal 96 kHz";
3241 break;
3242 case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
3243 clock_source = "Internal 128 kHz";
3244 break;
3245 case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
3246 clock_source = "Internal 176.4 kHz";
3247 break;
3248 case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
3249 clock_source = "Internal 192 kHz";
3250 break;
3251 default:
3252 clock_source = "Error";
3253 }
3254 snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
3255 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
3256 system_clock_mode = "Slave";
3257 else
3258 system_clock_mode = "Master";
3259 snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
3260
3261 pref_syncref = hdspm_pref_sync_ref(hdspm);
3262 if (pref_syncref == 0)
3263 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
3264 else
3265 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
3266 pref_syncref);
3267
3268 snd_iprintf(buffer, "System Clock Frequency: %d\n",
3269 hdspm->system_sample_rate);
3270
3271 snd_iprintf(buffer, "Double speed: %s\n",
3272 hdspm->control_register & HDSPM_DS_DoubleWire?
3273 "Double wire" : "Single wire");
3274 snd_iprintf(buffer, "Quad speed: %s\n",
3275 hdspm->control_register & HDSPM_QS_DoubleWire?
3276 "Double wire" :
3277 hdspm->control_register & HDSPM_QS_QuadWire?
3278 "Quad wire" : "Single wire");
3279
3280 snd_iprintf(buffer, "--- Status:\n");
3281
3282 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
3283 (status & HDSPM_AES32_wcLock)? "Sync " : "No Lock",
3284 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
3285
3286 for (x = 0; x < 8; x++) {
3287 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
3288 x+1,
3289 (status2 & (HDSPM_LockAES >> x))? "Sync ": "No Lock",
3290 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
3291 }
3292
3293 switch (hdspm_autosync_ref(hdspm)) {
3294 case HDSPM_AES32_AUTOSYNC_FROM_NONE: autosync_ref="None"; break;
3295 case HDSPM_AES32_AUTOSYNC_FROM_WORD: autosync_ref="Word Clock"; break;
3296 case HDSPM_AES32_AUTOSYNC_FROM_AES1: autosync_ref="AES1"; break;
3297 case HDSPM_AES32_AUTOSYNC_FROM_AES2: autosync_ref="AES2"; break;
3298 case HDSPM_AES32_AUTOSYNC_FROM_AES3: autosync_ref="AES3"; break;
3299 case HDSPM_AES32_AUTOSYNC_FROM_AES4: autosync_ref="AES4"; break;
3300 case HDSPM_AES32_AUTOSYNC_FROM_AES5: autosync_ref="AES5"; break;
3301 case HDSPM_AES32_AUTOSYNC_FROM_AES6: autosync_ref="AES6"; break;
3302 case HDSPM_AES32_AUTOSYNC_FROM_AES7: autosync_ref="AES7"; break;
3303 case HDSPM_AES32_AUTOSYNC_FROM_AES8: autosync_ref="AES8"; break;
3304 default: autosync_ref = "---"; break;
3305 }
3306 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
3307
3308 snd_iprintf(buffer, "\n");
3309}
3310
3311#ifdef CONFIG_SND_DEBUG
3312static void
3313snd_hdspm_proc_read_debug(struct snd_info_entry * entry,
3314 struct snd_info_buffer *buffer)
3315{
3316 struct hdspm *hdspm = (struct hdspm *)entry->private_data;
3317
3318 int j,i;
3319
3320 for (i = 0; i < 256 /* 1024*64 */; i += j)
3321 {
3322 snd_iprintf(buffer, "0x%08X: ", i);
3323 for (j = 0; j < 16; j += 4)
3324 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
3325 snd_iprintf(buffer, "\n");
3326 }
3327}
3328#endif
3329
3330
3331
Takashi Iwai98274f02005-11-17 14:52:34 +01003332static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003333{
Takashi Iwai98274f02005-11-17 14:52:34 +01003334 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02003335
3336 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry))
Takashi Iwaibf850202006-04-28 15:13:41 +02003337 snd_info_set_text_ops(entry, hdspm,
Remy Bruno3cee5a62006-10-16 12:46:32 +02003338 hdspm->is_aes32 ?
3339 snd_hdspm_proc_read_aes32 :
3340 snd_hdspm_proc_read_madi);
3341#ifdef CONFIG_SND_DEBUG
3342 /* debug file to read all hdspm registers */
3343 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
3344 snd_info_set_text_ops(entry, hdspm,
3345 snd_hdspm_proc_read_debug);
3346#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02003347}
3348
3349/*------------------------------------------------------------
3350 hdspm intitialize
3351 ------------------------------------------------------------*/
3352
Takashi Iwai98274f02005-11-17 14:52:34 +01003353static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003354{
3355 unsigned int i;
3356
3357 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
3358 hold it (e.g. during module initalization).
3359 */
3360
3361 /* set defaults: */
3362
Remy Bruno3cee5a62006-10-16 12:46:32 +02003363 if (hdspm->is_aes32)
3364 hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */
3365 hdspm_encode_latency(7) | /* latency maximum = 8192 samples */
3366 HDSPM_SyncRef0 | /* AES1 is syncclock */
3367 HDSPM_LineOut | /* Analog output in */
3368 HDSPM_Professional; /* Professional mode */
3369 else
3370 hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */
3371 hdspm_encode_latency(7) | /* latency maximum = 8192 samples */
3372 HDSPM_InputCoaxial | /* Input Coax not Optical */
3373 HDSPM_SyncRef_MADI | /* Madi is syncclock */
3374 HDSPM_LineOut | /* Analog output in */
3375 HDSPM_TX_64ch | /* transmit in 64ch mode */
3376 HDSPM_AutoInp; /* AutoInput chossing (takeover) */
Takashi Iwai763f3562005-06-03 11:25:34 +02003377
3378 /* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */
3379 /* ! HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */
3380 /* ! HDSPM_clr_tms = do not clear bits in track marks */
3381
3382 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3383
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003384 if (!hdspm->is_aes32) {
3385 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02003386#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003387 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02003388#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003389 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02003390#endif
3391
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003392 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
3393 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003394 hdspm_compute_period_size(hdspm);
3395
3396 /* silence everything */
3397
3398 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
3399
3400 if (line_outs_monitor[hdspm->dev]) {
3401
3402 snd_printk(KERN_INFO "HDSPM: sending all playback streams to line outs.\n");
3403
3404 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) {
3405 if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN))
3406 return -EIO;
3407 }
3408 }
3409
3410 /* set a default rate so that the channel map is set up. */
3411 hdspm->channel_map = channel_map_madi_ss;
3412 hdspm_set_rate(hdspm, 44100, 1);
3413
3414 return 0;
3415}
3416
3417
3418/*------------------------------------------------------------
3419 interupt
3420 ------------------------------------------------------------*/
3421
David Howells7d12e782006-10-05 14:55:46 +01003422static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02003423{
Takashi Iwai98274f02005-11-17 14:52:34 +01003424 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02003425 unsigned int status;
3426 int audio;
3427 int midi0;
3428 int midi1;
3429 unsigned int midi0status;
3430 unsigned int midi1status;
3431 int schedule = 0;
3432
3433 status = hdspm_read(hdspm, HDSPM_statusRegister);
3434
3435 audio = status & HDSPM_audioIRQPending;
3436 midi0 = status & HDSPM_midi0IRQPending;
3437 midi1 = status & HDSPM_midi1IRQPending;
3438
3439 if (!audio && !midi0 && !midi1)
3440 return IRQ_NONE;
3441
3442 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
3443 hdspm->irq_count++;
3444
3445 midi0status = hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff;
3446 midi1status = hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff;
3447
3448 if (audio) {
3449
3450 if (hdspm->capture_substream)
3451 snd_pcm_period_elapsed(hdspm->pcm->
3452 streams
3453 [SNDRV_PCM_STREAM_CAPTURE].
3454 substream);
3455
3456 if (hdspm->playback_substream)
3457 snd_pcm_period_elapsed(hdspm->pcm->
3458 streams
3459 [SNDRV_PCM_STREAM_PLAYBACK].
3460 substream);
3461 }
3462
3463 if (midi0 && midi0status) {
3464 /* we disable interrupts for this input until processing is done */
3465 hdspm->control_register &= ~HDSPM_Midi0InterruptEnable;
3466 hdspm_write(hdspm, HDSPM_controlRegister,
3467 hdspm->control_register);
3468 hdspm->midi[0].pending = 1;
3469 schedule = 1;
3470 }
3471 if (midi1 && midi1status) {
3472 /* we disable interrupts for this input until processing is done */
3473 hdspm->control_register &= ~HDSPM_Midi1InterruptEnable;
3474 hdspm_write(hdspm, HDSPM_controlRegister,
3475 hdspm->control_register);
3476 hdspm->midi[1].pending = 1;
3477 schedule = 1;
3478 }
3479 if (schedule)
3480 tasklet_hi_schedule(&hdspm->midi_tasklet);
3481 return IRQ_HANDLED;
3482}
3483
3484/*------------------------------------------------------------
3485 pcm interface
3486 ------------------------------------------------------------*/
3487
3488
Takashi Iwai98274f02005-11-17 14:52:34 +01003489static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream *
Takashi Iwai763f3562005-06-03 11:25:34 +02003490 substream)
3491{
Takashi Iwai98274f02005-11-17 14:52:34 +01003492 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003493 return hdspm_hw_pointer(hdspm);
3494}
3495
Takashi Iwai98274f02005-11-17 14:52:34 +01003496static char *hdspm_channel_buffer_location(struct hdspm * hdspm,
Takashi Iwai763f3562005-06-03 11:25:34 +02003497 int stream, int channel)
3498{
3499 int mapped_channel;
3500
3501 snd_assert(channel >= 0
3502 || channel < HDSPM_MAX_CHANNELS, return NULL);
3503
3504 if ((mapped_channel = hdspm->channel_map[channel]) < 0)
3505 return NULL;
3506
3507 if (stream == SNDRV_PCM_STREAM_CAPTURE) {
3508 return hdspm->capture_buffer +
3509 mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
3510 } else {
3511 return hdspm->playback_buffer +
3512 mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
3513 }
3514}
3515
3516
3517/* dont know why need it ??? */
Takashi Iwai98274f02005-11-17 14:52:34 +01003518static int snd_hdspm_playback_copy(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02003519 int channel, snd_pcm_uframes_t pos,
3520 void __user *src, snd_pcm_uframes_t count)
3521{
Takashi Iwai98274f02005-11-17 14:52:34 +01003522 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003523 char *channel_buf;
3524
3525 snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
3526 return -EINVAL);
3527
3528 channel_buf = hdspm_channel_buffer_location(hdspm,
3529 substream->pstr->
3530 stream, channel);
3531
3532 snd_assert(channel_buf != NULL, return -EIO);
3533
3534 return copy_from_user(channel_buf + pos * 4, src, count * 4);
3535}
3536
Takashi Iwai98274f02005-11-17 14:52:34 +01003537static int snd_hdspm_capture_copy(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02003538 int channel, snd_pcm_uframes_t pos,
3539 void __user *dst, snd_pcm_uframes_t count)
3540{
Takashi Iwai98274f02005-11-17 14:52:34 +01003541 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003542 char *channel_buf;
3543
3544 snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
3545 return -EINVAL);
3546
3547 channel_buf = hdspm_channel_buffer_location(hdspm,
3548 substream->pstr->
3549 stream, channel);
3550 snd_assert(channel_buf != NULL, return -EIO);
3551 return copy_to_user(dst, channel_buf + pos * 4, count * 4);
3552}
3553
Takashi Iwai98274f02005-11-17 14:52:34 +01003554static int snd_hdspm_hw_silence(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02003555 int channel, snd_pcm_uframes_t pos,
3556 snd_pcm_uframes_t count)
3557{
Takashi Iwai98274f02005-11-17 14:52:34 +01003558 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003559 char *channel_buf;
3560
3561 channel_buf =
3562 hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
3563 channel);
3564 snd_assert(channel_buf != NULL, return -EIO);
3565 memset(channel_buf + pos * 4, 0, count * 4);
3566 return 0;
3567}
3568
Takashi Iwai98274f02005-11-17 14:52:34 +01003569static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003570{
Takashi Iwai98274f02005-11-17 14:52:34 +01003571 struct snd_pcm_runtime *runtime = substream->runtime;
3572 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
3573 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02003574
3575 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3576 other = hdspm->capture_substream;
3577 else
3578 other = hdspm->playback_substream;
3579
3580 if (hdspm->running)
3581 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
3582 else
3583 runtime->status->hw_ptr = 0;
3584 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003585 struct snd_pcm_substream *s;
3586 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01003587 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02003588 if (s == other) {
3589 oruntime->status->hw_ptr =
3590 runtime->status->hw_ptr;
3591 break;
3592 }
3593 }
3594 }
3595 return 0;
3596}
3597
Takashi Iwai98274f02005-11-17 14:52:34 +01003598static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
3599 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02003600{
Takashi Iwai98274f02005-11-17 14:52:34 +01003601 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003602 int err;
3603 int i;
3604 pid_t this_pid;
3605 pid_t other_pid;
3606 struct snd_sg_buf *sgbuf;
3607
3608
3609 spin_lock_irq(&hdspm->lock);
3610
3611 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3612 this_pid = hdspm->playback_pid;
3613 other_pid = hdspm->capture_pid;
3614 } else {
3615 this_pid = hdspm->capture_pid;
3616 other_pid = hdspm->playback_pid;
3617 }
3618
3619 if ((other_pid > 0) && (this_pid != other_pid)) {
3620
3621 /* The other stream is open, and not by the same
3622 task as this one. Make sure that the parameters
3623 that matter are the same.
3624 */
3625
3626 if (params_rate(params) != hdspm->system_sample_rate) {
3627 spin_unlock_irq(&hdspm->lock);
3628 _snd_pcm_hw_param_setempty(params,
3629 SNDRV_PCM_HW_PARAM_RATE);
3630 return -EBUSY;
3631 }
3632
3633 if (params_period_size(params) != hdspm->period_bytes / 4) {
3634 spin_unlock_irq(&hdspm->lock);
3635 _snd_pcm_hw_param_setempty(params,
3636 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
3637 return -EBUSY;
3638 }
3639
3640 }
3641 /* We're fine. */
3642 spin_unlock_irq(&hdspm->lock);
3643
3644 /* how to make sure that the rate matches an externally-set one ? */
3645
3646 spin_lock_irq(&hdspm->lock);
3647 if ((err = hdspm_set_rate(hdspm, params_rate(params), 0)) < 0) {
3648 spin_unlock_irq(&hdspm->lock);
3649 _snd_pcm_hw_param_setempty(params,
3650 SNDRV_PCM_HW_PARAM_RATE);
3651 return err;
3652 }
3653 spin_unlock_irq(&hdspm->lock);
3654
3655 if ((err =
3656 hdspm_set_interrupt_interval(hdspm,
3657 params_period_size(params))) <
3658 0) {
3659 _snd_pcm_hw_param_setempty(params,
3660 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
3661 return err;
3662 }
3663
3664 /* Memory allocation, takashi's method, dont know if we should spinlock */
3665 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003666 /* Update for MADI rev 204: we need to allocate for all channels,
3667 * otherwise it doesn't work at 96kHz */
Takashi Iwai763f3562005-06-03 11:25:34 +02003668 err =
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003669 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
Takashi Iwai763f3562005-06-03 11:25:34 +02003670 if (err < 0)
3671 return err;
3672
3673 sgbuf = snd_pcm_substream_sgbuf(substream);
3674
3675 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3676
3677 hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferOut,
3678 params_channels(params));
3679
3680 for (i = 0; i < params_channels(params); ++i)
3681 snd_hdspm_enable_out(hdspm, i, 1);
3682
3683 hdspm->playback_buffer =
3684 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01003685 snd_printdd("Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02003686 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02003687 } else {
3688 hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferIn,
3689 params_channels(params));
3690
3691 for (i = 0; i < params_channels(params); ++i)
3692 snd_hdspm_enable_in(hdspm, i, 1);
3693
3694 hdspm->capture_buffer =
3695 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01003696 snd_printdd("Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02003697 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02003698 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02003699 /*
3700 snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
3701 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
3702 "playback" : "capture",
3703 snd_pcm_sgbuf_get_addr(sgbuf, 0));
3704 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003705 /*
3706 snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
3707 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
3708 "playback" : "capture",
3709 params_rate(params), params_channels(params),
3710 params_buffer_size(params));
3711 */
Takashi Iwai763f3562005-06-03 11:25:34 +02003712 return 0;
3713}
3714
Takashi Iwai98274f02005-11-17 14:52:34 +01003715static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003716{
3717 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01003718 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003719
3720 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3721
3722 /* params_channels(params) should be enough,
3723 but to get sure in case of error */
3724 for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
3725 snd_hdspm_enable_out(hdspm, i, 0);
3726
3727 hdspm->playback_buffer = NULL;
3728 } else {
3729 for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
3730 snd_hdspm_enable_in(hdspm, i, 0);
3731
3732 hdspm->capture_buffer = NULL;
3733
3734 }
3735
3736 snd_pcm_lib_free_pages(substream);
3737
3738 return 0;
3739}
3740
Takashi Iwai98274f02005-11-17 14:52:34 +01003741static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
3742 struct snd_pcm_channel_info * info)
Takashi Iwai763f3562005-06-03 11:25:34 +02003743{
Takashi Iwai98274f02005-11-17 14:52:34 +01003744 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003745 int mapped_channel;
3746
3747 snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL);
3748
3749 if ((mapped_channel = hdspm->channel_map[info->channel]) < 0)
3750 return -EINVAL;
3751
3752 info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
3753 info->first = 0;
3754 info->step = 32;
3755 return 0;
3756}
3757
Takashi Iwai98274f02005-11-17 14:52:34 +01003758static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02003759 unsigned int cmd, void *arg)
3760{
3761 switch (cmd) {
3762 case SNDRV_PCM_IOCTL1_RESET:
3763 {
3764 return snd_hdspm_reset(substream);
3765 }
3766
3767 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
3768 {
Takashi Iwai98274f02005-11-17 14:52:34 +01003769 struct snd_pcm_channel_info *info = arg;
Takashi Iwai763f3562005-06-03 11:25:34 +02003770 return snd_hdspm_channel_info(substream, info);
3771 }
3772 default:
3773 break;
3774 }
3775
3776 return snd_pcm_lib_ioctl(substream, cmd, arg);
3777}
3778
Takashi Iwai98274f02005-11-17 14:52:34 +01003779static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02003780{
Takashi Iwai98274f02005-11-17 14:52:34 +01003781 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
3782 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02003783 int running;
3784
3785 spin_lock(&hdspm->lock);
3786 running = hdspm->running;
3787 switch (cmd) {
3788 case SNDRV_PCM_TRIGGER_START:
3789 running |= 1 << substream->stream;
3790 break;
3791 case SNDRV_PCM_TRIGGER_STOP:
3792 running &= ~(1 << substream->stream);
3793 break;
3794 default:
3795 snd_BUG();
3796 spin_unlock(&hdspm->lock);
3797 return -EINVAL;
3798 }
3799 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3800 other = hdspm->capture_substream;
3801 else
3802 other = hdspm->playback_substream;
3803
3804 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003805 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01003806 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02003807 if (s == other) {
3808 snd_pcm_trigger_done(s, substream);
3809 if (cmd == SNDRV_PCM_TRIGGER_START)
3810 running |= 1 << s->stream;
3811 else
3812 running &= ~(1 << s->stream);
3813 goto _ok;
3814 }
3815 }
3816 if (cmd == SNDRV_PCM_TRIGGER_START) {
3817 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
3818 && substream->stream ==
3819 SNDRV_PCM_STREAM_CAPTURE)
3820 hdspm_silence_playback(hdspm);
3821 } else {
3822 if (running &&
3823 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3824 hdspm_silence_playback(hdspm);
3825 }
3826 } else {
3827 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
3828 hdspm_silence_playback(hdspm);
3829 }
3830 _ok:
3831 snd_pcm_trigger_done(substream, substream);
3832 if (!hdspm->running && running)
3833 hdspm_start_audio(hdspm);
3834 else if (hdspm->running && !running)
3835 hdspm_stop_audio(hdspm);
3836 hdspm->running = running;
3837 spin_unlock(&hdspm->lock);
3838
3839 return 0;
3840}
3841
Takashi Iwai98274f02005-11-17 14:52:34 +01003842static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003843{
3844 return 0;
3845}
3846
3847static unsigned int period_sizes[] =
3848 { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
3849
Takashi Iwai98274f02005-11-17 14:52:34 +01003850static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003851 .info = (SNDRV_PCM_INFO_MMAP |
3852 SNDRV_PCM_INFO_MMAP_VALID |
3853 SNDRV_PCM_INFO_NONINTERLEAVED |
3854 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
3855 .formats = SNDRV_PCM_FMTBIT_S32_LE,
3856 .rates = (SNDRV_PCM_RATE_32000 |
3857 SNDRV_PCM_RATE_44100 |
3858 SNDRV_PCM_RATE_48000 |
3859 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02003860 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
3861 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02003862 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02003863 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02003864 .channels_min = 1,
3865 .channels_max = HDSPM_MAX_CHANNELS,
3866 .buffer_bytes_max =
3867 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
3868 .period_bytes_min = (64 * 4),
3869 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
3870 .periods_min = 2,
3871 .periods_max = 2,
3872 .fifo_size = 0
3873};
3874
Takashi Iwai98274f02005-11-17 14:52:34 +01003875static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003876 .info = (SNDRV_PCM_INFO_MMAP |
3877 SNDRV_PCM_INFO_MMAP_VALID |
3878 SNDRV_PCM_INFO_NONINTERLEAVED |
3879 SNDRV_PCM_INFO_SYNC_START),
3880 .formats = SNDRV_PCM_FMTBIT_S32_LE,
3881 .rates = (SNDRV_PCM_RATE_32000 |
3882 SNDRV_PCM_RATE_44100 |
3883 SNDRV_PCM_RATE_48000 |
3884 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02003885 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
3886 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02003887 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02003888 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02003889 .channels_min = 1,
3890 .channels_max = HDSPM_MAX_CHANNELS,
3891 .buffer_bytes_max =
3892 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
3893 .period_bytes_min = (64 * 4),
3894 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
3895 .periods_min = 2,
3896 .periods_max = 2,
3897 .fifo_size = 0
3898};
3899
Takashi Iwai98274f02005-11-17 14:52:34 +01003900static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003901 .count = ARRAY_SIZE(period_sizes),
3902 .list = period_sizes,
3903 .mask = 0
3904};
3905
3906
Takashi Iwai98274f02005-11-17 14:52:34 +01003907static int snd_hdspm_hw_rule_channels_rate(struct snd_pcm_hw_params *params,
3908 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02003909{
Takashi Iwai98274f02005-11-17 14:52:34 +01003910 struct hdspm *hdspm = rule->private;
3911 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02003912 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01003913 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02003914 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
3915
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003916 if (r->min > 48000 && r->max <= 96000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003917 struct snd_interval t = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003918 .min = hdspm->ds_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02003919 .max = hdspm->ds_channels,
3920 .integer = 1,
3921 };
3922 return snd_interval_refine(c, &t);
3923 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003924 struct snd_interval t = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003925 .min = hdspm->ss_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02003926 .max = hdspm->ss_channels,
3927 .integer = 1,
3928 };
3929 return snd_interval_refine(c, &t);
3930 }
3931 return 0;
3932}
3933
Takashi Iwai98274f02005-11-17 14:52:34 +01003934static int snd_hdspm_hw_rule_rate_channels(struct snd_pcm_hw_params *params,
3935 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02003936{
Takashi Iwai98274f02005-11-17 14:52:34 +01003937 struct hdspm *hdspm = rule->private;
3938 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02003939 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01003940 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02003941 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
3942
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003943 if (c->min >= hdspm->ss_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003944 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003945 .min = 32000,
3946 .max = 48000,
3947 .integer = 1,
3948 };
3949 return snd_interval_refine(r, &t);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003950 } else if (c->max <= hdspm->ds_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003951 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003952 .min = 64000,
3953 .max = 96000,
3954 .integer = 1,
3955 };
3956
3957 return snd_interval_refine(r, &t);
3958 }
3959 return 0;
3960}
3961
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003962static int snd_hdspm_hw_rule_channels(struct snd_pcm_hw_params *params,
3963 struct snd_pcm_hw_rule *rule)
3964{
3965 unsigned int list[3];
3966 struct hdspm *hdspm = rule->private;
3967 struct snd_interval *c = hw_param_interval(params,
3968 SNDRV_PCM_HW_PARAM_CHANNELS);
3969 if (hdspm->is_aes32) {
3970 list[0] = hdspm->qs_channels;
3971 list[1] = hdspm->ds_channels;
3972 list[2] = hdspm->ss_channels;
3973 return snd_interval_list(c, 3, list, 0);
3974 } else {
3975 list[0] = hdspm->ds_channels;
3976 list[1] = hdspm->ss_channels;
3977 return snd_interval_list(c, 2, list, 0);
3978 }
3979}
3980
3981
3982static unsigned int hdspm_aes32_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 };
3983
3984static struct snd_pcm_hw_constraint_list hdspm_hw_constraints_aes32_sample_rates = {
3985 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
3986 .list = hdspm_aes32_sample_rates,
3987 .mask = 0
3988};
3989
Takashi Iwai98274f02005-11-17 14:52:34 +01003990static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003991{
Takashi Iwai98274f02005-11-17 14:52:34 +01003992 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
3993 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02003994
Takashi Iwai763f3562005-06-03 11:25:34 +02003995 spin_lock_irq(&hdspm->lock);
3996
3997 snd_pcm_set_sync(substream);
3998
3999 runtime->hw = snd_hdspm_playback_subinfo;
4000
4001 if (hdspm->capture_substream == NULL)
4002 hdspm_stop_audio(hdspm);
4003
4004 hdspm->playback_pid = current->pid;
4005 hdspm->playback_substream = substream;
4006
4007 spin_unlock_irq(&hdspm->lock);
4008
4009 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4010
4011 snd_pcm_hw_constraint_list(runtime, 0,
4012 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
4013 &hw_constraints_period_sizes);
4014
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004015 if (hdspm->is_aes32) {
4016 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4017 &hdspm_hw_constraints_aes32_sample_rates);
4018 } else {
4019 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4020 snd_hdspm_hw_rule_channels, hdspm,
4021 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4022 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4023 snd_hdspm_hw_rule_channels_rate, hdspm,
4024 SNDRV_PCM_HW_PARAM_RATE, -1);
Takashi Iwai763f3562005-06-03 11:25:34 +02004025
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004026 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4027 snd_hdspm_hw_rule_rate_channels, hdspm,
4028 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4029 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004030 return 0;
4031}
4032
Takashi Iwai98274f02005-11-17 14:52:34 +01004033static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02004034{
Takashi Iwai98274f02005-11-17 14:52:34 +01004035 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02004036
4037 spin_lock_irq(&hdspm->lock);
4038
4039 hdspm->playback_pid = -1;
4040 hdspm->playback_substream = NULL;
4041
4042 spin_unlock_irq(&hdspm->lock);
4043
4044 return 0;
4045}
4046
4047
Takashi Iwai98274f02005-11-17 14:52:34 +01004048static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02004049{
Takashi Iwai98274f02005-11-17 14:52:34 +01004050 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
4051 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02004052
4053 spin_lock_irq(&hdspm->lock);
4054 snd_pcm_set_sync(substream);
4055 runtime->hw = snd_hdspm_capture_subinfo;
4056
4057 if (hdspm->playback_substream == NULL)
4058 hdspm_stop_audio(hdspm);
4059
4060 hdspm->capture_pid = current->pid;
4061 hdspm->capture_substream = substream;
4062
4063 spin_unlock_irq(&hdspm->lock);
4064
4065 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4066 snd_pcm_hw_constraint_list(runtime, 0,
4067 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
4068 &hw_constraints_period_sizes);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004069 if (hdspm->is_aes32) {
4070 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4071 &hdspm_hw_constraints_aes32_sample_rates);
4072 } else {
4073 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4074 snd_hdspm_hw_rule_channels, hdspm,
4075 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4076 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4077 snd_hdspm_hw_rule_channels_rate, hdspm,
4078 SNDRV_PCM_HW_PARAM_RATE, -1);
Takashi Iwai763f3562005-06-03 11:25:34 +02004079
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004080 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4081 snd_hdspm_hw_rule_rate_channels, hdspm,
4082 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4083 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004084 return 0;
4085}
4086
Takashi Iwai98274f02005-11-17 14:52:34 +01004087static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02004088{
Takashi Iwai98274f02005-11-17 14:52:34 +01004089 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02004090
4091 spin_lock_irq(&hdspm->lock);
4092
4093 hdspm->capture_pid = -1;
4094 hdspm->capture_substream = NULL;
4095
4096 spin_unlock_irq(&hdspm->lock);
4097 return 0;
4098}
4099
Takashi Iwai98274f02005-11-17 14:52:34 +01004100static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep * hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02004101{
4102 /* we have nothing to initialize but the call is required */
4103 return 0;
4104}
4105
4106
Takashi Iwai98274f02005-11-17 14:52:34 +01004107static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
Takashi Iwai763f3562005-06-03 11:25:34 +02004108 unsigned int cmd, unsigned long arg)
4109{
Takashi Iwai98274f02005-11-17 14:52:34 +01004110 struct hdspm *hdspm = (struct hdspm *) hw->private_data;
4111 struct hdspm_mixer_ioctl mixer;
4112 struct hdspm_config_info info;
4113 struct hdspm_version hdspm_version;
4114 struct hdspm_peak_rms_ioctl rms;
Takashi Iwai763f3562005-06-03 11:25:34 +02004115
4116 switch (cmd) {
4117
4118
4119 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
4120 if (copy_from_user(&rms, (void __user *)arg, sizeof(rms)))
4121 return -EFAULT;
4122 /* maybe there is a chance to memorymap in future so dont touch just copy */
4123 if(copy_to_user_fromio((void __user *)rms.peak,
4124 hdspm->iobase+HDSPM_MADI_peakrmsbase,
Takashi Iwai98274f02005-11-17 14:52:34 +01004125 sizeof(struct hdspm_peak_rms)) != 0 )
Takashi Iwai763f3562005-06-03 11:25:34 +02004126 return -EFAULT;
4127
4128 break;
4129
4130
4131 case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO:
4132
4133 spin_lock_irq(&hdspm->lock);
4134 info.pref_sync_ref =
4135 (unsigned char) hdspm_pref_sync_ref(hdspm);
4136 info.wordclock_sync_check =
4137 (unsigned char) hdspm_wc_sync_check(hdspm);
4138
4139 info.system_sample_rate = hdspm->system_sample_rate;
4140 info.autosync_sample_rate =
4141 hdspm_external_sample_rate(hdspm);
4142 info.system_clock_mode =
4143 (unsigned char) hdspm_system_clock_mode(hdspm);
4144 info.clock_source =
4145 (unsigned char) hdspm_clock_source(hdspm);
4146 info.autosync_ref =
4147 (unsigned char) hdspm_autosync_ref(hdspm);
4148 info.line_out = (unsigned char) hdspm_line_out(hdspm);
4149 info.passthru = 0;
4150 spin_unlock_irq(&hdspm->lock);
4151 if (copy_to_user((void __user *) arg, &info, sizeof(info)))
4152 return -EFAULT;
4153 break;
4154
4155 case SNDRV_HDSPM_IOCTL_GET_VERSION:
4156 hdspm_version.firmware_rev = hdspm->firmware_rev;
4157 if (copy_to_user((void __user *) arg, &hdspm_version,
4158 sizeof(hdspm_version)))
4159 return -EFAULT;
4160 break;
4161
4162 case SNDRV_HDSPM_IOCTL_GET_MIXER:
4163 if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
4164 return -EFAULT;
4165 if (copy_to_user
Takashi Iwai98274f02005-11-17 14:52:34 +01004166 ((void __user *)mixer.mixer, hdspm->mixer, sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02004167 return -EFAULT;
4168 break;
4169
4170 default:
4171 return -EINVAL;
4172 }
4173 return 0;
4174}
4175
Takashi Iwai98274f02005-11-17 14:52:34 +01004176static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004177 .open = snd_hdspm_playback_open,
4178 .close = snd_hdspm_playback_release,
4179 .ioctl = snd_hdspm_ioctl,
4180 .hw_params = snd_hdspm_hw_params,
4181 .hw_free = snd_hdspm_hw_free,
4182 .prepare = snd_hdspm_prepare,
4183 .trigger = snd_hdspm_trigger,
4184 .pointer = snd_hdspm_hw_pointer,
4185 .copy = snd_hdspm_playback_copy,
4186 .silence = snd_hdspm_hw_silence,
4187 .page = snd_pcm_sgbuf_ops_page,
4188};
4189
Takashi Iwai98274f02005-11-17 14:52:34 +01004190static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004191 .open = snd_hdspm_capture_open,
4192 .close = snd_hdspm_capture_release,
4193 .ioctl = snd_hdspm_ioctl,
4194 .hw_params = snd_hdspm_hw_params,
4195 .hw_free = snd_hdspm_hw_free,
4196 .prepare = snd_hdspm_prepare,
4197 .trigger = snd_hdspm_trigger,
4198 .pointer = snd_hdspm_hw_pointer,
4199 .copy = snd_hdspm_capture_copy,
4200 .page = snd_pcm_sgbuf_ops_page,
4201};
4202
Takashi Iwai98274f02005-11-17 14:52:34 +01004203static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
4204 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004205{
Takashi Iwai98274f02005-11-17 14:52:34 +01004206 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02004207 int err;
4208
4209 if ((err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw)) < 0)
4210 return err;
4211
4212 hdspm->hwdep = hw;
4213 hw->private_data = hdspm;
4214 strcpy(hw->name, "HDSPM hwdep interface");
4215
4216 hw->ops.open = snd_hdspm_hwdep_dummy_op;
4217 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
4218 hw->ops.release = snd_hdspm_hwdep_dummy_op;
4219
4220 return 0;
4221}
4222
4223
4224/*------------------------------------------------------------
4225 memory interface
4226 ------------------------------------------------------------*/
Takashi Iwai98274f02005-11-17 14:52:34 +01004227static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004228{
4229 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004230 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02004231 size_t wanted;
4232
4233 pcm = hdspm->pcm;
4234
Remy Bruno3cee5a62006-10-16 12:46:32 +02004235/* wanted = HDSPM_DMA_AREA_BYTES + 4096;*/ /* dont know why, but it works */
4236 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02004237
4238 if ((err =
4239 snd_pcm_lib_preallocate_pages_for_all(pcm,
4240 SNDRV_DMA_TYPE_DEV_SG,
4241 snd_dma_pci_data(hdspm->pci),
4242 wanted,
4243 wanted)) < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01004244 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02004245
4246 return err;
4247 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01004248 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02004249
4250 return 0;
4251}
4252
Takashi Iwai98274f02005-11-17 14:52:34 +01004253static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
Takashi Iwai763f3562005-06-03 11:25:34 +02004254 unsigned int reg, int channels)
4255{
4256 int i;
4257 for (i = 0; i < (channels * 16); i++)
4258 hdspm_write(hdspm, reg + 4 * i,
4259 snd_pcm_sgbuf_get_addr(sgbuf,
4260 (size_t) 4096 * i));
4261}
4262
4263/* ------------- ALSA Devices ---------------------------- */
Takashi Iwai98274f02005-11-17 14:52:34 +01004264static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
4265 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004266{
Takashi Iwai98274f02005-11-17 14:52:34 +01004267 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02004268 int err;
4269
4270 if ((err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm)) < 0)
4271 return err;
4272
4273 hdspm->pcm = pcm;
4274 pcm->private_data = hdspm;
4275 strcpy(pcm->name, hdspm->card_name);
4276
4277 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
4278 &snd_hdspm_playback_ops);
4279 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
4280 &snd_hdspm_capture_ops);
4281
4282 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
4283
4284 if ((err = snd_hdspm_preallocate_memory(hdspm)) < 0)
4285 return err;
4286
4287 return 0;
4288}
4289
Takashi Iwai98274f02005-11-17 14:52:34 +01004290static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004291{
4292 snd_hdspm_flush_midi_input(hdspm, 0);
4293 snd_hdspm_flush_midi_input(hdspm, 1);
4294}
4295
Takashi Iwai98274f02005-11-17 14:52:34 +01004296static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
4297 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004298{
4299 int err;
4300
4301 snd_printdd("Create card...\n");
4302 if ((err = snd_hdspm_create_pcm(card, hdspm)) < 0)
4303 return err;
4304
4305 if ((err = snd_hdspm_create_midi(card, hdspm, 0)) < 0)
4306 return err;
4307
4308 if ((err = snd_hdspm_create_midi(card, hdspm, 1)) < 0)
4309 return err;
4310
4311 if ((err = snd_hdspm_create_controls(card, hdspm)) < 0)
4312 return err;
4313
4314 if ((err = snd_hdspm_create_hwdep(card, hdspm)) < 0)
4315 return err;
4316
4317 snd_printdd("proc init...\n");
4318 snd_hdspm_proc_init(hdspm);
4319
4320 hdspm->system_sample_rate = -1;
4321 hdspm->last_external_sample_rate = -1;
4322 hdspm->last_internal_sample_rate = -1;
4323 hdspm->playback_pid = -1;
4324 hdspm->capture_pid = -1;
4325 hdspm->capture_substream = NULL;
4326 hdspm->playback_substream = NULL;
4327
4328 snd_printdd("Set defaults...\n");
4329 if ((err = snd_hdspm_set_defaults(hdspm)) < 0)
4330 return err;
4331
4332 snd_printdd("Update mixer controls...\n");
4333 hdspm_update_simple_mixer_controls(hdspm);
4334
4335 snd_printdd("Initializeing complete ???\n");
4336
4337 if ((err = snd_card_register(card)) < 0) {
4338 snd_printk(KERN_ERR "HDSPM: error registering card\n");
4339 return err;
4340 }
4341
4342 snd_printdd("... yes now\n");
4343
4344 return 0;
4345}
4346
Takashi Iwai98274f02005-11-17 14:52:34 +01004347static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdspm,
Takashi Iwai763f3562005-06-03 11:25:34 +02004348 int precise_ptr, int enable_monitor)
4349{
4350 struct pci_dev *pci = hdspm->pci;
4351 int err;
4352 int i;
4353
4354 unsigned long io_extent;
4355
4356 hdspm->irq = -1;
4357 hdspm->irq_count = 0;
4358
4359 hdspm->midi[0].rmidi = NULL;
4360 hdspm->midi[1].rmidi = NULL;
4361 hdspm->midi[0].input = NULL;
4362 hdspm->midi[1].input = NULL;
4363 hdspm->midi[0].output = NULL;
4364 hdspm->midi[1].output = NULL;
4365 spin_lock_init(&hdspm->midi[0].lock);
4366 spin_lock_init(&hdspm->midi[1].lock);
4367 hdspm->iobase = NULL;
4368 hdspm->control_register = 0;
4369 hdspm->control2_register = 0;
4370
4371 hdspm->playback_buffer = NULL;
4372 hdspm->capture_buffer = NULL;
4373
4374 for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
4375 hdspm->playback_mixer_ctls[i] = NULL;
4376 hdspm->mixer = NULL;
4377
4378 hdspm->card = card;
4379
4380 spin_lock_init(&hdspm->lock);
4381
4382 tasklet_init(&hdspm->midi_tasklet,
4383 hdspm_midi_tasklet, (unsigned long) hdspm);
4384
4385 pci_read_config_word(hdspm->pci,
4386 PCI_CLASS_REVISION, &hdspm->firmware_rev);
4387
Remy Bruno3cee5a62006-10-16 12:46:32 +02004388 hdspm->is_aes32 = (hdspm->firmware_rev >= HDSPM_AESREVISION);
4389
Takashi Iwai763f3562005-06-03 11:25:34 +02004390 strcpy(card->mixername, "Xilinx FPGA");
Remy Bruno3cee5a62006-10-16 12:46:32 +02004391 if (hdspm->is_aes32) {
4392 strcpy(card->driver, "HDSPAES32");
4393 hdspm->card_name = "RME HDSPM AES32";
4394 } else {
4395 strcpy(card->driver, "HDSPM");
4396 hdspm->card_name = "RME HDSPM MADI";
4397 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004398
4399 if ((err = pci_enable_device(pci)) < 0)
4400 return err;
4401
4402 pci_set_master(hdspm->pci);
4403
4404 if ((err = pci_request_regions(pci, "hdspm")) < 0)
4405 return err;
4406
4407 hdspm->port = pci_resource_start(pci, 0);
4408 io_extent = pci_resource_len(pci, 0);
4409
4410 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
4411 hdspm->port, hdspm->port + io_extent - 1);
4412
4413
4414 if ((hdspm->iobase = ioremap_nocache(hdspm->port, io_extent)) == NULL) {
4415 snd_printk(KERN_ERR "HDSPM: unable to remap region 0x%lx-0x%lx\n",
4416 hdspm->port, hdspm->port + io_extent - 1);
4417 return -EBUSY;
4418 }
4419 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
4420 (unsigned long)hdspm->iobase, hdspm->port,
4421 hdspm->port + io_extent - 1);
4422
4423 if (request_irq(pci->irq, snd_hdspm_interrupt,
Takashi Iwai437a5a42006-11-21 12:14:23 +01004424 IRQF_SHARED, "hdspm", hdspm)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004425 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
4426 return -EBUSY;
4427 }
4428
4429 snd_printdd("use IRQ %d\n", pci->irq);
4430
4431 hdspm->irq = pci->irq;
4432 hdspm->precise_ptr = precise_ptr;
4433
4434 hdspm->monitor_outs = enable_monitor;
4435
Andrew Mortone2eba3e2006-01-20 14:07:13 +01004436 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Takashi Iwai98274f02005-11-17 14:52:34 +01004437 sizeof(struct hdspm_mixer));
4438 if ((hdspm->mixer = kmalloc(sizeof(struct hdspm_mixer), GFP_KERNEL))
Takashi Iwai763f3562005-06-03 11:25:34 +02004439 == NULL) {
4440 snd_printk(KERN_ERR "HDSPM: unable to kmalloc Mixer memory of %d Bytes\n",
Takashi Iwai98274f02005-11-17 14:52:34 +01004441 (int)sizeof(struct hdspm_mixer));
Takashi Iwai763f3562005-06-03 11:25:34 +02004442 return err;
4443 }
4444
4445 hdspm->ss_channels = MADI_SS_CHANNELS;
4446 hdspm->ds_channels = MADI_DS_CHANNELS;
4447 hdspm->qs_channels = MADI_QS_CHANNELS;
4448
4449 snd_printdd("create alsa devices.\n");
4450 if ((err = snd_hdspm_create_alsa_devices(card, hdspm)) < 0)
4451 return err;
4452
4453 snd_hdspm_initialize_midi_flush(hdspm);
4454
4455 return 0;
4456}
4457
Takashi Iwai98274f02005-11-17 14:52:34 +01004458static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004459{
4460
4461 if (hdspm->port) {
4462
4463 /* stop th audio, and cancel all interrupts */
4464 hdspm->control_register &=
4465 ~(HDSPM_Start | HDSPM_AudioInterruptEnable
4466 | HDSPM_Midi0InterruptEnable |
4467 HDSPM_Midi1InterruptEnable);
4468 hdspm_write(hdspm, HDSPM_controlRegister,
4469 hdspm->control_register);
4470 }
4471
4472 if (hdspm->irq >= 0)
4473 free_irq(hdspm->irq, (void *) hdspm);
4474
4475
Jesper Juhlfc584222005-10-24 15:11:28 +02004476 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02004477
4478 if (hdspm->iobase)
4479 iounmap(hdspm->iobase);
4480
Takashi Iwai763f3562005-06-03 11:25:34 +02004481 if (hdspm->port)
4482 pci_release_regions(hdspm->pci);
4483
4484 pci_disable_device(hdspm->pci);
4485 return 0;
4486}
4487
Takashi Iwai98274f02005-11-17 14:52:34 +01004488static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02004489{
Takashi Iwai98274f02005-11-17 14:52:34 +01004490 struct hdspm *hdspm = (struct hdspm *) card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02004491
4492 if (hdspm)
4493 snd_hdspm_free(hdspm);
4494}
4495
4496static int __devinit snd_hdspm_probe(struct pci_dev *pci,
4497 const struct pci_device_id *pci_id)
4498{
4499 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01004500 struct hdspm *hdspm;
4501 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02004502 int err;
4503
4504 if (dev >= SNDRV_CARDS)
4505 return -ENODEV;
4506 if (!enable[dev]) {
4507 dev++;
4508 return -ENOENT;
4509 }
4510
4511 if (!(card = snd_card_new(index[dev], id[dev],
Takashi Iwai98274f02005-11-17 14:52:34 +01004512 THIS_MODULE, sizeof(struct hdspm))))
Takashi Iwai763f3562005-06-03 11:25:34 +02004513 return -ENOMEM;
4514
Takashi Iwai98274f02005-11-17 14:52:34 +01004515 hdspm = (struct hdspm *) card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02004516 card->private_free = snd_hdspm_card_free;
4517 hdspm->dev = dev;
4518 hdspm->pci = pci;
4519
Takashi Iwaic187c042007-02-19 15:27:33 +01004520 snd_card_set_dev(card, &pci->dev);
4521
Takashi Iwai763f3562005-06-03 11:25:34 +02004522 if ((err =
4523 snd_hdspm_create(card, hdspm, precise_ptr[dev],
4524 enable_monitor[dev])) < 0) {
4525 snd_card_free(card);
4526 return err;
4527 }
4528
4529 strcpy(card->shortname, "HDSPM MADI");
4530 sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name,
4531 hdspm->port, hdspm->irq);
4532
4533 if ((err = snd_card_register(card)) < 0) {
4534 snd_card_free(card);
4535 return err;
4536 }
4537
4538 pci_set_drvdata(pci, card);
4539
4540 dev++;
4541 return 0;
4542}
4543
4544static void __devexit snd_hdspm_remove(struct pci_dev *pci)
4545{
4546 snd_card_free(pci_get_drvdata(pci));
4547 pci_set_drvdata(pci, NULL);
4548}
4549
4550static struct pci_driver driver = {
4551 .name = "RME Hammerfall DSP MADI",
Takashi Iwai763f3562005-06-03 11:25:34 +02004552 .id_table = snd_hdspm_ids,
4553 .probe = snd_hdspm_probe,
4554 .remove = __devexit_p(snd_hdspm_remove),
4555};
4556
4557
4558static int __init alsa_card_hdspm_init(void)
4559{
4560 return pci_register_driver(&driver);
4561}
4562
4563static void __exit alsa_card_hdspm_exit(void)
4564{
4565 pci_unregister_driver(&driver);
4566}
4567
4568module_init(alsa_card_hdspm_init)
4569module_exit(alsa_card_hdspm_exit)