blob: ab423bc823425834c108a3f84d060094324970ea [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>
32#include <asm/io.h>
33
34#include <sound/core.h>
35#include <sound/control.h>
36#include <sound/pcm.h>
37#include <sound/info.h>
38#include <sound/asoundef.h>
39#include <sound/rawmidi.h>
40#include <sound/hwdep.h>
41#include <sound/initval.h>
42
43#include <sound/hdspm.h>
44
45static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
46static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
47static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
48
49/* Disable precise pointer at start */
50static int precise_ptr[SNDRV_CARDS];
51
52/* Send all playback to line outs */
53static int line_outs_monitor[SNDRV_CARDS];
54
55/* Enable Analog Outs on Channel 63/64 by default */
56static int enable_monitor[SNDRV_CARDS];
57
58module_param_array(index, int, NULL, 0444);
59MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
60
61module_param_array(id, charp, NULL, 0444);
62MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
63
64module_param_array(enable, bool, NULL, 0444);
65MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
66
67module_param_array(precise_ptr, bool, NULL, 0444);
Takashi Iwaie8da2fb2005-08-16 16:55:13 +020068MODULE_PARM_DESC(precise_ptr, "Enable or disable precise pointer.");
Takashi Iwai763f3562005-06-03 11:25:34 +020069
70module_param_array(line_outs_monitor, bool, NULL, 0444);
71MODULE_PARM_DESC(line_outs_monitor,
72 "Send playback streams to analog outs by default.");
73
74module_param_array(enable_monitor, bool, NULL, 0444);
75MODULE_PARM_DESC(enable_monitor,
76 "Enable Analog Out on Channel 63/64 by default.");
77
78MODULE_AUTHOR
Takashi Iwaief5fa1a2007-07-27 16:52:46 +020079 ("Winfried Ritsch <ritsch_AT_iem.at>, "
80 "Paul Davis <paul@linuxaudiosystems.com>, "
Remy Bruno3cee5a62006-10-16 12:46:32 +020081 "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
82 "Remy Bruno <remy.bruno@trinnov.com>");
Takashi Iwai763f3562005-06-03 11:25:34 +020083MODULE_DESCRIPTION("RME HDSPM");
84MODULE_LICENSE("GPL");
85MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
86
87/* --- Write registers. ---
88 These are defined as byte-offsets from the iobase value. */
89
90#define HDSPM_controlRegister 64
91#define HDSPM_interruptConfirmation 96
92#define HDSPM_control2Reg 256 /* not in specs ???????? */
Remy Brunoffb2c3c2007-03-07 19:08:46 +010093#define HDSPM_freqReg 256 /* for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +020094#define HDSPM_midiDataOut0 352 /* just believe in old code */
95#define HDSPM_midiDataOut1 356
Remy Brunoffb2c3c2007-03-07 19:08:46 +010096#define HDSPM_eeprom_wr 384 /* for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +020097
98/* DMA enable for 64 channels, only Bit 0 is relevant */
99#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */
100#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */
101
102/* 16 page addresses for each of the 64 channels DMA buffer in and out
103 (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
104#define HDSPM_pageAddressBufferOut 8192
105#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)
106
107#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */
108
109#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */
110
111/* --- Read registers. ---
112 These are defined as byte-offsets from the iobase value */
113#define HDSPM_statusRegister 0
Remy Bruno3cee5a62006-10-16 12:46:32 +0200114/*#define HDSPM_statusRegister2 96 */
115/* after RME Windows driver sources, status2 is 4-byte word # 48 = word at
116 * offset 192, for AES32 *and* MADI
117 * => need to check that offset 192 is working on MADI */
118#define HDSPM_statusRegister2 192
119#define HDSPM_timecodeRegister 128
Takashi Iwai763f3562005-06-03 11:25:34 +0200120
121#define HDSPM_midiDataIn0 360
122#define HDSPM_midiDataIn1 364
123
124/* status is data bytes in MIDI-FIFO (0-128) */
125#define HDSPM_midiStatusOut0 384
126#define HDSPM_midiStatusOut1 388
127#define HDSPM_midiStatusIn0 392
128#define HDSPM_midiStatusIn1 396
129
130
131/* the meters are regular i/o-mapped registers, but offset
132 considerably from the rest. the peak registers are reset
133 when read; the least-significant 4 bits are full-scale counters;
134 the actual peak value is in the most-significant 24 bits.
135*/
136#define HDSPM_MADI_peakrmsbase 4096 /* 4096-8191 2x64x32Bit Meters */
137
138/* --- Control Register bits --------- */
139#define HDSPM_Start (1<<0) /* start engine */
140
141#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */
142#define HDSPM_Latency1 (1<<2) /* where n is defined */
143#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */
144
145#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */
146
147#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
148
149#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
150#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
151#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200152#define HDSPM_QuadSpeed (1<<31) /* quad speed bit */
Takashi Iwai763f3562005-06-03 11:25:34 +0200153
Remy Bruno3cee5a62006-10-16 12:46:32 +0200154#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200155#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200156 56channelMODE=0 */ /* MADI ONLY*/
157#define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200158
159#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200160 0=off, 1=on */ /* MADI ONLY */
161#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200162
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200163#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax
164 * -- MADI ONLY
165 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200166#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
167
168#define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200169#define HDSPM_SyncRef1 (1<<17) /* for AES32: SyncRefN codes the AES # */
170#define HDSPM_SyncRef2 (1<<13)
171#define HDSPM_SyncRef3 (1<<25)
Takashi Iwai763f3562005-06-03 11:25:34 +0200172
Remy Bruno3cee5a62006-10-16 12:46:32 +0200173#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200174#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
175 AES additional bits in
176 lower 5 Audiodatabits ??? */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200177#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */
178#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200179
180#define HDSPM_Midi0InterruptEnable (1<<22)
181#define HDSPM_Midi1InterruptEnable (1<<23)
182
183#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
184
Remy Bruno3cee5a62006-10-16 12:46:32 +0200185#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
186#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
187#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */
188
189#define HDSPM_wclk_sel (1<<30)
Takashi Iwai763f3562005-06-03 11:25:34 +0200190
191/* --- bit helper defines */
192#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200193#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\
194 HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
Takashi Iwai763f3562005-06-03 11:25:34 +0200195#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
196#define HDSPM_InputOptical 0
197#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200198#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\
199 HDSPM_SyncRef2|HDSPM_SyncRef3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200200#define HDSPM_SyncRef_Word 0
201#define HDSPM_SyncRef_MADI (HDSPM_SyncRef0)
202
203#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
204#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
205
206#define HDSPM_Frequency32KHz HDSPM_Frequency0
207#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
208#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
209#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
210#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200211#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\
212 HDSPM_Frequency0)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200213#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)
214#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200215#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\
216 HDSPM_Frequency0)
Takashi Iwai763f3562005-06-03 11:25:34 +0200217
218/* --- for internal discrimination */
219#define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */
220#define HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ 1
221#define HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ 2
222#define HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ 3
223#define HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ 4
224#define HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ 5
225#define HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ 6
226#define HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ 7
227#define HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ 8
228#define HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ 9
229
230/* Synccheck Status */
231#define HDSPM_SYNC_CHECK_NO_LOCK 0
232#define HDSPM_SYNC_CHECK_LOCK 1
233#define HDSPM_SYNC_CHECK_SYNC 2
234
235/* AutoSync References - used by "autosync_ref" control switch */
236#define HDSPM_AUTOSYNC_FROM_WORD 0
237#define HDSPM_AUTOSYNC_FROM_MADI 1
238#define HDSPM_AUTOSYNC_FROM_NONE 2
239
240/* Possible sources of MADI input */
241#define HDSPM_OPTICAL 0 /* optical */
242#define HDSPM_COAXIAL 1 /* BNC */
243
244#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
245#define hdspm_decode_latency(x) (((x) & HDSPM_LatencyMask)>>1)
246
247#define hdspm_encode_in(x) (((x)&0x3)<<14)
248#define hdspm_decode_in(x) (((x)>>14)&0x3)
249
250/* --- control2 register bits --- */
251#define HDSPM_TMS (1<<0)
252#define HDSPM_TCK (1<<1)
253#define HDSPM_TDI (1<<2)
254#define HDSPM_JTAG (1<<3)
255#define HDSPM_PWDN (1<<4)
256#define HDSPM_PROGRAM (1<<5)
257#define HDSPM_CONFIG_MODE_0 (1<<6)
258#define HDSPM_CONFIG_MODE_1 (1<<7)
259/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
260#define HDSPM_BIGENDIAN_MODE (1<<9)
261#define HDSPM_RD_MULTIPLE (1<<10)
262
Remy Bruno3cee5a62006-10-16 12:46:32 +0200263/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200264 that do not conflict with specific bits for AES32 seem to be valid also
265 for the AES32
266 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200267#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200268#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */
269#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1
270 * (like inp0)
271 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200272#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
273
274#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
275 /* since 64byte accurate last 6 bits
276 are not used */
277
278#define HDSPM_madiSync (1<<18) /* MADI is in sync */
279#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
280
281#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
282#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
283#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
284#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
285
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200286#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with
287 * Interrupt
288 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200289#define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */
290#define HDSPM_midi1IRQPending (1<<31) /* and aktiv */
291
292/* --- status bit helpers */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200293#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\
294 HDSPM_madiFreq2|HDSPM_madiFreq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200295#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
296#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
297#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
298#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
299#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
300#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
301#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
302#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
303#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
304
Remy Bruno3cee5a62006-10-16 12:46:32 +0200305/* Status2 Register bits */ /* MADI ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200306
307#define HDSPM_version0 (1<<0) /* not realy defined but I guess */
308#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
309#define HDSPM_version2 (1<<2)
310
311#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */
312#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */
313
314#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */
315#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */
316#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */
317/* missing Bit for 111=128, 1000=176.4, 1001=192 */
318
319#define HDSPM_SelSyncRef0 (1<<8) /* Sync Source in slave mode */
320#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */
321#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */
322
323#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
324
325#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
326#define HDSPM_wcFreq32 (HDSPM_wc_freq0)
327#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)
328#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)
329#define HDSPM_wcFreq64 (HDSPM_wc_freq2)
330#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)
331#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
332
333
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200334#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
335 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200336#define HDSPM_SelSyncRef_WORD 0
337#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200338#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
339 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200340
Remy Bruno3cee5a62006-10-16 12:46:32 +0200341/*
342 For AES32, bits for status, status2 and timecode are different
343*/
344/* status */
345#define HDSPM_AES32_wcLock 0x0200000
346#define HDSPM_AES32_wcFreq_bit 22
347/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
348 HDSPM_bit2freq */
349#define HDSPM_AES32_syncref_bit 16
350/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
351
352#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
353#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
354#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
355#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
356#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
357#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
358#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
359#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
360#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
Remy Bruno65345992007-08-31 12:21:08 +0200361#define HDSPM_AES32_AUTOSYNC_FROM_NONE 9
Remy Bruno3cee5a62006-10-16 12:46:32 +0200362
363/* status2 */
364/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
365#define HDSPM_LockAES 0x80
366#define HDSPM_LockAES1 0x80
367#define HDSPM_LockAES2 0x40
368#define HDSPM_LockAES3 0x20
369#define HDSPM_LockAES4 0x10
370#define HDSPM_LockAES5 0x8
371#define HDSPM_LockAES6 0x4
372#define HDSPM_LockAES7 0x2
373#define HDSPM_LockAES8 0x1
374/*
375 Timecode
376 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
377 AES i+1
378 bits 3210
379 0001 32kHz
380 0010 44.1kHz
381 0011 48kHz
382 0100 64kHz
383 0101 88.2kHz
384 0110 96kHz
385 0111 128kHz
386 1000 176.4kHz
387 1001 192kHz
388 NB: Timecode register doesn't seem to work on AES32 card revision 230
389*/
390
Takashi Iwai763f3562005-06-03 11:25:34 +0200391/* Mixer Values */
392#define UNITY_GAIN 32768 /* = 65536/2 */
393#define MINUS_INFINITY_GAIN 0
394
Takashi Iwai763f3562005-06-03 11:25:34 +0200395/* Number of channels for different Speed Modes */
396#define MADI_SS_CHANNELS 64
397#define MADI_DS_CHANNELS 32
398#define MADI_QS_CHANNELS 16
399
400/* the size of a substream (1 mono data stream) */
401#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
402#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
403
404/* the size of the area we need to allocate for DMA transfers. the
405 size is the same regardless of the number of channels, and
406 also the latency to use.
407 for one direction !!!
408*/
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100409#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
Takashi Iwai763f3562005-06-03 11:25:34 +0200410#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
411
Remy Bruno3cee5a62006-10-16 12:46:32 +0200412/* revisions >= 230 indicate AES32 card */
413#define HDSPM_AESREVISION 230
414
Remy Bruno65345992007-08-31 12:21:08 +0200415/* speed factor modes */
416#define HDSPM_SPEED_SINGLE 0
417#define HDSPM_SPEED_DOUBLE 1
418#define HDSPM_SPEED_QUAD 2
419/* names for speed modes */
420static char *hdspm_speed_names[] = { "single", "double", "quad" };
421
Takashi Iwai98274f02005-11-17 14:52:34 +0100422struct hdspm_midi {
423 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200424 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100425 struct snd_rawmidi *rmidi;
426 struct snd_rawmidi_substream *input;
427 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200428 char istimer; /* timer in use */
429 struct timer_list timer;
430 spinlock_t lock;
431 int pending;
432};
433
Takashi Iwai98274f02005-11-17 14:52:34 +0100434struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200435 spinlock_t lock;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200436 /* only one playback and/or capture stream */
437 struct snd_pcm_substream *capture_substream;
438 struct snd_pcm_substream *playback_substream;
Takashi Iwai763f3562005-06-03 11:25:34 +0200439
440 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200441 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
442
443 unsigned char is_aes32; /* indicates if card is AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200444
445 int precise_ptr; /* use precise pointers, to be tested */
446 int monitor_outs; /* set up monitoring outs init flag */
447
448 u32 control_register; /* cached value */
449 u32 control2_register; /* cached value */
450
Takashi Iwai98274f02005-11-17 14:52:34 +0100451 struct hdspm_midi midi[2];
Takashi Iwai763f3562005-06-03 11:25:34 +0200452 struct tasklet_struct midi_tasklet;
453
454 size_t period_bytes;
455 unsigned char ss_channels; /* channels of card in single speed */
456 unsigned char ds_channels; /* Double Speed */
457 unsigned char qs_channels; /* Quad Speed */
458
459 unsigned char *playback_buffer; /* suitably aligned address */
460 unsigned char *capture_buffer; /* suitably aligned address */
461
462 pid_t capture_pid; /* process id which uses capture */
463 pid_t playback_pid; /* process id which uses capture */
464 int running; /* running status */
465
466 int last_external_sample_rate; /* samplerate mystic ... */
467 int last_internal_sample_rate;
468 int system_sample_rate;
469
470 char *channel_map; /* channel map for DS and Quadspeed */
471
472 int dev; /* Hardware vars... */
473 int irq;
474 unsigned long port;
475 void __iomem *iobase;
476
477 int irq_count; /* for debug */
478
Takashi Iwai98274f02005-11-17 14:52:34 +0100479 struct snd_card *card; /* one card */
480 struct snd_pcm *pcm; /* has one pcm */
481 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +0200482 struct pci_dev *pci; /* and an pci info */
483
484 /* Mixer vars */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200485 /* fast alsa mixer */
486 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
487 /* but input to much, so not used */
488 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
489 /* full mixer accessable over mixer ioctl or hwdep-device */
490 struct hdspm_mixer *mixer;
Takashi Iwai763f3562005-06-03 11:25:34 +0200491
492};
493
494/* These tables map the ALSA channels 1..N to the channels that we
495 need to use in order to find the relevant channel buffer. RME
496 refer to this kind of mapping as between "the ADAT channel and
497 the DMA channel." We index it using the logical audio channel,
498 and the value is the DMA channel (i.e. channel buffer number)
499 where the data for that channel can be read/written from/to.
500*/
501
502static char channel_map_madi_ss[HDSPM_MAX_CHANNELS] = {
503 0, 1, 2, 3, 4, 5, 6, 7,
504 8, 9, 10, 11, 12, 13, 14, 15,
505 16, 17, 18, 19, 20, 21, 22, 23,
506 24, 25, 26, 27, 28, 29, 30, 31,
507 32, 33, 34, 35, 36, 37, 38, 39,
508 40, 41, 42, 43, 44, 45, 46, 47,
509 48, 49, 50, 51, 52, 53, 54, 55,
510 56, 57, 58, 59, 60, 61, 62, 63
511};
512
Takashi Iwai763f3562005-06-03 11:25:34 +0200513
Henrik Kretzschmar396c9b92006-04-24 15:59:04 +0200514static struct pci_device_id snd_hdspm_ids[] __devinitdata = {
Takashi Iwai763f3562005-06-03 11:25:34 +0200515 {
516 .vendor = PCI_VENDOR_ID_XILINX,
517 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
518 .subvendor = PCI_ANY_ID,
519 .subdevice = PCI_ANY_ID,
520 .class = 0,
521 .class_mask = 0,
522 .driver_data = 0},
523 {0,}
524};
525
526MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
527
528/* prototypes */
Takashi Iwai98274f02005-11-17 14:52:34 +0100529static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
530 struct hdspm * hdspm);
531static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
532 struct hdspm * hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200533
Takashi Iwai98274f02005-11-17 14:52:34 +0100534static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm);
535static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm);
536static int hdspm_autosync_ref(struct hdspm * hdspm);
537static int snd_hdspm_set_defaults(struct hdspm * hdspm);
538static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
Takashi Iwai763f3562005-06-03 11:25:34 +0200539 unsigned int reg, int channels);
540
Remy Bruno3cee5a62006-10-16 12:46:32 +0200541static inline int HDSPM_bit2freq(int n)
542{
Denys Vlasenko62cef822008-04-14 13:04:18 +0200543 static const int bit2freq_tab[] = {
544 0, 32000, 44100, 48000, 64000, 88200,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200545 96000, 128000, 176400, 192000 };
546 if (n < 1 || n > 9)
547 return 0;
548 return bit2freq_tab[n];
549}
550
Takashi Iwai763f3562005-06-03 11:25:34 +0200551/* Write/read to/from HDSPM with Adresses in Bytes
552 not words but only 32Bit writes are allowed */
553
Takashi Iwai98274f02005-11-17 14:52:34 +0100554static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +0200555 unsigned int val)
556{
557 writel(val, hdspm->iobase + reg);
558}
559
Takashi Iwai98274f02005-11-17 14:52:34 +0100560static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +0200561{
562 return readl(hdspm->iobase + reg);
563}
564
565/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
566 mixer is write only on hardware so we have to cache him for read
567 each fader is a u32, but uses only the first 16 bit */
568
Takashi Iwai98274f02005-11-17 14:52:34 +0100569static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200570 unsigned int in)
571{
Adrian Bunk5bab24822006-03-13 14:15:04 +0100572 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +0200573 return 0;
574
575 return hdspm->mixer->ch[chan].in[in];
576}
577
Takashi Iwai98274f02005-11-17 14:52:34 +0100578static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200579 unsigned int pb)
580{
Adrian Bunk5bab24822006-03-13 14:15:04 +0100581 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +0200582 return 0;
583 return hdspm->mixer->ch[chan].pb[pb];
584}
585
Denys Vlasenko62cef822008-04-14 13:04:18 +0200586static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200587 unsigned int in, unsigned short data)
588{
589 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
590 return -1;
591
592 hdspm_write(hdspm,
593 HDSPM_MADI_mixerBase +
594 ((in + 128 * chan) * sizeof(u32)),
595 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
596 return 0;
597}
598
Denys Vlasenko62cef822008-04-14 13:04:18 +0200599static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200600 unsigned int pb, unsigned short data)
601{
602 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
603 return -1;
604
605 hdspm_write(hdspm,
606 HDSPM_MADI_mixerBase +
607 ((64 + pb + 128 * chan) * sizeof(u32)),
608 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
609 return 0;
610}
611
612
613/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +0100614static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +0200615{
616 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
617}
618
Takashi Iwai98274f02005-11-17 14:52:34 +0100619static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +0200620{
621 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
622}
623
624/* check if same process is writing and reading */
Denys Vlasenko62cef822008-04-14 13:04:18 +0200625static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200626{
627 unsigned long flags;
628 int ret = 1;
629
630 spin_lock_irqsave(&hdspm->lock, flags);
631 if ((hdspm->playback_pid != hdspm->capture_pid) &&
632 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
633 ret = 0;
634 }
635 spin_unlock_irqrestore(&hdspm->lock, flags);
636 return ret;
637}
638
639/* check for external sample rate */
Denys Vlasenko62cef822008-04-14 13:04:18 +0200640static int hdspm_external_sample_rate(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200641{
Remy Bruno3cee5a62006-10-16 12:46:32 +0200642 if (hdspm->is_aes32) {
643 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
644 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200645 unsigned int timecode =
646 hdspm_read(hdspm, HDSPM_timecodeRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +0200647
Remy Bruno3cee5a62006-10-16 12:46:32 +0200648 int syncref = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200649
Remy Bruno3cee5a62006-10-16 12:46:32 +0200650 if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
651 status & HDSPM_AES32_wcLock)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200652 return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit)
653 & 0xF);
Remy Bruno3cee5a62006-10-16 12:46:32 +0200654 if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
655 syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
656 status2 & (HDSPM_LockAES >>
657 (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
658 return HDSPM_bit2freq((timecode >>
659 (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
660 return 0;
661 } else {
662 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
663 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
664 unsigned int rate_bits;
665 int rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +0200666
Remy Bruno3cee5a62006-10-16 12:46:32 +0200667 /* if wordclock has synced freq and wordclock is valid */
668 if ((status2 & HDSPM_wcLock) != 0 &&
669 (status & HDSPM_SelSyncRef0) == 0) {
670
671 rate_bits = status2 & HDSPM_wcFreqMask;
672
673 switch (rate_bits) {
674 case HDSPM_wcFreq32:
675 rate = 32000;
676 break;
677 case HDSPM_wcFreq44_1:
678 rate = 44100;
679 break;
680 case HDSPM_wcFreq48:
681 rate = 48000;
682 break;
683 case HDSPM_wcFreq64:
684 rate = 64000;
685 break;
686 case HDSPM_wcFreq88_2:
687 rate = 88200;
688 break;
689 case HDSPM_wcFreq96:
690 rate = 96000;
691 break;
692 /* Quadspeed Bit missing ???? */
693 default:
694 rate = 0;
695 break;
696 }
Takashi Iwai763f3562005-06-03 11:25:34 +0200697 }
Takashi Iwai763f3562005-06-03 11:25:34 +0200698
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200699 /* if rate detected and Syncref is Word than have it,
700 * word has priority to MADI
701 */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200702 if (rate != 0 &&
703 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
704 return rate;
705
706 /* maby a madi input (which is taken if sel sync is madi) */
707 if (status & HDSPM_madiLock) {
708 rate_bits = status & HDSPM_madiFreqMask;
709
710 switch (rate_bits) {
711 case HDSPM_madiFreq32:
712 rate = 32000;
713 break;
714 case HDSPM_madiFreq44_1:
715 rate = 44100;
716 break;
717 case HDSPM_madiFreq48:
718 rate = 48000;
719 break;
720 case HDSPM_madiFreq64:
721 rate = 64000;
722 break;
723 case HDSPM_madiFreq88_2:
724 rate = 88200;
725 break;
726 case HDSPM_madiFreq96:
727 rate = 96000;
728 break;
729 case HDSPM_madiFreq128:
730 rate = 128000;
731 break;
732 case HDSPM_madiFreq176_4:
733 rate = 176400;
734 break;
735 case HDSPM_madiFreq192:
736 rate = 192000;
737 break;
738 default:
739 rate = 0;
740 break;
741 }
742 }
Takashi Iwai763f3562005-06-03 11:25:34 +0200743 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +0200744 }
Takashi Iwai763f3562005-06-03 11:25:34 +0200745}
746
747/* Latency function */
Takashi Iwai98274f02005-11-17 14:52:34 +0100748static inline void hdspm_compute_period_size(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200749{
750 hdspm->period_bytes =
751 1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
752}
753
Takashi Iwai98274f02005-11-17 14:52:34 +0100754static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200755{
756 int position;
757
758 position = hdspm_read(hdspm, HDSPM_statusRegister);
759
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200760 if (!hdspm->precise_ptr)
761 return (position & HDSPM_BufferID) ?
762 (hdspm->period_bytes / 4) : 0;
Takashi Iwai763f3562005-06-03 11:25:34 +0200763
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200764 /* hwpointer comes in bytes and is 64Bytes accurate (by docu since
765 PCI Burst)
Takashi Iwai763f3562005-06-03 11:25:34 +0200766 i have experimented that it is at most 64 Byte to much for playing
767 so substraction of 64 byte should be ok for ALSA, but use it only
768 for application where you know what you do since if you come to
769 near with record pointer it can be a disaster */
770
771 position &= HDSPM_BufferPositionMask;
772 position = ((position - 64) % (2 * hdspm->period_bytes)) / 4;
773
774 return position;
775}
776
777
Takashi Iwai98274f02005-11-17 14:52:34 +0100778static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +0200779{
780 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
781 hdspm_write(s, HDSPM_controlRegister, s->control_register);
782}
783
Takashi Iwai98274f02005-11-17 14:52:34 +0100784static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +0200785{
786 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
787 hdspm_write(s, HDSPM_controlRegister, s->control_register);
788}
789
790/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Denys Vlasenko62cef822008-04-14 13:04:18 +0200791static void hdspm_silence_playback(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200792{
793 int i;
794 int n = hdspm->period_bytes;
795 void *buf = hdspm->playback_buffer;
796
Remy Bruno3cee5a62006-10-16 12:46:32 +0200797 if (buf == NULL)
798 return;
Takashi Iwai763f3562005-06-03 11:25:34 +0200799
800 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
801 memset(buf, 0, n);
802 buf += HDSPM_CHANNEL_BUFFER_BYTES;
803 }
804}
805
Takashi Iwai98274f02005-11-17 14:52:34 +0100806static int hdspm_set_interrupt_interval(struct hdspm * s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +0200807{
808 int n;
809
810 spin_lock_irq(&s->lock);
811
812 frames >>= 7;
813 n = 0;
814 while (frames) {
815 n++;
816 frames >>= 1;
817 }
818 s->control_register &= ~HDSPM_LatencyMask;
819 s->control_register |= hdspm_encode_latency(n);
820
821 hdspm_write(s, HDSPM_controlRegister, s->control_register);
822
823 hdspm_compute_period_size(s);
824
825 spin_unlock_irq(&s->lock);
826
827 return 0;
828}
829
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100830static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
831{
832 u64 n;
833 u32 r;
834
835 if (rate >= 112000)
836 rate /= 4;
837 else if (rate >= 56000)
838 rate /= 2;
839
840 /* RME says n = 104857600000000, but in the windows MADI driver, I see:
Remy Bruno65345992007-08-31 12:21:08 +0200841// return 104857600000000 / rate; // 100 MHz
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100842 return 110100480000000 / rate; // 105 MHz
843 */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200844 /* n = 104857600000000ULL; */ /* = 2^20 * 10^8 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100845 n = 110100480000000ULL; /* Value checked for AES32 and MADI */
846 div64_32(&n, rate, &r);
847 /* n should be less than 2^32 for being written to FREQ register */
848 snd_assert((n >> 32) == 0);
849 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
850}
Takashi Iwai763f3562005-06-03 11:25:34 +0200851
852/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +0100853static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +0200854{
Takashi Iwai763f3562005-06-03 11:25:34 +0200855 int current_rate;
856 int rate_bits;
857 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +0200858 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +0200859
860 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
861 it (e.g. during module initialization).
862 */
863
864 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
865
866 /* SLAVE --- */
867 if (called_internally) {
868
869 /* request from ctl or card initialization
870 just make a warning an remember setting
871 for future master mode switching */
872
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200873 snd_printk(KERN_WARNING "HDSPM: "
874 "Warning: device is not running "
875 "as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +0200876 not_set = 1;
877 } else {
878
879 /* hw_param request while in AutoSync mode */
880 int external_freq =
881 hdspm_external_sample_rate(hdspm);
882
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200883 if (hdspm_autosync_ref(hdspm) ==
884 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +0200885
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200886 snd_printk(KERN_WARNING "HDSPM: "
887 "Detected no Externel Sync \n");
Takashi Iwai763f3562005-06-03 11:25:34 +0200888 not_set = 1;
889
890 } else if (rate != external_freq) {
891
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200892 snd_printk(KERN_WARNING "HDSPM: "
893 "Warning: No AutoSync source for "
894 "requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +0200895 not_set = 1;
896 }
897 }
898 }
899
900 current_rate = hdspm->system_sample_rate;
901
902 /* Changing between Singe, Double and Quad speed is not
903 allowed if any substreams are open. This is because such a change
904 causes a shift in the location of the DMA buffers and a reduction
905 in the number of available buffers.
906
907 Note that a similar but essentially insoluble problem exists for
908 externally-driven rate changes. All we can do is to flag rate
909 changes in the read/write routines.
910 */
911
Remy Bruno65345992007-08-31 12:21:08 +0200912 if (current_rate <= 48000)
913 current_speed = HDSPM_SPEED_SINGLE;
914 else if (current_rate <= 96000)
915 current_speed = HDSPM_SPEED_DOUBLE;
916 else
917 current_speed = HDSPM_SPEED_QUAD;
918
919 if (rate <= 48000)
920 target_speed = HDSPM_SPEED_SINGLE;
921 else if (rate <= 96000)
922 target_speed = HDSPM_SPEED_DOUBLE;
923 else
924 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +0200925
Takashi Iwai763f3562005-06-03 11:25:34 +0200926 switch (rate) {
927 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +0200928 rate_bits = HDSPM_Frequency32KHz;
929 break;
930 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +0200931 rate_bits = HDSPM_Frequency44_1KHz;
932 break;
933 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +0200934 rate_bits = HDSPM_Frequency48KHz;
935 break;
936 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +0200937 rate_bits = HDSPM_Frequency64KHz;
938 break;
939 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +0200940 rate_bits = HDSPM_Frequency88_2KHz;
941 break;
942 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +0200943 rate_bits = HDSPM_Frequency96KHz;
944 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +0200945 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200946 rate_bits = HDSPM_Frequency128KHz;
947 break;
948 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200949 rate_bits = HDSPM_Frequency176_4KHz;
950 break;
951 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200952 rate_bits = HDSPM_Frequency192KHz;
953 break;
Takashi Iwai763f3562005-06-03 11:25:34 +0200954 default:
955 return -EINVAL;
956 }
957
Remy Bruno65345992007-08-31 12:21:08 +0200958 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +0200959 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
960 snd_printk
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200961 (KERN_ERR "HDSPM: "
Remy Bruno65345992007-08-31 12:21:08 +0200962 "cannot change from %s speed to %s speed mode "
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200963 "(capture PID = %d, playback PID = %d)\n",
Remy Bruno65345992007-08-31 12:21:08 +0200964 hdspm_speed_names[current_speed],
965 hdspm_speed_names[target_speed],
Takashi Iwai763f3562005-06-03 11:25:34 +0200966 hdspm->capture_pid, hdspm->playback_pid);
967 return -EBUSY;
968 }
969
970 hdspm->control_register &= ~HDSPM_FrequencyMask;
971 hdspm->control_register |= rate_bits;
972 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
973
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100974 /* For AES32, need to set DDS value in FREQ register
975 For MADI, also apparently */
976 hdspm_set_dds_value(hdspm, rate);
977
978 if (hdspm->is_aes32 && rate != current_rate)
979 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
980
981 /* For AES32 and for MADI (at least rev 204), channel_map needs to
982 * always be channel_map_madi_ss, whatever the sample rate */
983 hdspm->channel_map = channel_map_madi_ss;
Takashi Iwai763f3562005-06-03 11:25:34 +0200984
985 hdspm->system_sample_rate = rate;
986
987 if (not_set != 0)
988 return -1;
989
990 return 0;
991}
992
993/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +0100994static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +0200995{
996 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200997 unsigned int gain;
998
999 if (sgain > UNITY_GAIN)
1000 gain = UNITY_GAIN;
1001 else if (sgain < 0)
1002 gain = 0;
1003 else
1004 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001005
1006 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1007 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1008 hdspm_write_in_gain(hdspm, i, j, gain);
1009 hdspm_write_pb_gain(hdspm, i, j, gain);
1010 }
1011}
1012
1013/*----------------------------------------------------------------------------
1014 MIDI
1015 ----------------------------------------------------------------------------*/
1016
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001017static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1018 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001019{
1020 /* the hardware already does the relevant bit-mask with 0xff */
1021 if (id)
1022 return hdspm_read(hdspm, HDSPM_midiDataIn1);
1023 else
1024 return hdspm_read(hdspm, HDSPM_midiDataIn0);
1025}
1026
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001027static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1028 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001029{
1030 /* the hardware already does the relevant bit-mask with 0xff */
1031 if (id)
Harvey Harrison0b76b512008-02-29 11:54:49 +01001032 hdspm_write(hdspm, HDSPM_midiDataOut1, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001033 else
Harvey Harrison0b76b512008-02-29 11:54:49 +01001034 hdspm_write(hdspm, HDSPM_midiDataOut0, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001035}
1036
Takashi Iwai98274f02005-11-17 14:52:34 +01001037static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001038{
1039 if (id)
1040 return (hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff);
1041 else
1042 return (hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff);
1043}
1044
Takashi Iwai98274f02005-11-17 14:52:34 +01001045static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001046{
1047 int fifo_bytes_used;
1048
1049 if (id)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001050 fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1);
Takashi Iwai763f3562005-06-03 11:25:34 +02001051 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001052 fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0);
1053 fifo_bytes_used &= 0xff;
Takashi Iwai763f3562005-06-03 11:25:34 +02001054
1055 if (fifo_bytes_used < 128)
1056 return 128 - fifo_bytes_used;
1057 else
1058 return 0;
1059}
1060
Denys Vlasenko62cef822008-04-14 13:04:18 +02001061static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001062{
1063 while (snd_hdspm_midi_input_available (hdspm, id))
1064 snd_hdspm_midi_read_byte (hdspm, id);
1065}
1066
Takashi Iwai98274f02005-11-17 14:52:34 +01001067static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001068{
1069 unsigned long flags;
1070 int n_pending;
1071 int to_write;
1072 int i;
1073 unsigned char buf[128];
1074
1075 /* Output is not interrupt driven */
1076
1077 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001078 if (hmidi->output &&
1079 !snd_rawmidi_transmit_empty (hmidi->output)) {
1080 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1081 hmidi->id);
1082 if (n_pending > 0) {
1083 if (n_pending > (int)sizeof (buf))
1084 n_pending = sizeof (buf);
1085
1086 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1087 n_pending);
1088 if (to_write > 0) {
1089 for (i = 0; i < to_write; ++i)
1090 snd_hdspm_midi_write_byte (hmidi->hdspm,
1091 hmidi->id,
1092 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001093 }
1094 }
1095 }
1096 spin_unlock_irqrestore (&hmidi->lock, flags);
1097 return 0;
1098}
1099
Takashi Iwai98274f02005-11-17 14:52:34 +01001100static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001101{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001102 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1103 * input FIFO size
1104 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001105 unsigned long flags;
1106 int n_pending;
1107 int i;
1108
1109 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001110 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1111 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001112 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001113 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001114 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001115 for (i = 0; i < n_pending; ++i)
1116 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1117 hmidi->id);
1118 if (n_pending)
1119 snd_rawmidi_receive (hmidi->input, buf,
1120 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001121 } else {
1122 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001123 while (n_pending--)
1124 snd_hdspm_midi_read_byte (hmidi->hdspm,
1125 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001126 }
1127 }
1128 hmidi->pending = 0;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001129 if (hmidi->id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001130 hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001131 else
Takashi Iwai763f3562005-06-03 11:25:34 +02001132 hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001133 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1134 hmidi->hdspm->control_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02001135 spin_unlock_irqrestore (&hmidi->lock, flags);
1136 return snd_hdspm_midi_output_write (hmidi);
1137}
1138
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001139static void
1140snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001141{
Takashi Iwai98274f02005-11-17 14:52:34 +01001142 struct hdspm *hdspm;
1143 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001144 unsigned long flags;
1145 u32 ie;
1146
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001147 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001148 hdspm = hmidi->hdspm;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001149 ie = hmidi->id ?
1150 HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable;
Takashi Iwai763f3562005-06-03 11:25:34 +02001151 spin_lock_irqsave (&hdspm->lock, flags);
1152 if (up) {
1153 if (!(hdspm->control_register & ie)) {
1154 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
1155 hdspm->control_register |= ie;
1156 }
1157 } else {
1158 hdspm->control_register &= ~ie;
1159 }
1160
1161 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1162 spin_unlock_irqrestore (&hdspm->lock, flags);
1163}
1164
1165static void snd_hdspm_midi_output_timer(unsigned long data)
1166{
Takashi Iwai98274f02005-11-17 14:52:34 +01001167 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001168 unsigned long flags;
1169
1170 snd_hdspm_midi_output_write(hmidi);
1171 spin_lock_irqsave (&hmidi->lock, flags);
1172
1173 /* this does not bump hmidi->istimer, because the
1174 kernel automatically removed the timer when it
1175 expired, and we are now adding it back, thus
1176 leaving istimer wherever it was set before.
1177 */
1178
1179 if (hmidi->istimer) {
1180 hmidi->timer.expires = 1 + jiffies;
1181 add_timer(&hmidi->timer);
1182 }
1183
1184 spin_unlock_irqrestore (&hmidi->lock, flags);
1185}
1186
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001187static void
1188snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001189{
Takashi Iwai98274f02005-11-17 14:52:34 +01001190 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001191 unsigned long flags;
1192
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001193 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001194 spin_lock_irqsave (&hmidi->lock, flags);
1195 if (up) {
1196 if (!hmidi->istimer) {
1197 init_timer(&hmidi->timer);
1198 hmidi->timer.function = snd_hdspm_midi_output_timer;
1199 hmidi->timer.data = (unsigned long) hmidi;
1200 hmidi->timer.expires = 1 + jiffies;
1201 add_timer(&hmidi->timer);
1202 hmidi->istimer++;
1203 }
1204 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001205 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001206 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001207 }
1208 spin_unlock_irqrestore (&hmidi->lock, flags);
1209 if (up)
1210 snd_hdspm_midi_output_write(hmidi);
1211}
1212
Takashi Iwai98274f02005-11-17 14:52:34 +01001213static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001214{
Takashi Iwai98274f02005-11-17 14:52:34 +01001215 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001216
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001217 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001218 spin_lock_irq (&hmidi->lock);
1219 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1220 hmidi->input = substream;
1221 spin_unlock_irq (&hmidi->lock);
1222
1223 return 0;
1224}
1225
Takashi Iwai98274f02005-11-17 14:52:34 +01001226static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001227{
Takashi Iwai98274f02005-11-17 14:52:34 +01001228 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001229
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001230 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001231 spin_lock_irq (&hmidi->lock);
1232 hmidi->output = substream;
1233 spin_unlock_irq (&hmidi->lock);
1234
1235 return 0;
1236}
1237
Takashi Iwai98274f02005-11-17 14:52:34 +01001238static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001239{
Takashi Iwai98274f02005-11-17 14:52:34 +01001240 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001241
1242 snd_hdspm_midi_input_trigger (substream, 0);
1243
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001244 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001245 spin_lock_irq (&hmidi->lock);
1246 hmidi->input = NULL;
1247 spin_unlock_irq (&hmidi->lock);
1248
1249 return 0;
1250}
1251
Takashi Iwai98274f02005-11-17 14:52:34 +01001252static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001253{
Takashi Iwai98274f02005-11-17 14:52:34 +01001254 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001255
1256 snd_hdspm_midi_output_trigger (substream, 0);
1257
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001258 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001259 spin_lock_irq (&hmidi->lock);
1260 hmidi->output = NULL;
1261 spin_unlock_irq (&hmidi->lock);
1262
1263 return 0;
1264}
1265
Takashi Iwai98274f02005-11-17 14:52:34 +01001266static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001267{
1268 .open = snd_hdspm_midi_output_open,
1269 .close = snd_hdspm_midi_output_close,
1270 .trigger = snd_hdspm_midi_output_trigger,
1271};
1272
Takashi Iwai98274f02005-11-17 14:52:34 +01001273static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001274{
1275 .open = snd_hdspm_midi_input_open,
1276 .close = snd_hdspm_midi_input_close,
1277 .trigger = snd_hdspm_midi_input_trigger,
1278};
1279
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001280static int __devinit snd_hdspm_create_midi (struct snd_card *card,
1281 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001282{
1283 int err;
1284 char buf[32];
1285
1286 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02001287 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02001288 spin_lock_init (&hdspm->midi[id].lock);
1289
1290 sprintf (buf, "%s MIDI %d", card->shortname, id+1);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001291 err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi);
1292 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001293 return err;
1294
1295 sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);
1296 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
1297
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001298 snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
1299 &snd_hdspm_midi_output);
1300 snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
1301 &snd_hdspm_midi_input);
Takashi Iwai763f3562005-06-03 11:25:34 +02001302
1303 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
1304 SNDRV_RAWMIDI_INFO_INPUT |
1305 SNDRV_RAWMIDI_INFO_DUPLEX;
1306
1307 return 0;
1308}
1309
1310
1311static void hdspm_midi_tasklet(unsigned long arg)
1312{
Takashi Iwai98274f02005-11-17 14:52:34 +01001313 struct hdspm *hdspm = (struct hdspm *)arg;
Takashi Iwai763f3562005-06-03 11:25:34 +02001314
1315 if (hdspm->midi[0].pending)
1316 snd_hdspm_midi_input_read (&hdspm->midi[0]);
1317 if (hdspm->midi[1].pending)
1318 snd_hdspm_midi_input_read (&hdspm->midi[1]);
1319}
1320
1321
1322/*-----------------------------------------------------------------------------
1323 Status Interface
1324 ----------------------------------------------------------------------------*/
1325
1326/* get the system sample rate which is set */
1327
1328#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001329{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001330 .name = xname, \
1331 .index = xindex, \
1332 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1333 .info = snd_hdspm_info_system_sample_rate, \
1334 .get = snd_hdspm_get_system_sample_rate \
1335}
1336
Takashi Iwai98274f02005-11-17 14:52:34 +01001337static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
1338 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001339{
1340 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1341 uinfo->count = 1;
1342 return 0;
1343}
1344
Takashi Iwai98274f02005-11-17 14:52:34 +01001345static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
1346 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02001347 ucontrol)
1348{
Takashi Iwai98274f02005-11-17 14:52:34 +01001349 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001350
1351 ucontrol->value.enumerated.item[0] = hdspm->system_sample_rate;
1352 return 0;
1353}
1354
1355#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001356{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001357 .name = xname, \
1358 .index = xindex, \
1359 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1360 .info = snd_hdspm_info_autosync_sample_rate, \
1361 .get = snd_hdspm_get_autosync_sample_rate \
1362}
1363
Takashi Iwai98274f02005-11-17 14:52:34 +01001364static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
1365 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001366{
1367 static char *texts[] = { "32000", "44100", "48000",
1368 "64000", "88200", "96000",
1369 "128000", "176400", "192000",
1370 "None"
1371 };
1372 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1373 uinfo->count = 1;
1374 uinfo->value.enumerated.items = 10;
1375 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1376 uinfo->value.enumerated.item =
1377 uinfo->value.enumerated.items - 1;
1378 strcpy(uinfo->value.enumerated.name,
1379 texts[uinfo->value.enumerated.item]);
1380 return 0;
1381}
1382
Takashi Iwai98274f02005-11-17 14:52:34 +01001383static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
1384 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02001385 ucontrol)
1386{
Takashi Iwai98274f02005-11-17 14:52:34 +01001387 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001388
1389 switch (hdspm_external_sample_rate(hdspm)) {
1390 case 32000:
1391 ucontrol->value.enumerated.item[0] = 0;
1392 break;
1393 case 44100:
1394 ucontrol->value.enumerated.item[0] = 1;
1395 break;
1396 case 48000:
1397 ucontrol->value.enumerated.item[0] = 2;
1398 break;
1399 case 64000:
1400 ucontrol->value.enumerated.item[0] = 3;
1401 break;
1402 case 88200:
1403 ucontrol->value.enumerated.item[0] = 4;
1404 break;
1405 case 96000:
1406 ucontrol->value.enumerated.item[0] = 5;
1407 break;
1408 case 128000:
1409 ucontrol->value.enumerated.item[0] = 6;
1410 break;
1411 case 176400:
1412 ucontrol->value.enumerated.item[0] = 7;
1413 break;
1414 case 192000:
1415 ucontrol->value.enumerated.item[0] = 8;
1416 break;
1417
1418 default:
1419 ucontrol->value.enumerated.item[0] = 9;
1420 }
1421 return 0;
1422}
1423
1424#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001425{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001426 .name = xname, \
1427 .index = xindex, \
1428 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1429 .info = snd_hdspm_info_system_clock_mode, \
1430 .get = snd_hdspm_get_system_clock_mode, \
1431}
1432
1433
1434
Takashi Iwai98274f02005-11-17 14:52:34 +01001435static int hdspm_system_clock_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001436{
1437 /* Always reflect the hardware info, rme is never wrong !!!! */
1438
1439 if (hdspm->control_register & HDSPM_ClockModeMaster)
1440 return 0;
1441 return 1;
1442}
1443
Takashi Iwai98274f02005-11-17 14:52:34 +01001444static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
1445 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001446{
1447 static char *texts[] = { "Master", "Slave" };
1448
1449 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1450 uinfo->count = 1;
1451 uinfo->value.enumerated.items = 2;
1452 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1453 uinfo->value.enumerated.item =
1454 uinfo->value.enumerated.items - 1;
1455 strcpy(uinfo->value.enumerated.name,
1456 texts[uinfo->value.enumerated.item]);
1457 return 0;
1458}
1459
Takashi Iwai98274f02005-11-17 14:52:34 +01001460static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
1461 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001462{
Takashi Iwai98274f02005-11-17 14:52:34 +01001463 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001464
1465 ucontrol->value.enumerated.item[0] =
1466 hdspm_system_clock_mode(hdspm);
1467 return 0;
1468}
1469
1470#define HDSPM_CLOCK_SOURCE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001471{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001472 .name = xname, \
1473 .index = xindex, \
1474 .info = snd_hdspm_info_clock_source, \
1475 .get = snd_hdspm_get_clock_source, \
1476 .put = snd_hdspm_put_clock_source \
1477}
1478
Takashi Iwai98274f02005-11-17 14:52:34 +01001479static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001480{
1481 if (hdspm->control_register & HDSPM_ClockModeMaster) {
1482 switch (hdspm->system_sample_rate) {
1483 case 32000:
1484 return 1;
1485 case 44100:
1486 return 2;
1487 case 48000:
1488 return 3;
1489 case 64000:
1490 return 4;
1491 case 88200:
1492 return 5;
1493 case 96000:
1494 return 6;
1495 case 128000:
1496 return 7;
1497 case 176400:
1498 return 8;
1499 case 192000:
1500 return 9;
1501 default:
1502 return 3;
1503 }
1504 } else {
1505 return 0;
1506 }
1507}
1508
Takashi Iwai98274f02005-11-17 14:52:34 +01001509static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02001510{
1511 int rate;
1512 switch (mode) {
1513
1514 case HDSPM_CLOCK_SOURCE_AUTOSYNC:
1515 if (hdspm_external_sample_rate(hdspm) != 0) {
1516 hdspm->control_register &= ~HDSPM_ClockModeMaster;
1517 hdspm_write(hdspm, HDSPM_controlRegister,
1518 hdspm->control_register);
1519 return 0;
1520 }
1521 return -1;
1522 case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
1523 rate = 32000;
1524 break;
1525 case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
1526 rate = 44100;
1527 break;
1528 case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
1529 rate = 48000;
1530 break;
1531 case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
1532 rate = 64000;
1533 break;
1534 case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
1535 rate = 88200;
1536 break;
1537 case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
1538 rate = 96000;
1539 break;
1540 case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
1541 rate = 128000;
1542 break;
1543 case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
1544 rate = 176400;
1545 break;
1546 case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
1547 rate = 192000;
1548 break;
1549
1550 default:
1551 rate = 44100;
1552 }
1553 hdspm->control_register |= HDSPM_ClockModeMaster;
1554 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1555 hdspm_set_rate(hdspm, rate, 1);
1556 return 0;
1557}
1558
Takashi Iwai98274f02005-11-17 14:52:34 +01001559static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
1560 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001561{
1562 static char *texts[] = { "AutoSync",
1563 "Internal 32.0 kHz", "Internal 44.1 kHz",
1564 "Internal 48.0 kHz",
1565 "Internal 64.0 kHz", "Internal 88.2 kHz",
1566 "Internal 96.0 kHz",
1567 "Internal 128.0 kHz", "Internal 176.4 kHz",
1568 "Internal 192.0 kHz"
1569 };
1570
1571 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1572 uinfo->count = 1;
1573 uinfo->value.enumerated.items = 10;
1574
1575 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1576 uinfo->value.enumerated.item =
1577 uinfo->value.enumerated.items - 1;
1578
1579 strcpy(uinfo->value.enumerated.name,
1580 texts[uinfo->value.enumerated.item]);
1581
1582 return 0;
1583}
1584
Takashi Iwai98274f02005-11-17 14:52:34 +01001585static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
1586 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001587{
Takashi Iwai98274f02005-11-17 14:52:34 +01001588 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001589
1590 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
1591 return 0;
1592}
1593
Takashi Iwai98274f02005-11-17 14:52:34 +01001594static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
1595 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001596{
Takashi Iwai98274f02005-11-17 14:52:34 +01001597 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001598 int change;
1599 int val;
1600
1601 if (!snd_hdspm_use_is_exclusive(hdspm))
1602 return -EBUSY;
1603 val = ucontrol->value.enumerated.item[0];
1604 if (val < 0)
1605 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001606 if (val > 9)
1607 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02001608 spin_lock_irq(&hdspm->lock);
1609 if (val != hdspm_clock_source(hdspm))
1610 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
1611 else
1612 change = 0;
1613 spin_unlock_irq(&hdspm->lock);
1614 return change;
1615}
1616
1617#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001618{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001619 .name = xname, \
1620 .index = xindex, \
1621 .info = snd_hdspm_info_pref_sync_ref, \
1622 .get = snd_hdspm_get_pref_sync_ref, \
1623 .put = snd_hdspm_put_pref_sync_ref \
1624}
1625
Takashi Iwai98274f02005-11-17 14:52:34 +01001626static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001627{
1628 /* Notice that this looks at the requested sync source,
1629 not the one actually in use.
1630 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001631 if (hdspm->is_aes32) {
1632 switch (hdspm->control_register & HDSPM_SyncRefMask) {
1633 /* number gives AES index, except for 0 which
1634 corresponds to WordClock */
1635 case 0: return 0;
1636 case HDSPM_SyncRef0: return 1;
1637 case HDSPM_SyncRef1: return 2;
1638 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3;
1639 case HDSPM_SyncRef2: return 4;
1640 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5;
1641 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6;
1642 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0: return 7;
1643 case HDSPM_SyncRef3: return 8;
1644 }
1645 } else {
1646 switch (hdspm->control_register & HDSPM_SyncRefMask) {
1647 case HDSPM_SyncRef_Word:
1648 return HDSPM_SYNC_FROM_WORD;
1649 case HDSPM_SyncRef_MADI:
1650 return HDSPM_SYNC_FROM_MADI;
1651 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001652 }
1653
1654 return HDSPM_SYNC_FROM_WORD;
1655}
1656
Takashi Iwai98274f02005-11-17 14:52:34 +01001657static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02001658{
1659 hdspm->control_register &= ~HDSPM_SyncRefMask;
1660
Remy Bruno3cee5a62006-10-16 12:46:32 +02001661 if (hdspm->is_aes32) {
1662 switch (pref) {
1663 case 0:
1664 hdspm->control_register |= 0;
1665 break;
1666 case 1:
1667 hdspm->control_register |= HDSPM_SyncRef0;
1668 break;
1669 case 2:
1670 hdspm->control_register |= HDSPM_SyncRef1;
1671 break;
1672 case 3:
1673 hdspm->control_register |= HDSPM_SyncRef1+HDSPM_SyncRef0;
1674 break;
1675 case 4:
1676 hdspm->control_register |= HDSPM_SyncRef2;
1677 break;
1678 case 5:
1679 hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef0;
1680 break;
1681 case 6:
1682 hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1;
1683 break;
1684 case 7:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001685 hdspm->control_register |=
1686 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001687 break;
1688 case 8:
1689 hdspm->control_register |= HDSPM_SyncRef3;
1690 break;
1691 default:
1692 return -1;
1693 }
1694 } else {
1695 switch (pref) {
1696 case HDSPM_SYNC_FROM_MADI:
1697 hdspm->control_register |= HDSPM_SyncRef_MADI;
1698 break;
1699 case HDSPM_SYNC_FROM_WORD:
1700 hdspm->control_register |= HDSPM_SyncRef_Word;
1701 break;
1702 default:
1703 return -1;
1704 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001705 }
1706 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1707 return 0;
1708}
1709
Takashi Iwai98274f02005-11-17 14:52:34 +01001710static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
1711 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001712{
Remy Bruno3cee5a62006-10-16 12:46:32 +02001713 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001714
Remy Bruno3cee5a62006-10-16 12:46:32 +02001715 if (hdspm->is_aes32) {
1716 static char *texts[] = { "Word", "AES1", "AES2", "AES3",
1717 "AES4", "AES5", "AES6", "AES7", "AES8" };
Takashi Iwai763f3562005-06-03 11:25:34 +02001718
Remy Bruno3cee5a62006-10-16 12:46:32 +02001719 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1720 uinfo->count = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02001721
Remy Bruno3cee5a62006-10-16 12:46:32 +02001722 uinfo->value.enumerated.items = 9;
1723
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001724 if (uinfo->value.enumerated.item >=
1725 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001726 uinfo->value.enumerated.item =
1727 uinfo->value.enumerated.items - 1;
1728 strcpy(uinfo->value.enumerated.name,
1729 texts[uinfo->value.enumerated.item]);
1730 } else {
1731 static char *texts[] = { "Word", "MADI" };
1732
1733 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1734 uinfo->count = 1;
1735
1736 uinfo->value.enumerated.items = 2;
1737
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001738 if (uinfo->value.enumerated.item >=
1739 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001740 uinfo->value.enumerated.item =
1741 uinfo->value.enumerated.items - 1;
1742 strcpy(uinfo->value.enumerated.name,
1743 texts[uinfo->value.enumerated.item]);
1744 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001745 return 0;
1746}
1747
Takashi Iwai98274f02005-11-17 14:52:34 +01001748static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
1749 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001750{
Takashi Iwai98274f02005-11-17 14:52:34 +01001751 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001752
1753 ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
1754 return 0;
1755}
1756
Takashi Iwai98274f02005-11-17 14:52:34 +01001757static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
1758 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001759{
Takashi Iwai98274f02005-11-17 14:52:34 +01001760 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001761 int change, max;
1762 unsigned int val;
1763
Remy Bruno3cee5a62006-10-16 12:46:32 +02001764 max = hdspm->is_aes32 ? 9 : 2;
Takashi Iwai763f3562005-06-03 11:25:34 +02001765
1766 if (!snd_hdspm_use_is_exclusive(hdspm))
1767 return -EBUSY;
1768
1769 val = ucontrol->value.enumerated.item[0] % max;
1770
1771 spin_lock_irq(&hdspm->lock);
1772 change = (int) val != hdspm_pref_sync_ref(hdspm);
1773 hdspm_set_pref_sync_ref(hdspm, val);
1774 spin_unlock_irq(&hdspm->lock);
1775 return change;
1776}
1777
1778#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001779{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001780 .name = xname, \
1781 .index = xindex, \
1782 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1783 .info = snd_hdspm_info_autosync_ref, \
1784 .get = snd_hdspm_get_autosync_ref, \
1785}
1786
Takashi Iwai98274f02005-11-17 14:52:34 +01001787static int hdspm_autosync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001788{
Remy Bruno3cee5a62006-10-16 12:46:32 +02001789 if (hdspm->is_aes32) {
1790 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001791 unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) &
1792 0xF;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001793 if (syncref == 0)
1794 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
1795 if (syncref <= 8)
1796 return syncref;
1797 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
1798 } else {
1799 /* This looks at the autosync selected sync reference */
1800 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Takashi Iwai763f3562005-06-03 11:25:34 +02001801
Remy Bruno3cee5a62006-10-16 12:46:32 +02001802 switch (status2 & HDSPM_SelSyncRefMask) {
1803 case HDSPM_SelSyncRef_WORD:
1804 return HDSPM_AUTOSYNC_FROM_WORD;
1805 case HDSPM_SelSyncRef_MADI:
1806 return HDSPM_AUTOSYNC_FROM_MADI;
1807 case HDSPM_SelSyncRef_NVALID:
1808 return HDSPM_AUTOSYNC_FROM_NONE;
1809 default:
1810 return 0;
1811 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001812
Takashi Iwai763f3562005-06-03 11:25:34 +02001813 return 0;
1814 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001815}
1816
Takashi Iwai98274f02005-11-17 14:52:34 +01001817static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
1818 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001819{
Remy Bruno3cee5a62006-10-16 12:46:32 +02001820 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001821
Remy Bruno3cee5a62006-10-16 12:46:32 +02001822 if (hdspm->is_aes32) {
1823 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
1824 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
1825
1826 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1827 uinfo->count = 1;
1828 uinfo->value.enumerated.items = 10;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001829 if (uinfo->value.enumerated.item >=
1830 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001831 uinfo->value.enumerated.item =
1832 uinfo->value.enumerated.items - 1;
1833 strcpy(uinfo->value.enumerated.name,
1834 texts[uinfo->value.enumerated.item]);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001835 } else {
Remy Bruno3cee5a62006-10-16 12:46:32 +02001836 static char *texts[] = { "WordClock", "MADI", "None" };
1837
1838 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1839 uinfo->count = 1;
1840 uinfo->value.enumerated.items = 3;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001841 if (uinfo->value.enumerated.item >=
1842 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001843 uinfo->value.enumerated.item =
1844 uinfo->value.enumerated.items - 1;
1845 strcpy(uinfo->value.enumerated.name,
1846 texts[uinfo->value.enumerated.item]);
1847 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001848 return 0;
1849}
1850
Takashi Iwai98274f02005-11-17 14:52:34 +01001851static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
1852 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001853{
Takashi Iwai98274f02005-11-17 14:52:34 +01001854 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001855
Remy Bruno65345992007-08-31 12:21:08 +02001856 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001857 return 0;
1858}
1859
1860#define HDSPM_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001861{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001862 .name = xname, \
1863 .index = xindex, \
1864 .info = snd_hdspm_info_line_out, \
1865 .get = snd_hdspm_get_line_out, \
1866 .put = snd_hdspm_put_line_out \
1867}
1868
Takashi Iwai98274f02005-11-17 14:52:34 +01001869static int hdspm_line_out(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001870{
1871 return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
1872}
1873
1874
Takashi Iwai98274f02005-11-17 14:52:34 +01001875static int hdspm_set_line_output(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001876{
1877 if (out)
1878 hdspm->control_register |= HDSPM_LineOut;
1879 else
1880 hdspm->control_register &= ~HDSPM_LineOut;
1881 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1882
1883 return 0;
1884}
1885
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001886#define snd_hdspm_info_line_out snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02001887
Takashi Iwai98274f02005-11-17 14:52:34 +01001888static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
1889 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001890{
Takashi Iwai98274f02005-11-17 14:52:34 +01001891 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001892
1893 spin_lock_irq(&hdspm->lock);
1894 ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
1895 spin_unlock_irq(&hdspm->lock);
1896 return 0;
1897}
1898
Takashi Iwai98274f02005-11-17 14:52:34 +01001899static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
1900 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001901{
Takashi Iwai98274f02005-11-17 14:52:34 +01001902 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001903 int change;
1904 unsigned int val;
1905
1906 if (!snd_hdspm_use_is_exclusive(hdspm))
1907 return -EBUSY;
1908 val = ucontrol->value.integer.value[0] & 1;
1909 spin_lock_irq(&hdspm->lock);
1910 change = (int) val != hdspm_line_out(hdspm);
1911 hdspm_set_line_output(hdspm, val);
1912 spin_unlock_irq(&hdspm->lock);
1913 return change;
1914}
1915
1916#define HDSPM_TX_64(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001917{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001918 .name = xname, \
1919 .index = xindex, \
1920 .info = snd_hdspm_info_tx_64, \
1921 .get = snd_hdspm_get_tx_64, \
1922 .put = snd_hdspm_put_tx_64 \
1923}
1924
Takashi Iwai98274f02005-11-17 14:52:34 +01001925static int hdspm_tx_64(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001926{
1927 return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
1928}
1929
Takashi Iwai98274f02005-11-17 14:52:34 +01001930static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001931{
1932 if (out)
1933 hdspm->control_register |= HDSPM_TX_64ch;
1934 else
1935 hdspm->control_register &= ~HDSPM_TX_64ch;
1936 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1937
1938 return 0;
1939}
1940
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001941#define snd_hdspm_info_tx_64 snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02001942
Takashi Iwai98274f02005-11-17 14:52:34 +01001943static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
1944 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001945{
Takashi Iwai98274f02005-11-17 14:52:34 +01001946 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001947
1948 spin_lock_irq(&hdspm->lock);
1949 ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
1950 spin_unlock_irq(&hdspm->lock);
1951 return 0;
1952}
1953
Takashi Iwai98274f02005-11-17 14:52:34 +01001954static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
1955 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001956{
Takashi Iwai98274f02005-11-17 14:52:34 +01001957 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001958 int change;
1959 unsigned int val;
1960
1961 if (!snd_hdspm_use_is_exclusive(hdspm))
1962 return -EBUSY;
1963 val = ucontrol->value.integer.value[0] & 1;
1964 spin_lock_irq(&hdspm->lock);
1965 change = (int) val != hdspm_tx_64(hdspm);
1966 hdspm_set_tx_64(hdspm, val);
1967 spin_unlock_irq(&hdspm->lock);
1968 return change;
1969}
1970
1971#define HDSPM_C_TMS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001972{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001973 .name = xname, \
1974 .index = xindex, \
1975 .info = snd_hdspm_info_c_tms, \
1976 .get = snd_hdspm_get_c_tms, \
1977 .put = snd_hdspm_put_c_tms \
1978}
1979
Takashi Iwai98274f02005-11-17 14:52:34 +01001980static int hdspm_c_tms(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001981{
1982 return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
1983}
1984
Takashi Iwai98274f02005-11-17 14:52:34 +01001985static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001986{
1987 if (out)
1988 hdspm->control_register |= HDSPM_clr_tms;
1989 else
1990 hdspm->control_register &= ~HDSPM_clr_tms;
1991 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1992
1993 return 0;
1994}
1995
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001996#define snd_hdspm_info_c_tms snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02001997
Takashi Iwai98274f02005-11-17 14:52:34 +01001998static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
1999 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002000{
Takashi Iwai98274f02005-11-17 14:52:34 +01002001 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002002
2003 spin_lock_irq(&hdspm->lock);
2004 ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
2005 spin_unlock_irq(&hdspm->lock);
2006 return 0;
2007}
2008
Takashi Iwai98274f02005-11-17 14:52:34 +01002009static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
2010 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002011{
Takashi Iwai98274f02005-11-17 14:52:34 +01002012 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002013 int change;
2014 unsigned int val;
2015
2016 if (!snd_hdspm_use_is_exclusive(hdspm))
2017 return -EBUSY;
2018 val = ucontrol->value.integer.value[0] & 1;
2019 spin_lock_irq(&hdspm->lock);
2020 change = (int) val != hdspm_c_tms(hdspm);
2021 hdspm_set_c_tms(hdspm, val);
2022 spin_unlock_irq(&hdspm->lock);
2023 return change;
2024}
2025
2026#define HDSPM_SAFE_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002027{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002028 .name = xname, \
2029 .index = xindex, \
2030 .info = snd_hdspm_info_safe_mode, \
2031 .get = snd_hdspm_get_safe_mode, \
2032 .put = snd_hdspm_put_safe_mode \
2033}
2034
Takashi Iwai98274f02005-11-17 14:52:34 +01002035static int hdspm_safe_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002036{
2037 return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
2038}
2039
Takashi Iwai98274f02005-11-17 14:52:34 +01002040static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002041{
2042 if (out)
2043 hdspm->control_register |= HDSPM_AutoInp;
2044 else
2045 hdspm->control_register &= ~HDSPM_AutoInp;
2046 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2047
2048 return 0;
2049}
2050
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002051#define snd_hdspm_info_safe_mode snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002052
Takashi Iwai98274f02005-11-17 14:52:34 +01002053static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
2054 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002055{
Takashi Iwai98274f02005-11-17 14:52:34 +01002056 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002057
2058 spin_lock_irq(&hdspm->lock);
2059 ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
2060 spin_unlock_irq(&hdspm->lock);
2061 return 0;
2062}
2063
Takashi Iwai98274f02005-11-17 14:52:34 +01002064static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
2065 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002066{
Takashi Iwai98274f02005-11-17 14:52:34 +01002067 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002068 int change;
2069 unsigned int val;
2070
2071 if (!snd_hdspm_use_is_exclusive(hdspm))
2072 return -EBUSY;
2073 val = ucontrol->value.integer.value[0] & 1;
2074 spin_lock_irq(&hdspm->lock);
2075 change = (int) val != hdspm_safe_mode(hdspm);
2076 hdspm_set_safe_mode(hdspm, val);
2077 spin_unlock_irq(&hdspm->lock);
2078 return change;
2079}
2080
Remy Bruno3cee5a62006-10-16 12:46:32 +02002081#define HDSPM_EMPHASIS(xname, xindex) \
2082{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2083 .name = xname, \
2084 .index = xindex, \
2085 .info = snd_hdspm_info_emphasis, \
2086 .get = snd_hdspm_get_emphasis, \
2087 .put = snd_hdspm_put_emphasis \
2088}
2089
2090static int hdspm_emphasis(struct hdspm * hdspm)
2091{
2092 return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0;
2093}
2094
2095static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
2096{
2097 if (emp)
2098 hdspm->control_register |= HDSPM_Emphasis;
2099 else
2100 hdspm->control_register &= ~HDSPM_Emphasis;
2101 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2102
2103 return 0;
2104}
2105
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002106#define snd_hdspm_info_emphasis snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02002107
2108static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
2109 struct snd_ctl_elem_value *ucontrol)
2110{
2111 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2112
2113 spin_lock_irq(&hdspm->lock);
2114 ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm);
2115 spin_unlock_irq(&hdspm->lock);
2116 return 0;
2117}
2118
2119static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
2120 struct snd_ctl_elem_value *ucontrol)
2121{
2122 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2123 int change;
2124 unsigned int val;
2125
2126 if (!snd_hdspm_use_is_exclusive(hdspm))
2127 return -EBUSY;
2128 val = ucontrol->value.integer.value[0] & 1;
2129 spin_lock_irq(&hdspm->lock);
2130 change = (int) val != hdspm_emphasis(hdspm);
2131 hdspm_set_emphasis(hdspm, val);
2132 spin_unlock_irq(&hdspm->lock);
2133 return change;
2134}
2135
2136#define HDSPM_DOLBY(xname, xindex) \
2137{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2138 .name = xname, \
2139 .index = xindex, \
2140 .info = snd_hdspm_info_dolby, \
2141 .get = snd_hdspm_get_dolby, \
2142 .put = snd_hdspm_put_dolby \
2143}
2144
2145static int hdspm_dolby(struct hdspm * hdspm)
2146{
2147 return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0;
2148}
2149
2150static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
2151{
2152 if (dol)
2153 hdspm->control_register |= HDSPM_Dolby;
2154 else
2155 hdspm->control_register &= ~HDSPM_Dolby;
2156 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2157
2158 return 0;
2159}
2160
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002161#define snd_hdspm_info_dolby snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02002162
2163static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
2164 struct snd_ctl_elem_value *ucontrol)
2165{
2166 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2167
2168 spin_lock_irq(&hdspm->lock);
2169 ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm);
2170 spin_unlock_irq(&hdspm->lock);
2171 return 0;
2172}
2173
2174static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
2175 struct snd_ctl_elem_value *ucontrol)
2176{
2177 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2178 int change;
2179 unsigned int val;
2180
2181 if (!snd_hdspm_use_is_exclusive(hdspm))
2182 return -EBUSY;
2183 val = ucontrol->value.integer.value[0] & 1;
2184 spin_lock_irq(&hdspm->lock);
2185 change = (int) val != hdspm_dolby(hdspm);
2186 hdspm_set_dolby(hdspm, val);
2187 spin_unlock_irq(&hdspm->lock);
2188 return change;
2189}
2190
2191#define HDSPM_PROFESSIONAL(xname, xindex) \
2192{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2193 .name = xname, \
2194 .index = xindex, \
2195 .info = snd_hdspm_info_professional, \
2196 .get = snd_hdspm_get_professional, \
2197 .put = snd_hdspm_put_professional \
2198}
2199
2200static int hdspm_professional(struct hdspm * hdspm)
2201{
2202 return (hdspm->control_register & HDSPM_Professional) ? 1 : 0;
2203}
2204
2205static int hdspm_set_professional(struct hdspm * hdspm, int dol)
2206{
2207 if (dol)
2208 hdspm->control_register |= HDSPM_Professional;
2209 else
2210 hdspm->control_register &= ~HDSPM_Professional;
2211 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2212
2213 return 0;
2214}
2215
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002216#define snd_hdspm_info_professional snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02002217
2218static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
2219 struct snd_ctl_elem_value *ucontrol)
2220{
2221 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2222
2223 spin_lock_irq(&hdspm->lock);
2224 ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm);
2225 spin_unlock_irq(&hdspm->lock);
2226 return 0;
2227}
2228
2229static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
2230 struct snd_ctl_elem_value *ucontrol)
2231{
2232 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2233 int change;
2234 unsigned int val;
2235
2236 if (!snd_hdspm_use_is_exclusive(hdspm))
2237 return -EBUSY;
2238 val = ucontrol->value.integer.value[0] & 1;
2239 spin_lock_irq(&hdspm->lock);
2240 change = (int) val != hdspm_professional(hdspm);
2241 hdspm_set_professional(hdspm, val);
2242 spin_unlock_irq(&hdspm->lock);
2243 return change;
2244}
2245
Takashi Iwai763f3562005-06-03 11:25:34 +02002246#define HDSPM_INPUT_SELECT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002247{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002248 .name = xname, \
2249 .index = xindex, \
2250 .info = snd_hdspm_info_input_select, \
2251 .get = snd_hdspm_get_input_select, \
2252 .put = snd_hdspm_put_input_select \
2253}
2254
Takashi Iwai98274f02005-11-17 14:52:34 +01002255static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002256{
2257 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
2258}
2259
Takashi Iwai98274f02005-11-17 14:52:34 +01002260static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002261{
2262 if (out)
2263 hdspm->control_register |= HDSPM_InputSelect0;
2264 else
2265 hdspm->control_register &= ~HDSPM_InputSelect0;
2266 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2267
2268 return 0;
2269}
2270
Takashi Iwai98274f02005-11-17 14:52:34 +01002271static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
2272 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002273{
2274 static char *texts[] = { "optical", "coaxial" };
2275
2276 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2277 uinfo->count = 1;
2278 uinfo->value.enumerated.items = 2;
2279
2280 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2281 uinfo->value.enumerated.item =
2282 uinfo->value.enumerated.items - 1;
2283 strcpy(uinfo->value.enumerated.name,
2284 texts[uinfo->value.enumerated.item]);
2285
2286 return 0;
2287}
2288
Takashi Iwai98274f02005-11-17 14:52:34 +01002289static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
2290 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002291{
Takashi Iwai98274f02005-11-17 14:52:34 +01002292 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002293
2294 spin_lock_irq(&hdspm->lock);
2295 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
2296 spin_unlock_irq(&hdspm->lock);
2297 return 0;
2298}
2299
Takashi Iwai98274f02005-11-17 14:52:34 +01002300static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
2301 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002302{
Takashi Iwai98274f02005-11-17 14:52:34 +01002303 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002304 int change;
2305 unsigned int val;
2306
2307 if (!snd_hdspm_use_is_exclusive(hdspm))
2308 return -EBUSY;
2309 val = ucontrol->value.integer.value[0] & 1;
2310 spin_lock_irq(&hdspm->lock);
2311 change = (int) val != hdspm_input_select(hdspm);
2312 hdspm_set_input_select(hdspm, val);
2313 spin_unlock_irq(&hdspm->lock);
2314 return change;
2315}
2316
Remy Bruno3cee5a62006-10-16 12:46:32 +02002317#define HDSPM_DS_WIRE(xname, xindex) \
2318{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2319 .name = xname, \
2320 .index = xindex, \
2321 .info = snd_hdspm_info_ds_wire, \
2322 .get = snd_hdspm_get_ds_wire, \
2323 .put = snd_hdspm_put_ds_wire \
2324}
2325
2326static int hdspm_ds_wire(struct hdspm * hdspm)
2327{
2328 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
2329}
2330
2331static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
2332{
2333 if (ds)
2334 hdspm->control_register |= HDSPM_DS_DoubleWire;
2335 else
2336 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
2337 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2338
2339 return 0;
2340}
2341
2342static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
2343 struct snd_ctl_elem_info *uinfo)
2344{
2345 static char *texts[] = { "Single", "Double" };
2346
2347 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2348 uinfo->count = 1;
2349 uinfo->value.enumerated.items = 2;
2350
2351 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2352 uinfo->value.enumerated.item =
2353 uinfo->value.enumerated.items - 1;
2354 strcpy(uinfo->value.enumerated.name,
2355 texts[uinfo->value.enumerated.item]);
2356
2357 return 0;
2358}
2359
2360static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
2361 struct snd_ctl_elem_value *ucontrol)
2362{
2363 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2364
2365 spin_lock_irq(&hdspm->lock);
2366 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
2367 spin_unlock_irq(&hdspm->lock);
2368 return 0;
2369}
2370
2371static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
2372 struct snd_ctl_elem_value *ucontrol)
2373{
2374 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2375 int change;
2376 unsigned int val;
2377
2378 if (!snd_hdspm_use_is_exclusive(hdspm))
2379 return -EBUSY;
2380 val = ucontrol->value.integer.value[0] & 1;
2381 spin_lock_irq(&hdspm->lock);
2382 change = (int) val != hdspm_ds_wire(hdspm);
2383 hdspm_set_ds_wire(hdspm, val);
2384 spin_unlock_irq(&hdspm->lock);
2385 return change;
2386}
2387
2388#define HDSPM_QS_WIRE(xname, xindex) \
2389{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2390 .name = xname, \
2391 .index = xindex, \
2392 .info = snd_hdspm_info_qs_wire, \
2393 .get = snd_hdspm_get_qs_wire, \
2394 .put = snd_hdspm_put_qs_wire \
2395}
2396
2397static int hdspm_qs_wire(struct hdspm * hdspm)
2398{
2399 if (hdspm->control_register & HDSPM_QS_DoubleWire)
2400 return 1;
2401 if (hdspm->control_register & HDSPM_QS_QuadWire)
2402 return 2;
2403 return 0;
2404}
2405
2406static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
2407{
2408 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
2409 switch (mode) {
2410 case 0:
2411 break;
2412 case 1:
2413 hdspm->control_register |= HDSPM_QS_DoubleWire;
2414 break;
2415 case 2:
2416 hdspm->control_register |= HDSPM_QS_QuadWire;
2417 break;
2418 }
2419 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2420
2421 return 0;
2422}
2423
2424static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
2425 struct snd_ctl_elem_info *uinfo)
2426{
2427 static char *texts[] = { "Single", "Double", "Quad" };
2428
2429 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2430 uinfo->count = 1;
2431 uinfo->value.enumerated.items = 3;
2432
2433 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2434 uinfo->value.enumerated.item =
2435 uinfo->value.enumerated.items - 1;
2436 strcpy(uinfo->value.enumerated.name,
2437 texts[uinfo->value.enumerated.item]);
2438
2439 return 0;
2440}
2441
2442static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
2443 struct snd_ctl_elem_value *ucontrol)
2444{
2445 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2446
2447 spin_lock_irq(&hdspm->lock);
2448 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
2449 spin_unlock_irq(&hdspm->lock);
2450 return 0;
2451}
2452
2453static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
2454 struct snd_ctl_elem_value *ucontrol)
2455{
2456 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2457 int change;
2458 int val;
2459
2460 if (!snd_hdspm_use_is_exclusive(hdspm))
2461 return -EBUSY;
2462 val = ucontrol->value.integer.value[0];
2463 if (val < 0)
2464 val = 0;
2465 if (val > 2)
2466 val = 2;
2467 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002468 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002469 hdspm_set_qs_wire(hdspm, val);
2470 spin_unlock_irq(&hdspm->lock);
2471 return change;
2472}
2473
Takashi Iwai763f3562005-06-03 11:25:34 +02002474/* Simple Mixer
2475 deprecated since to much faders ???
2476 MIXER interface says output (source, destination, value)
2477 where source > MAX_channels are playback channels
2478 on MADICARD
2479 - playback mixer matrix: [channelout+64] [output] [value]
2480 - input(thru) mixer matrix: [channelin] [output] [value]
2481 (better do 2 kontrols for seperation ?)
2482*/
2483
2484#define HDSPM_MIXER(xname, xindex) \
2485{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
2486 .name = xname, \
2487 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002488 .device = 0, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002489 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2490 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2491 .info = snd_hdspm_info_mixer, \
2492 .get = snd_hdspm_get_mixer, \
2493 .put = snd_hdspm_put_mixer \
2494}
2495
Takashi Iwai98274f02005-11-17 14:52:34 +01002496static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
2497 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002498{
2499 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2500 uinfo->count = 3;
2501 uinfo->value.integer.min = 0;
2502 uinfo->value.integer.max = 65535;
2503 uinfo->value.integer.step = 1;
2504 return 0;
2505}
2506
Takashi Iwai98274f02005-11-17 14:52:34 +01002507static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
2508 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002509{
Takashi Iwai98274f02005-11-17 14:52:34 +01002510 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002511 int source;
2512 int destination;
2513
2514 source = ucontrol->value.integer.value[0];
2515 if (source < 0)
2516 source = 0;
2517 else if (source >= 2 * HDSPM_MAX_CHANNELS)
2518 source = 2 * HDSPM_MAX_CHANNELS - 1;
2519
2520 destination = ucontrol->value.integer.value[1];
2521 if (destination < 0)
2522 destination = 0;
2523 else if (destination >= HDSPM_MAX_CHANNELS)
2524 destination = HDSPM_MAX_CHANNELS - 1;
2525
2526 spin_lock_irq(&hdspm->lock);
2527 if (source >= HDSPM_MAX_CHANNELS)
2528 ucontrol->value.integer.value[2] =
2529 hdspm_read_pb_gain(hdspm, destination,
2530 source - HDSPM_MAX_CHANNELS);
2531 else
2532 ucontrol->value.integer.value[2] =
2533 hdspm_read_in_gain(hdspm, destination, source);
2534
2535 spin_unlock_irq(&hdspm->lock);
2536
2537 return 0;
2538}
2539
Takashi Iwai98274f02005-11-17 14:52:34 +01002540static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
2541 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002542{
Takashi Iwai98274f02005-11-17 14:52:34 +01002543 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002544 int change;
2545 int source;
2546 int destination;
2547 int gain;
2548
2549 if (!snd_hdspm_use_is_exclusive(hdspm))
2550 return -EBUSY;
2551
2552 source = ucontrol->value.integer.value[0];
2553 destination = ucontrol->value.integer.value[1];
2554
2555 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
2556 return -1;
2557 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
2558 return -1;
2559
2560 gain = ucontrol->value.integer.value[2];
2561
2562 spin_lock_irq(&hdspm->lock);
2563
2564 if (source >= HDSPM_MAX_CHANNELS)
2565 change = gain != hdspm_read_pb_gain(hdspm, destination,
2566 source -
2567 HDSPM_MAX_CHANNELS);
2568 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002569 change = gain != hdspm_read_in_gain(hdspm, destination,
2570 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02002571
2572 if (change) {
2573 if (source >= HDSPM_MAX_CHANNELS)
2574 hdspm_write_pb_gain(hdspm, destination,
2575 source - HDSPM_MAX_CHANNELS,
2576 gain);
2577 else
2578 hdspm_write_in_gain(hdspm, destination, source,
2579 gain);
2580 }
2581 spin_unlock_irq(&hdspm->lock);
2582
2583 return change;
2584}
2585
2586/* The simple mixer control(s) provide gain control for the
2587 basic 1:1 mappings of playback streams to output
2588 streams.
2589*/
2590
2591#define HDSPM_PLAYBACK_MIXER \
2592{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2593 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
2594 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2595 .info = snd_hdspm_info_playback_mixer, \
2596 .get = snd_hdspm_get_playback_mixer, \
2597 .put = snd_hdspm_put_playback_mixer \
2598}
2599
Takashi Iwai98274f02005-11-17 14:52:34 +01002600static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
2601 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002602{
2603 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2604 uinfo->count = 1;
2605 uinfo->value.integer.min = 0;
2606 uinfo->value.integer.max = 65536;
2607 uinfo->value.integer.step = 1;
2608 return 0;
2609}
2610
Takashi Iwai98274f02005-11-17 14:52:34 +01002611static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
2612 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002613{
Takashi Iwai98274f02005-11-17 14:52:34 +01002614 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002615 int channel;
2616 int mapped_channel;
2617
2618 channel = ucontrol->id.index - 1;
2619
2620 snd_assert(channel >= 0
2621 || channel < HDSPM_MAX_CHANNELS, return -EINVAL);
2622
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002623 mapped_channel = hdspm->channel_map[channel];
2624 if (mapped_channel < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02002625 return -EINVAL;
2626
2627 spin_lock_irq(&hdspm->lock);
2628 ucontrol->value.integer.value[0] =
2629 hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel);
2630 spin_unlock_irq(&hdspm->lock);
2631
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002632 /*
2633 snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, "
2634 "value %d\n",
2635 ucontrol->id.index, channel, mapped_channel,
2636 ucontrol->value.integer.value[0]);
2637 */
Takashi Iwai763f3562005-06-03 11:25:34 +02002638 return 0;
2639}
2640
Takashi Iwai98274f02005-11-17 14:52:34 +01002641static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
2642 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002643{
Takashi Iwai98274f02005-11-17 14:52:34 +01002644 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002645 int change;
2646 int channel;
2647 int mapped_channel;
2648 int gain;
2649
2650 if (!snd_hdspm_use_is_exclusive(hdspm))
2651 return -EBUSY;
2652
2653 channel = ucontrol->id.index - 1;
2654
2655 snd_assert(channel >= 0
2656 || channel < HDSPM_MAX_CHANNELS, return -EINVAL);
2657
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002658 mapped_channel = hdspm->channel_map[channel];
2659 if (mapped_channel < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02002660 return -EINVAL;
2661
2662 gain = ucontrol->value.integer.value[0];
2663
2664 spin_lock_irq(&hdspm->lock);
2665 change =
2666 gain != hdspm_read_pb_gain(hdspm, mapped_channel,
2667 mapped_channel);
2668 if (change)
2669 hdspm_write_pb_gain(hdspm, mapped_channel, mapped_channel,
2670 gain);
2671 spin_unlock_irq(&hdspm->lock);
2672 return change;
2673}
2674
2675#define HDSPM_WC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002676{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002677 .name = xname, \
2678 .index = xindex, \
2679 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2680 .info = snd_hdspm_info_sync_check, \
2681 .get = snd_hdspm_get_wc_sync_check \
2682}
2683
Takashi Iwai98274f02005-11-17 14:52:34 +01002684static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
2685 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002686{
2687 static char *texts[] = { "No Lock", "Lock", "Sync" };
2688 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2689 uinfo->count = 1;
2690 uinfo->value.enumerated.items = 3;
2691 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2692 uinfo->value.enumerated.item =
2693 uinfo->value.enumerated.items - 1;
2694 strcpy(uinfo->value.enumerated.name,
2695 texts[uinfo->value.enumerated.item]);
2696 return 0;
2697}
2698
Takashi Iwai98274f02005-11-17 14:52:34 +01002699static int hdspm_wc_sync_check(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002700{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002701 if (hdspm->is_aes32) {
2702 int status = hdspm_read(hdspm, HDSPM_statusRegister);
2703 if (status & HDSPM_AES32_wcLock) {
2704 /* I don't know how to differenciate sync from lock.
2705 Doing as if sync for now */
Takashi Iwai763f3562005-06-03 11:25:34 +02002706 return 2;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002707 }
2708 return 0;
2709 } else {
2710 int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
2711 if (status2 & HDSPM_wcLock) {
2712 if (status2 & HDSPM_wcSync)
2713 return 2;
2714 else
2715 return 1;
2716 }
2717 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002718 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002719}
2720
Takashi Iwai98274f02005-11-17 14:52:34 +01002721static int snd_hdspm_get_wc_sync_check(struct snd_kcontrol *kcontrol,
2722 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002723{
Takashi Iwai98274f02005-11-17 14:52:34 +01002724 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002725
2726 ucontrol->value.enumerated.item[0] = hdspm_wc_sync_check(hdspm);
2727 return 0;
2728}
2729
2730
2731#define HDSPM_MADI_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002732{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002733 .name = xname, \
2734 .index = xindex, \
2735 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2736 .info = snd_hdspm_info_sync_check, \
2737 .get = snd_hdspm_get_madisync_sync_check \
2738}
2739
Takashi Iwai98274f02005-11-17 14:52:34 +01002740static int hdspm_madisync_sync_check(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002741{
2742 int status = hdspm_read(hdspm, HDSPM_statusRegister);
2743 if (status & HDSPM_madiLock) {
2744 if (status & HDSPM_madiSync)
2745 return 2;
2746 else
2747 return 1;
2748 }
2749 return 0;
2750}
2751
Takashi Iwai98274f02005-11-17 14:52:34 +01002752static int snd_hdspm_get_madisync_sync_check(struct snd_kcontrol *kcontrol,
2753 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002754 ucontrol)
2755{
Takashi Iwai98274f02005-11-17 14:52:34 +01002756 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002757
2758 ucontrol->value.enumerated.item[0] =
2759 hdspm_madisync_sync_check(hdspm);
2760 return 0;
2761}
2762
2763
Remy Bruno3cee5a62006-10-16 12:46:32 +02002764#define HDSPM_AES_SYNC_CHECK(xname, xindex) \
2765{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2766 .name = xname, \
2767 .index = xindex, \
2768 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2769 .info = snd_hdspm_info_sync_check, \
2770 .get = snd_hdspm_get_aes_sync_check \
2771}
2772
2773static int hdspm_aes_sync_check(struct hdspm * hdspm, int idx)
2774{
2775 int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
2776 if (status2 & (HDSPM_LockAES >> idx)) {
2777 /* I don't know how to differenciate sync from lock.
2778 Doing as if sync for now */
2779 return 2;
2780 }
2781 return 0;
2782}
2783
2784static int snd_hdspm_get_aes_sync_check(struct snd_kcontrol *kcontrol,
2785 struct snd_ctl_elem_value *ucontrol)
2786{
2787 int offset;
2788 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2789
2790 offset = ucontrol->id.index - 1;
2791 if (offset < 0 || offset >= 8)
2792 return -EINVAL;
2793
2794 ucontrol->value.enumerated.item[0] =
2795 hdspm_aes_sync_check(hdspm, offset);
2796 return 0;
2797}
Takashi Iwai763f3562005-06-03 11:25:34 +02002798
2799
Remy Bruno3cee5a62006-10-16 12:46:32 +02002800static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02002801
2802 HDSPM_MIXER("Mixer", 0),
2803/* 'Sample Clock Source' complies with the alsa control naming scheme */
2804 HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
2805
2806 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
2807 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
2808 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
2809 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
2810/* 'External Rate' complies with the alsa control naming scheme */
2811 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
2812 HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
2813 HDSPM_MADI_SYNC_CHECK("MADI Sync Lock Status", 0),
2814 HDSPM_LINE_OUT("Line Out", 0),
2815 HDSPM_TX_64("TX 64 channels mode", 0),
2816 HDSPM_C_TMS("Clear Track Marker", 0),
2817 HDSPM_SAFE_MODE("Safe Mode", 0),
2818 HDSPM_INPUT_SELECT("Input Select", 0),
2819};
2820
Remy Bruno3cee5a62006-10-16 12:46:32 +02002821static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
2822
2823 HDSPM_MIXER("Mixer", 0),
2824/* 'Sample Clock Source' complies with the alsa control naming scheme */
2825 HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
2826
2827 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
2828 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
2829 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
2830 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
2831/* 'External Rate' complies with the alsa control naming scheme */
2832 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
2833 HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
2834/* HDSPM_AES_SYNC_CHECK("AES Lock Status", 0),*/ /* created in snd_hdspm_create_controls() */
2835 HDSPM_LINE_OUT("Line Out", 0),
2836 HDSPM_EMPHASIS("Emphasis", 0),
2837 HDSPM_DOLBY("Non Audio", 0),
2838 HDSPM_PROFESSIONAL("Professional", 0),
2839 HDSPM_C_TMS("Clear Track Marker", 0),
2840 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
2841 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
2842};
2843
Takashi Iwai98274f02005-11-17 14:52:34 +01002844static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02002845
2846
Takashi Iwai98274f02005-11-17 14:52:34 +01002847static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002848{
2849 int i;
2850
2851 for (i = hdspm->ds_channels; i < hdspm->ss_channels; ++i) {
2852 if (hdspm->system_sample_rate > 48000) {
2853 hdspm->playback_mixer_ctls[i]->vd[0].access =
2854 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
2855 SNDRV_CTL_ELEM_ACCESS_READ |
2856 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
2857 } else {
2858 hdspm->playback_mixer_ctls[i]->vd[0].access =
2859 SNDRV_CTL_ELEM_ACCESS_READWRITE |
2860 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
2861 }
2862 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
2863 SNDRV_CTL_EVENT_MASK_INFO,
2864 &hdspm->playback_mixer_ctls[i]->id);
2865 }
2866
2867 return 0;
2868}
2869
2870
Takashi Iwai98274f02005-11-17 14:52:34 +01002871static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002872{
2873 unsigned int idx, limit;
2874 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01002875 struct snd_kcontrol *kctl;
Takashi Iwai763f3562005-06-03 11:25:34 +02002876
2877 /* add control list first */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002878 if (hdspm->is_aes32) {
2879 struct snd_kcontrol_new aes_sync_ctl =
2880 HDSPM_AES_SYNC_CHECK("AES Lock Status", 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02002881
Remy Bruno3cee5a62006-10-16 12:46:32 +02002882 for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_aes32);
2883 idx++) {
2884 err = snd_ctl_add(card,
2885 snd_ctl_new1(&snd_hdspm_controls_aes32[idx],
2886 hdspm));
2887 if (err < 0)
2888 return err;
2889 }
2890 for (idx = 1; idx <= 8; idx++) {
2891 aes_sync_ctl.index = idx;
2892 err = snd_ctl_add(card,
2893 snd_ctl_new1(&aes_sync_ctl, hdspm));
2894 if (err < 0)
2895 return err;
2896 }
2897 } else {
2898 for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_madi);
2899 idx++) {
2900 err = snd_ctl_add(card,
2901 snd_ctl_new1(&snd_hdspm_controls_madi[idx],
2902 hdspm));
2903 if (err < 0)
2904 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02002905 }
2906 }
2907
2908 /* Channel playback mixer as default control
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002909 Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders,
2910 thats too * big for any alsamixer they are accesible via special
2911 IOCTL on hwdep and the mixer 2dimensional mixer control
2912 */
Takashi Iwai763f3562005-06-03 11:25:34 +02002913
2914 snd_hdspm_playback_mixer.name = "Chn";
2915 limit = HDSPM_MAX_CHANNELS;
2916
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002917 /* The index values are one greater than the channel ID so that
2918 * alsamixer will display them correctly. We want to use the index
2919 * for fast lookup of the relevant channel, but if we use it at all,
2920 * most ALSA software does the wrong thing with it ...
Takashi Iwai763f3562005-06-03 11:25:34 +02002921 */
2922
2923 for (idx = 0; idx < limit; ++idx) {
2924 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002925 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
2926 err = snd_ctl_add(card, kctl);
2927 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02002928 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02002929 hdspm->playback_mixer_ctls[idx] = kctl;
2930 }
2931
2932 return 0;
2933}
2934
2935/*------------------------------------------------------------
2936 /proc interface
2937 ------------------------------------------------------------*/
2938
2939static void
Remy Bruno3cee5a62006-10-16 12:46:32 +02002940snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
2941 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02002942{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002943 struct hdspm *hdspm = entry->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02002944 unsigned int status;
2945 unsigned int status2;
2946 char *pref_sync_ref;
2947 char *autosync_ref;
2948 char *system_clock_mode;
2949 char *clock_source;
2950 char *insel;
2951 char *syncref;
2952 int x, x2;
2953
2954 status = hdspm_read(hdspm, HDSPM_statusRegister);
2955 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
2956
2957 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
2958 hdspm->card_name, hdspm->card->number + 1,
2959 hdspm->firmware_rev,
2960 (status2 & HDSPM_version0) |
2961 (status2 & HDSPM_version1) | (status2 &
2962 HDSPM_version2));
2963
2964 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
2965 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
2966
2967 snd_iprintf(buffer, "--- System ---\n");
2968
2969 snd_iprintf(buffer,
2970 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
2971 status & HDSPM_audioIRQPending,
2972 (status & HDSPM_midi0IRQPending) ? 1 : 0,
2973 (status & HDSPM_midi1IRQPending) ? 1 : 0,
2974 hdspm->irq_count);
2975 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002976 "HW pointer: id = %d, rawptr = %d (%d->%d) "
2977 "estimated= %ld (bytes)\n",
Takashi Iwai763f3562005-06-03 11:25:34 +02002978 ((status & HDSPM_BufferID) ? 1 : 0),
2979 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002980 (status & HDSPM_BufferPositionMask) %
2981 (2 * (int)hdspm->period_bytes),
2982 ((status & HDSPM_BufferPositionMask) - 64) %
2983 (2 * (int)hdspm->period_bytes),
Takashi Iwai763f3562005-06-03 11:25:34 +02002984 (long) hdspm_hw_pointer(hdspm) * 4);
2985
2986 snd_iprintf(buffer,
2987 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
2988 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
2989 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
2990 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
2991 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
2992 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002993 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
2994 "status2=0x%x\n",
Takashi Iwai763f3562005-06-03 11:25:34 +02002995 hdspm->control_register, hdspm->control2_register,
2996 status, status2);
2997
2998 snd_iprintf(buffer, "--- Settings ---\n");
2999
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003000 x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
3001 HDSPM_LatencyMask));
Takashi Iwai763f3562005-06-03 11:25:34 +02003002
3003 snd_iprintf(buffer,
3004 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
3005 x, (unsigned long) hdspm->period_bytes);
3006
3007 snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003008 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off",
Takashi Iwai763f3562005-06-03 11:25:34 +02003009 (hdspm->precise_ptr) ? "on" : "off");
3010
3011 switch (hdspm->control_register & HDSPM_InputMask) {
3012 case HDSPM_InputOptical:
3013 insel = "Optical";
3014 break;
3015 case HDSPM_InputCoaxial:
3016 insel = "Coaxial";
3017 break;
3018 default:
3019 insel = "Unkown";
3020 }
3021
3022 switch (hdspm->control_register & HDSPM_SyncRefMask) {
3023 case HDSPM_SyncRef_Word:
3024 syncref = "WordClock";
3025 break;
3026 case HDSPM_SyncRef_MADI:
3027 syncref = "MADI";
3028 break;
3029 default:
3030 syncref = "Unkown";
3031 }
3032 snd_iprintf(buffer, "Inputsel = %s, SyncRef = %s\n", insel,
3033 syncref);
3034
3035 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003036 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
3037 "Auto Input %s\n",
Takashi Iwai763f3562005-06-03 11:25:34 +02003038 (hdspm->
3039 control_register & HDSPM_clr_tms) ? "on" : "off",
3040 (hdspm->
3041 control_register & HDSPM_TX_64ch) ? "64" : "56",
3042 (hdspm->
3043 control_register & HDSPM_AutoInp) ? "on" : "off");
3044
3045 switch (hdspm_clock_source(hdspm)) {
3046 case HDSPM_CLOCK_SOURCE_AUTOSYNC:
3047 clock_source = "AutoSync";
3048 break;
3049 case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
3050 clock_source = "Internal 32 kHz";
3051 break;
3052 case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
3053 clock_source = "Internal 44.1 kHz";
3054 break;
3055 case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
3056 clock_source = "Internal 48 kHz";
3057 break;
3058 case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
3059 clock_source = "Internal 64 kHz";
3060 break;
3061 case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
3062 clock_source = "Internal 88.2 kHz";
3063 break;
3064 case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
3065 clock_source = "Internal 96 kHz";
3066 break;
3067 default:
3068 clock_source = "Error";
3069 }
3070 snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003071 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Takashi Iwai763f3562005-06-03 11:25:34 +02003072 system_clock_mode = "Slave";
Remy Bruno3cee5a62006-10-16 12:46:32 +02003073 else
Takashi Iwai763f3562005-06-03 11:25:34 +02003074 system_clock_mode = "Master";
Takashi Iwai763f3562005-06-03 11:25:34 +02003075 snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
3076
3077 switch (hdspm_pref_sync_ref(hdspm)) {
3078 case HDSPM_SYNC_FROM_WORD:
3079 pref_sync_ref = "Word Clock";
3080 break;
3081 case HDSPM_SYNC_FROM_MADI:
3082 pref_sync_ref = "MADI Sync";
3083 break;
3084 default:
3085 pref_sync_ref = "XXXX Clock";
3086 break;
3087 }
3088 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
3089 pref_sync_ref);
3090
3091 snd_iprintf(buffer, "System Clock Frequency: %d\n",
3092 hdspm->system_sample_rate);
3093
3094
3095 snd_iprintf(buffer, "--- Status:\n");
3096
3097 x = status & HDSPM_madiSync;
3098 x2 = status2 & HDSPM_wcSync;
3099
3100 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
3101 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
3102 "NoLock",
3103 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
3104 "NoLock");
3105
3106 switch (hdspm_autosync_ref(hdspm)) {
3107 case HDSPM_AUTOSYNC_FROM_WORD:
3108 autosync_ref = "Word Clock";
3109 break;
3110 case HDSPM_AUTOSYNC_FROM_MADI:
3111 autosync_ref = "MADI Sync";
3112 break;
3113 case HDSPM_AUTOSYNC_FROM_NONE:
3114 autosync_ref = "Input not valid";
3115 break;
3116 default:
3117 autosync_ref = "---";
3118 break;
3119 }
3120 snd_iprintf(buffer,
3121 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
3122 autosync_ref, hdspm_external_sample_rate(hdspm),
3123 (status & HDSPM_madiFreqMask) >> 22,
3124 (status2 & HDSPM_wcFreqMask) >> 5);
3125
3126 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
3127 (status & HDSPM_AB_int) ? "Coax" : "Optical",
3128 (status & HDSPM_RX_64ch) ? "64 channels" :
3129 "56 channels");
3130
3131 snd_iprintf(buffer, "\n");
3132}
3133
Remy Bruno3cee5a62006-10-16 12:46:32 +02003134static void
3135snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
3136 struct snd_info_buffer *buffer)
3137{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003138 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003139 unsigned int status;
3140 unsigned int status2;
3141 unsigned int timecode;
3142 int pref_syncref;
3143 char *autosync_ref;
3144 char *system_clock_mode;
3145 char *clock_source;
3146 int x;
3147
3148 status = hdspm_read(hdspm, HDSPM_statusRegister);
3149 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3150 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
3151
3152 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
3153 hdspm->card_name, hdspm->card->number + 1,
3154 hdspm->firmware_rev);
3155
3156 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
3157 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
3158
3159 snd_iprintf(buffer, "--- System ---\n");
3160
3161 snd_iprintf(buffer,
3162 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
3163 status & HDSPM_audioIRQPending,
3164 (status & HDSPM_midi0IRQPending) ? 1 : 0,
3165 (status & HDSPM_midi1IRQPending) ? 1 : 0,
3166 hdspm->irq_count);
3167 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003168 "HW pointer: id = %d, rawptr = %d (%d->%d) "
3169 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02003170 ((status & HDSPM_BufferID) ? 1 : 0),
3171 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003172 (status & HDSPM_BufferPositionMask) %
3173 (2 * (int)hdspm->period_bytes),
3174 ((status & HDSPM_BufferPositionMask) - 64) %
3175 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02003176 (long) hdspm_hw_pointer(hdspm) * 4);
3177
3178 snd_iprintf(buffer,
3179 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
3180 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
3181 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
3182 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
3183 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
3184 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003185 "Register: ctrl1=0x%x, status1=0x%x, status2=0x%x, "
3186 "timecode=0x%x\n",
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003187 hdspm->control_register,
Remy Bruno3cee5a62006-10-16 12:46:32 +02003188 status, status2, timecode);
3189
3190 snd_iprintf(buffer, "--- Settings ---\n");
3191
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003192 x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
3193 HDSPM_LatencyMask));
Remy Bruno3cee5a62006-10-16 12:46:32 +02003194
3195 snd_iprintf(buffer,
3196 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
3197 x, (unsigned long) hdspm->period_bytes);
3198
3199 snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n",
3200 (hdspm->
3201 control_register & HDSPM_LineOut) ? "on " : "off",
3202 (hdspm->precise_ptr) ? "on" : "off");
3203
3204 snd_iprintf(buffer,
3205 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
3206 (hdspm->
3207 control_register & HDSPM_clr_tms) ? "on" : "off",
3208 (hdspm->
3209 control_register & HDSPM_Emphasis) ? "on" : "off",
3210 (hdspm->
3211 control_register & HDSPM_Dolby) ? "on" : "off");
3212
3213 switch (hdspm_clock_source(hdspm)) {
3214 case HDSPM_CLOCK_SOURCE_AUTOSYNC:
3215 clock_source = "AutoSync";
3216 break;
3217 case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
3218 clock_source = "Internal 32 kHz";
3219 break;
3220 case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
3221 clock_source = "Internal 44.1 kHz";
3222 break;
3223 case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
3224 clock_source = "Internal 48 kHz";
3225 break;
3226 case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
3227 clock_source = "Internal 64 kHz";
3228 break;
3229 case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
3230 clock_source = "Internal 88.2 kHz";
3231 break;
3232 case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
3233 clock_source = "Internal 96 kHz";
3234 break;
3235 case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
3236 clock_source = "Internal 128 kHz";
3237 break;
3238 case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
3239 clock_source = "Internal 176.4 kHz";
3240 break;
3241 case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
3242 clock_source = "Internal 192 kHz";
3243 break;
3244 default:
3245 clock_source = "Error";
3246 }
3247 snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
3248 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
3249 system_clock_mode = "Slave";
3250 else
3251 system_clock_mode = "Master";
3252 snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
3253
3254 pref_syncref = hdspm_pref_sync_ref(hdspm);
3255 if (pref_syncref == 0)
3256 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
3257 else
3258 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
3259 pref_syncref);
3260
3261 snd_iprintf(buffer, "System Clock Frequency: %d\n",
3262 hdspm->system_sample_rate);
3263
3264 snd_iprintf(buffer, "Double speed: %s\n",
3265 hdspm->control_register & HDSPM_DS_DoubleWire?
3266 "Double wire" : "Single wire");
3267 snd_iprintf(buffer, "Quad speed: %s\n",
3268 hdspm->control_register & HDSPM_QS_DoubleWire?
3269 "Double wire" :
3270 hdspm->control_register & HDSPM_QS_QuadWire?
3271 "Quad wire" : "Single wire");
3272
3273 snd_iprintf(buffer, "--- Status:\n");
3274
3275 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003276 (status & HDSPM_AES32_wcLock)? "Sync " : "No Lock",
3277 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02003278
3279 for (x = 0; x < 8; x++) {
3280 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003281 x+1,
3282 (status2 & (HDSPM_LockAES >> x)) ?
3283 "Sync ": "No Lock",
3284 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02003285 }
3286
3287 switch (hdspm_autosync_ref(hdspm)) {
3288 case HDSPM_AES32_AUTOSYNC_FROM_NONE: autosync_ref="None"; break;
3289 case HDSPM_AES32_AUTOSYNC_FROM_WORD: autosync_ref="Word Clock"; break;
3290 case HDSPM_AES32_AUTOSYNC_FROM_AES1: autosync_ref="AES1"; break;
3291 case HDSPM_AES32_AUTOSYNC_FROM_AES2: autosync_ref="AES2"; break;
3292 case HDSPM_AES32_AUTOSYNC_FROM_AES3: autosync_ref="AES3"; break;
3293 case HDSPM_AES32_AUTOSYNC_FROM_AES4: autosync_ref="AES4"; break;
3294 case HDSPM_AES32_AUTOSYNC_FROM_AES5: autosync_ref="AES5"; break;
3295 case HDSPM_AES32_AUTOSYNC_FROM_AES6: autosync_ref="AES6"; break;
3296 case HDSPM_AES32_AUTOSYNC_FROM_AES7: autosync_ref="AES7"; break;
3297 case HDSPM_AES32_AUTOSYNC_FROM_AES8: autosync_ref="AES8"; break;
3298 default: autosync_ref = "---"; break;
3299 }
3300 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
3301
3302 snd_iprintf(buffer, "\n");
3303}
3304
3305#ifdef CONFIG_SND_DEBUG
3306static void
3307snd_hdspm_proc_read_debug(struct snd_info_entry * entry,
3308 struct snd_info_buffer *buffer)
3309{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003310 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003311
3312 int j,i;
3313
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003314 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02003315 snd_iprintf(buffer, "0x%08X: ", i);
3316 for (j = 0; j < 16; j += 4)
3317 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
3318 snd_iprintf(buffer, "\n");
3319 }
3320}
3321#endif
3322
3323
3324
Takashi Iwai98274f02005-11-17 14:52:34 +01003325static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003326{
Takashi Iwai98274f02005-11-17 14:52:34 +01003327 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02003328
3329 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry))
Takashi Iwaibf850202006-04-28 15:13:41 +02003330 snd_info_set_text_ops(entry, hdspm,
Remy Bruno3cee5a62006-10-16 12:46:32 +02003331 hdspm->is_aes32 ?
3332 snd_hdspm_proc_read_aes32 :
3333 snd_hdspm_proc_read_madi);
3334#ifdef CONFIG_SND_DEBUG
3335 /* debug file to read all hdspm registers */
3336 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
3337 snd_info_set_text_ops(entry, hdspm,
3338 snd_hdspm_proc_read_debug);
3339#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02003340}
3341
3342/*------------------------------------------------------------
3343 hdspm intitialize
3344 ------------------------------------------------------------*/
3345
Takashi Iwai98274f02005-11-17 14:52:34 +01003346static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003347{
3348 unsigned int i;
3349
3350 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01003351 hold it (e.g. during module initialization).
Takashi Iwai763f3562005-06-03 11:25:34 +02003352 */
3353
3354 /* set defaults: */
3355
Remy Bruno3cee5a62006-10-16 12:46:32 +02003356 if (hdspm->is_aes32)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003357 hdspm->control_register =
3358 HDSPM_ClockModeMaster | /* Master Cloack Mode on */
3359 hdspm_encode_latency(7) | /* latency maximum =
3360 * 8192 samples
3361 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02003362 HDSPM_SyncRef0 | /* AES1 is syncclock */
3363 HDSPM_LineOut | /* Analog output in */
3364 HDSPM_Professional; /* Professional mode */
3365 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003366 hdspm->control_register =
3367 HDSPM_ClockModeMaster | /* Master Cloack Mode on */
3368 hdspm_encode_latency(7) | /* latency maximum =
3369 * 8192 samples
3370 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02003371 HDSPM_InputCoaxial | /* Input Coax not Optical */
3372 HDSPM_SyncRef_MADI | /* Madi is syncclock */
3373 HDSPM_LineOut | /* Analog output in */
3374 HDSPM_TX_64ch | /* transmit in 64ch mode */
3375 HDSPM_AutoInp; /* AutoInput chossing (takeover) */
Takashi Iwai763f3562005-06-03 11:25:34 +02003376
3377 /* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */
3378 /* ! HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */
3379 /* ! HDSPM_clr_tms = do not clear bits in track marks */
3380
3381 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3382
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003383 if (!hdspm->is_aes32) {
3384 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02003385#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003386 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02003387#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003388 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02003389#endif
3390
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003391 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
3392 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003393 hdspm_compute_period_size(hdspm);
3394
3395 /* silence everything */
3396
3397 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
3398
3399 if (line_outs_monitor[hdspm->dev]) {
3400
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003401 snd_printk(KERN_INFO "HDSPM: "
3402 "sending all playback streams to line outs.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02003403
3404 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) {
3405 if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN))
3406 return -EIO;
3407 }
3408 }
3409
3410 /* set a default rate so that the channel map is set up. */
3411 hdspm->channel_map = channel_map_madi_ss;
3412 hdspm_set_rate(hdspm, 44100, 1);
3413
3414 return 0;
3415}
3416
3417
3418/*------------------------------------------------------------
Joe Perches561de312007-12-18 13:13:47 +01003419 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02003420 ------------------------------------------------------------*/
3421
David Howells7d12e782006-10-05 14:55:46 +01003422static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02003423{
Takashi Iwai98274f02005-11-17 14:52:34 +01003424 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02003425 unsigned int status;
3426 int audio;
3427 int midi0;
3428 int midi1;
3429 unsigned int midi0status;
3430 unsigned int midi1status;
3431 int schedule = 0;
3432
3433 status = hdspm_read(hdspm, HDSPM_statusRegister);
3434
3435 audio = status & HDSPM_audioIRQPending;
3436 midi0 = status & HDSPM_midi0IRQPending;
3437 midi1 = status & HDSPM_midi1IRQPending;
3438
3439 if (!audio && !midi0 && !midi1)
3440 return IRQ_NONE;
3441
3442 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
3443 hdspm->irq_count++;
3444
3445 midi0status = hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff;
3446 midi1status = hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff;
3447
3448 if (audio) {
3449
3450 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003451 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003452
3453 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003454 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003455 }
3456
3457 if (midi0 && midi0status) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003458 /* we disable interrupts for this input until processing
3459 * is done
3460 */
Takashi Iwai763f3562005-06-03 11:25:34 +02003461 hdspm->control_register &= ~HDSPM_Midi0InterruptEnable;
3462 hdspm_write(hdspm, HDSPM_controlRegister,
3463 hdspm->control_register);
3464 hdspm->midi[0].pending = 1;
3465 schedule = 1;
3466 }
3467 if (midi1 && midi1status) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003468 /* we disable interrupts for this input until processing
3469 * is done
3470 */
Takashi Iwai763f3562005-06-03 11:25:34 +02003471 hdspm->control_register &= ~HDSPM_Midi1InterruptEnable;
3472 hdspm_write(hdspm, HDSPM_controlRegister,
3473 hdspm->control_register);
3474 hdspm->midi[1].pending = 1;
3475 schedule = 1;
3476 }
3477 if (schedule)
3478 tasklet_hi_schedule(&hdspm->midi_tasklet);
3479 return IRQ_HANDLED;
3480}
3481
3482/*------------------------------------------------------------
3483 pcm interface
3484 ------------------------------------------------------------*/
3485
3486
Takashi Iwai98274f02005-11-17 14:52:34 +01003487static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream *
Takashi Iwai763f3562005-06-03 11:25:34 +02003488 substream)
3489{
Takashi Iwai98274f02005-11-17 14:52:34 +01003490 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003491 return hdspm_hw_pointer(hdspm);
3492}
3493
Takashi Iwai98274f02005-11-17 14:52:34 +01003494static char *hdspm_channel_buffer_location(struct hdspm * hdspm,
Takashi Iwai763f3562005-06-03 11:25:34 +02003495 int stream, int channel)
3496{
3497 int mapped_channel;
3498
3499 snd_assert(channel >= 0
3500 || channel < HDSPM_MAX_CHANNELS, return NULL);
3501
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003502 mapped_channel = hdspm->channel_map[channel];
3503 if (mapped_channel < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02003504 return NULL;
3505
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003506 if (stream == SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02003507 return hdspm->capture_buffer +
3508 mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003509 else
Takashi Iwai763f3562005-06-03 11:25:34 +02003510 return hdspm->playback_buffer +
3511 mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02003512}
3513
3514
3515/* dont know why need it ??? */
Takashi Iwai98274f02005-11-17 14:52:34 +01003516static int snd_hdspm_playback_copy(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02003517 int channel, snd_pcm_uframes_t pos,
3518 void __user *src, snd_pcm_uframes_t count)
3519{
Takashi Iwai98274f02005-11-17 14:52:34 +01003520 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003521 char *channel_buf;
3522
3523 snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
3524 return -EINVAL);
3525
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003526 channel_buf =
3527 hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
3528 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003529
3530 snd_assert(channel_buf != NULL, return -EIO);
3531
3532 return copy_from_user(channel_buf + pos * 4, src, count * 4);
3533}
3534
Takashi Iwai98274f02005-11-17 14:52:34 +01003535static int snd_hdspm_capture_copy(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02003536 int channel, snd_pcm_uframes_t pos,
3537 void __user *dst, snd_pcm_uframes_t count)
3538{
Takashi Iwai98274f02005-11-17 14:52:34 +01003539 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003540 char *channel_buf;
3541
3542 snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
3543 return -EINVAL);
3544
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003545 channel_buf =
3546 hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
3547 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003548 snd_assert(channel_buf != NULL, return -EIO);
3549 return copy_to_user(dst, channel_buf + pos * 4, count * 4);
3550}
3551
Takashi Iwai98274f02005-11-17 14:52:34 +01003552static int snd_hdspm_hw_silence(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02003553 int channel, snd_pcm_uframes_t pos,
3554 snd_pcm_uframes_t count)
3555{
Takashi Iwai98274f02005-11-17 14:52:34 +01003556 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003557 char *channel_buf;
3558
3559 channel_buf =
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003560 hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
3561 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003562 snd_assert(channel_buf != NULL, return -EIO);
3563 memset(channel_buf + pos * 4, 0, count * 4);
3564 return 0;
3565}
3566
Takashi Iwai98274f02005-11-17 14:52:34 +01003567static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003568{
Takashi Iwai98274f02005-11-17 14:52:34 +01003569 struct snd_pcm_runtime *runtime = substream->runtime;
3570 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
3571 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02003572
3573 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3574 other = hdspm->capture_substream;
3575 else
3576 other = hdspm->playback_substream;
3577
3578 if (hdspm->running)
3579 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
3580 else
3581 runtime->status->hw_ptr = 0;
3582 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003583 struct snd_pcm_substream *s;
3584 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01003585 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02003586 if (s == other) {
3587 oruntime->status->hw_ptr =
3588 runtime->status->hw_ptr;
3589 break;
3590 }
3591 }
3592 }
3593 return 0;
3594}
3595
Takashi Iwai98274f02005-11-17 14:52:34 +01003596static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
3597 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02003598{
Takashi Iwai98274f02005-11-17 14:52:34 +01003599 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003600 int err;
3601 int i;
3602 pid_t this_pid;
3603 pid_t other_pid;
3604 struct snd_sg_buf *sgbuf;
3605
3606
3607 spin_lock_irq(&hdspm->lock);
3608
3609 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3610 this_pid = hdspm->playback_pid;
3611 other_pid = hdspm->capture_pid;
3612 } else {
3613 this_pid = hdspm->capture_pid;
3614 other_pid = hdspm->playback_pid;
3615 }
3616
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003617 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02003618
3619 /* The other stream is open, and not by the same
3620 task as this one. Make sure that the parameters
3621 that matter are the same.
3622 */
3623
3624 if (params_rate(params) != hdspm->system_sample_rate) {
3625 spin_unlock_irq(&hdspm->lock);
3626 _snd_pcm_hw_param_setempty(params,
3627 SNDRV_PCM_HW_PARAM_RATE);
3628 return -EBUSY;
3629 }
3630
3631 if (params_period_size(params) != hdspm->period_bytes / 4) {
3632 spin_unlock_irq(&hdspm->lock);
3633 _snd_pcm_hw_param_setempty(params,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003634 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02003635 return -EBUSY;
3636 }
3637
3638 }
3639 /* We're fine. */
3640 spin_unlock_irq(&hdspm->lock);
3641
3642 /* how to make sure that the rate matches an externally-set one ? */
3643
3644 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003645 err = hdspm_set_rate(hdspm, params_rate(params), 0);
3646 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02003647 spin_unlock_irq(&hdspm->lock);
3648 _snd_pcm_hw_param_setempty(params,
3649 SNDRV_PCM_HW_PARAM_RATE);
3650 return err;
3651 }
3652 spin_unlock_irq(&hdspm->lock);
3653
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003654 err = hdspm_set_interrupt_interval(hdspm,
3655 params_period_size(params));
3656 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02003657 _snd_pcm_hw_param_setempty(params,
3658 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
3659 return err;
3660 }
3661
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003662 /* Memory allocation, takashi's method, dont know if we should
3663 * spinlock
3664 */
Takashi Iwai763f3562005-06-03 11:25:34 +02003665 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003666 /* Update for MADI rev 204: we need to allocate for all channels,
3667 * otherwise it doesn't work at 96kHz */
Takashi Iwai763f3562005-06-03 11:25:34 +02003668 err =
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003669 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
Takashi Iwai763f3562005-06-03 11:25:34 +02003670 if (err < 0)
3671 return err;
3672
3673 sgbuf = snd_pcm_substream_sgbuf(substream);
3674
3675 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3676
3677 hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferOut,
3678 params_channels(params));
3679
3680 for (i = 0; i < params_channels(params); ++i)
3681 snd_hdspm_enable_out(hdspm, i, 1);
3682
3683 hdspm->playback_buffer =
3684 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01003685 snd_printdd("Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02003686 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02003687 } else {
3688 hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferIn,
3689 params_channels(params));
3690
3691 for (i = 0; i < params_channels(params); ++i)
3692 snd_hdspm_enable_in(hdspm, i, 1);
3693
3694 hdspm->capture_buffer =
3695 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01003696 snd_printdd("Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02003697 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02003698 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02003699 /*
3700 snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
3701 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
3702 "playback" : "capture",
3703 snd_pcm_sgbuf_get_addr(sgbuf, 0));
3704 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003705 /*
3706 snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
3707 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
3708 "playback" : "capture",
3709 params_rate(params), params_channels(params),
3710 params_buffer_size(params));
3711 */
Takashi Iwai763f3562005-06-03 11:25:34 +02003712 return 0;
3713}
3714
Takashi Iwai98274f02005-11-17 14:52:34 +01003715static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003716{
3717 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01003718 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003719
3720 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3721
3722 /* params_channels(params) should be enough,
3723 but to get sure in case of error */
3724 for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
3725 snd_hdspm_enable_out(hdspm, i, 0);
3726
3727 hdspm->playback_buffer = NULL;
3728 } else {
3729 for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
3730 snd_hdspm_enable_in(hdspm, i, 0);
3731
3732 hdspm->capture_buffer = NULL;
3733
3734 }
3735
3736 snd_pcm_lib_free_pages(substream);
3737
3738 return 0;
3739}
3740
Takashi Iwai98274f02005-11-17 14:52:34 +01003741static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
3742 struct snd_pcm_channel_info * info)
Takashi Iwai763f3562005-06-03 11:25:34 +02003743{
Takashi Iwai98274f02005-11-17 14:52:34 +01003744 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003745 int mapped_channel;
3746
3747 snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL);
3748
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003749 mapped_channel = hdspm->channel_map[info->channel];
3750 if (mapped_channel < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02003751 return -EINVAL;
3752
3753 info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
3754 info->first = 0;
3755 info->step = 32;
3756 return 0;
3757}
3758
Takashi Iwai98274f02005-11-17 14:52:34 +01003759static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02003760 unsigned int cmd, void *arg)
3761{
3762 switch (cmd) {
3763 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003764 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003765
3766 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003767 {
3768 struct snd_pcm_channel_info *info = arg;
3769 return snd_hdspm_channel_info(substream, info);
3770 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003771 default:
3772 break;
3773 }
3774
3775 return snd_pcm_lib_ioctl(substream, cmd, arg);
3776}
3777
Takashi Iwai98274f02005-11-17 14:52:34 +01003778static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02003779{
Takashi Iwai98274f02005-11-17 14:52:34 +01003780 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
3781 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02003782 int running;
3783
3784 spin_lock(&hdspm->lock);
3785 running = hdspm->running;
3786 switch (cmd) {
3787 case SNDRV_PCM_TRIGGER_START:
3788 running |= 1 << substream->stream;
3789 break;
3790 case SNDRV_PCM_TRIGGER_STOP:
3791 running &= ~(1 << substream->stream);
3792 break;
3793 default:
3794 snd_BUG();
3795 spin_unlock(&hdspm->lock);
3796 return -EINVAL;
3797 }
3798 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3799 other = hdspm->capture_substream;
3800 else
3801 other = hdspm->playback_substream;
3802
3803 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003804 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01003805 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02003806 if (s == other) {
3807 snd_pcm_trigger_done(s, substream);
3808 if (cmd == SNDRV_PCM_TRIGGER_START)
3809 running |= 1 << s->stream;
3810 else
3811 running &= ~(1 << s->stream);
3812 goto _ok;
3813 }
3814 }
3815 if (cmd == SNDRV_PCM_TRIGGER_START) {
3816 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
3817 && substream->stream ==
3818 SNDRV_PCM_STREAM_CAPTURE)
3819 hdspm_silence_playback(hdspm);
3820 } else {
3821 if (running &&
3822 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3823 hdspm_silence_playback(hdspm);
3824 }
3825 } else {
3826 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
3827 hdspm_silence_playback(hdspm);
3828 }
3829 _ok:
3830 snd_pcm_trigger_done(substream, substream);
3831 if (!hdspm->running && running)
3832 hdspm_start_audio(hdspm);
3833 else if (hdspm->running && !running)
3834 hdspm_stop_audio(hdspm);
3835 hdspm->running = running;
3836 spin_unlock(&hdspm->lock);
3837
3838 return 0;
3839}
3840
Takashi Iwai98274f02005-11-17 14:52:34 +01003841static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003842{
3843 return 0;
3844}
3845
3846static unsigned int period_sizes[] =
3847 { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
3848
Takashi Iwai98274f02005-11-17 14:52:34 +01003849static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003850 .info = (SNDRV_PCM_INFO_MMAP |
3851 SNDRV_PCM_INFO_MMAP_VALID |
3852 SNDRV_PCM_INFO_NONINTERLEAVED |
3853 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
3854 .formats = SNDRV_PCM_FMTBIT_S32_LE,
3855 .rates = (SNDRV_PCM_RATE_32000 |
3856 SNDRV_PCM_RATE_44100 |
3857 SNDRV_PCM_RATE_48000 |
3858 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02003859 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
3860 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02003861 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02003862 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02003863 .channels_min = 1,
3864 .channels_max = HDSPM_MAX_CHANNELS,
3865 .buffer_bytes_max =
3866 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
3867 .period_bytes_min = (64 * 4),
3868 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
3869 .periods_min = 2,
3870 .periods_max = 2,
3871 .fifo_size = 0
3872};
3873
Takashi Iwai98274f02005-11-17 14:52:34 +01003874static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003875 .info = (SNDRV_PCM_INFO_MMAP |
3876 SNDRV_PCM_INFO_MMAP_VALID |
3877 SNDRV_PCM_INFO_NONINTERLEAVED |
3878 SNDRV_PCM_INFO_SYNC_START),
3879 .formats = SNDRV_PCM_FMTBIT_S32_LE,
3880 .rates = (SNDRV_PCM_RATE_32000 |
3881 SNDRV_PCM_RATE_44100 |
3882 SNDRV_PCM_RATE_48000 |
3883 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02003884 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
3885 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02003886 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02003887 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02003888 .channels_min = 1,
3889 .channels_max = HDSPM_MAX_CHANNELS,
3890 .buffer_bytes_max =
3891 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
3892 .period_bytes_min = (64 * 4),
3893 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
3894 .periods_min = 2,
3895 .periods_max = 2,
3896 .fifo_size = 0
3897};
3898
Takashi Iwai98274f02005-11-17 14:52:34 +01003899static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003900 .count = ARRAY_SIZE(period_sizes),
3901 .list = period_sizes,
3902 .mask = 0
3903};
3904
3905
Takashi Iwai98274f02005-11-17 14:52:34 +01003906static int snd_hdspm_hw_rule_channels_rate(struct snd_pcm_hw_params *params,
3907 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02003908{
Takashi Iwai98274f02005-11-17 14:52:34 +01003909 struct hdspm *hdspm = rule->private;
3910 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02003911 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01003912 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02003913 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
3914
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003915 if (r->min > 48000 && r->max <= 96000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003916 struct snd_interval t = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003917 .min = hdspm->ds_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02003918 .max = hdspm->ds_channels,
3919 .integer = 1,
3920 };
3921 return snd_interval_refine(c, &t);
3922 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003923 struct snd_interval t = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003924 .min = hdspm->ss_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02003925 .max = hdspm->ss_channels,
3926 .integer = 1,
3927 };
3928 return snd_interval_refine(c, &t);
3929 }
3930 return 0;
3931}
3932
Takashi Iwai98274f02005-11-17 14:52:34 +01003933static int snd_hdspm_hw_rule_rate_channels(struct snd_pcm_hw_params *params,
3934 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02003935{
Takashi Iwai98274f02005-11-17 14:52:34 +01003936 struct hdspm *hdspm = rule->private;
3937 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02003938 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01003939 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02003940 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
3941
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003942 if (c->min >= hdspm->ss_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003943 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003944 .min = 32000,
3945 .max = 48000,
3946 .integer = 1,
3947 };
3948 return snd_interval_refine(r, &t);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003949 } else if (c->max <= hdspm->ds_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003950 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003951 .min = 64000,
3952 .max = 96000,
3953 .integer = 1,
3954 };
3955
3956 return snd_interval_refine(r, &t);
3957 }
3958 return 0;
3959}
3960
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003961static int snd_hdspm_hw_rule_channels(struct snd_pcm_hw_params *params,
3962 struct snd_pcm_hw_rule *rule)
3963{
3964 unsigned int list[3];
3965 struct hdspm *hdspm = rule->private;
3966 struct snd_interval *c = hw_param_interval(params,
3967 SNDRV_PCM_HW_PARAM_CHANNELS);
3968 if (hdspm->is_aes32) {
3969 list[0] = hdspm->qs_channels;
3970 list[1] = hdspm->ds_channels;
3971 list[2] = hdspm->ss_channels;
3972 return snd_interval_list(c, 3, list, 0);
3973 } else {
3974 list[0] = hdspm->ds_channels;
3975 list[1] = hdspm->ss_channels;
3976 return snd_interval_list(c, 2, list, 0);
3977 }
3978}
3979
3980
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003981static unsigned int hdspm_aes32_sample_rates[] = {
3982 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
3983};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003984
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003985static struct snd_pcm_hw_constraint_list
3986hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01003987 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
3988 .list = hdspm_aes32_sample_rates,
3989 .mask = 0
3990};
3991
Takashi Iwai98274f02005-11-17 14:52:34 +01003992static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003993{
Takashi Iwai98274f02005-11-17 14:52:34 +01003994 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
3995 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02003996
Takashi Iwai763f3562005-06-03 11:25:34 +02003997 spin_lock_irq(&hdspm->lock);
3998
3999 snd_pcm_set_sync(substream);
4000
4001 runtime->hw = snd_hdspm_playback_subinfo;
4002
4003 if (hdspm->capture_substream == NULL)
4004 hdspm_stop_audio(hdspm);
4005
4006 hdspm->playback_pid = current->pid;
4007 hdspm->playback_substream = substream;
4008
4009 spin_unlock_irq(&hdspm->lock);
4010
4011 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4012
4013 snd_pcm_hw_constraint_list(runtime, 0,
4014 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
4015 &hw_constraints_period_sizes);
4016
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004017 if (hdspm->is_aes32) {
4018 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4019 &hdspm_hw_constraints_aes32_sample_rates);
4020 } else {
4021 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4022 snd_hdspm_hw_rule_channels, hdspm,
4023 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4024 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4025 snd_hdspm_hw_rule_channels_rate, hdspm,
4026 SNDRV_PCM_HW_PARAM_RATE, -1);
Takashi Iwai763f3562005-06-03 11:25:34 +02004027
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004028 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4029 snd_hdspm_hw_rule_rate_channels, hdspm,
4030 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4031 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004032 return 0;
4033}
4034
Takashi Iwai98274f02005-11-17 14:52:34 +01004035static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02004036{
Takashi Iwai98274f02005-11-17 14:52:34 +01004037 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02004038
4039 spin_lock_irq(&hdspm->lock);
4040
4041 hdspm->playback_pid = -1;
4042 hdspm->playback_substream = NULL;
4043
4044 spin_unlock_irq(&hdspm->lock);
4045
4046 return 0;
4047}
4048
4049
Takashi Iwai98274f02005-11-17 14:52:34 +01004050static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02004051{
Takashi Iwai98274f02005-11-17 14:52:34 +01004052 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
4053 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02004054
4055 spin_lock_irq(&hdspm->lock);
4056 snd_pcm_set_sync(substream);
4057 runtime->hw = snd_hdspm_capture_subinfo;
4058
4059 if (hdspm->playback_substream == NULL)
4060 hdspm_stop_audio(hdspm);
4061
4062 hdspm->capture_pid = current->pid;
4063 hdspm->capture_substream = substream;
4064
4065 spin_unlock_irq(&hdspm->lock);
4066
4067 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4068 snd_pcm_hw_constraint_list(runtime, 0,
4069 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
4070 &hw_constraints_period_sizes);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004071 if (hdspm->is_aes32) {
4072 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4073 &hdspm_hw_constraints_aes32_sample_rates);
4074 } else {
4075 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4076 snd_hdspm_hw_rule_channels, hdspm,
4077 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4078 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
4079 snd_hdspm_hw_rule_channels_rate, hdspm,
4080 SNDRV_PCM_HW_PARAM_RATE, -1);
Takashi Iwai763f3562005-06-03 11:25:34 +02004081
Remy Brunoffb2c3c2007-03-07 19:08:46 +01004082 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
4083 snd_hdspm_hw_rule_rate_channels, hdspm,
4084 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
4085 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004086 return 0;
4087}
4088
Takashi Iwai98274f02005-11-17 14:52:34 +01004089static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02004090{
Takashi Iwai98274f02005-11-17 14:52:34 +01004091 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02004092
4093 spin_lock_irq(&hdspm->lock);
4094
4095 hdspm->capture_pid = -1;
4096 hdspm->capture_substream = NULL;
4097
4098 spin_unlock_irq(&hdspm->lock);
4099 return 0;
4100}
4101
Takashi Iwai98274f02005-11-17 14:52:34 +01004102static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep * hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02004103{
4104 /* we have nothing to initialize but the call is required */
4105 return 0;
4106}
4107
4108
Takashi Iwai98274f02005-11-17 14:52:34 +01004109static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
Takashi Iwai763f3562005-06-03 11:25:34 +02004110 unsigned int cmd, unsigned long arg)
4111{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004112 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01004113 struct hdspm_mixer_ioctl mixer;
4114 struct hdspm_config_info info;
4115 struct hdspm_version hdspm_version;
4116 struct hdspm_peak_rms_ioctl rms;
Takashi Iwai763f3562005-06-03 11:25:34 +02004117
4118 switch (cmd) {
4119
Takashi Iwai763f3562005-06-03 11:25:34 +02004120 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
4121 if (copy_from_user(&rms, (void __user *)arg, sizeof(rms)))
4122 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004123 /* maybe there is a chance to memorymap in future
4124 * so dont touch just copy
4125 */
Takashi Iwai763f3562005-06-03 11:25:34 +02004126 if(copy_to_user_fromio((void __user *)rms.peak,
4127 hdspm->iobase+HDSPM_MADI_peakrmsbase,
Takashi Iwai98274f02005-11-17 14:52:34 +01004128 sizeof(struct hdspm_peak_rms)) != 0 )
Takashi Iwai763f3562005-06-03 11:25:34 +02004129 return -EFAULT;
4130
4131 break;
4132
4133
4134 case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO:
4135
4136 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004137 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
4138 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02004139
4140 info.system_sample_rate = hdspm->system_sample_rate;
4141 info.autosync_sample_rate =
4142 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004143 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
4144 info.clock_source = hdspm_clock_source(hdspm);
4145 info.autosync_ref = hdspm_autosync_ref(hdspm);
4146 info.line_out = hdspm_line_out(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02004147 info.passthru = 0;
4148 spin_unlock_irq(&hdspm->lock);
4149 if (copy_to_user((void __user *) arg, &info, sizeof(info)))
4150 return -EFAULT;
4151 break;
4152
4153 case SNDRV_HDSPM_IOCTL_GET_VERSION:
4154 hdspm_version.firmware_rev = hdspm->firmware_rev;
4155 if (copy_to_user((void __user *) arg, &hdspm_version,
4156 sizeof(hdspm_version)))
4157 return -EFAULT;
4158 break;
4159
4160 case SNDRV_HDSPM_IOCTL_GET_MIXER:
4161 if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
4162 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004163 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
4164 sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02004165 return -EFAULT;
4166 break;
4167
4168 default:
4169 return -EINVAL;
4170 }
4171 return 0;
4172}
4173
Takashi Iwai98274f02005-11-17 14:52:34 +01004174static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004175 .open = snd_hdspm_playback_open,
4176 .close = snd_hdspm_playback_release,
4177 .ioctl = snd_hdspm_ioctl,
4178 .hw_params = snd_hdspm_hw_params,
4179 .hw_free = snd_hdspm_hw_free,
4180 .prepare = snd_hdspm_prepare,
4181 .trigger = snd_hdspm_trigger,
4182 .pointer = snd_hdspm_hw_pointer,
4183 .copy = snd_hdspm_playback_copy,
4184 .silence = snd_hdspm_hw_silence,
4185 .page = snd_pcm_sgbuf_ops_page,
4186};
4187
Takashi Iwai98274f02005-11-17 14:52:34 +01004188static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004189 .open = snd_hdspm_capture_open,
4190 .close = snd_hdspm_capture_release,
4191 .ioctl = snd_hdspm_ioctl,
4192 .hw_params = snd_hdspm_hw_params,
4193 .hw_free = snd_hdspm_hw_free,
4194 .prepare = snd_hdspm_prepare,
4195 .trigger = snd_hdspm_trigger,
4196 .pointer = snd_hdspm_hw_pointer,
4197 .copy = snd_hdspm_capture_copy,
4198 .page = snd_pcm_sgbuf_ops_page,
4199};
4200
Takashi Iwai98274f02005-11-17 14:52:34 +01004201static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
4202 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004203{
Takashi Iwai98274f02005-11-17 14:52:34 +01004204 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02004205 int err;
4206
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004207 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
4208 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004209 return err;
4210
4211 hdspm->hwdep = hw;
4212 hw->private_data = hdspm;
4213 strcpy(hw->name, "HDSPM hwdep interface");
4214
4215 hw->ops.open = snd_hdspm_hwdep_dummy_op;
4216 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
4217 hw->ops.release = snd_hdspm_hwdep_dummy_op;
4218
4219 return 0;
4220}
4221
4222
4223/*------------------------------------------------------------
4224 memory interface
4225 ------------------------------------------------------------*/
Takashi Iwai98274f02005-11-17 14:52:34 +01004226static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004227{
4228 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004229 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02004230 size_t wanted;
4231
4232 pcm = hdspm->pcm;
4233
Remy Bruno3cee5a62006-10-16 12:46:32 +02004234 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02004235
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004236 err =
Takashi Iwai763f3562005-06-03 11:25:34 +02004237 snd_pcm_lib_preallocate_pages_for_all(pcm,
4238 SNDRV_DMA_TYPE_DEV_SG,
4239 snd_dma_pci_data(hdspm->pci),
4240 wanted,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004241 wanted);
4242 if (err < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01004243 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02004244
4245 return err;
4246 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01004247 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02004248
4249 return 0;
4250}
4251
Takashi Iwai98274f02005-11-17 14:52:34 +01004252static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
Takashi Iwai763f3562005-06-03 11:25:34 +02004253 unsigned int reg, int channels)
4254{
4255 int i;
4256 for (i = 0; i < (channels * 16); i++)
4257 hdspm_write(hdspm, reg + 4 * i,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004258 snd_pcm_sgbuf_get_addr(sgbuf, (size_t) 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02004259}
4260
4261/* ------------- ALSA Devices ---------------------------- */
Takashi Iwai98274f02005-11-17 14:52:34 +01004262static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
4263 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004264{
Takashi Iwai98274f02005-11-17 14:52:34 +01004265 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02004266 int err;
4267
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004268 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
4269 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004270 return err;
4271
4272 hdspm->pcm = pcm;
4273 pcm->private_data = hdspm;
4274 strcpy(pcm->name, hdspm->card_name);
4275
4276 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
4277 &snd_hdspm_playback_ops);
4278 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
4279 &snd_hdspm_capture_ops);
4280
4281 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
4282
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004283 err = snd_hdspm_preallocate_memory(hdspm);
4284 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004285 return err;
4286
4287 return 0;
4288}
4289
Takashi Iwai98274f02005-11-17 14:52:34 +01004290static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004291{
4292 snd_hdspm_flush_midi_input(hdspm, 0);
4293 snd_hdspm_flush_midi_input(hdspm, 1);
4294}
4295
Takashi Iwai98274f02005-11-17 14:52:34 +01004296static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
4297 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004298{
4299 int err;
4300
4301 snd_printdd("Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004302 err = snd_hdspm_create_pcm(card, hdspm);
4303 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004304 return err;
4305
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004306 err = snd_hdspm_create_midi(card, hdspm, 0);
4307 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004308 return err;
4309
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004310 err = snd_hdspm_create_midi(card, hdspm, 1);
4311 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004312 return err;
4313
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004314 err = snd_hdspm_create_controls(card, hdspm);
4315 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004316 return err;
4317
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004318 err = snd_hdspm_create_hwdep(card, hdspm);
4319 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004320 return err;
4321
4322 snd_printdd("proc init...\n");
4323 snd_hdspm_proc_init(hdspm);
4324
4325 hdspm->system_sample_rate = -1;
4326 hdspm->last_external_sample_rate = -1;
4327 hdspm->last_internal_sample_rate = -1;
4328 hdspm->playback_pid = -1;
4329 hdspm->capture_pid = -1;
4330 hdspm->capture_substream = NULL;
4331 hdspm->playback_substream = NULL;
4332
4333 snd_printdd("Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004334 err = snd_hdspm_set_defaults(hdspm);
4335 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004336 return err;
4337
4338 snd_printdd("Update mixer controls...\n");
4339 hdspm_update_simple_mixer_controls(hdspm);
4340
4341 snd_printdd("Initializeing complete ???\n");
4342
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004343 err = snd_card_register(card);
4344 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004345 snd_printk(KERN_ERR "HDSPM: error registering card\n");
4346 return err;
4347 }
4348
4349 snd_printdd("... yes now\n");
4350
4351 return 0;
4352}
4353
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004354static int __devinit snd_hdspm_create(struct snd_card *card,
4355 struct hdspm *hdspm,
Takashi Iwai763f3562005-06-03 11:25:34 +02004356 int precise_ptr, int enable_monitor)
4357{
4358 struct pci_dev *pci = hdspm->pci;
4359 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004360 unsigned long io_extent;
4361
4362 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02004363
Takashi Iwai763f3562005-06-03 11:25:34 +02004364 spin_lock_init(&hdspm->midi[0].lock);
4365 spin_lock_init(&hdspm->midi[1].lock);
Takashi Iwai763f3562005-06-03 11:25:34 +02004366
4367 hdspm->card = card;
4368
4369 spin_lock_init(&hdspm->lock);
4370
4371 tasklet_init(&hdspm->midi_tasklet,
4372 hdspm_midi_tasklet, (unsigned long) hdspm);
4373
4374 pci_read_config_word(hdspm->pci,
4375 PCI_CLASS_REVISION, &hdspm->firmware_rev);
4376
Remy Bruno3cee5a62006-10-16 12:46:32 +02004377 hdspm->is_aes32 = (hdspm->firmware_rev >= HDSPM_AESREVISION);
4378
Takashi Iwai763f3562005-06-03 11:25:34 +02004379 strcpy(card->mixername, "Xilinx FPGA");
Remy Bruno3cee5a62006-10-16 12:46:32 +02004380 if (hdspm->is_aes32) {
4381 strcpy(card->driver, "HDSPAES32");
4382 hdspm->card_name = "RME HDSPM AES32";
4383 } else {
4384 strcpy(card->driver, "HDSPM");
4385 hdspm->card_name = "RME HDSPM MADI";
4386 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004387
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004388 err = pci_enable_device(pci);
4389 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004390 return err;
4391
4392 pci_set_master(hdspm->pci);
4393
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004394 err = pci_request_regions(pci, "hdspm");
4395 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004396 return err;
4397
4398 hdspm->port = pci_resource_start(pci, 0);
4399 io_extent = pci_resource_len(pci, 0);
4400
4401 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
4402 hdspm->port, hdspm->port + io_extent - 1);
4403
4404
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004405 hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
4406 if (!hdspm->iobase) {
4407 snd_printk(KERN_ERR "HDSPM: "
4408 "unable to remap region 0x%lx-0x%lx\n",
Takashi Iwai763f3562005-06-03 11:25:34 +02004409 hdspm->port, hdspm->port + io_extent - 1);
4410 return -EBUSY;
4411 }
4412 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
4413 (unsigned long)hdspm->iobase, hdspm->port,
4414 hdspm->port + io_extent - 1);
4415
4416 if (request_irq(pci->irq, snd_hdspm_interrupt,
Takashi Iwai437a5a42006-11-21 12:14:23 +01004417 IRQF_SHARED, "hdspm", hdspm)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004418 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
4419 return -EBUSY;
4420 }
4421
4422 snd_printdd("use IRQ %d\n", pci->irq);
4423
4424 hdspm->irq = pci->irq;
4425 hdspm->precise_ptr = precise_ptr;
4426
4427 hdspm->monitor_outs = enable_monitor;
4428
Andrew Mortone2eba3e2006-01-20 14:07:13 +01004429 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Takashi Iwai98274f02005-11-17 14:52:34 +01004430 sizeof(struct hdspm_mixer));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004431 hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
4432 if (!hdspm->mixer) {
4433 snd_printk(KERN_ERR "HDSPM: "
4434 "unable to kmalloc Mixer memory of %d Bytes\n",
Takashi Iwai98274f02005-11-17 14:52:34 +01004435 (int)sizeof(struct hdspm_mixer));
Takashi Iwai763f3562005-06-03 11:25:34 +02004436 return err;
4437 }
4438
4439 hdspm->ss_channels = MADI_SS_CHANNELS;
4440 hdspm->ds_channels = MADI_DS_CHANNELS;
4441 hdspm->qs_channels = MADI_QS_CHANNELS;
4442
4443 snd_printdd("create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004444 err = snd_hdspm_create_alsa_devices(card, hdspm);
4445 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004446 return err;
4447
4448 snd_hdspm_initialize_midi_flush(hdspm);
4449
4450 return 0;
4451}
4452
Takashi Iwai98274f02005-11-17 14:52:34 +01004453static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004454{
4455
4456 if (hdspm->port) {
4457
4458 /* stop th audio, and cancel all interrupts */
4459 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004460 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
4461 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02004462 hdspm_write(hdspm, HDSPM_controlRegister,
4463 hdspm->control_register);
4464 }
4465
4466 if (hdspm->irq >= 0)
4467 free_irq(hdspm->irq, (void *) hdspm);
4468
Jesper Juhlfc584222005-10-24 15:11:28 +02004469 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02004470
4471 if (hdspm->iobase)
4472 iounmap(hdspm->iobase);
4473
Takashi Iwai763f3562005-06-03 11:25:34 +02004474 if (hdspm->port)
4475 pci_release_regions(hdspm->pci);
4476
4477 pci_disable_device(hdspm->pci);
4478 return 0;
4479}
4480
Takashi Iwai98274f02005-11-17 14:52:34 +01004481static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02004482{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004483 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02004484
4485 if (hdspm)
4486 snd_hdspm_free(hdspm);
4487}
4488
4489static int __devinit snd_hdspm_probe(struct pci_dev *pci,
4490 const struct pci_device_id *pci_id)
4491{
4492 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01004493 struct hdspm *hdspm;
4494 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02004495 int err;
4496
4497 if (dev >= SNDRV_CARDS)
4498 return -ENODEV;
4499 if (!enable[dev]) {
4500 dev++;
4501 return -ENOENT;
4502 }
4503
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004504 card = snd_card_new(index[dev], id[dev],
4505 THIS_MODULE, sizeof(struct hdspm));
4506 if (!card)
Takashi Iwai763f3562005-06-03 11:25:34 +02004507 return -ENOMEM;
4508
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004509 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02004510 card->private_free = snd_hdspm_card_free;
4511 hdspm->dev = dev;
4512 hdspm->pci = pci;
4513
Takashi Iwaic187c042007-02-19 15:27:33 +01004514 snd_card_set_dev(card, &pci->dev);
4515
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004516 err = snd_hdspm_create(card, hdspm, precise_ptr[dev],
4517 enable_monitor[dev]);
4518 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004519 snd_card_free(card);
4520 return err;
4521 }
4522
4523 strcpy(card->shortname, "HDSPM MADI");
4524 sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name,
4525 hdspm->port, hdspm->irq);
4526
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004527 err = snd_card_register(card);
4528 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004529 snd_card_free(card);
4530 return err;
4531 }
4532
4533 pci_set_drvdata(pci, card);
4534
4535 dev++;
4536 return 0;
4537}
4538
4539static void __devexit snd_hdspm_remove(struct pci_dev *pci)
4540{
4541 snd_card_free(pci_get_drvdata(pci));
4542 pci_set_drvdata(pci, NULL);
4543}
4544
4545static struct pci_driver driver = {
4546 .name = "RME Hammerfall DSP MADI",
Takashi Iwai763f3562005-06-03 11:25:34 +02004547 .id_table = snd_hdspm_ids,
4548 .probe = snd_hdspm_probe,
4549 .remove = __devexit_p(snd_hdspm_remove),
4550};
4551
4552
4553static int __init alsa_card_hdspm_init(void)
4554{
4555 return pci_register_driver(&driver);
4556}
4557
4558static void __exit alsa_card_hdspm_exit(void)
4559{
4560 pci_unregister_driver(&driver);
4561}
4562
4563module_init(alsa_card_hdspm_init)
4564module_exit(alsa_card_hdspm_exit)