blob: f5eadfc0672ab0073db93f8fe2b484069b42c814 [file] [log] [blame]
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001/*
Takashi Iwai763f3562005-06-03 11:25:34 +02002 * ALSA driver for RME Hammerfall DSP MADI audio interface(s)
3 *
4 * Copyright (c) 2003 Winfried Ritsch (IEM)
5 * code based on hdsp.c Paul Davis
6 * Marcus Andersson
7 * Thomas Charbonnel
Remy Bruno3cee5a62006-10-16 12:46:32 +02008 * Modified 2006-06-01 for AES32 support by Remy Bruno
9 * <remy.bruno@trinnov.com>
Takashi Iwai763f3562005-06-03 11:25:34 +020010 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
Takashi Iwai763f3562005-06-03 11:25:34 +020026#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/interrupt.h>
29#include <linux/moduleparam.h>
30#include <linux/slab.h>
31#include <linux/pci.h>
Takashi Iwai3f7440a2009-06-05 17:40:04 +020032#include <linux/math64.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020033#include <asm/io.h>
34
35#include <sound/core.h>
36#include <sound/control.h>
37#include <sound/pcm.h>
38#include <sound/info.h>
39#include <sound/asoundef.h>
40#include <sound/rawmidi.h>
41#include <sound/hwdep.h>
42#include <sound/initval.h>
43
44#include <sound/hdspm.h>
45
46static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
47static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
48static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
49
50/* Disable precise pointer at start */
51static int precise_ptr[SNDRV_CARDS];
52
53/* Send all playback to line outs */
54static int line_outs_monitor[SNDRV_CARDS];
55
56/* Enable Analog Outs on Channel 63/64 by default */
57static int enable_monitor[SNDRV_CARDS];
58
59module_param_array(index, int, NULL, 0444);
60MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
61
62module_param_array(id, charp, NULL, 0444);
63MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
64
65module_param_array(enable, bool, NULL, 0444);
66MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
67
68module_param_array(precise_ptr, bool, NULL, 0444);
Takashi Iwaie8da2fb2005-08-16 16:55:13 +020069MODULE_PARM_DESC(precise_ptr, "Enable or disable precise pointer.");
Takashi Iwai763f3562005-06-03 11:25:34 +020070
71module_param_array(line_outs_monitor, bool, NULL, 0444);
72MODULE_PARM_DESC(line_outs_monitor,
73 "Send playback streams to analog outs by default.");
74
75module_param_array(enable_monitor, bool, NULL, 0444);
76MODULE_PARM_DESC(enable_monitor,
77 "Enable Analog Out on Channel 63/64 by default.");
78
79MODULE_AUTHOR
Takashi Iwaief5fa1a2007-07-27 16:52:46 +020080 ("Winfried Ritsch <ritsch_AT_iem.at>, "
81 "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
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200164#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax
165 * -- MADI ONLY
166 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200167#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
168
169#define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200170#define HDSPM_SyncRef1 (1<<17) /* for AES32: SyncRefN codes the AES # */
171#define HDSPM_SyncRef2 (1<<13)
172#define HDSPM_SyncRef3 (1<<25)
Takashi Iwai763f3562005-06-03 11:25:34 +0200173
Remy Bruno3cee5a62006-10-16 12:46:32 +0200174#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200175#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
176 AES additional bits in
177 lower 5 Audiodatabits ??? */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200178#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */
179#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200180
181#define HDSPM_Midi0InterruptEnable (1<<22)
182#define HDSPM_Midi1InterruptEnable (1<<23)
183
184#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
185
Remy Bruno3cee5a62006-10-16 12:46:32 +0200186#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
187#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
188#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */
189
190#define HDSPM_wclk_sel (1<<30)
Takashi Iwai763f3562005-06-03 11:25:34 +0200191
192/* --- bit helper defines */
193#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200194#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\
195 HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
Takashi Iwai763f3562005-06-03 11:25:34 +0200196#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
197#define HDSPM_InputOptical 0
198#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200199#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\
200 HDSPM_SyncRef2|HDSPM_SyncRef3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200201#define HDSPM_SyncRef_Word 0
202#define HDSPM_SyncRef_MADI (HDSPM_SyncRef0)
203
204#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
205#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
206
207#define HDSPM_Frequency32KHz HDSPM_Frequency0
208#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
209#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
210#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
211#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200212#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\
213 HDSPM_Frequency0)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200214#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)
215#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200216#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\
217 HDSPM_Frequency0)
Takashi Iwai763f3562005-06-03 11:25:34 +0200218
219/* --- for internal discrimination */
220#define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */
221#define HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ 1
222#define HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ 2
223#define HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ 3
224#define HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ 4
225#define HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ 5
226#define HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ 6
227#define HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ 7
228#define HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ 8
229#define HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ 9
230
231/* Synccheck Status */
232#define HDSPM_SYNC_CHECK_NO_LOCK 0
233#define HDSPM_SYNC_CHECK_LOCK 1
234#define HDSPM_SYNC_CHECK_SYNC 2
235
236/* AutoSync References - used by "autosync_ref" control switch */
237#define HDSPM_AUTOSYNC_FROM_WORD 0
238#define HDSPM_AUTOSYNC_FROM_MADI 1
239#define HDSPM_AUTOSYNC_FROM_NONE 2
240
241/* Possible sources of MADI input */
242#define HDSPM_OPTICAL 0 /* optical */
243#define HDSPM_COAXIAL 1 /* BNC */
244
245#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
246#define hdspm_decode_latency(x) (((x) & HDSPM_LatencyMask)>>1)
247
248#define hdspm_encode_in(x) (((x)&0x3)<<14)
249#define hdspm_decode_in(x) (((x)>>14)&0x3)
250
251/* --- control2 register bits --- */
252#define HDSPM_TMS (1<<0)
253#define HDSPM_TCK (1<<1)
254#define HDSPM_TDI (1<<2)
255#define HDSPM_JTAG (1<<3)
256#define HDSPM_PWDN (1<<4)
257#define HDSPM_PROGRAM (1<<5)
258#define HDSPM_CONFIG_MODE_0 (1<<6)
259#define HDSPM_CONFIG_MODE_1 (1<<7)
260/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
261#define HDSPM_BIGENDIAN_MODE (1<<9)
262#define HDSPM_RD_MULTIPLE (1<<10)
263
Remy Bruno3cee5a62006-10-16 12:46:32 +0200264/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200265 that do not conflict with specific bits for AES32 seem to be valid also
266 for the AES32
267 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200268#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200269#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */
270#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1
271 * (like inp0)
272 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200273#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
274
275#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
276 /* since 64byte accurate last 6 bits
277 are not used */
278
279#define HDSPM_madiSync (1<<18) /* MADI is in sync */
280#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
281
282#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
283#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
284#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
285#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
286
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200287#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with
288 * Interrupt
289 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200290#define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */
291#define HDSPM_midi1IRQPending (1<<31) /* and aktiv */
292
293/* --- status bit helpers */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200294#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\
295 HDSPM_madiFreq2|HDSPM_madiFreq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200296#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
297#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
298#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
299#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
300#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
301#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
302#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
303#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
304#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
305
Remy Bruno3cee5a62006-10-16 12:46:32 +0200306/* Status2 Register bits */ /* MADI ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200307
308#define HDSPM_version0 (1<<0) /* not realy defined but I guess */
309#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
310#define HDSPM_version2 (1<<2)
311
312#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */
313#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */
314
315#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */
316#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */
317#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */
318/* missing Bit for 111=128, 1000=176.4, 1001=192 */
319
320#define HDSPM_SelSyncRef0 (1<<8) /* Sync Source in slave mode */
321#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */
322#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */
323
324#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
325
326#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
327#define HDSPM_wcFreq32 (HDSPM_wc_freq0)
328#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)
329#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)
330#define HDSPM_wcFreq64 (HDSPM_wc_freq2)
331#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)
332#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
333
334
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200335#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
336 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200337#define HDSPM_SelSyncRef_WORD 0
338#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200339#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
340 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200341
Remy Bruno3cee5a62006-10-16 12:46:32 +0200342/*
343 For AES32, bits for status, status2 and timecode are different
344*/
345/* status */
346#define HDSPM_AES32_wcLock 0x0200000
347#define HDSPM_AES32_wcFreq_bit 22
348/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
349 HDSPM_bit2freq */
350#define HDSPM_AES32_syncref_bit 16
351/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
352
353#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
354#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
355#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
356#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
357#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
358#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
359#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
360#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
361#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
Remy Bruno65345992007-08-31 12:21:08 +0200362#define HDSPM_AES32_AUTOSYNC_FROM_NONE 9
Remy Bruno3cee5a62006-10-16 12:46:32 +0200363
364/* status2 */
365/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
366#define HDSPM_LockAES 0x80
367#define HDSPM_LockAES1 0x80
368#define HDSPM_LockAES2 0x40
369#define HDSPM_LockAES3 0x20
370#define HDSPM_LockAES4 0x10
371#define HDSPM_LockAES5 0x8
372#define HDSPM_LockAES6 0x4
373#define HDSPM_LockAES7 0x2
374#define HDSPM_LockAES8 0x1
375/*
376 Timecode
377 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
378 AES i+1
379 bits 3210
380 0001 32kHz
381 0010 44.1kHz
382 0011 48kHz
383 0100 64kHz
384 0101 88.2kHz
385 0110 96kHz
386 0111 128kHz
387 1000 176.4kHz
388 1001 192kHz
389 NB: Timecode register doesn't seem to work on AES32 card revision 230
390*/
391
Takashi Iwai763f3562005-06-03 11:25:34 +0200392/* Mixer Values */
393#define UNITY_GAIN 32768 /* = 65536/2 */
394#define MINUS_INFINITY_GAIN 0
395
Takashi Iwai763f3562005-06-03 11:25:34 +0200396/* Number of channels for different Speed Modes */
397#define MADI_SS_CHANNELS 64
398#define MADI_DS_CHANNELS 32
399#define MADI_QS_CHANNELS 16
400
401/* the size of a substream (1 mono data stream) */
402#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
403#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
404
405/* the size of the area we need to allocate for DMA transfers. the
406 size is the same regardless of the number of channels, and
407 also the latency to use.
408 for one direction !!!
409*/
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100410#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
Takashi Iwai763f3562005-06-03 11:25:34 +0200411#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
412
Remy Bruno3cee5a62006-10-16 12:46:32 +0200413/* revisions >= 230 indicate AES32 card */
414#define HDSPM_AESREVISION 230
415
Remy Bruno65345992007-08-31 12:21:08 +0200416/* speed factor modes */
417#define HDSPM_SPEED_SINGLE 0
418#define HDSPM_SPEED_DOUBLE 1
419#define HDSPM_SPEED_QUAD 2
420/* names for speed modes */
421static char *hdspm_speed_names[] = { "single", "double", "quad" };
422
Takashi Iwai98274f02005-11-17 14:52:34 +0100423struct hdspm_midi {
424 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200425 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100426 struct snd_rawmidi *rmidi;
427 struct snd_rawmidi_substream *input;
428 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200429 char istimer; /* timer in use */
430 struct timer_list timer;
431 spinlock_t lock;
432 int pending;
433};
434
Takashi Iwai98274f02005-11-17 14:52:34 +0100435struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200436 spinlock_t lock;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200437 /* only one playback and/or capture stream */
438 struct snd_pcm_substream *capture_substream;
439 struct snd_pcm_substream *playback_substream;
Takashi Iwai763f3562005-06-03 11:25:34 +0200440
441 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200442 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
443
444 unsigned char is_aes32; /* indicates if card is AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200445
446 int precise_ptr; /* use precise pointers, to be tested */
447 int monitor_outs; /* set up monitoring outs init flag */
448
449 u32 control_register; /* cached value */
450 u32 control2_register; /* cached value */
451
Takashi Iwai98274f02005-11-17 14:52:34 +0100452 struct hdspm_midi midi[2];
Takashi Iwai763f3562005-06-03 11:25:34 +0200453 struct tasklet_struct midi_tasklet;
454
455 size_t period_bytes;
456 unsigned char ss_channels; /* channels of card in single speed */
457 unsigned char ds_channels; /* Double Speed */
458 unsigned char qs_channels; /* Quad Speed */
459
460 unsigned char *playback_buffer; /* suitably aligned address */
461 unsigned char *capture_buffer; /* suitably aligned address */
462
463 pid_t capture_pid; /* process id which uses capture */
464 pid_t playback_pid; /* process id which uses capture */
465 int running; /* running status */
466
467 int last_external_sample_rate; /* samplerate mystic ... */
468 int last_internal_sample_rate;
469 int system_sample_rate;
470
471 char *channel_map; /* channel map for DS and Quadspeed */
472
473 int dev; /* Hardware vars... */
474 int irq;
475 unsigned long port;
476 void __iomem *iobase;
477
478 int irq_count; /* for debug */
479
Takashi Iwai98274f02005-11-17 14:52:34 +0100480 struct snd_card *card; /* one card */
481 struct snd_pcm *pcm; /* has one pcm */
482 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +0200483 struct pci_dev *pci; /* and an pci info */
484
485 /* Mixer vars */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200486 /* fast alsa mixer */
487 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
488 /* but input to much, so not used */
489 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
Uwe Kleine-Königb5950762010-11-01 15:38:34 -0400490 /* full mixer accessible over mixer ioctl or hwdep-device */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200491 struct hdspm_mixer *mixer;
Takashi Iwai763f3562005-06-03 11:25:34 +0200492
493};
494
495/* These tables map the ALSA channels 1..N to the channels that we
496 need to use in order to find the relevant channel buffer. RME
497 refer to this kind of mapping as between "the ADAT channel and
498 the DMA channel." We index it using the logical audio channel,
499 and the value is the DMA channel (i.e. channel buffer number)
500 where the data for that channel can be read/written from/to.
501*/
502
503static char channel_map_madi_ss[HDSPM_MAX_CHANNELS] = {
504 0, 1, 2, 3, 4, 5, 6, 7,
505 8, 9, 10, 11, 12, 13, 14, 15,
506 16, 17, 18, 19, 20, 21, 22, 23,
507 24, 25, 26, 27, 28, 29, 30, 31,
508 32, 33, 34, 35, 36, 37, 38, 39,
509 40, 41, 42, 43, 44, 45, 46, 47,
510 48, 49, 50, 51, 52, 53, 54, 55,
511 56, 57, 58, 59, 60, 61, 62, 63
512};
513
Takashi Iwai763f3562005-06-03 11:25:34 +0200514
Alexey Dobriyancebe41d2010-02-06 00:21:03 +0200515static DEFINE_PCI_DEVICE_TABLE(snd_hdspm_ids) = {
Takashi Iwai763f3562005-06-03 11:25:34 +0200516 {
517 .vendor = PCI_VENDOR_ID_XILINX,
518 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
519 .subvendor = PCI_ANY_ID,
520 .subdevice = PCI_ANY_ID,
521 .class = 0,
522 .class_mask = 0,
523 .driver_data = 0},
524 {0,}
525};
526
527MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
528
529/* prototypes */
Takashi Iwai98274f02005-11-17 14:52:34 +0100530static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
531 struct hdspm * hdspm);
532static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
533 struct hdspm * hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200534
Takashi Iwai98274f02005-11-17 14:52:34 +0100535static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm);
536static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm);
537static int hdspm_autosync_ref(struct hdspm * hdspm);
538static int snd_hdspm_set_defaults(struct hdspm * hdspm);
Takashi Iwai77a23f22008-08-21 13:00:13 +0200539static void hdspm_set_sgbuf(struct hdspm * hdspm,
540 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +0200541 unsigned int reg, int channels);
542
Remy Bruno3cee5a62006-10-16 12:46:32 +0200543static inline int HDSPM_bit2freq(int n)
544{
Denys Vlasenko62cef822008-04-14 13:04:18 +0200545 static const int bit2freq_tab[] = {
546 0, 32000, 44100, 48000, 64000, 88200,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200547 96000, 128000, 176400, 192000 };
548 if (n < 1 || n > 9)
549 return 0;
550 return bit2freq_tab[n];
551}
552
Uwe Kleine-Königb5950762010-11-01 15:38:34 -0400553/* Write/read to/from HDSPM with Addresses in Bytes
Takashi Iwai763f3562005-06-03 11:25:34 +0200554 not words but only 32Bit writes are allowed */
555
Takashi Iwai98274f02005-11-17 14:52:34 +0100556static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +0200557 unsigned int val)
558{
559 writel(val, hdspm->iobase + reg);
560}
561
Takashi Iwai98274f02005-11-17 14:52:34 +0100562static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +0200563{
564 return readl(hdspm->iobase + reg);
565}
566
567/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
568 mixer is write only on hardware so we have to cache him for read
569 each fader is a u32, but uses only the first 16 bit */
570
Takashi Iwai98274f02005-11-17 14:52:34 +0100571static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200572 unsigned int in)
573{
Adrian Bunk5bab24822006-03-13 14:15:04 +0100574 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +0200575 return 0;
576
577 return hdspm->mixer->ch[chan].in[in];
578}
579
Takashi Iwai98274f02005-11-17 14:52:34 +0100580static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200581 unsigned int pb)
582{
Adrian Bunk5bab24822006-03-13 14:15:04 +0100583 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +0200584 return 0;
585 return hdspm->mixer->ch[chan].pb[pb];
586}
587
Denys Vlasenko62cef822008-04-14 13:04:18 +0200588static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200589 unsigned int in, unsigned short data)
590{
591 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
592 return -1;
593
594 hdspm_write(hdspm,
595 HDSPM_MADI_mixerBase +
596 ((in + 128 * chan) * sizeof(u32)),
597 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
598 return 0;
599}
600
Denys Vlasenko62cef822008-04-14 13:04:18 +0200601static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200602 unsigned int pb, unsigned short data)
603{
604 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
605 return -1;
606
607 hdspm_write(hdspm,
608 HDSPM_MADI_mixerBase +
609 ((64 + pb + 128 * chan) * sizeof(u32)),
610 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
611 return 0;
612}
613
614
615/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +0100616static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +0200617{
618 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
619}
620
Takashi Iwai98274f02005-11-17 14:52:34 +0100621static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +0200622{
623 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
624}
625
626/* check if same process is writing and reading */
Denys Vlasenko62cef822008-04-14 13:04:18 +0200627static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200628{
629 unsigned long flags;
630 int ret = 1;
631
632 spin_lock_irqsave(&hdspm->lock, flags);
633 if ((hdspm->playback_pid != hdspm->capture_pid) &&
634 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
635 ret = 0;
636 }
637 spin_unlock_irqrestore(&hdspm->lock, flags);
638 return ret;
639}
640
641/* check for external sample rate */
Denys Vlasenko62cef822008-04-14 13:04:18 +0200642static int hdspm_external_sample_rate(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200643{
Remy Bruno3cee5a62006-10-16 12:46:32 +0200644 if (hdspm->is_aes32) {
645 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
646 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200647 unsigned int timecode =
648 hdspm_read(hdspm, HDSPM_timecodeRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +0200649
Remy Bruno3cee5a62006-10-16 12:46:32 +0200650 int syncref = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200651
Remy Bruno3cee5a62006-10-16 12:46:32 +0200652 if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
653 status & HDSPM_AES32_wcLock)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200654 return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit)
655 & 0xF);
Remy Bruno3cee5a62006-10-16 12:46:32 +0200656 if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
657 syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
658 status2 & (HDSPM_LockAES >>
659 (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
660 return HDSPM_bit2freq((timecode >>
661 (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
662 return 0;
663 } else {
664 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
665 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
666 unsigned int rate_bits;
667 int rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +0200668
Remy Bruno3cee5a62006-10-16 12:46:32 +0200669 /* if wordclock has synced freq and wordclock is valid */
670 if ((status2 & HDSPM_wcLock) != 0 &&
671 (status & HDSPM_SelSyncRef0) == 0) {
672
673 rate_bits = status2 & HDSPM_wcFreqMask;
674
675 switch (rate_bits) {
676 case HDSPM_wcFreq32:
677 rate = 32000;
678 break;
679 case HDSPM_wcFreq44_1:
680 rate = 44100;
681 break;
682 case HDSPM_wcFreq48:
683 rate = 48000;
684 break;
685 case HDSPM_wcFreq64:
686 rate = 64000;
687 break;
688 case HDSPM_wcFreq88_2:
689 rate = 88200;
690 break;
691 case HDSPM_wcFreq96:
692 rate = 96000;
693 break;
694 /* Quadspeed Bit missing ???? */
695 default:
696 rate = 0;
697 break;
698 }
Takashi Iwai763f3562005-06-03 11:25:34 +0200699 }
Takashi Iwai763f3562005-06-03 11:25:34 +0200700
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200701 /* if rate detected and Syncref is Word than have it,
702 * word has priority to MADI
703 */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200704 if (rate != 0 &&
705 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
706 return rate;
707
708 /* maby a madi input (which is taken if sel sync is madi) */
709 if (status & HDSPM_madiLock) {
710 rate_bits = status & HDSPM_madiFreqMask;
711
712 switch (rate_bits) {
713 case HDSPM_madiFreq32:
714 rate = 32000;
715 break;
716 case HDSPM_madiFreq44_1:
717 rate = 44100;
718 break;
719 case HDSPM_madiFreq48:
720 rate = 48000;
721 break;
722 case HDSPM_madiFreq64:
723 rate = 64000;
724 break;
725 case HDSPM_madiFreq88_2:
726 rate = 88200;
727 break;
728 case HDSPM_madiFreq96:
729 rate = 96000;
730 break;
731 case HDSPM_madiFreq128:
732 rate = 128000;
733 break;
734 case HDSPM_madiFreq176_4:
735 rate = 176400;
736 break;
737 case HDSPM_madiFreq192:
738 rate = 192000;
739 break;
740 default:
741 rate = 0;
742 break;
743 }
744 }
Takashi Iwai763f3562005-06-03 11:25:34 +0200745 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +0200746 }
Takashi Iwai763f3562005-06-03 11:25:34 +0200747}
748
749/* Latency function */
Takashi Iwai98274f02005-11-17 14:52:34 +0100750static inline void hdspm_compute_period_size(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200751{
752 hdspm->period_bytes =
753 1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
754}
755
Takashi Iwai98274f02005-11-17 14:52:34 +0100756static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200757{
758 int position;
759
760 position = hdspm_read(hdspm, HDSPM_statusRegister);
761
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200762 if (!hdspm->precise_ptr)
763 return (position & HDSPM_BufferID) ?
764 (hdspm->period_bytes / 4) : 0;
Takashi Iwai763f3562005-06-03 11:25:34 +0200765
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200766 /* hwpointer comes in bytes and is 64Bytes accurate (by docu since
767 PCI Burst)
Takashi Iwai763f3562005-06-03 11:25:34 +0200768 i have experimented that it is at most 64 Byte to much for playing
769 so substraction of 64 byte should be ok for ALSA, but use it only
770 for application where you know what you do since if you come to
771 near with record pointer it can be a disaster */
772
773 position &= HDSPM_BufferPositionMask;
774 position = ((position - 64) % (2 * hdspm->period_bytes)) / 4;
775
776 return position;
777}
778
779
Takashi Iwai98274f02005-11-17 14:52:34 +0100780static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +0200781{
782 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
783 hdspm_write(s, HDSPM_controlRegister, s->control_register);
784}
785
Takashi Iwai98274f02005-11-17 14:52:34 +0100786static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +0200787{
788 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
789 hdspm_write(s, HDSPM_controlRegister, s->control_register);
790}
791
792/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Denys Vlasenko62cef822008-04-14 13:04:18 +0200793static void hdspm_silence_playback(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200794{
795 int i;
796 int n = hdspm->period_bytes;
797 void *buf = hdspm->playback_buffer;
798
Remy Bruno3cee5a62006-10-16 12:46:32 +0200799 if (buf == NULL)
800 return;
Takashi Iwai763f3562005-06-03 11:25:34 +0200801
802 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
803 memset(buf, 0, n);
804 buf += HDSPM_CHANNEL_BUFFER_BYTES;
805 }
806}
807
Takashi Iwai98274f02005-11-17 14:52:34 +0100808static int hdspm_set_interrupt_interval(struct hdspm * s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +0200809{
810 int n;
811
812 spin_lock_irq(&s->lock);
813
814 frames >>= 7;
815 n = 0;
816 while (frames) {
817 n++;
818 frames >>= 1;
819 }
820 s->control_register &= ~HDSPM_LatencyMask;
821 s->control_register |= hdspm_encode_latency(n);
822
823 hdspm_write(s, HDSPM_controlRegister, s->control_register);
824
825 hdspm_compute_period_size(s);
826
827 spin_unlock_irq(&s->lock);
828
829 return 0;
830}
831
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100832static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
833{
834 u64 n;
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100835
836 if (rate >= 112000)
837 rate /= 4;
838 else if (rate >= 56000)
839 rate /= 2;
840
841 /* RME says n = 104857600000000, but in the windows MADI driver, I see:
Remy Bruno65345992007-08-31 12:21:08 +0200842// return 104857600000000 / rate; // 100 MHz
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100843 return 110100480000000 / rate; // 105 MHz
844 */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200845 /* n = 104857600000000ULL; */ /* = 2^20 * 10^8 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100846 n = 110100480000000ULL; /* Value checked for AES32 and MADI */
Takashi Iwai3f7440a2009-06-05 17:40:04 +0200847 n = div_u64(n, rate);
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100848 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +0200849 snd_BUG_ON(n >> 32);
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100850 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
851}
Takashi Iwai763f3562005-06-03 11:25:34 +0200852
853/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +0100854static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +0200855{
Takashi Iwai763f3562005-06-03 11:25:34 +0200856 int current_rate;
857 int rate_bits;
858 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +0200859 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +0200860
861 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
862 it (e.g. during module initialization).
863 */
864
865 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
866
867 /* SLAVE --- */
868 if (called_internally) {
869
870 /* request from ctl or card initialization
871 just make a warning an remember setting
872 for future master mode switching */
873
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200874 snd_printk(KERN_WARNING "HDSPM: "
875 "Warning: device is not running "
876 "as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +0200877 not_set = 1;
878 } else {
879
880 /* hw_param request while in AutoSync mode */
881 int external_freq =
882 hdspm_external_sample_rate(hdspm);
883
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200884 if (hdspm_autosync_ref(hdspm) ==
885 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +0200886
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200887 snd_printk(KERN_WARNING "HDSPM: "
888 "Detected no Externel Sync \n");
Takashi Iwai763f3562005-06-03 11:25:34 +0200889 not_set = 1;
890
891 } else if (rate != external_freq) {
892
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200893 snd_printk(KERN_WARNING "HDSPM: "
894 "Warning: No AutoSync source for "
895 "requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +0200896 not_set = 1;
897 }
898 }
899 }
900
901 current_rate = hdspm->system_sample_rate;
902
903 /* Changing between Singe, Double and Quad speed is not
904 allowed if any substreams are open. This is because such a change
905 causes a shift in the location of the DMA buffers and a reduction
906 in the number of available buffers.
907
908 Note that a similar but essentially insoluble problem exists for
909 externally-driven rate changes. All we can do is to flag rate
910 changes in the read/write routines.
911 */
912
Remy Bruno65345992007-08-31 12:21:08 +0200913 if (current_rate <= 48000)
914 current_speed = HDSPM_SPEED_SINGLE;
915 else if (current_rate <= 96000)
916 current_speed = HDSPM_SPEED_DOUBLE;
917 else
918 current_speed = HDSPM_SPEED_QUAD;
919
920 if (rate <= 48000)
921 target_speed = HDSPM_SPEED_SINGLE;
922 else if (rate <= 96000)
923 target_speed = HDSPM_SPEED_DOUBLE;
924 else
925 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +0200926
Takashi Iwai763f3562005-06-03 11:25:34 +0200927 switch (rate) {
928 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +0200929 rate_bits = HDSPM_Frequency32KHz;
930 break;
931 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +0200932 rate_bits = HDSPM_Frequency44_1KHz;
933 break;
934 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +0200935 rate_bits = HDSPM_Frequency48KHz;
936 break;
937 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +0200938 rate_bits = HDSPM_Frequency64KHz;
939 break;
940 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +0200941 rate_bits = HDSPM_Frequency88_2KHz;
942 break;
943 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +0200944 rate_bits = HDSPM_Frequency96KHz;
945 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +0200946 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200947 rate_bits = HDSPM_Frequency128KHz;
948 break;
949 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200950 rate_bits = HDSPM_Frequency176_4KHz;
951 break;
952 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200953 rate_bits = HDSPM_Frequency192KHz;
954 break;
Takashi Iwai763f3562005-06-03 11:25:34 +0200955 default:
956 return -EINVAL;
957 }
958
Remy Bruno65345992007-08-31 12:21:08 +0200959 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +0200960 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
961 snd_printk
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200962 (KERN_ERR "HDSPM: "
Remy Bruno65345992007-08-31 12:21:08 +0200963 "cannot change from %s speed to %s speed mode "
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200964 "(capture PID = %d, playback PID = %d)\n",
Remy Bruno65345992007-08-31 12:21:08 +0200965 hdspm_speed_names[current_speed],
966 hdspm_speed_names[target_speed],
Takashi Iwai763f3562005-06-03 11:25:34 +0200967 hdspm->capture_pid, hdspm->playback_pid);
968 return -EBUSY;
969 }
970
971 hdspm->control_register &= ~HDSPM_FrequencyMask;
972 hdspm->control_register |= rate_bits;
973 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
974
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100975 /* For AES32, need to set DDS value in FREQ register
976 For MADI, also apparently */
977 hdspm_set_dds_value(hdspm, rate);
978
979 if (hdspm->is_aes32 && rate != current_rate)
980 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
981
982 /* For AES32 and for MADI (at least rev 204), channel_map needs to
983 * always be channel_map_madi_ss, whatever the sample rate */
984 hdspm->channel_map = channel_map_madi_ss;
Takashi Iwai763f3562005-06-03 11:25:34 +0200985
986 hdspm->system_sample_rate = rate;
987
988 if (not_set != 0)
989 return -1;
990
991 return 0;
992}
993
994/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +0100995static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +0200996{
997 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200998 unsigned int gain;
999
1000 if (sgain > UNITY_GAIN)
1001 gain = UNITY_GAIN;
1002 else if (sgain < 0)
1003 gain = 0;
1004 else
1005 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001006
1007 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1008 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1009 hdspm_write_in_gain(hdspm, i, j, gain);
1010 hdspm_write_pb_gain(hdspm, i, j, gain);
1011 }
1012}
1013
1014/*----------------------------------------------------------------------------
1015 MIDI
1016 ----------------------------------------------------------------------------*/
1017
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001018static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1019 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001020{
1021 /* the hardware already does the relevant bit-mask with 0xff */
1022 if (id)
1023 return hdspm_read(hdspm, HDSPM_midiDataIn1);
1024 else
1025 return hdspm_read(hdspm, HDSPM_midiDataIn0);
1026}
1027
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001028static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1029 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001030{
1031 /* the hardware already does the relevant bit-mask with 0xff */
1032 if (id)
Harvey Harrison0b76b512008-02-29 11:54:49 +01001033 hdspm_write(hdspm, HDSPM_midiDataOut1, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001034 else
Harvey Harrison0b76b512008-02-29 11:54:49 +01001035 hdspm_write(hdspm, HDSPM_midiDataOut0, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001036}
1037
Takashi Iwai98274f02005-11-17 14:52:34 +01001038static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001039{
1040 if (id)
1041 return (hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff);
1042 else
1043 return (hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff);
1044}
1045
Takashi Iwai98274f02005-11-17 14:52:34 +01001046static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001047{
1048 int fifo_bytes_used;
1049
1050 if (id)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001051 fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1);
Takashi Iwai763f3562005-06-03 11:25:34 +02001052 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001053 fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0);
1054 fifo_bytes_used &= 0xff;
Takashi Iwai763f3562005-06-03 11:25:34 +02001055
1056 if (fifo_bytes_used < 128)
1057 return 128 - fifo_bytes_used;
1058 else
1059 return 0;
1060}
1061
Denys Vlasenko62cef822008-04-14 13:04:18 +02001062static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001063{
1064 while (snd_hdspm_midi_input_available (hdspm, id))
1065 snd_hdspm_midi_read_byte (hdspm, id);
1066}
1067
Takashi Iwai98274f02005-11-17 14:52:34 +01001068static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001069{
1070 unsigned long flags;
1071 int n_pending;
1072 int to_write;
1073 int i;
1074 unsigned char buf[128];
1075
1076 /* Output is not interrupt driven */
1077
1078 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001079 if (hmidi->output &&
1080 !snd_rawmidi_transmit_empty (hmidi->output)) {
1081 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1082 hmidi->id);
1083 if (n_pending > 0) {
1084 if (n_pending > (int)sizeof (buf))
1085 n_pending = sizeof (buf);
1086
1087 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1088 n_pending);
1089 if (to_write > 0) {
1090 for (i = 0; i < to_write; ++i)
1091 snd_hdspm_midi_write_byte (hmidi->hdspm,
1092 hmidi->id,
1093 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001094 }
1095 }
1096 }
1097 spin_unlock_irqrestore (&hmidi->lock, flags);
1098 return 0;
1099}
1100
Takashi Iwai98274f02005-11-17 14:52:34 +01001101static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001102{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001103 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1104 * input FIFO size
1105 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001106 unsigned long flags;
1107 int n_pending;
1108 int i;
1109
1110 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001111 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1112 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001113 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001114 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001115 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001116 for (i = 0; i < n_pending; ++i)
1117 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1118 hmidi->id);
1119 if (n_pending)
1120 snd_rawmidi_receive (hmidi->input, buf,
1121 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001122 } else {
1123 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001124 while (n_pending--)
1125 snd_hdspm_midi_read_byte (hmidi->hdspm,
1126 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001127 }
1128 }
1129 hmidi->pending = 0;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001130 if (hmidi->id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001131 hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001132 else
Takashi Iwai763f3562005-06-03 11:25:34 +02001133 hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001134 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1135 hmidi->hdspm->control_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02001136 spin_unlock_irqrestore (&hmidi->lock, flags);
1137 return snd_hdspm_midi_output_write (hmidi);
1138}
1139
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001140static void
1141snd_hdspm_midi_input_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 *hdspm;
1144 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001145 unsigned long flags;
1146 u32 ie;
1147
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001148 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001149 hdspm = hmidi->hdspm;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001150 ie = hmidi->id ?
1151 HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable;
Takashi Iwai763f3562005-06-03 11:25:34 +02001152 spin_lock_irqsave (&hdspm->lock, flags);
1153 if (up) {
1154 if (!(hdspm->control_register & ie)) {
1155 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
1156 hdspm->control_register |= ie;
1157 }
1158 } else {
1159 hdspm->control_register &= ~ie;
1160 }
1161
1162 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1163 spin_unlock_irqrestore (&hdspm->lock, flags);
1164}
1165
1166static void snd_hdspm_midi_output_timer(unsigned long data)
1167{
Takashi Iwai98274f02005-11-17 14:52:34 +01001168 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001169 unsigned long flags;
1170
1171 snd_hdspm_midi_output_write(hmidi);
1172 spin_lock_irqsave (&hmidi->lock, flags);
1173
1174 /* this does not bump hmidi->istimer, because the
1175 kernel automatically removed the timer when it
1176 expired, and we are now adding it back, thus
1177 leaving istimer wherever it was set before.
1178 */
1179
1180 if (hmidi->istimer) {
1181 hmidi->timer.expires = 1 + jiffies;
1182 add_timer(&hmidi->timer);
1183 }
1184
1185 spin_unlock_irqrestore (&hmidi->lock, flags);
1186}
1187
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001188static void
1189snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001190{
Takashi Iwai98274f02005-11-17 14:52:34 +01001191 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001192 unsigned long flags;
1193
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001194 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001195 spin_lock_irqsave (&hmidi->lock, flags);
1196 if (up) {
1197 if (!hmidi->istimer) {
1198 init_timer(&hmidi->timer);
1199 hmidi->timer.function = snd_hdspm_midi_output_timer;
1200 hmidi->timer.data = (unsigned long) hmidi;
1201 hmidi->timer.expires = 1 + jiffies;
1202 add_timer(&hmidi->timer);
1203 hmidi->istimer++;
1204 }
1205 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001206 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001207 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001208 }
1209 spin_unlock_irqrestore (&hmidi->lock, flags);
1210 if (up)
1211 snd_hdspm_midi_output_write(hmidi);
1212}
1213
Takashi Iwai98274f02005-11-17 14:52:34 +01001214static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001215{
Takashi Iwai98274f02005-11-17 14:52:34 +01001216 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001217
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001218 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001219 spin_lock_irq (&hmidi->lock);
1220 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1221 hmidi->input = substream;
1222 spin_unlock_irq (&hmidi->lock);
1223
1224 return 0;
1225}
1226
Takashi Iwai98274f02005-11-17 14:52:34 +01001227static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001228{
Takashi Iwai98274f02005-11-17 14:52:34 +01001229 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001230
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001231 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001232 spin_lock_irq (&hmidi->lock);
1233 hmidi->output = substream;
1234 spin_unlock_irq (&hmidi->lock);
1235
1236 return 0;
1237}
1238
Takashi Iwai98274f02005-11-17 14:52:34 +01001239static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001240{
Takashi Iwai98274f02005-11-17 14:52:34 +01001241 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001242
1243 snd_hdspm_midi_input_trigger (substream, 0);
1244
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001245 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001246 spin_lock_irq (&hmidi->lock);
1247 hmidi->input = NULL;
1248 spin_unlock_irq (&hmidi->lock);
1249
1250 return 0;
1251}
1252
Takashi Iwai98274f02005-11-17 14:52:34 +01001253static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001254{
Takashi Iwai98274f02005-11-17 14:52:34 +01001255 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001256
1257 snd_hdspm_midi_output_trigger (substream, 0);
1258
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001259 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001260 spin_lock_irq (&hmidi->lock);
1261 hmidi->output = NULL;
1262 spin_unlock_irq (&hmidi->lock);
1263
1264 return 0;
1265}
1266
Takashi Iwai98274f02005-11-17 14:52:34 +01001267static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001268{
1269 .open = snd_hdspm_midi_output_open,
1270 .close = snd_hdspm_midi_output_close,
1271 .trigger = snd_hdspm_midi_output_trigger,
1272};
1273
Takashi Iwai98274f02005-11-17 14:52:34 +01001274static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001275{
1276 .open = snd_hdspm_midi_input_open,
1277 .close = snd_hdspm_midi_input_close,
1278 .trigger = snd_hdspm_midi_input_trigger,
1279};
1280
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001281static int __devinit snd_hdspm_create_midi (struct snd_card *card,
1282 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001283{
1284 int err;
1285 char buf[32];
1286
1287 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02001288 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02001289 spin_lock_init (&hdspm->midi[id].lock);
1290
1291 sprintf (buf, "%s MIDI %d", card->shortname, id+1);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001292 err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi);
1293 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001294 return err;
1295
Jaroslav Kysela972d4c52008-11-12 16:37:48 +01001296 sprintf(hdspm->midi[id].rmidi->name, "HDSPM MIDI %d", id+1);
Takashi Iwai763f3562005-06-03 11:25:34 +02001297 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
1298
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001299 snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
1300 &snd_hdspm_midi_output);
1301 snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
1302 &snd_hdspm_midi_input);
Takashi Iwai763f3562005-06-03 11:25:34 +02001303
1304 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
1305 SNDRV_RAWMIDI_INFO_INPUT |
1306 SNDRV_RAWMIDI_INFO_DUPLEX;
1307
1308 return 0;
1309}
1310
1311
1312static void hdspm_midi_tasklet(unsigned long arg)
1313{
Takashi Iwai98274f02005-11-17 14:52:34 +01001314 struct hdspm *hdspm = (struct hdspm *)arg;
Takashi Iwai763f3562005-06-03 11:25:34 +02001315
1316 if (hdspm->midi[0].pending)
1317 snd_hdspm_midi_input_read (&hdspm->midi[0]);
1318 if (hdspm->midi[1].pending)
1319 snd_hdspm_midi_input_read (&hdspm->midi[1]);
1320}
1321
1322
1323/*-----------------------------------------------------------------------------
1324 Status Interface
1325 ----------------------------------------------------------------------------*/
1326
1327/* get the system sample rate which is set */
1328
1329#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001330{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001331 .name = xname, \
1332 .index = xindex, \
1333 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1334 .info = snd_hdspm_info_system_sample_rate, \
1335 .get = snd_hdspm_get_system_sample_rate \
1336}
1337
Takashi Iwai98274f02005-11-17 14:52:34 +01001338static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
1339 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001340{
1341 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1342 uinfo->count = 1;
1343 return 0;
1344}
1345
Takashi Iwai98274f02005-11-17 14:52:34 +01001346static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
1347 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02001348 ucontrol)
1349{
Takashi Iwai98274f02005-11-17 14:52:34 +01001350 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001351
1352 ucontrol->value.enumerated.item[0] = hdspm->system_sample_rate;
1353 return 0;
1354}
1355
1356#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001357{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001358 .name = xname, \
1359 .index = xindex, \
1360 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1361 .info = snd_hdspm_info_autosync_sample_rate, \
1362 .get = snd_hdspm_get_autosync_sample_rate \
1363}
1364
Takashi Iwai98274f02005-11-17 14:52:34 +01001365static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
1366 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001367{
1368 static char *texts[] = { "32000", "44100", "48000",
1369 "64000", "88200", "96000",
1370 "128000", "176400", "192000",
1371 "None"
1372 };
1373 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1374 uinfo->count = 1;
1375 uinfo->value.enumerated.items = 10;
1376 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1377 uinfo->value.enumerated.item =
1378 uinfo->value.enumerated.items - 1;
1379 strcpy(uinfo->value.enumerated.name,
1380 texts[uinfo->value.enumerated.item]);
1381 return 0;
1382}
1383
Takashi Iwai98274f02005-11-17 14:52:34 +01001384static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
1385 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02001386 ucontrol)
1387{
Takashi Iwai98274f02005-11-17 14:52:34 +01001388 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001389
1390 switch (hdspm_external_sample_rate(hdspm)) {
1391 case 32000:
1392 ucontrol->value.enumerated.item[0] = 0;
1393 break;
1394 case 44100:
1395 ucontrol->value.enumerated.item[0] = 1;
1396 break;
1397 case 48000:
1398 ucontrol->value.enumerated.item[0] = 2;
1399 break;
1400 case 64000:
1401 ucontrol->value.enumerated.item[0] = 3;
1402 break;
1403 case 88200:
1404 ucontrol->value.enumerated.item[0] = 4;
1405 break;
1406 case 96000:
1407 ucontrol->value.enumerated.item[0] = 5;
1408 break;
1409 case 128000:
1410 ucontrol->value.enumerated.item[0] = 6;
1411 break;
1412 case 176400:
1413 ucontrol->value.enumerated.item[0] = 7;
1414 break;
1415 case 192000:
1416 ucontrol->value.enumerated.item[0] = 8;
1417 break;
1418
1419 default:
1420 ucontrol->value.enumerated.item[0] = 9;
1421 }
1422 return 0;
1423}
1424
1425#define HDSPM_SYSTEM_CLOCK_MODE(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 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1430 .info = snd_hdspm_info_system_clock_mode, \
1431 .get = snd_hdspm_get_system_clock_mode, \
1432}
1433
1434
1435
Takashi Iwai98274f02005-11-17 14:52:34 +01001436static int hdspm_system_clock_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001437{
1438 /* Always reflect the hardware info, rme is never wrong !!!! */
1439
1440 if (hdspm->control_register & HDSPM_ClockModeMaster)
1441 return 0;
1442 return 1;
1443}
1444
Takashi Iwai98274f02005-11-17 14:52:34 +01001445static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
1446 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001447{
1448 static char *texts[] = { "Master", "Slave" };
1449
1450 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1451 uinfo->count = 1;
1452 uinfo->value.enumerated.items = 2;
1453 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1454 uinfo->value.enumerated.item =
1455 uinfo->value.enumerated.items - 1;
1456 strcpy(uinfo->value.enumerated.name,
1457 texts[uinfo->value.enumerated.item]);
1458 return 0;
1459}
1460
Takashi Iwai98274f02005-11-17 14:52:34 +01001461static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
1462 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001463{
Takashi Iwai98274f02005-11-17 14:52:34 +01001464 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001465
1466 ucontrol->value.enumerated.item[0] =
1467 hdspm_system_clock_mode(hdspm);
1468 return 0;
1469}
1470
1471#define HDSPM_CLOCK_SOURCE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001472{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001473 .name = xname, \
1474 .index = xindex, \
1475 .info = snd_hdspm_info_clock_source, \
1476 .get = snd_hdspm_get_clock_source, \
1477 .put = snd_hdspm_put_clock_source \
1478}
1479
Takashi Iwai98274f02005-11-17 14:52:34 +01001480static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001481{
1482 if (hdspm->control_register & HDSPM_ClockModeMaster) {
1483 switch (hdspm->system_sample_rate) {
1484 case 32000:
1485 return 1;
1486 case 44100:
1487 return 2;
1488 case 48000:
1489 return 3;
1490 case 64000:
1491 return 4;
1492 case 88200:
1493 return 5;
1494 case 96000:
1495 return 6;
1496 case 128000:
1497 return 7;
1498 case 176400:
1499 return 8;
1500 case 192000:
1501 return 9;
1502 default:
1503 return 3;
1504 }
1505 } else {
1506 return 0;
1507 }
1508}
1509
Takashi Iwai98274f02005-11-17 14:52:34 +01001510static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02001511{
1512 int rate;
1513 switch (mode) {
1514
1515 case HDSPM_CLOCK_SOURCE_AUTOSYNC:
1516 if (hdspm_external_sample_rate(hdspm) != 0) {
1517 hdspm->control_register &= ~HDSPM_ClockModeMaster;
1518 hdspm_write(hdspm, HDSPM_controlRegister,
1519 hdspm->control_register);
1520 return 0;
1521 }
1522 return -1;
1523 case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
1524 rate = 32000;
1525 break;
1526 case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
1527 rate = 44100;
1528 break;
1529 case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
1530 rate = 48000;
1531 break;
1532 case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
1533 rate = 64000;
1534 break;
1535 case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
1536 rate = 88200;
1537 break;
1538 case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
1539 rate = 96000;
1540 break;
1541 case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
1542 rate = 128000;
1543 break;
1544 case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
1545 rate = 176400;
1546 break;
1547 case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
1548 rate = 192000;
1549 break;
1550
1551 default:
1552 rate = 44100;
1553 }
1554 hdspm->control_register |= HDSPM_ClockModeMaster;
1555 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1556 hdspm_set_rate(hdspm, rate, 1);
1557 return 0;
1558}
1559
Takashi Iwai98274f02005-11-17 14:52:34 +01001560static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
1561 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001562{
1563 static char *texts[] = { "AutoSync",
1564 "Internal 32.0 kHz", "Internal 44.1 kHz",
1565 "Internal 48.0 kHz",
1566 "Internal 64.0 kHz", "Internal 88.2 kHz",
1567 "Internal 96.0 kHz",
1568 "Internal 128.0 kHz", "Internal 176.4 kHz",
1569 "Internal 192.0 kHz"
1570 };
1571
1572 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1573 uinfo->count = 1;
1574 uinfo->value.enumerated.items = 10;
1575
1576 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1577 uinfo->value.enumerated.item =
1578 uinfo->value.enumerated.items - 1;
1579
1580 strcpy(uinfo->value.enumerated.name,
1581 texts[uinfo->value.enumerated.item]);
1582
1583 return 0;
1584}
1585
Takashi Iwai98274f02005-11-17 14:52:34 +01001586static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
1587 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001588{
Takashi Iwai98274f02005-11-17 14:52:34 +01001589 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001590
1591 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
1592 return 0;
1593}
1594
Takashi Iwai98274f02005-11-17 14:52:34 +01001595static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
1596 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001597{
Takashi Iwai98274f02005-11-17 14:52:34 +01001598 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001599 int change;
1600 int val;
1601
1602 if (!snd_hdspm_use_is_exclusive(hdspm))
1603 return -EBUSY;
1604 val = ucontrol->value.enumerated.item[0];
1605 if (val < 0)
1606 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001607 if (val > 9)
1608 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02001609 spin_lock_irq(&hdspm->lock);
1610 if (val != hdspm_clock_source(hdspm))
1611 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
1612 else
1613 change = 0;
1614 spin_unlock_irq(&hdspm->lock);
1615 return change;
1616}
1617
1618#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001619{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001620 .name = xname, \
1621 .index = xindex, \
1622 .info = snd_hdspm_info_pref_sync_ref, \
1623 .get = snd_hdspm_get_pref_sync_ref, \
1624 .put = snd_hdspm_put_pref_sync_ref \
1625}
1626
Takashi Iwai98274f02005-11-17 14:52:34 +01001627static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001628{
1629 /* Notice that this looks at the requested sync source,
1630 not the one actually in use.
1631 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001632 if (hdspm->is_aes32) {
1633 switch (hdspm->control_register & HDSPM_SyncRefMask) {
1634 /* number gives AES index, except for 0 which
1635 corresponds to WordClock */
1636 case 0: return 0;
1637 case HDSPM_SyncRef0: return 1;
1638 case HDSPM_SyncRef1: return 2;
1639 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3;
1640 case HDSPM_SyncRef2: return 4;
1641 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5;
1642 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6;
1643 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0: return 7;
1644 case HDSPM_SyncRef3: return 8;
1645 }
1646 } else {
1647 switch (hdspm->control_register & HDSPM_SyncRefMask) {
1648 case HDSPM_SyncRef_Word:
1649 return HDSPM_SYNC_FROM_WORD;
1650 case HDSPM_SyncRef_MADI:
1651 return HDSPM_SYNC_FROM_MADI;
1652 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001653 }
1654
1655 return HDSPM_SYNC_FROM_WORD;
1656}
1657
Takashi Iwai98274f02005-11-17 14:52:34 +01001658static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02001659{
1660 hdspm->control_register &= ~HDSPM_SyncRefMask;
1661
Remy Bruno3cee5a62006-10-16 12:46:32 +02001662 if (hdspm->is_aes32) {
1663 switch (pref) {
1664 case 0:
1665 hdspm->control_register |= 0;
1666 break;
1667 case 1:
1668 hdspm->control_register |= HDSPM_SyncRef0;
1669 break;
1670 case 2:
1671 hdspm->control_register |= HDSPM_SyncRef1;
1672 break;
1673 case 3:
1674 hdspm->control_register |= HDSPM_SyncRef1+HDSPM_SyncRef0;
1675 break;
1676 case 4:
1677 hdspm->control_register |= HDSPM_SyncRef2;
1678 break;
1679 case 5:
1680 hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef0;
1681 break;
1682 case 6:
1683 hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1;
1684 break;
1685 case 7:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001686 hdspm->control_register |=
1687 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001688 break;
1689 case 8:
1690 hdspm->control_register |= HDSPM_SyncRef3;
1691 break;
1692 default:
1693 return -1;
1694 }
1695 } else {
1696 switch (pref) {
1697 case HDSPM_SYNC_FROM_MADI:
1698 hdspm->control_register |= HDSPM_SyncRef_MADI;
1699 break;
1700 case HDSPM_SYNC_FROM_WORD:
1701 hdspm->control_register |= HDSPM_SyncRef_Word;
1702 break;
1703 default:
1704 return -1;
1705 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001706 }
1707 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1708 return 0;
1709}
1710
Takashi Iwai98274f02005-11-17 14:52:34 +01001711static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
1712 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001713{
Remy Bruno3cee5a62006-10-16 12:46:32 +02001714 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001715
Remy Bruno3cee5a62006-10-16 12:46:32 +02001716 if (hdspm->is_aes32) {
1717 static char *texts[] = { "Word", "AES1", "AES2", "AES3",
1718 "AES4", "AES5", "AES6", "AES7", "AES8" };
Takashi Iwai763f3562005-06-03 11:25:34 +02001719
Remy Bruno3cee5a62006-10-16 12:46:32 +02001720 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1721 uinfo->count = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02001722
Remy Bruno3cee5a62006-10-16 12:46:32 +02001723 uinfo->value.enumerated.items = 9;
1724
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001725 if (uinfo->value.enumerated.item >=
1726 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001727 uinfo->value.enumerated.item =
1728 uinfo->value.enumerated.items - 1;
1729 strcpy(uinfo->value.enumerated.name,
1730 texts[uinfo->value.enumerated.item]);
1731 } else {
1732 static char *texts[] = { "Word", "MADI" };
1733
1734 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1735 uinfo->count = 1;
1736
1737 uinfo->value.enumerated.items = 2;
1738
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001739 if (uinfo->value.enumerated.item >=
1740 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001741 uinfo->value.enumerated.item =
1742 uinfo->value.enumerated.items - 1;
1743 strcpy(uinfo->value.enumerated.name,
1744 texts[uinfo->value.enumerated.item]);
1745 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001746 return 0;
1747}
1748
Takashi Iwai98274f02005-11-17 14:52:34 +01001749static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
1750 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001751{
Takashi Iwai98274f02005-11-17 14:52:34 +01001752 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001753
1754 ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
1755 return 0;
1756}
1757
Takashi Iwai98274f02005-11-17 14:52:34 +01001758static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
1759 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001760{
Takashi Iwai98274f02005-11-17 14:52:34 +01001761 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001762 int change, max;
1763 unsigned int val;
1764
Remy Bruno3cee5a62006-10-16 12:46:32 +02001765 max = hdspm->is_aes32 ? 9 : 2;
Takashi Iwai763f3562005-06-03 11:25:34 +02001766
1767 if (!snd_hdspm_use_is_exclusive(hdspm))
1768 return -EBUSY;
1769
1770 val = ucontrol->value.enumerated.item[0] % max;
1771
1772 spin_lock_irq(&hdspm->lock);
1773 change = (int) val != hdspm_pref_sync_ref(hdspm);
1774 hdspm_set_pref_sync_ref(hdspm, val);
1775 spin_unlock_irq(&hdspm->lock);
1776 return change;
1777}
1778
1779#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001780{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001781 .name = xname, \
1782 .index = xindex, \
1783 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1784 .info = snd_hdspm_info_autosync_ref, \
1785 .get = snd_hdspm_get_autosync_ref, \
1786}
1787
Takashi Iwai98274f02005-11-17 14:52:34 +01001788static int hdspm_autosync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001789{
Remy Bruno3cee5a62006-10-16 12:46:32 +02001790 if (hdspm->is_aes32) {
1791 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001792 unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) &
1793 0xF;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001794 if (syncref == 0)
1795 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
1796 if (syncref <= 8)
1797 return syncref;
1798 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
1799 } else {
1800 /* This looks at the autosync selected sync reference */
1801 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Takashi Iwai763f3562005-06-03 11:25:34 +02001802
Remy Bruno3cee5a62006-10-16 12:46:32 +02001803 switch (status2 & HDSPM_SelSyncRefMask) {
1804 case HDSPM_SelSyncRef_WORD:
1805 return HDSPM_AUTOSYNC_FROM_WORD;
1806 case HDSPM_SelSyncRef_MADI:
1807 return HDSPM_AUTOSYNC_FROM_MADI;
1808 case HDSPM_SelSyncRef_NVALID:
1809 return HDSPM_AUTOSYNC_FROM_NONE;
1810 default:
1811 return 0;
1812 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001813
Takashi Iwai763f3562005-06-03 11:25:34 +02001814 return 0;
1815 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001816}
1817
Takashi Iwai98274f02005-11-17 14:52:34 +01001818static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
1819 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001820{
Remy Bruno3cee5a62006-10-16 12:46:32 +02001821 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001822
Remy Bruno3cee5a62006-10-16 12:46:32 +02001823 if (hdspm->is_aes32) {
1824 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
1825 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
1826
1827 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1828 uinfo->count = 1;
1829 uinfo->value.enumerated.items = 10;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001830 if (uinfo->value.enumerated.item >=
1831 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001832 uinfo->value.enumerated.item =
1833 uinfo->value.enumerated.items - 1;
1834 strcpy(uinfo->value.enumerated.name,
1835 texts[uinfo->value.enumerated.item]);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001836 } else {
Remy Bruno3cee5a62006-10-16 12:46:32 +02001837 static char *texts[] = { "WordClock", "MADI", "None" };
1838
1839 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1840 uinfo->count = 1;
1841 uinfo->value.enumerated.items = 3;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001842 if (uinfo->value.enumerated.item >=
1843 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001844 uinfo->value.enumerated.item =
1845 uinfo->value.enumerated.items - 1;
1846 strcpy(uinfo->value.enumerated.name,
1847 texts[uinfo->value.enumerated.item]);
1848 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001849 return 0;
1850}
1851
Takashi Iwai98274f02005-11-17 14:52:34 +01001852static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
1853 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001854{
Takashi Iwai98274f02005-11-17 14:52:34 +01001855 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001856
Remy Bruno65345992007-08-31 12:21:08 +02001857 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001858 return 0;
1859}
1860
1861#define HDSPM_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001862{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001863 .name = xname, \
1864 .index = xindex, \
1865 .info = snd_hdspm_info_line_out, \
1866 .get = snd_hdspm_get_line_out, \
1867 .put = snd_hdspm_put_line_out \
1868}
1869
Takashi Iwai98274f02005-11-17 14:52:34 +01001870static int hdspm_line_out(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001871{
1872 return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
1873}
1874
1875
Takashi Iwai98274f02005-11-17 14:52:34 +01001876static int hdspm_set_line_output(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001877{
1878 if (out)
1879 hdspm->control_register |= HDSPM_LineOut;
1880 else
1881 hdspm->control_register &= ~HDSPM_LineOut;
1882 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1883
1884 return 0;
1885}
1886
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001887#define snd_hdspm_info_line_out snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02001888
Takashi Iwai98274f02005-11-17 14:52:34 +01001889static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
1890 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001891{
Takashi Iwai98274f02005-11-17 14:52:34 +01001892 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001893
1894 spin_lock_irq(&hdspm->lock);
1895 ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
1896 spin_unlock_irq(&hdspm->lock);
1897 return 0;
1898}
1899
Takashi Iwai98274f02005-11-17 14:52:34 +01001900static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
1901 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001902{
Takashi Iwai98274f02005-11-17 14:52:34 +01001903 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001904 int change;
1905 unsigned int val;
1906
1907 if (!snd_hdspm_use_is_exclusive(hdspm))
1908 return -EBUSY;
1909 val = ucontrol->value.integer.value[0] & 1;
1910 spin_lock_irq(&hdspm->lock);
1911 change = (int) val != hdspm_line_out(hdspm);
1912 hdspm_set_line_output(hdspm, val);
1913 spin_unlock_irq(&hdspm->lock);
1914 return change;
1915}
1916
1917#define HDSPM_TX_64(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001918{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001919 .name = xname, \
1920 .index = xindex, \
1921 .info = snd_hdspm_info_tx_64, \
1922 .get = snd_hdspm_get_tx_64, \
1923 .put = snd_hdspm_put_tx_64 \
1924}
1925
Takashi Iwai98274f02005-11-17 14:52:34 +01001926static int hdspm_tx_64(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001927{
1928 return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
1929}
1930
Takashi Iwai98274f02005-11-17 14:52:34 +01001931static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001932{
1933 if (out)
1934 hdspm->control_register |= HDSPM_TX_64ch;
1935 else
1936 hdspm->control_register &= ~HDSPM_TX_64ch;
1937 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1938
1939 return 0;
1940}
1941
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001942#define snd_hdspm_info_tx_64 snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02001943
Takashi Iwai98274f02005-11-17 14:52:34 +01001944static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
1945 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001946{
Takashi Iwai98274f02005-11-17 14:52:34 +01001947 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001948
1949 spin_lock_irq(&hdspm->lock);
1950 ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
1951 spin_unlock_irq(&hdspm->lock);
1952 return 0;
1953}
1954
Takashi Iwai98274f02005-11-17 14:52:34 +01001955static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
1956 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001957{
Takashi Iwai98274f02005-11-17 14:52:34 +01001958 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001959 int change;
1960 unsigned int val;
1961
1962 if (!snd_hdspm_use_is_exclusive(hdspm))
1963 return -EBUSY;
1964 val = ucontrol->value.integer.value[0] & 1;
1965 spin_lock_irq(&hdspm->lock);
1966 change = (int) val != hdspm_tx_64(hdspm);
1967 hdspm_set_tx_64(hdspm, val);
1968 spin_unlock_irq(&hdspm->lock);
1969 return change;
1970}
1971
1972#define HDSPM_C_TMS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001973{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001974 .name = xname, \
1975 .index = xindex, \
1976 .info = snd_hdspm_info_c_tms, \
1977 .get = snd_hdspm_get_c_tms, \
1978 .put = snd_hdspm_put_c_tms \
1979}
1980
Takashi Iwai98274f02005-11-17 14:52:34 +01001981static int hdspm_c_tms(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001982{
1983 return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
1984}
1985
Takashi Iwai98274f02005-11-17 14:52:34 +01001986static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001987{
1988 if (out)
1989 hdspm->control_register |= HDSPM_clr_tms;
1990 else
1991 hdspm->control_register &= ~HDSPM_clr_tms;
1992 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1993
1994 return 0;
1995}
1996
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001997#define snd_hdspm_info_c_tms snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02001998
Takashi Iwai98274f02005-11-17 14:52:34 +01001999static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
2000 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002001{
Takashi Iwai98274f02005-11-17 14:52:34 +01002002 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002003
2004 spin_lock_irq(&hdspm->lock);
2005 ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
2006 spin_unlock_irq(&hdspm->lock);
2007 return 0;
2008}
2009
Takashi Iwai98274f02005-11-17 14:52:34 +01002010static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
2011 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002012{
Takashi Iwai98274f02005-11-17 14:52:34 +01002013 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002014 int change;
2015 unsigned int val;
2016
2017 if (!snd_hdspm_use_is_exclusive(hdspm))
2018 return -EBUSY;
2019 val = ucontrol->value.integer.value[0] & 1;
2020 spin_lock_irq(&hdspm->lock);
2021 change = (int) val != hdspm_c_tms(hdspm);
2022 hdspm_set_c_tms(hdspm, val);
2023 spin_unlock_irq(&hdspm->lock);
2024 return change;
2025}
2026
2027#define HDSPM_SAFE_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002028{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002029 .name = xname, \
2030 .index = xindex, \
2031 .info = snd_hdspm_info_safe_mode, \
2032 .get = snd_hdspm_get_safe_mode, \
2033 .put = snd_hdspm_put_safe_mode \
2034}
2035
Takashi Iwai98274f02005-11-17 14:52:34 +01002036static int hdspm_safe_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002037{
2038 return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
2039}
2040
Takashi Iwai98274f02005-11-17 14:52:34 +01002041static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002042{
2043 if (out)
2044 hdspm->control_register |= HDSPM_AutoInp;
2045 else
2046 hdspm->control_register &= ~HDSPM_AutoInp;
2047 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2048
2049 return 0;
2050}
2051
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002052#define snd_hdspm_info_safe_mode snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002053
Takashi Iwai98274f02005-11-17 14:52:34 +01002054static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
2055 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002056{
Takashi Iwai98274f02005-11-17 14:52:34 +01002057 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002058
2059 spin_lock_irq(&hdspm->lock);
2060 ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
2061 spin_unlock_irq(&hdspm->lock);
2062 return 0;
2063}
2064
Takashi Iwai98274f02005-11-17 14:52:34 +01002065static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
2066 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002067{
Takashi Iwai98274f02005-11-17 14:52:34 +01002068 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002069 int change;
2070 unsigned int val;
2071
2072 if (!snd_hdspm_use_is_exclusive(hdspm))
2073 return -EBUSY;
2074 val = ucontrol->value.integer.value[0] & 1;
2075 spin_lock_irq(&hdspm->lock);
2076 change = (int) val != hdspm_safe_mode(hdspm);
2077 hdspm_set_safe_mode(hdspm, val);
2078 spin_unlock_irq(&hdspm->lock);
2079 return change;
2080}
2081
Remy Bruno3cee5a62006-10-16 12:46:32 +02002082#define HDSPM_EMPHASIS(xname, xindex) \
2083{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2084 .name = xname, \
2085 .index = xindex, \
2086 .info = snd_hdspm_info_emphasis, \
2087 .get = snd_hdspm_get_emphasis, \
2088 .put = snd_hdspm_put_emphasis \
2089}
2090
2091static int hdspm_emphasis(struct hdspm * hdspm)
2092{
2093 return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0;
2094}
2095
2096static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
2097{
2098 if (emp)
2099 hdspm->control_register |= HDSPM_Emphasis;
2100 else
2101 hdspm->control_register &= ~HDSPM_Emphasis;
2102 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2103
2104 return 0;
2105}
2106
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002107#define snd_hdspm_info_emphasis snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02002108
2109static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
2110 struct snd_ctl_elem_value *ucontrol)
2111{
2112 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2113
2114 spin_lock_irq(&hdspm->lock);
2115 ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm);
2116 spin_unlock_irq(&hdspm->lock);
2117 return 0;
2118}
2119
2120static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
2121 struct snd_ctl_elem_value *ucontrol)
2122{
2123 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2124 int change;
2125 unsigned int val;
2126
2127 if (!snd_hdspm_use_is_exclusive(hdspm))
2128 return -EBUSY;
2129 val = ucontrol->value.integer.value[0] & 1;
2130 spin_lock_irq(&hdspm->lock);
2131 change = (int) val != hdspm_emphasis(hdspm);
2132 hdspm_set_emphasis(hdspm, val);
2133 spin_unlock_irq(&hdspm->lock);
2134 return change;
2135}
2136
2137#define HDSPM_DOLBY(xname, xindex) \
2138{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2139 .name = xname, \
2140 .index = xindex, \
2141 .info = snd_hdspm_info_dolby, \
2142 .get = snd_hdspm_get_dolby, \
2143 .put = snd_hdspm_put_dolby \
2144}
2145
2146static int hdspm_dolby(struct hdspm * hdspm)
2147{
2148 return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0;
2149}
2150
2151static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
2152{
2153 if (dol)
2154 hdspm->control_register |= HDSPM_Dolby;
2155 else
2156 hdspm->control_register &= ~HDSPM_Dolby;
2157 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2158
2159 return 0;
2160}
2161
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002162#define snd_hdspm_info_dolby snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02002163
2164static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
2165 struct snd_ctl_elem_value *ucontrol)
2166{
2167 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2168
2169 spin_lock_irq(&hdspm->lock);
2170 ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm);
2171 spin_unlock_irq(&hdspm->lock);
2172 return 0;
2173}
2174
2175static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
2176 struct snd_ctl_elem_value *ucontrol)
2177{
2178 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2179 int change;
2180 unsigned int val;
2181
2182 if (!snd_hdspm_use_is_exclusive(hdspm))
2183 return -EBUSY;
2184 val = ucontrol->value.integer.value[0] & 1;
2185 spin_lock_irq(&hdspm->lock);
2186 change = (int) val != hdspm_dolby(hdspm);
2187 hdspm_set_dolby(hdspm, val);
2188 spin_unlock_irq(&hdspm->lock);
2189 return change;
2190}
2191
2192#define HDSPM_PROFESSIONAL(xname, xindex) \
2193{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2194 .name = xname, \
2195 .index = xindex, \
2196 .info = snd_hdspm_info_professional, \
2197 .get = snd_hdspm_get_professional, \
2198 .put = snd_hdspm_put_professional \
2199}
2200
2201static int hdspm_professional(struct hdspm * hdspm)
2202{
2203 return (hdspm->control_register & HDSPM_Professional) ? 1 : 0;
2204}
2205
2206static int hdspm_set_professional(struct hdspm * hdspm, int dol)
2207{
2208 if (dol)
2209 hdspm->control_register |= HDSPM_Professional;
2210 else
2211 hdspm->control_register &= ~HDSPM_Professional;
2212 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2213
2214 return 0;
2215}
2216
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002217#define snd_hdspm_info_professional snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02002218
2219static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
2220 struct snd_ctl_elem_value *ucontrol)
2221{
2222 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2223
2224 spin_lock_irq(&hdspm->lock);
2225 ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm);
2226 spin_unlock_irq(&hdspm->lock);
2227 return 0;
2228}
2229
2230static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
2231 struct snd_ctl_elem_value *ucontrol)
2232{
2233 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2234 int change;
2235 unsigned int val;
2236
2237 if (!snd_hdspm_use_is_exclusive(hdspm))
2238 return -EBUSY;
2239 val = ucontrol->value.integer.value[0] & 1;
2240 spin_lock_irq(&hdspm->lock);
2241 change = (int) val != hdspm_professional(hdspm);
2242 hdspm_set_professional(hdspm, val);
2243 spin_unlock_irq(&hdspm->lock);
2244 return change;
2245}
2246
Takashi Iwai763f3562005-06-03 11:25:34 +02002247#define HDSPM_INPUT_SELECT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002248{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002249 .name = xname, \
2250 .index = xindex, \
2251 .info = snd_hdspm_info_input_select, \
2252 .get = snd_hdspm_get_input_select, \
2253 .put = snd_hdspm_put_input_select \
2254}
2255
Takashi Iwai98274f02005-11-17 14:52:34 +01002256static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002257{
2258 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
2259}
2260
Takashi Iwai98274f02005-11-17 14:52:34 +01002261static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002262{
2263 if (out)
2264 hdspm->control_register |= HDSPM_InputSelect0;
2265 else
2266 hdspm->control_register &= ~HDSPM_InputSelect0;
2267 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2268
2269 return 0;
2270}
2271
Takashi Iwai98274f02005-11-17 14:52:34 +01002272static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
2273 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002274{
2275 static char *texts[] = { "optical", "coaxial" };
2276
2277 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2278 uinfo->count = 1;
2279 uinfo->value.enumerated.items = 2;
2280
2281 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2282 uinfo->value.enumerated.item =
2283 uinfo->value.enumerated.items - 1;
2284 strcpy(uinfo->value.enumerated.name,
2285 texts[uinfo->value.enumerated.item]);
2286
2287 return 0;
2288}
2289
Takashi Iwai98274f02005-11-17 14:52:34 +01002290static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
2291 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002292{
Takashi Iwai98274f02005-11-17 14:52:34 +01002293 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002294
2295 spin_lock_irq(&hdspm->lock);
2296 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
2297 spin_unlock_irq(&hdspm->lock);
2298 return 0;
2299}
2300
Takashi Iwai98274f02005-11-17 14:52:34 +01002301static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
2302 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002303{
Takashi Iwai98274f02005-11-17 14:52:34 +01002304 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002305 int change;
2306 unsigned int val;
2307
2308 if (!snd_hdspm_use_is_exclusive(hdspm))
2309 return -EBUSY;
2310 val = ucontrol->value.integer.value[0] & 1;
2311 spin_lock_irq(&hdspm->lock);
2312 change = (int) val != hdspm_input_select(hdspm);
2313 hdspm_set_input_select(hdspm, val);
2314 spin_unlock_irq(&hdspm->lock);
2315 return change;
2316}
2317
Remy Bruno3cee5a62006-10-16 12:46:32 +02002318#define HDSPM_DS_WIRE(xname, xindex) \
2319{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2320 .name = xname, \
2321 .index = xindex, \
2322 .info = snd_hdspm_info_ds_wire, \
2323 .get = snd_hdspm_get_ds_wire, \
2324 .put = snd_hdspm_put_ds_wire \
2325}
2326
2327static int hdspm_ds_wire(struct hdspm * hdspm)
2328{
2329 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
2330}
2331
2332static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
2333{
2334 if (ds)
2335 hdspm->control_register |= HDSPM_DS_DoubleWire;
2336 else
2337 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
2338 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2339
2340 return 0;
2341}
2342
2343static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
2344 struct snd_ctl_elem_info *uinfo)
2345{
2346 static char *texts[] = { "Single", "Double" };
2347
2348 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2349 uinfo->count = 1;
2350 uinfo->value.enumerated.items = 2;
2351
2352 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2353 uinfo->value.enumerated.item =
2354 uinfo->value.enumerated.items - 1;
2355 strcpy(uinfo->value.enumerated.name,
2356 texts[uinfo->value.enumerated.item]);
2357
2358 return 0;
2359}
2360
2361static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
2362 struct snd_ctl_elem_value *ucontrol)
2363{
2364 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2365
2366 spin_lock_irq(&hdspm->lock);
2367 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
2368 spin_unlock_irq(&hdspm->lock);
2369 return 0;
2370}
2371
2372static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
2373 struct snd_ctl_elem_value *ucontrol)
2374{
2375 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2376 int change;
2377 unsigned int val;
2378
2379 if (!snd_hdspm_use_is_exclusive(hdspm))
2380 return -EBUSY;
2381 val = ucontrol->value.integer.value[0] & 1;
2382 spin_lock_irq(&hdspm->lock);
2383 change = (int) val != hdspm_ds_wire(hdspm);
2384 hdspm_set_ds_wire(hdspm, val);
2385 spin_unlock_irq(&hdspm->lock);
2386 return change;
2387}
2388
2389#define HDSPM_QS_WIRE(xname, xindex) \
2390{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2391 .name = xname, \
2392 .index = xindex, \
2393 .info = snd_hdspm_info_qs_wire, \
2394 .get = snd_hdspm_get_qs_wire, \
2395 .put = snd_hdspm_put_qs_wire \
2396}
2397
2398static int hdspm_qs_wire(struct hdspm * hdspm)
2399{
2400 if (hdspm->control_register & HDSPM_QS_DoubleWire)
2401 return 1;
2402 if (hdspm->control_register & HDSPM_QS_QuadWire)
2403 return 2;
2404 return 0;
2405}
2406
2407static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
2408{
2409 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
2410 switch (mode) {
2411 case 0:
2412 break;
2413 case 1:
2414 hdspm->control_register |= HDSPM_QS_DoubleWire;
2415 break;
2416 case 2:
2417 hdspm->control_register |= HDSPM_QS_QuadWire;
2418 break;
2419 }
2420 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2421
2422 return 0;
2423}
2424
2425static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
2426 struct snd_ctl_elem_info *uinfo)
2427{
2428 static char *texts[] = { "Single", "Double", "Quad" };
2429
2430 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2431 uinfo->count = 1;
2432 uinfo->value.enumerated.items = 3;
2433
2434 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2435 uinfo->value.enumerated.item =
2436 uinfo->value.enumerated.items - 1;
2437 strcpy(uinfo->value.enumerated.name,
2438 texts[uinfo->value.enumerated.item]);
2439
2440 return 0;
2441}
2442
2443static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
2444 struct snd_ctl_elem_value *ucontrol)
2445{
2446 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2447
2448 spin_lock_irq(&hdspm->lock);
2449 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
2450 spin_unlock_irq(&hdspm->lock);
2451 return 0;
2452}
2453
2454static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
2455 struct snd_ctl_elem_value *ucontrol)
2456{
2457 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2458 int change;
2459 int val;
2460
2461 if (!snd_hdspm_use_is_exclusive(hdspm))
2462 return -EBUSY;
2463 val = ucontrol->value.integer.value[0];
2464 if (val < 0)
2465 val = 0;
2466 if (val > 2)
2467 val = 2;
2468 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002469 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002470 hdspm_set_qs_wire(hdspm, val);
2471 spin_unlock_irq(&hdspm->lock);
2472 return change;
2473}
2474
Takashi Iwai763f3562005-06-03 11:25:34 +02002475/* Simple Mixer
2476 deprecated since to much faders ???
2477 MIXER interface says output (source, destination, value)
2478 where source > MAX_channels are playback channels
2479 on MADICARD
2480 - playback mixer matrix: [channelout+64] [output] [value]
2481 - input(thru) mixer matrix: [channelin] [output] [value]
Daniel Mack3ad2f3f2010-02-03 08:01:28 +08002482 (better do 2 kontrols for separation ?)
Takashi Iwai763f3562005-06-03 11:25:34 +02002483*/
2484
2485#define HDSPM_MIXER(xname, xindex) \
2486{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
2487 .name = xname, \
2488 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002489 .device = 0, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002490 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2491 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2492 .info = snd_hdspm_info_mixer, \
2493 .get = snd_hdspm_get_mixer, \
2494 .put = snd_hdspm_put_mixer \
2495}
2496
Takashi Iwai98274f02005-11-17 14:52:34 +01002497static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
2498 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002499{
2500 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2501 uinfo->count = 3;
2502 uinfo->value.integer.min = 0;
2503 uinfo->value.integer.max = 65535;
2504 uinfo->value.integer.step = 1;
2505 return 0;
2506}
2507
Takashi Iwai98274f02005-11-17 14:52:34 +01002508static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
2509 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002510{
Takashi Iwai98274f02005-11-17 14:52:34 +01002511 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002512 int source;
2513 int destination;
2514
2515 source = ucontrol->value.integer.value[0];
2516 if (source < 0)
2517 source = 0;
2518 else if (source >= 2 * HDSPM_MAX_CHANNELS)
2519 source = 2 * HDSPM_MAX_CHANNELS - 1;
2520
2521 destination = ucontrol->value.integer.value[1];
2522 if (destination < 0)
2523 destination = 0;
2524 else if (destination >= HDSPM_MAX_CHANNELS)
2525 destination = HDSPM_MAX_CHANNELS - 1;
2526
2527 spin_lock_irq(&hdspm->lock);
2528 if (source >= HDSPM_MAX_CHANNELS)
2529 ucontrol->value.integer.value[2] =
2530 hdspm_read_pb_gain(hdspm, destination,
2531 source - HDSPM_MAX_CHANNELS);
2532 else
2533 ucontrol->value.integer.value[2] =
2534 hdspm_read_in_gain(hdspm, destination, source);
2535
2536 spin_unlock_irq(&hdspm->lock);
2537
2538 return 0;
2539}
2540
Takashi Iwai98274f02005-11-17 14:52:34 +01002541static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
2542 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002543{
Takashi Iwai98274f02005-11-17 14:52:34 +01002544 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002545 int change;
2546 int source;
2547 int destination;
2548 int gain;
2549
2550 if (!snd_hdspm_use_is_exclusive(hdspm))
2551 return -EBUSY;
2552
2553 source = ucontrol->value.integer.value[0];
2554 destination = ucontrol->value.integer.value[1];
2555
2556 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
2557 return -1;
2558 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
2559 return -1;
2560
2561 gain = ucontrol->value.integer.value[2];
2562
2563 spin_lock_irq(&hdspm->lock);
2564
2565 if (source >= HDSPM_MAX_CHANNELS)
2566 change = gain != hdspm_read_pb_gain(hdspm, destination,
2567 source -
2568 HDSPM_MAX_CHANNELS);
2569 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002570 change = gain != hdspm_read_in_gain(hdspm, destination,
2571 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02002572
2573 if (change) {
2574 if (source >= HDSPM_MAX_CHANNELS)
2575 hdspm_write_pb_gain(hdspm, destination,
2576 source - HDSPM_MAX_CHANNELS,
2577 gain);
2578 else
2579 hdspm_write_in_gain(hdspm, destination, source,
2580 gain);
2581 }
2582 spin_unlock_irq(&hdspm->lock);
2583
2584 return change;
2585}
2586
2587/* The simple mixer control(s) provide gain control for the
2588 basic 1:1 mappings of playback streams to output
2589 streams.
2590*/
2591
2592#define HDSPM_PLAYBACK_MIXER \
2593{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2594 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
2595 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2596 .info = snd_hdspm_info_playback_mixer, \
2597 .get = snd_hdspm_get_playback_mixer, \
2598 .put = snd_hdspm_put_playback_mixer \
2599}
2600
Takashi Iwai98274f02005-11-17 14:52:34 +01002601static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
2602 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002603{
2604 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2605 uinfo->count = 1;
2606 uinfo->value.integer.min = 0;
2607 uinfo->value.integer.max = 65536;
2608 uinfo->value.integer.step = 1;
2609 return 0;
2610}
2611
Takashi Iwai98274f02005-11-17 14:52:34 +01002612static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
2613 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002614{
Takashi Iwai98274f02005-11-17 14:52:34 +01002615 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002616 int channel;
2617 int mapped_channel;
2618
2619 channel = ucontrol->id.index - 1;
2620
Takashi Iwaida3cec32008-08-08 17:12:14 +02002621 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
2622 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02002623
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002624 mapped_channel = hdspm->channel_map[channel];
2625 if (mapped_channel < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02002626 return -EINVAL;
2627
2628 spin_lock_irq(&hdspm->lock);
2629 ucontrol->value.integer.value[0] =
2630 hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel);
2631 spin_unlock_irq(&hdspm->lock);
2632
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002633 /*
2634 snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, "
2635 "value %d\n",
2636 ucontrol->id.index, channel, mapped_channel,
2637 ucontrol->value.integer.value[0]);
2638 */
Takashi Iwai763f3562005-06-03 11:25:34 +02002639 return 0;
2640}
2641
Takashi Iwai98274f02005-11-17 14:52:34 +01002642static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
2643 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002644{
Takashi Iwai98274f02005-11-17 14:52:34 +01002645 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002646 int change;
2647 int channel;
2648 int mapped_channel;
2649 int gain;
2650
2651 if (!snd_hdspm_use_is_exclusive(hdspm))
2652 return -EBUSY;
2653
2654 channel = ucontrol->id.index - 1;
2655
Takashi Iwaida3cec32008-08-08 17:12:14 +02002656 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
2657 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02002658
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002659 mapped_channel = hdspm->channel_map[channel];
2660 if (mapped_channel < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02002661 return -EINVAL;
2662
2663 gain = ucontrol->value.integer.value[0];
2664
2665 spin_lock_irq(&hdspm->lock);
2666 change =
2667 gain != hdspm_read_pb_gain(hdspm, mapped_channel,
2668 mapped_channel);
2669 if (change)
2670 hdspm_write_pb_gain(hdspm, mapped_channel, mapped_channel,
2671 gain);
2672 spin_unlock_irq(&hdspm->lock);
2673 return change;
2674}
2675
2676#define HDSPM_WC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002677{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002678 .name = xname, \
2679 .index = xindex, \
2680 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2681 .info = snd_hdspm_info_sync_check, \
2682 .get = snd_hdspm_get_wc_sync_check \
2683}
2684
Takashi Iwai98274f02005-11-17 14:52:34 +01002685static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
2686 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002687{
2688 static char *texts[] = { "No Lock", "Lock", "Sync" };
2689 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2690 uinfo->count = 1;
2691 uinfo->value.enumerated.items = 3;
2692 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2693 uinfo->value.enumerated.item =
2694 uinfo->value.enumerated.items - 1;
2695 strcpy(uinfo->value.enumerated.name,
2696 texts[uinfo->value.enumerated.item]);
2697 return 0;
2698}
2699
Takashi Iwai98274f02005-11-17 14:52:34 +01002700static int hdspm_wc_sync_check(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002701{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002702 if (hdspm->is_aes32) {
2703 int status = hdspm_read(hdspm, HDSPM_statusRegister);
2704 if (status & HDSPM_AES32_wcLock) {
2705 /* I don't know how to differenciate sync from lock.
2706 Doing as if sync for now */
Takashi Iwai763f3562005-06-03 11:25:34 +02002707 return 2;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002708 }
2709 return 0;
2710 } else {
2711 int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
2712 if (status2 & HDSPM_wcLock) {
2713 if (status2 & HDSPM_wcSync)
2714 return 2;
2715 else
2716 return 1;
2717 }
2718 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002719 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002720}
2721
Takashi Iwai98274f02005-11-17 14:52:34 +01002722static int snd_hdspm_get_wc_sync_check(struct snd_kcontrol *kcontrol,
2723 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002724{
Takashi Iwai98274f02005-11-17 14:52:34 +01002725 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002726
2727 ucontrol->value.enumerated.item[0] = hdspm_wc_sync_check(hdspm);
2728 return 0;
2729}
2730
2731
2732#define HDSPM_MADI_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002733{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002734 .name = xname, \
2735 .index = xindex, \
2736 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2737 .info = snd_hdspm_info_sync_check, \
2738 .get = snd_hdspm_get_madisync_sync_check \
2739}
2740
Takashi Iwai98274f02005-11-17 14:52:34 +01002741static int hdspm_madisync_sync_check(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002742{
2743 int status = hdspm_read(hdspm, HDSPM_statusRegister);
2744 if (status & HDSPM_madiLock) {
2745 if (status & HDSPM_madiSync)
2746 return 2;
2747 else
2748 return 1;
2749 }
2750 return 0;
2751}
2752
Takashi Iwai98274f02005-11-17 14:52:34 +01002753static int snd_hdspm_get_madisync_sync_check(struct snd_kcontrol *kcontrol,
2754 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002755 ucontrol)
2756{
Takashi Iwai98274f02005-11-17 14:52:34 +01002757 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002758
2759 ucontrol->value.enumerated.item[0] =
2760 hdspm_madisync_sync_check(hdspm);
2761 return 0;
2762}
2763
2764
Remy Bruno3cee5a62006-10-16 12:46:32 +02002765#define HDSPM_AES_SYNC_CHECK(xname, xindex) \
2766{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2767 .name = xname, \
2768 .index = xindex, \
2769 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2770 .info = snd_hdspm_info_sync_check, \
2771 .get = snd_hdspm_get_aes_sync_check \
2772}
2773
2774static int hdspm_aes_sync_check(struct hdspm * hdspm, int idx)
2775{
2776 int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
2777 if (status2 & (HDSPM_LockAES >> idx)) {
2778 /* I don't know how to differenciate sync from lock.
2779 Doing as if sync for now */
2780 return 2;
2781 }
2782 return 0;
2783}
2784
2785static int snd_hdspm_get_aes_sync_check(struct snd_kcontrol *kcontrol,
2786 struct snd_ctl_elem_value *ucontrol)
2787{
2788 int offset;
2789 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2790
2791 offset = ucontrol->id.index - 1;
2792 if (offset < 0 || offset >= 8)
2793 return -EINVAL;
2794
2795 ucontrol->value.enumerated.item[0] =
2796 hdspm_aes_sync_check(hdspm, offset);
2797 return 0;
2798}
Takashi Iwai763f3562005-06-03 11:25:34 +02002799
2800
Remy Bruno3cee5a62006-10-16 12:46:32 +02002801static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02002802
2803 HDSPM_MIXER("Mixer", 0),
2804/* 'Sample Clock Source' complies with the alsa control naming scheme */
2805 HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
2806
2807 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
2808 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
2809 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
2810 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
2811/* 'External Rate' complies with the alsa control naming scheme */
2812 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
2813 HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
2814 HDSPM_MADI_SYNC_CHECK("MADI Sync Lock Status", 0),
2815 HDSPM_LINE_OUT("Line Out", 0),
2816 HDSPM_TX_64("TX 64 channels mode", 0),
2817 HDSPM_C_TMS("Clear Track Marker", 0),
2818 HDSPM_SAFE_MODE("Safe Mode", 0),
2819 HDSPM_INPUT_SELECT("Input Select", 0),
2820};
2821
Remy Bruno3cee5a62006-10-16 12:46:32 +02002822static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
2823
2824 HDSPM_MIXER("Mixer", 0),
2825/* 'Sample Clock Source' complies with the alsa control naming scheme */
2826 HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
2827
2828 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
2829 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
2830 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
2831 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
2832/* 'External Rate' complies with the alsa control naming scheme */
2833 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
2834 HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
2835/* HDSPM_AES_SYNC_CHECK("AES Lock Status", 0),*/ /* created in snd_hdspm_create_controls() */
2836 HDSPM_LINE_OUT("Line Out", 0),
2837 HDSPM_EMPHASIS("Emphasis", 0),
2838 HDSPM_DOLBY("Non Audio", 0),
2839 HDSPM_PROFESSIONAL("Professional", 0),
2840 HDSPM_C_TMS("Clear Track Marker", 0),
2841 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
2842 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
2843};
2844
Takashi Iwai98274f02005-11-17 14:52:34 +01002845static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02002846
2847
Takashi Iwai98274f02005-11-17 14:52:34 +01002848static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002849{
2850 int i;
2851
2852 for (i = hdspm->ds_channels; i < hdspm->ss_channels; ++i) {
2853 if (hdspm->system_sample_rate > 48000) {
2854 hdspm->playback_mixer_ctls[i]->vd[0].access =
2855 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
2856 SNDRV_CTL_ELEM_ACCESS_READ |
2857 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
2858 } else {
2859 hdspm->playback_mixer_ctls[i]->vd[0].access =
2860 SNDRV_CTL_ELEM_ACCESS_READWRITE |
2861 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
2862 }
2863 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
2864 SNDRV_CTL_EVENT_MASK_INFO,
2865 &hdspm->playback_mixer_ctls[i]->id);
2866 }
2867
2868 return 0;
2869}
2870
2871
Takashi Iwai98274f02005-11-17 14:52:34 +01002872static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002873{
2874 unsigned int idx, limit;
2875 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01002876 struct snd_kcontrol *kctl;
Takashi Iwai763f3562005-06-03 11:25:34 +02002877
2878 /* add control list first */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002879 if (hdspm->is_aes32) {
2880 struct snd_kcontrol_new aes_sync_ctl =
2881 HDSPM_AES_SYNC_CHECK("AES Lock Status", 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02002882
Remy Bruno3cee5a62006-10-16 12:46:32 +02002883 for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_aes32);
2884 idx++) {
2885 err = snd_ctl_add(card,
2886 snd_ctl_new1(&snd_hdspm_controls_aes32[idx],
2887 hdspm));
2888 if (err < 0)
2889 return err;
2890 }
2891 for (idx = 1; idx <= 8; idx++) {
2892 aes_sync_ctl.index = idx;
2893 err = snd_ctl_add(card,
2894 snd_ctl_new1(&aes_sync_ctl, hdspm));
2895 if (err < 0)
2896 return err;
2897 }
2898 } else {
2899 for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_madi);
2900 idx++) {
2901 err = snd_ctl_add(card,
2902 snd_ctl_new1(&snd_hdspm_controls_madi[idx],
2903 hdspm));
2904 if (err < 0)
2905 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02002906 }
2907 }
2908
2909 /* Channel playback mixer as default control
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002910 Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders,
Uwe Kleine-Königb5950762010-11-01 15:38:34 -04002911 thats too * big for any alsamixer they are accessible via special
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002912 IOCTL on hwdep and the mixer 2dimensional mixer control
2913 */
Takashi Iwai763f3562005-06-03 11:25:34 +02002914
2915 snd_hdspm_playback_mixer.name = "Chn";
2916 limit = HDSPM_MAX_CHANNELS;
2917
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002918 /* The index values are one greater than the channel ID so that
2919 * alsamixer will display them correctly. We want to use the index
2920 * for fast lookup of the relevant channel, but if we use it at all,
2921 * most ALSA software does the wrong thing with it ...
Takashi Iwai763f3562005-06-03 11:25:34 +02002922 */
2923
2924 for (idx = 0; idx < limit; ++idx) {
2925 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002926 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
2927 err = snd_ctl_add(card, kctl);
2928 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02002929 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02002930 hdspm->playback_mixer_ctls[idx] = kctl;
2931 }
2932
2933 return 0;
2934}
2935
2936/*------------------------------------------------------------
2937 /proc interface
2938 ------------------------------------------------------------*/
2939
2940static void
Remy Bruno3cee5a62006-10-16 12:46:32 +02002941snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
2942 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02002943{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002944 struct hdspm *hdspm = entry->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02002945 unsigned int status;
2946 unsigned int status2;
2947 char *pref_sync_ref;
2948 char *autosync_ref;
2949 char *system_clock_mode;
2950 char *clock_source;
2951 char *insel;
2952 char *syncref;
2953 int x, x2;
2954
2955 status = hdspm_read(hdspm, HDSPM_statusRegister);
2956 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
2957
2958 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
2959 hdspm->card_name, hdspm->card->number + 1,
2960 hdspm->firmware_rev,
2961 (status2 & HDSPM_version0) |
2962 (status2 & HDSPM_version1) | (status2 &
2963 HDSPM_version2));
2964
2965 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
2966 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
2967
2968 snd_iprintf(buffer, "--- System ---\n");
2969
2970 snd_iprintf(buffer,
2971 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
2972 status & HDSPM_audioIRQPending,
2973 (status & HDSPM_midi0IRQPending) ? 1 : 0,
2974 (status & HDSPM_midi1IRQPending) ? 1 : 0,
2975 hdspm->irq_count);
2976 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002977 "HW pointer: id = %d, rawptr = %d (%d->%d) "
2978 "estimated= %ld (bytes)\n",
Takashi Iwai763f3562005-06-03 11:25:34 +02002979 ((status & HDSPM_BufferID) ? 1 : 0),
2980 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002981 (status & HDSPM_BufferPositionMask) %
2982 (2 * (int)hdspm->period_bytes),
2983 ((status & HDSPM_BufferPositionMask) - 64) %
2984 (2 * (int)hdspm->period_bytes),
Takashi Iwai763f3562005-06-03 11:25:34 +02002985 (long) hdspm_hw_pointer(hdspm) * 4);
2986
2987 snd_iprintf(buffer,
2988 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
2989 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
2990 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
2991 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
2992 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
2993 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002994 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
2995 "status2=0x%x\n",
Takashi Iwai763f3562005-06-03 11:25:34 +02002996 hdspm->control_register, hdspm->control2_register,
2997 status, status2);
2998
2999 snd_iprintf(buffer, "--- Settings ---\n");
3000
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003001 x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
3002 HDSPM_LatencyMask));
Takashi Iwai763f3562005-06-03 11:25:34 +02003003
3004 snd_iprintf(buffer,
3005 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
3006 x, (unsigned long) hdspm->period_bytes);
3007
3008 snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003009 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off",
Takashi Iwai763f3562005-06-03 11:25:34 +02003010 (hdspm->precise_ptr) ? "on" : "off");
3011
3012 switch (hdspm->control_register & HDSPM_InputMask) {
3013 case HDSPM_InputOptical:
3014 insel = "Optical";
3015 break;
3016 case HDSPM_InputCoaxial:
3017 insel = "Coaxial";
3018 break;
3019 default:
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02003020 insel = "Unknown";
Takashi Iwai763f3562005-06-03 11:25:34 +02003021 }
3022
3023 switch (hdspm->control_register & HDSPM_SyncRefMask) {
3024 case HDSPM_SyncRef_Word:
3025 syncref = "WordClock";
3026 break;
3027 case HDSPM_SyncRef_MADI:
3028 syncref = "MADI";
3029 break;
3030 default:
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02003031 syncref = "Unknown";
Takashi Iwai763f3562005-06-03 11:25:34 +02003032 }
3033 snd_iprintf(buffer, "Inputsel = %s, SyncRef = %s\n", insel,
3034 syncref);
3035
3036 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003037 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
3038 "Auto Input %s\n",
Takashi Iwai763f3562005-06-03 11:25:34 +02003039 (hdspm->
3040 control_register & HDSPM_clr_tms) ? "on" : "off",
3041 (hdspm->
3042 control_register & HDSPM_TX_64ch) ? "64" : "56",
3043 (hdspm->
3044 control_register & HDSPM_AutoInp) ? "on" : "off");
3045
3046 switch (hdspm_clock_source(hdspm)) {
3047 case HDSPM_CLOCK_SOURCE_AUTOSYNC:
3048 clock_source = "AutoSync";
3049 break;
3050 case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
3051 clock_source = "Internal 32 kHz";
3052 break;
3053 case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
3054 clock_source = "Internal 44.1 kHz";
3055 break;
3056 case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
3057 clock_source = "Internal 48 kHz";
3058 break;
3059 case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
3060 clock_source = "Internal 64 kHz";
3061 break;
3062 case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
3063 clock_source = "Internal 88.2 kHz";
3064 break;
3065 case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
3066 clock_source = "Internal 96 kHz";
3067 break;
3068 default:
3069 clock_source = "Error";
3070 }
3071 snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003072 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Takashi Iwai763f3562005-06-03 11:25:34 +02003073 system_clock_mode = "Slave";
Remy Bruno3cee5a62006-10-16 12:46:32 +02003074 else
Takashi Iwai763f3562005-06-03 11:25:34 +02003075 system_clock_mode = "Master";
Takashi Iwai763f3562005-06-03 11:25:34 +02003076 snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
3077
3078 switch (hdspm_pref_sync_ref(hdspm)) {
3079 case HDSPM_SYNC_FROM_WORD:
3080 pref_sync_ref = "Word Clock";
3081 break;
3082 case HDSPM_SYNC_FROM_MADI:
3083 pref_sync_ref = "MADI Sync";
3084 break;
3085 default:
3086 pref_sync_ref = "XXXX Clock";
3087 break;
3088 }
3089 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
3090 pref_sync_ref);
3091
3092 snd_iprintf(buffer, "System Clock Frequency: %d\n",
3093 hdspm->system_sample_rate);
3094
3095
3096 snd_iprintf(buffer, "--- Status:\n");
3097
3098 x = status & HDSPM_madiSync;
3099 x2 = status2 & HDSPM_wcSync;
3100
3101 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
3102 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
3103 "NoLock",
3104 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
3105 "NoLock");
3106
3107 switch (hdspm_autosync_ref(hdspm)) {
3108 case HDSPM_AUTOSYNC_FROM_WORD:
3109 autosync_ref = "Word Clock";
3110 break;
3111 case HDSPM_AUTOSYNC_FROM_MADI:
3112 autosync_ref = "MADI Sync";
3113 break;
3114 case HDSPM_AUTOSYNC_FROM_NONE:
3115 autosync_ref = "Input not valid";
3116 break;
3117 default:
3118 autosync_ref = "---";
3119 break;
3120 }
3121 snd_iprintf(buffer,
3122 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
3123 autosync_ref, hdspm_external_sample_rate(hdspm),
3124 (status & HDSPM_madiFreqMask) >> 22,
3125 (status2 & HDSPM_wcFreqMask) >> 5);
3126
3127 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
3128 (status & HDSPM_AB_int) ? "Coax" : "Optical",
3129 (status & HDSPM_RX_64ch) ? "64 channels" :
3130 "56 channels");
3131
3132 snd_iprintf(buffer, "\n");
3133}
3134
Remy Bruno3cee5a62006-10-16 12:46:32 +02003135static void
3136snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
3137 struct snd_info_buffer *buffer)
3138{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003139 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003140 unsigned int status;
3141 unsigned int status2;
3142 unsigned int timecode;
3143 int pref_syncref;
3144 char *autosync_ref;
3145 char *system_clock_mode;
3146 char *clock_source;
3147 int x;
3148
3149 status = hdspm_read(hdspm, HDSPM_statusRegister);
3150 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3151 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
3152
3153 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
3154 hdspm->card_name, hdspm->card->number + 1,
3155 hdspm->firmware_rev);
3156
3157 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
3158 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
3159
3160 snd_iprintf(buffer, "--- System ---\n");
3161
3162 snd_iprintf(buffer,
3163 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
3164 status & HDSPM_audioIRQPending,
3165 (status & HDSPM_midi0IRQPending) ? 1 : 0,
3166 (status & HDSPM_midi1IRQPending) ? 1 : 0,
3167 hdspm->irq_count);
3168 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003169 "HW pointer: id = %d, rawptr = %d (%d->%d) "
3170 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02003171 ((status & HDSPM_BufferID) ? 1 : 0),
3172 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003173 (status & HDSPM_BufferPositionMask) %
3174 (2 * (int)hdspm->period_bytes),
3175 ((status & HDSPM_BufferPositionMask) - 64) %
3176 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02003177 (long) hdspm_hw_pointer(hdspm) * 4);
3178
3179 snd_iprintf(buffer,
3180 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
3181 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
3182 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
3183 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
3184 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
3185 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003186 "Register: ctrl1=0x%x, status1=0x%x, status2=0x%x, "
3187 "timecode=0x%x\n",
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003188 hdspm->control_register,
Remy Bruno3cee5a62006-10-16 12:46:32 +02003189 status, status2, timecode);
3190
3191 snd_iprintf(buffer, "--- Settings ---\n");
3192
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003193 x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
3194 HDSPM_LatencyMask));
Remy Bruno3cee5a62006-10-16 12:46:32 +02003195
3196 snd_iprintf(buffer,
3197 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
3198 x, (unsigned long) hdspm->period_bytes);
3199
3200 snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n",
3201 (hdspm->
3202 control_register & HDSPM_LineOut) ? "on " : "off",
3203 (hdspm->precise_ptr) ? "on" : "off");
3204
3205 snd_iprintf(buffer,
3206 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
3207 (hdspm->
3208 control_register & HDSPM_clr_tms) ? "on" : "off",
3209 (hdspm->
3210 control_register & HDSPM_Emphasis) ? "on" : "off",
3211 (hdspm->
3212 control_register & HDSPM_Dolby) ? "on" : "off");
3213
3214 switch (hdspm_clock_source(hdspm)) {
3215 case HDSPM_CLOCK_SOURCE_AUTOSYNC:
3216 clock_source = "AutoSync";
3217 break;
3218 case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
3219 clock_source = "Internal 32 kHz";
3220 break;
3221 case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
3222 clock_source = "Internal 44.1 kHz";
3223 break;
3224 case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
3225 clock_source = "Internal 48 kHz";
3226 break;
3227 case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
3228 clock_source = "Internal 64 kHz";
3229 break;
3230 case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
3231 clock_source = "Internal 88.2 kHz";
3232 break;
3233 case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
3234 clock_source = "Internal 96 kHz";
3235 break;
3236 case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
3237 clock_source = "Internal 128 kHz";
3238 break;
3239 case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
3240 clock_source = "Internal 176.4 kHz";
3241 break;
3242 case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
3243 clock_source = "Internal 192 kHz";
3244 break;
3245 default:
3246 clock_source = "Error";
3247 }
3248 snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
3249 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
3250 system_clock_mode = "Slave";
3251 else
3252 system_clock_mode = "Master";
3253 snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
3254
3255 pref_syncref = hdspm_pref_sync_ref(hdspm);
3256 if (pref_syncref == 0)
3257 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
3258 else
3259 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
3260 pref_syncref);
3261
3262 snd_iprintf(buffer, "System Clock Frequency: %d\n",
3263 hdspm->system_sample_rate);
3264
3265 snd_iprintf(buffer, "Double speed: %s\n",
3266 hdspm->control_register & HDSPM_DS_DoubleWire?
3267 "Double wire" : "Single wire");
3268 snd_iprintf(buffer, "Quad speed: %s\n",
3269 hdspm->control_register & HDSPM_QS_DoubleWire?
3270 "Double wire" :
3271 hdspm->control_register & HDSPM_QS_QuadWire?
3272 "Quad wire" : "Single wire");
3273
3274 snd_iprintf(buffer, "--- Status:\n");
3275
3276 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003277 (status & HDSPM_AES32_wcLock)? "Sync " : "No Lock",
3278 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02003279
3280 for (x = 0; x < 8; x++) {
3281 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003282 x+1,
3283 (status2 & (HDSPM_LockAES >> x)) ?
3284 "Sync ": "No Lock",
3285 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02003286 }
3287
3288 switch (hdspm_autosync_ref(hdspm)) {
3289 case HDSPM_AES32_AUTOSYNC_FROM_NONE: autosync_ref="None"; break;
3290 case HDSPM_AES32_AUTOSYNC_FROM_WORD: autosync_ref="Word Clock"; break;
3291 case HDSPM_AES32_AUTOSYNC_FROM_AES1: autosync_ref="AES1"; break;
3292 case HDSPM_AES32_AUTOSYNC_FROM_AES2: autosync_ref="AES2"; break;
3293 case HDSPM_AES32_AUTOSYNC_FROM_AES3: autosync_ref="AES3"; break;
3294 case HDSPM_AES32_AUTOSYNC_FROM_AES4: autosync_ref="AES4"; break;
3295 case HDSPM_AES32_AUTOSYNC_FROM_AES5: autosync_ref="AES5"; break;
3296 case HDSPM_AES32_AUTOSYNC_FROM_AES6: autosync_ref="AES6"; break;
3297 case HDSPM_AES32_AUTOSYNC_FROM_AES7: autosync_ref="AES7"; break;
3298 case HDSPM_AES32_AUTOSYNC_FROM_AES8: autosync_ref="AES8"; break;
3299 default: autosync_ref = "---"; break;
3300 }
3301 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
3302
3303 snd_iprintf(buffer, "\n");
3304}
3305
3306#ifdef CONFIG_SND_DEBUG
3307static void
3308snd_hdspm_proc_read_debug(struct snd_info_entry * entry,
3309 struct snd_info_buffer *buffer)
3310{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003311 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003312
3313 int j,i;
3314
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003315 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02003316 snd_iprintf(buffer, "0x%08X: ", i);
3317 for (j = 0; j < 16; j += 4)
3318 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
3319 snd_iprintf(buffer, "\n");
3320 }
3321}
3322#endif
3323
3324
3325
Takashi Iwai98274f02005-11-17 14:52:34 +01003326static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003327{
Takashi Iwai98274f02005-11-17 14:52:34 +01003328 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02003329
3330 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry))
Takashi Iwaibf850202006-04-28 15:13:41 +02003331 snd_info_set_text_ops(entry, hdspm,
Remy Bruno3cee5a62006-10-16 12:46:32 +02003332 hdspm->is_aes32 ?
3333 snd_hdspm_proc_read_aes32 :
3334 snd_hdspm_proc_read_madi);
3335#ifdef CONFIG_SND_DEBUG
3336 /* debug file to read all hdspm registers */
3337 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
3338 snd_info_set_text_ops(entry, hdspm,
3339 snd_hdspm_proc_read_debug);
3340#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02003341}
3342
3343/*------------------------------------------------------------
3344 hdspm intitialize
3345 ------------------------------------------------------------*/
3346
Takashi Iwai98274f02005-11-17 14:52:34 +01003347static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003348{
3349 unsigned int i;
3350
3351 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01003352 hold it (e.g. during module initialization).
Takashi Iwai763f3562005-06-03 11:25:34 +02003353 */
3354
3355 /* set defaults: */
3356
Remy Bruno3cee5a62006-10-16 12:46:32 +02003357 if (hdspm->is_aes32)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003358 hdspm->control_register =
3359 HDSPM_ClockModeMaster | /* Master Cloack Mode on */
3360 hdspm_encode_latency(7) | /* latency maximum =
3361 * 8192 samples
3362 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02003363 HDSPM_SyncRef0 | /* AES1 is syncclock */
3364 HDSPM_LineOut | /* Analog output in */
3365 HDSPM_Professional; /* Professional mode */
3366 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003367 hdspm->control_register =
3368 HDSPM_ClockModeMaster | /* Master Cloack Mode on */
3369 hdspm_encode_latency(7) | /* latency maximum =
3370 * 8192 samples
3371 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02003372 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
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003402 snd_printk(KERN_INFO "HDSPM: "
3403 "sending all playback streams to line outs.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02003404
3405 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) {
3406 if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN))
3407 return -EIO;
3408 }
3409 }
3410
3411 /* set a default rate so that the channel map is set up. */
3412 hdspm->channel_map = channel_map_madi_ss;
3413 hdspm_set_rate(hdspm, 44100, 1);
3414
3415 return 0;
3416}
3417
3418
3419/*------------------------------------------------------------
Joe Perches561de312007-12-18 13:13:47 +01003420 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02003421 ------------------------------------------------------------*/
3422
David Howells7d12e782006-10-05 14:55:46 +01003423static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02003424{
Takashi Iwai98274f02005-11-17 14:52:34 +01003425 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02003426 unsigned int status;
3427 int audio;
3428 int midi0;
3429 int midi1;
3430 unsigned int midi0status;
3431 unsigned int midi1status;
3432 int schedule = 0;
3433
3434 status = hdspm_read(hdspm, HDSPM_statusRegister);
3435
3436 audio = status & HDSPM_audioIRQPending;
3437 midi0 = status & HDSPM_midi0IRQPending;
3438 midi1 = status & HDSPM_midi1IRQPending;
3439
3440 if (!audio && !midi0 && !midi1)
3441 return IRQ_NONE;
3442
3443 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
3444 hdspm->irq_count++;
3445
3446 midi0status = hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff;
3447 midi1status = hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff;
3448
3449 if (audio) {
3450
3451 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003452 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003453
3454 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003455 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003456 }
3457
3458 if (midi0 && midi0status) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003459 /* we disable interrupts for this input until processing
3460 * is done
3461 */
Takashi Iwai763f3562005-06-03 11:25:34 +02003462 hdspm->control_register &= ~HDSPM_Midi0InterruptEnable;
3463 hdspm_write(hdspm, HDSPM_controlRegister,
3464 hdspm->control_register);
3465 hdspm->midi[0].pending = 1;
3466 schedule = 1;
3467 }
3468 if (midi1 && midi1status) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003469 /* we disable interrupts for this input until processing
3470 * is done
3471 */
Takashi Iwai763f3562005-06-03 11:25:34 +02003472 hdspm->control_register &= ~HDSPM_Midi1InterruptEnable;
3473 hdspm_write(hdspm, HDSPM_controlRegister,
3474 hdspm->control_register);
3475 hdspm->midi[1].pending = 1;
3476 schedule = 1;
3477 }
3478 if (schedule)
Takashi Iwai1f041282008-12-18 12:17:55 +01003479 tasklet_schedule(&hdspm->midi_tasklet);
Takashi Iwai763f3562005-06-03 11:25:34 +02003480 return IRQ_HANDLED;
3481}
3482
3483/*------------------------------------------------------------
3484 pcm interface
3485 ------------------------------------------------------------*/
3486
3487
Takashi Iwai98274f02005-11-17 14:52:34 +01003488static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream *
Takashi Iwai763f3562005-06-03 11:25:34 +02003489 substream)
3490{
Takashi Iwai98274f02005-11-17 14:52:34 +01003491 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003492 return hdspm_hw_pointer(hdspm);
3493}
3494
Takashi Iwai98274f02005-11-17 14:52:34 +01003495static char *hdspm_channel_buffer_location(struct hdspm * hdspm,
Takashi Iwai763f3562005-06-03 11:25:34 +02003496 int stream, int channel)
3497{
3498 int mapped_channel;
3499
Takashi Iwaida3cec32008-08-08 17:12:14 +02003500 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3501 return NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003502
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003503 mapped_channel = hdspm->channel_map[channel];
3504 if (mapped_channel < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02003505 return NULL;
3506
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003507 if (stream == SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02003508 return hdspm->capture_buffer +
3509 mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003510 else
Takashi Iwai763f3562005-06-03 11:25:34 +02003511 return hdspm->playback_buffer +
3512 mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02003513}
3514
3515
3516/* dont know why need it ??? */
Takashi Iwai98274f02005-11-17 14:52:34 +01003517static int snd_hdspm_playback_copy(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02003518 int channel, snd_pcm_uframes_t pos,
3519 void __user *src, snd_pcm_uframes_t count)
3520{
Takashi Iwai98274f02005-11-17 14:52:34 +01003521 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003522 char *channel_buf;
3523
Takashi Iwaida3cec32008-08-08 17:12:14 +02003524 if (snd_BUG_ON(pos + count > HDSPM_CHANNEL_BUFFER_BYTES / 4))
3525 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003526
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003527 channel_buf =
3528 hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
3529 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003530
Takashi Iwaida3cec32008-08-08 17:12:14 +02003531 if (snd_BUG_ON(!channel_buf))
3532 return -EIO;
Takashi Iwai763f3562005-06-03 11:25:34 +02003533
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
Takashi Iwaida3cec32008-08-08 17:12:14 +02003544 if (snd_BUG_ON(pos + count > HDSPM_CHANNEL_BUFFER_BYTES / 4))
3545 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003546
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003547 channel_buf =
3548 hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
3549 channel);
Takashi Iwaida3cec32008-08-08 17:12:14 +02003550 if (snd_BUG_ON(!channel_buf))
3551 return -EIO;
Takashi Iwai763f3562005-06-03 11:25:34 +02003552 return copy_to_user(dst, channel_buf + pos * 4, count * 4);
3553}
3554
Takashi Iwai98274f02005-11-17 14:52:34 +01003555static int snd_hdspm_hw_silence(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02003556 int channel, snd_pcm_uframes_t pos,
3557 snd_pcm_uframes_t count)
3558{
Takashi Iwai98274f02005-11-17 14:52:34 +01003559 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003560 char *channel_buf;
3561
3562 channel_buf =
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003563 hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
3564 channel);
Takashi Iwaida3cec32008-08-08 17:12:14 +02003565 if (snd_BUG_ON(!channel_buf))
3566 return -EIO;
Takashi Iwai763f3562005-06-03 11:25:34 +02003567 memset(channel_buf + pos * 4, 0, count * 4);
3568 return 0;
3569}
3570
Takashi Iwai98274f02005-11-17 14:52:34 +01003571static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003572{
Takashi Iwai98274f02005-11-17 14:52:34 +01003573 struct snd_pcm_runtime *runtime = substream->runtime;
3574 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
3575 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02003576
3577 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3578 other = hdspm->capture_substream;
3579 else
3580 other = hdspm->playback_substream;
3581
3582 if (hdspm->running)
3583 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
3584 else
3585 runtime->status->hw_ptr = 0;
3586 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003587 struct snd_pcm_substream *s;
3588 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01003589 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02003590 if (s == other) {
3591 oruntime->status->hw_ptr =
3592 runtime->status->hw_ptr;
3593 break;
3594 }
3595 }
3596 }
3597 return 0;
3598}
3599
Takashi Iwai98274f02005-11-17 14:52:34 +01003600static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
3601 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02003602{
Takashi Iwai98274f02005-11-17 14:52:34 +01003603 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003604 int err;
3605 int i;
3606 pid_t this_pid;
3607 pid_t other_pid;
Takashi Iwai763f3562005-06-03 11:25:34 +02003608
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
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003619 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02003620
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,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003636 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02003637 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);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003647 err = hdspm_set_rate(hdspm, params_rate(params), 0);
3648 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02003649 spin_unlock_irq(&hdspm->lock);
3650 _snd_pcm_hw_param_setempty(params,
3651 SNDRV_PCM_HW_PARAM_RATE);
3652 return err;
3653 }
3654 spin_unlock_irq(&hdspm->lock);
3655
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003656 err = hdspm_set_interrupt_interval(hdspm,
3657 params_period_size(params));
3658 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02003659 _snd_pcm_hw_param_setempty(params,
3660 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
3661 return err;
3662 }
3663
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003664 /* Memory allocation, takashi's method, dont know if we should
3665 * spinlock
3666 */
Takashi Iwai763f3562005-06-03 11:25:34 +02003667 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003668 /* Update for MADI rev 204: we need to allocate for all channels,
3669 * otherwise it doesn't work at 96kHz */
Takashi Iwai763f3562005-06-03 11:25:34 +02003670 err =
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003671 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
Takashi Iwai763f3562005-06-03 11:25:34 +02003672 if (err < 0)
3673 return err;
3674
Takashi Iwai763f3562005-06-03 11:25:34 +02003675 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3676
Takashi Iwai77a23f22008-08-21 13:00:13 +02003677 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut,
Takashi Iwai763f3562005-06-03 11:25:34 +02003678 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 {
Takashi Iwai77a23f22008-08-21 13:00:13 +02003688 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn,
Takashi Iwai763f3562005-06-03 11:25:34 +02003689 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",
Takashi Iwai77a23f22008-08-21 13:00:13 +02003703 snd_pcm_sgbuf_get_addr(substream, 0));
Remy Bruno3cee5a62006-10-16 12:46:32 +02003704 */
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
Takashi Iwaida3cec32008-08-08 17:12:14 +02003747 if (snd_BUG_ON(info->channel >= HDSPM_MAX_CHANNELS))
3748 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003749
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003750 mapped_channel = hdspm->channel_map[info->channel];
3751 if (mapped_channel < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02003752 return -EINVAL;
3753
3754 info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
3755 info->first = 0;
3756 info->step = 32;
3757 return 0;
3758}
3759
Takashi Iwai98274f02005-11-17 14:52:34 +01003760static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02003761 unsigned int cmd, void *arg)
3762{
3763 switch (cmd) {
3764 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003765 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003766
3767 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003768 {
3769 struct snd_pcm_channel_info *info = arg;
3770 return snd_hdspm_channel_info(substream, info);
3771 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003772 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
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003982static unsigned int hdspm_aes32_sample_rates[] = {
3983 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
3984};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003985
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003986static struct snd_pcm_hw_constraint_list
3987hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003988 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
3989 .list = hdspm_aes32_sample_rates,
3990 .mask = 0
3991};
3992
Takashi Iwai98274f02005-11-17 14:52:34 +01003993static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003994{
Takashi Iwai98274f02005-11-17 14:52:34 +01003995 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
3996 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02003997
Takashi Iwai763f3562005-06-03 11:25:34 +02003998 spin_lock_irq(&hdspm->lock);
3999
4000 snd_pcm_set_sync(substream);
4001
4002 runtime->hw = snd_hdspm_playback_subinfo;
4003
4004 if (hdspm->capture_substream == NULL)
4005 hdspm_stop_audio(hdspm);
4006
4007 hdspm->playback_pid = current->pid;
4008 hdspm->playback_substream = substream;
4009
4010 spin_unlock_irq(&hdspm->lock);
4011
4012 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4013
4014 snd_pcm_hw_constraint_list(runtime, 0,
4015 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
4016 &hw_constraints_period_sizes);
4017
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004018 if (hdspm->is_aes32) {
4019 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4020 &hdspm_hw_constraints_aes32_sample_rates);
4021 } else {
4022 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4023 snd_hdspm_hw_rule_channels, hdspm,
4024 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4025 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4026 snd_hdspm_hw_rule_channels_rate, hdspm,
4027 SNDRV_PCM_HW_PARAM_RATE, -1);
Takashi Iwai763f3562005-06-03 11:25:34 +02004028
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004029 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4030 snd_hdspm_hw_rule_rate_channels, hdspm,
4031 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4032 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004033 return 0;
4034}
4035
Takashi Iwai98274f02005-11-17 14:52:34 +01004036static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02004037{
Takashi Iwai98274f02005-11-17 14:52:34 +01004038 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02004039
4040 spin_lock_irq(&hdspm->lock);
4041
4042 hdspm->playback_pid = -1;
4043 hdspm->playback_substream = NULL;
4044
4045 spin_unlock_irq(&hdspm->lock);
4046
4047 return 0;
4048}
4049
4050
Takashi Iwai98274f02005-11-17 14:52:34 +01004051static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02004052{
Takashi Iwai98274f02005-11-17 14:52:34 +01004053 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
4054 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02004055
4056 spin_lock_irq(&hdspm->lock);
4057 snd_pcm_set_sync(substream);
4058 runtime->hw = snd_hdspm_capture_subinfo;
4059
4060 if (hdspm->playback_substream == NULL)
4061 hdspm_stop_audio(hdspm);
4062
4063 hdspm->capture_pid = current->pid;
4064 hdspm->capture_substream = substream;
4065
4066 spin_unlock_irq(&hdspm->lock);
4067
4068 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4069 snd_pcm_hw_constraint_list(runtime, 0,
4070 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
4071 &hw_constraints_period_sizes);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004072 if (hdspm->is_aes32) {
4073 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4074 &hdspm_hw_constraints_aes32_sample_rates);
4075 } else {
4076 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4077 snd_hdspm_hw_rule_channels, hdspm,
4078 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4079 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4080 snd_hdspm_hw_rule_channels_rate, hdspm,
4081 SNDRV_PCM_HW_PARAM_RATE, -1);
Takashi Iwai763f3562005-06-03 11:25:34 +02004082
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004083 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4084 snd_hdspm_hw_rule_rate_channels, hdspm,
4085 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4086 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004087 return 0;
4088}
4089
Takashi Iwai98274f02005-11-17 14:52:34 +01004090static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02004091{
Takashi Iwai98274f02005-11-17 14:52:34 +01004092 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02004093
4094 spin_lock_irq(&hdspm->lock);
4095
4096 hdspm->capture_pid = -1;
4097 hdspm->capture_substream = NULL;
4098
4099 spin_unlock_irq(&hdspm->lock);
4100 return 0;
4101}
4102
Takashi Iwai98274f02005-11-17 14:52:34 +01004103static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
Takashi Iwai763f3562005-06-03 11:25:34 +02004104 unsigned int cmd, unsigned long arg)
4105{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004106 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01004107 struct hdspm_mixer_ioctl mixer;
4108 struct hdspm_config_info info;
4109 struct hdspm_version hdspm_version;
4110 struct hdspm_peak_rms_ioctl rms;
Takashi Iwai763f3562005-06-03 11:25:34 +02004111
4112 switch (cmd) {
4113
Takashi Iwai763f3562005-06-03 11:25:34 +02004114 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
4115 if (copy_from_user(&rms, (void __user *)arg, sizeof(rms)))
4116 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004117 /* maybe there is a chance to memorymap in future
4118 * so dont touch just copy
4119 */
Takashi Iwai763f3562005-06-03 11:25:34 +02004120 if(copy_to_user_fromio((void __user *)rms.peak,
4121 hdspm->iobase+HDSPM_MADI_peakrmsbase,
Takashi Iwai98274f02005-11-17 14:52:34 +01004122 sizeof(struct hdspm_peak_rms)) != 0 )
Takashi Iwai763f3562005-06-03 11:25:34 +02004123 return -EFAULT;
4124
4125 break;
4126
4127
4128 case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO:
4129
Dan Rosenberge68d3b32010-09-25 11:07:27 -04004130 memset(&info, 0, sizeof(info));
Takashi Iwai763f3562005-06-03 11:25:34 +02004131 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004132 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
4133 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02004134
4135 info.system_sample_rate = hdspm->system_sample_rate;
4136 info.autosync_sample_rate =
4137 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004138 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
4139 info.clock_source = hdspm_clock_source(hdspm);
4140 info.autosync_ref = hdspm_autosync_ref(hdspm);
4141 info.line_out = hdspm_line_out(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02004142 info.passthru = 0;
4143 spin_unlock_irq(&hdspm->lock);
4144 if (copy_to_user((void __user *) arg, &info, sizeof(info)))
4145 return -EFAULT;
4146 break;
4147
4148 case SNDRV_HDSPM_IOCTL_GET_VERSION:
4149 hdspm_version.firmware_rev = hdspm->firmware_rev;
4150 if (copy_to_user((void __user *) arg, &hdspm_version,
4151 sizeof(hdspm_version)))
4152 return -EFAULT;
4153 break;
4154
4155 case SNDRV_HDSPM_IOCTL_GET_MIXER:
4156 if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
4157 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004158 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
4159 sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02004160 return -EFAULT;
4161 break;
4162
4163 default:
4164 return -EINVAL;
4165 }
4166 return 0;
4167}
4168
Takashi Iwai98274f02005-11-17 14:52:34 +01004169static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004170 .open = snd_hdspm_playback_open,
4171 .close = snd_hdspm_playback_release,
4172 .ioctl = snd_hdspm_ioctl,
4173 .hw_params = snd_hdspm_hw_params,
4174 .hw_free = snd_hdspm_hw_free,
4175 .prepare = snd_hdspm_prepare,
4176 .trigger = snd_hdspm_trigger,
4177 .pointer = snd_hdspm_hw_pointer,
4178 .copy = snd_hdspm_playback_copy,
4179 .silence = snd_hdspm_hw_silence,
4180 .page = snd_pcm_sgbuf_ops_page,
4181};
4182
Takashi Iwai98274f02005-11-17 14:52:34 +01004183static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004184 .open = snd_hdspm_capture_open,
4185 .close = snd_hdspm_capture_release,
4186 .ioctl = snd_hdspm_ioctl,
4187 .hw_params = snd_hdspm_hw_params,
4188 .hw_free = snd_hdspm_hw_free,
4189 .prepare = snd_hdspm_prepare,
4190 .trigger = snd_hdspm_trigger,
4191 .pointer = snd_hdspm_hw_pointer,
4192 .copy = snd_hdspm_capture_copy,
4193 .page = snd_pcm_sgbuf_ops_page,
4194};
4195
Takashi Iwai98274f02005-11-17 14:52:34 +01004196static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
4197 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004198{
Takashi Iwai98274f02005-11-17 14:52:34 +01004199 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02004200 int err;
4201
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004202 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
4203 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004204 return err;
4205
4206 hdspm->hwdep = hw;
4207 hw->private_data = hdspm;
4208 strcpy(hw->name, "HDSPM hwdep interface");
4209
Takashi Iwai763f3562005-06-03 11:25:34 +02004210 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
Takashi Iwai763f3562005-06-03 11:25:34 +02004211
4212 return 0;
4213}
4214
4215
4216/*------------------------------------------------------------
4217 memory interface
4218 ------------------------------------------------------------*/
Takashi Iwai98274f02005-11-17 14:52:34 +01004219static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004220{
4221 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004222 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02004223 size_t wanted;
4224
4225 pcm = hdspm->pcm;
4226
Remy Bruno3cee5a62006-10-16 12:46:32 +02004227 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02004228
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004229 err =
Takashi Iwai763f3562005-06-03 11:25:34 +02004230 snd_pcm_lib_preallocate_pages_for_all(pcm,
4231 SNDRV_DMA_TYPE_DEV_SG,
4232 snd_dma_pci_data(hdspm->pci),
4233 wanted,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004234 wanted);
4235 if (err < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01004236 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02004237
4238 return err;
4239 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01004240 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02004241
4242 return 0;
4243}
4244
Takashi Iwai77a23f22008-08-21 13:00:13 +02004245static void hdspm_set_sgbuf(struct hdspm * hdspm,
4246 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02004247 unsigned int reg, int channels)
4248{
4249 int i;
4250 for (i = 0; i < (channels * 16); i++)
4251 hdspm_write(hdspm, reg + 4 * i,
Takashi Iwai77a23f22008-08-21 13:00:13 +02004252 snd_pcm_sgbuf_get_addr(substream, 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02004253}
4254
4255/* ------------- ALSA Devices ---------------------------- */
Takashi Iwai98274f02005-11-17 14:52:34 +01004256static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
4257 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004258{
Takashi Iwai98274f02005-11-17 14:52:34 +01004259 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02004260 int err;
4261
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004262 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
4263 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004264 return err;
4265
4266 hdspm->pcm = pcm;
4267 pcm->private_data = hdspm;
4268 strcpy(pcm->name, hdspm->card_name);
4269
4270 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
4271 &snd_hdspm_playback_ops);
4272 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
4273 &snd_hdspm_capture_ops);
4274
4275 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
4276
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004277 err = snd_hdspm_preallocate_memory(hdspm);
4278 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004279 return err;
4280
4281 return 0;
4282}
4283
Takashi Iwai98274f02005-11-17 14:52:34 +01004284static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004285{
4286 snd_hdspm_flush_midi_input(hdspm, 0);
4287 snd_hdspm_flush_midi_input(hdspm, 1);
4288}
4289
Takashi Iwai98274f02005-11-17 14:52:34 +01004290static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
4291 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004292{
4293 int err;
4294
4295 snd_printdd("Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004296 err = snd_hdspm_create_pcm(card, hdspm);
4297 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004298 return err;
4299
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004300 err = snd_hdspm_create_midi(card, hdspm, 0);
4301 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004302 return err;
4303
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004304 err = snd_hdspm_create_midi(card, hdspm, 1);
4305 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004306 return err;
4307
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004308 err = snd_hdspm_create_controls(card, hdspm);
4309 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004310 return err;
4311
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004312 err = snd_hdspm_create_hwdep(card, hdspm);
4313 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004314 return err;
4315
4316 snd_printdd("proc init...\n");
4317 snd_hdspm_proc_init(hdspm);
4318
4319 hdspm->system_sample_rate = -1;
4320 hdspm->last_external_sample_rate = -1;
4321 hdspm->last_internal_sample_rate = -1;
4322 hdspm->playback_pid = -1;
4323 hdspm->capture_pid = -1;
4324 hdspm->capture_substream = NULL;
4325 hdspm->playback_substream = NULL;
4326
4327 snd_printdd("Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004328 err = snd_hdspm_set_defaults(hdspm);
4329 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004330 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
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004337 err = snd_card_register(card);
4338 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004339 snd_printk(KERN_ERR "HDSPM: error registering card\n");
4340 return err;
4341 }
4342
4343 snd_printdd("... yes now\n");
4344
4345 return 0;
4346}
4347
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004348static int __devinit snd_hdspm_create(struct snd_card *card,
4349 struct hdspm *hdspm,
Takashi Iwai763f3562005-06-03 11:25:34 +02004350 int precise_ptr, int enable_monitor)
4351{
4352 struct pci_dev *pci = hdspm->pci;
4353 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004354 unsigned long io_extent;
4355
4356 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02004357
Takashi Iwai763f3562005-06-03 11:25:34 +02004358 spin_lock_init(&hdspm->midi[0].lock);
4359 spin_lock_init(&hdspm->midi[1].lock);
Takashi Iwai763f3562005-06-03 11:25:34 +02004360
4361 hdspm->card = card;
4362
4363 spin_lock_init(&hdspm->lock);
4364
4365 tasklet_init(&hdspm->midi_tasklet,
4366 hdspm_midi_tasklet, (unsigned long) hdspm);
4367
4368 pci_read_config_word(hdspm->pci,
4369 PCI_CLASS_REVISION, &hdspm->firmware_rev);
4370
Remy Bruno3cee5a62006-10-16 12:46:32 +02004371 hdspm->is_aes32 = (hdspm->firmware_rev >= HDSPM_AESREVISION);
4372
Takashi Iwai763f3562005-06-03 11:25:34 +02004373 strcpy(card->mixername, "Xilinx FPGA");
Remy Bruno3cee5a62006-10-16 12:46:32 +02004374 if (hdspm->is_aes32) {
4375 strcpy(card->driver, "HDSPAES32");
4376 hdspm->card_name = "RME HDSPM AES32";
4377 } else {
4378 strcpy(card->driver, "HDSPM");
4379 hdspm->card_name = "RME HDSPM MADI";
4380 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004381
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004382 err = pci_enable_device(pci);
4383 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004384 return err;
4385
4386 pci_set_master(hdspm->pci);
4387
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004388 err = pci_request_regions(pci, "hdspm");
4389 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004390 return err;
4391
4392 hdspm->port = pci_resource_start(pci, 0);
4393 io_extent = pci_resource_len(pci, 0);
4394
4395 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
4396 hdspm->port, hdspm->port + io_extent - 1);
4397
4398
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004399 hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
4400 if (!hdspm->iobase) {
4401 snd_printk(KERN_ERR "HDSPM: "
4402 "unable to remap region 0x%lx-0x%lx\n",
Takashi Iwai763f3562005-06-03 11:25:34 +02004403 hdspm->port, hdspm->port + io_extent - 1);
4404 return -EBUSY;
4405 }
4406 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
4407 (unsigned long)hdspm->iobase, hdspm->port,
4408 hdspm->port + io_extent - 1);
4409
4410 if (request_irq(pci->irq, snd_hdspm_interrupt,
Takashi Iwai437a5a42006-11-21 12:14:23 +01004411 IRQF_SHARED, "hdspm", hdspm)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004412 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
4413 return -EBUSY;
4414 }
4415
4416 snd_printdd("use IRQ %d\n", pci->irq);
4417
4418 hdspm->irq = pci->irq;
4419 hdspm->precise_ptr = precise_ptr;
4420
4421 hdspm->monitor_outs = enable_monitor;
4422
Andrew Mortone2eba3e2006-01-20 14:07:13 +01004423 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Takashi Iwai98274f02005-11-17 14:52:34 +01004424 sizeof(struct hdspm_mixer));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004425 hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
4426 if (!hdspm->mixer) {
4427 snd_printk(KERN_ERR "HDSPM: "
4428 "unable to kmalloc Mixer memory of %d Bytes\n",
Takashi Iwai98274f02005-11-17 14:52:34 +01004429 (int)sizeof(struct hdspm_mixer));
Takashi Iwai763f3562005-06-03 11:25:34 +02004430 return err;
4431 }
4432
4433 hdspm->ss_channels = MADI_SS_CHANNELS;
4434 hdspm->ds_channels = MADI_DS_CHANNELS;
4435 hdspm->qs_channels = MADI_QS_CHANNELS;
4436
4437 snd_printdd("create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004438 err = snd_hdspm_create_alsa_devices(card, hdspm);
4439 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004440 return err;
4441
4442 snd_hdspm_initialize_midi_flush(hdspm);
4443
4444 return 0;
4445}
4446
Takashi Iwai98274f02005-11-17 14:52:34 +01004447static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004448{
4449
4450 if (hdspm->port) {
4451
4452 /* stop th audio, and cancel all interrupts */
4453 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004454 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
4455 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02004456 hdspm_write(hdspm, HDSPM_controlRegister,
4457 hdspm->control_register);
4458 }
4459
4460 if (hdspm->irq >= 0)
4461 free_irq(hdspm->irq, (void *) hdspm);
4462
Jesper Juhlfc584222005-10-24 15:11:28 +02004463 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02004464
4465 if (hdspm->iobase)
4466 iounmap(hdspm->iobase);
4467
Takashi Iwai763f3562005-06-03 11:25:34 +02004468 if (hdspm->port)
4469 pci_release_regions(hdspm->pci);
4470
4471 pci_disable_device(hdspm->pci);
4472 return 0;
4473}
4474
Takashi Iwai98274f02005-11-17 14:52:34 +01004475static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02004476{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004477 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02004478
4479 if (hdspm)
4480 snd_hdspm_free(hdspm);
4481}
4482
4483static int __devinit snd_hdspm_probe(struct pci_dev *pci,
4484 const struct pci_device_id *pci_id)
4485{
4486 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01004487 struct hdspm *hdspm;
4488 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02004489 int err;
4490
4491 if (dev >= SNDRV_CARDS)
4492 return -ENODEV;
4493 if (!enable[dev]) {
4494 dev++;
4495 return -ENOENT;
4496 }
4497
Takashi Iwaie58de7b2008-12-28 16:44:30 +01004498 err = snd_card_create(index[dev], id[dev],
4499 THIS_MODULE, sizeof(struct hdspm), &card);
4500 if (err < 0)
4501 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004502
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004503 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02004504 card->private_free = snd_hdspm_card_free;
4505 hdspm->dev = dev;
4506 hdspm->pci = pci;
4507
Takashi Iwaic187c042007-02-19 15:27:33 +01004508 snd_card_set_dev(card, &pci->dev);
4509
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004510 err = snd_hdspm_create(card, hdspm, precise_ptr[dev],
4511 enable_monitor[dev]);
4512 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004513 snd_card_free(card);
4514 return err;
4515 }
4516
4517 strcpy(card->shortname, "HDSPM MADI");
4518 sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name,
4519 hdspm->port, hdspm->irq);
4520
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004521 err = snd_card_register(card);
4522 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004523 snd_card_free(card);
4524 return err;
4525 }
4526
4527 pci_set_drvdata(pci, card);
4528
4529 dev++;
4530 return 0;
4531}
4532
4533static void __devexit snd_hdspm_remove(struct pci_dev *pci)
4534{
4535 snd_card_free(pci_get_drvdata(pci));
4536 pci_set_drvdata(pci, NULL);
4537}
4538
4539static struct pci_driver driver = {
4540 .name = "RME Hammerfall DSP MADI",
Takashi Iwai763f3562005-06-03 11:25:34 +02004541 .id_table = snd_hdspm_ids,
4542 .probe = snd_hdspm_probe,
4543 .remove = __devexit_p(snd_hdspm_remove),
4544};
4545
4546
4547static int __init alsa_card_hdspm_init(void)
4548{
4549 return pci_register_driver(&driver);
4550}
4551
4552static void __exit alsa_card_hdspm_exit(void)
4553{
4554 pci_unregister_driver(&driver);
4555}
4556
4557module_init(alsa_card_hdspm_init)
4558module_exit(alsa_card_hdspm_exit)