blob: d2ae6380943e6347c9ad6bea406b95d58a6b3d93 [file] [log] [blame]
Takashi Iwai763f3562005-06-03 11:25:34 +02001/* -*- linux-c -*-
2 *
3 * ALSA driver for RME Hammerfall DSP MADI audio interface(s)
4 *
5 * Copyright (c) 2003 Winfried Ritsch (IEM)
6 * code based on hdsp.c Paul Davis
7 * Marcus Andersson
8 * Thomas Charbonnel
Remy Bruno3cee5a62006-10-16 12:46:32 +02009 * Modified 2006-06-01 for AES32 support by Remy Bruno
10 * <remy.bruno@trinnov.com>
Takashi Iwai763f3562005-06-03 11:25:34 +020011 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 */
27#include <sound/driver.h>
28#include <linux/init.h>
29#include <linux/delay.h>
30#include <linux/interrupt.h>
31#include <linux/moduleparam.h>
32#include <linux/slab.h>
33#include <linux/pci.h>
34#include <asm/io.h>
35
36#include <sound/core.h>
37#include <sound/control.h>
38#include <sound/pcm.h>
39#include <sound/info.h>
40#include <sound/asoundef.h>
41#include <sound/rawmidi.h>
42#include <sound/hwdep.h>
43#include <sound/initval.h>
44
45#include <sound/hdspm.h>
46
47static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
48static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
49static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
50
51/* Disable precise pointer at start */
52static int precise_ptr[SNDRV_CARDS];
53
54/* Send all playback to line outs */
55static int line_outs_monitor[SNDRV_CARDS];
56
57/* Enable Analog Outs on Channel 63/64 by default */
58static int enable_monitor[SNDRV_CARDS];
59
60module_param_array(index, int, NULL, 0444);
61MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
62
63module_param_array(id, charp, NULL, 0444);
64MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
65
66module_param_array(enable, bool, NULL, 0444);
67MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
68
69module_param_array(precise_ptr, bool, NULL, 0444);
Takashi Iwaie8da2fb2005-08-16 16:55:13 +020070MODULE_PARM_DESC(precise_ptr, "Enable or disable precise pointer.");
Takashi Iwai763f3562005-06-03 11:25:34 +020071
72module_param_array(line_outs_monitor, bool, NULL, 0444);
73MODULE_PARM_DESC(line_outs_monitor,
74 "Send playback streams to analog outs by default.");
75
76module_param_array(enable_monitor, bool, NULL, 0444);
77MODULE_PARM_DESC(enable_monitor,
78 "Enable Analog Out on Channel 63/64 by default.");
79
80MODULE_AUTHOR
81 ("Winfried Ritsch <ritsch_AT_iem.at>, Paul Davis <paul@linuxaudiosystems.com>, "
Remy Bruno3cee5a62006-10-16 12:46:32 +020082 "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
83 "Remy Bruno <remy.bruno@trinnov.com>");
Takashi Iwai763f3562005-06-03 11:25:34 +020084MODULE_DESCRIPTION("RME HDSPM");
85MODULE_LICENSE("GPL");
86MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
87
88/* --- Write registers. ---
89 These are defined as byte-offsets from the iobase value. */
90
91#define HDSPM_controlRegister 64
92#define HDSPM_interruptConfirmation 96
93#define HDSPM_control2Reg 256 /* not in specs ???????? */
94#define HDSPM_midiDataOut0 352 /* just believe in old code */
95#define HDSPM_midiDataOut1 356
96
97/* DMA enable for 64 channels, only Bit 0 is relevant */
98#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */
99#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */
100
101/* 16 page addresses for each of the 64 channels DMA buffer in and out
102 (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
103#define HDSPM_pageAddressBufferOut 8192
104#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)
105
106#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */
107
108#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */
109
110/* --- Read registers. ---
111 These are defined as byte-offsets from the iobase value */
112#define HDSPM_statusRegister 0
Remy Bruno3cee5a62006-10-16 12:46:32 +0200113/*#define HDSPM_statusRegister2 96 */
114/* after RME Windows driver sources, status2 is 4-byte word # 48 = word at
115 * offset 192, for AES32 *and* MADI
116 * => need to check that offset 192 is working on MADI */
117#define HDSPM_statusRegister2 192
118#define HDSPM_timecodeRegister 128
Takashi Iwai763f3562005-06-03 11:25:34 +0200119
120#define HDSPM_midiDataIn0 360
121#define HDSPM_midiDataIn1 364
122
123/* status is data bytes in MIDI-FIFO (0-128) */
124#define HDSPM_midiStatusOut0 384
125#define HDSPM_midiStatusOut1 388
126#define HDSPM_midiStatusIn0 392
127#define HDSPM_midiStatusIn1 396
128
129
130/* the meters are regular i/o-mapped registers, but offset
131 considerably from the rest. the peak registers are reset
132 when read; the least-significant 4 bits are full-scale counters;
133 the actual peak value is in the most-significant 24 bits.
134*/
135#define HDSPM_MADI_peakrmsbase 4096 /* 4096-8191 2x64x32Bit Meters */
136
137/* --- Control Register bits --------- */
138#define HDSPM_Start (1<<0) /* start engine */
139
140#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */
141#define HDSPM_Latency1 (1<<2) /* where n is defined */
142#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */
143
144#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */
145
146#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
147
148#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
149#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
150#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200151#define HDSPM_QuadSpeed (1<<31) /* quad speed bit */
Takashi Iwai763f3562005-06-03 11:25:34 +0200152
Remy Bruno3cee5a62006-10-16 12:46:32 +0200153#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200154#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200155 56channelMODE=0 */ /* MADI ONLY*/
156#define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200157
158#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200159 0=off, 1=on */ /* MADI ONLY */
160#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200161
Remy Bruno3cee5a62006-10-16 12:46:32 +0200162#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */ /* MADI ONLY*/
Takashi Iwai763f3562005-06-03 11:25:34 +0200163#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
164
165#define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200166#define HDSPM_SyncRef1 (1<<17) /* for AES32: SyncRefN codes the AES # */
167#define HDSPM_SyncRef2 (1<<13)
168#define HDSPM_SyncRef3 (1<<25)
Takashi Iwai763f3562005-06-03 11:25:34 +0200169
Remy Bruno3cee5a62006-10-16 12:46:32 +0200170#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200171#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
172 AES additional bits in
173 lower 5 Audiodatabits ??? */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200174#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */
175#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200176
177#define HDSPM_Midi0InterruptEnable (1<<22)
178#define HDSPM_Midi1InterruptEnable (1<<23)
179
180#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
181
Remy Bruno3cee5a62006-10-16 12:46:32 +0200182#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
183#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
184#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */
185
186#define HDSPM_wclk_sel (1<<30)
Takashi Iwai763f3562005-06-03 11:25:34 +0200187
188/* --- bit helper defines */
189#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200190#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
Takashi Iwai763f3562005-06-03 11:25:34 +0200191#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
192#define HDSPM_InputOptical 0
193#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200194#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|HDSPM_SyncRef2|HDSPM_SyncRef3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200195#define HDSPM_SyncRef_Word 0
196#define HDSPM_SyncRef_MADI (HDSPM_SyncRef0)
197
198#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
199#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
200
201#define HDSPM_Frequency32KHz HDSPM_Frequency0
202#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
203#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
204#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
205#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
206#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200207#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)
208#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)
209#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|HDSPM_Frequency0)
Takashi Iwai763f3562005-06-03 11:25:34 +0200210
211/* --- for internal discrimination */
212#define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */
213#define HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ 1
214#define HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ 2
215#define HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ 3
216#define HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ 4
217#define HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ 5
218#define HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ 6
219#define HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ 7
220#define HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ 8
221#define HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ 9
222
223/* Synccheck Status */
224#define HDSPM_SYNC_CHECK_NO_LOCK 0
225#define HDSPM_SYNC_CHECK_LOCK 1
226#define HDSPM_SYNC_CHECK_SYNC 2
227
228/* AutoSync References - used by "autosync_ref" control switch */
229#define HDSPM_AUTOSYNC_FROM_WORD 0
230#define HDSPM_AUTOSYNC_FROM_MADI 1
231#define HDSPM_AUTOSYNC_FROM_NONE 2
232
233/* Possible sources of MADI input */
234#define HDSPM_OPTICAL 0 /* optical */
235#define HDSPM_COAXIAL 1 /* BNC */
236
237#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
238#define hdspm_decode_latency(x) (((x) & HDSPM_LatencyMask)>>1)
239
240#define hdspm_encode_in(x) (((x)&0x3)<<14)
241#define hdspm_decode_in(x) (((x)>>14)&0x3)
242
243/* --- control2 register bits --- */
244#define HDSPM_TMS (1<<0)
245#define HDSPM_TCK (1<<1)
246#define HDSPM_TDI (1<<2)
247#define HDSPM_JTAG (1<<3)
248#define HDSPM_PWDN (1<<4)
249#define HDSPM_PROGRAM (1<<5)
250#define HDSPM_CONFIG_MODE_0 (1<<6)
251#define HDSPM_CONFIG_MODE_1 (1<<7)
252/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
253#define HDSPM_BIGENDIAN_MODE (1<<9)
254#define HDSPM_RD_MULTIPLE (1<<10)
255
Remy Bruno3cee5a62006-10-16 12:46:32 +0200256/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
257 that do not conflict with specific bits for AES32 seem to be valid also for the AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200258#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
259#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn. MODE=0 */
260#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 (like inp0) */
261#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
262
263#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
264 /* since 64byte accurate last 6 bits
265 are not used */
266
267#define HDSPM_madiSync (1<<18) /* MADI is in sync */
268#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
269
270#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
271#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
272#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
273#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
274
275#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with Interrupt */
276#define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */
277#define HDSPM_midi1IRQPending (1<<31) /* and aktiv */
278
279/* --- status bit helpers */
280#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2|HDSPM_madiFreq3)
281#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
282#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
283#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
284#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
285#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
286#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
287#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
288#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
289#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
290
Remy Bruno3cee5a62006-10-16 12:46:32 +0200291/* Status2 Register bits */ /* MADI ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200292
293#define HDSPM_version0 (1<<0) /* not realy defined but I guess */
294#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
295#define HDSPM_version2 (1<<2)
296
297#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */
298#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */
299
300#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */
301#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */
302#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */
303/* missing Bit for 111=128, 1000=176.4, 1001=192 */
304
305#define HDSPM_SelSyncRef0 (1<<8) /* Sync Source in slave mode */
306#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */
307#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */
308
309#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
310
311#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
312#define HDSPM_wcFreq32 (HDSPM_wc_freq0)
313#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)
314#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)
315#define HDSPM_wcFreq64 (HDSPM_wc_freq2)
316#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)
317#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
318
319
320#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
321#define HDSPM_SelSyncRef_WORD 0
322#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
323#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
324
Remy Bruno3cee5a62006-10-16 12:46:32 +0200325/*
326 For AES32, bits for status, status2 and timecode are different
327*/
328/* status */
329#define HDSPM_AES32_wcLock 0x0200000
330#define HDSPM_AES32_wcFreq_bit 22
331/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
332 HDSPM_bit2freq */
333#define HDSPM_AES32_syncref_bit 16
334/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
335
336#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
337#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
338#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
339#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
340#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
341#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
342#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
343#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
344#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
345#define HDSPM_AES32_AUTOSYNC_FROM_NONE -1
346
347/* status2 */
348/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
349#define HDSPM_LockAES 0x80
350#define HDSPM_LockAES1 0x80
351#define HDSPM_LockAES2 0x40
352#define HDSPM_LockAES3 0x20
353#define HDSPM_LockAES4 0x10
354#define HDSPM_LockAES5 0x8
355#define HDSPM_LockAES6 0x4
356#define HDSPM_LockAES7 0x2
357#define HDSPM_LockAES8 0x1
358/*
359 Timecode
360 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
361 AES i+1
362 bits 3210
363 0001 32kHz
364 0010 44.1kHz
365 0011 48kHz
366 0100 64kHz
367 0101 88.2kHz
368 0110 96kHz
369 0111 128kHz
370 1000 176.4kHz
371 1001 192kHz
372 NB: Timecode register doesn't seem to work on AES32 card revision 230
373*/
374
Takashi Iwai763f3562005-06-03 11:25:34 +0200375/* Mixer Values */
376#define UNITY_GAIN 32768 /* = 65536/2 */
377#define MINUS_INFINITY_GAIN 0
378
Takashi Iwai763f3562005-06-03 11:25:34 +0200379/* Number of channels for different Speed Modes */
380#define MADI_SS_CHANNELS 64
381#define MADI_DS_CHANNELS 32
382#define MADI_QS_CHANNELS 16
383
384/* the size of a substream (1 mono data stream) */
385#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
386#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
387
388/* the size of the area we need to allocate for DMA transfers. the
389 size is the same regardless of the number of channels, and
390 also the latency to use.
391 for one direction !!!
Remy Bruno3cee5a62006-10-16 12:46:32 +0200392 => need to mupltiply by 2!!
Takashi Iwai763f3562005-06-03 11:25:34 +0200393*/
Remy Bruno3cee5a62006-10-16 12:46:32 +0200394#define HDSPM_DMA_AREA_BYTES (2 * HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
Takashi Iwai763f3562005-06-03 11:25:34 +0200395#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
396
Remy Bruno3cee5a62006-10-16 12:46:32 +0200397/* revisions >= 230 indicate AES32 card */
398#define HDSPM_AESREVISION 230
399
Takashi Iwai98274f02005-11-17 14:52:34 +0100400struct hdspm_midi {
401 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200402 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100403 struct snd_rawmidi *rmidi;
404 struct snd_rawmidi_substream *input;
405 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200406 char istimer; /* timer in use */
407 struct timer_list timer;
408 spinlock_t lock;
409 int pending;
410};
411
Takashi Iwai98274f02005-11-17 14:52:34 +0100412struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200413 spinlock_t lock;
Takashi Iwai98274f02005-11-17 14:52:34 +0100414 struct snd_pcm_substream *capture_substream; /* only one playback */
415 struct snd_pcm_substream *playback_substream; /* and/or capture stream */
Takashi Iwai763f3562005-06-03 11:25:34 +0200416
417 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200418 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
419
420 unsigned char is_aes32; /* indicates if card is AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200421
422 int precise_ptr; /* use precise pointers, to be tested */
423 int monitor_outs; /* set up monitoring outs init flag */
424
425 u32 control_register; /* cached value */
426 u32 control2_register; /* cached value */
427
Takashi Iwai98274f02005-11-17 14:52:34 +0100428 struct hdspm_midi midi[2];
Takashi Iwai763f3562005-06-03 11:25:34 +0200429 struct tasklet_struct midi_tasklet;
430
431 size_t period_bytes;
432 unsigned char ss_channels; /* channels of card in single speed */
433 unsigned char ds_channels; /* Double Speed */
434 unsigned char qs_channels; /* Quad Speed */
435
436 unsigned char *playback_buffer; /* suitably aligned address */
437 unsigned char *capture_buffer; /* suitably aligned address */
438
439 pid_t capture_pid; /* process id which uses capture */
440 pid_t playback_pid; /* process id which uses capture */
441 int running; /* running status */
442
443 int last_external_sample_rate; /* samplerate mystic ... */
444 int last_internal_sample_rate;
445 int system_sample_rate;
446
447 char *channel_map; /* channel map for DS and Quadspeed */
448
449 int dev; /* Hardware vars... */
450 int irq;
451 unsigned long port;
452 void __iomem *iobase;
453
454 int irq_count; /* for debug */
455
Takashi Iwai98274f02005-11-17 14:52:34 +0100456 struct snd_card *card; /* one card */
457 struct snd_pcm *pcm; /* has one pcm */
458 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +0200459 struct pci_dev *pci; /* and an pci info */
460
461 /* Mixer vars */
Takashi Iwai98274f02005-11-17 14:52:34 +0100462 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; /* fast alsa mixer */
463 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS]; /* but input to much, so not used */
464 struct hdspm_mixer *mixer; /* full mixer accessable over mixer ioctl or hwdep-device */
Takashi Iwai763f3562005-06-03 11:25:34 +0200465
466};
467
468/* These tables map the ALSA channels 1..N to the channels that we
469 need to use in order to find the relevant channel buffer. RME
470 refer to this kind of mapping as between "the ADAT channel and
471 the DMA channel." We index it using the logical audio channel,
472 and the value is the DMA channel (i.e. channel buffer number)
473 where the data for that channel can be read/written from/to.
474*/
475
476static char channel_map_madi_ss[HDSPM_MAX_CHANNELS] = {
477 0, 1, 2, 3, 4, 5, 6, 7,
478 8, 9, 10, 11, 12, 13, 14, 15,
479 16, 17, 18, 19, 20, 21, 22, 23,
480 24, 25, 26, 27, 28, 29, 30, 31,
481 32, 33, 34, 35, 36, 37, 38, 39,
482 40, 41, 42, 43, 44, 45, 46, 47,
483 48, 49, 50, 51, 52, 53, 54, 55,
484 56, 57, 58, 59, 60, 61, 62, 63
485};
486
487static char channel_map_madi_ds[HDSPM_MAX_CHANNELS] = {
488 0, 2, 4, 6, 8, 10, 12, 14,
489 16, 18, 20, 22, 24, 26, 28, 30,
490 32, 34, 36, 38, 40, 42, 44, 46,
491 48, 50, 52, 54, 56, 58, 60, 62,
492 -1, -1, -1, -1, -1, -1, -1, -1,
493 -1, -1, -1, -1, -1, -1, -1, -1,
494 -1, -1, -1, -1, -1, -1, -1, -1,
495 -1, -1, -1, -1, -1, -1, -1, -1
496};
497
498static char channel_map_madi_qs[HDSPM_MAX_CHANNELS] = {
499 0, 4, 8, 12, 16, 20, 24, 28,
500 32, 36, 40, 44, 48, 52, 56, 60
501 -1, -1, -1, -1, -1, -1, -1, -1,
502 -1, -1, -1, -1, -1, -1, -1, -1,
503 -1, -1, -1, -1, -1, -1, -1, -1,
504 -1, -1, -1, -1, -1, -1, -1, -1,
505 -1, -1, -1, -1, -1, -1, -1, -1,
506 -1, -1, -1, -1, -1, -1, -1, -1
507};
508
509
Henrik Kretzschmar396c9b92006-04-24 15:59:04 +0200510static struct pci_device_id snd_hdspm_ids[] __devinitdata = {
Takashi Iwai763f3562005-06-03 11:25:34 +0200511 {
512 .vendor = PCI_VENDOR_ID_XILINX,
513 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
514 .subvendor = PCI_ANY_ID,
515 .subdevice = PCI_ANY_ID,
516 .class = 0,
517 .class_mask = 0,
518 .driver_data = 0},
519 {0,}
520};
521
522MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
523
524/* prototypes */
Takashi Iwai98274f02005-11-17 14:52:34 +0100525static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
526 struct hdspm * hdspm);
527static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
528 struct hdspm * hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200529
Takashi Iwai98274f02005-11-17 14:52:34 +0100530static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm);
531static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm);
532static int hdspm_autosync_ref(struct hdspm * hdspm);
533static int snd_hdspm_set_defaults(struct hdspm * hdspm);
534static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
Takashi Iwai763f3562005-06-03 11:25:34 +0200535 unsigned int reg, int channels);
536
Remy Bruno3cee5a62006-10-16 12:46:32 +0200537static inline int HDSPM_bit2freq(int n)
538{
539 static int bit2freq_tab[] = { 0, 32000, 44100, 48000, 64000, 88200,
540 96000, 128000, 176400, 192000 };
541 if (n < 1 || n > 9)
542 return 0;
543 return bit2freq_tab[n];
544}
545
Takashi Iwai763f3562005-06-03 11:25:34 +0200546/* Write/read to/from HDSPM with Adresses in Bytes
547 not words but only 32Bit writes are allowed */
548
Takashi Iwai98274f02005-11-17 14:52:34 +0100549static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +0200550 unsigned int val)
551{
552 writel(val, hdspm->iobase + reg);
553}
554
Takashi Iwai98274f02005-11-17 14:52:34 +0100555static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +0200556{
557 return readl(hdspm->iobase + reg);
558}
559
560/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
561 mixer is write only on hardware so we have to cache him for read
562 each fader is a u32, but uses only the first 16 bit */
563
Takashi Iwai98274f02005-11-17 14:52:34 +0100564static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200565 unsigned int in)
566{
Adrian Bunk5bab24822006-03-13 14:15:04 +0100567 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +0200568 return 0;
569
570 return hdspm->mixer->ch[chan].in[in];
571}
572
Takashi Iwai98274f02005-11-17 14:52:34 +0100573static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200574 unsigned int pb)
575{
Adrian Bunk5bab24822006-03-13 14:15:04 +0100576 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +0200577 return 0;
578 return hdspm->mixer->ch[chan].pb[pb];
579}
580
Takashi Iwai98274f02005-11-17 14:52:34 +0100581static inline int hdspm_write_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200582 unsigned int in, unsigned short data)
583{
584 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
585 return -1;
586
587 hdspm_write(hdspm,
588 HDSPM_MADI_mixerBase +
589 ((in + 128 * chan) * sizeof(u32)),
590 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
591 return 0;
592}
593
Takashi Iwai98274f02005-11-17 14:52:34 +0100594static inline int hdspm_write_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200595 unsigned int pb, unsigned short data)
596{
597 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
598 return -1;
599
600 hdspm_write(hdspm,
601 HDSPM_MADI_mixerBase +
602 ((64 + pb + 128 * chan) * sizeof(u32)),
603 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
604 return 0;
605}
606
607
608/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +0100609static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +0200610{
611 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
612}
613
Takashi Iwai98274f02005-11-17 14:52:34 +0100614static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +0200615{
616 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
617}
618
619/* check if same process is writing and reading */
Takashi Iwai98274f02005-11-17 14:52:34 +0100620static inline int snd_hdspm_use_is_exclusive(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200621{
622 unsigned long flags;
623 int ret = 1;
624
625 spin_lock_irqsave(&hdspm->lock, flags);
626 if ((hdspm->playback_pid != hdspm->capture_pid) &&
627 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
628 ret = 0;
629 }
630 spin_unlock_irqrestore(&hdspm->lock, flags);
631 return ret;
632}
633
634/* check for external sample rate */
Takashi Iwai98274f02005-11-17 14:52:34 +0100635static inline int hdspm_external_sample_rate(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200636{
Remy Bruno3cee5a62006-10-16 12:46:32 +0200637 if (hdspm->is_aes32) {
638 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
639 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
640 unsigned int timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +0200641
Remy Bruno3cee5a62006-10-16 12:46:32 +0200642 int syncref = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200643
Remy Bruno3cee5a62006-10-16 12:46:32 +0200644 if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
645 status & HDSPM_AES32_wcLock)
646 return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
647 if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
648 syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
649 status2 & (HDSPM_LockAES >>
650 (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
651 return HDSPM_bit2freq((timecode >>
652 (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
653 return 0;
654 } else {
655 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
656 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
657 unsigned int rate_bits;
658 int rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +0200659
Remy Bruno3cee5a62006-10-16 12:46:32 +0200660 /* if wordclock has synced freq and wordclock is valid */
661 if ((status2 & HDSPM_wcLock) != 0 &&
662 (status & HDSPM_SelSyncRef0) == 0) {
663
664 rate_bits = status2 & HDSPM_wcFreqMask;
665
666 switch (rate_bits) {
667 case HDSPM_wcFreq32:
668 rate = 32000;
669 break;
670 case HDSPM_wcFreq44_1:
671 rate = 44100;
672 break;
673 case HDSPM_wcFreq48:
674 rate = 48000;
675 break;
676 case HDSPM_wcFreq64:
677 rate = 64000;
678 break;
679 case HDSPM_wcFreq88_2:
680 rate = 88200;
681 break;
682 case HDSPM_wcFreq96:
683 rate = 96000;
684 break;
685 /* Quadspeed Bit missing ???? */
686 default:
687 rate = 0;
688 break;
689 }
Takashi Iwai763f3562005-06-03 11:25:34 +0200690 }
Takashi Iwai763f3562005-06-03 11:25:34 +0200691
Remy Bruno3cee5a62006-10-16 12:46:32 +0200692 /* if rate detected and Syncref is Word than have it, word has priority to MADI */
693 if (rate != 0 &&
694 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
695 return rate;
696
697 /* maby a madi input (which is taken if sel sync is madi) */
698 if (status & HDSPM_madiLock) {
699 rate_bits = status & HDSPM_madiFreqMask;
700
701 switch (rate_bits) {
702 case HDSPM_madiFreq32:
703 rate = 32000;
704 break;
705 case HDSPM_madiFreq44_1:
706 rate = 44100;
707 break;
708 case HDSPM_madiFreq48:
709 rate = 48000;
710 break;
711 case HDSPM_madiFreq64:
712 rate = 64000;
713 break;
714 case HDSPM_madiFreq88_2:
715 rate = 88200;
716 break;
717 case HDSPM_madiFreq96:
718 rate = 96000;
719 break;
720 case HDSPM_madiFreq128:
721 rate = 128000;
722 break;
723 case HDSPM_madiFreq176_4:
724 rate = 176400;
725 break;
726 case HDSPM_madiFreq192:
727 rate = 192000;
728 break;
729 default:
730 rate = 0;
731 break;
732 }
733 }
Takashi Iwai763f3562005-06-03 11:25:34 +0200734 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +0200735 }
Takashi Iwai763f3562005-06-03 11:25:34 +0200736}
737
738/* Latency function */
Takashi Iwai98274f02005-11-17 14:52:34 +0100739static inline void hdspm_compute_period_size(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200740{
741 hdspm->period_bytes =
742 1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
743}
744
Takashi Iwai98274f02005-11-17 14:52:34 +0100745static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200746{
747 int position;
748
749 position = hdspm_read(hdspm, HDSPM_statusRegister);
750
751 if (!hdspm->precise_ptr) {
752 return (position & HDSPM_BufferID) ? (hdspm->period_bytes /
753 4) : 0;
754 }
755
756 /* hwpointer comes in bytes and is 64Bytes accurate (by docu since PCI Burst)
757 i have experimented that it is at most 64 Byte to much for playing
758 so substraction of 64 byte should be ok for ALSA, but use it only
759 for application where you know what you do since if you come to
760 near with record pointer it can be a disaster */
761
762 position &= HDSPM_BufferPositionMask;
763 position = ((position - 64) % (2 * hdspm->period_bytes)) / 4;
764
765 return position;
766}
767
768
Takashi Iwai98274f02005-11-17 14:52:34 +0100769static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +0200770{
771 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
772 hdspm_write(s, HDSPM_controlRegister, s->control_register);
773}
774
Takashi Iwai98274f02005-11-17 14:52:34 +0100775static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +0200776{
777 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
778 hdspm_write(s, HDSPM_controlRegister, s->control_register);
779}
780
781/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Takashi Iwai98274f02005-11-17 14:52:34 +0100782static inline void hdspm_silence_playback(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200783{
784 int i;
785 int n = hdspm->period_bytes;
786 void *buf = hdspm->playback_buffer;
787
Remy Bruno3cee5a62006-10-16 12:46:32 +0200788 if (buf == NULL)
789 return;
Takashi Iwai763f3562005-06-03 11:25:34 +0200790
791 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
792 memset(buf, 0, n);
793 buf += HDSPM_CHANNEL_BUFFER_BYTES;
794 }
795}
796
Takashi Iwai98274f02005-11-17 14:52:34 +0100797static int hdspm_set_interrupt_interval(struct hdspm * s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +0200798{
799 int n;
800
801 spin_lock_irq(&s->lock);
802
803 frames >>= 7;
804 n = 0;
805 while (frames) {
806 n++;
807 frames >>= 1;
808 }
809 s->control_register &= ~HDSPM_LatencyMask;
810 s->control_register |= hdspm_encode_latency(n);
811
812 hdspm_write(s, HDSPM_controlRegister, s->control_register);
813
814 hdspm_compute_period_size(s);
815
816 spin_unlock_irq(&s->lock);
817
818 return 0;
819}
820
821
822/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +0100823static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +0200824{
825 int reject_if_open = 0;
826 int current_rate;
827 int rate_bits;
828 int not_set = 0;
Remy Bruno3cee5a62006-10-16 12:46:32 +0200829 int is_single, is_double, is_quad;
Takashi Iwai763f3562005-06-03 11:25:34 +0200830
831 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
832 it (e.g. during module initialization).
833 */
834
835 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
836
837 /* SLAVE --- */
838 if (called_internally) {
839
840 /* request from ctl or card initialization
841 just make a warning an remember setting
842 for future master mode switching */
843
844 snd_printk
845 (KERN_WARNING "HDSPM: Warning: device is not running as a clock master.\n");
846 not_set = 1;
847 } else {
848
849 /* hw_param request while in AutoSync mode */
850 int external_freq =
851 hdspm_external_sample_rate(hdspm);
852
853 if ((hdspm_autosync_ref(hdspm) ==
854 HDSPM_AUTOSYNC_FROM_NONE)) {
855
856 snd_printk(KERN_WARNING "HDSPM: Detected no Externel Sync \n");
857 not_set = 1;
858
859 } else if (rate != external_freq) {
860
861 snd_printk
862 (KERN_WARNING "HDSPM: Warning: No AutoSync source for requested rate\n");
863 not_set = 1;
864 }
865 }
866 }
867
868 current_rate = hdspm->system_sample_rate;
869
870 /* Changing between Singe, Double and Quad speed is not
871 allowed if any substreams are open. This is because such a change
872 causes a shift in the location of the DMA buffers and a reduction
873 in the number of available buffers.
874
875 Note that a similar but essentially insoluble problem exists for
876 externally-driven rate changes. All we can do is to flag rate
877 changes in the read/write routines.
878 */
879
Remy Bruno3cee5a62006-10-16 12:46:32 +0200880 is_single = (current_rate <= 48000);
881 is_double = (current_rate > 48000 && current_rate <= 96000);
882 is_quad = (current_rate > 96000);
883
Takashi Iwai763f3562005-06-03 11:25:34 +0200884 switch (rate) {
885 case 32000:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200886 if (!is_single)
Takashi Iwai763f3562005-06-03 11:25:34 +0200887 reject_if_open = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +0200888 rate_bits = HDSPM_Frequency32KHz;
889 break;
890 case 44100:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200891 if (!is_single)
Takashi Iwai763f3562005-06-03 11:25:34 +0200892 reject_if_open = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +0200893 rate_bits = HDSPM_Frequency44_1KHz;
894 break;
895 case 48000:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200896 if (!is_single)
Takashi Iwai763f3562005-06-03 11:25:34 +0200897 reject_if_open = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +0200898 rate_bits = HDSPM_Frequency48KHz;
899 break;
900 case 64000:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200901 if (!is_double)
Takashi Iwai763f3562005-06-03 11:25:34 +0200902 reject_if_open = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +0200903 rate_bits = HDSPM_Frequency64KHz;
904 break;
905 case 88200:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200906 if (!is_double)
Takashi Iwai763f3562005-06-03 11:25:34 +0200907 reject_if_open = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +0200908 rate_bits = HDSPM_Frequency88_2KHz;
909 break;
910 case 96000:
Remy Bruno3cee5a62006-10-16 12:46:32 +0200911 if (!is_double)
Takashi Iwai763f3562005-06-03 11:25:34 +0200912 reject_if_open = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +0200913 rate_bits = HDSPM_Frequency96KHz;
914 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +0200915 case 128000:
916 if (!is_quad)
917 reject_if_open = 1;
918 rate_bits = HDSPM_Frequency128KHz;
919 break;
920 case 176400:
921 if (!is_quad)
922 reject_if_open = 1;
923 rate_bits = HDSPM_Frequency176_4KHz;
924 break;
925 case 192000:
926 if (!is_quad)
927 reject_if_open = 1;
928 rate_bits = HDSPM_Frequency192KHz;
929 break;
Takashi Iwai763f3562005-06-03 11:25:34 +0200930 default:
931 return -EINVAL;
932 }
933
934 if (reject_if_open
935 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
936 snd_printk
937 (KERN_ERR "HDSPM: cannot change between single- and double-speed mode (capture PID = %d, playback PID = %d)\n",
938 hdspm->capture_pid, hdspm->playback_pid);
939 return -EBUSY;
940 }
941
942 hdspm->control_register &= ~HDSPM_FrequencyMask;
943 hdspm->control_register |= rate_bits;
944 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
945
Remy Bruno3cee5a62006-10-16 12:46:32 +0200946 if (rate > 96000 /* 64000*/)
Takashi Iwai763f3562005-06-03 11:25:34 +0200947 hdspm->channel_map = channel_map_madi_qs;
948 else if (rate > 48000)
949 hdspm->channel_map = channel_map_madi_ds;
950 else
951 hdspm->channel_map = channel_map_madi_ss;
952
953 hdspm->system_sample_rate = rate;
954
955 if (not_set != 0)
956 return -1;
957
958 return 0;
959}
960
961/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +0100962static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +0200963{
964 int i, j;
965 unsigned int gain =
966 (sgain > UNITY_GAIN) ? UNITY_GAIN : (sgain < 0) ? 0 : sgain;
967
968 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
969 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
970 hdspm_write_in_gain(hdspm, i, j, gain);
971 hdspm_write_pb_gain(hdspm, i, j, gain);
972 }
973}
974
975/*----------------------------------------------------------------------------
976 MIDI
977 ----------------------------------------------------------------------------*/
978
Takashi Iwai98274f02005-11-17 14:52:34 +0100979static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +0200980{
981 /* the hardware already does the relevant bit-mask with 0xff */
982 if (id)
983 return hdspm_read(hdspm, HDSPM_midiDataIn1);
984 else
985 return hdspm_read(hdspm, HDSPM_midiDataIn0);
986}
987
Takashi Iwai98274f02005-11-17 14:52:34 +0100988static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id, int val)
Takashi Iwai763f3562005-06-03 11:25:34 +0200989{
990 /* the hardware already does the relevant bit-mask with 0xff */
991 if (id)
992 return hdspm_write(hdspm, HDSPM_midiDataOut1, val);
993 else
994 return hdspm_write(hdspm, HDSPM_midiDataOut0, val);
995}
996
Takashi Iwai98274f02005-11-17 14:52:34 +0100997static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +0200998{
999 if (id)
1000 return (hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff);
1001 else
1002 return (hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff);
1003}
1004
Takashi Iwai98274f02005-11-17 14:52:34 +01001005static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001006{
1007 int fifo_bytes_used;
1008
1009 if (id)
1010 fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xff;
1011 else
1012 fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xff;
1013
1014 if (fifo_bytes_used < 128)
1015 return 128 - fifo_bytes_used;
1016 else
1017 return 0;
1018}
1019
Takashi Iwai98274f02005-11-17 14:52:34 +01001020static inline void snd_hdspm_flush_midi_input (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001021{
1022 while (snd_hdspm_midi_input_available (hdspm, id))
1023 snd_hdspm_midi_read_byte (hdspm, id);
1024}
1025
Takashi Iwai98274f02005-11-17 14:52:34 +01001026static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001027{
1028 unsigned long flags;
1029 int n_pending;
1030 int to_write;
1031 int i;
1032 unsigned char buf[128];
1033
1034 /* Output is not interrupt driven */
1035
1036 spin_lock_irqsave (&hmidi->lock, flags);
1037 if (hmidi->output) {
1038 if (!snd_rawmidi_transmit_empty (hmidi->output)) {
1039 if ((n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, hmidi->id)) > 0) {
1040 if (n_pending > (int)sizeof (buf))
1041 n_pending = sizeof (buf);
1042
1043 if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {
1044 for (i = 0; i < to_write; ++i)
1045 snd_hdspm_midi_write_byte (hmidi->hdspm, hmidi->id, buf[i]);
1046 }
1047 }
1048 }
1049 }
1050 spin_unlock_irqrestore (&hmidi->lock, flags);
1051 return 0;
1052}
1053
Takashi Iwai98274f02005-11-17 14:52:34 +01001054static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001055{
1056 unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
1057 unsigned long flags;
1058 int n_pending;
1059 int i;
1060
1061 spin_lock_irqsave (&hmidi->lock, flags);
1062 if ((n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id)) > 0) {
1063 if (hmidi->input) {
1064 if (n_pending > (int)sizeof (buf)) {
1065 n_pending = sizeof (buf);
1066 }
1067 for (i = 0; i < n_pending; ++i) {
1068 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id);
1069 }
1070 if (n_pending) {
1071 snd_rawmidi_receive (hmidi->input, buf, n_pending);
1072 }
1073 } else {
1074 /* flush the MIDI input FIFO */
1075 while (n_pending--) {
1076 snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id);
1077 }
1078 }
1079 }
1080 hmidi->pending = 0;
1081 if (hmidi->id) {
1082 hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable;
1083 } else {
1084 hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable;
1085 }
1086 hdspm_write(hmidi->hdspm, HDSPM_controlRegister, hmidi->hdspm->control_register);
1087 spin_unlock_irqrestore (&hmidi->lock, flags);
1088 return snd_hdspm_midi_output_write (hmidi);
1089}
1090
Takashi Iwai98274f02005-11-17 14:52:34 +01001091static void snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001092{
Takashi Iwai98274f02005-11-17 14:52:34 +01001093 struct hdspm *hdspm;
1094 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001095 unsigned long flags;
1096 u32 ie;
1097
Takashi Iwai98274f02005-11-17 14:52:34 +01001098 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001099 hdspm = hmidi->hdspm;
1100 ie = hmidi->id ? HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable;
1101 spin_lock_irqsave (&hdspm->lock, flags);
1102 if (up) {
1103 if (!(hdspm->control_register & ie)) {
1104 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
1105 hdspm->control_register |= ie;
1106 }
1107 } else {
1108 hdspm->control_register &= ~ie;
1109 }
1110
1111 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1112 spin_unlock_irqrestore (&hdspm->lock, flags);
1113}
1114
1115static void snd_hdspm_midi_output_timer(unsigned long data)
1116{
Takashi Iwai98274f02005-11-17 14:52:34 +01001117 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001118 unsigned long flags;
1119
1120 snd_hdspm_midi_output_write(hmidi);
1121 spin_lock_irqsave (&hmidi->lock, flags);
1122
1123 /* this does not bump hmidi->istimer, because the
1124 kernel automatically removed the timer when it
1125 expired, and we are now adding it back, thus
1126 leaving istimer wherever it was set before.
1127 */
1128
1129 if (hmidi->istimer) {
1130 hmidi->timer.expires = 1 + jiffies;
1131 add_timer(&hmidi->timer);
1132 }
1133
1134 spin_unlock_irqrestore (&hmidi->lock, flags);
1135}
1136
Takashi Iwai98274f02005-11-17 14:52:34 +01001137static void snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001138{
Takashi Iwai98274f02005-11-17 14:52:34 +01001139 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001140 unsigned long flags;
1141
Takashi Iwai98274f02005-11-17 14:52:34 +01001142 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001143 spin_lock_irqsave (&hmidi->lock, flags);
1144 if (up) {
1145 if (!hmidi->istimer) {
1146 init_timer(&hmidi->timer);
1147 hmidi->timer.function = snd_hdspm_midi_output_timer;
1148 hmidi->timer.data = (unsigned long) hmidi;
1149 hmidi->timer.expires = 1 + jiffies;
1150 add_timer(&hmidi->timer);
1151 hmidi->istimer++;
1152 }
1153 } else {
1154 if (hmidi->istimer && --hmidi->istimer <= 0) {
1155 del_timer (&hmidi->timer);
1156 }
1157 }
1158 spin_unlock_irqrestore (&hmidi->lock, flags);
1159 if (up)
1160 snd_hdspm_midi_output_write(hmidi);
1161}
1162
Takashi Iwai98274f02005-11-17 14:52:34 +01001163static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001164{
Takashi Iwai98274f02005-11-17 14:52:34 +01001165 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001166
Takashi Iwai98274f02005-11-17 14:52:34 +01001167 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001168 spin_lock_irq (&hmidi->lock);
1169 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1170 hmidi->input = substream;
1171 spin_unlock_irq (&hmidi->lock);
1172
1173 return 0;
1174}
1175
Takashi Iwai98274f02005-11-17 14:52:34 +01001176static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001177{
Takashi Iwai98274f02005-11-17 14:52:34 +01001178 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001179
Takashi Iwai98274f02005-11-17 14:52:34 +01001180 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001181 spin_lock_irq (&hmidi->lock);
1182 hmidi->output = substream;
1183 spin_unlock_irq (&hmidi->lock);
1184
1185 return 0;
1186}
1187
Takashi Iwai98274f02005-11-17 14:52:34 +01001188static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
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
1192 snd_hdspm_midi_input_trigger (substream, 0);
1193
Takashi Iwai98274f02005-11-17 14:52:34 +01001194 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001195 spin_lock_irq (&hmidi->lock);
1196 hmidi->input = NULL;
1197 spin_unlock_irq (&hmidi->lock);
1198
1199 return 0;
1200}
1201
Takashi Iwai98274f02005-11-17 14:52:34 +01001202static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001203{
Takashi Iwai98274f02005-11-17 14:52:34 +01001204 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001205
1206 snd_hdspm_midi_output_trigger (substream, 0);
1207
Takashi Iwai98274f02005-11-17 14:52:34 +01001208 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001209 spin_lock_irq (&hmidi->lock);
1210 hmidi->output = NULL;
1211 spin_unlock_irq (&hmidi->lock);
1212
1213 return 0;
1214}
1215
Takashi Iwai98274f02005-11-17 14:52:34 +01001216static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001217{
1218 .open = snd_hdspm_midi_output_open,
1219 .close = snd_hdspm_midi_output_close,
1220 .trigger = snd_hdspm_midi_output_trigger,
1221};
1222
Takashi Iwai98274f02005-11-17 14:52:34 +01001223static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001224{
1225 .open = snd_hdspm_midi_input_open,
1226 .close = snd_hdspm_midi_input_close,
1227 .trigger = snd_hdspm_midi_input_trigger,
1228};
1229
Takashi Iwai98274f02005-11-17 14:52:34 +01001230static int __devinit snd_hdspm_create_midi (struct snd_card *card, struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001231{
1232 int err;
1233 char buf[32];
1234
1235 hdspm->midi[id].id = id;
1236 hdspm->midi[id].rmidi = NULL;
1237 hdspm->midi[id].input = NULL;
1238 hdspm->midi[id].output = NULL;
1239 hdspm->midi[id].hdspm = hdspm;
1240 hdspm->midi[id].istimer = 0;
1241 hdspm->midi[id].pending = 0;
1242 spin_lock_init (&hdspm->midi[id].lock);
1243
1244 sprintf (buf, "%s MIDI %d", card->shortname, id+1);
1245 if ((err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi)) < 0)
1246 return err;
1247
1248 sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);
1249 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
1250
1251 snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdspm_midi_output);
1252 snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdspm_midi_input);
1253
1254 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
1255 SNDRV_RAWMIDI_INFO_INPUT |
1256 SNDRV_RAWMIDI_INFO_DUPLEX;
1257
1258 return 0;
1259}
1260
1261
1262static void hdspm_midi_tasklet(unsigned long arg)
1263{
Takashi Iwai98274f02005-11-17 14:52:34 +01001264 struct hdspm *hdspm = (struct hdspm *)arg;
Takashi Iwai763f3562005-06-03 11:25:34 +02001265
1266 if (hdspm->midi[0].pending)
1267 snd_hdspm_midi_input_read (&hdspm->midi[0]);
1268 if (hdspm->midi[1].pending)
1269 snd_hdspm_midi_input_read (&hdspm->midi[1]);
1270}
1271
1272
1273/*-----------------------------------------------------------------------------
1274 Status Interface
1275 ----------------------------------------------------------------------------*/
1276
1277/* get the system sample rate which is set */
1278
1279#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001280{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001281 .name = xname, \
1282 .index = xindex, \
1283 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1284 .info = snd_hdspm_info_system_sample_rate, \
1285 .get = snd_hdspm_get_system_sample_rate \
1286}
1287
Takashi Iwai98274f02005-11-17 14:52:34 +01001288static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
1289 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001290{
1291 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1292 uinfo->count = 1;
1293 return 0;
1294}
1295
Takashi Iwai98274f02005-11-17 14:52:34 +01001296static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
1297 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02001298 ucontrol)
1299{
Takashi Iwai98274f02005-11-17 14:52:34 +01001300 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001301
1302 ucontrol->value.enumerated.item[0] = hdspm->system_sample_rate;
1303 return 0;
1304}
1305
1306#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001307{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001308 .name = xname, \
1309 .index = xindex, \
1310 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1311 .info = snd_hdspm_info_autosync_sample_rate, \
1312 .get = snd_hdspm_get_autosync_sample_rate \
1313}
1314
Takashi Iwai98274f02005-11-17 14:52:34 +01001315static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
1316 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001317{
1318 static char *texts[] = { "32000", "44100", "48000",
1319 "64000", "88200", "96000",
1320 "128000", "176400", "192000",
1321 "None"
1322 };
1323 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1324 uinfo->count = 1;
1325 uinfo->value.enumerated.items = 10;
1326 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1327 uinfo->value.enumerated.item =
1328 uinfo->value.enumerated.items - 1;
1329 strcpy(uinfo->value.enumerated.name,
1330 texts[uinfo->value.enumerated.item]);
1331 return 0;
1332}
1333
Takashi Iwai98274f02005-11-17 14:52:34 +01001334static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
1335 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02001336 ucontrol)
1337{
Takashi Iwai98274f02005-11-17 14:52:34 +01001338 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001339
1340 switch (hdspm_external_sample_rate(hdspm)) {
1341 case 32000:
1342 ucontrol->value.enumerated.item[0] = 0;
1343 break;
1344 case 44100:
1345 ucontrol->value.enumerated.item[0] = 1;
1346 break;
1347 case 48000:
1348 ucontrol->value.enumerated.item[0] = 2;
1349 break;
1350 case 64000:
1351 ucontrol->value.enumerated.item[0] = 3;
1352 break;
1353 case 88200:
1354 ucontrol->value.enumerated.item[0] = 4;
1355 break;
1356 case 96000:
1357 ucontrol->value.enumerated.item[0] = 5;
1358 break;
1359 case 128000:
1360 ucontrol->value.enumerated.item[0] = 6;
1361 break;
1362 case 176400:
1363 ucontrol->value.enumerated.item[0] = 7;
1364 break;
1365 case 192000:
1366 ucontrol->value.enumerated.item[0] = 8;
1367 break;
1368
1369 default:
1370 ucontrol->value.enumerated.item[0] = 9;
1371 }
1372 return 0;
1373}
1374
1375#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001376{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001377 .name = xname, \
1378 .index = xindex, \
1379 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1380 .info = snd_hdspm_info_system_clock_mode, \
1381 .get = snd_hdspm_get_system_clock_mode, \
1382}
1383
1384
1385
Takashi Iwai98274f02005-11-17 14:52:34 +01001386static int hdspm_system_clock_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001387{
1388 /* Always reflect the hardware info, rme is never wrong !!!! */
1389
1390 if (hdspm->control_register & HDSPM_ClockModeMaster)
1391 return 0;
1392 return 1;
1393}
1394
Takashi Iwai98274f02005-11-17 14:52:34 +01001395static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
1396 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001397{
1398 static char *texts[] = { "Master", "Slave" };
1399
1400 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1401 uinfo->count = 1;
1402 uinfo->value.enumerated.items = 2;
1403 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1404 uinfo->value.enumerated.item =
1405 uinfo->value.enumerated.items - 1;
1406 strcpy(uinfo->value.enumerated.name,
1407 texts[uinfo->value.enumerated.item]);
1408 return 0;
1409}
1410
Takashi Iwai98274f02005-11-17 14:52:34 +01001411static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
1412 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001413{
Takashi Iwai98274f02005-11-17 14:52:34 +01001414 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001415
1416 ucontrol->value.enumerated.item[0] =
1417 hdspm_system_clock_mode(hdspm);
1418 return 0;
1419}
1420
1421#define HDSPM_CLOCK_SOURCE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001422{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001423 .name = xname, \
1424 .index = xindex, \
1425 .info = snd_hdspm_info_clock_source, \
1426 .get = snd_hdspm_get_clock_source, \
1427 .put = snd_hdspm_put_clock_source \
1428}
1429
Takashi Iwai98274f02005-11-17 14:52:34 +01001430static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001431{
1432 if (hdspm->control_register & HDSPM_ClockModeMaster) {
1433 switch (hdspm->system_sample_rate) {
1434 case 32000:
1435 return 1;
1436 case 44100:
1437 return 2;
1438 case 48000:
1439 return 3;
1440 case 64000:
1441 return 4;
1442 case 88200:
1443 return 5;
1444 case 96000:
1445 return 6;
1446 case 128000:
1447 return 7;
1448 case 176400:
1449 return 8;
1450 case 192000:
1451 return 9;
1452 default:
1453 return 3;
1454 }
1455 } else {
1456 return 0;
1457 }
1458}
1459
Takashi Iwai98274f02005-11-17 14:52:34 +01001460static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02001461{
1462 int rate;
1463 switch (mode) {
1464
1465 case HDSPM_CLOCK_SOURCE_AUTOSYNC:
1466 if (hdspm_external_sample_rate(hdspm) != 0) {
1467 hdspm->control_register &= ~HDSPM_ClockModeMaster;
1468 hdspm_write(hdspm, HDSPM_controlRegister,
1469 hdspm->control_register);
1470 return 0;
1471 }
1472 return -1;
1473 case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
1474 rate = 32000;
1475 break;
1476 case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
1477 rate = 44100;
1478 break;
1479 case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
1480 rate = 48000;
1481 break;
1482 case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
1483 rate = 64000;
1484 break;
1485 case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
1486 rate = 88200;
1487 break;
1488 case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
1489 rate = 96000;
1490 break;
1491 case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
1492 rate = 128000;
1493 break;
1494 case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
1495 rate = 176400;
1496 break;
1497 case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
1498 rate = 192000;
1499 break;
1500
1501 default:
1502 rate = 44100;
1503 }
1504 hdspm->control_register |= HDSPM_ClockModeMaster;
1505 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1506 hdspm_set_rate(hdspm, rate, 1);
1507 return 0;
1508}
1509
Takashi Iwai98274f02005-11-17 14:52:34 +01001510static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
1511 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001512{
1513 static char *texts[] = { "AutoSync",
1514 "Internal 32.0 kHz", "Internal 44.1 kHz",
1515 "Internal 48.0 kHz",
1516 "Internal 64.0 kHz", "Internal 88.2 kHz",
1517 "Internal 96.0 kHz",
1518 "Internal 128.0 kHz", "Internal 176.4 kHz",
1519 "Internal 192.0 kHz"
1520 };
1521
1522 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1523 uinfo->count = 1;
1524 uinfo->value.enumerated.items = 10;
1525
1526 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1527 uinfo->value.enumerated.item =
1528 uinfo->value.enumerated.items - 1;
1529
1530 strcpy(uinfo->value.enumerated.name,
1531 texts[uinfo->value.enumerated.item]);
1532
1533 return 0;
1534}
1535
Takashi Iwai98274f02005-11-17 14:52:34 +01001536static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
1537 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001538{
Takashi Iwai98274f02005-11-17 14:52:34 +01001539 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001540
1541 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
1542 return 0;
1543}
1544
Takashi Iwai98274f02005-11-17 14:52:34 +01001545static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
1546 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001547{
Takashi Iwai98274f02005-11-17 14:52:34 +01001548 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001549 int change;
1550 int val;
1551
1552 if (!snd_hdspm_use_is_exclusive(hdspm))
1553 return -EBUSY;
1554 val = ucontrol->value.enumerated.item[0];
1555 if (val < 0)
1556 val = 0;
1557 if (val > 6)
1558 val = 6;
1559 spin_lock_irq(&hdspm->lock);
1560 if (val != hdspm_clock_source(hdspm))
1561 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
1562 else
1563 change = 0;
1564 spin_unlock_irq(&hdspm->lock);
1565 return change;
1566}
1567
1568#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001569{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001570 .name = xname, \
1571 .index = xindex, \
1572 .info = snd_hdspm_info_pref_sync_ref, \
1573 .get = snd_hdspm_get_pref_sync_ref, \
1574 .put = snd_hdspm_put_pref_sync_ref \
1575}
1576
Takashi Iwai98274f02005-11-17 14:52:34 +01001577static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001578{
1579 /* Notice that this looks at the requested sync source,
1580 not the one actually in use.
1581 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001582 if (hdspm->is_aes32) {
1583 switch (hdspm->control_register & HDSPM_SyncRefMask) {
1584 /* number gives AES index, except for 0 which
1585 corresponds to WordClock */
1586 case 0: return 0;
1587 case HDSPM_SyncRef0: return 1;
1588 case HDSPM_SyncRef1: return 2;
1589 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3;
1590 case HDSPM_SyncRef2: return 4;
1591 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5;
1592 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6;
1593 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0: return 7;
1594 case HDSPM_SyncRef3: return 8;
1595 }
1596 } else {
1597 switch (hdspm->control_register & HDSPM_SyncRefMask) {
1598 case HDSPM_SyncRef_Word:
1599 return HDSPM_SYNC_FROM_WORD;
1600 case HDSPM_SyncRef_MADI:
1601 return HDSPM_SYNC_FROM_MADI;
1602 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001603 }
1604
1605 return HDSPM_SYNC_FROM_WORD;
1606}
1607
Takashi Iwai98274f02005-11-17 14:52:34 +01001608static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02001609{
1610 hdspm->control_register &= ~HDSPM_SyncRefMask;
1611
Remy Bruno3cee5a62006-10-16 12:46:32 +02001612 if (hdspm->is_aes32) {
1613 switch (pref) {
1614 case 0:
1615 hdspm->control_register |= 0;
1616 break;
1617 case 1:
1618 hdspm->control_register |= HDSPM_SyncRef0;
1619 break;
1620 case 2:
1621 hdspm->control_register |= HDSPM_SyncRef1;
1622 break;
1623 case 3:
1624 hdspm->control_register |= HDSPM_SyncRef1+HDSPM_SyncRef0;
1625 break;
1626 case 4:
1627 hdspm->control_register |= HDSPM_SyncRef2;
1628 break;
1629 case 5:
1630 hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef0;
1631 break;
1632 case 6:
1633 hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1;
1634 break;
1635 case 7:
1636 hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
1637 break;
1638 case 8:
1639 hdspm->control_register |= HDSPM_SyncRef3;
1640 break;
1641 default:
1642 return -1;
1643 }
1644 } else {
1645 switch (pref) {
1646 case HDSPM_SYNC_FROM_MADI:
1647 hdspm->control_register |= HDSPM_SyncRef_MADI;
1648 break;
1649 case HDSPM_SYNC_FROM_WORD:
1650 hdspm->control_register |= HDSPM_SyncRef_Word;
1651 break;
1652 default:
1653 return -1;
1654 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001655 }
1656 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1657 return 0;
1658}
1659
Takashi Iwai98274f02005-11-17 14:52:34 +01001660static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
1661 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001662{
Remy Bruno3cee5a62006-10-16 12:46:32 +02001663 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001664
Remy Bruno3cee5a62006-10-16 12:46:32 +02001665 if (hdspm->is_aes32) {
1666 static char *texts[] = { "Word", "AES1", "AES2", "AES3",
1667 "AES4", "AES5", "AES6", "AES7", "AES8" };
Takashi Iwai763f3562005-06-03 11:25:34 +02001668
Remy Bruno3cee5a62006-10-16 12:46:32 +02001669 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1670 uinfo->count = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02001671
Remy Bruno3cee5a62006-10-16 12:46:32 +02001672 uinfo->value.enumerated.items = 9;
1673
1674 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1675 uinfo->value.enumerated.item =
1676 uinfo->value.enumerated.items - 1;
1677 strcpy(uinfo->value.enumerated.name,
1678 texts[uinfo->value.enumerated.item]);
1679 } else {
1680 static char *texts[] = { "Word", "MADI" };
1681
1682 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1683 uinfo->count = 1;
1684
1685 uinfo->value.enumerated.items = 2;
1686
1687 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1688 uinfo->value.enumerated.item =
1689 uinfo->value.enumerated.items - 1;
1690 strcpy(uinfo->value.enumerated.name,
1691 texts[uinfo->value.enumerated.item]);
1692 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001693 return 0;
1694}
1695
Takashi Iwai98274f02005-11-17 14:52:34 +01001696static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
1697 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001698{
Takashi Iwai98274f02005-11-17 14:52:34 +01001699 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001700
1701 ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
1702 return 0;
1703}
1704
Takashi Iwai98274f02005-11-17 14:52:34 +01001705static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
1706 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001707{
Takashi Iwai98274f02005-11-17 14:52:34 +01001708 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001709 int change, max;
1710 unsigned int val;
1711
Remy Bruno3cee5a62006-10-16 12:46:32 +02001712 max = hdspm->is_aes32 ? 9 : 2;
Takashi Iwai763f3562005-06-03 11:25:34 +02001713
1714 if (!snd_hdspm_use_is_exclusive(hdspm))
1715 return -EBUSY;
1716
1717 val = ucontrol->value.enumerated.item[0] % max;
1718
1719 spin_lock_irq(&hdspm->lock);
1720 change = (int) val != hdspm_pref_sync_ref(hdspm);
1721 hdspm_set_pref_sync_ref(hdspm, val);
1722 spin_unlock_irq(&hdspm->lock);
1723 return change;
1724}
1725
1726#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001727{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001728 .name = xname, \
1729 .index = xindex, \
1730 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1731 .info = snd_hdspm_info_autosync_ref, \
1732 .get = snd_hdspm_get_autosync_ref, \
1733}
1734
Takashi Iwai98274f02005-11-17 14:52:34 +01001735static int hdspm_autosync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001736{
Remy Bruno3cee5a62006-10-16 12:46:32 +02001737 if (hdspm->is_aes32) {
1738 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
1739 unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & 0xF;
1740 if (syncref == 0)
1741 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
1742 if (syncref <= 8)
1743 return syncref;
1744 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
1745 } else {
1746 /* This looks at the autosync selected sync reference */
1747 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Takashi Iwai763f3562005-06-03 11:25:34 +02001748
Remy Bruno3cee5a62006-10-16 12:46:32 +02001749 switch (status2 & HDSPM_SelSyncRefMask) {
1750 case HDSPM_SelSyncRef_WORD:
1751 return HDSPM_AUTOSYNC_FROM_WORD;
1752 case HDSPM_SelSyncRef_MADI:
1753 return HDSPM_AUTOSYNC_FROM_MADI;
1754 case HDSPM_SelSyncRef_NVALID:
1755 return HDSPM_AUTOSYNC_FROM_NONE;
1756 default:
1757 return 0;
1758 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001759
Takashi Iwai763f3562005-06-03 11:25:34 +02001760 return 0;
1761 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001762}
1763
Takashi Iwai98274f02005-11-17 14:52:34 +01001764static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
1765 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001766{
Remy Bruno3cee5a62006-10-16 12:46:32 +02001767 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001768
Remy Bruno3cee5a62006-10-16 12:46:32 +02001769 if (hdspm->is_aes32) {
1770 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
1771 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
1772
1773 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1774 uinfo->count = 1;
1775 uinfo->value.enumerated.items = 10;
1776 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1777 uinfo->value.enumerated.item =
1778 uinfo->value.enumerated.items - 1;
1779 strcpy(uinfo->value.enumerated.name,
1780 texts[uinfo->value.enumerated.item]);
1781 }
1782 else
1783 {
1784 static char *texts[] = { "WordClock", "MADI", "None" };
1785
1786 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1787 uinfo->count = 1;
1788 uinfo->value.enumerated.items = 3;
1789 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1790 uinfo->value.enumerated.item =
1791 uinfo->value.enumerated.items - 1;
1792 strcpy(uinfo->value.enumerated.name,
1793 texts[uinfo->value.enumerated.item]);
1794 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001795 return 0;
1796}
1797
Takashi Iwai98274f02005-11-17 14:52:34 +01001798static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
1799 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001800{
Takashi Iwai98274f02005-11-17 14:52:34 +01001801 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001802
1803 ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
1804 return 0;
1805}
1806
1807#define HDSPM_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001808{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001809 .name = xname, \
1810 .index = xindex, \
1811 .info = snd_hdspm_info_line_out, \
1812 .get = snd_hdspm_get_line_out, \
1813 .put = snd_hdspm_put_line_out \
1814}
1815
Takashi Iwai98274f02005-11-17 14:52:34 +01001816static int hdspm_line_out(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001817{
1818 return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
1819}
1820
1821
Takashi Iwai98274f02005-11-17 14:52:34 +01001822static int hdspm_set_line_output(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001823{
1824 if (out)
1825 hdspm->control_register |= HDSPM_LineOut;
1826 else
1827 hdspm->control_register &= ~HDSPM_LineOut;
1828 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1829
1830 return 0;
1831}
1832
Takashi Iwai98274f02005-11-17 14:52:34 +01001833static int snd_hdspm_info_line_out(struct snd_kcontrol *kcontrol,
1834 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001835{
1836 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1837 uinfo->count = 1;
1838 uinfo->value.integer.min = 0;
1839 uinfo->value.integer.max = 1;
1840 return 0;
1841}
1842
Takashi Iwai98274f02005-11-17 14:52:34 +01001843static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
1844 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001845{
Takashi Iwai98274f02005-11-17 14:52:34 +01001846 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001847
1848 spin_lock_irq(&hdspm->lock);
1849 ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
1850 spin_unlock_irq(&hdspm->lock);
1851 return 0;
1852}
1853
Takashi Iwai98274f02005-11-17 14:52:34 +01001854static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
1855 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001856{
Takashi Iwai98274f02005-11-17 14:52:34 +01001857 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001858 int change;
1859 unsigned int val;
1860
1861 if (!snd_hdspm_use_is_exclusive(hdspm))
1862 return -EBUSY;
1863 val = ucontrol->value.integer.value[0] & 1;
1864 spin_lock_irq(&hdspm->lock);
1865 change = (int) val != hdspm_line_out(hdspm);
1866 hdspm_set_line_output(hdspm, val);
1867 spin_unlock_irq(&hdspm->lock);
1868 return change;
1869}
1870
1871#define HDSPM_TX_64(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001872{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001873 .name = xname, \
1874 .index = xindex, \
1875 .info = snd_hdspm_info_tx_64, \
1876 .get = snd_hdspm_get_tx_64, \
1877 .put = snd_hdspm_put_tx_64 \
1878}
1879
Takashi Iwai98274f02005-11-17 14:52:34 +01001880static int hdspm_tx_64(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001881{
1882 return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
1883}
1884
Takashi Iwai98274f02005-11-17 14:52:34 +01001885static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001886{
1887 if (out)
1888 hdspm->control_register |= HDSPM_TX_64ch;
1889 else
1890 hdspm->control_register &= ~HDSPM_TX_64ch;
1891 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1892
1893 return 0;
1894}
1895
Takashi Iwai98274f02005-11-17 14:52:34 +01001896static int snd_hdspm_info_tx_64(struct snd_kcontrol *kcontrol,
1897 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001898{
1899 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1900 uinfo->count = 1;
1901 uinfo->value.integer.min = 0;
1902 uinfo->value.integer.max = 1;
1903 return 0;
1904}
1905
Takashi Iwai98274f02005-11-17 14:52:34 +01001906static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
1907 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001908{
Takashi Iwai98274f02005-11-17 14:52:34 +01001909 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001910
1911 spin_lock_irq(&hdspm->lock);
1912 ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
1913 spin_unlock_irq(&hdspm->lock);
1914 return 0;
1915}
1916
Takashi Iwai98274f02005-11-17 14:52:34 +01001917static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
1918 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001919{
Takashi Iwai98274f02005-11-17 14:52:34 +01001920 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001921 int change;
1922 unsigned int val;
1923
1924 if (!snd_hdspm_use_is_exclusive(hdspm))
1925 return -EBUSY;
1926 val = ucontrol->value.integer.value[0] & 1;
1927 spin_lock_irq(&hdspm->lock);
1928 change = (int) val != hdspm_tx_64(hdspm);
1929 hdspm_set_tx_64(hdspm, val);
1930 spin_unlock_irq(&hdspm->lock);
1931 return change;
1932}
1933
1934#define HDSPM_C_TMS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001935{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001936 .name = xname, \
1937 .index = xindex, \
1938 .info = snd_hdspm_info_c_tms, \
1939 .get = snd_hdspm_get_c_tms, \
1940 .put = snd_hdspm_put_c_tms \
1941}
1942
Takashi Iwai98274f02005-11-17 14:52:34 +01001943static int hdspm_c_tms(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001944{
1945 return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
1946}
1947
Takashi Iwai98274f02005-11-17 14:52:34 +01001948static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001949{
1950 if (out)
1951 hdspm->control_register |= HDSPM_clr_tms;
1952 else
1953 hdspm->control_register &= ~HDSPM_clr_tms;
1954 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1955
1956 return 0;
1957}
1958
Takashi Iwai98274f02005-11-17 14:52:34 +01001959static int snd_hdspm_info_c_tms(struct snd_kcontrol *kcontrol,
1960 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001961{
1962 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1963 uinfo->count = 1;
1964 uinfo->value.integer.min = 0;
1965 uinfo->value.integer.max = 1;
1966 return 0;
1967}
1968
Takashi Iwai98274f02005-11-17 14:52:34 +01001969static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
1970 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001971{
Takashi Iwai98274f02005-11-17 14:52:34 +01001972 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001973
1974 spin_lock_irq(&hdspm->lock);
1975 ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
1976 spin_unlock_irq(&hdspm->lock);
1977 return 0;
1978}
1979
Takashi Iwai98274f02005-11-17 14:52:34 +01001980static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
1981 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001982{
Takashi Iwai98274f02005-11-17 14:52:34 +01001983 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001984 int change;
1985 unsigned int val;
1986
1987 if (!snd_hdspm_use_is_exclusive(hdspm))
1988 return -EBUSY;
1989 val = ucontrol->value.integer.value[0] & 1;
1990 spin_lock_irq(&hdspm->lock);
1991 change = (int) val != hdspm_c_tms(hdspm);
1992 hdspm_set_c_tms(hdspm, val);
1993 spin_unlock_irq(&hdspm->lock);
1994 return change;
1995}
1996
1997#define HDSPM_SAFE_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001998{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001999 .name = xname, \
2000 .index = xindex, \
2001 .info = snd_hdspm_info_safe_mode, \
2002 .get = snd_hdspm_get_safe_mode, \
2003 .put = snd_hdspm_put_safe_mode \
2004}
2005
Takashi Iwai98274f02005-11-17 14:52:34 +01002006static int hdspm_safe_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002007{
2008 return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
2009}
2010
Takashi Iwai98274f02005-11-17 14:52:34 +01002011static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002012{
2013 if (out)
2014 hdspm->control_register |= HDSPM_AutoInp;
2015 else
2016 hdspm->control_register &= ~HDSPM_AutoInp;
2017 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2018
2019 return 0;
2020}
2021
Takashi Iwai98274f02005-11-17 14:52:34 +01002022static int snd_hdspm_info_safe_mode(struct snd_kcontrol *kcontrol,
2023 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002024{
2025 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2026 uinfo->count = 1;
2027 uinfo->value.integer.min = 0;
2028 uinfo->value.integer.max = 1;
2029 return 0;
2030}
2031
Takashi Iwai98274f02005-11-17 14:52:34 +01002032static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
2033 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002034{
Takashi Iwai98274f02005-11-17 14:52:34 +01002035 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002036
2037 spin_lock_irq(&hdspm->lock);
2038 ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
2039 spin_unlock_irq(&hdspm->lock);
2040 return 0;
2041}
2042
Takashi Iwai98274f02005-11-17 14:52:34 +01002043static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
2044 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002045{
Takashi Iwai98274f02005-11-17 14:52:34 +01002046 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002047 int change;
2048 unsigned int val;
2049
2050 if (!snd_hdspm_use_is_exclusive(hdspm))
2051 return -EBUSY;
2052 val = ucontrol->value.integer.value[0] & 1;
2053 spin_lock_irq(&hdspm->lock);
2054 change = (int) val != hdspm_safe_mode(hdspm);
2055 hdspm_set_safe_mode(hdspm, val);
2056 spin_unlock_irq(&hdspm->lock);
2057 return change;
2058}
2059
Remy Bruno3cee5a62006-10-16 12:46:32 +02002060#define HDSPM_EMPHASIS(xname, xindex) \
2061{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2062 .name = xname, \
2063 .index = xindex, \
2064 .info = snd_hdspm_info_emphasis, \
2065 .get = snd_hdspm_get_emphasis, \
2066 .put = snd_hdspm_put_emphasis \
2067}
2068
2069static int hdspm_emphasis(struct hdspm * hdspm)
2070{
2071 return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0;
2072}
2073
2074static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
2075{
2076 if (emp)
2077 hdspm->control_register |= HDSPM_Emphasis;
2078 else
2079 hdspm->control_register &= ~HDSPM_Emphasis;
2080 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2081
2082 return 0;
2083}
2084
2085static int snd_hdspm_info_emphasis(struct snd_kcontrol *kcontrol,
2086 struct snd_ctl_elem_info *uinfo)
2087{
2088 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2089 uinfo->count = 1;
2090 uinfo->value.integer.min = 0;
2091 uinfo->value.integer.max = 1;
2092 return 0;
2093}
2094
2095static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
2096 struct snd_ctl_elem_value *ucontrol)
2097{
2098 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2099
2100 spin_lock_irq(&hdspm->lock);
2101 ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm);
2102 spin_unlock_irq(&hdspm->lock);
2103 return 0;
2104}
2105
2106static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
2107 struct snd_ctl_elem_value *ucontrol)
2108{
2109 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2110 int change;
2111 unsigned int val;
2112
2113 if (!snd_hdspm_use_is_exclusive(hdspm))
2114 return -EBUSY;
2115 val = ucontrol->value.integer.value[0] & 1;
2116 spin_lock_irq(&hdspm->lock);
2117 change = (int) val != hdspm_emphasis(hdspm);
2118 hdspm_set_emphasis(hdspm, val);
2119 spin_unlock_irq(&hdspm->lock);
2120 return change;
2121}
2122
2123#define HDSPM_DOLBY(xname, xindex) \
2124{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2125 .name = xname, \
2126 .index = xindex, \
2127 .info = snd_hdspm_info_dolby, \
2128 .get = snd_hdspm_get_dolby, \
2129 .put = snd_hdspm_put_dolby \
2130}
2131
2132static int hdspm_dolby(struct hdspm * hdspm)
2133{
2134 return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0;
2135}
2136
2137static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
2138{
2139 if (dol)
2140 hdspm->control_register |= HDSPM_Dolby;
2141 else
2142 hdspm->control_register &= ~HDSPM_Dolby;
2143 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2144
2145 return 0;
2146}
2147
2148static int snd_hdspm_info_dolby(struct snd_kcontrol *kcontrol,
2149 struct snd_ctl_elem_info *uinfo)
2150{
2151 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2152 uinfo->count = 1;
2153 uinfo->value.integer.min = 0;
2154 uinfo->value.integer.max = 1;
2155 return 0;
2156}
2157
2158static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
2159 struct snd_ctl_elem_value *ucontrol)
2160{
2161 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2162
2163 spin_lock_irq(&hdspm->lock);
2164 ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm);
2165 spin_unlock_irq(&hdspm->lock);
2166 return 0;
2167}
2168
2169static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
2170 struct snd_ctl_elem_value *ucontrol)
2171{
2172 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2173 int change;
2174 unsigned int val;
2175
2176 if (!snd_hdspm_use_is_exclusive(hdspm))
2177 return -EBUSY;
2178 val = ucontrol->value.integer.value[0] & 1;
2179 spin_lock_irq(&hdspm->lock);
2180 change = (int) val != hdspm_dolby(hdspm);
2181 hdspm_set_dolby(hdspm, val);
2182 spin_unlock_irq(&hdspm->lock);
2183 return change;
2184}
2185
2186#define HDSPM_PROFESSIONAL(xname, xindex) \
2187{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2188 .name = xname, \
2189 .index = xindex, \
2190 .info = snd_hdspm_info_professional, \
2191 .get = snd_hdspm_get_professional, \
2192 .put = snd_hdspm_put_professional \
2193}
2194
2195static int hdspm_professional(struct hdspm * hdspm)
2196{
2197 return (hdspm->control_register & HDSPM_Professional) ? 1 : 0;
2198}
2199
2200static int hdspm_set_professional(struct hdspm * hdspm, int dol)
2201{
2202 if (dol)
2203 hdspm->control_register |= HDSPM_Professional;
2204 else
2205 hdspm->control_register &= ~HDSPM_Professional;
2206 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2207
2208 return 0;
2209}
2210
2211static int snd_hdspm_info_professional(struct snd_kcontrol *kcontrol,
2212 struct snd_ctl_elem_info *uinfo)
2213{
2214 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2215 uinfo->count = 1;
2216 uinfo->value.integer.min = 0;
2217 uinfo->value.integer.max = 1;
2218 return 0;
2219}
2220
2221static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
2222 struct snd_ctl_elem_value *ucontrol)
2223{
2224 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2225
2226 spin_lock_irq(&hdspm->lock);
2227 ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm);
2228 spin_unlock_irq(&hdspm->lock);
2229 return 0;
2230}
2231
2232static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
2233 struct snd_ctl_elem_value *ucontrol)
2234{
2235 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2236 int change;
2237 unsigned int val;
2238
2239 if (!snd_hdspm_use_is_exclusive(hdspm))
2240 return -EBUSY;
2241 val = ucontrol->value.integer.value[0] & 1;
2242 spin_lock_irq(&hdspm->lock);
2243 change = (int) val != hdspm_professional(hdspm);
2244 hdspm_set_professional(hdspm, val);
2245 spin_unlock_irq(&hdspm->lock);
2246 return change;
2247}
2248
Takashi Iwai763f3562005-06-03 11:25:34 +02002249#define HDSPM_INPUT_SELECT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002250{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002251 .name = xname, \
2252 .index = xindex, \
2253 .info = snd_hdspm_info_input_select, \
2254 .get = snd_hdspm_get_input_select, \
2255 .put = snd_hdspm_put_input_select \
2256}
2257
Takashi Iwai98274f02005-11-17 14:52:34 +01002258static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002259{
2260 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
2261}
2262
Takashi Iwai98274f02005-11-17 14:52:34 +01002263static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002264{
2265 if (out)
2266 hdspm->control_register |= HDSPM_InputSelect0;
2267 else
2268 hdspm->control_register &= ~HDSPM_InputSelect0;
2269 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2270
2271 return 0;
2272}
2273
Takashi Iwai98274f02005-11-17 14:52:34 +01002274static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
2275 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002276{
2277 static char *texts[] = { "optical", "coaxial" };
2278
2279 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2280 uinfo->count = 1;
2281 uinfo->value.enumerated.items = 2;
2282
2283 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2284 uinfo->value.enumerated.item =
2285 uinfo->value.enumerated.items - 1;
2286 strcpy(uinfo->value.enumerated.name,
2287 texts[uinfo->value.enumerated.item]);
2288
2289 return 0;
2290}
2291
Takashi Iwai98274f02005-11-17 14:52:34 +01002292static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
2293 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002294{
Takashi Iwai98274f02005-11-17 14:52:34 +01002295 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002296
2297 spin_lock_irq(&hdspm->lock);
2298 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
2299 spin_unlock_irq(&hdspm->lock);
2300 return 0;
2301}
2302
Takashi Iwai98274f02005-11-17 14:52:34 +01002303static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
2304 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002305{
Takashi Iwai98274f02005-11-17 14:52:34 +01002306 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002307 int change;
2308 unsigned int val;
2309
2310 if (!snd_hdspm_use_is_exclusive(hdspm))
2311 return -EBUSY;
2312 val = ucontrol->value.integer.value[0] & 1;
2313 spin_lock_irq(&hdspm->lock);
2314 change = (int) val != hdspm_input_select(hdspm);
2315 hdspm_set_input_select(hdspm, val);
2316 spin_unlock_irq(&hdspm->lock);
2317 return change;
2318}
2319
Remy Bruno3cee5a62006-10-16 12:46:32 +02002320#define HDSPM_DS_WIRE(xname, xindex) \
2321{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2322 .name = xname, \
2323 .index = xindex, \
2324 .info = snd_hdspm_info_ds_wire, \
2325 .get = snd_hdspm_get_ds_wire, \
2326 .put = snd_hdspm_put_ds_wire \
2327}
2328
2329static int hdspm_ds_wire(struct hdspm * hdspm)
2330{
2331 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
2332}
2333
2334static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
2335{
2336 if (ds)
2337 hdspm->control_register |= HDSPM_DS_DoubleWire;
2338 else
2339 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
2340 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2341
2342 return 0;
2343}
2344
2345static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
2346 struct snd_ctl_elem_info *uinfo)
2347{
2348 static char *texts[] = { "Single", "Double" };
2349
2350 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2351 uinfo->count = 1;
2352 uinfo->value.enumerated.items = 2;
2353
2354 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2355 uinfo->value.enumerated.item =
2356 uinfo->value.enumerated.items - 1;
2357 strcpy(uinfo->value.enumerated.name,
2358 texts[uinfo->value.enumerated.item]);
2359
2360 return 0;
2361}
2362
2363static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
2364 struct snd_ctl_elem_value *ucontrol)
2365{
2366 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2367
2368 spin_lock_irq(&hdspm->lock);
2369 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
2370 spin_unlock_irq(&hdspm->lock);
2371 return 0;
2372}
2373
2374static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
2375 struct snd_ctl_elem_value *ucontrol)
2376{
2377 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2378 int change;
2379 unsigned int val;
2380
2381 if (!snd_hdspm_use_is_exclusive(hdspm))
2382 return -EBUSY;
2383 val = ucontrol->value.integer.value[0] & 1;
2384 spin_lock_irq(&hdspm->lock);
2385 change = (int) val != hdspm_ds_wire(hdspm);
2386 hdspm_set_ds_wire(hdspm, val);
2387 spin_unlock_irq(&hdspm->lock);
2388 return change;
2389}
2390
2391#define HDSPM_QS_WIRE(xname, xindex) \
2392{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2393 .name = xname, \
2394 .index = xindex, \
2395 .info = snd_hdspm_info_qs_wire, \
2396 .get = snd_hdspm_get_qs_wire, \
2397 .put = snd_hdspm_put_qs_wire \
2398}
2399
2400static int hdspm_qs_wire(struct hdspm * hdspm)
2401{
2402 if (hdspm->control_register & HDSPM_QS_DoubleWire)
2403 return 1;
2404 if (hdspm->control_register & HDSPM_QS_QuadWire)
2405 return 2;
2406 return 0;
2407}
2408
2409static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
2410{
2411 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
2412 switch (mode) {
2413 case 0:
2414 break;
2415 case 1:
2416 hdspm->control_register |= HDSPM_QS_DoubleWire;
2417 break;
2418 case 2:
2419 hdspm->control_register |= HDSPM_QS_QuadWire;
2420 break;
2421 }
2422 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2423
2424 return 0;
2425}
2426
2427static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
2428 struct snd_ctl_elem_info *uinfo)
2429{
2430 static char *texts[] = { "Single", "Double", "Quad" };
2431
2432 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2433 uinfo->count = 1;
2434 uinfo->value.enumerated.items = 3;
2435
2436 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2437 uinfo->value.enumerated.item =
2438 uinfo->value.enumerated.items - 1;
2439 strcpy(uinfo->value.enumerated.name,
2440 texts[uinfo->value.enumerated.item]);
2441
2442 return 0;
2443}
2444
2445static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
2446 struct snd_ctl_elem_value *ucontrol)
2447{
2448 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2449
2450 spin_lock_irq(&hdspm->lock);
2451 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
2452 spin_unlock_irq(&hdspm->lock);
2453 return 0;
2454}
2455
2456static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
2457 struct snd_ctl_elem_value *ucontrol)
2458{
2459 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2460 int change;
2461 int val;
2462
2463 if (!snd_hdspm_use_is_exclusive(hdspm))
2464 return -EBUSY;
2465 val = ucontrol->value.integer.value[0];
2466 if (val < 0)
2467 val = 0;
2468 if (val > 2)
2469 val = 2;
2470 spin_lock_irq(&hdspm->lock);
2471 change = (int) val != hdspm_qs_wire(hdspm);
2472 hdspm_set_qs_wire(hdspm, val);
2473 spin_unlock_irq(&hdspm->lock);
2474 return change;
2475}
2476
Takashi Iwai763f3562005-06-03 11:25:34 +02002477/* Simple Mixer
2478 deprecated since to much faders ???
2479 MIXER interface says output (source, destination, value)
2480 where source > MAX_channels are playback channels
2481 on MADICARD
2482 - playback mixer matrix: [channelout+64] [output] [value]
2483 - input(thru) mixer matrix: [channelin] [output] [value]
2484 (better do 2 kontrols for seperation ?)
2485*/
2486
2487#define HDSPM_MIXER(xname, xindex) \
2488{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
2489 .name = xname, \
2490 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002491 .device = 0, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002492 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
2493 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2494 .info = snd_hdspm_info_mixer, \
2495 .get = snd_hdspm_get_mixer, \
2496 .put = snd_hdspm_put_mixer \
2497}
2498
Takashi Iwai98274f02005-11-17 14:52:34 +01002499static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
2500 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002501{
2502 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2503 uinfo->count = 3;
2504 uinfo->value.integer.min = 0;
2505 uinfo->value.integer.max = 65535;
2506 uinfo->value.integer.step = 1;
2507 return 0;
2508}
2509
Takashi Iwai98274f02005-11-17 14:52:34 +01002510static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
2511 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002512{
Takashi Iwai98274f02005-11-17 14:52:34 +01002513 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002514 int source;
2515 int destination;
2516
2517 source = ucontrol->value.integer.value[0];
2518 if (source < 0)
2519 source = 0;
2520 else if (source >= 2 * HDSPM_MAX_CHANNELS)
2521 source = 2 * HDSPM_MAX_CHANNELS - 1;
2522
2523 destination = ucontrol->value.integer.value[1];
2524 if (destination < 0)
2525 destination = 0;
2526 else if (destination >= HDSPM_MAX_CHANNELS)
2527 destination = HDSPM_MAX_CHANNELS - 1;
2528
2529 spin_lock_irq(&hdspm->lock);
2530 if (source >= HDSPM_MAX_CHANNELS)
2531 ucontrol->value.integer.value[2] =
2532 hdspm_read_pb_gain(hdspm, destination,
2533 source - HDSPM_MAX_CHANNELS);
2534 else
2535 ucontrol->value.integer.value[2] =
2536 hdspm_read_in_gain(hdspm, destination, source);
2537
2538 spin_unlock_irq(&hdspm->lock);
2539
2540 return 0;
2541}
2542
Takashi Iwai98274f02005-11-17 14:52:34 +01002543static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
2544 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002545{
Takashi Iwai98274f02005-11-17 14:52:34 +01002546 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002547 int change;
2548 int source;
2549 int destination;
2550 int gain;
2551
2552 if (!snd_hdspm_use_is_exclusive(hdspm))
2553 return -EBUSY;
2554
2555 source = ucontrol->value.integer.value[0];
2556 destination = ucontrol->value.integer.value[1];
2557
2558 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
2559 return -1;
2560 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
2561 return -1;
2562
2563 gain = ucontrol->value.integer.value[2];
2564
2565 spin_lock_irq(&hdspm->lock);
2566
2567 if (source >= HDSPM_MAX_CHANNELS)
2568 change = gain != hdspm_read_pb_gain(hdspm, destination,
2569 source -
2570 HDSPM_MAX_CHANNELS);
2571 else
2572 change =
2573 gain != hdspm_read_in_gain(hdspm, destination, source);
2574
2575 if (change) {
2576 if (source >= HDSPM_MAX_CHANNELS)
2577 hdspm_write_pb_gain(hdspm, destination,
2578 source - HDSPM_MAX_CHANNELS,
2579 gain);
2580 else
2581 hdspm_write_in_gain(hdspm, destination, source,
2582 gain);
2583 }
2584 spin_unlock_irq(&hdspm->lock);
2585
2586 return change;
2587}
2588
2589/* The simple mixer control(s) provide gain control for the
2590 basic 1:1 mappings of playback streams to output
2591 streams.
2592*/
2593
2594#define HDSPM_PLAYBACK_MIXER \
2595{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2596 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
2597 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2598 .info = snd_hdspm_info_playback_mixer, \
2599 .get = snd_hdspm_get_playback_mixer, \
2600 .put = snd_hdspm_put_playback_mixer \
2601}
2602
Takashi Iwai98274f02005-11-17 14:52:34 +01002603static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
2604 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002605{
2606 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2607 uinfo->count = 1;
2608 uinfo->value.integer.min = 0;
2609 uinfo->value.integer.max = 65536;
2610 uinfo->value.integer.step = 1;
2611 return 0;
2612}
2613
Takashi Iwai98274f02005-11-17 14:52:34 +01002614static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
2615 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002616{
Takashi Iwai98274f02005-11-17 14:52:34 +01002617 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002618 int channel;
2619 int mapped_channel;
2620
2621 channel = ucontrol->id.index - 1;
2622
2623 snd_assert(channel >= 0
2624 || channel < HDSPM_MAX_CHANNELS, return -EINVAL);
2625
2626 if ((mapped_channel = hdspm->channel_map[channel]) < 0)
2627 return -EINVAL;
2628
2629 spin_lock_irq(&hdspm->lock);
2630 ucontrol->value.integer.value[0] =
2631 hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel);
2632 spin_unlock_irq(&hdspm->lock);
2633
2634 /* snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, value %d\n",
2635 ucontrol->id.index, channel, mapped_channel, ucontrol->value.integer.value[0]);
2636 */
2637
2638 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
2658 if ((mapped_channel = hdspm->channel_map[channel]) < 0)
2659 return -EINVAL;
2660
2661 gain = ucontrol->value.integer.value[0];
2662
2663 spin_lock_irq(&hdspm->lock);
2664 change =
2665 gain != hdspm_read_pb_gain(hdspm, mapped_channel,
2666 mapped_channel);
2667 if (change)
2668 hdspm_write_pb_gain(hdspm, mapped_channel, mapped_channel,
2669 gain);
2670 spin_unlock_irq(&hdspm->lock);
2671 return change;
2672}
2673
2674#define HDSPM_WC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002675{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002676 .name = xname, \
2677 .index = xindex, \
2678 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2679 .info = snd_hdspm_info_sync_check, \
2680 .get = snd_hdspm_get_wc_sync_check \
2681}
2682
Takashi Iwai98274f02005-11-17 14:52:34 +01002683static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
2684 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002685{
2686 static char *texts[] = { "No Lock", "Lock", "Sync" };
2687 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2688 uinfo->count = 1;
2689 uinfo->value.enumerated.items = 3;
2690 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2691 uinfo->value.enumerated.item =
2692 uinfo->value.enumerated.items - 1;
2693 strcpy(uinfo->value.enumerated.name,
2694 texts[uinfo->value.enumerated.item]);
2695 return 0;
2696}
2697
Takashi Iwai98274f02005-11-17 14:52:34 +01002698static int hdspm_wc_sync_check(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002699{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002700 if (hdspm->is_aes32) {
2701 int status = hdspm_read(hdspm, HDSPM_statusRegister);
2702 if (status & HDSPM_AES32_wcLock) {
2703 /* I don't know how to differenciate sync from lock.
2704 Doing as if sync for now */
Takashi Iwai763f3562005-06-03 11:25:34 +02002705 return 2;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002706 }
2707 return 0;
2708 } else {
2709 int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
2710 if (status2 & HDSPM_wcLock) {
2711 if (status2 & HDSPM_wcSync)
2712 return 2;
2713 else
2714 return 1;
2715 }
2716 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002717 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002718}
2719
Takashi Iwai98274f02005-11-17 14:52:34 +01002720static int snd_hdspm_get_wc_sync_check(struct snd_kcontrol *kcontrol,
2721 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002722{
Takashi Iwai98274f02005-11-17 14:52:34 +01002723 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002724
2725 ucontrol->value.enumerated.item[0] = hdspm_wc_sync_check(hdspm);
2726 return 0;
2727}
2728
2729
2730#define HDSPM_MADI_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002731{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002732 .name = xname, \
2733 .index = xindex, \
2734 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2735 .info = snd_hdspm_info_sync_check, \
2736 .get = snd_hdspm_get_madisync_sync_check \
2737}
2738
Takashi Iwai98274f02005-11-17 14:52:34 +01002739static int hdspm_madisync_sync_check(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002740{
2741 int status = hdspm_read(hdspm, HDSPM_statusRegister);
2742 if (status & HDSPM_madiLock) {
2743 if (status & HDSPM_madiSync)
2744 return 2;
2745 else
2746 return 1;
2747 }
2748 return 0;
2749}
2750
Takashi Iwai98274f02005-11-17 14:52:34 +01002751static int snd_hdspm_get_madisync_sync_check(struct snd_kcontrol *kcontrol,
2752 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002753 ucontrol)
2754{
Takashi Iwai98274f02005-11-17 14:52:34 +01002755 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002756
2757 ucontrol->value.enumerated.item[0] =
2758 hdspm_madisync_sync_check(hdspm);
2759 return 0;
2760}
2761
2762
Remy Bruno3cee5a62006-10-16 12:46:32 +02002763#define HDSPM_AES_SYNC_CHECK(xname, xindex) \
2764{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2765 .name = xname, \
2766 .index = xindex, \
2767 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2768 .info = snd_hdspm_info_sync_check, \
2769 .get = snd_hdspm_get_aes_sync_check \
2770}
2771
2772static int hdspm_aes_sync_check(struct hdspm * hdspm, int idx)
2773{
2774 int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
2775 if (status2 & (HDSPM_LockAES >> idx)) {
2776 /* I don't know how to differenciate sync from lock.
2777 Doing as if sync for now */
2778 return 2;
2779 }
2780 return 0;
2781}
2782
2783static int snd_hdspm_get_aes_sync_check(struct snd_kcontrol *kcontrol,
2784 struct snd_ctl_elem_value *ucontrol)
2785{
2786 int offset;
2787 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2788
2789 offset = ucontrol->id.index - 1;
2790 if (offset < 0 || offset >= 8)
2791 return -EINVAL;
2792
2793 ucontrol->value.enumerated.item[0] =
2794 hdspm_aes_sync_check(hdspm, offset);
2795 return 0;
2796}
Takashi Iwai763f3562005-06-03 11:25:34 +02002797
2798
Remy Bruno3cee5a62006-10-16 12:46:32 +02002799static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02002800
2801 HDSPM_MIXER("Mixer", 0),
2802/* 'Sample Clock Source' complies with the alsa control naming scheme */
2803 HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
2804
2805 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
2806 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
2807 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
2808 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
2809/* 'External Rate' complies with the alsa control naming scheme */
2810 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
2811 HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
2812 HDSPM_MADI_SYNC_CHECK("MADI Sync Lock Status", 0),
2813 HDSPM_LINE_OUT("Line Out", 0),
2814 HDSPM_TX_64("TX 64 channels mode", 0),
2815 HDSPM_C_TMS("Clear Track Marker", 0),
2816 HDSPM_SAFE_MODE("Safe Mode", 0),
2817 HDSPM_INPUT_SELECT("Input Select", 0),
2818};
2819
Remy Bruno3cee5a62006-10-16 12:46:32 +02002820static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
2821
2822 HDSPM_MIXER("Mixer", 0),
2823/* 'Sample Clock Source' complies with the alsa control naming scheme */
2824 HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
2825
2826 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
2827 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
2828 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
2829 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
2830/* 'External Rate' complies with the alsa control naming scheme */
2831 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
2832 HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
2833/* HDSPM_AES_SYNC_CHECK("AES Lock Status", 0),*/ /* created in snd_hdspm_create_controls() */
2834 HDSPM_LINE_OUT("Line Out", 0),
2835 HDSPM_EMPHASIS("Emphasis", 0),
2836 HDSPM_DOLBY("Non Audio", 0),
2837 HDSPM_PROFESSIONAL("Professional", 0),
2838 HDSPM_C_TMS("Clear Track Marker", 0),
2839 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
2840 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
2841};
2842
Takashi Iwai98274f02005-11-17 14:52:34 +01002843static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02002844
2845
Takashi Iwai98274f02005-11-17 14:52:34 +01002846static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002847{
2848 int i;
2849
2850 for (i = hdspm->ds_channels; i < hdspm->ss_channels; ++i) {
2851 if (hdspm->system_sample_rate > 48000) {
2852 hdspm->playback_mixer_ctls[i]->vd[0].access =
2853 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
2854 SNDRV_CTL_ELEM_ACCESS_READ |
2855 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
2856 } else {
2857 hdspm->playback_mixer_ctls[i]->vd[0].access =
2858 SNDRV_CTL_ELEM_ACCESS_READWRITE |
2859 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
2860 }
2861 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
2862 SNDRV_CTL_EVENT_MASK_INFO,
2863 &hdspm->playback_mixer_ctls[i]->id);
2864 }
2865
2866 return 0;
2867}
2868
2869
Takashi Iwai98274f02005-11-17 14:52:34 +01002870static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002871{
2872 unsigned int idx, limit;
2873 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01002874 struct snd_kcontrol *kctl;
Takashi Iwai763f3562005-06-03 11:25:34 +02002875
2876 /* add control list first */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002877 if (hdspm->is_aes32) {
2878 struct snd_kcontrol_new aes_sync_ctl =
2879 HDSPM_AES_SYNC_CHECK("AES Lock Status", 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02002880
Remy Bruno3cee5a62006-10-16 12:46:32 +02002881 for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_aes32);
2882 idx++) {
2883 err = snd_ctl_add(card,
2884 snd_ctl_new1(&snd_hdspm_controls_aes32[idx],
2885 hdspm));
2886 if (err < 0)
2887 return err;
2888 }
2889 for (idx = 1; idx <= 8; idx++) {
2890 aes_sync_ctl.index = idx;
2891 err = snd_ctl_add(card,
2892 snd_ctl_new1(&aes_sync_ctl, hdspm));
2893 if (err < 0)
2894 return err;
2895 }
2896 } else {
2897 for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_madi);
2898 idx++) {
2899 err = snd_ctl_add(card,
2900 snd_ctl_new1(&snd_hdspm_controls_madi[idx],
2901 hdspm));
2902 if (err < 0)
2903 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02002904 }
2905 }
2906
2907 /* Channel playback mixer as default control
Remy Bruno3cee5a62006-10-16 12:46:32 +02002908Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats too big for any alsamixer
2909they are accesible via special IOCTL on hwdep
2910and the mixer 2dimensional mixer control */
Takashi Iwai763f3562005-06-03 11:25:34 +02002911
2912 snd_hdspm_playback_mixer.name = "Chn";
2913 limit = HDSPM_MAX_CHANNELS;
2914
2915 /* The index values are one greater than the channel ID so that alsamixer
2916 will display them correctly. We want to use the index for fast lookup
2917 of the relevant channel, but if we use it at all, most ALSA software
2918 does the wrong thing with it ...
2919 */
2920
2921 for (idx = 0; idx < limit; ++idx) {
2922 snd_hdspm_playback_mixer.index = idx + 1;
2923 if ((err = snd_ctl_add(card,
2924 kctl =
2925 snd_ctl_new1
2926 (&snd_hdspm_playback_mixer,
2927 hdspm)))) {
2928 return err;
2929 }
2930 hdspm->playback_mixer_ctls[idx] = kctl;
2931 }
2932
2933 return 0;
2934}
2935
2936/*------------------------------------------------------------
2937 /proc interface
2938 ------------------------------------------------------------*/
2939
2940static void
Remy Bruno3cee5a62006-10-16 12:46:32 +02002941snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
2942 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02002943{
Takashi Iwai98274f02005-11-17 14:52:34 +01002944 struct hdspm *hdspm = (struct hdspm *) entry->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02002945 unsigned int status;
2946 unsigned int status2;
2947 char *pref_sync_ref;
2948 char *autosync_ref;
2949 char *system_clock_mode;
2950 char *clock_source;
2951 char *insel;
2952 char *syncref;
2953 int x, x2;
2954
2955 status = hdspm_read(hdspm, HDSPM_statusRegister);
2956 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
2957
2958 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
2959 hdspm->card_name, hdspm->card->number + 1,
2960 hdspm->firmware_rev,
2961 (status2 & HDSPM_version0) |
2962 (status2 & HDSPM_version1) | (status2 &
2963 HDSPM_version2));
2964
2965 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
2966 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
2967
2968 snd_iprintf(buffer, "--- System ---\n");
2969
2970 snd_iprintf(buffer,
2971 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
2972 status & HDSPM_audioIRQPending,
2973 (status & HDSPM_midi0IRQPending) ? 1 : 0,
2974 (status & HDSPM_midi1IRQPending) ? 1 : 0,
2975 hdspm->irq_count);
2976 snd_iprintf(buffer,
2977 "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n",
2978 ((status & HDSPM_BufferID) ? 1 : 0),
2979 (status & HDSPM_BufferPositionMask),
2980 (status & HDSPM_BufferPositionMask) % (2 *
2981 (int)hdspm->
2982 period_bytes),
2983 ((status & HDSPM_BufferPositionMask) -
2984 64) % (2 * (int)hdspm->period_bytes),
2985 (long) hdspm_hw_pointer(hdspm) * 4);
2986
2987 snd_iprintf(buffer,
2988 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
2989 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
2990 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
2991 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
2992 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
2993 snd_iprintf(buffer,
2994 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x\n",
2995 hdspm->control_register, hdspm->control2_register,
2996 status, status2);
2997
2998 snd_iprintf(buffer, "--- Settings ---\n");
2999
3000 x = 1 << (6 +
3001 hdspm_decode_latency(hdspm->
3002 control_register &
3003 HDSPM_LatencyMask));
3004
3005 snd_iprintf(buffer,
3006 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
3007 x, (unsigned long) hdspm->period_bytes);
3008
3009 snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n",
3010 (hdspm->
3011 control_register & HDSPM_LineOut) ? "on " : "off",
3012 (hdspm->precise_ptr) ? "on" : "off");
3013
3014 switch (hdspm->control_register & HDSPM_InputMask) {
3015 case HDSPM_InputOptical:
3016 insel = "Optical";
3017 break;
3018 case HDSPM_InputCoaxial:
3019 insel = "Coaxial";
3020 break;
3021 default:
3022 insel = "Unkown";
3023 }
3024
3025 switch (hdspm->control_register & HDSPM_SyncRefMask) {
3026 case HDSPM_SyncRef_Word:
3027 syncref = "WordClock";
3028 break;
3029 case HDSPM_SyncRef_MADI:
3030 syncref = "MADI";
3031 break;
3032 default:
3033 syncref = "Unkown";
3034 }
3035 snd_iprintf(buffer, "Inputsel = %s, SyncRef = %s\n", insel,
3036 syncref);
3037
3038 snd_iprintf(buffer,
3039 "ClearTrackMarker = %s, Transmit in %s Channel Mode, Auto Input %s\n",
3040 (hdspm->
3041 control_register & HDSPM_clr_tms) ? "on" : "off",
3042 (hdspm->
3043 control_register & HDSPM_TX_64ch) ? "64" : "56",
3044 (hdspm->
3045 control_register & HDSPM_AutoInp) ? "on" : "off");
3046
3047 switch (hdspm_clock_source(hdspm)) {
3048 case HDSPM_CLOCK_SOURCE_AUTOSYNC:
3049 clock_source = "AutoSync";
3050 break;
3051 case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
3052 clock_source = "Internal 32 kHz";
3053 break;
3054 case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
3055 clock_source = "Internal 44.1 kHz";
3056 break;
3057 case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
3058 clock_source = "Internal 48 kHz";
3059 break;
3060 case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
3061 clock_source = "Internal 64 kHz";
3062 break;
3063 case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
3064 clock_source = "Internal 88.2 kHz";
3065 break;
3066 case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
3067 clock_source = "Internal 96 kHz";
3068 break;
3069 default:
3070 clock_source = "Error";
3071 }
3072 snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003073 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Takashi Iwai763f3562005-06-03 11:25:34 +02003074 system_clock_mode = "Slave";
Remy Bruno3cee5a62006-10-16 12:46:32 +02003075 else
Takashi Iwai763f3562005-06-03 11:25:34 +02003076 system_clock_mode = "Master";
Takashi Iwai763f3562005-06-03 11:25:34 +02003077 snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
3078
3079 switch (hdspm_pref_sync_ref(hdspm)) {
3080 case HDSPM_SYNC_FROM_WORD:
3081 pref_sync_ref = "Word Clock";
3082 break;
3083 case HDSPM_SYNC_FROM_MADI:
3084 pref_sync_ref = "MADI Sync";
3085 break;
3086 default:
3087 pref_sync_ref = "XXXX Clock";
3088 break;
3089 }
3090 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
3091 pref_sync_ref);
3092
3093 snd_iprintf(buffer, "System Clock Frequency: %d\n",
3094 hdspm->system_sample_rate);
3095
3096
3097 snd_iprintf(buffer, "--- Status:\n");
3098
3099 x = status & HDSPM_madiSync;
3100 x2 = status2 & HDSPM_wcSync;
3101
3102 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
3103 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
3104 "NoLock",
3105 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
3106 "NoLock");
3107
3108 switch (hdspm_autosync_ref(hdspm)) {
3109 case HDSPM_AUTOSYNC_FROM_WORD:
3110 autosync_ref = "Word Clock";
3111 break;
3112 case HDSPM_AUTOSYNC_FROM_MADI:
3113 autosync_ref = "MADI Sync";
3114 break;
3115 case HDSPM_AUTOSYNC_FROM_NONE:
3116 autosync_ref = "Input not valid";
3117 break;
3118 default:
3119 autosync_ref = "---";
3120 break;
3121 }
3122 snd_iprintf(buffer,
3123 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
3124 autosync_ref, hdspm_external_sample_rate(hdspm),
3125 (status & HDSPM_madiFreqMask) >> 22,
3126 (status2 & HDSPM_wcFreqMask) >> 5);
3127
3128 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
3129 (status & HDSPM_AB_int) ? "Coax" : "Optical",
3130 (status & HDSPM_RX_64ch) ? "64 channels" :
3131 "56 channels");
3132
3133 snd_iprintf(buffer, "\n");
3134}
3135
Remy Bruno3cee5a62006-10-16 12:46:32 +02003136static void
3137snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
3138 struct snd_info_buffer *buffer)
3139{
3140 struct hdspm *hdspm = (struct hdspm *) entry->private_data;
3141 unsigned int status;
3142 unsigned int status2;
3143 unsigned int timecode;
3144 int pref_syncref;
3145 char *autosync_ref;
3146 char *system_clock_mode;
3147 char *clock_source;
3148 int x;
3149
3150 status = hdspm_read(hdspm, HDSPM_statusRegister);
3151 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3152 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
3153
3154 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
3155 hdspm->card_name, hdspm->card->number + 1,
3156 hdspm->firmware_rev);
3157
3158 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
3159 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
3160
3161 snd_iprintf(buffer, "--- System ---\n");
3162
3163 snd_iprintf(buffer,
3164 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
3165 status & HDSPM_audioIRQPending,
3166 (status & HDSPM_midi0IRQPending) ? 1 : 0,
3167 (status & HDSPM_midi1IRQPending) ? 1 : 0,
3168 hdspm->irq_count);
3169 snd_iprintf(buffer,
3170 "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n",
3171 ((status & HDSPM_BufferID) ? 1 : 0),
3172 (status & HDSPM_BufferPositionMask),
3173 (status & HDSPM_BufferPositionMask) % (2 *
3174 (int)hdspm->
3175 period_bytes),
3176 ((status & HDSPM_BufferPositionMask) -
3177 64) % (2 * (int)hdspm->period_bytes),
3178 (long) hdspm_hw_pointer(hdspm) * 4);
3179
3180 snd_iprintf(buffer,
3181 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
3182 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
3183 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
3184 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
3185 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
3186 snd_iprintf(buffer,
3187 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x, timecode=0x%x\n",
3188 hdspm->control_register, hdspm->control2_register,
3189 status, status2, timecode);
3190
3191 snd_iprintf(buffer, "--- Settings ---\n");
3192
3193 x = 1 << (6 +
3194 hdspm_decode_latency(hdspm->
3195 control_register &
3196 HDSPM_LatencyMask));
3197
3198 snd_iprintf(buffer,
3199 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
3200 x, (unsigned long) hdspm->period_bytes);
3201
3202 snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n",
3203 (hdspm->
3204 control_register & HDSPM_LineOut) ? "on " : "off",
3205 (hdspm->precise_ptr) ? "on" : "off");
3206
3207 snd_iprintf(buffer,
3208 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
3209 (hdspm->
3210 control_register & HDSPM_clr_tms) ? "on" : "off",
3211 (hdspm->
3212 control_register & HDSPM_Emphasis) ? "on" : "off",
3213 (hdspm->
3214 control_register & HDSPM_Dolby) ? "on" : "off");
3215
3216 switch (hdspm_clock_source(hdspm)) {
3217 case HDSPM_CLOCK_SOURCE_AUTOSYNC:
3218 clock_source = "AutoSync";
3219 break;
3220 case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
3221 clock_source = "Internal 32 kHz";
3222 break;
3223 case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
3224 clock_source = "Internal 44.1 kHz";
3225 break;
3226 case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
3227 clock_source = "Internal 48 kHz";
3228 break;
3229 case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
3230 clock_source = "Internal 64 kHz";
3231 break;
3232 case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
3233 clock_source = "Internal 88.2 kHz";
3234 break;
3235 case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
3236 clock_source = "Internal 96 kHz";
3237 break;
3238 case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
3239 clock_source = "Internal 128 kHz";
3240 break;
3241 case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
3242 clock_source = "Internal 176.4 kHz";
3243 break;
3244 case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
3245 clock_source = "Internal 192 kHz";
3246 break;
3247 default:
3248 clock_source = "Error";
3249 }
3250 snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
3251 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
3252 system_clock_mode = "Slave";
3253 else
3254 system_clock_mode = "Master";
3255 snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
3256
3257 pref_syncref = hdspm_pref_sync_ref(hdspm);
3258 if (pref_syncref == 0)
3259 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
3260 else
3261 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
3262 pref_syncref);
3263
3264 snd_iprintf(buffer, "System Clock Frequency: %d\n",
3265 hdspm->system_sample_rate);
3266
3267 snd_iprintf(buffer, "Double speed: %s\n",
3268 hdspm->control_register & HDSPM_DS_DoubleWire?
3269 "Double wire" : "Single wire");
3270 snd_iprintf(buffer, "Quad speed: %s\n",
3271 hdspm->control_register & HDSPM_QS_DoubleWire?
3272 "Double wire" :
3273 hdspm->control_register & HDSPM_QS_QuadWire?
3274 "Quad wire" : "Single wire");
3275
3276 snd_iprintf(buffer, "--- Status:\n");
3277
3278 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
3279 (status & HDSPM_AES32_wcLock)? "Sync " : "No Lock",
3280 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
3281
3282 for (x = 0; x < 8; x++) {
3283 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
3284 x+1,
3285 (status2 & (HDSPM_LockAES >> x))? "Sync ": "No Lock",
3286 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
3287 }
3288
3289 switch (hdspm_autosync_ref(hdspm)) {
3290 case HDSPM_AES32_AUTOSYNC_FROM_NONE: autosync_ref="None"; break;
3291 case HDSPM_AES32_AUTOSYNC_FROM_WORD: autosync_ref="Word Clock"; break;
3292 case HDSPM_AES32_AUTOSYNC_FROM_AES1: autosync_ref="AES1"; break;
3293 case HDSPM_AES32_AUTOSYNC_FROM_AES2: autosync_ref="AES2"; break;
3294 case HDSPM_AES32_AUTOSYNC_FROM_AES3: autosync_ref="AES3"; break;
3295 case HDSPM_AES32_AUTOSYNC_FROM_AES4: autosync_ref="AES4"; break;
3296 case HDSPM_AES32_AUTOSYNC_FROM_AES5: autosync_ref="AES5"; break;
3297 case HDSPM_AES32_AUTOSYNC_FROM_AES6: autosync_ref="AES6"; break;
3298 case HDSPM_AES32_AUTOSYNC_FROM_AES7: autosync_ref="AES7"; break;
3299 case HDSPM_AES32_AUTOSYNC_FROM_AES8: autosync_ref="AES8"; break;
3300 default: autosync_ref = "---"; break;
3301 }
3302 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
3303
3304 snd_iprintf(buffer, "\n");
3305}
3306
3307#ifdef CONFIG_SND_DEBUG
3308static void
3309snd_hdspm_proc_read_debug(struct snd_info_entry * entry,
3310 struct snd_info_buffer *buffer)
3311{
3312 struct hdspm *hdspm = (struct hdspm *)entry->private_data;
3313
3314 int j,i;
3315
3316 for (i = 0; i < 256 /* 1024*64 */; i += j)
3317 {
3318 snd_iprintf(buffer, "0x%08X: ", i);
3319 for (j = 0; j < 16; j += 4)
3320 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
3321 snd_iprintf(buffer, "\n");
3322 }
3323}
3324#endif
3325
3326
3327
Takashi Iwai98274f02005-11-17 14:52:34 +01003328static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003329{
Takashi Iwai98274f02005-11-17 14:52:34 +01003330 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02003331
3332 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry))
Takashi Iwaibf850202006-04-28 15:13:41 +02003333 snd_info_set_text_ops(entry, hdspm,
Remy Bruno3cee5a62006-10-16 12:46:32 +02003334 hdspm->is_aes32 ?
3335 snd_hdspm_proc_read_aes32 :
3336 snd_hdspm_proc_read_madi);
3337#ifdef CONFIG_SND_DEBUG
3338 /* debug file to read all hdspm registers */
3339 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
3340 snd_info_set_text_ops(entry, hdspm,
3341 snd_hdspm_proc_read_debug);
3342#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02003343}
3344
3345/*------------------------------------------------------------
3346 hdspm intitialize
3347 ------------------------------------------------------------*/
3348
Takashi Iwai98274f02005-11-17 14:52:34 +01003349static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003350{
3351 unsigned int i;
3352
3353 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
3354 hold it (e.g. during module initalization).
3355 */
3356
3357 /* set defaults: */
3358
Remy Bruno3cee5a62006-10-16 12:46:32 +02003359 if (hdspm->is_aes32)
3360 hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */
3361 hdspm_encode_latency(7) | /* latency maximum = 8192 samples */
3362 HDSPM_SyncRef0 | /* AES1 is syncclock */
3363 HDSPM_LineOut | /* Analog output in */
3364 HDSPM_Professional; /* Professional mode */
3365 else
3366 hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */
3367 hdspm_encode_latency(7) | /* latency maximum = 8192 samples */
3368 HDSPM_InputCoaxial | /* Input Coax not Optical */
3369 HDSPM_SyncRef_MADI | /* Madi is syncclock */
3370 HDSPM_LineOut | /* Analog output in */
3371 HDSPM_TX_64ch | /* transmit in 64ch mode */
3372 HDSPM_AutoInp; /* AutoInput chossing (takeover) */
Takashi Iwai763f3562005-06-03 11:25:34 +02003373
3374 /* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */
3375 /* ! HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */
3376 /* ! HDSPM_clr_tms = do not clear bits in track marks */
3377
3378 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3379
3380#ifdef SNDRV_BIG_ENDIAN
3381 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
3382#else
3383 hdspm->control2_register = 0;
3384#endif
3385
3386 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
3387 hdspm_compute_period_size(hdspm);
3388
3389 /* silence everything */
3390
3391 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
3392
3393 if (line_outs_monitor[hdspm->dev]) {
3394
3395 snd_printk(KERN_INFO "HDSPM: sending all playback streams to line outs.\n");
3396
3397 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) {
3398 if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN))
3399 return -EIO;
3400 }
3401 }
3402
3403 /* set a default rate so that the channel map is set up. */
3404 hdspm->channel_map = channel_map_madi_ss;
3405 hdspm_set_rate(hdspm, 44100, 1);
3406
3407 return 0;
3408}
3409
3410
3411/*------------------------------------------------------------
3412 interupt
3413 ------------------------------------------------------------*/
3414
David Howells7d12e782006-10-05 14:55:46 +01003415static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02003416{
Takashi Iwai98274f02005-11-17 14:52:34 +01003417 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02003418 unsigned int status;
3419 int audio;
3420 int midi0;
3421 int midi1;
3422 unsigned int midi0status;
3423 unsigned int midi1status;
3424 int schedule = 0;
3425
3426 status = hdspm_read(hdspm, HDSPM_statusRegister);
3427
3428 audio = status & HDSPM_audioIRQPending;
3429 midi0 = status & HDSPM_midi0IRQPending;
3430 midi1 = status & HDSPM_midi1IRQPending;
3431
3432 if (!audio && !midi0 && !midi1)
3433 return IRQ_NONE;
3434
3435 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
3436 hdspm->irq_count++;
3437
3438 midi0status = hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff;
3439 midi1status = hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff;
3440
3441 if (audio) {
3442
3443 if (hdspm->capture_substream)
3444 snd_pcm_period_elapsed(hdspm->pcm->
3445 streams
3446 [SNDRV_PCM_STREAM_CAPTURE].
3447 substream);
3448
3449 if (hdspm->playback_substream)
3450 snd_pcm_period_elapsed(hdspm->pcm->
3451 streams
3452 [SNDRV_PCM_STREAM_PLAYBACK].
3453 substream);
3454 }
3455
3456 if (midi0 && midi0status) {
3457 /* we disable interrupts for this input until processing is done */
3458 hdspm->control_register &= ~HDSPM_Midi0InterruptEnable;
3459 hdspm_write(hdspm, HDSPM_controlRegister,
3460 hdspm->control_register);
3461 hdspm->midi[0].pending = 1;
3462 schedule = 1;
3463 }
3464 if (midi1 && midi1status) {
3465 /* we disable interrupts for this input until processing is done */
3466 hdspm->control_register &= ~HDSPM_Midi1InterruptEnable;
3467 hdspm_write(hdspm, HDSPM_controlRegister,
3468 hdspm->control_register);
3469 hdspm->midi[1].pending = 1;
3470 schedule = 1;
3471 }
3472 if (schedule)
3473 tasklet_hi_schedule(&hdspm->midi_tasklet);
3474 return IRQ_HANDLED;
3475}
3476
3477/*------------------------------------------------------------
3478 pcm interface
3479 ------------------------------------------------------------*/
3480
3481
Takashi Iwai98274f02005-11-17 14:52:34 +01003482static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream *
Takashi Iwai763f3562005-06-03 11:25:34 +02003483 substream)
3484{
Takashi Iwai98274f02005-11-17 14:52:34 +01003485 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003486 return hdspm_hw_pointer(hdspm);
3487}
3488
Takashi Iwai98274f02005-11-17 14:52:34 +01003489static char *hdspm_channel_buffer_location(struct hdspm * hdspm,
Takashi Iwai763f3562005-06-03 11:25:34 +02003490 int stream, int channel)
3491{
3492 int mapped_channel;
3493
3494 snd_assert(channel >= 0
3495 || channel < HDSPM_MAX_CHANNELS, return NULL);
3496
3497 if ((mapped_channel = hdspm->channel_map[channel]) < 0)
3498 return NULL;
3499
3500 if (stream == SNDRV_PCM_STREAM_CAPTURE) {
3501 return hdspm->capture_buffer +
3502 mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
3503 } else {
3504 return hdspm->playback_buffer +
3505 mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
3506 }
3507}
3508
3509
3510/* dont know why need it ??? */
Takashi Iwai98274f02005-11-17 14:52:34 +01003511static int snd_hdspm_playback_copy(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02003512 int channel, snd_pcm_uframes_t pos,
3513 void __user *src, snd_pcm_uframes_t count)
3514{
Takashi Iwai98274f02005-11-17 14:52:34 +01003515 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003516 char *channel_buf;
3517
3518 snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
3519 return -EINVAL);
3520
3521 channel_buf = hdspm_channel_buffer_location(hdspm,
3522 substream->pstr->
3523 stream, channel);
3524
3525 snd_assert(channel_buf != NULL, return -EIO);
3526
3527 return copy_from_user(channel_buf + pos * 4, src, count * 4);
3528}
3529
Takashi Iwai98274f02005-11-17 14:52:34 +01003530static int snd_hdspm_capture_copy(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02003531 int channel, snd_pcm_uframes_t pos,
3532 void __user *dst, snd_pcm_uframes_t count)
3533{
Takashi Iwai98274f02005-11-17 14:52:34 +01003534 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003535 char *channel_buf;
3536
3537 snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
3538 return -EINVAL);
3539
3540 channel_buf = hdspm_channel_buffer_location(hdspm,
3541 substream->pstr->
3542 stream, channel);
3543 snd_assert(channel_buf != NULL, return -EIO);
3544 return copy_to_user(dst, channel_buf + pos * 4, count * 4);
3545}
3546
Takashi Iwai98274f02005-11-17 14:52:34 +01003547static int snd_hdspm_hw_silence(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02003548 int channel, snd_pcm_uframes_t pos,
3549 snd_pcm_uframes_t count)
3550{
Takashi Iwai98274f02005-11-17 14:52:34 +01003551 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003552 char *channel_buf;
3553
3554 channel_buf =
3555 hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
3556 channel);
3557 snd_assert(channel_buf != NULL, return -EIO);
3558 memset(channel_buf + pos * 4, 0, count * 4);
3559 return 0;
3560}
3561
Takashi Iwai98274f02005-11-17 14:52:34 +01003562static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003563{
Takashi Iwai98274f02005-11-17 14:52:34 +01003564 struct snd_pcm_runtime *runtime = substream->runtime;
3565 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
3566 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02003567
3568 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3569 other = hdspm->capture_substream;
3570 else
3571 other = hdspm->playback_substream;
3572
3573 if (hdspm->running)
3574 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
3575 else
3576 runtime->status->hw_ptr = 0;
3577 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003578 struct snd_pcm_substream *s;
3579 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01003580 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02003581 if (s == other) {
3582 oruntime->status->hw_ptr =
3583 runtime->status->hw_ptr;
3584 break;
3585 }
3586 }
3587 }
3588 return 0;
3589}
3590
Takashi Iwai98274f02005-11-17 14:52:34 +01003591static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
3592 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02003593{
Takashi Iwai98274f02005-11-17 14:52:34 +01003594 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003595 int err;
3596 int i;
3597 pid_t this_pid;
3598 pid_t other_pid;
3599 struct snd_sg_buf *sgbuf;
3600
3601
3602 spin_lock_irq(&hdspm->lock);
3603
3604 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3605 this_pid = hdspm->playback_pid;
3606 other_pid = hdspm->capture_pid;
3607 } else {
3608 this_pid = hdspm->capture_pid;
3609 other_pid = hdspm->playback_pid;
3610 }
3611
3612 if ((other_pid > 0) && (this_pid != other_pid)) {
3613
3614 /* The other stream is open, and not by the same
3615 task as this one. Make sure that the parameters
3616 that matter are the same.
3617 */
3618
3619 if (params_rate(params) != hdspm->system_sample_rate) {
3620 spin_unlock_irq(&hdspm->lock);
3621 _snd_pcm_hw_param_setempty(params,
3622 SNDRV_PCM_HW_PARAM_RATE);
3623 return -EBUSY;
3624 }
3625
3626 if (params_period_size(params) != hdspm->period_bytes / 4) {
3627 spin_unlock_irq(&hdspm->lock);
3628 _snd_pcm_hw_param_setempty(params,
3629 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
3630 return -EBUSY;
3631 }
3632
3633 }
3634 /* We're fine. */
3635 spin_unlock_irq(&hdspm->lock);
3636
3637 /* how to make sure that the rate matches an externally-set one ? */
3638
3639 spin_lock_irq(&hdspm->lock);
3640 if ((err = hdspm_set_rate(hdspm, params_rate(params), 0)) < 0) {
3641 spin_unlock_irq(&hdspm->lock);
3642 _snd_pcm_hw_param_setempty(params,
3643 SNDRV_PCM_HW_PARAM_RATE);
3644 return err;
3645 }
3646 spin_unlock_irq(&hdspm->lock);
3647
3648 if ((err =
3649 hdspm_set_interrupt_interval(hdspm,
3650 params_period_size(params))) <
3651 0) {
3652 _snd_pcm_hw_param_setempty(params,
3653 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
3654 return err;
3655 }
3656
3657 /* Memory allocation, takashi's method, dont know if we should spinlock */
3658 /* malloc all buffer even if not enabled to get sure */
3659 /* malloc only needed bytes */
3660 err =
3661 snd_pcm_lib_malloc_pages(substream,
3662 HDSPM_CHANNEL_BUFFER_BYTES *
3663 params_channels(params));
3664 if (err < 0)
3665 return err;
3666
3667 sgbuf = snd_pcm_substream_sgbuf(substream);
3668
3669 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3670
3671 hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferOut,
3672 params_channels(params));
3673
3674 for (i = 0; i < params_channels(params); ++i)
3675 snd_hdspm_enable_out(hdspm, i, 1);
3676
3677 hdspm->playback_buffer =
3678 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01003679 snd_printdd("Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02003680 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02003681 } else {
3682 hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferIn,
3683 params_channels(params));
3684
3685 for (i = 0; i < params_channels(params); ++i)
3686 snd_hdspm_enable_in(hdspm, i, 1);
3687
3688 hdspm->capture_buffer =
3689 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01003690 snd_printdd("Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02003691 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02003692 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02003693 /*
3694 snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
3695 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
3696 "playback" : "capture",
3697 snd_pcm_sgbuf_get_addr(sgbuf, 0));
3698 */
Takashi Iwai763f3562005-06-03 11:25:34 +02003699 return 0;
3700}
3701
Takashi Iwai98274f02005-11-17 14:52:34 +01003702static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003703{
3704 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01003705 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003706
3707 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3708
3709 /* params_channels(params) should be enough,
3710 but to get sure in case of error */
3711 for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
3712 snd_hdspm_enable_out(hdspm, i, 0);
3713
3714 hdspm->playback_buffer = NULL;
3715 } else {
3716 for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
3717 snd_hdspm_enable_in(hdspm, i, 0);
3718
3719 hdspm->capture_buffer = NULL;
3720
3721 }
3722
3723 snd_pcm_lib_free_pages(substream);
3724
3725 return 0;
3726}
3727
Takashi Iwai98274f02005-11-17 14:52:34 +01003728static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
3729 struct snd_pcm_channel_info * info)
Takashi Iwai763f3562005-06-03 11:25:34 +02003730{
Takashi Iwai98274f02005-11-17 14:52:34 +01003731 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003732 int mapped_channel;
3733
3734 snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL);
3735
3736 if ((mapped_channel = hdspm->channel_map[info->channel]) < 0)
3737 return -EINVAL;
3738
3739 info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
3740 info->first = 0;
3741 info->step = 32;
3742 return 0;
3743}
3744
Takashi Iwai98274f02005-11-17 14:52:34 +01003745static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02003746 unsigned int cmd, void *arg)
3747{
3748 switch (cmd) {
3749 case SNDRV_PCM_IOCTL1_RESET:
3750 {
3751 return snd_hdspm_reset(substream);
3752 }
3753
3754 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
3755 {
Takashi Iwai98274f02005-11-17 14:52:34 +01003756 struct snd_pcm_channel_info *info = arg;
Takashi Iwai763f3562005-06-03 11:25:34 +02003757 return snd_hdspm_channel_info(substream, info);
3758 }
3759 default:
3760 break;
3761 }
3762
3763 return snd_pcm_lib_ioctl(substream, cmd, arg);
3764}
3765
Takashi Iwai98274f02005-11-17 14:52:34 +01003766static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02003767{
Takashi Iwai98274f02005-11-17 14:52:34 +01003768 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
3769 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02003770 int running;
3771
3772 spin_lock(&hdspm->lock);
3773 running = hdspm->running;
3774 switch (cmd) {
3775 case SNDRV_PCM_TRIGGER_START:
3776 running |= 1 << substream->stream;
3777 break;
3778 case SNDRV_PCM_TRIGGER_STOP:
3779 running &= ~(1 << substream->stream);
3780 break;
3781 default:
3782 snd_BUG();
3783 spin_unlock(&hdspm->lock);
3784 return -EINVAL;
3785 }
3786 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3787 other = hdspm->capture_substream;
3788 else
3789 other = hdspm->playback_substream;
3790
3791 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003792 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01003793 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02003794 if (s == other) {
3795 snd_pcm_trigger_done(s, substream);
3796 if (cmd == SNDRV_PCM_TRIGGER_START)
3797 running |= 1 << s->stream;
3798 else
3799 running &= ~(1 << s->stream);
3800 goto _ok;
3801 }
3802 }
3803 if (cmd == SNDRV_PCM_TRIGGER_START) {
3804 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
3805 && substream->stream ==
3806 SNDRV_PCM_STREAM_CAPTURE)
3807 hdspm_silence_playback(hdspm);
3808 } else {
3809 if (running &&
3810 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3811 hdspm_silence_playback(hdspm);
3812 }
3813 } else {
3814 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
3815 hdspm_silence_playback(hdspm);
3816 }
3817 _ok:
3818 snd_pcm_trigger_done(substream, substream);
3819 if (!hdspm->running && running)
3820 hdspm_start_audio(hdspm);
3821 else if (hdspm->running && !running)
3822 hdspm_stop_audio(hdspm);
3823 hdspm->running = running;
3824 spin_unlock(&hdspm->lock);
3825
3826 return 0;
3827}
3828
Takashi Iwai98274f02005-11-17 14:52:34 +01003829static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003830{
3831 return 0;
3832}
3833
3834static unsigned int period_sizes[] =
3835 { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
3836
Takashi Iwai98274f02005-11-17 14:52:34 +01003837static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003838 .info = (SNDRV_PCM_INFO_MMAP |
3839 SNDRV_PCM_INFO_MMAP_VALID |
3840 SNDRV_PCM_INFO_NONINTERLEAVED |
3841 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
3842 .formats = SNDRV_PCM_FMTBIT_S32_LE,
3843 .rates = (SNDRV_PCM_RATE_32000 |
3844 SNDRV_PCM_RATE_44100 |
3845 SNDRV_PCM_RATE_48000 |
3846 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02003847 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
3848 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02003849 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02003850 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02003851 .channels_min = 1,
3852 .channels_max = HDSPM_MAX_CHANNELS,
3853 .buffer_bytes_max =
3854 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
3855 .period_bytes_min = (64 * 4),
3856 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
3857 .periods_min = 2,
3858 .periods_max = 2,
3859 .fifo_size = 0
3860};
3861
Takashi Iwai98274f02005-11-17 14:52:34 +01003862static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003863 .info = (SNDRV_PCM_INFO_MMAP |
3864 SNDRV_PCM_INFO_MMAP_VALID |
3865 SNDRV_PCM_INFO_NONINTERLEAVED |
3866 SNDRV_PCM_INFO_SYNC_START),
3867 .formats = SNDRV_PCM_FMTBIT_S32_LE,
3868 .rates = (SNDRV_PCM_RATE_32000 |
3869 SNDRV_PCM_RATE_44100 |
3870 SNDRV_PCM_RATE_48000 |
3871 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02003872 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
3873 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02003874 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02003875 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02003876 .channels_min = 1,
3877 .channels_max = HDSPM_MAX_CHANNELS,
3878 .buffer_bytes_max =
3879 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
3880 .period_bytes_min = (64 * 4),
3881 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
3882 .periods_min = 2,
3883 .periods_max = 2,
3884 .fifo_size = 0
3885};
3886
Takashi Iwai98274f02005-11-17 14:52:34 +01003887static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003888 .count = ARRAY_SIZE(period_sizes),
3889 .list = period_sizes,
3890 .mask = 0
3891};
3892
3893
Takashi Iwai98274f02005-11-17 14:52:34 +01003894static int snd_hdspm_hw_rule_channels_rate(struct snd_pcm_hw_params *params,
3895 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02003896{
Takashi Iwai98274f02005-11-17 14:52:34 +01003897 struct hdspm *hdspm = rule->private;
3898 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02003899 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01003900 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02003901 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
3902
3903 if (r->min > 48000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003904 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003905 .min = 1,
3906 .max = hdspm->ds_channels,
3907 .integer = 1,
3908 };
3909 return snd_interval_refine(c, &t);
3910 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003911 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003912 .min = 1,
3913 .max = hdspm->ss_channels,
3914 .integer = 1,
3915 };
3916 return snd_interval_refine(c, &t);
3917 }
3918 return 0;
3919}
3920
Takashi Iwai98274f02005-11-17 14:52:34 +01003921static int snd_hdspm_hw_rule_rate_channels(struct snd_pcm_hw_params *params,
3922 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02003923{
Takashi Iwai98274f02005-11-17 14:52:34 +01003924 struct hdspm *hdspm = rule->private;
3925 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02003926 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01003927 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02003928 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
3929
3930 if (c->min <= hdspm->ss_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003931 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003932 .min = 32000,
3933 .max = 48000,
3934 .integer = 1,
3935 };
3936 return snd_interval_refine(r, &t);
3937 } else if (c->max > hdspm->ss_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003938 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003939 .min = 64000,
3940 .max = 96000,
3941 .integer = 1,
3942 };
3943
3944 return snd_interval_refine(r, &t);
3945 }
3946 return 0;
3947}
3948
Takashi Iwai98274f02005-11-17 14:52:34 +01003949static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003950{
Takashi Iwai98274f02005-11-17 14:52:34 +01003951 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
3952 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02003953
3954 snd_printdd("Open device substream %d\n", substream->stream);
3955
3956 spin_lock_irq(&hdspm->lock);
3957
3958 snd_pcm_set_sync(substream);
3959
3960 runtime->hw = snd_hdspm_playback_subinfo;
3961
3962 if (hdspm->capture_substream == NULL)
3963 hdspm_stop_audio(hdspm);
3964
3965 hdspm->playback_pid = current->pid;
3966 hdspm->playback_substream = substream;
3967
3968 spin_unlock_irq(&hdspm->lock);
3969
3970 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
3971
3972 snd_pcm_hw_constraint_list(runtime, 0,
3973 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
3974 &hw_constraints_period_sizes);
3975
3976 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
3977 snd_hdspm_hw_rule_channels_rate, hdspm,
3978 SNDRV_PCM_HW_PARAM_RATE, -1);
3979
3980 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
3981 snd_hdspm_hw_rule_rate_channels, hdspm,
3982 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
3983
3984 return 0;
3985}
3986
Takashi Iwai98274f02005-11-17 14:52:34 +01003987static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003988{
Takashi Iwai98274f02005-11-17 14:52:34 +01003989 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003990
3991 spin_lock_irq(&hdspm->lock);
3992
3993 hdspm->playback_pid = -1;
3994 hdspm->playback_substream = NULL;
3995
3996 spin_unlock_irq(&hdspm->lock);
3997
3998 return 0;
3999}
4000
4001
Takashi Iwai98274f02005-11-17 14:52:34 +01004002static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02004003{
Takashi Iwai98274f02005-11-17 14:52:34 +01004004 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
4005 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02004006
4007 spin_lock_irq(&hdspm->lock);
4008 snd_pcm_set_sync(substream);
4009 runtime->hw = snd_hdspm_capture_subinfo;
4010
4011 if (hdspm->playback_substream == NULL)
4012 hdspm_stop_audio(hdspm);
4013
4014 hdspm->capture_pid = current->pid;
4015 hdspm->capture_substream = substream;
4016
4017 spin_unlock_irq(&hdspm->lock);
4018
4019 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
4020 snd_pcm_hw_constraint_list(runtime, 0,
4021 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
4022 &hw_constraints_period_sizes);
4023
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);
4027
4028 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 return 0;
4032}
4033
Takashi Iwai98274f02005-11-17 14:52:34 +01004034static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02004035{
Takashi Iwai98274f02005-11-17 14:52:34 +01004036 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02004037
4038 spin_lock_irq(&hdspm->lock);
4039
4040 hdspm->capture_pid = -1;
4041 hdspm->capture_substream = NULL;
4042
4043 spin_unlock_irq(&hdspm->lock);
4044 return 0;
4045}
4046
Takashi Iwai98274f02005-11-17 14:52:34 +01004047static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep * hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02004048{
4049 /* we have nothing to initialize but the call is required */
4050 return 0;
4051}
4052
4053
Takashi Iwai98274f02005-11-17 14:52:34 +01004054static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
Takashi Iwai763f3562005-06-03 11:25:34 +02004055 unsigned int cmd, unsigned long arg)
4056{
Takashi Iwai98274f02005-11-17 14:52:34 +01004057 struct hdspm *hdspm = (struct hdspm *) hw->private_data;
4058 struct hdspm_mixer_ioctl mixer;
4059 struct hdspm_config_info info;
4060 struct hdspm_version hdspm_version;
4061 struct hdspm_peak_rms_ioctl rms;
Takashi Iwai763f3562005-06-03 11:25:34 +02004062
4063 switch (cmd) {
4064
4065
4066 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
4067 if (copy_from_user(&rms, (void __user *)arg, sizeof(rms)))
4068 return -EFAULT;
4069 /* maybe there is a chance to memorymap in future so dont touch just copy */
4070 if(copy_to_user_fromio((void __user *)rms.peak,
4071 hdspm->iobase+HDSPM_MADI_peakrmsbase,
Takashi Iwai98274f02005-11-17 14:52:34 +01004072 sizeof(struct hdspm_peak_rms)) != 0 )
Takashi Iwai763f3562005-06-03 11:25:34 +02004073 return -EFAULT;
4074
4075 break;
4076
4077
4078 case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO:
4079
4080 spin_lock_irq(&hdspm->lock);
4081 info.pref_sync_ref =
4082 (unsigned char) hdspm_pref_sync_ref(hdspm);
4083 info.wordclock_sync_check =
4084 (unsigned char) hdspm_wc_sync_check(hdspm);
4085
4086 info.system_sample_rate = hdspm->system_sample_rate;
4087 info.autosync_sample_rate =
4088 hdspm_external_sample_rate(hdspm);
4089 info.system_clock_mode =
4090 (unsigned char) hdspm_system_clock_mode(hdspm);
4091 info.clock_source =
4092 (unsigned char) hdspm_clock_source(hdspm);
4093 info.autosync_ref =
4094 (unsigned char) hdspm_autosync_ref(hdspm);
4095 info.line_out = (unsigned char) hdspm_line_out(hdspm);
4096 info.passthru = 0;
4097 spin_unlock_irq(&hdspm->lock);
4098 if (copy_to_user((void __user *) arg, &info, sizeof(info)))
4099 return -EFAULT;
4100 break;
4101
4102 case SNDRV_HDSPM_IOCTL_GET_VERSION:
4103 hdspm_version.firmware_rev = hdspm->firmware_rev;
4104 if (copy_to_user((void __user *) arg, &hdspm_version,
4105 sizeof(hdspm_version)))
4106 return -EFAULT;
4107 break;
4108
4109 case SNDRV_HDSPM_IOCTL_GET_MIXER:
4110 if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
4111 return -EFAULT;
4112 if (copy_to_user
Takashi Iwai98274f02005-11-17 14:52:34 +01004113 ((void __user *)mixer.mixer, hdspm->mixer, sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02004114 return -EFAULT;
4115 break;
4116
4117 default:
4118 return -EINVAL;
4119 }
4120 return 0;
4121}
4122
Takashi Iwai98274f02005-11-17 14:52:34 +01004123static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004124 .open = snd_hdspm_playback_open,
4125 .close = snd_hdspm_playback_release,
4126 .ioctl = snd_hdspm_ioctl,
4127 .hw_params = snd_hdspm_hw_params,
4128 .hw_free = snd_hdspm_hw_free,
4129 .prepare = snd_hdspm_prepare,
4130 .trigger = snd_hdspm_trigger,
4131 .pointer = snd_hdspm_hw_pointer,
4132 .copy = snd_hdspm_playback_copy,
4133 .silence = snd_hdspm_hw_silence,
4134 .page = snd_pcm_sgbuf_ops_page,
4135};
4136
Takashi Iwai98274f02005-11-17 14:52:34 +01004137static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004138 .open = snd_hdspm_capture_open,
4139 .close = snd_hdspm_capture_release,
4140 .ioctl = snd_hdspm_ioctl,
4141 .hw_params = snd_hdspm_hw_params,
4142 .hw_free = snd_hdspm_hw_free,
4143 .prepare = snd_hdspm_prepare,
4144 .trigger = snd_hdspm_trigger,
4145 .pointer = snd_hdspm_hw_pointer,
4146 .copy = snd_hdspm_capture_copy,
4147 .page = snd_pcm_sgbuf_ops_page,
4148};
4149
Takashi Iwai98274f02005-11-17 14:52:34 +01004150static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
4151 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004152{
Takashi Iwai98274f02005-11-17 14:52:34 +01004153 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02004154 int err;
4155
4156 if ((err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw)) < 0)
4157 return err;
4158
4159 hdspm->hwdep = hw;
4160 hw->private_data = hdspm;
4161 strcpy(hw->name, "HDSPM hwdep interface");
4162
4163 hw->ops.open = snd_hdspm_hwdep_dummy_op;
4164 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
4165 hw->ops.release = snd_hdspm_hwdep_dummy_op;
4166
4167 return 0;
4168}
4169
4170
4171/*------------------------------------------------------------
4172 memory interface
4173 ------------------------------------------------------------*/
Takashi Iwai98274f02005-11-17 14:52:34 +01004174static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004175{
4176 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004177 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02004178 size_t wanted;
4179
4180 pcm = hdspm->pcm;
4181
Remy Bruno3cee5a62006-10-16 12:46:32 +02004182/* wanted = HDSPM_DMA_AREA_BYTES + 4096;*/ /* dont know why, but it works */
4183 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02004184
4185 if ((err =
4186 snd_pcm_lib_preallocate_pages_for_all(pcm,
4187 SNDRV_DMA_TYPE_DEV_SG,
4188 snd_dma_pci_data(hdspm->pci),
4189 wanted,
4190 wanted)) < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01004191 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02004192
4193 return err;
4194 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01004195 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02004196
4197 return 0;
4198}
4199
Takashi Iwai98274f02005-11-17 14:52:34 +01004200static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
Takashi Iwai763f3562005-06-03 11:25:34 +02004201 unsigned int reg, int channels)
4202{
4203 int i;
4204 for (i = 0; i < (channels * 16); i++)
4205 hdspm_write(hdspm, reg + 4 * i,
4206 snd_pcm_sgbuf_get_addr(sgbuf,
4207 (size_t) 4096 * i));
4208}
4209
4210/* ------------- ALSA Devices ---------------------------- */
Takashi Iwai98274f02005-11-17 14:52:34 +01004211static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
4212 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004213{
Takashi Iwai98274f02005-11-17 14:52:34 +01004214 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02004215 int err;
4216
4217 if ((err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm)) < 0)
4218 return err;
4219
4220 hdspm->pcm = pcm;
4221 pcm->private_data = hdspm;
4222 strcpy(pcm->name, hdspm->card_name);
4223
4224 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
4225 &snd_hdspm_playback_ops);
4226 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
4227 &snd_hdspm_capture_ops);
4228
4229 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
4230
4231 if ((err = snd_hdspm_preallocate_memory(hdspm)) < 0)
4232 return err;
4233
4234 return 0;
4235}
4236
Takashi Iwai98274f02005-11-17 14:52:34 +01004237static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004238{
4239 snd_hdspm_flush_midi_input(hdspm, 0);
4240 snd_hdspm_flush_midi_input(hdspm, 1);
4241}
4242
Takashi Iwai98274f02005-11-17 14:52:34 +01004243static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
4244 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004245{
4246 int err;
4247
4248 snd_printdd("Create card...\n");
4249 if ((err = snd_hdspm_create_pcm(card, hdspm)) < 0)
4250 return err;
4251
4252 if ((err = snd_hdspm_create_midi(card, hdspm, 0)) < 0)
4253 return err;
4254
4255 if ((err = snd_hdspm_create_midi(card, hdspm, 1)) < 0)
4256 return err;
4257
4258 if ((err = snd_hdspm_create_controls(card, hdspm)) < 0)
4259 return err;
4260
4261 if ((err = snd_hdspm_create_hwdep(card, hdspm)) < 0)
4262 return err;
4263
4264 snd_printdd("proc init...\n");
4265 snd_hdspm_proc_init(hdspm);
4266
4267 hdspm->system_sample_rate = -1;
4268 hdspm->last_external_sample_rate = -1;
4269 hdspm->last_internal_sample_rate = -1;
4270 hdspm->playback_pid = -1;
4271 hdspm->capture_pid = -1;
4272 hdspm->capture_substream = NULL;
4273 hdspm->playback_substream = NULL;
4274
4275 snd_printdd("Set defaults...\n");
4276 if ((err = snd_hdspm_set_defaults(hdspm)) < 0)
4277 return err;
4278
4279 snd_printdd("Update mixer controls...\n");
4280 hdspm_update_simple_mixer_controls(hdspm);
4281
4282 snd_printdd("Initializeing complete ???\n");
4283
4284 if ((err = snd_card_register(card)) < 0) {
4285 snd_printk(KERN_ERR "HDSPM: error registering card\n");
4286 return err;
4287 }
4288
4289 snd_printdd("... yes now\n");
4290
4291 return 0;
4292}
4293
Takashi Iwai98274f02005-11-17 14:52:34 +01004294static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdspm,
Takashi Iwai763f3562005-06-03 11:25:34 +02004295 int precise_ptr, int enable_monitor)
4296{
4297 struct pci_dev *pci = hdspm->pci;
4298 int err;
4299 int i;
4300
4301 unsigned long io_extent;
4302
4303 hdspm->irq = -1;
4304 hdspm->irq_count = 0;
4305
4306 hdspm->midi[0].rmidi = NULL;
4307 hdspm->midi[1].rmidi = NULL;
4308 hdspm->midi[0].input = NULL;
4309 hdspm->midi[1].input = NULL;
4310 hdspm->midi[0].output = NULL;
4311 hdspm->midi[1].output = NULL;
4312 spin_lock_init(&hdspm->midi[0].lock);
4313 spin_lock_init(&hdspm->midi[1].lock);
4314 hdspm->iobase = NULL;
4315 hdspm->control_register = 0;
4316 hdspm->control2_register = 0;
4317
4318 hdspm->playback_buffer = NULL;
4319 hdspm->capture_buffer = NULL;
4320
4321 for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
4322 hdspm->playback_mixer_ctls[i] = NULL;
4323 hdspm->mixer = NULL;
4324
4325 hdspm->card = card;
4326
4327 spin_lock_init(&hdspm->lock);
4328
4329 tasklet_init(&hdspm->midi_tasklet,
4330 hdspm_midi_tasklet, (unsigned long) hdspm);
4331
4332 pci_read_config_word(hdspm->pci,
4333 PCI_CLASS_REVISION, &hdspm->firmware_rev);
4334
Remy Bruno3cee5a62006-10-16 12:46:32 +02004335 hdspm->is_aes32 = (hdspm->firmware_rev >= HDSPM_AESREVISION);
4336
Takashi Iwai763f3562005-06-03 11:25:34 +02004337 strcpy(card->mixername, "Xilinx FPGA");
Remy Bruno3cee5a62006-10-16 12:46:32 +02004338 if (hdspm->is_aes32) {
4339 strcpy(card->driver, "HDSPAES32");
4340 hdspm->card_name = "RME HDSPM AES32";
4341 } else {
4342 strcpy(card->driver, "HDSPM");
4343 hdspm->card_name = "RME HDSPM MADI";
4344 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004345
4346 if ((err = pci_enable_device(pci)) < 0)
4347 return err;
4348
4349 pci_set_master(hdspm->pci);
4350
4351 if ((err = pci_request_regions(pci, "hdspm")) < 0)
4352 return err;
4353
4354 hdspm->port = pci_resource_start(pci, 0);
4355 io_extent = pci_resource_len(pci, 0);
4356
4357 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
4358 hdspm->port, hdspm->port + io_extent - 1);
4359
4360
4361 if ((hdspm->iobase = ioremap_nocache(hdspm->port, io_extent)) == NULL) {
4362 snd_printk(KERN_ERR "HDSPM: unable to remap region 0x%lx-0x%lx\n",
4363 hdspm->port, hdspm->port + io_extent - 1);
4364 return -EBUSY;
4365 }
4366 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
4367 (unsigned long)hdspm->iobase, hdspm->port,
4368 hdspm->port + io_extent - 1);
4369
4370 if (request_irq(pci->irq, snd_hdspm_interrupt,
Takashi Iwai437a5a42006-11-21 12:14:23 +01004371 IRQF_SHARED, "hdspm", hdspm)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004372 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
4373 return -EBUSY;
4374 }
4375
4376 snd_printdd("use IRQ %d\n", pci->irq);
4377
4378 hdspm->irq = pci->irq;
4379 hdspm->precise_ptr = precise_ptr;
4380
4381 hdspm->monitor_outs = enable_monitor;
4382
Andrew Mortone2eba3e2006-01-20 14:07:13 +01004383 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Takashi Iwai98274f02005-11-17 14:52:34 +01004384 sizeof(struct hdspm_mixer));
4385 if ((hdspm->mixer = kmalloc(sizeof(struct hdspm_mixer), GFP_KERNEL))
Takashi Iwai763f3562005-06-03 11:25:34 +02004386 == NULL) {
4387 snd_printk(KERN_ERR "HDSPM: unable to kmalloc Mixer memory of %d Bytes\n",
Takashi Iwai98274f02005-11-17 14:52:34 +01004388 (int)sizeof(struct hdspm_mixer));
Takashi Iwai763f3562005-06-03 11:25:34 +02004389 return err;
4390 }
4391
4392 hdspm->ss_channels = MADI_SS_CHANNELS;
4393 hdspm->ds_channels = MADI_DS_CHANNELS;
4394 hdspm->qs_channels = MADI_QS_CHANNELS;
4395
4396 snd_printdd("create alsa devices.\n");
4397 if ((err = snd_hdspm_create_alsa_devices(card, hdspm)) < 0)
4398 return err;
4399
4400 snd_hdspm_initialize_midi_flush(hdspm);
4401
4402 return 0;
4403}
4404
Takashi Iwai98274f02005-11-17 14:52:34 +01004405static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004406{
4407
4408 if (hdspm->port) {
4409
4410 /* stop th audio, and cancel all interrupts */
4411 hdspm->control_register &=
4412 ~(HDSPM_Start | HDSPM_AudioInterruptEnable
4413 | HDSPM_Midi0InterruptEnable |
4414 HDSPM_Midi1InterruptEnable);
4415 hdspm_write(hdspm, HDSPM_controlRegister,
4416 hdspm->control_register);
4417 }
4418
4419 if (hdspm->irq >= 0)
4420 free_irq(hdspm->irq, (void *) hdspm);
4421
4422
Jesper Juhlfc584222005-10-24 15:11:28 +02004423 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02004424
4425 if (hdspm->iobase)
4426 iounmap(hdspm->iobase);
4427
Takashi Iwai763f3562005-06-03 11:25:34 +02004428 if (hdspm->port)
4429 pci_release_regions(hdspm->pci);
4430
4431 pci_disable_device(hdspm->pci);
4432 return 0;
4433}
4434
Takashi Iwai98274f02005-11-17 14:52:34 +01004435static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02004436{
Takashi Iwai98274f02005-11-17 14:52:34 +01004437 struct hdspm *hdspm = (struct hdspm *) card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02004438
4439 if (hdspm)
4440 snd_hdspm_free(hdspm);
4441}
4442
4443static int __devinit snd_hdspm_probe(struct pci_dev *pci,
4444 const struct pci_device_id *pci_id)
4445{
4446 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01004447 struct hdspm *hdspm;
4448 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02004449 int err;
4450
4451 if (dev >= SNDRV_CARDS)
4452 return -ENODEV;
4453 if (!enable[dev]) {
4454 dev++;
4455 return -ENOENT;
4456 }
4457
4458 if (!(card = snd_card_new(index[dev], id[dev],
Takashi Iwai98274f02005-11-17 14:52:34 +01004459 THIS_MODULE, sizeof(struct hdspm))))
Takashi Iwai763f3562005-06-03 11:25:34 +02004460 return -ENOMEM;
4461
Takashi Iwai98274f02005-11-17 14:52:34 +01004462 hdspm = (struct hdspm *) card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02004463 card->private_free = snd_hdspm_card_free;
4464 hdspm->dev = dev;
4465 hdspm->pci = pci;
4466
Takashi Iwaic187c042007-02-19 15:27:33 +01004467 snd_card_set_dev(card, &pci->dev);
4468
Takashi Iwai763f3562005-06-03 11:25:34 +02004469 if ((err =
4470 snd_hdspm_create(card, hdspm, precise_ptr[dev],
4471 enable_monitor[dev])) < 0) {
4472 snd_card_free(card);
4473 return err;
4474 }
4475
4476 strcpy(card->shortname, "HDSPM MADI");
4477 sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name,
4478 hdspm->port, hdspm->irq);
4479
4480 if ((err = snd_card_register(card)) < 0) {
4481 snd_card_free(card);
4482 return err;
4483 }
4484
4485 pci_set_drvdata(pci, card);
4486
4487 dev++;
4488 return 0;
4489}
4490
4491static void __devexit snd_hdspm_remove(struct pci_dev *pci)
4492{
4493 snd_card_free(pci_get_drvdata(pci));
4494 pci_set_drvdata(pci, NULL);
4495}
4496
4497static struct pci_driver driver = {
4498 .name = "RME Hammerfall DSP MADI",
Takashi Iwai763f3562005-06-03 11:25:34 +02004499 .id_table = snd_hdspm_ids,
4500 .probe = snd_hdspm_probe,
4501 .remove = __devexit_p(snd_hdspm_remove),
4502};
4503
4504
4505static int __init alsa_card_hdspm_init(void)
4506{
4507 return pci_register_driver(&driver);
4508}
4509
4510static void __exit alsa_card_hdspm_exit(void)
4511{
4512 pci_unregister_driver(&driver);
4513}
4514
4515module_init(alsa_card_hdspm_init)
4516module_exit(alsa_card_hdspm_exit)