blob: 92588975f580267ba06d299435b44579e85df8c0 [file] [log] [blame]
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001/*
Takashi Iwai763f3562005-06-03 11:25:34 +02002 * ALSA driver for RME Hammerfall DSP MADI audio interface(s)
3 *
4 * Copyright (c) 2003 Winfried Ritsch (IEM)
5 * code based on hdsp.c Paul Davis
6 * Marcus Andersson
7 * Thomas Charbonnel
Remy Bruno3cee5a62006-10-16 12:46:32 +02008 * Modified 2006-06-01 for AES32 support by Remy Bruno
9 * <remy.bruno@trinnov.com>
Takashi Iwai763f3562005-06-03 11:25:34 +020010 *
Adrian Knoth0dca1792011-01-26 19:32:14 +010011 * Modified 2009-04-13 for proper metering by Florian Faber
12 * <faber@faberman.de>
13 *
14 * Modified 2009-04-14 for native float support by Florian Faber
15 * <faber@faberman.de>
16 *
17 * Modified 2009-04-26 fixed bug in rms metering by Florian Faber
18 * <faber@faberman.de>
19 *
20 * Modified 2009-04-30 added hw serial number support by Florian Faber
21 *
22 * Modified 2011-01-14 added S/PDIF input on RayDATs by Adrian Knoth
23 *
24 * Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth
25 *
Takashi Iwai763f3562005-06-03 11:25:34 +020026 * This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published by
28 * the Free Software Foundation; either version 2 of the License, or
29 * (at your option) any later version.
30 *
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
35 *
36 * You should have received a copy of the GNU General Public License
37 * along with this program; if not, write to the Free Software
38 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 *
40 */
Takashi Iwai763f3562005-06-03 11:25:34 +020041#include <linux/init.h>
42#include <linux/delay.h>
43#include <linux/interrupt.h>
44#include <linux/moduleparam.h>
45#include <linux/slab.h>
46#include <linux/pci.h>
Takashi Iwai3f7440a2009-06-05 17:40:04 +020047#include <linux/math64.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020048#include <asm/io.h>
49
50#include <sound/core.h>
51#include <sound/control.h>
52#include <sound/pcm.h>
Adrian Knoth0dca1792011-01-26 19:32:14 +010053#include <sound/pcm_params.h>
Takashi Iwai763f3562005-06-03 11:25:34 +020054#include <sound/info.h>
55#include <sound/asoundef.h>
56#include <sound/rawmidi.h>
57#include <sound/hwdep.h>
58#include <sound/initval.h>
59
60#include <sound/hdspm.h>
61
62static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
63static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
64static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
65
Takashi Iwai763f3562005-06-03 11:25:34 +020066module_param_array(index, int, NULL, 0444);
67MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
68
69module_param_array(id, charp, NULL, 0444);
70MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
71
72module_param_array(enable, bool, NULL, 0444);
73MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
74
Takashi Iwai763f3562005-06-03 11:25:34 +020075
76MODULE_AUTHOR
Adrian Knoth0dca1792011-01-26 19:32:14 +010077(
78 "Winfried Ritsch <ritsch_AT_iem.at>, "
79 "Paul Davis <paul@linuxaudiosystems.com>, "
80 "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
81 "Remy Bruno <remy.bruno@trinnov.com>, "
82 "Florian Faber <faberman@linuxproaudio.org>, "
83 "Adrian Knoth <adi@drcomp.erfurt.thur.de>"
84);
Takashi Iwai763f3562005-06-03 11:25:34 +020085MODULE_DESCRIPTION("RME HDSPM");
86MODULE_LICENSE("GPL");
87MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
88
Adrian Knoth0dca1792011-01-26 19:32:14 +010089/* --- Write registers. ---
Takashi Iwai763f3562005-06-03 11:25:34 +020090 These are defined as byte-offsets from the iobase value. */
91
Adrian Knoth0dca1792011-01-26 19:32:14 +010092#define HDSPM_WR_SETTINGS 0
93#define HDSPM_outputBufferAddress 32
94#define HDSPM_inputBufferAddress 36
Takashi Iwai763f3562005-06-03 11:25:34 +020095#define HDSPM_controlRegister 64
96#define HDSPM_interruptConfirmation 96
97#define HDSPM_control2Reg 256 /* not in specs ???????? */
Remy Brunoffb2c3c2007-03-07 19:08:46 +010098#define HDSPM_freqReg 256 /* for AES32 */
Adrian Knoth0dca1792011-01-26 19:32:14 +010099#define HDSPM_midiDataOut0 352 /* just believe in old code */
100#define HDSPM_midiDataOut1 356
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100101#define HDSPM_eeprom_wr 384 /* for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200102
103/* DMA enable for 64 channels, only Bit 0 is relevant */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100104#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */
Takashi Iwai763f3562005-06-03 11:25:34 +0200105#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */
106
Adrian Knoth0dca1792011-01-26 19:32:14 +0100107/* 16 page addresses for each of the 64 channels DMA buffer in and out
Takashi Iwai763f3562005-06-03 11:25:34 +0200108 (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
109#define HDSPM_pageAddressBufferOut 8192
110#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)
111
112#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */
113
114#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */
115
116/* --- Read registers. ---
117 These are defined as byte-offsets from the iobase value */
118#define HDSPM_statusRegister 0
Remy Bruno3cee5a62006-10-16 12:46:32 +0200119/*#define HDSPM_statusRegister2 96 */
120/* after RME Windows driver sources, status2 is 4-byte word # 48 = word at
121 * offset 192, for AES32 *and* MADI
122 * => need to check that offset 192 is working on MADI */
123#define HDSPM_statusRegister2 192
124#define HDSPM_timecodeRegister 128
Takashi Iwai763f3562005-06-03 11:25:34 +0200125
Adrian Knoth0dca1792011-01-26 19:32:14 +0100126/* AIO, RayDAT */
127#define HDSPM_RD_STATUS_0 0
128#define HDSPM_RD_STATUS_1 64
129#define HDSPM_RD_STATUS_2 128
130#define HDSPM_RD_STATUS_3 192
131
132#define HDSPM_RD_TCO 256
133#define HDSPM_RD_PLL_FREQ 512
134#define HDSPM_WR_TCO 128
135
136#define HDSPM_TCO1_TCO_lock 0x00000001
137#define HDSPM_TCO1_WCK_Input_Range_LSB 0x00000002
138#define HDSPM_TCO1_WCK_Input_Range_MSB 0x00000004
139#define HDSPM_TCO1_LTC_Input_valid 0x00000008
140#define HDSPM_TCO1_WCK_Input_valid 0x00000010
141#define HDSPM_TCO1_Video_Input_Format_NTSC 0x00000020
142#define HDSPM_TCO1_Video_Input_Format_PAL 0x00000040
143
144#define HDSPM_TCO1_set_TC 0x00000100
145#define HDSPM_TCO1_set_drop_frame_flag 0x00000200
146#define HDSPM_TCO1_LTC_Format_LSB 0x00000400
147#define HDSPM_TCO1_LTC_Format_MSB 0x00000800
148
149#define HDSPM_TCO2_TC_run 0x00010000
150#define HDSPM_TCO2_WCK_IO_ratio_LSB 0x00020000
151#define HDSPM_TCO2_WCK_IO_ratio_MSB 0x00040000
152#define HDSPM_TCO2_set_num_drop_frames_LSB 0x00080000
153#define HDSPM_TCO2_set_num_drop_frames_MSB 0x00100000
154#define HDSPM_TCO2_set_jam_sync 0x00200000
155#define HDSPM_TCO2_set_flywheel 0x00400000
156
157#define HDSPM_TCO2_set_01_4 0x01000000
158#define HDSPM_TCO2_set_pull_down 0x02000000
159#define HDSPM_TCO2_set_pull_up 0x04000000
160#define HDSPM_TCO2_set_freq 0x08000000
161#define HDSPM_TCO2_set_term_75R 0x10000000
162#define HDSPM_TCO2_set_input_LSB 0x20000000
163#define HDSPM_TCO2_set_input_MSB 0x40000000
164#define HDSPM_TCO2_set_freq_from_app 0x80000000
165
166
167#define HDSPM_midiDataOut0 352
168#define HDSPM_midiDataOut1 356
169#define HDSPM_midiDataOut2 368
170
Takashi Iwai763f3562005-06-03 11:25:34 +0200171#define HDSPM_midiDataIn0 360
172#define HDSPM_midiDataIn1 364
Adrian Knoth0dca1792011-01-26 19:32:14 +0100173#define HDSPM_midiDataIn2 372
174#define HDSPM_midiDataIn3 376
Takashi Iwai763f3562005-06-03 11:25:34 +0200175
176/* status is data bytes in MIDI-FIFO (0-128) */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100177#define HDSPM_midiStatusOut0 384
178#define HDSPM_midiStatusOut1 388
179#define HDSPM_midiStatusOut2 400
180
181#define HDSPM_midiStatusIn0 392
182#define HDSPM_midiStatusIn1 396
183#define HDSPM_midiStatusIn2 404
184#define HDSPM_midiStatusIn3 408
Takashi Iwai763f3562005-06-03 11:25:34 +0200185
186
187/* the meters are regular i/o-mapped registers, but offset
188 considerably from the rest. the peak registers are reset
Adrian Knoth0dca1792011-01-26 19:32:14 +0100189 when read; the least-significant 4 bits are full-scale counters;
Takashi Iwai763f3562005-06-03 11:25:34 +0200190 the actual peak value is in the most-significant 24 bits.
191*/
Adrian Knoth0dca1792011-01-26 19:32:14 +0100192
193#define HDSPM_MADI_INPUT_PEAK 4096
194#define HDSPM_MADI_PLAYBACK_PEAK 4352
195#define HDSPM_MADI_OUTPUT_PEAK 4608
196
197#define HDSPM_MADI_INPUT_RMS_L 6144
198#define HDSPM_MADI_PLAYBACK_RMS_L 6400
199#define HDSPM_MADI_OUTPUT_RMS_L 6656
200
201#define HDSPM_MADI_INPUT_RMS_H 7168
202#define HDSPM_MADI_PLAYBACK_RMS_H 7424
203#define HDSPM_MADI_OUTPUT_RMS_H 7680
Takashi Iwai763f3562005-06-03 11:25:34 +0200204
205/* --- Control Register bits --------- */
206#define HDSPM_Start (1<<0) /* start engine */
207
208#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */
209#define HDSPM_Latency1 (1<<2) /* where n is defined */
210#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */
211
Adrian Knoth0dca1792011-01-26 19:32:14 +0100212#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Autosync */
213#define HDSPM_c0Master 0x1 /* Master clock bit in settings
214 register [RayDAT, AIO] */
Takashi Iwai763f3562005-06-03 11:25:34 +0200215
216#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
217
218#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
219#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
220#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200221#define HDSPM_QuadSpeed (1<<31) /* quad speed bit */
Takashi Iwai763f3562005-06-03 11:25:34 +0200222
Remy Bruno3cee5a62006-10-16 12:46:32 +0200223#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200224#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200225 56channelMODE=0 */ /* MADI ONLY*/
226#define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200227
Adrian Knoth0dca1792011-01-26 19:32:14 +0100228#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200229 0=off, 1=on */ /* MADI ONLY */
230#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200231
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200232#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax
233 * -- MADI ONLY
234 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200235#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
236
Remy Bruno3cee5a62006-10-16 12:46:32 +0200237#define HDSPM_SyncRef2 (1<<13)
238#define HDSPM_SyncRef3 (1<<25)
Takashi Iwai763f3562005-06-03 11:25:34 +0200239
Remy Bruno3cee5a62006-10-16 12:46:32 +0200240#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100241#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
Takashi Iwai763f3562005-06-03 11:25:34 +0200242 AES additional bits in
243 lower 5 Audiodatabits ??? */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200244#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */
245#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200246
Adrian Knoth0dca1792011-01-26 19:32:14 +0100247#define HDSPM_Midi0InterruptEnable 0x0400000
248#define HDSPM_Midi1InterruptEnable 0x0800000
249#define HDSPM_Midi2InterruptEnable 0x0200000
250#define HDSPM_Midi3InterruptEnable 0x4000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200251
252#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100253#define HDSPe_FLOAT_FORMAT 0x2000000
Takashi Iwai763f3562005-06-03 11:25:34 +0200254
Remy Bruno3cee5a62006-10-16 12:46:32 +0200255#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
256#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
257#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */
258
259#define HDSPM_wclk_sel (1<<30)
Takashi Iwai763f3562005-06-03 11:25:34 +0200260
261/* --- bit helper defines */
262#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200263#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|\
264 HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
Takashi Iwai763f3562005-06-03 11:25:34 +0200265#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
266#define HDSPM_InputOptical 0
267#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200268#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\
269 HDSPM_SyncRef2|HDSPM_SyncRef3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200270
Adrian Knoth0dca1792011-01-26 19:32:14 +0100271#define HDSPM_c0_SyncRef0 0x2
272#define HDSPM_c0_SyncRef1 0x4
273#define HDSPM_c0_SyncRef2 0x8
274#define HDSPM_c0_SyncRef3 0x10
275#define HDSPM_c0_SyncRefMask (HDSPM_c0_SyncRef0 | HDSPM_c0_SyncRef1 |\
276 HDSPM_c0_SyncRef2 | HDSPM_c0_SyncRef3)
277
278#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
279#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
280#define HDSPM_SYNC_FROM_TCO 2
281#define HDSPM_SYNC_FROM_SYNC_IN 3
Takashi Iwai763f3562005-06-03 11:25:34 +0200282
283#define HDSPM_Frequency32KHz HDSPM_Frequency0
284#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
285#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
286#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
287#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200288#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|\
289 HDSPM_Frequency0)
Remy Bruno3cee5a62006-10-16 12:46:32 +0200290#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)
291#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200292#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\
293 HDSPM_Frequency0)
Takashi Iwai763f3562005-06-03 11:25:34 +0200294
Takashi Iwai763f3562005-06-03 11:25:34 +0200295
296/* Synccheck Status */
297#define HDSPM_SYNC_CHECK_NO_LOCK 0
298#define HDSPM_SYNC_CHECK_LOCK 1
299#define HDSPM_SYNC_CHECK_SYNC 2
300
301/* AutoSync References - used by "autosync_ref" control switch */
302#define HDSPM_AUTOSYNC_FROM_WORD 0
303#define HDSPM_AUTOSYNC_FROM_MADI 1
Adrian Knoth0dca1792011-01-26 19:32:14 +0100304#define HDSPM_AUTOSYNC_FROM_TCO 2
305#define HDSPM_AUTOSYNC_FROM_SYNC_IN 3
306#define HDSPM_AUTOSYNC_FROM_NONE 4
Takashi Iwai763f3562005-06-03 11:25:34 +0200307
308/* Possible sources of MADI input */
309#define HDSPM_OPTICAL 0 /* optical */
310#define HDSPM_COAXIAL 1 /* BNC */
311
312#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100313#define hdspm_decode_latency(x) ((((x) & HDSPM_LatencyMask)>>1))
Takashi Iwai763f3562005-06-03 11:25:34 +0200314
315#define hdspm_encode_in(x) (((x)&0x3)<<14)
316#define hdspm_decode_in(x) (((x)>>14)&0x3)
317
318/* --- control2 register bits --- */
319#define HDSPM_TMS (1<<0)
320#define HDSPM_TCK (1<<1)
321#define HDSPM_TDI (1<<2)
322#define HDSPM_JTAG (1<<3)
323#define HDSPM_PWDN (1<<4)
324#define HDSPM_PROGRAM (1<<5)
325#define HDSPM_CONFIG_MODE_0 (1<<6)
326#define HDSPM_CONFIG_MODE_1 (1<<7)
327/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
328#define HDSPM_BIGENDIAN_MODE (1<<9)
329#define HDSPM_RD_MULTIPLE (1<<10)
330
Remy Bruno3cee5a62006-10-16 12:46:32 +0200331/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200332 that do not conflict with specific bits for AES32 seem to be valid also
333 for the AES32
334 */
Takashi Iwai763f3562005-06-03 11:25:34 +0200335#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200336#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn MODE=0 */
337#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1
338 * (like inp0)
339 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100340
Takashi Iwai763f3562005-06-03 11:25:34 +0200341#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100342#define HDSPM_madiSync (1<<18) /* MADI is in sync */
343
344#define HDSPM_tcoLock 0x00000020 /* Optional TCO locked status FOR HDSPe MADI! */
345#define HDSPM_tcoSync 0x10000000 /* Optional TCO sync status */
346
347#define HDSPM_syncInLock 0x00010000 /* Sync In lock status FOR HDSPe MADI! */
348#define HDSPM_syncInSync 0x00020000 /* Sync In sync status FOR HDSPe MADI! */
Takashi Iwai763f3562005-06-03 11:25:34 +0200349
350#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100351 /* since 64byte accurate, last 6 bits are not used */
Takashi Iwai763f3562005-06-03 11:25:34 +0200352
Adrian Knoth0dca1792011-01-26 19:32:14 +0100353
354
Takashi Iwai763f3562005-06-03 11:25:34 +0200355#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
356
357#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
358#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
359#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
360#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
361
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200362#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with
363 * Interrupt
364 */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100365#define HDSPM_tco_detect 0x08000000
366#define HDSPM_tco_lock 0x20000000
367
368#define HDSPM_s2_tco_detect 0x00000040
369#define HDSPM_s2_AEBO_D 0x00000080
370#define HDSPM_s2_AEBI_D 0x00000100
371
372
373#define HDSPM_midi0IRQPending 0x40000000
374#define HDSPM_midi1IRQPending 0x80000000
375#define HDSPM_midi2IRQPending 0x20000000
376#define HDSPM_midi2IRQPendingAES 0x00000020
377#define HDSPM_midi3IRQPending 0x00200000
Takashi Iwai763f3562005-06-03 11:25:34 +0200378
379/* --- status bit helpers */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200380#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\
381 HDSPM_madiFreq2|HDSPM_madiFreq3)
Takashi Iwai763f3562005-06-03 11:25:34 +0200382#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
383#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
384#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
385#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
386#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
387#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
388#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
389#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
390#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
391
Remy Bruno3cee5a62006-10-16 12:46:32 +0200392/* Status2 Register bits */ /* MADI ONLY */
Takashi Iwai763f3562005-06-03 11:25:34 +0200393
394#define HDSPM_version0 (1<<0) /* not realy defined but I guess */
395#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
396#define HDSPM_version2 (1<<2)
397
398#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */
399#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */
400
401#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */
402#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */
403#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */
404/* missing Bit for 111=128, 1000=176.4, 1001=192 */
405
Adrian Knoth0dca1792011-01-26 19:32:14 +0100406#define HDSPM_SyncRef0 0x10000 /* Sync Reference */
407#define HDSPM_SyncRef1 0x20000
408
409#define HDSPM_SelSyncRef0 (1<<8) /* AutoSync Source */
Takashi Iwai763f3562005-06-03 11:25:34 +0200410#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */
411#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */
412
413#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
414
415#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
416#define HDSPM_wcFreq32 (HDSPM_wc_freq0)
417#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)
418#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)
419#define HDSPM_wcFreq64 (HDSPM_wc_freq2)
420#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)
421#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
422
Adrian Knoth0dca1792011-01-26 19:32:14 +0100423#define HDSPM_status1_F_0 0x0400000
424#define HDSPM_status1_F_1 0x0800000
425#define HDSPM_status1_F_2 0x1000000
426#define HDSPM_status1_F_3 0x2000000
427#define HDSPM_status1_freqMask (HDSPM_status1_F_0|HDSPM_status1_F_1|HDSPM_status1_F_2|HDSPM_status1_F_3)
428
Takashi Iwai763f3562005-06-03 11:25:34 +0200429
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200430#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
431 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200432#define HDSPM_SelSyncRef_WORD 0
433#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
Adrian Knoth0dca1792011-01-26 19:32:14 +0100434#define HDSPM_SelSyncRef_TCO (HDSPM_SelSyncRef1)
435#define HDSPM_SelSyncRef_SyncIn (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200436#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
437 HDSPM_SelSyncRef2)
Takashi Iwai763f3562005-06-03 11:25:34 +0200438
Remy Bruno3cee5a62006-10-16 12:46:32 +0200439/*
440 For AES32, bits for status, status2 and timecode are different
441*/
442/* status */
443#define HDSPM_AES32_wcLock 0x0200000
444#define HDSPM_AES32_wcFreq_bit 22
Adrian Knoth0dca1792011-01-26 19:32:14 +0100445/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
Remy Bruno3cee5a62006-10-16 12:46:32 +0200446 HDSPM_bit2freq */
447#define HDSPM_AES32_syncref_bit 16
448/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
449
450#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
451#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
452#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
453#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
454#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
455#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
456#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
457#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
458#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
Remy Bruno65345992007-08-31 12:21:08 +0200459#define HDSPM_AES32_AUTOSYNC_FROM_NONE 9
Remy Bruno3cee5a62006-10-16 12:46:32 +0200460
461/* status2 */
462/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
463#define HDSPM_LockAES 0x80
464#define HDSPM_LockAES1 0x80
465#define HDSPM_LockAES2 0x40
466#define HDSPM_LockAES3 0x20
467#define HDSPM_LockAES4 0x10
468#define HDSPM_LockAES5 0x8
469#define HDSPM_LockAES6 0x4
470#define HDSPM_LockAES7 0x2
471#define HDSPM_LockAES8 0x1
472/*
473 Timecode
474 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
475 AES i+1
476 bits 3210
477 0001 32kHz
478 0010 44.1kHz
479 0011 48kHz
480 0100 64kHz
481 0101 88.2kHz
482 0110 96kHz
483 0111 128kHz
484 1000 176.4kHz
485 1001 192kHz
486 NB: Timecode register doesn't seem to work on AES32 card revision 230
487*/
488
Takashi Iwai763f3562005-06-03 11:25:34 +0200489/* Mixer Values */
490#define UNITY_GAIN 32768 /* = 65536/2 */
491#define MINUS_INFINITY_GAIN 0
492
Takashi Iwai763f3562005-06-03 11:25:34 +0200493/* Number of channels for different Speed Modes */
494#define MADI_SS_CHANNELS 64
495#define MADI_DS_CHANNELS 32
496#define MADI_QS_CHANNELS 16
497
Adrian Knoth0dca1792011-01-26 19:32:14 +0100498#define RAYDAT_SS_CHANNELS 36
499#define RAYDAT_DS_CHANNELS 20
500#define RAYDAT_QS_CHANNELS 12
501
502#define AIO_IN_SS_CHANNELS 14
503#define AIO_IN_DS_CHANNELS 10
504#define AIO_IN_QS_CHANNELS 8
505#define AIO_OUT_SS_CHANNELS 16
506#define AIO_OUT_DS_CHANNELS 12
507#define AIO_OUT_QS_CHANNELS 10
508
Takashi Iwai763f3562005-06-03 11:25:34 +0200509/* the size of a substream (1 mono data stream) */
510#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
511#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
512
513/* the size of the area we need to allocate for DMA transfers. the
514 size is the same regardless of the number of channels, and
Adrian Knoth0dca1792011-01-26 19:32:14 +0100515 also the latency to use.
Takashi Iwai763f3562005-06-03 11:25:34 +0200516 for one direction !!!
517*/
Remy Brunoffb2c3c2007-03-07 19:08:46 +0100518#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
Takashi Iwai763f3562005-06-03 11:25:34 +0200519#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
520
Remy Bruno3cee5a62006-10-16 12:46:32 +0200521/* revisions >= 230 indicate AES32 card */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100522#define HDSPM_MADI_REV 210
523#define HDSPM_RAYDAT_REV 211
524#define HDSPM_AIO_REV 212
525#define HDSPM_MADIFACE_REV 213
526#define HDSPM_AES_REV 240
Remy Bruno3cee5a62006-10-16 12:46:32 +0200527
Remy Bruno65345992007-08-31 12:21:08 +0200528/* speed factor modes */
529#define HDSPM_SPEED_SINGLE 0
530#define HDSPM_SPEED_DOUBLE 1
531#define HDSPM_SPEED_QUAD 2
Adrian Knoth0dca1792011-01-26 19:32:14 +0100532
Remy Bruno65345992007-08-31 12:21:08 +0200533/* names for speed modes */
534static char *hdspm_speed_names[] = { "single", "double", "quad" };
535
Adrian Knoth0dca1792011-01-26 19:32:14 +0100536static char *texts_autosync_aes_tco[] = { "Word Clock",
537 "AES1", "AES2", "AES3", "AES4",
538 "AES5", "AES6", "AES7", "AES8",
539 "TCO" };
540static char *texts_autosync_aes[] = { "Word Clock",
541 "AES1", "AES2", "AES3", "AES4",
542 "AES5", "AES6", "AES7", "AES8" };
543static char *texts_autosync_madi_tco[] = { "Word Clock",
544 "MADI", "TCO", "Sync In" };
545static char *texts_autosync_madi[] = { "Word Clock",
546 "MADI", "Sync In" };
547
548static char *texts_autosync_raydat_tco[] = {
549 "Word Clock",
550 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
551 "AES", "SPDIF", "TCO", "Sync In"
552};
553static char *texts_autosync_raydat[] = {
554 "Word Clock",
555 "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
556 "AES", "SPDIF", "Sync In"
557};
558static char *texts_autosync_aio_tco[] = {
559 "Word Clock",
560 "ADAT", "AES", "SPDIF", "TCO", "Sync In"
561};
562static char *texts_autosync_aio[] = { "Word Clock",
563 "ADAT", "AES", "SPDIF", "Sync In" };
564
565static char *texts_freq[] = {
566 "No Lock",
567 "32 kHz",
568 "44.1 kHz",
569 "48 kHz",
570 "64 kHz",
571 "88.2 kHz",
572 "96 kHz",
573 "128 kHz",
574 "176.4 kHz",
575 "192 kHz"
576};
577
Adrian Knoth0dca1792011-01-26 19:32:14 +0100578static char *texts_ports_madi[] = {
579 "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6",
580 "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12",
581 "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18",
582 "MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24",
583 "MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30",
584 "MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36",
585 "MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42",
586 "MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48",
587 "MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54",
588 "MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60",
589 "MADI.61", "MADI.62", "MADI.63", "MADI.64",
590};
591
592
593static char *texts_ports_raydat_ss[] = {
594 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6",
595 "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
596 "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2",
597 "ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8",
598 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6",
599 "ADAT4.7", "ADAT4.8",
600 "AES.L", "AES.R",
601 "SPDIF.L", "SPDIF.R"
602};
603
604static char *texts_ports_raydat_ds[] = {
605 "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4",
606 "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
607 "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4",
608 "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4",
609 "AES.L", "AES.R",
610 "SPDIF.L", "SPDIF.R"
611};
612
613static char *texts_ports_raydat_qs[] = {
614 "ADAT1.1", "ADAT1.2",
615 "ADAT2.1", "ADAT2.2",
616 "ADAT3.1", "ADAT3.2",
617 "ADAT4.1", "ADAT4.2",
618 "AES.L", "AES.R",
619 "SPDIF.L", "SPDIF.R"
620};
621
622
623static char *texts_ports_aio_in_ss[] = {
624 "Analogue.L", "Analogue.R",
625 "AES.L", "AES.R",
626 "SPDIF.L", "SPDIF.R",
627 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
628 "ADAT.7", "ADAT.8"
629};
630
631static char *texts_ports_aio_out_ss[] = {
632 "Analogue.L", "Analogue.R",
633 "AES.L", "AES.R",
634 "SPDIF.L", "SPDIF.R",
635 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
636 "ADAT.7", "ADAT.8",
637 "Phone.L", "Phone.R"
638};
639
640static char *texts_ports_aio_in_ds[] = {
641 "Analogue.L", "Analogue.R",
642 "AES.L", "AES.R",
643 "SPDIF.L", "SPDIF.R",
644 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
645};
646
647static char *texts_ports_aio_out_ds[] = {
648 "Analogue.L", "Analogue.R",
649 "AES.L", "AES.R",
650 "SPDIF.L", "SPDIF.R",
651 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
652 "Phone.L", "Phone.R"
653};
654
655static char *texts_ports_aio_in_qs[] = {
656 "Analogue.L", "Analogue.R",
657 "AES.L", "AES.R",
658 "SPDIF.L", "SPDIF.R",
659 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
660};
661
662static char *texts_ports_aio_out_qs[] = {
663 "Analogue.L", "Analogue.R",
664 "AES.L", "AES.R",
665 "SPDIF.L", "SPDIF.R",
666 "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
667 "Phone.L", "Phone.R"
668};
669
Adrian Knoth432d2502011-02-23 11:43:08 +0100670static char *texts_ports_aes32[] = {
671 "AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7",
672 "AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14",
673 "AES.15", "AES.16"
674};
675
Adrian Knoth55a57602011-01-27 11:23:15 +0100676/* These tables map the ALSA channels 1..N to the channels that we
677 need to use in order to find the relevant channel buffer. RME
678 refers to this kind of mapping as between "the ADAT channel and
679 the DMA channel." We index it using the logical audio channel,
680 and the value is the DMA channel (i.e. channel buffer number)
681 where the data for that channel can be read/written from/to.
682*/
683
684static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = {
685 0, 1, 2, 3, 4, 5, 6, 7,
686 8, 9, 10, 11, 12, 13, 14, 15,
687 16, 17, 18, 19, 20, 21, 22, 23,
688 24, 25, 26, 27, 28, 29, 30, 31,
689 32, 33, 34, 35, 36, 37, 38, 39,
690 40, 41, 42, 43, 44, 45, 46, 47,
691 48, 49, 50, 51, 52, 53, 54, 55,
692 56, 57, 58, 59, 60, 61, 62, 63
693};
694
Adrian Knoth55a57602011-01-27 11:23:15 +0100695static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = {
696 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */
697 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */
698 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */
699 28, 29, 30, 31, 32, 33, 34, 35, /* ADAT 4 */
700 0, 1, /* AES */
701 2, 3, /* SPDIF */
702 -1, -1, -1, -1,
703 -1, -1, -1, -1, -1, -1, -1, -1,
704 -1, -1, -1, -1, -1, -1, -1, -1,
705 -1, -1, -1, -1, -1, -1, -1, -1,
706};
707
708static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = {
709 4, 5, 6, 7, /* ADAT 1 */
710 8, 9, 10, 11, /* ADAT 2 */
711 12, 13, 14, 15, /* ADAT 3 */
712 16, 17, 18, 19, /* ADAT 4 */
713 0, 1, /* AES */
714 2, 3, /* SPDIF */
715 -1, -1, -1, -1,
716 -1, -1, -1, -1, -1, -1, -1, -1,
717 -1, -1, -1, -1, -1, -1, -1, -1,
718 -1, -1, -1, -1, -1, -1, -1, -1,
719 -1, -1, -1, -1, -1, -1, -1, -1,
720 -1, -1, -1, -1, -1, -1, -1, -1,
721};
722
723static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = {
724 4, 5, /* ADAT 1 */
725 6, 7, /* ADAT 2 */
726 8, 9, /* ADAT 3 */
727 10, 11, /* ADAT 4 */
728 0, 1, /* AES */
729 2, 3, /* SPDIF */
730 -1, -1, -1, -1,
731 -1, -1, -1, -1, -1, -1, -1, -1,
732 -1, -1, -1, -1, -1, -1, -1, -1,
733 -1, -1, -1, -1, -1, -1, -1, -1,
734 -1, -1, -1, -1, -1, -1, -1, -1,
735 -1, -1, -1, -1, -1, -1, -1, -1,
736 -1, -1, -1, -1, -1, -1, -1, -1,
737};
738
739static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = {
740 0, 1, /* line in */
741 8, 9, /* aes in, */
742 10, 11, /* spdif in */
743 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT in */
744 -1, -1,
745 -1, -1, -1, -1, -1, -1, -1, -1,
746 -1, -1, -1, -1, -1, -1, -1, -1,
747 -1, -1, -1, -1, -1, -1, -1, -1,
748 -1, -1, -1, -1, -1, -1, -1, -1,
749 -1, -1, -1, -1, -1, -1, -1, -1,
750 -1, -1, -1, -1, -1, -1, -1, -1,
751};
752
753static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = {
754 0, 1, /* line out */
755 8, 9, /* aes out */
756 10, 11, /* spdif out */
757 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT out */
758 6, 7, /* phone out */
759 -1, -1, -1, -1, -1, -1, -1, -1,
760 -1, -1, -1, -1, -1, -1, -1, -1,
761 -1, -1, -1, -1, -1, -1, -1, -1,
762 -1, -1, -1, -1, -1, -1, -1, -1,
763 -1, -1, -1, -1, -1, -1, -1, -1,
764 -1, -1, -1, -1, -1, -1, -1, -1,
765};
766
767static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = {
768 0, 1, /* line in */
769 8, 9, /* aes in */
770 10, 11, /* spdif in */
771 12, 14, 16, 18, /* adat in */
772 -1, -1, -1, -1, -1, -1,
773 -1, -1, -1, -1, -1, -1, -1, -1,
774 -1, -1, -1, -1, -1, -1, -1, -1,
775 -1, -1, -1, -1, -1, -1, -1, -1,
776 -1, -1, -1, -1, -1, -1, -1, -1,
777 -1, -1, -1, -1, -1, -1, -1, -1,
778 -1, -1, -1, -1, -1, -1, -1, -1
779};
780
781static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
782 0, 1, /* line out */
783 8, 9, /* aes out */
784 10, 11, /* spdif out */
785 12, 14, 16, 18, /* adat out */
786 6, 7, /* phone out */
787 -1, -1, -1, -1,
788 -1, -1, -1, -1, -1, -1, -1, -1,
789 -1, -1, -1, -1, -1, -1, -1, -1,
790 -1, -1, -1, -1, -1, -1, -1, -1,
791 -1, -1, -1, -1, -1, -1, -1, -1,
792 -1, -1, -1, -1, -1, -1, -1, -1,
793 -1, -1, -1, -1, -1, -1, -1, -1
794};
795
796static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
797 0, 1, /* line in */
798 8, 9, /* aes in */
799 10, 11, /* spdif in */
800 12, 16, /* adat in */
801 -1, -1, -1, -1, -1, -1, -1, -1,
802 -1, -1, -1, -1, -1, -1, -1, -1,
803 -1, -1, -1, -1, -1, -1, -1, -1,
804 -1, -1, -1, -1, -1, -1, -1, -1,
805 -1, -1, -1, -1, -1, -1, -1, -1,
806 -1, -1, -1, -1, -1, -1, -1, -1,
807 -1, -1, -1, -1, -1, -1, -1, -1
808};
809
810static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
811 0, 1, /* line out */
812 8, 9, /* aes out */
813 10, 11, /* spdif out */
814 12, 16, /* adat out */
815 6, 7, /* phone out */
816 -1, -1, -1, -1, -1, -1,
817 -1, -1, -1, -1, -1, -1, -1, -1,
818 -1, -1, -1, -1, -1, -1, -1, -1,
819 -1, -1, -1, -1, -1, -1, -1, -1,
820 -1, -1, -1, -1, -1, -1, -1, -1,
821 -1, -1, -1, -1, -1, -1, -1, -1,
822 -1, -1, -1, -1, -1, -1, -1, -1
823};
824
Adrian Knoth432d2502011-02-23 11:43:08 +0100825static char channel_map_aes32[HDSPM_MAX_CHANNELS] = {
826 0, 1, 2, 3, 4, 5, 6, 7,
827 8, 9, 10, 11, 12, 13, 14, 15,
828 -1, -1, -1, -1, -1, -1, -1, -1,
829 -1, -1, -1, -1, -1, -1, -1, -1,
830 -1, -1, -1, -1, -1, -1, -1, -1,
831 -1, -1, -1, -1, -1, -1, -1, -1,
832 -1, -1, -1, -1, -1, -1, -1, -1,
833 -1, -1, -1, -1, -1, -1, -1, -1
834};
835
Takashi Iwai98274f02005-11-17 14:52:34 +0100836struct hdspm_midi {
837 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200838 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100839 struct snd_rawmidi *rmidi;
840 struct snd_rawmidi_substream *input;
841 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200842 char istimer; /* timer in use */
843 struct timer_list timer;
844 spinlock_t lock;
845 int pending;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100846 int dataIn;
847 int statusIn;
848 int dataOut;
849 int statusOut;
850 int ie;
851 int irq;
852};
853
854struct hdspm_tco {
855 int input;
856 int framerate;
857 int wordclock;
858 int samplerate;
859 int pull;
860 int term; /* 0 = off, 1 = on */
Takashi Iwai763f3562005-06-03 11:25:34 +0200861};
862
Takashi Iwai98274f02005-11-17 14:52:34 +0100863struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200864 spinlock_t lock;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200865 /* only one playback and/or capture stream */
866 struct snd_pcm_substream *capture_substream;
867 struct snd_pcm_substream *playback_substream;
Takashi Iwai763f3562005-06-03 11:25:34 +0200868
869 char *card_name; /* for procinfo */
Remy Bruno3cee5a62006-10-16 12:46:32 +0200870 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
871
Adrian Knoth0dca1792011-01-26 19:32:14 +0100872 uint8_t io_type;
Takashi Iwai763f3562005-06-03 11:25:34 +0200873
Takashi Iwai763f3562005-06-03 11:25:34 +0200874 int monitor_outs; /* set up monitoring outs init flag */
875
876 u32 control_register; /* cached value */
877 u32 control2_register; /* cached value */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100878 u32 settings_register;
Takashi Iwai763f3562005-06-03 11:25:34 +0200879
Adrian Knoth0dca1792011-01-26 19:32:14 +0100880 struct hdspm_midi midi[4];
Takashi Iwai763f3562005-06-03 11:25:34 +0200881 struct tasklet_struct midi_tasklet;
882
883 size_t period_bytes;
Adrian Knoth0dca1792011-01-26 19:32:14 +0100884 unsigned char ss_in_channels;
885 unsigned char ds_in_channels;
886 unsigned char qs_in_channels;
887 unsigned char ss_out_channels;
888 unsigned char ds_out_channels;
889 unsigned char qs_out_channels;
890
891 unsigned char max_channels_in;
892 unsigned char max_channels_out;
893
894 char *channel_map_in;
895 char *channel_map_out;
896
897 char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
898 char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
899
900 char **port_names_in;
901 char **port_names_out;
902
903 char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs;
904 char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs;
Takashi Iwai763f3562005-06-03 11:25:34 +0200905
906 unsigned char *playback_buffer; /* suitably aligned address */
907 unsigned char *capture_buffer; /* suitably aligned address */
908
909 pid_t capture_pid; /* process id which uses capture */
910 pid_t playback_pid; /* process id which uses capture */
911 int running; /* running status */
912
913 int last_external_sample_rate; /* samplerate mystic ... */
914 int last_internal_sample_rate;
915 int system_sample_rate;
916
Takashi Iwai763f3562005-06-03 11:25:34 +0200917 int dev; /* Hardware vars... */
918 int irq;
919 unsigned long port;
920 void __iomem *iobase;
921
922 int irq_count; /* for debug */
Adrian Knoth0dca1792011-01-26 19:32:14 +0100923 int midiPorts;
Takashi Iwai763f3562005-06-03 11:25:34 +0200924
Takashi Iwai98274f02005-11-17 14:52:34 +0100925 struct snd_card *card; /* one card */
926 struct snd_pcm *pcm; /* has one pcm */
927 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +0200928 struct pci_dev *pci; /* and an pci info */
929
930 /* Mixer vars */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200931 /* fast alsa mixer */
932 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
933 /* but input to much, so not used */
934 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
Adrian Knoth0dca1792011-01-26 19:32:14 +0100935 /* full mixer accessable over mixer ioctl or hwdep-device */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +0200936 struct hdspm_mixer *mixer;
Takashi Iwai763f3562005-06-03 11:25:34 +0200937
Adrian Knoth0dca1792011-01-26 19:32:14 +0100938 struct hdspm_tco *tco; /* NULL if no TCO detected */
Takashi Iwai763f3562005-06-03 11:25:34 +0200939
Adrian Knoth0dca1792011-01-26 19:32:14 +0100940 char **texts_autosync;
941 int texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +0200942
Adrian Knoth0dca1792011-01-26 19:32:14 +0100943 cycles_t last_interrupt;
Jaroslav Kysela730a5862011-01-27 13:03:15 +0100944
945 struct hdspm_peak_rms peak_rms;
Takashi Iwai763f3562005-06-03 11:25:34 +0200946};
947
Takashi Iwai763f3562005-06-03 11:25:34 +0200948
Alexey Dobriyancebe41d2010-02-06 00:21:03 +0200949static DEFINE_PCI_DEVICE_TABLE(snd_hdspm_ids) = {
Takashi Iwai763f3562005-06-03 11:25:34 +0200950 {
951 .vendor = PCI_VENDOR_ID_XILINX,
952 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
953 .subvendor = PCI_ANY_ID,
954 .subdevice = PCI_ANY_ID,
955 .class = 0,
956 .class_mask = 0,
957 .driver_data = 0},
958 {0,}
959};
960
961MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
962
963/* prototypes */
Takashi Iwai98274f02005-11-17 14:52:34 +0100964static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
965 struct hdspm * hdspm);
966static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
967 struct hdspm * hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200968
Adrian Knoth0dca1792011-01-26 19:32:14 +0100969static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
970static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
971static int hdspm_autosync_ref(struct hdspm *hdspm);
972static int snd_hdspm_set_defaults(struct hdspm *hdspm);
973static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +0200974 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +0200975 unsigned int reg, int channels);
976
Remy Bruno3cee5a62006-10-16 12:46:32 +0200977static inline int HDSPM_bit2freq(int n)
978{
Denys Vlasenko62cef822008-04-14 13:04:18 +0200979 static const int bit2freq_tab[] = {
980 0, 32000, 44100, 48000, 64000, 88200,
Remy Bruno3cee5a62006-10-16 12:46:32 +0200981 96000, 128000, 176400, 192000 };
982 if (n < 1 || n > 9)
983 return 0;
984 return bit2freq_tab[n];
985}
986
Adrian Knoth0dca1792011-01-26 19:32:14 +0100987/* Write/read to/from HDSPM with Adresses in Bytes
Takashi Iwai763f3562005-06-03 11:25:34 +0200988 not words but only 32Bit writes are allowed */
989
Takashi Iwai98274f02005-11-17 14:52:34 +0100990static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +0200991 unsigned int val)
992{
993 writel(val, hdspm->iobase + reg);
994}
995
Takashi Iwai98274f02005-11-17 14:52:34 +0100996static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +0200997{
998 return readl(hdspm->iobase + reg);
999}
1000
Adrian Knoth0dca1792011-01-26 19:32:14 +01001001/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
1002 mixer is write only on hardware so we have to cache him for read
Takashi Iwai763f3562005-06-03 11:25:34 +02001003 each fader is a u32, but uses only the first 16 bit */
1004
Takashi Iwai98274f02005-11-17 14:52:34 +01001005static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001006 unsigned int in)
1007{
Adrian Bunk5bab2482006-03-13 14:15:04 +01001008 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001009 return 0;
1010
1011 return hdspm->mixer->ch[chan].in[in];
1012}
1013
Takashi Iwai98274f02005-11-17 14:52:34 +01001014static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001015 unsigned int pb)
1016{
Adrian Bunk5bab2482006-03-13 14:15:04 +01001017 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +02001018 return 0;
1019 return hdspm->mixer->ch[chan].pb[pb];
1020}
1021
Denys Vlasenko62cef822008-04-14 13:04:18 +02001022static int hdspm_write_in_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001023 unsigned int in, unsigned short data)
1024{
1025 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
1026 return -1;
1027
1028 hdspm_write(hdspm,
1029 HDSPM_MADI_mixerBase +
1030 ((in + 128 * chan) * sizeof(u32)),
1031 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
1032 return 0;
1033}
1034
Denys Vlasenko62cef822008-04-14 13:04:18 +02001035static int hdspm_write_pb_gain(struct hdspm *hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +02001036 unsigned int pb, unsigned short data)
1037{
1038 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
1039 return -1;
1040
1041 hdspm_write(hdspm,
1042 HDSPM_MADI_mixerBase +
1043 ((64 + pb + 128 * chan) * sizeof(u32)),
1044 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
1045 return 0;
1046}
1047
1048
1049/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +01001050static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001051{
1052 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
1053}
1054
Takashi Iwai98274f02005-11-17 14:52:34 +01001055static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +02001056{
1057 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
1058}
1059
1060/* check if same process is writing and reading */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001061static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001062{
1063 unsigned long flags;
1064 int ret = 1;
1065
1066 spin_lock_irqsave(&hdspm->lock, flags);
1067 if ((hdspm->playback_pid != hdspm->capture_pid) &&
1068 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
1069 ret = 0;
1070 }
1071 spin_unlock_irqrestore(&hdspm->lock, flags);
1072 return ret;
1073}
1074
1075/* check for external sample rate */
Denys Vlasenko62cef822008-04-14 13:04:18 +02001076static int hdspm_external_sample_rate(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001077{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001078 unsigned int status, status2, timecode;
1079 int syncref, rate = 0, rate_bits;
Takashi Iwai763f3562005-06-03 11:25:34 +02001080
Adrian Knoth0dca1792011-01-26 19:32:14 +01001081 switch (hdspm->io_type) {
1082 case AES32:
1083 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1084 status = hdspm_read(hdspm, HDSPM_statusRegister);
1085 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
1086
1087 syncref = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001088
Remy Bruno3cee5a62006-10-16 12:46:32 +02001089 if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
1090 status & HDSPM_AES32_wcLock)
Adrian Knoth0dca1792011-01-26 19:32:14 +01001091 return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
1092
Remy Bruno3cee5a62006-10-16 12:46:32 +02001093 if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001094 syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
1095 status2 & (HDSPM_LockAES >>
1096 (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
1097 return HDSPM_bit2freq((timecode >> (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
Remy Bruno3cee5a62006-10-16 12:46:32 +02001098 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001099 break;
1100
1101 case MADIface:
1102 status = hdspm_read(hdspm, HDSPM_statusRegister);
1103
1104 if (!(status & HDSPM_madiLock)) {
1105 rate = 0; /* no lock */
1106 } else {
1107 switch (status & (HDSPM_status1_freqMask)) {
1108 case HDSPM_status1_F_0*1:
1109 rate = 32000; break;
1110 case HDSPM_status1_F_0*2:
1111 rate = 44100; break;
1112 case HDSPM_status1_F_0*3:
1113 rate = 48000; break;
1114 case HDSPM_status1_F_0*4:
1115 rate = 64000; break;
1116 case HDSPM_status1_F_0*5:
1117 rate = 88200; break;
1118 case HDSPM_status1_F_0*6:
1119 rate = 96000; break;
1120 case HDSPM_status1_F_0*7:
1121 rate = 128000; break;
1122 case HDSPM_status1_F_0*8:
1123 rate = 176400; break;
1124 case HDSPM_status1_F_0*9:
1125 rate = 192000; break;
1126 default:
1127 rate = 0; break;
1128 }
1129 }
1130
1131 break;
1132
1133 case MADI:
1134 case AIO:
1135 case RayDAT:
1136 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1137 status = hdspm_read(hdspm, HDSPM_statusRegister);
1138 rate = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001139
Remy Bruno3cee5a62006-10-16 12:46:32 +02001140 /* if wordclock has synced freq and wordclock is valid */
1141 if ((status2 & HDSPM_wcLock) != 0 &&
1142 (status & HDSPM_SelSyncRef0) == 0) {
1143
1144 rate_bits = status2 & HDSPM_wcFreqMask;
1145
Adrian Knoth0dca1792011-01-26 19:32:14 +01001146
Remy Bruno3cee5a62006-10-16 12:46:32 +02001147 switch (rate_bits) {
1148 case HDSPM_wcFreq32:
1149 rate = 32000;
1150 break;
1151 case HDSPM_wcFreq44_1:
1152 rate = 44100;
1153 break;
1154 case HDSPM_wcFreq48:
1155 rate = 48000;
1156 break;
1157 case HDSPM_wcFreq64:
1158 rate = 64000;
1159 break;
1160 case HDSPM_wcFreq88_2:
1161 rate = 88200;
1162 break;
1163 case HDSPM_wcFreq96:
1164 rate = 96000;
1165 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001166 default:
1167 rate = 0;
1168 break;
1169 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001170 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001171
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001172 /* if rate detected and Syncref is Word than have it,
1173 * word has priority to MADI
1174 */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001175 if (rate != 0 &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01001176 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
Remy Bruno3cee5a62006-10-16 12:46:32 +02001177 return rate;
1178
Adrian Knoth0dca1792011-01-26 19:32:14 +01001179 /* maybe a madi input (which is taken if sel sync is madi) */
Remy Bruno3cee5a62006-10-16 12:46:32 +02001180 if (status & HDSPM_madiLock) {
1181 rate_bits = status & HDSPM_madiFreqMask;
1182
1183 switch (rate_bits) {
1184 case HDSPM_madiFreq32:
1185 rate = 32000;
1186 break;
1187 case HDSPM_madiFreq44_1:
1188 rate = 44100;
1189 break;
1190 case HDSPM_madiFreq48:
1191 rate = 48000;
1192 break;
1193 case HDSPM_madiFreq64:
1194 rate = 64000;
1195 break;
1196 case HDSPM_madiFreq88_2:
1197 rate = 88200;
1198 break;
1199 case HDSPM_madiFreq96:
1200 rate = 96000;
1201 break;
1202 case HDSPM_madiFreq128:
1203 rate = 128000;
1204 break;
1205 case HDSPM_madiFreq176_4:
1206 rate = 176400;
1207 break;
1208 case HDSPM_madiFreq192:
1209 rate = 192000;
1210 break;
1211 default:
1212 rate = 0;
1213 break;
1214 }
1215 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001216 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001217 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01001218
1219 return rate;
Takashi Iwai763f3562005-06-03 11:25:34 +02001220}
1221
1222/* Latency function */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001223static inline void hdspm_compute_period_size(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001224{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001225 hdspm->period_bytes = 1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
Takashi Iwai763f3562005-06-03 11:25:34 +02001226}
1227
Adrian Knoth0dca1792011-01-26 19:32:14 +01001228
1229static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001230{
1231 int position;
1232
1233 position = hdspm_read(hdspm, HDSPM_statusRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +02001234 position &= HDSPM_BufferPositionMask;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001235 position /= 4; /* Bytes per sample */
Takashi Iwai763f3562005-06-03 11:25:34 +02001236
1237 return position;
1238}
1239
1240
Takashi Iwai98274f02005-11-17 14:52:34 +01001241static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001242{
1243 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
1244 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1245}
1246
Takashi Iwai98274f02005-11-17 14:52:34 +01001247static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +02001248{
1249 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
1250 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1251}
1252
1253/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Denys Vlasenko62cef822008-04-14 13:04:18 +02001254static void hdspm_silence_playback(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001255{
1256 int i;
1257 int n = hdspm->period_bytes;
1258 void *buf = hdspm->playback_buffer;
1259
Remy Bruno3cee5a62006-10-16 12:46:32 +02001260 if (buf == NULL)
1261 return;
Takashi Iwai763f3562005-06-03 11:25:34 +02001262
1263 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
1264 memset(buf, 0, n);
1265 buf += HDSPM_CHANNEL_BUFFER_BYTES;
1266 }
1267}
1268
Adrian Knoth0dca1792011-01-26 19:32:14 +01001269static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +02001270{
1271 int n;
1272
1273 spin_lock_irq(&s->lock);
1274
1275 frames >>= 7;
1276 n = 0;
1277 while (frames) {
1278 n++;
1279 frames >>= 1;
1280 }
1281 s->control_register &= ~HDSPM_LatencyMask;
1282 s->control_register |= hdspm_encode_latency(n);
1283
1284 hdspm_write(s, HDSPM_controlRegister, s->control_register);
1285
1286 hdspm_compute_period_size(s);
1287
1288 spin_unlock_irq(&s->lock);
1289
1290 return 0;
1291}
1292
Adrian Knoth0dca1792011-01-26 19:32:14 +01001293static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
1294{
1295 u64 freq_const;
1296
1297 if (period == 0)
1298 return 0;
1299
1300 switch (hdspm->io_type) {
1301 case MADI:
1302 case AES32:
1303 freq_const = 110069313433624ULL;
1304 break;
1305 case RayDAT:
1306 case AIO:
1307 freq_const = 104857600000000ULL;
1308 break;
1309 case MADIface:
1310 freq_const = 131072000000000ULL;
1311 }
1312
1313 return div_u64(freq_const, period);
1314}
1315
1316
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001317static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
1318{
1319 u64 n;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001320
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001321 if (rate >= 112000)
1322 rate /= 4;
1323 else if (rate >= 56000)
1324 rate /= 2;
1325
Adrian Knoth0dca1792011-01-26 19:32:14 +01001326 switch (hdspm->io_type) {
1327 case MADIface:
1328 n = 131072000000000ULL; /* 125 MHz */
1329 break;
1330 case MADI:
1331 case AES32:
1332 n = 110069313433624ULL; /* 105 MHz */
1333 break;
1334 case RayDAT:
1335 case AIO:
1336 n = 104857600000000ULL; /* 100 MHz */
1337 break;
1338 }
1339
Takashi Iwai3f7440a2009-06-05 17:40:04 +02001340 n = div_u64(n, rate);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001341 /* n should be less than 2^32 for being written to FREQ register */
Takashi Iwaida3cec32008-08-08 17:12:14 +02001342 snd_BUG_ON(n >> 32);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001343 hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
1344}
Takashi Iwai763f3562005-06-03 11:25:34 +02001345
1346/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +01001347static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +02001348{
Takashi Iwai763f3562005-06-03 11:25:34 +02001349 int current_rate;
1350 int rate_bits;
1351 int not_set = 0;
Remy Bruno65345992007-08-31 12:21:08 +02001352 int current_speed, target_speed;
Takashi Iwai763f3562005-06-03 11:25:34 +02001353
1354 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
1355 it (e.g. during module initialization).
1356 */
1357
1358 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
1359
Adrian Knoth0dca1792011-01-26 19:32:14 +01001360 /* SLAVE --- */
Takashi Iwai763f3562005-06-03 11:25:34 +02001361 if (called_internally) {
1362
Adrian Knoth0dca1792011-01-26 19:32:14 +01001363 /* request from ctl or card initialization
1364 just make a warning an remember setting
1365 for future master mode switching */
1366
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001367 snd_printk(KERN_WARNING "HDSPM: "
1368 "Warning: device is not running "
1369 "as a clock master.\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001370 not_set = 1;
1371 } else {
1372
1373 /* hw_param request while in AutoSync mode */
1374 int external_freq =
1375 hdspm_external_sample_rate(hdspm);
1376
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001377 if (hdspm_autosync_ref(hdspm) ==
1378 HDSPM_AUTOSYNC_FROM_NONE) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001379
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001380 snd_printk(KERN_WARNING "HDSPM: "
1381 "Detected no Externel Sync \n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001382 not_set = 1;
1383
1384 } else if (rate != external_freq) {
1385
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001386 snd_printk(KERN_WARNING "HDSPM: "
1387 "Warning: No AutoSync source for "
1388 "requested rate\n");
Takashi Iwai763f3562005-06-03 11:25:34 +02001389 not_set = 1;
1390 }
1391 }
1392 }
1393
1394 current_rate = hdspm->system_sample_rate;
1395
1396 /* Changing between Singe, Double and Quad speed is not
1397 allowed if any substreams are open. This is because such a change
1398 causes a shift in the location of the DMA buffers and a reduction
1399 in the number of available buffers.
1400
1401 Note that a similar but essentially insoluble problem exists for
1402 externally-driven rate changes. All we can do is to flag rate
Adrian Knoth0dca1792011-01-26 19:32:14 +01001403 changes in the read/write routines.
Takashi Iwai763f3562005-06-03 11:25:34 +02001404 */
1405
Remy Bruno65345992007-08-31 12:21:08 +02001406 if (current_rate <= 48000)
1407 current_speed = HDSPM_SPEED_SINGLE;
1408 else if (current_rate <= 96000)
1409 current_speed = HDSPM_SPEED_DOUBLE;
1410 else
1411 current_speed = HDSPM_SPEED_QUAD;
1412
1413 if (rate <= 48000)
1414 target_speed = HDSPM_SPEED_SINGLE;
1415 else if (rate <= 96000)
1416 target_speed = HDSPM_SPEED_DOUBLE;
1417 else
1418 target_speed = HDSPM_SPEED_QUAD;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001419
Takashi Iwai763f3562005-06-03 11:25:34 +02001420 switch (rate) {
1421 case 32000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001422 rate_bits = HDSPM_Frequency32KHz;
1423 break;
1424 case 44100:
Takashi Iwai763f3562005-06-03 11:25:34 +02001425 rate_bits = HDSPM_Frequency44_1KHz;
1426 break;
1427 case 48000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001428 rate_bits = HDSPM_Frequency48KHz;
1429 break;
1430 case 64000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001431 rate_bits = HDSPM_Frequency64KHz;
1432 break;
1433 case 88200:
Takashi Iwai763f3562005-06-03 11:25:34 +02001434 rate_bits = HDSPM_Frequency88_2KHz;
1435 break;
1436 case 96000:
Takashi Iwai763f3562005-06-03 11:25:34 +02001437 rate_bits = HDSPM_Frequency96KHz;
1438 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02001439 case 128000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001440 rate_bits = HDSPM_Frequency128KHz;
1441 break;
1442 case 176400:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001443 rate_bits = HDSPM_Frequency176_4KHz;
1444 break;
1445 case 192000:
Remy Bruno3cee5a62006-10-16 12:46:32 +02001446 rate_bits = HDSPM_Frequency192KHz;
1447 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02001448 default:
1449 return -EINVAL;
1450 }
1451
Remy Bruno65345992007-08-31 12:21:08 +02001452 if (current_speed != target_speed
Takashi Iwai763f3562005-06-03 11:25:34 +02001453 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
1454 snd_printk
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001455 (KERN_ERR "HDSPM: "
Remy Bruno65345992007-08-31 12:21:08 +02001456 "cannot change from %s speed to %s speed mode "
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001457 "(capture PID = %d, playback PID = %d)\n",
Remy Bruno65345992007-08-31 12:21:08 +02001458 hdspm_speed_names[current_speed],
1459 hdspm_speed_names[target_speed],
Takashi Iwai763f3562005-06-03 11:25:34 +02001460 hdspm->capture_pid, hdspm->playback_pid);
1461 return -EBUSY;
1462 }
1463
1464 hdspm->control_register &= ~HDSPM_FrequencyMask;
1465 hdspm->control_register |= rate_bits;
1466 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1467
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001468 /* For AES32, need to set DDS value in FREQ register
1469 For MADI, also apparently */
1470 hdspm_set_dds_value(hdspm, rate);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001471
1472 if (AES32 == hdspm->io_type && rate != current_rate)
Remy Brunoffb2c3c2007-03-07 19:08:46 +01001473 hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
Takashi Iwai763f3562005-06-03 11:25:34 +02001474
1475 hdspm->system_sample_rate = rate;
1476
Adrian Knoth0dca1792011-01-26 19:32:14 +01001477 if (rate <= 48000) {
1478 hdspm->channel_map_in = hdspm->channel_map_in_ss;
1479 hdspm->channel_map_out = hdspm->channel_map_out_ss;
1480 hdspm->max_channels_in = hdspm->ss_in_channels;
1481 hdspm->max_channels_out = hdspm->ss_out_channels;
1482 hdspm->port_names_in = hdspm->port_names_in_ss;
1483 hdspm->port_names_out = hdspm->port_names_out_ss;
1484 } else if (rate <= 96000) {
1485 hdspm->channel_map_in = hdspm->channel_map_in_ds;
1486 hdspm->channel_map_out = hdspm->channel_map_out_ds;
1487 hdspm->max_channels_in = hdspm->ds_in_channels;
1488 hdspm->max_channels_out = hdspm->ds_out_channels;
1489 hdspm->port_names_in = hdspm->port_names_in_ds;
1490 hdspm->port_names_out = hdspm->port_names_out_ds;
1491 } else {
1492 hdspm->channel_map_in = hdspm->channel_map_in_qs;
1493 hdspm->channel_map_out = hdspm->channel_map_out_qs;
1494 hdspm->max_channels_in = hdspm->qs_in_channels;
1495 hdspm->max_channels_out = hdspm->qs_out_channels;
1496 hdspm->port_names_in = hdspm->port_names_in_qs;
1497 hdspm->port_names_out = hdspm->port_names_out_qs;
1498 }
1499
Takashi Iwai763f3562005-06-03 11:25:34 +02001500 if (not_set != 0)
1501 return -1;
1502
1503 return 0;
1504}
1505
1506/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +01001507static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +02001508{
1509 int i, j;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001510 unsigned int gain;
1511
1512 if (sgain > UNITY_GAIN)
1513 gain = UNITY_GAIN;
1514 else if (sgain < 0)
1515 gain = 0;
1516 else
1517 gain = sgain;
Takashi Iwai763f3562005-06-03 11:25:34 +02001518
1519 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
1520 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
1521 hdspm_write_in_gain(hdspm, i, j, gain);
1522 hdspm_write_pb_gain(hdspm, i, j, gain);
1523 }
1524}
1525
1526/*----------------------------------------------------------------------------
1527 MIDI
1528 ----------------------------------------------------------------------------*/
1529
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001530static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
1531 int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001532{
1533 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001534 return hdspm_read(hdspm, hdspm->midi[id].dataIn);
Takashi Iwai763f3562005-06-03 11:25:34 +02001535}
1536
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001537static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
1538 int val)
Takashi Iwai763f3562005-06-03 11:25:34 +02001539{
1540 /* the hardware already does the relevant bit-mask with 0xff */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001541 return hdspm_write(hdspm, hdspm->midi[id].dataOut, val);
Takashi Iwai763f3562005-06-03 11:25:34 +02001542}
1543
Takashi Iwai98274f02005-11-17 14:52:34 +01001544static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001545{
Adrian Knoth0dca1792011-01-26 19:32:14 +01001546 return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001547}
1548
Takashi Iwai98274f02005-11-17 14:52:34 +01001549static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001550{
1551 int fifo_bytes_used;
1552
Adrian Knoth0dca1792011-01-26 19:32:14 +01001553 fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02001554
1555 if (fifo_bytes_used < 128)
1556 return 128 - fifo_bytes_used;
1557 else
1558 return 0;
1559}
1560
Denys Vlasenko62cef822008-04-14 13:04:18 +02001561static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001562{
1563 while (snd_hdspm_midi_input_available (hdspm, id))
1564 snd_hdspm_midi_read_byte (hdspm, id);
1565}
1566
Takashi Iwai98274f02005-11-17 14:52:34 +01001567static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001568{
1569 unsigned long flags;
1570 int n_pending;
1571 int to_write;
1572 int i;
1573 unsigned char buf[128];
1574
1575 /* Output is not interrupt driven */
Adrian Knoth0dca1792011-01-26 19:32:14 +01001576
Takashi Iwai763f3562005-06-03 11:25:34 +02001577 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001578 if (hmidi->output &&
1579 !snd_rawmidi_transmit_empty (hmidi->output)) {
1580 n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm,
1581 hmidi->id);
1582 if (n_pending > 0) {
1583 if (n_pending > (int)sizeof (buf))
1584 n_pending = sizeof (buf);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001585
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001586 to_write = snd_rawmidi_transmit (hmidi->output, buf,
1587 n_pending);
1588 if (to_write > 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001589 for (i = 0; i < to_write; ++i)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001590 snd_hdspm_midi_write_byte (hmidi->hdspm,
1591 hmidi->id,
1592 buf[i]);
Takashi Iwai763f3562005-06-03 11:25:34 +02001593 }
1594 }
1595 }
1596 spin_unlock_irqrestore (&hmidi->lock, flags);
1597 return 0;
1598}
1599
Takashi Iwai98274f02005-11-17 14:52:34 +01001600static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +02001601{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001602 unsigned char buf[128]; /* this buffer is designed to match the MIDI
1603 * input FIFO size
1604 */
Takashi Iwai763f3562005-06-03 11:25:34 +02001605 unsigned long flags;
1606 int n_pending;
1607 int i;
1608
1609 spin_lock_irqsave (&hmidi->lock, flags);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001610 n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id);
1611 if (n_pending > 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001612 if (hmidi->input) {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001613 if (n_pending > (int)sizeof (buf))
Takashi Iwai763f3562005-06-03 11:25:34 +02001614 n_pending = sizeof (buf);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001615 for (i = 0; i < n_pending; ++i)
1616 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm,
1617 hmidi->id);
1618 if (n_pending)
1619 snd_rawmidi_receive (hmidi->input, buf,
1620 n_pending);
Takashi Iwai763f3562005-06-03 11:25:34 +02001621 } else {
1622 /* flush the MIDI input FIFO */
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001623 while (n_pending--)
1624 snd_hdspm_midi_read_byte (hmidi->hdspm,
1625 hmidi->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02001626 }
1627 }
1628 hmidi->pending = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001629
1630 hmidi->hdspm->control_register |= hmidi->ie;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001631 hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
1632 hmidi->hdspm->control_register);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001633
Takashi Iwai763f3562005-06-03 11:25:34 +02001634 spin_unlock_irqrestore (&hmidi->lock, flags);
1635 return snd_hdspm_midi_output_write (hmidi);
1636}
1637
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001638static void
1639snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001640{
Takashi Iwai98274f02005-11-17 14:52:34 +01001641 struct hdspm *hdspm;
1642 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001643 unsigned long flags;
Takashi Iwai763f3562005-06-03 11:25:34 +02001644
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001645 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001646 hdspm = hmidi->hdspm;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001647
Takashi Iwai763f3562005-06-03 11:25:34 +02001648 spin_lock_irqsave (&hdspm->lock, flags);
1649 if (up) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001650 if (!(hdspm->control_register & hmidi->ie)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02001651 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
Adrian Knoth0dca1792011-01-26 19:32:14 +01001652 hdspm->control_register |= hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001653 }
1654 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01001655 hdspm->control_register &= ~hmidi->ie;
Takashi Iwai763f3562005-06-03 11:25:34 +02001656 }
1657
1658 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1659 spin_unlock_irqrestore (&hdspm->lock, flags);
1660}
1661
1662static void snd_hdspm_midi_output_timer(unsigned long data)
1663{
Takashi Iwai98274f02005-11-17 14:52:34 +01001664 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001665 unsigned long flags;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001666
Takashi Iwai763f3562005-06-03 11:25:34 +02001667 snd_hdspm_midi_output_write(hmidi);
1668 spin_lock_irqsave (&hmidi->lock, flags);
1669
1670 /* this does not bump hmidi->istimer, because the
1671 kernel automatically removed the timer when it
1672 expired, and we are now adding it back, thus
Adrian Knoth0dca1792011-01-26 19:32:14 +01001673 leaving istimer wherever it was set before.
Takashi Iwai763f3562005-06-03 11:25:34 +02001674 */
1675
1676 if (hmidi->istimer) {
1677 hmidi->timer.expires = 1 + jiffies;
1678 add_timer(&hmidi->timer);
1679 }
1680
1681 spin_unlock_irqrestore (&hmidi->lock, flags);
1682}
1683
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001684static void
1685snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001686{
Takashi Iwai98274f02005-11-17 14:52:34 +01001687 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001688 unsigned long flags;
1689
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001690 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001691 spin_lock_irqsave (&hmidi->lock, flags);
1692 if (up) {
1693 if (!hmidi->istimer) {
1694 init_timer(&hmidi->timer);
1695 hmidi->timer.function = snd_hdspm_midi_output_timer;
1696 hmidi->timer.data = (unsigned long) hmidi;
1697 hmidi->timer.expires = 1 + jiffies;
1698 add_timer(&hmidi->timer);
1699 hmidi->istimer++;
1700 }
1701 } else {
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001702 if (hmidi->istimer && --hmidi->istimer <= 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02001703 del_timer (&hmidi->timer);
Takashi Iwai763f3562005-06-03 11:25:34 +02001704 }
1705 spin_unlock_irqrestore (&hmidi->lock, flags);
1706 if (up)
1707 snd_hdspm_midi_output_write(hmidi);
1708}
1709
Takashi Iwai98274f02005-11-17 14:52:34 +01001710static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001711{
Takashi Iwai98274f02005-11-17 14:52:34 +01001712 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001713
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001714 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001715 spin_lock_irq (&hmidi->lock);
1716 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1717 hmidi->input = substream;
1718 spin_unlock_irq (&hmidi->lock);
1719
1720 return 0;
1721}
1722
Takashi Iwai98274f02005-11-17 14:52:34 +01001723static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001724{
Takashi Iwai98274f02005-11-17 14:52:34 +01001725 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001726
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001727 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001728 spin_lock_irq (&hmidi->lock);
1729 hmidi->output = substream;
1730 spin_unlock_irq (&hmidi->lock);
1731
1732 return 0;
1733}
1734
Takashi Iwai98274f02005-11-17 14:52:34 +01001735static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001736{
Takashi Iwai98274f02005-11-17 14:52:34 +01001737 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001738
1739 snd_hdspm_midi_input_trigger (substream, 0);
1740
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001741 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001742 spin_lock_irq (&hmidi->lock);
1743 hmidi->input = NULL;
1744 spin_unlock_irq (&hmidi->lock);
1745
1746 return 0;
1747}
1748
Takashi Iwai98274f02005-11-17 14:52:34 +01001749static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001750{
Takashi Iwai98274f02005-11-17 14:52:34 +01001751 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001752
1753 snd_hdspm_midi_output_trigger (substream, 0);
1754
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001755 hmidi = substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001756 spin_lock_irq (&hmidi->lock);
1757 hmidi->output = NULL;
1758 spin_unlock_irq (&hmidi->lock);
1759
1760 return 0;
1761}
1762
Takashi Iwai98274f02005-11-17 14:52:34 +01001763static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001764{
1765 .open = snd_hdspm_midi_output_open,
1766 .close = snd_hdspm_midi_output_close,
1767 .trigger = snd_hdspm_midi_output_trigger,
1768};
1769
Takashi Iwai98274f02005-11-17 14:52:34 +01001770static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001771{
1772 .open = snd_hdspm_midi_input_open,
1773 .close = snd_hdspm_midi_input_close,
1774 .trigger = snd_hdspm_midi_input_trigger,
1775};
1776
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02001777static int __devinit snd_hdspm_create_midi (struct snd_card *card,
1778 struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001779{
1780 int err;
1781 char buf[32];
1782
1783 hdspm->midi[id].id = id;
Takashi Iwai763f3562005-06-03 11:25:34 +02001784 hdspm->midi[id].hdspm = hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +02001785 spin_lock_init (&hdspm->midi[id].lock);
1786
Adrian Knoth0dca1792011-01-26 19:32:14 +01001787 if (0 == id) {
1788 if (MADIface == hdspm->io_type) {
1789 /* MIDI-over-MADI on HDSPe MADIface */
1790 hdspm->midi[0].dataIn = HDSPM_midiDataIn2;
1791 hdspm->midi[0].statusIn = HDSPM_midiStatusIn2;
1792 hdspm->midi[0].dataOut = HDSPM_midiDataOut2;
1793 hdspm->midi[0].statusOut = HDSPM_midiStatusOut2;
1794 hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable;
1795 hdspm->midi[0].irq = HDSPM_midi2IRQPending;
1796 } else {
1797 hdspm->midi[0].dataIn = HDSPM_midiDataIn0;
1798 hdspm->midi[0].statusIn = HDSPM_midiStatusIn0;
1799 hdspm->midi[0].dataOut = HDSPM_midiDataOut0;
1800 hdspm->midi[0].statusOut = HDSPM_midiStatusOut0;
1801 hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable;
1802 hdspm->midi[0].irq = HDSPM_midi0IRQPending;
1803 }
1804 } else if (1 == id) {
1805 hdspm->midi[1].dataIn = HDSPM_midiDataIn1;
1806 hdspm->midi[1].statusIn = HDSPM_midiStatusIn1;
1807 hdspm->midi[1].dataOut = HDSPM_midiDataOut1;
1808 hdspm->midi[1].statusOut = HDSPM_midiStatusOut1;
1809 hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable;
1810 hdspm->midi[1].irq = HDSPM_midi1IRQPending;
1811 } else if ((2 == id) && (MADI == hdspm->io_type)) {
1812 /* MIDI-over-MADI on HDSPe MADI */
1813 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1814 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1815 hdspm->midi[2].dataOut = HDSPM_midiDataOut2;
1816 hdspm->midi[2].statusOut = HDSPM_midiStatusOut2;
1817 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1818 hdspm->midi[2].irq = HDSPM_midi2IRQPending;
1819 } else if (2 == id) {
1820 /* TCO MTC, read only */
1821 hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
1822 hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
1823 hdspm->midi[2].dataOut = -1;
1824 hdspm->midi[2].statusOut = -1;
1825 hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
1826 hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES;
1827 } else if (3 == id) {
1828 /* TCO MTC on HDSPe MADI */
1829 hdspm->midi[3].dataIn = HDSPM_midiDataIn3;
1830 hdspm->midi[3].statusIn = HDSPM_midiStatusIn3;
1831 hdspm->midi[3].dataOut = -1;
1832 hdspm->midi[3].statusOut = -1;
1833 hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable;
1834 hdspm->midi[3].irq = HDSPM_midi3IRQPending;
1835 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001836
Adrian Knoth0dca1792011-01-26 19:32:14 +01001837 if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) ||
1838 (MADIface == hdspm->io_type)))) {
1839 if ((id == 0) && (MADIface == hdspm->io_type)) {
1840 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1841 } else if ((id == 2) && (MADI == hdspm->io_type)) {
1842 sprintf(buf, "%s MIDIoverMADI", card->shortname);
1843 } else {
1844 sprintf(buf, "%s MIDI %d", card->shortname, id+1);
1845 }
1846 err = snd_rawmidi_new(card, buf, id, 1, 1,
1847 &hdspm->midi[id].rmidi);
1848 if (err < 0)
1849 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02001850
Adrian Knoth0dca1792011-01-26 19:32:14 +01001851 sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d",
1852 card->id, id+1);
1853 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
Takashi Iwai763f3562005-06-03 11:25:34 +02001854
Adrian Knoth0dca1792011-01-26 19:32:14 +01001855 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1856 SNDRV_RAWMIDI_STREAM_OUTPUT,
1857 &snd_hdspm_midi_output);
1858 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1859 SNDRV_RAWMIDI_STREAM_INPUT,
1860 &snd_hdspm_midi_input);
1861
1862 hdspm->midi[id].rmidi->info_flags |=
1863 SNDRV_RAWMIDI_INFO_OUTPUT |
1864 SNDRV_RAWMIDI_INFO_INPUT |
1865 SNDRV_RAWMIDI_INFO_DUPLEX;
1866 } else {
1867 /* TCO MTC, read only */
1868 sprintf(buf, "%s MTC %d", card->shortname, id+1);
1869 err = snd_rawmidi_new(card, buf, id, 1, 1,
1870 &hdspm->midi[id].rmidi);
1871 if (err < 0)
1872 return err;
1873
1874 sprintf(hdspm->midi[id].rmidi->name,
1875 "%s MTC %d", card->id, id+1);
1876 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
1877
1878 snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
1879 SNDRV_RAWMIDI_STREAM_INPUT,
1880 &snd_hdspm_midi_input);
1881
1882 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
1883 }
Takashi Iwai763f3562005-06-03 11:25:34 +02001884
1885 return 0;
1886}
1887
1888
1889static void hdspm_midi_tasklet(unsigned long arg)
1890{
Takashi Iwai98274f02005-11-17 14:52:34 +01001891 struct hdspm *hdspm = (struct hdspm *)arg;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001892 int i = 0;
1893
1894 while (i < hdspm->midiPorts) {
1895 if (hdspm->midi[i].pending)
1896 snd_hdspm_midi_input_read(&hdspm->midi[i]);
1897
1898 i++;
1899 }
1900}
Takashi Iwai763f3562005-06-03 11:25:34 +02001901
1902
1903/*-----------------------------------------------------------------------------
1904 Status Interface
1905 ----------------------------------------------------------------------------*/
1906
1907/* get the system sample rate which is set */
1908
Adrian Knoth0dca1792011-01-26 19:32:14 +01001909
1910/**
1911 * Calculate the real sample rate from the
1912 * current DDS value.
1913 **/
1914static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
1915{
1916 unsigned int period, rate;
1917
1918 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
1919 rate = hdspm_calc_dds_value(hdspm, period);
1920
1921 return rate;
1922}
1923
1924
Takashi Iwai763f3562005-06-03 11:25:34 +02001925#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001926{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001927 .name = xname, \
1928 .index = xindex, \
1929 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1930 .info = snd_hdspm_info_system_sample_rate, \
1931 .get = snd_hdspm_get_system_sample_rate \
1932}
1933
Takashi Iwai98274f02005-11-17 14:52:34 +01001934static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
1935 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001936{
1937 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1938 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01001939 uinfo->value.integer.min = 27000;
1940 uinfo->value.integer.max = 207000;
1941 uinfo->value.integer.step = 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02001942 return 0;
1943}
1944
Adrian Knoth0dca1792011-01-26 19:32:14 +01001945
Takashi Iwai98274f02005-11-17 14:52:34 +01001946static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
1947 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02001948 ucontrol)
1949{
Takashi Iwai98274f02005-11-17 14:52:34 +01001950 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001951
Adrian Knoth0dca1792011-01-26 19:32:14 +01001952 ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02001953 return 0;
1954}
1955
Adrian Knoth0dca1792011-01-26 19:32:14 +01001956
1957/**
1958 * Returns the WordClock sample rate class for the given card.
1959 **/
1960static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
1961{
1962 int status;
1963
1964 switch (hdspm->io_type) {
1965 case RayDAT:
1966 case AIO:
1967 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
1968 return (status >> 16) & 0xF;
1969 break;
1970 default:
1971 break;
1972 }
1973
1974
1975 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02001976}
1977
Adrian Knoth0dca1792011-01-26 19:32:14 +01001978
1979/**
1980 * Returns the TCO sample rate class for the given card.
1981 **/
1982static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
1983{
1984 int status;
1985
1986 if (hdspm->tco) {
1987 switch (hdspm->io_type) {
1988 case RayDAT:
1989 case AIO:
1990 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
1991 return (status >> 20) & 0xF;
1992 break;
1993 default:
1994 break;
1995 }
1996 }
1997
1998 return 0;
1999}
2000
2001
2002/**
2003 * Returns the SYNC_IN sample rate class for the given card.
2004 **/
2005static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
2006{
2007 int status;
2008
2009 if (hdspm->tco) {
2010 switch (hdspm->io_type) {
2011 case RayDAT:
2012 case AIO:
2013 status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2014 return (status >> 12) & 0xF;
2015 break;
2016 default:
2017 break;
2018 }
2019 }
2020
2021 return 0;
2022}
2023
2024
2025/**
2026 * Returns the sample rate class for input source <idx> for
2027 * 'new style' cards like the AIO and RayDAT.
2028 **/
2029static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
2030{
2031 int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
2032
2033 return (status >> (idx*4)) & 0xF;
2034}
2035
2036
2037
2038#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
2039{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2040 .name = xname, \
2041 .private_value = xindex, \
2042 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2043 .info = snd_hdspm_info_autosync_sample_rate, \
2044 .get = snd_hdspm_get_autosync_sample_rate \
2045}
2046
2047
Takashi Iwai98274f02005-11-17 14:52:34 +01002048static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2049 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002050{
Takashi Iwai763f3562005-06-03 11:25:34 +02002051 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2052 uinfo->count = 1;
2053 uinfo->value.enumerated.items = 10;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002054
Takashi Iwai763f3562005-06-03 11:25:34 +02002055 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
Adrian Knoth0dca1792011-01-26 19:32:14 +01002056 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002057 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002058 texts_freq[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002059 return 0;
2060}
2061
Adrian Knoth0dca1792011-01-26 19:32:14 +01002062
Takashi Iwai98274f02005-11-17 14:52:34 +01002063static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
2064 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002065 ucontrol)
2066{
Takashi Iwai98274f02005-11-17 14:52:34 +01002067 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002068
Adrian Knoth0dca1792011-01-26 19:32:14 +01002069 switch (hdspm->io_type) {
2070 case RayDAT:
2071 switch (kcontrol->private_value) {
2072 case 0:
2073 ucontrol->value.enumerated.item[0] =
2074 hdspm_get_wc_sample_rate(hdspm);
2075 break;
2076 case 7:
2077 ucontrol->value.enumerated.item[0] =
2078 hdspm_get_tco_sample_rate(hdspm);
2079 break;
2080 case 8:
2081 ucontrol->value.enumerated.item[0] =
2082 hdspm_get_sync_in_sample_rate(hdspm);
2083 break;
2084 default:
2085 ucontrol->value.enumerated.item[0] =
2086 hdspm_get_s1_sample_rate(hdspm,
2087 kcontrol->private_value-1);
2088 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002089
Adrian Knoth0dca1792011-01-26 19:32:14 +01002090 case AIO:
2091 switch (kcontrol->private_value) {
2092 case 0: /* WC */
2093 ucontrol->value.enumerated.item[0] =
2094 hdspm_get_wc_sample_rate(hdspm);
2095 break;
2096 case 4: /* TCO */
2097 ucontrol->value.enumerated.item[0] =
2098 hdspm_get_tco_sample_rate(hdspm);
2099 break;
2100 case 5: /* SYNC_IN */
2101 ucontrol->value.enumerated.item[0] =
2102 hdspm_get_sync_in_sample_rate(hdspm);
2103 break;
2104 default:
2105 ucontrol->value.enumerated.item[0] =
2106 hdspm_get_s1_sample_rate(hdspm,
2107 ucontrol->id.index-1);
2108 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002109 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002110 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002111 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002112
Takashi Iwai763f3562005-06-03 11:25:34 +02002113 return 0;
2114}
2115
Adrian Knoth0dca1792011-01-26 19:32:14 +01002116
Takashi Iwai763f3562005-06-03 11:25:34 +02002117#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002118{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2119 .name = xname, \
2120 .index = xindex, \
2121 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2122 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2123 .info = snd_hdspm_info_system_clock_mode, \
2124 .get = snd_hdspm_get_system_clock_mode, \
2125 .put = snd_hdspm_put_system_clock_mode, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002126}
2127
2128
Adrian Knoth0dca1792011-01-26 19:32:14 +01002129/**
2130 * Returns the system clock mode for the given card.
2131 * @returns 0 - master, 1 - slave
2132 **/
2133static int hdspm_system_clock_mode(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002134{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002135 switch (hdspm->io_type) {
2136 case AIO:
2137 case RayDAT:
2138 if (hdspm->settings_register & HDSPM_c0Master)
2139 return 0;
2140 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002141
Adrian Knoth0dca1792011-01-26 19:32:14 +01002142 default:
2143 if (hdspm->control_register & HDSPM_ClockModeMaster)
2144 return 0;
2145 }
2146
Takashi Iwai763f3562005-06-03 11:25:34 +02002147 return 1;
2148}
2149
Adrian Knoth0dca1792011-01-26 19:32:14 +01002150
2151/**
2152 * Sets the system clock mode.
2153 * @param mode 0 - master, 1 - slave
2154 **/
2155static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
2156{
2157 switch (hdspm->io_type) {
2158 case AIO:
2159 case RayDAT:
2160 if (0 == mode)
2161 hdspm->settings_register |= HDSPM_c0Master;
2162 else
2163 hdspm->settings_register &= ~HDSPM_c0Master;
2164
2165 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2166 break;
2167
2168 default:
2169 if (0 == mode)
2170 hdspm->control_register |= HDSPM_ClockModeMaster;
2171 else
2172 hdspm->control_register &= ~HDSPM_ClockModeMaster;
2173
2174 hdspm_write(hdspm, HDSPM_controlRegister,
2175 hdspm->control_register);
2176 }
2177}
2178
2179
Takashi Iwai98274f02005-11-17 14:52:34 +01002180static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
2181 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002182{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002183 static char *texts[] = { "Master", "AutoSync" };
Takashi Iwai763f3562005-06-03 11:25:34 +02002184
2185 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2186 uinfo->count = 1;
2187 uinfo->value.enumerated.items = 2;
2188 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2189 uinfo->value.enumerated.item =
2190 uinfo->value.enumerated.items - 1;
2191 strcpy(uinfo->value.enumerated.name,
2192 texts[uinfo->value.enumerated.item]);
2193 return 0;
2194}
2195
Takashi Iwai98274f02005-11-17 14:52:34 +01002196static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
2197 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002198{
Takashi Iwai98274f02005-11-17 14:52:34 +01002199 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002200
Adrian Knoth0dca1792011-01-26 19:32:14 +01002201 ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002202 return 0;
2203}
2204
Adrian Knoth0dca1792011-01-26 19:32:14 +01002205static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol,
2206 struct snd_ctl_elem_value *ucontrol)
2207{
2208 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2209 int val;
2210
2211 if (!snd_hdspm_use_is_exclusive(hdspm))
2212 return -EBUSY;
2213
2214 val = ucontrol->value.enumerated.item[0];
2215 if (val < 0)
2216 val = 0;
2217 else if (val > 1)
2218 val = 1;
2219
2220 hdspm_set_system_clock_mode(hdspm, val);
2221
2222 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002223}
2224
Adrian Knoth0dca1792011-01-26 19:32:14 +01002225
2226#define HDSPM_INTERNAL_CLOCK(xname, xindex) \
2227{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2228 .name = xname, \
2229 .index = xindex, \
2230 .info = snd_hdspm_info_clock_source, \
2231 .get = snd_hdspm_get_clock_source, \
2232 .put = snd_hdspm_put_clock_source \
2233}
2234
2235
Takashi Iwai98274f02005-11-17 14:52:34 +01002236static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002237{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002238 switch (hdspm->system_sample_rate) {
2239 case 32000: return 0;
2240 case 44100: return 1;
2241 case 48000: return 2;
2242 case 64000: return 3;
2243 case 88200: return 4;
2244 case 96000: return 5;
2245 case 128000: return 6;
2246 case 176400: return 7;
2247 case 192000: return 8;
Takashi Iwai763f3562005-06-03 11:25:34 +02002248 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002249
2250 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002251}
2252
Takashi Iwai98274f02005-11-17 14:52:34 +01002253static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02002254{
2255 int rate;
2256 switch (mode) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002257 case 0:
2258 rate = 32000; break;
2259 case 1:
2260 rate = 44100; break;
2261 case 2:
2262 rate = 48000; break;
2263 case 3:
2264 rate = 64000; break;
2265 case 4:
2266 rate = 88200; break;
2267 case 5:
2268 rate = 96000; break;
2269 case 6:
2270 rate = 128000; break;
2271 case 7:
2272 rate = 176400; break;
2273 case 8:
2274 rate = 192000; break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002275 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01002276 rate = 48000;
Takashi Iwai763f3562005-06-03 11:25:34 +02002277 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002278 hdspm_set_rate(hdspm, rate, 1);
2279 return 0;
2280}
2281
Takashi Iwai98274f02005-11-17 14:52:34 +01002282static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
2283 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002284{
Takashi Iwai763f3562005-06-03 11:25:34 +02002285 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2286 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002287 uinfo->value.enumerated.items = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002288
2289 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2290 uinfo->value.enumerated.item =
2291 uinfo->value.enumerated.items - 1;
2292
2293 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01002294 texts_freq[uinfo->value.enumerated.item+1]);
Takashi Iwai763f3562005-06-03 11:25:34 +02002295
2296 return 0;
2297}
2298
Takashi Iwai98274f02005-11-17 14:52:34 +01002299static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
2300 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002301{
Takashi Iwai98274f02005-11-17 14:52:34 +01002302 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002303
2304 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
2305 return 0;
2306}
2307
Takashi Iwai98274f02005-11-17 14:52:34 +01002308static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
2309 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002310{
Takashi Iwai98274f02005-11-17 14:52:34 +01002311 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002312 int change;
2313 int val;
2314
2315 if (!snd_hdspm_use_is_exclusive(hdspm))
2316 return -EBUSY;
2317 val = ucontrol->value.enumerated.item[0];
2318 if (val < 0)
2319 val = 0;
Remy Bruno65345992007-08-31 12:21:08 +02002320 if (val > 9)
2321 val = 9;
Takashi Iwai763f3562005-06-03 11:25:34 +02002322 spin_lock_irq(&hdspm->lock);
2323 if (val != hdspm_clock_source(hdspm))
2324 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
2325 else
2326 change = 0;
2327 spin_unlock_irq(&hdspm->lock);
2328 return change;
2329}
2330
Adrian Knoth0dca1792011-01-26 19:32:14 +01002331
Takashi Iwai763f3562005-06-03 11:25:34 +02002332#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Adrian Knoth0dca1792011-01-26 19:32:14 +01002333{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2334 .name = xname, \
2335 .index = xindex, \
2336 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
2337 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2338 .info = snd_hdspm_info_pref_sync_ref, \
2339 .get = snd_hdspm_get_pref_sync_ref, \
2340 .put = snd_hdspm_put_pref_sync_ref \
Takashi Iwai763f3562005-06-03 11:25:34 +02002341}
2342
Adrian Knoth0dca1792011-01-26 19:32:14 +01002343
2344/**
2345 * Returns the current preferred sync reference setting.
2346 * The semantics of the return value are depending on the
2347 * card, please see the comments for clarification.
2348 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002349static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002350{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002351 switch (hdspm->io_type) {
2352 case AES32:
Remy Bruno3cee5a62006-10-16 12:46:32 +02002353 switch (hdspm->control_register & HDSPM_SyncRefMask) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002354 case 0: return 0; /* WC */
2355 case HDSPM_SyncRef0: return 1; /* AES 1 */
2356 case HDSPM_SyncRef1: return 2; /* AES 2 */
2357 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */
2358 case HDSPM_SyncRef2: return 4; /* AES 4 */
2359 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */
2360 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */
2361 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0:
2362 return 7; /* AES 7 */
2363 case HDSPM_SyncRef3: return 8; /* AES 8 */
2364 case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002365 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002366 break;
2367
2368 case MADI:
2369 case MADIface:
2370 if (hdspm->tco) {
2371 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2372 case 0: return 0; /* WC */
2373 case HDSPM_SyncRef0: return 1; /* MADI */
2374 case HDSPM_SyncRef1: return 2; /* TCO */
2375 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2376 return 3; /* SYNC_IN */
2377 }
2378 } else {
2379 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2380 case 0: return 0; /* WC */
2381 case HDSPM_SyncRef0: return 1; /* MADI */
2382 case HDSPM_SyncRef1+HDSPM_SyncRef0:
2383 return 2; /* SYNC_IN */
2384 }
Remy Bruno3cee5a62006-10-16 12:46:32 +02002385 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002386 break;
2387
2388 case RayDAT:
2389 if (hdspm->tco) {
2390 switch ((hdspm->settings_register &
2391 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2392 case 0: return 0; /* WC */
2393 case 3: return 1; /* ADAT 1 */
2394 case 4: return 2; /* ADAT 2 */
2395 case 5: return 3; /* ADAT 3 */
2396 case 6: return 4; /* ADAT 4 */
2397 case 1: return 5; /* AES */
2398 case 2: return 6; /* SPDIF */
2399 case 9: return 7; /* TCO */
2400 case 10: return 8; /* SYNC_IN */
2401 }
2402 } else {
2403 switch ((hdspm->settings_register &
2404 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2405 case 0: return 0; /* WC */
2406 case 3: return 1; /* ADAT 1 */
2407 case 4: return 2; /* ADAT 2 */
2408 case 5: return 3; /* ADAT 3 */
2409 case 6: return 4; /* ADAT 4 */
2410 case 1: return 5; /* AES */
2411 case 2: return 6; /* SPDIF */
2412 case 10: return 7; /* SYNC_IN */
2413 }
2414 }
2415
2416 break;
2417
2418 case AIO:
2419 if (hdspm->tco) {
2420 switch ((hdspm->settings_register &
2421 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2422 case 0: return 0; /* WC */
2423 case 3: return 1; /* ADAT */
2424 case 1: return 2; /* AES */
2425 case 2: return 3; /* SPDIF */
2426 case 9: return 4; /* TCO */
2427 case 10: return 5; /* SYNC_IN */
2428 }
2429 } else {
2430 switch ((hdspm->settings_register &
2431 HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
2432 case 0: return 0; /* WC */
2433 case 3: return 1; /* ADAT */
2434 case 1: return 2; /* AES */
2435 case 2: return 3; /* SPDIF */
2436 case 10: return 4; /* SYNC_IN */
2437 }
2438 }
2439
2440 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002441 }
2442
Adrian Knoth0dca1792011-01-26 19:32:14 +01002443 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002444}
2445
Adrian Knoth0dca1792011-01-26 19:32:14 +01002446
2447/**
2448 * Set the preferred sync reference to <pref>. The semantics
2449 * of <pref> are depending on the card type, see the comments
2450 * for clarification.
2451 **/
Takashi Iwai98274f02005-11-17 14:52:34 +01002452static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02002453{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002454 int p = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002455
Adrian Knoth0dca1792011-01-26 19:32:14 +01002456 switch (hdspm->io_type) {
2457 case AES32:
2458 hdspm->control_register &= ~HDSPM_SyncRefMask;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002459 switch (pref) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01002460 case 0: /* WC */
Remy Bruno3cee5a62006-10-16 12:46:32 +02002461 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002462 case 1: /* AES 1 */
2463 hdspm->control_register |= HDSPM_SyncRef0;
2464 break;
2465 case 2: /* AES 2 */
2466 hdspm->control_register |= HDSPM_SyncRef1;
2467 break;
2468 case 3: /* AES 3 */
2469 hdspm->control_register |=
2470 HDSPM_SyncRef1+HDSPM_SyncRef0;
2471 break;
2472 case 4: /* AES 4 */
2473 hdspm->control_register |= HDSPM_SyncRef2;
2474 break;
2475 case 5: /* AES 5 */
2476 hdspm->control_register |=
2477 HDSPM_SyncRef2+HDSPM_SyncRef0;
2478 break;
2479 case 6: /* AES 6 */
2480 hdspm->control_register |=
2481 HDSPM_SyncRef2+HDSPM_SyncRef1;
2482 break;
2483 case 7: /* AES 7 */
2484 hdspm->control_register |=
2485 HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
2486 break;
2487 case 8: /* AES 8 */
2488 hdspm->control_register |= HDSPM_SyncRef3;
2489 break;
2490 case 9: /* TCO */
2491 hdspm->control_register |=
2492 HDSPM_SyncRef3+HDSPM_SyncRef0;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002493 break;
2494 default:
2495 return -1;
2496 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002497
2498 break;
2499
2500 case MADI:
2501 case MADIface:
2502 hdspm->control_register &= ~HDSPM_SyncRefMask;
2503 if (hdspm->tco) {
2504 switch (pref) {
2505 case 0: /* WC */
2506 break;
2507 case 1: /* MADI */
2508 hdspm->control_register |= HDSPM_SyncRef0;
2509 break;
2510 case 2: /* TCO */
2511 hdspm->control_register |= HDSPM_SyncRef1;
2512 break;
2513 case 3: /* SYNC_IN */
2514 hdspm->control_register |=
2515 HDSPM_SyncRef0+HDSPM_SyncRef1;
2516 break;
2517 default:
2518 return -1;
2519 }
2520 } else {
2521 switch (pref) {
2522 case 0: /* WC */
2523 break;
2524 case 1: /* MADI */
2525 hdspm->control_register |= HDSPM_SyncRef0;
2526 break;
2527 case 2: /* SYNC_IN */
2528 hdspm->control_register |=
2529 HDSPM_SyncRef0+HDSPM_SyncRef1;
2530 break;
2531 default:
2532 return -1;
2533 }
2534 }
2535
2536 break;
2537
2538 case RayDAT:
2539 if (hdspm->tco) {
2540 switch (pref) {
2541 case 0: p = 0; break; /* WC */
2542 case 1: p = 3; break; /* ADAT 1 */
2543 case 2: p = 4; break; /* ADAT 2 */
2544 case 3: p = 5; break; /* ADAT 3 */
2545 case 4: p = 6; break; /* ADAT 4 */
2546 case 5: p = 1; break; /* AES */
2547 case 6: p = 2; break; /* SPDIF */
2548 case 7: p = 9; break; /* TCO */
2549 case 8: p = 10; break; /* SYNC_IN */
2550 default: return -1;
2551 }
2552 } else {
2553 switch (pref) {
2554 case 0: p = 0; break; /* WC */
2555 case 1: p = 3; break; /* ADAT 1 */
2556 case 2: p = 4; break; /* ADAT 2 */
2557 case 3: p = 5; break; /* ADAT 3 */
2558 case 4: p = 6; break; /* ADAT 4 */
2559 case 5: p = 1; break; /* AES */
2560 case 6: p = 2; break; /* SPDIF */
2561 case 7: p = 10; break; /* SYNC_IN */
2562 default: return -1;
2563 }
2564 }
2565 break;
2566
2567 case AIO:
2568 if (hdspm->tco) {
2569 switch (pref) {
2570 case 0: p = 0; break; /* WC */
2571 case 1: p = 3; break; /* ADAT */
2572 case 2: p = 1; break; /* AES */
2573 case 3: p = 2; break; /* SPDIF */
2574 case 4: p = 9; break; /* TCO */
2575 case 5: p = 10; break; /* SYNC_IN */
2576 default: return -1;
2577 }
2578 } else {
2579 switch (pref) {
2580 case 0: p = 0; break; /* WC */
2581 case 1: p = 3; break; /* ADAT */
2582 case 2: p = 1; break; /* AES */
2583 case 3: p = 2; break; /* SPDIF */
2584 case 4: p = 10; break; /* SYNC_IN */
2585 default: return -1;
2586 }
2587 }
2588 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02002589 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002590
2591 switch (hdspm->io_type) {
2592 case RayDAT:
2593 case AIO:
2594 hdspm->settings_register &= ~HDSPM_c0_SyncRefMask;
2595 hdspm->settings_register |= HDSPM_c0_SyncRef0 * p;
2596 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
2597 break;
2598
2599 case MADI:
2600 case MADIface:
2601 case AES32:
2602 hdspm_write(hdspm, HDSPM_controlRegister,
2603 hdspm->control_register);
2604 }
2605
Takashi Iwai763f3562005-06-03 11:25:34 +02002606 return 0;
2607}
2608
Adrian Knoth0dca1792011-01-26 19:32:14 +01002609
Takashi Iwai98274f02005-11-17 14:52:34 +01002610static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
2611 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002612{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002613 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002614
Adrian Knoth0dca1792011-01-26 19:32:14 +01002615 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2616 uinfo->count = 1;
2617 uinfo->value.enumerated.items = hdspm->texts_autosync_items;
Takashi Iwai763f3562005-06-03 11:25:34 +02002618
Adrian Knoth0dca1792011-01-26 19:32:14 +01002619 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2620 uinfo->value.enumerated.item =
2621 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002622
Adrian Knoth0dca1792011-01-26 19:32:14 +01002623 strcpy(uinfo->value.enumerated.name,
2624 hdspm->texts_autosync[uinfo->value.enumerated.item]);
Remy Bruno3cee5a62006-10-16 12:46:32 +02002625
Takashi Iwai763f3562005-06-03 11:25:34 +02002626 return 0;
2627}
2628
Takashi Iwai98274f02005-11-17 14:52:34 +01002629static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
2630 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002631{
Takashi Iwai98274f02005-11-17 14:52:34 +01002632 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002633 int psf = hdspm_pref_sync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002634
Adrian Knoth0dca1792011-01-26 19:32:14 +01002635 if (psf >= 0) {
2636 ucontrol->value.enumerated.item[0] = psf;
2637 return 0;
2638 }
2639
2640 return -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002641}
2642
Takashi Iwai98274f02005-11-17 14:52:34 +01002643static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
2644 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002645{
Takashi Iwai98274f02005-11-17 14:52:34 +01002646 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002647 int val, change = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002648
2649 if (!snd_hdspm_use_is_exclusive(hdspm))
2650 return -EBUSY;
2651
Adrian Knoth0dca1792011-01-26 19:32:14 +01002652 val = ucontrol->value.enumerated.item[0];
2653
2654 if (val < 0)
2655 val = 0;
2656 else if (val >= hdspm->texts_autosync_items)
2657 val = hdspm->texts_autosync_items-1;
Takashi Iwai763f3562005-06-03 11:25:34 +02002658
2659 spin_lock_irq(&hdspm->lock);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002660 if (val != hdspm_pref_sync_ref(hdspm))
2661 change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0;
2662
Takashi Iwai763f3562005-06-03 11:25:34 +02002663 spin_unlock_irq(&hdspm->lock);
2664 return change;
2665}
2666
Adrian Knoth0dca1792011-01-26 19:32:14 +01002667
Takashi Iwai763f3562005-06-03 11:25:34 +02002668#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002669{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002670 .name = xname, \
2671 .index = xindex, \
2672 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
2673 .info = snd_hdspm_info_autosync_ref, \
2674 .get = snd_hdspm_get_autosync_ref, \
2675}
2676
Adrian Knoth0dca1792011-01-26 19:32:14 +01002677static int hdspm_autosync_ref(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002678{
Adrian Knoth0dca1792011-01-26 19:32:14 +01002679 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002680 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002681 unsigned int syncref =
2682 (status >> HDSPM_AES32_syncref_bit) & 0xF;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002683 if (syncref == 0)
2684 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
2685 if (syncref <= 8)
2686 return syncref;
2687 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002688 } else if (MADI == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002689 /* This looks at the autosync selected sync reference */
2690 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Takashi Iwai763f3562005-06-03 11:25:34 +02002691
Remy Bruno3cee5a62006-10-16 12:46:32 +02002692 switch (status2 & HDSPM_SelSyncRefMask) {
2693 case HDSPM_SelSyncRef_WORD:
2694 return HDSPM_AUTOSYNC_FROM_WORD;
2695 case HDSPM_SelSyncRef_MADI:
2696 return HDSPM_AUTOSYNC_FROM_MADI;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002697 case HDSPM_SelSyncRef_TCO:
2698 return HDSPM_AUTOSYNC_FROM_TCO;
2699 case HDSPM_SelSyncRef_SyncIn:
2700 return HDSPM_AUTOSYNC_FROM_SYNC_IN;
Remy Bruno3cee5a62006-10-16 12:46:32 +02002701 case HDSPM_SelSyncRef_NVALID:
2702 return HDSPM_AUTOSYNC_FROM_NONE;
2703 default:
2704 return 0;
2705 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002706
Takashi Iwai763f3562005-06-03 11:25:34 +02002707 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01002708 return 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02002709}
2710
Adrian Knoth0dca1792011-01-26 19:32:14 +01002711
Takashi Iwai98274f02005-11-17 14:52:34 +01002712static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
2713 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002714{
Remy Bruno3cee5a62006-10-16 12:46:32 +02002715 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002716
Adrian Knoth0dca1792011-01-26 19:32:14 +01002717 if (AES32 == hdspm->io_type) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02002718 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
2719 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
2720
2721 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2722 uinfo->count = 1;
2723 uinfo->value.enumerated.items = 10;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002724 if (uinfo->value.enumerated.item >=
2725 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002726 uinfo->value.enumerated.item =
2727 uinfo->value.enumerated.items - 1;
2728 strcpy(uinfo->value.enumerated.name,
2729 texts[uinfo->value.enumerated.item]);
Adrian Knoth0dca1792011-01-26 19:32:14 +01002730 } else if (MADI == hdspm->io_type) {
2731 static char *texts[] = {"Word Clock", "MADI", "TCO",
2732 "Sync In", "None" };
Remy Bruno3cee5a62006-10-16 12:46:32 +02002733
2734 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2735 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01002736 uinfo->value.enumerated.items = 5;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02002737 if (uinfo->value.enumerated.item >=
Adrian Knoth0dca1792011-01-26 19:32:14 +01002738 uinfo->value.enumerated.items)
Remy Bruno3cee5a62006-10-16 12:46:32 +02002739 uinfo->value.enumerated.item =
2740 uinfo->value.enumerated.items - 1;
2741 strcpy(uinfo->value.enumerated.name,
2742 texts[uinfo->value.enumerated.item]);
2743 }
Takashi Iwai763f3562005-06-03 11:25:34 +02002744 return 0;
2745}
2746
Takashi Iwai98274f02005-11-17 14:52:34 +01002747static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
2748 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002749{
Takashi Iwai98274f02005-11-17 14:52:34 +01002750 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002751
Remy Bruno65345992007-08-31 12:21:08 +02002752 ucontrol->value.enumerated.item[0] = hdspm_autosync_ref(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02002753 return 0;
2754}
2755
Adrian Knoth0dca1792011-01-26 19:32:14 +01002756
Takashi Iwai763f3562005-06-03 11:25:34 +02002757#define HDSPM_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002758{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002759 .name = xname, \
2760 .index = xindex, \
2761 .info = snd_hdspm_info_line_out, \
2762 .get = snd_hdspm_get_line_out, \
2763 .put = snd_hdspm_put_line_out \
2764}
2765
Takashi Iwai98274f02005-11-17 14:52:34 +01002766static int hdspm_line_out(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002767{
2768 return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
2769}
2770
2771
Takashi Iwai98274f02005-11-17 14:52:34 +01002772static int hdspm_set_line_output(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002773{
2774 if (out)
2775 hdspm->control_register |= HDSPM_LineOut;
2776 else
2777 hdspm->control_register &= ~HDSPM_LineOut;
2778 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2779
2780 return 0;
2781}
2782
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002783#define snd_hdspm_info_line_out snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002784
Takashi Iwai98274f02005-11-17 14:52:34 +01002785static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
2786 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002787{
Takashi Iwai98274f02005-11-17 14:52:34 +01002788 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002789
2790 spin_lock_irq(&hdspm->lock);
2791 ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
2792 spin_unlock_irq(&hdspm->lock);
2793 return 0;
2794}
2795
Takashi Iwai98274f02005-11-17 14:52:34 +01002796static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
2797 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002798{
Takashi Iwai98274f02005-11-17 14:52:34 +01002799 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002800 int change;
2801 unsigned int val;
2802
2803 if (!snd_hdspm_use_is_exclusive(hdspm))
2804 return -EBUSY;
2805 val = ucontrol->value.integer.value[0] & 1;
2806 spin_lock_irq(&hdspm->lock);
2807 change = (int) val != hdspm_line_out(hdspm);
2808 hdspm_set_line_output(hdspm, val);
2809 spin_unlock_irq(&hdspm->lock);
2810 return change;
2811}
2812
Adrian Knoth0dca1792011-01-26 19:32:14 +01002813
Takashi Iwai763f3562005-06-03 11:25:34 +02002814#define HDSPM_TX_64(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002815{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002816 .name = xname, \
2817 .index = xindex, \
2818 .info = snd_hdspm_info_tx_64, \
2819 .get = snd_hdspm_get_tx_64, \
2820 .put = snd_hdspm_put_tx_64 \
2821}
2822
Takashi Iwai98274f02005-11-17 14:52:34 +01002823static int hdspm_tx_64(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002824{
2825 return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
2826}
2827
Takashi Iwai98274f02005-11-17 14:52:34 +01002828static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002829{
2830 if (out)
2831 hdspm->control_register |= HDSPM_TX_64ch;
2832 else
2833 hdspm->control_register &= ~HDSPM_TX_64ch;
2834 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2835
2836 return 0;
2837}
2838
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002839#define snd_hdspm_info_tx_64 snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002840
Takashi Iwai98274f02005-11-17 14:52:34 +01002841static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
2842 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002843{
Takashi Iwai98274f02005-11-17 14:52:34 +01002844 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002845
2846 spin_lock_irq(&hdspm->lock);
2847 ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
2848 spin_unlock_irq(&hdspm->lock);
2849 return 0;
2850}
2851
Takashi Iwai98274f02005-11-17 14:52:34 +01002852static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
2853 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002854{
Takashi Iwai98274f02005-11-17 14:52:34 +01002855 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002856 int change;
2857 unsigned int val;
2858
2859 if (!snd_hdspm_use_is_exclusive(hdspm))
2860 return -EBUSY;
2861 val = ucontrol->value.integer.value[0] & 1;
2862 spin_lock_irq(&hdspm->lock);
2863 change = (int) val != hdspm_tx_64(hdspm);
2864 hdspm_set_tx_64(hdspm, val);
2865 spin_unlock_irq(&hdspm->lock);
2866 return change;
2867}
2868
Adrian Knoth0dca1792011-01-26 19:32:14 +01002869
Takashi Iwai763f3562005-06-03 11:25:34 +02002870#define HDSPM_C_TMS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002871{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002872 .name = xname, \
2873 .index = xindex, \
2874 .info = snd_hdspm_info_c_tms, \
2875 .get = snd_hdspm_get_c_tms, \
2876 .put = snd_hdspm_put_c_tms \
2877}
2878
Takashi Iwai98274f02005-11-17 14:52:34 +01002879static int hdspm_c_tms(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002880{
2881 return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
2882}
2883
Takashi Iwai98274f02005-11-17 14:52:34 +01002884static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002885{
2886 if (out)
2887 hdspm->control_register |= HDSPM_clr_tms;
2888 else
2889 hdspm->control_register &= ~HDSPM_clr_tms;
2890 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2891
2892 return 0;
2893}
2894
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002895#define snd_hdspm_info_c_tms snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002896
Takashi Iwai98274f02005-11-17 14:52:34 +01002897static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
2898 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002899{
Takashi Iwai98274f02005-11-17 14:52:34 +01002900 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002901
2902 spin_lock_irq(&hdspm->lock);
2903 ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
2904 spin_unlock_irq(&hdspm->lock);
2905 return 0;
2906}
2907
Takashi Iwai98274f02005-11-17 14:52:34 +01002908static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
2909 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002910{
Takashi Iwai98274f02005-11-17 14:52:34 +01002911 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002912 int change;
2913 unsigned int val;
2914
2915 if (!snd_hdspm_use_is_exclusive(hdspm))
2916 return -EBUSY;
2917 val = ucontrol->value.integer.value[0] & 1;
2918 spin_lock_irq(&hdspm->lock);
2919 change = (int) val != hdspm_c_tms(hdspm);
2920 hdspm_set_c_tms(hdspm, val);
2921 spin_unlock_irq(&hdspm->lock);
2922 return change;
2923}
2924
Adrian Knoth0dca1792011-01-26 19:32:14 +01002925
Takashi Iwai763f3562005-06-03 11:25:34 +02002926#define HDSPM_SAFE_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002927{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002928 .name = xname, \
2929 .index = xindex, \
2930 .info = snd_hdspm_info_safe_mode, \
2931 .get = snd_hdspm_get_safe_mode, \
2932 .put = snd_hdspm_put_safe_mode \
2933}
2934
Takashi Iwai98274f02005-11-17 14:52:34 +01002935static int hdspm_safe_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002936{
2937 return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
2938}
2939
Takashi Iwai98274f02005-11-17 14:52:34 +01002940static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02002941{
2942 if (out)
2943 hdspm->control_register |= HDSPM_AutoInp;
2944 else
2945 hdspm->control_register &= ~HDSPM_AutoInp;
2946 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2947
2948 return 0;
2949}
2950
Takashi Iwaia5ce8892007-07-23 15:42:26 +02002951#define snd_hdspm_info_safe_mode snd_ctl_boolean_mono_info
Takashi Iwai763f3562005-06-03 11:25:34 +02002952
Takashi Iwai98274f02005-11-17 14:52:34 +01002953static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
2954 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002955{
Takashi Iwai98274f02005-11-17 14:52:34 +01002956 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002957
2958 spin_lock_irq(&hdspm->lock);
2959 ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
2960 spin_unlock_irq(&hdspm->lock);
2961 return 0;
2962}
2963
Takashi Iwai98274f02005-11-17 14:52:34 +01002964static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
2965 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002966{
Takashi Iwai98274f02005-11-17 14:52:34 +01002967 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002968 int change;
2969 unsigned int val;
2970
2971 if (!snd_hdspm_use_is_exclusive(hdspm))
2972 return -EBUSY;
2973 val = ucontrol->value.integer.value[0] & 1;
2974 spin_lock_irq(&hdspm->lock);
2975 change = (int) val != hdspm_safe_mode(hdspm);
2976 hdspm_set_safe_mode(hdspm, val);
2977 spin_unlock_irq(&hdspm->lock);
2978 return change;
2979}
2980
Adrian Knoth0dca1792011-01-26 19:32:14 +01002981
Remy Bruno3cee5a62006-10-16 12:46:32 +02002982#define HDSPM_EMPHASIS(xname, xindex) \
2983{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2984 .name = xname, \
2985 .index = xindex, \
2986 .info = snd_hdspm_info_emphasis, \
2987 .get = snd_hdspm_get_emphasis, \
2988 .put = snd_hdspm_put_emphasis \
2989}
2990
2991static int hdspm_emphasis(struct hdspm * hdspm)
2992{
2993 return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0;
2994}
2995
2996static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
2997{
2998 if (emp)
2999 hdspm->control_register |= HDSPM_Emphasis;
3000 else
3001 hdspm->control_register &= ~HDSPM_Emphasis;
3002 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3003
3004 return 0;
3005}
3006
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003007#define snd_hdspm_info_emphasis snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003008
3009static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
3010 struct snd_ctl_elem_value *ucontrol)
3011{
3012 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3013
3014 spin_lock_irq(&hdspm->lock);
3015 ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm);
3016 spin_unlock_irq(&hdspm->lock);
3017 return 0;
3018}
3019
3020static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
3021 struct snd_ctl_elem_value *ucontrol)
3022{
3023 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3024 int change;
3025 unsigned int val;
3026
3027 if (!snd_hdspm_use_is_exclusive(hdspm))
3028 return -EBUSY;
3029 val = ucontrol->value.integer.value[0] & 1;
3030 spin_lock_irq(&hdspm->lock);
3031 change = (int) val != hdspm_emphasis(hdspm);
3032 hdspm_set_emphasis(hdspm, val);
3033 spin_unlock_irq(&hdspm->lock);
3034 return change;
3035}
3036
Adrian Knoth0dca1792011-01-26 19:32:14 +01003037
Remy Bruno3cee5a62006-10-16 12:46:32 +02003038#define HDSPM_DOLBY(xname, xindex) \
3039{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3040 .name = xname, \
3041 .index = xindex, \
3042 .info = snd_hdspm_info_dolby, \
3043 .get = snd_hdspm_get_dolby, \
3044 .put = snd_hdspm_put_dolby \
3045}
3046
3047static int hdspm_dolby(struct hdspm * hdspm)
3048{
3049 return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0;
3050}
3051
3052static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
3053{
3054 if (dol)
3055 hdspm->control_register |= HDSPM_Dolby;
3056 else
3057 hdspm->control_register &= ~HDSPM_Dolby;
3058 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3059
3060 return 0;
3061}
3062
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003063#define snd_hdspm_info_dolby snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003064
3065static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
3066 struct snd_ctl_elem_value *ucontrol)
3067{
3068 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3069
3070 spin_lock_irq(&hdspm->lock);
3071 ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm);
3072 spin_unlock_irq(&hdspm->lock);
3073 return 0;
3074}
3075
3076static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
3077 struct snd_ctl_elem_value *ucontrol)
3078{
3079 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3080 int change;
3081 unsigned int val;
3082
3083 if (!snd_hdspm_use_is_exclusive(hdspm))
3084 return -EBUSY;
3085 val = ucontrol->value.integer.value[0] & 1;
3086 spin_lock_irq(&hdspm->lock);
3087 change = (int) val != hdspm_dolby(hdspm);
3088 hdspm_set_dolby(hdspm, val);
3089 spin_unlock_irq(&hdspm->lock);
3090 return change;
3091}
3092
Adrian Knoth0dca1792011-01-26 19:32:14 +01003093
Remy Bruno3cee5a62006-10-16 12:46:32 +02003094#define HDSPM_PROFESSIONAL(xname, xindex) \
3095{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3096 .name = xname, \
3097 .index = xindex, \
3098 .info = snd_hdspm_info_professional, \
3099 .get = snd_hdspm_get_professional, \
3100 .put = snd_hdspm_put_professional \
3101}
3102
3103static int hdspm_professional(struct hdspm * hdspm)
3104{
3105 return (hdspm->control_register & HDSPM_Professional) ? 1 : 0;
3106}
3107
3108static int hdspm_set_professional(struct hdspm * hdspm, int dol)
3109{
3110 if (dol)
3111 hdspm->control_register |= HDSPM_Professional;
3112 else
3113 hdspm->control_register &= ~HDSPM_Professional;
3114 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3115
3116 return 0;
3117}
3118
Takashi Iwaia5ce8892007-07-23 15:42:26 +02003119#define snd_hdspm_info_professional snd_ctl_boolean_mono_info
Remy Bruno3cee5a62006-10-16 12:46:32 +02003120
3121static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
3122 struct snd_ctl_elem_value *ucontrol)
3123{
3124 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3125
3126 spin_lock_irq(&hdspm->lock);
3127 ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm);
3128 spin_unlock_irq(&hdspm->lock);
3129 return 0;
3130}
3131
3132static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
3133 struct snd_ctl_elem_value *ucontrol)
3134{
3135 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3136 int change;
3137 unsigned int val;
3138
3139 if (!snd_hdspm_use_is_exclusive(hdspm))
3140 return -EBUSY;
3141 val = ucontrol->value.integer.value[0] & 1;
3142 spin_lock_irq(&hdspm->lock);
3143 change = (int) val != hdspm_professional(hdspm);
3144 hdspm_set_professional(hdspm, val);
3145 spin_unlock_irq(&hdspm->lock);
3146 return change;
3147}
3148
Takashi Iwai763f3562005-06-03 11:25:34 +02003149#define HDSPM_INPUT_SELECT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003150{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003151 .name = xname, \
3152 .index = xindex, \
3153 .info = snd_hdspm_info_input_select, \
3154 .get = snd_hdspm_get_input_select, \
3155 .put = snd_hdspm_put_input_select \
3156}
3157
Takashi Iwai98274f02005-11-17 14:52:34 +01003158static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003159{
3160 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
3161}
3162
Takashi Iwai98274f02005-11-17 14:52:34 +01003163static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02003164{
3165 if (out)
3166 hdspm->control_register |= HDSPM_InputSelect0;
3167 else
3168 hdspm->control_register &= ~HDSPM_InputSelect0;
3169 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3170
3171 return 0;
3172}
3173
Takashi Iwai98274f02005-11-17 14:52:34 +01003174static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
3175 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003176{
3177 static char *texts[] = { "optical", "coaxial" };
3178
3179 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3180 uinfo->count = 1;
3181 uinfo->value.enumerated.items = 2;
3182
3183 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3184 uinfo->value.enumerated.item =
3185 uinfo->value.enumerated.items - 1;
3186 strcpy(uinfo->value.enumerated.name,
3187 texts[uinfo->value.enumerated.item]);
3188
3189 return 0;
3190}
3191
Takashi Iwai98274f02005-11-17 14:52:34 +01003192static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
3193 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003194{
Takashi Iwai98274f02005-11-17 14:52:34 +01003195 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003196
3197 spin_lock_irq(&hdspm->lock);
3198 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
3199 spin_unlock_irq(&hdspm->lock);
3200 return 0;
3201}
3202
Takashi Iwai98274f02005-11-17 14:52:34 +01003203static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
3204 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003205{
Takashi Iwai98274f02005-11-17 14:52:34 +01003206 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003207 int change;
3208 unsigned int val;
3209
3210 if (!snd_hdspm_use_is_exclusive(hdspm))
3211 return -EBUSY;
3212 val = ucontrol->value.integer.value[0] & 1;
3213 spin_lock_irq(&hdspm->lock);
3214 change = (int) val != hdspm_input_select(hdspm);
3215 hdspm_set_input_select(hdspm, val);
3216 spin_unlock_irq(&hdspm->lock);
3217 return change;
3218}
3219
Adrian Knoth0dca1792011-01-26 19:32:14 +01003220
Remy Bruno3cee5a62006-10-16 12:46:32 +02003221#define HDSPM_DS_WIRE(xname, xindex) \
3222{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3223 .name = xname, \
3224 .index = xindex, \
3225 .info = snd_hdspm_info_ds_wire, \
3226 .get = snd_hdspm_get_ds_wire, \
3227 .put = snd_hdspm_put_ds_wire \
3228}
3229
3230static int hdspm_ds_wire(struct hdspm * hdspm)
3231{
3232 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
3233}
3234
3235static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
3236{
3237 if (ds)
3238 hdspm->control_register |= HDSPM_DS_DoubleWire;
3239 else
3240 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
3241 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3242
3243 return 0;
3244}
3245
3246static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
3247 struct snd_ctl_elem_info *uinfo)
3248{
3249 static char *texts[] = { "Single", "Double" };
3250
3251 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3252 uinfo->count = 1;
3253 uinfo->value.enumerated.items = 2;
3254
3255 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3256 uinfo->value.enumerated.item =
3257 uinfo->value.enumerated.items - 1;
3258 strcpy(uinfo->value.enumerated.name,
3259 texts[uinfo->value.enumerated.item]);
3260
3261 return 0;
3262}
3263
3264static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
3265 struct snd_ctl_elem_value *ucontrol)
3266{
3267 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3268
3269 spin_lock_irq(&hdspm->lock);
3270 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
3271 spin_unlock_irq(&hdspm->lock);
3272 return 0;
3273}
3274
3275static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
3276 struct snd_ctl_elem_value *ucontrol)
3277{
3278 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3279 int change;
3280 unsigned int val;
3281
3282 if (!snd_hdspm_use_is_exclusive(hdspm))
3283 return -EBUSY;
3284 val = ucontrol->value.integer.value[0] & 1;
3285 spin_lock_irq(&hdspm->lock);
3286 change = (int) val != hdspm_ds_wire(hdspm);
3287 hdspm_set_ds_wire(hdspm, val);
3288 spin_unlock_irq(&hdspm->lock);
3289 return change;
3290}
3291
Adrian Knoth0dca1792011-01-26 19:32:14 +01003292
Remy Bruno3cee5a62006-10-16 12:46:32 +02003293#define HDSPM_QS_WIRE(xname, xindex) \
3294{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3295 .name = xname, \
3296 .index = xindex, \
3297 .info = snd_hdspm_info_qs_wire, \
3298 .get = snd_hdspm_get_qs_wire, \
3299 .put = snd_hdspm_put_qs_wire \
3300}
3301
3302static int hdspm_qs_wire(struct hdspm * hdspm)
3303{
3304 if (hdspm->control_register & HDSPM_QS_DoubleWire)
3305 return 1;
3306 if (hdspm->control_register & HDSPM_QS_QuadWire)
3307 return 2;
3308 return 0;
3309}
3310
3311static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
3312{
3313 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
3314 switch (mode) {
3315 case 0:
3316 break;
3317 case 1:
3318 hdspm->control_register |= HDSPM_QS_DoubleWire;
3319 break;
3320 case 2:
3321 hdspm->control_register |= HDSPM_QS_QuadWire;
3322 break;
3323 }
3324 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
3325
3326 return 0;
3327}
3328
3329static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
3330 struct snd_ctl_elem_info *uinfo)
3331{
3332 static char *texts[] = { "Single", "Double", "Quad" };
3333
3334 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3335 uinfo->count = 1;
3336 uinfo->value.enumerated.items = 3;
3337
3338 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3339 uinfo->value.enumerated.item =
3340 uinfo->value.enumerated.items - 1;
3341 strcpy(uinfo->value.enumerated.name,
3342 texts[uinfo->value.enumerated.item]);
3343
3344 return 0;
3345}
3346
3347static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
3348 struct snd_ctl_elem_value *ucontrol)
3349{
3350 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3351
3352 spin_lock_irq(&hdspm->lock);
3353 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
3354 spin_unlock_irq(&hdspm->lock);
3355 return 0;
3356}
3357
3358static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
3359 struct snd_ctl_elem_value *ucontrol)
3360{
3361 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3362 int change;
3363 int val;
3364
3365 if (!snd_hdspm_use_is_exclusive(hdspm))
3366 return -EBUSY;
3367 val = ucontrol->value.integer.value[0];
3368 if (val < 0)
3369 val = 0;
3370 if (val > 2)
3371 val = 2;
3372 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003373 change = val != hdspm_qs_wire(hdspm);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003374 hdspm_set_qs_wire(hdspm, val);
3375 spin_unlock_irq(&hdspm->lock);
3376 return change;
3377}
3378
Takashi Iwai763f3562005-06-03 11:25:34 +02003379
3380#define HDSPM_MIXER(xname, xindex) \
3381{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
3382 .name = xname, \
3383 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02003384 .device = 0, \
Takashi Iwai763f3562005-06-03 11:25:34 +02003385 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3386 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3387 .info = snd_hdspm_info_mixer, \
3388 .get = snd_hdspm_get_mixer, \
3389 .put = snd_hdspm_put_mixer \
3390}
3391
Takashi Iwai98274f02005-11-17 14:52:34 +01003392static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
3393 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003394{
3395 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3396 uinfo->count = 3;
3397 uinfo->value.integer.min = 0;
3398 uinfo->value.integer.max = 65535;
3399 uinfo->value.integer.step = 1;
3400 return 0;
3401}
3402
Takashi Iwai98274f02005-11-17 14:52:34 +01003403static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
3404 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003405{
Takashi Iwai98274f02005-11-17 14:52:34 +01003406 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003407 int source;
3408 int destination;
3409
3410 source = ucontrol->value.integer.value[0];
3411 if (source < 0)
3412 source = 0;
3413 else if (source >= 2 * HDSPM_MAX_CHANNELS)
3414 source = 2 * HDSPM_MAX_CHANNELS - 1;
3415
3416 destination = ucontrol->value.integer.value[1];
3417 if (destination < 0)
3418 destination = 0;
3419 else if (destination >= HDSPM_MAX_CHANNELS)
3420 destination = HDSPM_MAX_CHANNELS - 1;
3421
3422 spin_lock_irq(&hdspm->lock);
3423 if (source >= HDSPM_MAX_CHANNELS)
3424 ucontrol->value.integer.value[2] =
3425 hdspm_read_pb_gain(hdspm, destination,
3426 source - HDSPM_MAX_CHANNELS);
3427 else
3428 ucontrol->value.integer.value[2] =
3429 hdspm_read_in_gain(hdspm, destination, source);
3430
3431 spin_unlock_irq(&hdspm->lock);
3432
3433 return 0;
3434}
3435
Takashi Iwai98274f02005-11-17 14:52:34 +01003436static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
3437 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003438{
Takashi Iwai98274f02005-11-17 14:52:34 +01003439 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003440 int change;
3441 int source;
3442 int destination;
3443 int gain;
3444
3445 if (!snd_hdspm_use_is_exclusive(hdspm))
3446 return -EBUSY;
3447
3448 source = ucontrol->value.integer.value[0];
3449 destination = ucontrol->value.integer.value[1];
3450
3451 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
3452 return -1;
3453 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
3454 return -1;
3455
3456 gain = ucontrol->value.integer.value[2];
3457
3458 spin_lock_irq(&hdspm->lock);
3459
3460 if (source >= HDSPM_MAX_CHANNELS)
3461 change = gain != hdspm_read_pb_gain(hdspm, destination,
3462 source -
3463 HDSPM_MAX_CHANNELS);
3464 else
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02003465 change = gain != hdspm_read_in_gain(hdspm, destination,
3466 source);
Takashi Iwai763f3562005-06-03 11:25:34 +02003467
3468 if (change) {
3469 if (source >= HDSPM_MAX_CHANNELS)
3470 hdspm_write_pb_gain(hdspm, destination,
3471 source - HDSPM_MAX_CHANNELS,
3472 gain);
3473 else
3474 hdspm_write_in_gain(hdspm, destination, source,
3475 gain);
3476 }
3477 spin_unlock_irq(&hdspm->lock);
3478
3479 return change;
3480}
3481
3482/* The simple mixer control(s) provide gain control for the
3483 basic 1:1 mappings of playback streams to output
Adrian Knoth0dca1792011-01-26 19:32:14 +01003484 streams.
Takashi Iwai763f3562005-06-03 11:25:34 +02003485*/
3486
3487#define HDSPM_PLAYBACK_MIXER \
3488{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3489 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
3490 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3491 .info = snd_hdspm_info_playback_mixer, \
3492 .get = snd_hdspm_get_playback_mixer, \
3493 .put = snd_hdspm_put_playback_mixer \
3494}
3495
Takashi Iwai98274f02005-11-17 14:52:34 +01003496static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
3497 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003498{
3499 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3500 uinfo->count = 1;
3501 uinfo->value.integer.min = 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003502 uinfo->value.integer.max = 64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003503 uinfo->value.integer.step = 1;
3504 return 0;
3505}
3506
Takashi Iwai98274f02005-11-17 14:52:34 +01003507static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
3508 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003509{
Takashi Iwai98274f02005-11-17 14:52:34 +01003510 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003511 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003512
3513 channel = ucontrol->id.index - 1;
3514
Takashi Iwaida3cec32008-08-08 17:12:14 +02003515 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3516 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003517
Takashi Iwai763f3562005-06-03 11:25:34 +02003518 spin_lock_irq(&hdspm->lock);
3519 ucontrol->value.integer.value[0] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003520 (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN;
Takashi Iwai763f3562005-06-03 11:25:34 +02003521 spin_unlock_irq(&hdspm->lock);
3522
Takashi Iwai763f3562005-06-03 11:25:34 +02003523 return 0;
3524}
3525
Takashi Iwai98274f02005-11-17 14:52:34 +01003526static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
3527 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003528{
Takashi Iwai98274f02005-11-17 14:52:34 +01003529 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003530 int change;
3531 int channel;
Takashi Iwai763f3562005-06-03 11:25:34 +02003532 int gain;
3533
3534 if (!snd_hdspm_use_is_exclusive(hdspm))
3535 return -EBUSY;
3536
3537 channel = ucontrol->id.index - 1;
3538
Takashi Iwaida3cec32008-08-08 17:12:14 +02003539 if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
3540 return -EINVAL;
Takashi Iwai763f3562005-06-03 11:25:34 +02003541
Adrian Knoth0dca1792011-01-26 19:32:14 +01003542 gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64;
Takashi Iwai763f3562005-06-03 11:25:34 +02003543
3544 spin_lock_irq(&hdspm->lock);
3545 change =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003546 gain != hdspm_read_pb_gain(hdspm, channel,
3547 channel);
Takashi Iwai763f3562005-06-03 11:25:34 +02003548 if (change)
Adrian Knoth0dca1792011-01-26 19:32:14 +01003549 hdspm_write_pb_gain(hdspm, channel, channel,
Takashi Iwai763f3562005-06-03 11:25:34 +02003550 gain);
3551 spin_unlock_irq(&hdspm->lock);
3552 return change;
3553}
3554
Adrian Knoth0dca1792011-01-26 19:32:14 +01003555#define HDSPM_SYNC_CHECK(xname, xindex) \
3556{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3557 .name = xname, \
3558 .private_value = xindex, \
3559 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3560 .info = snd_hdspm_info_sync_check, \
3561 .get = snd_hdspm_get_sync_check \
Takashi Iwai763f3562005-06-03 11:25:34 +02003562}
3563
Adrian Knoth0dca1792011-01-26 19:32:14 +01003564
Takashi Iwai98274f02005-11-17 14:52:34 +01003565static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
3566 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02003567{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003568 static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
Takashi Iwai763f3562005-06-03 11:25:34 +02003569 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3570 uinfo->count = 1;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003571 uinfo->value.enumerated.items = 4;
Takashi Iwai763f3562005-06-03 11:25:34 +02003572 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3573 uinfo->value.enumerated.item =
Adrian Knoth0dca1792011-01-26 19:32:14 +01003574 uinfo->value.enumerated.items - 1;
Takashi Iwai763f3562005-06-03 11:25:34 +02003575 strcpy(uinfo->value.enumerated.name,
Adrian Knoth0dca1792011-01-26 19:32:14 +01003576 texts[uinfo->value.enumerated.item]);
Takashi Iwai763f3562005-06-03 11:25:34 +02003577 return 0;
3578}
3579
Adrian Knoth0dca1792011-01-26 19:32:14 +01003580static int hdspm_wc_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003581{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003582 int status, status2;
3583
3584 switch (hdspm->io_type) {
3585 case AES32:
3586 status = hdspm_read(hdspm, HDSPM_statusRegister);
3587 if (status & HDSPM_wcSync)
Takashi Iwai763f3562005-06-03 11:25:34 +02003588 return 2;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003589 else if (status & HDSPM_wcLock)
3590 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003591 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003592 break;
3593
3594 case MADI:
3595 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02003596 if (status2 & HDSPM_wcLock) {
3597 if (status2 & HDSPM_wcSync)
3598 return 2;
3599 else
3600 return 1;
3601 }
3602 return 0;
Adrian Knoth0dca1792011-01-26 19:32:14 +01003603 break;
3604
3605 case RayDAT:
3606 case AIO:
3607 status = hdspm_read(hdspm, HDSPM_statusRegister);
3608
3609 if (status & 0x2000000)
3610 return 2;
3611 else if (status & 0x1000000)
3612 return 1;
3613 return 0;
3614
3615 break;
3616
3617 case MADIface:
3618 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02003619 }
Takashi Iwai763f3562005-06-03 11:25:34 +02003620
Takashi Iwai763f3562005-06-03 11:25:34 +02003621
Adrian Knoth0dca1792011-01-26 19:32:14 +01003622 return 3;
Takashi Iwai763f3562005-06-03 11:25:34 +02003623}
3624
3625
Adrian Knoth0dca1792011-01-26 19:32:14 +01003626static int hdspm_madi_sync_check(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003627{
3628 int status = hdspm_read(hdspm, HDSPM_statusRegister);
3629 if (status & HDSPM_madiLock) {
3630 if (status & HDSPM_madiSync)
3631 return 2;
3632 else
3633 return 1;
3634 }
3635 return 0;
3636}
3637
Adrian Knoth0dca1792011-01-26 19:32:14 +01003638
3639static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx)
3640{
3641 int status, lock, sync;
3642
3643 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3644
3645 lock = (status & (0x1<<idx)) ? 1 : 0;
3646 sync = (status & (0x100<<idx)) ? 1 : 0;
3647
3648 if (lock && sync)
3649 return 2;
3650 else if (lock)
3651 return 1;
3652 return 0;
3653}
3654
3655
3656static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
3657{
3658 int status, lock = 0, sync = 0;
3659
3660 switch (hdspm->io_type) {
3661 case RayDAT:
3662 case AIO:
3663 status = hdspm_read(hdspm, HDSPM_RD_STATUS_3);
3664 lock = (status & 0x400) ? 1 : 0;
3665 sync = (status & 0x800) ? 1 : 0;
3666 break;
3667
3668 case MADI:
3669 case AES32:
3670 status = hdspm_read(hdspm, HDSPM_statusRegister2);
3671 lock = (status & 0x400000) ? 1 : 0;
3672 sync = (status & 0x800000) ? 1 : 0;
3673 break;
3674
3675 case MADIface:
3676 break;
3677 }
3678
3679 if (lock && sync)
3680 return 2;
3681 else if (lock)
3682 return 1;
3683
3684 return 0;
3685}
3686
3687static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
3688{
3689 int status2, lock, sync;
3690 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3691
3692 lock = (status2 & (0x0080 >> idx)) ? 1 : 0;
3693 sync = (status2 & (0x8000 >> idx)) ? 1 : 0;
3694
3695 if (sync)
3696 return 2;
3697 else if (lock)
3698 return 1;
3699 return 0;
3700}
3701
3702
3703static int hdspm_tco_sync_check(struct hdspm *hdspm)
3704{
3705 int status;
3706
3707 if (hdspm->tco) {
3708 switch (hdspm->io_type) {
3709 case MADI:
3710 case AES32:
3711 status = hdspm_read(hdspm, HDSPM_statusRegister);
3712 if (status & HDSPM_tcoLock) {
3713 if (status & HDSPM_tcoSync)
3714 return 2;
3715 else
3716 return 1;
3717 }
3718 return 0;
3719
3720 break;
3721
3722 case RayDAT:
3723 case AIO:
3724 status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
3725
3726 if (status & 0x8000000)
3727 return 2; /* Sync */
3728 if (status & 0x4000000)
3729 return 1; /* Lock */
3730 return 0; /* No signal */
3731 break;
3732
3733 default:
3734 break;
3735 }
3736 }
3737
3738 return 3; /* N/A */
3739}
3740
3741
3742static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
3743 struct snd_ctl_elem_value *ucontrol)
3744{
3745 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3746 int val = -1;
3747
3748 switch (hdspm->io_type) {
3749 case RayDAT:
3750 switch (kcontrol->private_value) {
3751 case 0: /* WC */
3752 val = hdspm_wc_sync_check(hdspm); break;
3753 case 7: /* TCO */
3754 val = hdspm_tco_sync_check(hdspm); break;
3755 case 8: /* SYNC IN */
3756 val = hdspm_sync_in_sync_check(hdspm); break;
3757 default:
3758 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3759 }
3760
3761 case AIO:
3762 switch (kcontrol->private_value) {
3763 case 0: /* WC */
3764 val = hdspm_wc_sync_check(hdspm); break;
3765 case 4: /* TCO */
3766 val = hdspm_tco_sync_check(hdspm); break;
3767 case 5: /* SYNC IN */
3768 val = hdspm_sync_in_sync_check(hdspm); break;
3769 default:
3770 val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
3771 }
3772
3773 case MADI:
3774 switch (kcontrol->private_value) {
3775 case 0: /* WC */
3776 val = hdspm_wc_sync_check(hdspm); break;
3777 case 1: /* MADI */
3778 val = hdspm_madi_sync_check(hdspm); break;
3779 case 2: /* TCO */
3780 val = hdspm_tco_sync_check(hdspm); break;
3781 case 3: /* SYNC_IN */
3782 val = hdspm_sync_in_sync_check(hdspm); break;
3783 }
3784
3785 case MADIface:
3786 val = hdspm_madi_sync_check(hdspm); /* MADI */
3787 break;
3788
3789 case AES32:
3790 switch (kcontrol->private_value) {
3791 case 0: /* WC */
3792 val = hdspm_wc_sync_check(hdspm); break;
3793 case 9: /* TCO */
3794 val = hdspm_tco_sync_check(hdspm); break;
3795 case 10 /* SYNC IN */:
3796 val = hdspm_sync_in_sync_check(hdspm); break;
3797 default:
3798 val = hdspm_aes_sync_check(hdspm,
3799 ucontrol->id.index-1);
3800 }
3801
3802 }
3803
3804 if (-1 == val)
3805 val = 3;
3806
3807 ucontrol->value.enumerated.item[0] = val;
3808 return 0;
3809}
3810
3811
3812
3813/**
3814 * TCO controls
3815 **/
3816static void hdspm_tco_write(struct hdspm *hdspm)
3817{
3818 unsigned int tc[4] = { 0, 0, 0, 0};
3819
3820 switch (hdspm->tco->input) {
3821 case 0:
3822 tc[2] |= HDSPM_TCO2_set_input_MSB;
3823 break;
3824 case 1:
3825 tc[2] |= HDSPM_TCO2_set_input_LSB;
3826 break;
3827 default:
3828 break;
3829 }
3830
3831 switch (hdspm->tco->framerate) {
3832 case 1:
3833 tc[1] |= HDSPM_TCO1_LTC_Format_LSB;
3834 break;
3835 case 2:
3836 tc[1] |= HDSPM_TCO1_LTC_Format_MSB;
3837 break;
3838 case 3:
3839 tc[1] |= HDSPM_TCO1_LTC_Format_MSB +
3840 HDSPM_TCO1_set_drop_frame_flag;
3841 break;
3842 case 4:
3843 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
3844 HDSPM_TCO1_LTC_Format_MSB;
3845 break;
3846 case 5:
3847 tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
3848 HDSPM_TCO1_LTC_Format_MSB +
3849 HDSPM_TCO1_set_drop_frame_flag;
3850 break;
3851 default:
3852 break;
3853 }
3854
3855 switch (hdspm->tco->wordclock) {
3856 case 1:
3857 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB;
3858 break;
3859 case 2:
3860 tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB;
3861 break;
3862 default:
3863 break;
3864 }
3865
3866 switch (hdspm->tco->samplerate) {
3867 case 1:
3868 tc[2] |= HDSPM_TCO2_set_freq;
3869 break;
3870 case 2:
3871 tc[2] |= HDSPM_TCO2_set_freq_from_app;
3872 break;
3873 default:
3874 break;
3875 }
3876
3877 switch (hdspm->tco->pull) {
3878 case 1:
3879 tc[2] |= HDSPM_TCO2_set_pull_up;
3880 break;
3881 case 2:
3882 tc[2] |= HDSPM_TCO2_set_pull_down;
3883 break;
3884 case 3:
3885 tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4;
3886 break;
3887 case 4:
3888 tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4;
3889 break;
3890 default:
3891 break;
3892 }
3893
3894 if (1 == hdspm->tco->term) {
3895 tc[2] |= HDSPM_TCO2_set_term_75R;
3896 }
3897
3898 hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]);
3899 hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]);
3900 hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]);
3901 hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]);
3902}
3903
3904
3905#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \
3906{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3907 .name = xname, \
3908 .index = xindex, \
3909 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3910 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3911 .info = snd_hdspm_info_tco_sample_rate, \
3912 .get = snd_hdspm_get_tco_sample_rate, \
3913 .put = snd_hdspm_put_tco_sample_rate \
3914}
3915
3916static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol,
3917 struct snd_ctl_elem_info *uinfo)
3918{
3919 static char *texts[] = { "44.1 kHz", "48 kHz" };
3920 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3921 uinfo->count = 1;
3922 uinfo->value.enumerated.items = 2;
3923
3924 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3925 uinfo->value.enumerated.item =
3926 uinfo->value.enumerated.items - 1;
3927
3928 strcpy(uinfo->value.enumerated.name,
3929 texts[uinfo->value.enumerated.item]);
3930
3931 return 0;
3932}
3933
3934static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol,
3935 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02003936{
Takashi Iwai98274f02005-11-17 14:52:34 +01003937 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02003938
Adrian Knoth0dca1792011-01-26 19:32:14 +01003939 ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate;
3940
Takashi Iwai763f3562005-06-03 11:25:34 +02003941 return 0;
3942}
3943
Adrian Knoth0dca1792011-01-26 19:32:14 +01003944static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
3945 struct snd_ctl_elem_value *ucontrol)
Remy Bruno3cee5a62006-10-16 12:46:32 +02003946{
Adrian Knoth0dca1792011-01-26 19:32:14 +01003947 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3948
3949 if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) {
3950 hdspm->tco->samplerate = ucontrol->value.enumerated.item[0];
3951
3952 hdspm_tco_write(hdspm);
3953
3954 return 1;
Remy Bruno3cee5a62006-10-16 12:46:32 +02003955 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01003956
Remy Bruno3cee5a62006-10-16 12:46:32 +02003957 return 0;
3958}
3959
Adrian Knoth0dca1792011-01-26 19:32:14 +01003960
3961#define HDSPM_TCO_PULL(xname, xindex) \
3962{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3963 .name = xname, \
3964 .index = xindex, \
3965 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
3966 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
3967 .info = snd_hdspm_info_tco_pull, \
3968 .get = snd_hdspm_get_tco_pull, \
3969 .put = snd_hdspm_put_tco_pull \
3970}
3971
3972static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol,
3973 struct snd_ctl_elem_info *uinfo)
3974{
3975 static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" };
3976 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
3977 uinfo->count = 1;
3978 uinfo->value.enumerated.items = 5;
3979
3980 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
3981 uinfo->value.enumerated.item =
3982 uinfo->value.enumerated.items - 1;
3983
3984 strcpy(uinfo->value.enumerated.name,
3985 texts[uinfo->value.enumerated.item]);
3986
3987 return 0;
3988}
3989
3990static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol,
3991 struct snd_ctl_elem_value *ucontrol)
3992{
3993 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
3994
3995 ucontrol->value.enumerated.item[0] = hdspm->tco->pull;
3996
3997 return 0;
3998}
3999
4000static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol,
4001 struct snd_ctl_elem_value *ucontrol)
4002{
4003 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4004
4005 if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) {
4006 hdspm->tco->pull = ucontrol->value.enumerated.item[0];
4007
4008 hdspm_tco_write(hdspm);
4009
4010 return 1;
4011 }
4012
4013 return 0;
4014}
4015
4016#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \
4017{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4018 .name = xname, \
4019 .index = xindex, \
4020 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4021 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4022 .info = snd_hdspm_info_tco_wck_conversion, \
4023 .get = snd_hdspm_get_tco_wck_conversion, \
4024 .put = snd_hdspm_put_tco_wck_conversion \
4025}
4026
4027static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4028 struct snd_ctl_elem_info *uinfo)
4029{
4030 static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" };
4031 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4032 uinfo->count = 1;
4033 uinfo->value.enumerated.items = 3;
4034
4035 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4036 uinfo->value.enumerated.item =
4037 uinfo->value.enumerated.items - 1;
4038
4039 strcpy(uinfo->value.enumerated.name,
4040 texts[uinfo->value.enumerated.item]);
4041
4042 return 0;
4043}
4044
4045static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4046 struct snd_ctl_elem_value *ucontrol)
4047{
4048 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4049
4050 ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock;
4051
4052 return 0;
4053}
4054
4055static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol,
4056 struct snd_ctl_elem_value *ucontrol)
4057{
4058 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4059
4060 if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) {
4061 hdspm->tco->wordclock = ucontrol->value.enumerated.item[0];
4062
4063 hdspm_tco_write(hdspm);
4064
4065 return 1;
4066 }
4067
4068 return 0;
4069}
4070
4071
4072#define HDSPM_TCO_FRAME_RATE(xname, xindex) \
4073{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4074 .name = xname, \
4075 .index = xindex, \
4076 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4077 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4078 .info = snd_hdspm_info_tco_frame_rate, \
4079 .get = snd_hdspm_get_tco_frame_rate, \
4080 .put = snd_hdspm_put_tco_frame_rate \
4081}
4082
4083static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
4084 struct snd_ctl_elem_info *uinfo)
4085{
4086 static char *texts[] = { "24 fps", "25 fps", "29.97fps",
4087 "29.97 dfps", "30 fps", "30 dfps" };
4088 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4089 uinfo->count = 1;
4090 uinfo->value.enumerated.items = 6;
4091
4092 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4093 uinfo->value.enumerated.item =
4094 uinfo->value.enumerated.items - 1;
4095
4096 strcpy(uinfo->value.enumerated.name,
4097 texts[uinfo->value.enumerated.item]);
4098
4099 return 0;
4100}
4101
4102static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004103 struct snd_ctl_elem_value *ucontrol)
4104{
Remy Bruno3cee5a62006-10-16 12:46:32 +02004105 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4106
Adrian Knoth0dca1792011-01-26 19:32:14 +01004107 ucontrol->value.enumerated.item[0] = hdspm->tco->framerate;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004108
Remy Bruno3cee5a62006-10-16 12:46:32 +02004109 return 0;
4110}
Takashi Iwai763f3562005-06-03 11:25:34 +02004111
Adrian Knoth0dca1792011-01-26 19:32:14 +01004112static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
4113 struct snd_ctl_elem_value *ucontrol)
4114{
4115 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4116
4117 if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) {
4118 hdspm->tco->framerate = ucontrol->value.enumerated.item[0];
4119
4120 hdspm_tco_write(hdspm);
4121
4122 return 1;
4123 }
4124
4125 return 0;
4126}
4127
4128
4129#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \
4130{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4131 .name = xname, \
4132 .index = xindex, \
4133 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4134 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4135 .info = snd_hdspm_info_tco_sync_source, \
4136 .get = snd_hdspm_get_tco_sync_source, \
4137 .put = snd_hdspm_put_tco_sync_source \
4138}
4139
4140static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol,
4141 struct snd_ctl_elem_info *uinfo)
4142{
4143 static char *texts[] = { "LTC", "Video", "WCK" };
4144 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
4145 uinfo->count = 1;
4146 uinfo->value.enumerated.items = 3;
4147
4148 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
4149 uinfo->value.enumerated.item =
4150 uinfo->value.enumerated.items - 1;
4151
4152 strcpy(uinfo->value.enumerated.name,
4153 texts[uinfo->value.enumerated.item]);
4154
4155 return 0;
4156}
4157
4158static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol,
4159 struct snd_ctl_elem_value *ucontrol)
4160{
4161 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4162
4163 ucontrol->value.enumerated.item[0] = hdspm->tco->input;
4164
4165 return 0;
4166}
4167
4168static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol,
4169 struct snd_ctl_elem_value *ucontrol)
4170{
4171 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4172
4173 if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) {
4174 hdspm->tco->input = ucontrol->value.enumerated.item[0];
4175
4176 hdspm_tco_write(hdspm);
4177
4178 return 1;
4179 }
4180
4181 return 0;
4182}
4183
4184
4185#define HDSPM_TCO_WORD_TERM(xname, xindex) \
4186{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
4187 .name = xname, \
4188 .index = xindex, \
4189 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
4190 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
4191 .info = snd_hdspm_info_tco_word_term, \
4192 .get = snd_hdspm_get_tco_word_term, \
4193 .put = snd_hdspm_put_tco_word_term \
4194}
4195
4196static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol,
4197 struct snd_ctl_elem_info *uinfo)
4198{
4199 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
4200 uinfo->count = 1;
4201 uinfo->value.integer.min = 0;
4202 uinfo->value.integer.max = 1;
4203
4204 return 0;
4205}
4206
4207
4208static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
4209 struct snd_ctl_elem_value *ucontrol)
4210{
4211 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4212
4213 ucontrol->value.enumerated.item[0] = hdspm->tco->term;
4214
4215 return 0;
4216}
4217
4218
4219static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
4220 struct snd_ctl_elem_value *ucontrol)
4221{
4222 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
4223
4224 if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
4225 hdspm->tco->term = ucontrol->value.enumerated.item[0];
4226
4227 hdspm_tco_write(hdspm);
4228
4229 return 1;
4230 }
4231
4232 return 0;
4233}
4234
4235
4236
Takashi Iwai763f3562005-06-03 11:25:34 +02004237
Remy Bruno3cee5a62006-10-16 12:46:32 +02004238static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02004239 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004240 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004241 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4242 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4243 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4244 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004245 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4246 HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
4247 HDSPM_SYNC_CHECK("TCO SyncCHeck", 2),
4248 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
Takashi Iwai763f3562005-06-03 11:25:34 +02004249 HDSPM_LINE_OUT("Line Out", 0),
4250 HDSPM_TX_64("TX 64 channels mode", 0),
4251 HDSPM_C_TMS("Clear Track Marker", 0),
4252 HDSPM_SAFE_MODE("Safe Mode", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004253 HDSPM_INPUT_SELECT("Input Select", 0)
4254};
4255
4256
4257static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
4258 HDSPM_MIXER("Mixer", 0),
4259 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4260 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4261 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4262 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4263 HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
4264 HDSPM_TX_64("TX 64 channels mode", 0),
4265 HDSPM_C_TMS("Clear Track Marker", 0),
4266 HDSPM_SAFE_MODE("Safe Mode", 0),
Takashi Iwai763f3562005-06-03 11:25:34 +02004267 HDSPM_INPUT_SELECT("Input Select", 0),
4268};
4269
Adrian Knoth0dca1792011-01-26 19:32:14 +01004270static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004271 HDSPM_MIXER("Mixer", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004272 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004273 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4274 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4275 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4276 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004277 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
Adrian Knoth0dca1792011-01-26 19:32:14 +01004278 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4279 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4280 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4281 HDSPM_SYNC_CHECK("ADAT SyncCheck", 3),
4282 HDSPM_SYNC_CHECK("TCO SyncCheck", 4),
4283 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5),
4284 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4285 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4286 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4287 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
4288 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
4289 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5)
4290
4291 /*
4292 HDSPM_INPUT_SELECT("Input Select", 0),
4293 HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0),
4294 HDSPM_PROFESSIONAL("SPDIF Out Professional", 0);
4295 HDSPM_SPDIF_IN("SPDIF In", 0);
4296 HDSPM_BREAKOUT_CABLE("Breakout Cable", 0);
4297 HDSPM_INPUT_LEVEL("Input Level", 0);
4298 HDSPM_OUTPUT_LEVEL("Output Level", 0);
4299 HDSPM_PHONES("Phones", 0);
4300 */
4301};
4302
4303static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
4304 HDSPM_MIXER("Mixer", 0),
4305 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4306 HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
4307 HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0),
4308 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4309 HDSPM_SYNC_CHECK("WC SyncCheck", 0),
4310 HDSPM_SYNC_CHECK("AES SyncCheck", 1),
4311 HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
4312 HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3),
4313 HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4),
4314 HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5),
4315 HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6),
4316 HDSPM_SYNC_CHECK("TCO SyncCheck", 7),
4317 HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8),
4318 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4319 HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
4320 HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
4321 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3),
4322 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4),
4323 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
4324 HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
4325 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
4326 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8)
4327};
4328
4329static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
4330 HDSPM_MIXER("Mixer", 0),
4331 HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
4332 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
4333 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
4334 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
4335 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
4336 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
4337 HDSPM_SYNC_CHECK("WC Sync Check", 0),
4338 HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
4339 HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
4340 HDSPM_SYNC_CHECK("AES3 Sync Check", 3),
4341 HDSPM_SYNC_CHECK("AES4 Sync Check", 4),
4342 HDSPM_SYNC_CHECK("AES5 Sync Check", 5),
4343 HDSPM_SYNC_CHECK("AES6 Sync Check", 6),
4344 HDSPM_SYNC_CHECK("AES7 Sync Check", 7),
4345 HDSPM_SYNC_CHECK("AES8 Sync Check", 8),
4346 HDSPM_SYNC_CHECK("TCO Sync Check", 9),
4347 HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10),
4348 HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
4349 HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1),
4350 HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2),
4351 HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3),
4352 HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4),
4353 HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5),
4354 HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6),
4355 HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7),
4356 HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
4357 HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
4358 HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004359 HDSPM_LINE_OUT("Line Out", 0),
4360 HDSPM_EMPHASIS("Emphasis", 0),
4361 HDSPM_DOLBY("Non Audio", 0),
4362 HDSPM_PROFESSIONAL("Professional", 0),
4363 HDSPM_C_TMS("Clear Track Marker", 0),
4364 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
4365 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
4366};
4367
Adrian Knoth0dca1792011-01-26 19:32:14 +01004368
4369
4370/* Control elements for the optional TCO module */
4371static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
4372 HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
4373 HDSPM_TCO_PULL("TCO Pull", 0),
4374 HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
4375 HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0),
4376 HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0),
4377 HDSPM_TCO_WORD_TERM("TCO Word Term", 0)
4378};
4379
4380
Takashi Iwai98274f02005-11-17 14:52:34 +01004381static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02004382
4383
Takashi Iwai98274f02005-11-17 14:52:34 +01004384static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004385{
4386 int i;
4387
Adrian Knoth0dca1792011-01-26 19:32:14 +01004388 for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) {
Takashi Iwai763f3562005-06-03 11:25:34 +02004389 if (hdspm->system_sample_rate > 48000) {
4390 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004391 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
4392 SNDRV_CTL_ELEM_ACCESS_READ |
4393 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004394 } else {
4395 hdspm->playback_mixer_ctls[i]->vd[0].access =
Adrian Knoth0dca1792011-01-26 19:32:14 +01004396 SNDRV_CTL_ELEM_ACCESS_READWRITE |
4397 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
Takashi Iwai763f3562005-06-03 11:25:34 +02004398 }
4399 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
Adrian Knoth0dca1792011-01-26 19:32:14 +01004400 SNDRV_CTL_EVENT_MASK_INFO,
4401 &hdspm->playback_mixer_ctls[i]->id);
Takashi Iwai763f3562005-06-03 11:25:34 +02004402 }
4403
4404 return 0;
4405}
4406
4407
Adrian Knoth0dca1792011-01-26 19:32:14 +01004408static int snd_hdspm_create_controls(struct snd_card *card,
4409 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02004410{
4411 unsigned int idx, limit;
4412 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01004413 struct snd_kcontrol *kctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004414 struct snd_kcontrol_new *list = NULL;
Takashi Iwai763f3562005-06-03 11:25:34 +02004415
Adrian Knoth0dca1792011-01-26 19:32:14 +01004416 switch (hdspm->io_type) {
4417 case MADI:
4418 list = snd_hdspm_controls_madi;
4419 limit = ARRAY_SIZE(snd_hdspm_controls_madi);
4420 break;
4421 case MADIface:
4422 list = snd_hdspm_controls_madiface;
4423 limit = ARRAY_SIZE(snd_hdspm_controls_madiface);
4424 break;
4425 case AIO:
4426 list = snd_hdspm_controls_aio;
4427 limit = ARRAY_SIZE(snd_hdspm_controls_aio);
4428 break;
4429 case RayDAT:
4430 list = snd_hdspm_controls_raydat;
4431 limit = ARRAY_SIZE(snd_hdspm_controls_raydat);
4432 break;
4433 case AES32:
4434 list = snd_hdspm_controls_aes32;
4435 limit = ARRAY_SIZE(snd_hdspm_controls_aes32);
4436 break;
4437 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004438
Adrian Knoth0dca1792011-01-26 19:32:14 +01004439 if (NULL != list) {
4440 for (idx = 0; idx < limit; idx++) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004441 err = snd_ctl_add(card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004442 snd_ctl_new1(&list[idx], hdspm));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004443 if (err < 0)
4444 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004445 }
4446 }
4447
Takashi Iwai763f3562005-06-03 11:25:34 +02004448
Adrian Knoth0dca1792011-01-26 19:32:14 +01004449 /* create simple 1:1 playback mixer controls */
Takashi Iwai763f3562005-06-03 11:25:34 +02004450 snd_hdspm_playback_mixer.name = "Chn";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004451 if (hdspm->system_sample_rate >= 128000) {
4452 limit = hdspm->qs_out_channels;
4453 } else if (hdspm->system_sample_rate >= 64000) {
4454 limit = hdspm->ds_out_channels;
4455 } else {
4456 limit = hdspm->ss_out_channels;
4457 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004458 for (idx = 0; idx < limit; ++idx) {
4459 snd_hdspm_playback_mixer.index = idx + 1;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004460 kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
4461 err = snd_ctl_add(card, kctl);
4462 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02004463 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02004464 hdspm->playback_mixer_ctls[idx] = kctl;
4465 }
4466
Adrian Knoth0dca1792011-01-26 19:32:14 +01004467
4468 if (hdspm->tco) {
4469 /* add tco control elements */
4470 list = snd_hdspm_controls_tco;
4471 limit = ARRAY_SIZE(snd_hdspm_controls_tco);
4472 for (idx = 0; idx < limit; idx++) {
4473 err = snd_ctl_add(card,
4474 snd_ctl_new1(&list[idx], hdspm));
4475 if (err < 0)
4476 return err;
4477 }
4478 }
4479
Takashi Iwai763f3562005-06-03 11:25:34 +02004480 return 0;
4481}
4482
4483/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01004484 /proc interface
Takashi Iwai763f3562005-06-03 11:25:34 +02004485 ------------------------------------------------------------*/
4486
4487static void
Remy Bruno3cee5a62006-10-16 12:46:32 +02004488snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
4489 struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02004490{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004491 struct hdspm *hdspm = entry->private_data;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004492 unsigned int status, status2, control, freq;
4493
Takashi Iwai763f3562005-06-03 11:25:34 +02004494 char *pref_sync_ref;
4495 char *autosync_ref;
4496 char *system_clock_mode;
Takashi Iwai763f3562005-06-03 11:25:34 +02004497 char *insel;
Takashi Iwai763f3562005-06-03 11:25:34 +02004498 int x, x2;
4499
Adrian Knoth0dca1792011-01-26 19:32:14 +01004500 /* TCO stuff */
4501 int a, ltc, frames, seconds, minutes, hours;
4502 unsigned int period;
4503 u64 freq_const = 0;
4504 u32 rate;
4505
Takashi Iwai763f3562005-06-03 11:25:34 +02004506 status = hdspm_read(hdspm, HDSPM_statusRegister);
4507 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01004508 control = hdspm->control_register;
4509 freq = hdspm_read(hdspm, HDSPM_timecodeRegister);
Takashi Iwai763f3562005-06-03 11:25:34 +02004510
4511 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004512 hdspm->card_name, hdspm->card->number + 1,
4513 hdspm->firmware_rev,
4514 (status2 & HDSPM_version0) |
4515 (status2 & HDSPM_version1) | (status2 &
4516 HDSPM_version2));
4517
4518 snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
4519 (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
4520 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004521
4522 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004523 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
Takashi Iwai763f3562005-06-03 11:25:34 +02004524
4525 snd_iprintf(buffer, "--- System ---\n");
4526
4527 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004528 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4529 status & HDSPM_audioIRQPending,
4530 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4531 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4532 hdspm->irq_count);
Takashi Iwai763f3562005-06-03 11:25:34 +02004533 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004534 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4535 "estimated= %ld (bytes)\n",
4536 ((status & HDSPM_BufferID) ? 1 : 0),
4537 (status & HDSPM_BufferPositionMask),
4538 (status & HDSPM_BufferPositionMask) %
4539 (2 * (int)hdspm->period_bytes),
4540 ((status & HDSPM_BufferPositionMask) - 64) %
4541 (2 * (int)hdspm->period_bytes),
4542 (long) hdspm_hw_pointer(hdspm) * 4);
Takashi Iwai763f3562005-06-03 11:25:34 +02004543
4544 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004545 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4546 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4547 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4548 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4549 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
Takashi Iwai763f3562005-06-03 11:25:34 +02004550 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004551 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4552 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4553 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4554 snd_iprintf(buffer,
4555 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4556 "status2=0x%x\n",
4557 hdspm->control_register, hdspm->control2_register,
4558 status, status2);
4559 if (status & HDSPM_tco_detect) {
4560 snd_iprintf(buffer, "TCO module detected.\n");
4561 a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
4562 if (a & HDSPM_TCO1_LTC_Input_valid) {
4563 snd_iprintf(buffer, " LTC valid, ");
4564 switch (a & (HDSPM_TCO1_LTC_Format_LSB |
4565 HDSPM_TCO1_LTC_Format_MSB)) {
4566 case 0:
4567 snd_iprintf(buffer, "24 fps, ");
4568 break;
4569 case HDSPM_TCO1_LTC_Format_LSB:
4570 snd_iprintf(buffer, "25 fps, ");
4571 break;
4572 case HDSPM_TCO1_LTC_Format_MSB:
4573 snd_iprintf(buffer, "29.97 fps, ");
4574 break;
4575 default:
4576 snd_iprintf(buffer, "30 fps, ");
4577 break;
4578 }
4579 if (a & HDSPM_TCO1_set_drop_frame_flag) {
4580 snd_iprintf(buffer, "drop frame\n");
4581 } else {
4582 snd_iprintf(buffer, "full frame\n");
4583 }
4584 } else {
4585 snd_iprintf(buffer, " no LTC\n");
4586 }
4587 if (a & HDSPM_TCO1_Video_Input_Format_NTSC) {
4588 snd_iprintf(buffer, " Video: NTSC\n");
4589 } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) {
4590 snd_iprintf(buffer, " Video: PAL\n");
4591 } else {
4592 snd_iprintf(buffer, " No video\n");
4593 }
4594 if (a & HDSPM_TCO1_TCO_lock) {
4595 snd_iprintf(buffer, " Sync: lock\n");
4596 } else {
4597 snd_iprintf(buffer, " Sync: no lock\n");
4598 }
4599
4600 switch (hdspm->io_type) {
4601 case MADI:
4602 case AES32:
4603 freq_const = 110069313433624ULL;
4604 break;
4605 case RayDAT:
4606 case AIO:
4607 freq_const = 104857600000000ULL;
4608 break;
4609 case MADIface:
4610 break; /* no TCO possible */
4611 }
4612
4613 period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
4614 snd_iprintf(buffer, " period: %u\n", period);
4615
4616
4617 /* rate = freq_const/period; */
4618 rate = div_u64(freq_const, period);
4619
4620 if (control & HDSPM_QuadSpeed) {
4621 rate *= 4;
4622 } else if (control & HDSPM_DoubleSpeed) {
4623 rate *= 2;
4624 }
4625
4626 snd_iprintf(buffer, " Frequency: %u Hz\n",
4627 (unsigned int) rate);
4628
4629 ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
4630 frames = ltc & 0xF;
4631 ltc >>= 4;
4632 frames += (ltc & 0x3) * 10;
4633 ltc >>= 4;
4634 seconds = ltc & 0xF;
4635 ltc >>= 4;
4636 seconds += (ltc & 0x7) * 10;
4637 ltc >>= 4;
4638 minutes = ltc & 0xF;
4639 ltc >>= 4;
4640 minutes += (ltc & 0x7) * 10;
4641 ltc >>= 4;
4642 hours = ltc & 0xF;
4643 ltc >>= 4;
4644 hours += (ltc & 0x3) * 10;
4645 snd_iprintf(buffer,
4646 " LTC In: %02d:%02d:%02d:%02d\n",
4647 hours, minutes, seconds, frames);
4648
4649 } else {
4650 snd_iprintf(buffer, "No TCO module detected.\n");
4651 }
Takashi Iwai763f3562005-06-03 11:25:34 +02004652
4653 snd_iprintf(buffer, "--- Settings ---\n");
4654
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004655 x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
Adrian Knoth0dca1792011-01-26 19:32:14 +01004656 HDSPM_LatencyMask));
Takashi Iwai763f3562005-06-03 11:25:34 +02004657
4658 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004659 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4660 x, (unsigned long) hdspm->period_bytes);
Takashi Iwai763f3562005-06-03 11:25:34 +02004661
Adrian Knoth0dca1792011-01-26 19:32:14 +01004662 snd_iprintf(buffer, "Line out: %s\n",
4663 (hdspm->control_register & HDSPM_LineOut) ? "on " : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004664
4665 switch (hdspm->control_register & HDSPM_InputMask) {
4666 case HDSPM_InputOptical:
4667 insel = "Optical";
4668 break;
4669 case HDSPM_InputCoaxial:
4670 insel = "Coaxial";
4671 break;
4672 default:
Adrian Knoth0dca1792011-01-26 19:32:14 +01004673 insel = "Unkown";
Takashi Iwai763f3562005-06-03 11:25:34 +02004674 }
4675
Takashi Iwai763f3562005-06-03 11:25:34 +02004676 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004677 "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
4678 "Auto Input %s\n",
4679 (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off",
4680 (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56",
4681 (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off");
Takashi Iwai763f3562005-06-03 11:25:34 +02004682
Adrian Knoth0dca1792011-01-26 19:32:14 +01004683
Remy Bruno3cee5a62006-10-16 12:46:32 +02004684 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
Adrian Knoth0dca1792011-01-26 19:32:14 +01004685 system_clock_mode = "AutoSync";
Remy Bruno3cee5a62006-10-16 12:46:32 +02004686 else
Takashi Iwai763f3562005-06-03 11:25:34 +02004687 system_clock_mode = "Master";
Adrian Knoth0dca1792011-01-26 19:32:14 +01004688 snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode);
Takashi Iwai763f3562005-06-03 11:25:34 +02004689
4690 switch (hdspm_pref_sync_ref(hdspm)) {
4691 case HDSPM_SYNC_FROM_WORD:
4692 pref_sync_ref = "Word Clock";
4693 break;
4694 case HDSPM_SYNC_FROM_MADI:
4695 pref_sync_ref = "MADI Sync";
4696 break;
Adrian Knoth0dca1792011-01-26 19:32:14 +01004697 case HDSPM_SYNC_FROM_TCO:
4698 pref_sync_ref = "TCO";
4699 break;
4700 case HDSPM_SYNC_FROM_SYNC_IN:
4701 pref_sync_ref = "Sync In";
4702 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004703 default:
4704 pref_sync_ref = "XXXX Clock";
4705 break;
4706 }
4707 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004708 pref_sync_ref);
Takashi Iwai763f3562005-06-03 11:25:34 +02004709
4710 snd_iprintf(buffer, "System Clock Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004711 hdspm->system_sample_rate);
Takashi Iwai763f3562005-06-03 11:25:34 +02004712
4713
4714 snd_iprintf(buffer, "--- Status:\n");
4715
4716 x = status & HDSPM_madiSync;
4717 x2 = status2 & HDSPM_wcSync;
4718
4719 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004720 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
4721 "NoLock",
4722 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
4723 "NoLock");
Takashi Iwai763f3562005-06-03 11:25:34 +02004724
4725 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004726 case HDSPM_AUTOSYNC_FROM_SYNC_IN:
4727 autosync_ref = "Sync In";
4728 break;
4729 case HDSPM_AUTOSYNC_FROM_TCO:
4730 autosync_ref = "TCO";
4731 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02004732 case HDSPM_AUTOSYNC_FROM_WORD:
4733 autosync_ref = "Word Clock";
4734 break;
4735 case HDSPM_AUTOSYNC_FROM_MADI:
4736 autosync_ref = "MADI Sync";
4737 break;
4738 case HDSPM_AUTOSYNC_FROM_NONE:
4739 autosync_ref = "Input not valid";
4740 break;
4741 default:
4742 autosync_ref = "---";
4743 break;
4744 }
4745 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004746 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
4747 autosync_ref, hdspm_external_sample_rate(hdspm),
4748 (status & HDSPM_madiFreqMask) >> 22,
4749 (status2 & HDSPM_wcFreqMask) >> 5);
Takashi Iwai763f3562005-06-03 11:25:34 +02004750
4751 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004752 (status & HDSPM_AB_int) ? "Coax" : "Optical",
4753 (status & HDSPM_RX_64ch) ? "64 channels" :
4754 "56 channels");
Takashi Iwai763f3562005-06-03 11:25:34 +02004755
4756 snd_iprintf(buffer, "\n");
4757}
4758
Remy Bruno3cee5a62006-10-16 12:46:32 +02004759static void
4760snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
4761 struct snd_info_buffer *buffer)
4762{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004763 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004764 unsigned int status;
4765 unsigned int status2;
4766 unsigned int timecode;
4767 int pref_syncref;
4768 char *autosync_ref;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004769 int x;
4770
4771 status = hdspm_read(hdspm, HDSPM_statusRegister);
4772 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
4773 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
4774
4775 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
4776 hdspm->card_name, hdspm->card->number + 1,
4777 hdspm->firmware_rev);
4778
4779 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
4780 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
4781
4782 snd_iprintf(buffer, "--- System ---\n");
4783
4784 snd_iprintf(buffer,
4785 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
4786 status & HDSPM_audioIRQPending,
4787 (status & HDSPM_midi0IRQPending) ? 1 : 0,
4788 (status & HDSPM_midi1IRQPending) ? 1 : 0,
4789 hdspm->irq_count);
4790 snd_iprintf(buffer,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004791 "HW pointer: id = %d, rawptr = %d (%d->%d) "
4792 "estimated= %ld (bytes)\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004793 ((status & HDSPM_BufferID) ? 1 : 0),
4794 (status & HDSPM_BufferPositionMask),
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004795 (status & HDSPM_BufferPositionMask) %
4796 (2 * (int)hdspm->period_bytes),
4797 ((status & HDSPM_BufferPositionMask) - 64) %
4798 (2 * (int)hdspm->period_bytes),
Remy Bruno3cee5a62006-10-16 12:46:32 +02004799 (long) hdspm_hw_pointer(hdspm) * 4);
4800
4801 snd_iprintf(buffer,
4802 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
4803 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
4804 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
4805 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
4806 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
4807 snd_iprintf(buffer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01004808 "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
4809 hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
4810 hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
4811 snd_iprintf(buffer,
4812 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
4813 "status2=0x%x\n",
4814 hdspm->control_register, hdspm->control2_register,
4815 status, status2);
Remy Bruno3cee5a62006-10-16 12:46:32 +02004816
4817 snd_iprintf(buffer, "--- Settings ---\n");
4818
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004819 x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
Adrian Knoth0dca1792011-01-26 19:32:14 +01004820 HDSPM_LatencyMask));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004821
4822 snd_iprintf(buffer,
4823 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
4824 x, (unsigned long) hdspm->period_bytes);
4825
Adrian Knoth0dca1792011-01-26 19:32:14 +01004826 snd_iprintf(buffer, "Line out: %s\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02004827 (hdspm->
Adrian Knoth0dca1792011-01-26 19:32:14 +01004828 control_register & HDSPM_LineOut) ? "on " : "off");
Remy Bruno3cee5a62006-10-16 12:46:32 +02004829
4830 snd_iprintf(buffer,
4831 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
4832 (hdspm->
4833 control_register & HDSPM_clr_tms) ? "on" : "off",
4834 (hdspm->
4835 control_register & HDSPM_Emphasis) ? "on" : "off",
4836 (hdspm->
4837 control_register & HDSPM_Dolby) ? "on" : "off");
4838
Remy Bruno3cee5a62006-10-16 12:46:32 +02004839
4840 pref_syncref = hdspm_pref_sync_ref(hdspm);
4841 if (pref_syncref == 0)
4842 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
4843 else
4844 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
4845 pref_syncref);
4846
4847 snd_iprintf(buffer, "System Clock Frequency: %d\n",
4848 hdspm->system_sample_rate);
4849
4850 snd_iprintf(buffer, "Double speed: %s\n",
4851 hdspm->control_register & HDSPM_DS_DoubleWire?
4852 "Double wire" : "Single wire");
4853 snd_iprintf(buffer, "Quad speed: %s\n",
4854 hdspm->control_register & HDSPM_QS_DoubleWire?
4855 "Double wire" :
4856 hdspm->control_register & HDSPM_QS_QuadWire?
4857 "Quad wire" : "Single wire");
4858
4859 snd_iprintf(buffer, "--- Status:\n");
4860
4861 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01004862 (status & HDSPM_AES32_wcLock) ? "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004863 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004864
4865 for (x = 0; x < 8; x++) {
4866 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004867 x+1,
4868 (status2 & (HDSPM_LockAES >> x)) ?
Adrian Knoth0dca1792011-01-26 19:32:14 +01004869 "Sync " : "No Lock",
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004870 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
Remy Bruno3cee5a62006-10-16 12:46:32 +02004871 }
4872
4873 switch (hdspm_autosync_ref(hdspm)) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01004874 case HDSPM_AES32_AUTOSYNC_FROM_NONE:
4875 autosync_ref = "None"; break;
4876 case HDSPM_AES32_AUTOSYNC_FROM_WORD:
4877 autosync_ref = "Word Clock"; break;
4878 case HDSPM_AES32_AUTOSYNC_FROM_AES1:
4879 autosync_ref = "AES1"; break;
4880 case HDSPM_AES32_AUTOSYNC_FROM_AES2:
4881 autosync_ref = "AES2"; break;
4882 case HDSPM_AES32_AUTOSYNC_FROM_AES3:
4883 autosync_ref = "AES3"; break;
4884 case HDSPM_AES32_AUTOSYNC_FROM_AES4:
4885 autosync_ref = "AES4"; break;
4886 case HDSPM_AES32_AUTOSYNC_FROM_AES5:
4887 autosync_ref = "AES5"; break;
4888 case HDSPM_AES32_AUTOSYNC_FROM_AES6:
4889 autosync_ref = "AES6"; break;
4890 case HDSPM_AES32_AUTOSYNC_FROM_AES7:
4891 autosync_ref = "AES7"; break;
4892 case HDSPM_AES32_AUTOSYNC_FROM_AES8:
4893 autosync_ref = "AES8"; break;
4894 default:
4895 autosync_ref = "---"; break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004896 }
4897 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
4898
4899 snd_iprintf(buffer, "\n");
4900}
4901
Adrian Knoth0dca1792011-01-26 19:32:14 +01004902static void
4903snd_hdspm_proc_read_raydat(struct snd_info_entry *entry,
4904 struct snd_info_buffer *buffer)
4905{
4906 struct hdspm *hdspm = entry->private_data;
4907 unsigned int status1, status2, status3, control, i;
4908 unsigned int lock, sync;
4909
4910 status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */
4911 status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */
4912 status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */
4913
4914 control = hdspm->control_register;
4915
4916 snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1);
4917 snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2);
4918 snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3);
4919
4920
4921 snd_iprintf(buffer, "\n*** CLOCK MODE\n\n");
4922
4923 snd_iprintf(buffer, "Clock mode : %s\n",
4924 (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave");
4925 snd_iprintf(buffer, "System frequency: %d Hz\n",
4926 hdspm_get_system_sample_rate(hdspm));
4927
4928 snd_iprintf(buffer, "\n*** INPUT STATUS\n\n");
4929
4930 lock = 0x1;
4931 sync = 0x100;
4932
4933 for (i = 0; i < 8; i++) {
4934 snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n",
4935 i,
4936 (status1 & lock) ? 1 : 0,
4937 (status1 & sync) ? 1 : 0,
4938 texts_freq[(status2 >> (i * 4)) & 0xF]);
4939
4940 lock = lock<<1;
4941 sync = sync<<1;
4942 }
4943
4944 snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n",
4945 (status1 & 0x1000000) ? 1 : 0,
4946 (status1 & 0x2000000) ? 1 : 0,
4947 texts_freq[(status1 >> 16) & 0xF]);
4948
4949 snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n",
4950 (status1 & 0x4000000) ? 1 : 0,
4951 (status1 & 0x8000000) ? 1 : 0,
4952 texts_freq[(status1 >> 20) & 0xF]);
4953
4954 snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n",
4955 (status3 & 0x400) ? 1 : 0,
4956 (status3 & 0x800) ? 1 : 0,
4957 texts_freq[(status2 >> 12) & 0xF]);
4958
4959}
4960
Remy Bruno3cee5a62006-10-16 12:46:32 +02004961#ifdef CONFIG_SND_DEBUG
4962static void
Adrian Knoth0dca1792011-01-26 19:32:14 +01004963snd_hdspm_proc_read_debug(struct snd_info_entry *entry,
Remy Bruno3cee5a62006-10-16 12:46:32 +02004964 struct snd_info_buffer *buffer)
4965{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004966 struct hdspm *hdspm = entry->private_data;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004967
4968 int j,i;
4969
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02004970 for (i = 0; i < 256 /* 1024*64 */; i += j) {
Remy Bruno3cee5a62006-10-16 12:46:32 +02004971 snd_iprintf(buffer, "0x%08X: ", i);
4972 for (j = 0; j < 16; j += 4)
4973 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
4974 snd_iprintf(buffer, "\n");
4975 }
4976}
4977#endif
4978
4979
Adrian Knoth0dca1792011-01-26 19:32:14 +01004980static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry,
4981 struct snd_info_buffer *buffer)
4982{
4983 struct hdspm *hdspm = entry->private_data;
4984 int i;
Remy Bruno3cee5a62006-10-16 12:46:32 +02004985
Adrian Knoth0dca1792011-01-26 19:32:14 +01004986 snd_iprintf(buffer, "# generated by hdspm\n");
4987
4988 for (i = 0; i < hdspm->max_channels_in; i++) {
4989 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]);
4990 }
4991}
4992
4993static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
4994 struct snd_info_buffer *buffer)
4995{
4996 struct hdspm *hdspm = entry->private_data;
4997 int i;
4998
4999 snd_iprintf(buffer, "# generated by hdspm\n");
5000
5001 for (i = 0; i < hdspm->max_channels_out; i++) {
5002 snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]);
5003 }
5004}
5005
5006
5007static void __devinit snd_hdspm_proc_init(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005008{
Takashi Iwai98274f02005-11-17 14:52:34 +01005009 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02005010
Adrian Knoth0dca1792011-01-26 19:32:14 +01005011 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) {
5012 switch (hdspm->io_type) {
5013 case AES32:
5014 snd_info_set_text_ops(entry, hdspm,
5015 snd_hdspm_proc_read_aes32);
5016 break;
5017 case MADI:
5018 snd_info_set_text_ops(entry, hdspm,
5019 snd_hdspm_proc_read_madi);
5020 break;
5021 case MADIface:
5022 /* snd_info_set_text_ops(entry, hdspm,
5023 snd_hdspm_proc_read_madiface); */
5024 break;
5025 case RayDAT:
5026 snd_info_set_text_ops(entry, hdspm,
5027 snd_hdspm_proc_read_raydat);
5028 break;
5029 case AIO:
5030 break;
5031 }
5032 }
5033
5034 if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) {
5035 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in);
5036 }
5037
5038 if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) {
5039 snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out);
5040 }
5041
Remy Bruno3cee5a62006-10-16 12:46:32 +02005042#ifdef CONFIG_SND_DEBUG
5043 /* debug file to read all hdspm registers */
5044 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
5045 snd_info_set_text_ops(entry, hdspm,
5046 snd_hdspm_proc_read_debug);
5047#endif
Takashi Iwai763f3562005-06-03 11:25:34 +02005048}
5049
5050/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005051 hdspm intitialize
Takashi Iwai763f3562005-06-03 11:25:34 +02005052 ------------------------------------------------------------*/
5053
Takashi Iwai98274f02005-11-17 14:52:34 +01005054static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02005055{
Takashi Iwai763f3562005-06-03 11:25:34 +02005056 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
Joe Perches561de312007-12-18 13:13:47 +01005057 hold it (e.g. during module initialization).
Adrian Knoth0dca1792011-01-26 19:32:14 +01005058 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005059
5060 /* set defaults: */
5061
Adrian Knoth0dca1792011-01-26 19:32:14 +01005062 hdspm->settings_register = 0;
5063
5064 switch (hdspm->io_type) {
5065 case MADI:
5066 case MADIface:
5067 hdspm->control_register =
5068 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5069 break;
5070
5071 case RayDAT:
5072 case AIO:
5073 hdspm->settings_register = 0x1 + 0x1000;
5074 /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0,
5075 * line_out */
5076 hdspm->control_register =
5077 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
5078 break;
5079
5080 case AES32:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005081 hdspm->control_register =
5082 HDSPM_ClockModeMaster | /* Master Cloack Mode on */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005083 hdspm_encode_latency(7) | /* latency max=8192samples */
Remy Bruno3cee5a62006-10-16 12:46:32 +02005084 HDSPM_SyncRef0 | /* AES1 is syncclock */
5085 HDSPM_LineOut | /* Analog output in */
5086 HDSPM_Professional; /* Professional mode */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005087 break;
5088 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005089
5090 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5091
Adrian Knoth0dca1792011-01-26 19:32:14 +01005092 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005093 /* No control2 register for AES32 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005094#ifdef SNDRV_BIG_ENDIAN
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005095 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
Takashi Iwai763f3562005-06-03 11:25:34 +02005096#else
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005097 hdspm->control2_register = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005098#endif
5099
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005100 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
5101 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005102 hdspm_compute_period_size(hdspm);
5103
5104 /* silence everything */
5105
5106 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
5107
Adrian Knoth0dca1792011-01-26 19:32:14 +01005108 if (hdspm->io_type == AIO || hdspm->io_type == RayDAT) {
5109 hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
Takashi Iwai763f3562005-06-03 11:25:34 +02005110 }
5111
5112 /* set a default rate so that the channel map is set up. */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005113 hdspm_set_rate(hdspm, 48000, 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005114
5115 return 0;
5116}
5117
5118
5119/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005120 interrupt
Takashi Iwai763f3562005-06-03 11:25:34 +02005121 ------------------------------------------------------------*/
5122
David Howells7d12e782006-10-05 14:55:46 +01005123static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02005124{
Takashi Iwai98274f02005-11-17 14:52:34 +01005125 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02005126 unsigned int status;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005127 int i, audio, midi, schedule = 0;
5128 /* cycles_t now; */
Takashi Iwai763f3562005-06-03 11:25:34 +02005129
5130 status = hdspm_read(hdspm, HDSPM_statusRegister);
5131
5132 audio = status & HDSPM_audioIRQPending;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005133 midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending |
5134 HDSPM_midi2IRQPending | HDSPM_midi3IRQPending);
Takashi Iwai763f3562005-06-03 11:25:34 +02005135
Adrian Knoth0dca1792011-01-26 19:32:14 +01005136 /* now = get_cycles(); */
5137 /**
5138 * LAT_2..LAT_0 period counter (win) counter (mac)
5139 * 6 4096 ~256053425 ~514672358
5140 * 5 2048 ~128024983 ~257373821
5141 * 4 1024 ~64023706 ~128718089
5142 * 3 512 ~32005945 ~64385999
5143 * 2 256 ~16003039 ~32260176
5144 * 1 128 ~7998738 ~16194507
5145 * 0 64 ~3998231 ~8191558
5146 **/
5147 /*
5148 snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n",
5149 now-hdspm->last_interrupt, status & 0xFFC0);
5150 hdspm->last_interrupt = now;
5151 */
5152
5153 if (!audio && !midi)
Takashi Iwai763f3562005-06-03 11:25:34 +02005154 return IRQ_NONE;
5155
5156 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
5157 hdspm->irq_count++;
5158
Takashi Iwai763f3562005-06-03 11:25:34 +02005159
5160 if (audio) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005161 if (hdspm->capture_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005162 snd_pcm_period_elapsed(hdspm->capture_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005163
5164 if (hdspm->playback_substream)
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005165 snd_pcm_period_elapsed(hdspm->playback_substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005166 }
5167
Adrian Knoth0dca1792011-01-26 19:32:14 +01005168 if (midi) {
5169 i = 0;
5170 while (i < hdspm->midiPorts) {
5171 if ((hdspm_read(hdspm,
5172 hdspm->midi[i].statusIn) & 0xff) &&
5173 (status & hdspm->midi[i].irq)) {
5174 /* we disable interrupts for this input until
5175 * processing is done
5176 */
5177 hdspm->control_register &= ~hdspm->midi[i].ie;
5178 hdspm_write(hdspm, HDSPM_controlRegister,
5179 hdspm->control_register);
5180 hdspm->midi[i].pending = 1;
5181 schedule = 1;
5182 }
5183
5184 i++;
5185 }
5186
5187 if (schedule)
5188 tasklet_hi_schedule(&hdspm->midi_tasklet);
Takashi Iwai763f3562005-06-03 11:25:34 +02005189 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005190
Takashi Iwai763f3562005-06-03 11:25:34 +02005191 return IRQ_HANDLED;
5192}
5193
5194/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01005195 pcm interface
Takashi Iwai763f3562005-06-03 11:25:34 +02005196 ------------------------------------------------------------*/
5197
5198
Adrian Knoth0dca1792011-01-26 19:32:14 +01005199static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream
5200 *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005201{
Takashi Iwai98274f02005-11-17 14:52:34 +01005202 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005203 return hdspm_hw_pointer(hdspm);
5204}
5205
Takashi Iwai763f3562005-06-03 11:25:34 +02005206
Takashi Iwai98274f02005-11-17 14:52:34 +01005207static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005208{
Takashi Iwai98274f02005-11-17 14:52:34 +01005209 struct snd_pcm_runtime *runtime = substream->runtime;
5210 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5211 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005212
5213 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5214 other = hdspm->capture_substream;
5215 else
5216 other = hdspm->playback_substream;
5217
5218 if (hdspm->running)
5219 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
5220 else
5221 runtime->status->hw_ptr = 0;
5222 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005223 struct snd_pcm_substream *s;
5224 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwaief991b92007-02-22 12:52:53 +01005225 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005226 if (s == other) {
5227 oruntime->status->hw_ptr =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005228 runtime->status->hw_ptr;
Takashi Iwai763f3562005-06-03 11:25:34 +02005229 break;
5230 }
5231 }
5232 }
5233 return 0;
5234}
5235
Takashi Iwai98274f02005-11-17 14:52:34 +01005236static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
5237 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02005238{
Takashi Iwai98274f02005-11-17 14:52:34 +01005239 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005240 int err;
5241 int i;
5242 pid_t this_pid;
5243 pid_t other_pid;
Takashi Iwai763f3562005-06-03 11:25:34 +02005244
5245 spin_lock_irq(&hdspm->lock);
5246
5247 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5248 this_pid = hdspm->playback_pid;
5249 other_pid = hdspm->capture_pid;
5250 } else {
5251 this_pid = hdspm->capture_pid;
5252 other_pid = hdspm->playback_pid;
5253 }
5254
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005255 if (other_pid > 0 && this_pid != other_pid) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005256
5257 /* The other stream is open, and not by the same
5258 task as this one. Make sure that the parameters
5259 that matter are the same.
Adrian Knoth0dca1792011-01-26 19:32:14 +01005260 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005261
5262 if (params_rate(params) != hdspm->system_sample_rate) {
5263 spin_unlock_irq(&hdspm->lock);
5264 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005265 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005266 return -EBUSY;
5267 }
5268
5269 if (params_period_size(params) != hdspm->period_bytes / 4) {
5270 spin_unlock_irq(&hdspm->lock);
5271 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005272 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005273 return -EBUSY;
5274 }
5275
5276 }
5277 /* We're fine. */
5278 spin_unlock_irq(&hdspm->lock);
5279
5280 /* how to make sure that the rate matches an externally-set one ? */
5281
5282 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005283 err = hdspm_set_rate(hdspm, params_rate(params), 0);
5284 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005285 snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005286 spin_unlock_irq(&hdspm->lock);
5287 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005288 SNDRV_PCM_HW_PARAM_RATE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005289 return err;
5290 }
5291 spin_unlock_irq(&hdspm->lock);
5292
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005293 err = hdspm_set_interrupt_interval(hdspm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005294 params_period_size(params));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005295 if (err < 0) {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005296 snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005297 _snd_pcm_hw_param_setempty(params,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005298 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
Takashi Iwai763f3562005-06-03 11:25:34 +02005299 return err;
5300 }
5301
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005302 /* Memory allocation, takashi's method, dont know if we should
5303 * spinlock
5304 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005305 /* malloc all buffer even if not enabled to get sure */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005306 /* Update for MADI rev 204: we need to allocate for all channels,
5307 * otherwise it doesn't work at 96kHz */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005308
Takashi Iwai763f3562005-06-03 11:25:34 +02005309 err =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005310 snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
5311 if (err < 0) {
5312 snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err);
Takashi Iwai763f3562005-06-03 11:25:34 +02005313 return err;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005314 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005315
Takashi Iwai763f3562005-06-03 11:25:34 +02005316 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5317
Takashi Iwai77a23f22008-08-21 13:00:13 +02005318 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferOut,
Takashi Iwai763f3562005-06-03 11:25:34 +02005319 params_channels(params));
5320
5321 for (i = 0; i < params_channels(params); ++i)
5322 snd_hdspm_enable_out(hdspm, i, 1);
5323
5324 hdspm->playback_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005325 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005326 snd_printdd("Allocated sample buffer for playback at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005327 hdspm->playback_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005328 } else {
Takashi Iwai77a23f22008-08-21 13:00:13 +02005329 hdspm_set_sgbuf(hdspm, substream, HDSPM_pageAddressBufferIn,
Takashi Iwai763f3562005-06-03 11:25:34 +02005330 params_channels(params));
5331
5332 for (i = 0; i < params_channels(params); ++i)
5333 snd_hdspm_enable_in(hdspm, i, 1);
5334
5335 hdspm->capture_buffer =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005336 (unsigned char *) substream->runtime->dma_area;
Takashi Iwai54bf5dd2006-11-06 15:38:55 +01005337 snd_printdd("Allocated sample buffer for capture at %p\n",
Remy Bruno3cee5a62006-10-16 12:46:32 +02005338 hdspm->capture_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005339 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005340
Remy Bruno3cee5a62006-10-16 12:46:32 +02005341 /*
5342 snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
5343 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5344 "playback" : "capture",
Takashi Iwai77a23f22008-08-21 13:00:13 +02005345 snd_pcm_sgbuf_get_addr(substream, 0));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005346 */
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005347 /*
Adrian Knoth0dca1792011-01-26 19:32:14 +01005348 snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
5349 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
5350 "playback" : "capture",
5351 params_rate(params), params_channels(params),
5352 params_buffer_size(params));
5353 */
5354
5355
5356 /* Switch to native float format if requested */
5357 if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
5358 if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
5359 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n");
5360
5361 hdspm->control_register |= HDSPe_FLOAT_FORMAT;
5362 } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) {
5363 if (hdspm->control_register & HDSPe_FLOAT_FORMAT)
5364 snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n");
5365
5366 hdspm->control_register &= ~HDSPe_FLOAT_FORMAT;
5367 }
5368 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
5369
Takashi Iwai763f3562005-06-03 11:25:34 +02005370 return 0;
5371}
5372
Takashi Iwai98274f02005-11-17 14:52:34 +01005373static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005374{
5375 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01005376 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005377
5378 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5379
Adrian Knoth0dca1792011-01-26 19:32:14 +01005380 /* params_channels(params) should be enough,
Takashi Iwai763f3562005-06-03 11:25:34 +02005381 but to get sure in case of error */
Adrian Knoth0dca1792011-01-26 19:32:14 +01005382 for (i = 0; i < hdspm->max_channels_out; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005383 snd_hdspm_enable_out(hdspm, i, 0);
5384
5385 hdspm->playback_buffer = NULL;
5386 } else {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005387 for (i = 0; i < hdspm->max_channels_in; ++i)
Takashi Iwai763f3562005-06-03 11:25:34 +02005388 snd_hdspm_enable_in(hdspm, i, 0);
5389
5390 hdspm->capture_buffer = NULL;
5391
5392 }
5393
5394 snd_pcm_lib_free_pages(substream);
5395
5396 return 0;
5397}
5398
Adrian Knoth0dca1792011-01-26 19:32:14 +01005399
Takashi Iwai98274f02005-11-17 14:52:34 +01005400static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005401 struct snd_pcm_channel_info *info)
Takashi Iwai763f3562005-06-03 11:25:34 +02005402{
Takashi Iwai98274f02005-11-17 14:52:34 +01005403 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005404
Adrian Knoth0dca1792011-01-26 19:32:14 +01005405 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
5406 if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) {
5407 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel);
5408 return -EINVAL;
5409 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005410
Adrian Knoth0dca1792011-01-26 19:32:14 +01005411 if (hdspm->channel_map_out[info->channel] < 0) {
5412 snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel);
5413 return -EINVAL;
5414 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005415
Adrian Knoth0dca1792011-01-26 19:32:14 +01005416 info->offset = hdspm->channel_map_out[info->channel] *
5417 HDSPM_CHANNEL_BUFFER_BYTES;
5418 } else {
5419 if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) {
5420 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel);
5421 return -EINVAL;
5422 }
5423
5424 if (hdspm->channel_map_in[info->channel] < 0) {
5425 snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel);
5426 return -EINVAL;
5427 }
5428
5429 info->offset = hdspm->channel_map_in[info->channel] *
5430 HDSPM_CHANNEL_BUFFER_BYTES;
5431 }
5432
Takashi Iwai763f3562005-06-03 11:25:34 +02005433 info->first = 0;
5434 info->step = 32;
5435 return 0;
5436}
5437
Adrian Knoth0dca1792011-01-26 19:32:14 +01005438
Takashi Iwai98274f02005-11-17 14:52:34 +01005439static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005440 unsigned int cmd, void *arg)
Takashi Iwai763f3562005-06-03 11:25:34 +02005441{
5442 switch (cmd) {
5443 case SNDRV_PCM_IOCTL1_RESET:
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005444 return snd_hdspm_reset(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005445
5446 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
Adrian Knoth0dca1792011-01-26 19:32:14 +01005447 {
5448 struct snd_pcm_channel_info *info = arg;
5449 return snd_hdspm_channel_info(substream, info);
5450 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005451 default:
5452 break;
5453 }
5454
5455 return snd_pcm_lib_ioctl(substream, cmd, arg);
5456}
5457
Takashi Iwai98274f02005-11-17 14:52:34 +01005458static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02005459{
Takashi Iwai98274f02005-11-17 14:52:34 +01005460 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5461 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02005462 int running;
5463
5464 spin_lock(&hdspm->lock);
5465 running = hdspm->running;
5466 switch (cmd) {
5467 case SNDRV_PCM_TRIGGER_START:
5468 running |= 1 << substream->stream;
5469 break;
5470 case SNDRV_PCM_TRIGGER_STOP:
5471 running &= ~(1 << substream->stream);
5472 break;
5473 default:
5474 snd_BUG();
5475 spin_unlock(&hdspm->lock);
5476 return -EINVAL;
5477 }
5478 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
5479 other = hdspm->capture_substream;
5480 else
5481 other = hdspm->playback_substream;
5482
5483 if (other) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005484 struct snd_pcm_substream *s;
Takashi Iwaief991b92007-02-22 12:52:53 +01005485 snd_pcm_group_for_each_entry(s, substream) {
Takashi Iwai763f3562005-06-03 11:25:34 +02005486 if (s == other) {
5487 snd_pcm_trigger_done(s, substream);
5488 if (cmd == SNDRV_PCM_TRIGGER_START)
5489 running |= 1 << s->stream;
5490 else
5491 running &= ~(1 << s->stream);
5492 goto _ok;
5493 }
5494 }
5495 if (cmd == SNDRV_PCM_TRIGGER_START) {
5496 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
Adrian Knoth0dca1792011-01-26 19:32:14 +01005497 && substream->stream ==
5498 SNDRV_PCM_STREAM_CAPTURE)
Takashi Iwai763f3562005-06-03 11:25:34 +02005499 hdspm_silence_playback(hdspm);
5500 } else {
5501 if (running &&
Adrian Knoth0dca1792011-01-26 19:32:14 +01005502 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
Takashi Iwai763f3562005-06-03 11:25:34 +02005503 hdspm_silence_playback(hdspm);
5504 }
5505 } else {
5506 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
5507 hdspm_silence_playback(hdspm);
5508 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005509_ok:
Takashi Iwai763f3562005-06-03 11:25:34 +02005510 snd_pcm_trigger_done(substream, substream);
5511 if (!hdspm->running && running)
5512 hdspm_start_audio(hdspm);
5513 else if (hdspm->running && !running)
5514 hdspm_stop_audio(hdspm);
5515 hdspm->running = running;
5516 spin_unlock(&hdspm->lock);
5517
5518 return 0;
5519}
5520
Takashi Iwai98274f02005-11-17 14:52:34 +01005521static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005522{
5523 return 0;
5524}
5525
Adrian Knoth0dca1792011-01-26 19:32:14 +01005526static unsigned int period_sizes_old[] = {
5527 64, 128, 256, 512, 1024, 2048, 4096
5528};
5529
5530static unsigned int period_sizes_new[] = {
5531 32, 64, 128, 256, 512, 1024, 2048, 4096
5532};
5533
5534/* RayDAT and AIO always have a buffer of 16384 samples per channel */
5535static unsigned int raydat_aio_buffer_sizes[] = {
5536 16384
5537};
Takashi Iwai763f3562005-06-03 11:25:34 +02005538
Takashi Iwai98274f02005-11-17 14:52:34 +01005539static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005540 .info = (SNDRV_PCM_INFO_MMAP |
5541 SNDRV_PCM_INFO_MMAP_VALID |
5542 SNDRV_PCM_INFO_NONINTERLEAVED |
5543 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
5544 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5545 .rates = (SNDRV_PCM_RATE_32000 |
5546 SNDRV_PCM_RATE_44100 |
5547 SNDRV_PCM_RATE_48000 |
5548 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005549 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5550 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
Takashi Iwai763f3562005-06-03 11:25:34 +02005551 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005552 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005553 .channels_min = 1,
5554 .channels_max = HDSPM_MAX_CHANNELS,
5555 .buffer_bytes_max =
5556 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
5557 .period_bytes_min = (64 * 4),
Adrian Knoth0dca1792011-01-26 19:32:14 +01005558 .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005559 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005560 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005561 .fifo_size = 0
5562};
5563
Takashi Iwai98274f02005-11-17 14:52:34 +01005564static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005565 .info = (SNDRV_PCM_INFO_MMAP |
5566 SNDRV_PCM_INFO_MMAP_VALID |
5567 SNDRV_PCM_INFO_NONINTERLEAVED |
5568 SNDRV_PCM_INFO_SYNC_START),
5569 .formats = SNDRV_PCM_FMTBIT_S32_LE,
5570 .rates = (SNDRV_PCM_RATE_32000 |
5571 SNDRV_PCM_RATE_44100 |
5572 SNDRV_PCM_RATE_48000 |
5573 SNDRV_PCM_RATE_64000 |
Remy Bruno3cee5a62006-10-16 12:46:32 +02005574 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
5575 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
Takashi Iwai763f3562005-06-03 11:25:34 +02005576 .rate_min = 32000,
Remy Bruno3cee5a62006-10-16 12:46:32 +02005577 .rate_max = 192000,
Takashi Iwai763f3562005-06-03 11:25:34 +02005578 .channels_min = 1,
5579 .channels_max = HDSPM_MAX_CHANNELS,
5580 .buffer_bytes_max =
5581 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
5582 .period_bytes_min = (64 * 4),
Adrian Knoth0dca1792011-01-26 19:32:14 +01005583 .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
Takashi Iwai763f3562005-06-03 11:25:34 +02005584 .periods_min = 2,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005585 .periods_max = 512,
Takashi Iwai763f3562005-06-03 11:25:34 +02005586 .fifo_size = 0
5587};
5588
Adrian Knoth0dca1792011-01-26 19:32:14 +01005589static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_old = {
5590 .count = ARRAY_SIZE(period_sizes_old),
5591 .list = period_sizes_old,
Takashi Iwai763f3562005-06-03 11:25:34 +02005592 .mask = 0
5593};
5594
Adrian Knoth0dca1792011-01-26 19:32:14 +01005595static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_new = {
5596 .count = ARRAY_SIZE(period_sizes_new),
5597 .list = period_sizes_new,
5598 .mask = 0
5599};
Takashi Iwai763f3562005-06-03 11:25:34 +02005600
Adrian Knoth0dca1792011-01-26 19:32:14 +01005601static struct snd_pcm_hw_constraint_list hw_constraints_raydat_io_buffer = {
5602 .count = ARRAY_SIZE(raydat_aio_buffer_sizes),
5603 .list = raydat_aio_buffer_sizes,
5604 .mask = 0
5605};
5606
5607static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
5608 struct snd_pcm_hw_rule *rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005609{
Takashi Iwai98274f02005-11-17 14:52:34 +01005610 struct hdspm *hdspm = rule->private;
5611 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005612 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005613 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005614 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5615
Adrian Knoth0dca1792011-01-26 19:32:14 +01005616 if (r->min > 96000 && r->max <= 192000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005617 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005618 .min = hdspm->qs_in_channels,
5619 .max = hdspm->qs_in_channels,
5620 .integer = 1,
5621 };
5622 return snd_interval_refine(c, &t);
5623 } else if (r->min > 48000 && r->max <= 96000) {
5624 struct snd_interval t = {
5625 .min = hdspm->ds_in_channels,
5626 .max = hdspm->ds_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005627 .integer = 1,
5628 };
5629 return snd_interval_refine(c, &t);
5630 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005631 struct snd_interval t = {
Adrian Knoth0dca1792011-01-26 19:32:14 +01005632 .min = hdspm->ss_in_channels,
5633 .max = hdspm->ss_in_channels,
Takashi Iwai763f3562005-06-03 11:25:34 +02005634 .integer = 1,
5635 };
5636 return snd_interval_refine(c, &t);
5637 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005638
Takashi Iwai763f3562005-06-03 11:25:34 +02005639 return 0;
5640}
5641
Adrian Knoth0dca1792011-01-26 19:32:14 +01005642static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
Takashi Iwai98274f02005-11-17 14:52:34 +01005643 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02005644{
Takashi Iwai98274f02005-11-17 14:52:34 +01005645 struct hdspm *hdspm = rule->private;
5646 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02005647 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01005648 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02005649 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5650
Adrian Knoth0dca1792011-01-26 19:32:14 +01005651 if (r->min > 96000 && r->max <= 192000) {
5652 struct snd_interval t = {
5653 .min = hdspm->qs_out_channels,
5654 .max = hdspm->qs_out_channels,
5655 .integer = 1,
5656 };
5657 return snd_interval_refine(c, &t);
5658 } else if (r->min > 48000 && r->max <= 96000) {
5659 struct snd_interval t = {
5660 .min = hdspm->ds_out_channels,
5661 .max = hdspm->ds_out_channels,
5662 .integer = 1,
5663 };
5664 return snd_interval_refine(c, &t);
5665 } else if (r->max < 64000) {
5666 struct snd_interval t = {
5667 .min = hdspm->ss_out_channels,
5668 .max = hdspm->ss_out_channels,
5669 .integer = 1,
5670 };
5671 return snd_interval_refine(c, &t);
5672 } else {
5673 }
5674 return 0;
5675}
5676
5677static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
5678 struct snd_pcm_hw_rule * rule)
5679{
5680 struct hdspm *hdspm = rule->private;
5681 struct snd_interval *c =
5682 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5683 struct snd_interval *r =
5684 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5685
5686 if (c->min >= hdspm->ss_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005687 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005688 .min = 32000,
5689 .max = 48000,
5690 .integer = 1,
5691 };
5692 return snd_interval_refine(r, &t);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005693 } else if (c->max <= hdspm->qs_in_channels) {
5694 struct snd_interval t = {
5695 .min = 128000,
5696 .max = 192000,
5697 .integer = 1,
5698 };
5699 return snd_interval_refine(r, &t);
5700 } else if (c->max <= hdspm->ds_in_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01005701 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02005702 .min = 64000,
5703 .max = 96000,
5704 .integer = 1,
5705 };
Takashi Iwai763f3562005-06-03 11:25:34 +02005706 return snd_interval_refine(r, &t);
5707 }
Adrian Knoth0dca1792011-01-26 19:32:14 +01005708
5709 return 0;
5710}
5711static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
5712 struct snd_pcm_hw_rule *rule)
5713{
5714 struct hdspm *hdspm = rule->private;
5715 struct snd_interval *c =
5716 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
5717 struct snd_interval *r =
5718 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
5719
5720 if (c->min >= hdspm->ss_out_channels) {
5721 struct snd_interval t = {
5722 .min = 32000,
5723 .max = 48000,
5724 .integer = 1,
5725 };
5726 return snd_interval_refine(r, &t);
5727 } else if (c->max <= hdspm->qs_out_channels) {
5728 struct snd_interval t = {
5729 .min = 128000,
5730 .max = 192000,
5731 .integer = 1,
5732 };
5733 return snd_interval_refine(r, &t);
5734 } else if (c->max <= hdspm->ds_out_channels) {
5735 struct snd_interval t = {
5736 .min = 64000,
5737 .max = 96000,
5738 .integer = 1,
5739 };
5740 return snd_interval_refine(r, &t);
5741 }
5742
Takashi Iwai763f3562005-06-03 11:25:34 +02005743 return 0;
5744}
5745
Adrian Knoth0dca1792011-01-26 19:32:14 +01005746static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005747 struct snd_pcm_hw_rule *rule)
5748{
5749 unsigned int list[3];
5750 struct hdspm *hdspm = rule->private;
5751 struct snd_interval *c = hw_param_interval(params,
5752 SNDRV_PCM_HW_PARAM_CHANNELS);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005753
5754 list[0] = hdspm->qs_in_channels;
5755 list[1] = hdspm->ds_in_channels;
5756 list[2] = hdspm->ss_in_channels;
5757 return snd_interval_list(c, 3, list, 0);
5758}
5759
5760static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params,
5761 struct snd_pcm_hw_rule *rule)
5762{
5763 unsigned int list[3];
5764 struct hdspm *hdspm = rule->private;
5765 struct snd_interval *c = hw_param_interval(params,
5766 SNDRV_PCM_HW_PARAM_CHANNELS);
5767
5768 list[0] = hdspm->qs_out_channels;
5769 list[1] = hdspm->ds_out_channels;
5770 list[2] = hdspm->ss_out_channels;
5771 return snd_interval_list(c, 3, list, 0);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005772}
5773
5774
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005775static unsigned int hdspm_aes32_sample_rates[] = {
5776 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000
5777};
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005778
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005779static struct snd_pcm_hw_constraint_list
5780hdspm_hw_constraints_aes32_sample_rates = {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005781 .count = ARRAY_SIZE(hdspm_aes32_sample_rates),
5782 .list = hdspm_aes32_sample_rates,
5783 .mask = 0
5784};
5785
Takashi Iwai98274f02005-11-17 14:52:34 +01005786static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005787{
Takashi Iwai98274f02005-11-17 14:52:34 +01005788 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5789 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005790
Takashi Iwai763f3562005-06-03 11:25:34 +02005791 spin_lock_irq(&hdspm->lock);
5792
5793 snd_pcm_set_sync(substream);
5794
Adrian Knoth0dca1792011-01-26 19:32:14 +01005795
Takashi Iwai763f3562005-06-03 11:25:34 +02005796 runtime->hw = snd_hdspm_playback_subinfo;
5797
5798 if (hdspm->capture_substream == NULL)
5799 hdspm_stop_audio(hdspm);
5800
5801 hdspm->playback_pid = current->pid;
5802 hdspm->playback_substream = substream;
5803
5804 spin_unlock_irq(&hdspm->lock);
5805
5806 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
5807
Adrian Knoth0dca1792011-01-26 19:32:14 +01005808 switch (hdspm->io_type) {
5809 case AIO:
5810 case RayDAT:
5811 snd_pcm_hw_constraint_list(runtime, 0,
5812 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5813 &hw_constraints_period_sizes_new);
5814 snd_pcm_hw_constraint_list(runtime, 0,
5815 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5816 &hw_constraints_raydat_io_buffer);
Takashi Iwai763f3562005-06-03 11:25:34 +02005817
Adrian Knoth0dca1792011-01-26 19:32:14 +01005818 break;
5819
5820 default:
5821 snd_pcm_hw_constraint_list(runtime, 0,
5822 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5823 &hw_constraints_period_sizes_old);
5824 }
5825
5826 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005827 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5828 &hdspm_hw_constraints_aes32_sample_rates);
5829 } else {
5830 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005831 snd_hdspm_hw_rule_out_channels, hdspm,
5832 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005833 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005834 snd_hdspm_hw_rule_out_channels_rate, hdspm,
5835 SNDRV_PCM_HW_PARAM_RATE, -1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005836
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005837 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005838 snd_hdspm_hw_rule_rate_out_channels, hdspm,
5839 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005840 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005841 return 0;
5842}
5843
Takashi Iwai98274f02005-11-17 14:52:34 +01005844static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005845{
Takashi Iwai98274f02005-11-17 14:52:34 +01005846 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005847
5848 spin_lock_irq(&hdspm->lock);
5849
5850 hdspm->playback_pid = -1;
5851 hdspm->playback_substream = NULL;
5852
5853 spin_unlock_irq(&hdspm->lock);
5854
5855 return 0;
5856}
5857
5858
Takashi Iwai98274f02005-11-17 14:52:34 +01005859static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005860{
Takashi Iwai98274f02005-11-17 14:52:34 +01005861 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
5862 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02005863
5864 spin_lock_irq(&hdspm->lock);
5865 snd_pcm_set_sync(substream);
5866 runtime->hw = snd_hdspm_capture_subinfo;
5867
5868 if (hdspm->playback_substream == NULL)
5869 hdspm_stop_audio(hdspm);
5870
5871 hdspm->capture_pid = current->pid;
5872 hdspm->capture_substream = substream;
5873
5874 spin_unlock_irq(&hdspm->lock);
5875
5876 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005877 switch (hdspm->io_type) {
5878 case AIO:
5879 case RayDAT:
5880 snd_pcm_hw_constraint_list(runtime, 0,
5881 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5882 &hw_constraints_period_sizes_new);
5883 snd_pcm_hw_constraint_list(runtime, 0,
5884 SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
5885 &hw_constraints_raydat_io_buffer);
5886 break;
5887
5888 default:
5889 snd_pcm_hw_constraint_list(runtime, 0,
5890 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
5891 &hw_constraints_period_sizes_old);
5892 }
5893
5894 if (AES32 == hdspm->io_type) {
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005895 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
5896 &hdspm_hw_constraints_aes32_sample_rates);
5897 } else {
5898 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005899 snd_hdspm_hw_rule_in_channels, hdspm,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005900 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5901 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005902 snd_hdspm_hw_rule_in_channels_rate, hdspm,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005903 SNDRV_PCM_HW_PARAM_RATE, -1);
Takashi Iwai763f3562005-06-03 11:25:34 +02005904
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005905 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
Adrian Knoth0dca1792011-01-26 19:32:14 +01005906 snd_hdspm_hw_rule_rate_in_channels, hdspm,
Remy Brunoffb2c3c2007-03-07 19:08:46 +01005907 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
5908 }
Takashi Iwai763f3562005-06-03 11:25:34 +02005909 return 0;
5910}
5911
Takashi Iwai98274f02005-11-17 14:52:34 +01005912static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02005913{
Takashi Iwai98274f02005-11-17 14:52:34 +01005914 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02005915
5916 spin_lock_irq(&hdspm->lock);
5917
5918 hdspm->capture_pid = -1;
5919 hdspm->capture_substream = NULL;
5920
5921 spin_unlock_irq(&hdspm->lock);
5922 return 0;
5923}
5924
Adrian Knoth0dca1792011-01-26 19:32:14 +01005925static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02005926{
Adrian Knoth0dca1792011-01-26 19:32:14 +01005927 /* we have nothing to initialize but the call is required */
5928 return 0;
5929}
5930
5931static inline int copy_u32_le(void __user *dest, void __iomem *src)
5932{
5933 u32 val = readl(src);
5934 return copy_to_user(dest, &val, 4);
5935}
5936
5937static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
5938 unsigned int cmd, unsigned long __user arg)
5939{
5940 void __user *argp = (void __user *)arg;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02005941 struct hdspm *hdspm = hw->private_data;
Takashi Iwai98274f02005-11-17 14:52:34 +01005942 struct hdspm_mixer_ioctl mixer;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005943 struct hdspm_config info;
5944 struct hdspm_status status;
Takashi Iwai98274f02005-11-17 14:52:34 +01005945 struct hdspm_version hdspm_version;
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005946 struct hdspm_peak_rms *levels;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005947 struct hdspm_ltc ltc;
5948 unsigned int statusregister;
5949 long unsigned int s;
5950 int i = 0;
Takashi Iwai763f3562005-06-03 11:25:34 +02005951
5952 switch (cmd) {
5953
Takashi Iwai763f3562005-06-03 11:25:34 +02005954 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005955 levels = &hdspm->peak_rms;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005956 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005957 levels->input_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005958 readl(hdspm->iobase +
5959 HDSPM_MADI_INPUT_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005960 levels->playback_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005961 readl(hdspm->iobase +
5962 HDSPM_MADI_PLAYBACK_PEAK + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005963 levels->output_peaks[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005964 readl(hdspm->iobase +
5965 HDSPM_MADI_OUTPUT_PEAK + i*4);
5966
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005967 levels->input_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005968 ((uint64_t) readl(hdspm->iobase +
5969 HDSPM_MADI_INPUT_RMS_H + i*4) << 32) |
5970 (uint64_t) readl(hdspm->iobase +
5971 HDSPM_MADI_INPUT_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005972 levels->playback_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005973 ((uint64_t)readl(hdspm->iobase +
5974 HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) |
5975 (uint64_t)readl(hdspm->iobase +
5976 HDSPM_MADI_PLAYBACK_RMS_L + i*4);
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005977 levels->output_rms[i] =
Adrian Knoth0dca1792011-01-26 19:32:14 +01005978 ((uint64_t)readl(hdspm->iobase +
5979 HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) |
5980 (uint64_t)readl(hdspm->iobase +
5981 HDSPM_MADI_OUTPUT_RMS_L + i*4);
5982 }
5983
5984 if (hdspm->system_sample_rate > 96000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005985 levels->speed = qs;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005986 } else if (hdspm->system_sample_rate > 48000) {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005987 levels->speed = ds;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005988 } else {
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005989 levels->speed = ss;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005990 }
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005991 levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
Adrian Knoth0dca1792011-01-26 19:32:14 +01005992
Jaroslav Kysela730a5862011-01-27 13:03:15 +01005993 s = copy_to_user(argp, levels, sizeof(struct hdspm_peak_rms));
Adrian Knoth0dca1792011-01-26 19:32:14 +01005994 if (0 != s) {
5995 /* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu
5996 [Levels]\n", sizeof(struct hdspm_peak_rms), s);
5997 */
Takashi Iwai763f3562005-06-03 11:25:34 +02005998 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01005999 }
6000 break;
6001
6002 case SNDRV_HDSPM_IOCTL_GET_LTC:
6003 ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
6004 i = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
6005 if (i & HDSPM_TCO1_LTC_Input_valid) {
6006 switch (i & (HDSPM_TCO1_LTC_Format_LSB |
6007 HDSPM_TCO1_LTC_Format_MSB)) {
6008 case 0:
6009 ltc.format = fps_24;
6010 break;
6011 case HDSPM_TCO1_LTC_Format_LSB:
6012 ltc.format = fps_25;
6013 break;
6014 case HDSPM_TCO1_LTC_Format_MSB:
6015 ltc.format = fps_2997;
6016 break;
6017 default:
6018 ltc.format = 30;
6019 break;
6020 }
6021 if (i & HDSPM_TCO1_set_drop_frame_flag) {
6022 ltc.frame = drop_frame;
6023 } else {
6024 ltc.frame = full_frame;
6025 }
6026 } else {
6027 ltc.format = format_invalid;
6028 ltc.frame = frame_invalid;
6029 }
6030 if (i & HDSPM_TCO1_Video_Input_Format_NTSC) {
6031 ltc.input_format = ntsc;
6032 } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) {
6033 ltc.input_format = pal;
6034 } else {
6035 ltc.input_format = no_video;
6036 }
6037
6038 s = copy_to_user(argp, &ltc, sizeof(struct hdspm_ltc));
6039 if (0 != s) {
6040 /*
6041 snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */
Takashi Iwai763f3562005-06-03 11:25:34 +02006042 return -EFAULT;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006043 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006044
6045 break;
Takashi Iwai763f3562005-06-03 11:25:34 +02006046
Adrian Knoth0dca1792011-01-26 19:32:14 +01006047 case SNDRV_HDSPM_IOCTL_GET_CONFIG:
Takashi Iwai763f3562005-06-03 11:25:34 +02006048
6049 spin_lock_irq(&hdspm->lock);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006050 info.pref_sync_ref = hdspm_pref_sync_ref(hdspm);
6051 info.wordclock_sync_check = hdspm_wc_sync_check(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006052
6053 info.system_sample_rate = hdspm->system_sample_rate;
6054 info.autosync_sample_rate =
Adrian Knoth0dca1792011-01-26 19:32:14 +01006055 hdspm_external_sample_rate(hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006056 info.system_clock_mode = hdspm_system_clock_mode(hdspm);
6057 info.clock_source = hdspm_clock_source(hdspm);
6058 info.autosync_ref = hdspm_autosync_ref(hdspm);
6059 info.line_out = hdspm_line_out(hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006060 info.passthru = 0;
6061 spin_unlock_irq(&hdspm->lock);
6062 if (copy_to_user((void __user *) arg, &info, sizeof(info)))
6063 return -EFAULT;
6064 break;
6065
Adrian Knoth0dca1792011-01-26 19:32:14 +01006066 case SNDRV_HDSPM_IOCTL_GET_STATUS:
6067 status.card_type = hdspm->io_type;
6068
6069 status.autosync_source = hdspm_autosync_ref(hdspm);
6070
6071 status.card_clock = 110069313433624ULL;
6072 status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
6073
6074 switch (hdspm->io_type) {
6075 case MADI:
6076 case MADIface:
6077 status.card_specific.madi.sync_wc =
6078 hdspm_wc_sync_check(hdspm);
6079 status.card_specific.madi.sync_madi =
6080 hdspm_madi_sync_check(hdspm);
6081 status.card_specific.madi.sync_tco =
6082 hdspm_tco_sync_check(hdspm);
6083 status.card_specific.madi.sync_in =
6084 hdspm_sync_in_sync_check(hdspm);
6085
6086 statusregister =
6087 hdspm_read(hdspm, HDSPM_statusRegister);
6088 status.card_specific.madi.madi_input =
6089 (statusregister & HDSPM_AB_int) ? 1 : 0;
6090 status.card_specific.madi.channel_format =
6091 (statusregister & HDSPM_TX_64ch) ? 1 : 0;
6092 /* TODO: Mac driver sets it when f_s>48kHz */
6093 status.card_specific.madi.frame_format = 0;
6094
6095 default:
6096 break;
6097 }
6098
6099 if (copy_to_user((void __user *) arg, &status, sizeof(status)))
6100 return -EFAULT;
6101
6102
6103 break;
6104
Takashi Iwai763f3562005-06-03 11:25:34 +02006105 case SNDRV_HDSPM_IOCTL_GET_VERSION:
Adrian Knoth0dca1792011-01-26 19:32:14 +01006106 hdspm_version.card_type = hdspm->io_type;
6107 strncpy(hdspm_version.cardname, hdspm->card_name,
6108 sizeof(hdspm_version.cardname));
6109 hdspm_version.serial = (hdspm_read(hdspm,
6110 HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
Takashi Iwai763f3562005-06-03 11:25:34 +02006111 hdspm_version.firmware_rev = hdspm->firmware_rev;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006112 hdspm_version.addons = 0;
6113 if (hdspm->tco)
6114 hdspm_version.addons |= HDSPM_ADDON_TCO;
6115
Takashi Iwai763f3562005-06-03 11:25:34 +02006116 if (copy_to_user((void __user *) arg, &hdspm_version,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006117 sizeof(hdspm_version)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006118 return -EFAULT;
6119 break;
6120
6121 case SNDRV_HDSPM_IOCTL_GET_MIXER:
6122 if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
6123 return -EFAULT;
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006124 if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006125 sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02006126 return -EFAULT;
6127 break;
6128
6129 default:
6130 return -EINVAL;
6131 }
6132 return 0;
6133}
6134
Takashi Iwai98274f02005-11-17 14:52:34 +01006135static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006136 .open = snd_hdspm_playback_open,
6137 .close = snd_hdspm_playback_release,
6138 .ioctl = snd_hdspm_ioctl,
6139 .hw_params = snd_hdspm_hw_params,
6140 .hw_free = snd_hdspm_hw_free,
6141 .prepare = snd_hdspm_prepare,
6142 .trigger = snd_hdspm_trigger,
6143 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006144 .page = snd_pcm_sgbuf_ops_page,
6145};
6146
Takashi Iwai98274f02005-11-17 14:52:34 +01006147static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02006148 .open = snd_hdspm_capture_open,
6149 .close = snd_hdspm_capture_release,
6150 .ioctl = snd_hdspm_ioctl,
6151 .hw_params = snd_hdspm_hw_params,
6152 .hw_free = snd_hdspm_hw_free,
6153 .prepare = snd_hdspm_prepare,
6154 .trigger = snd_hdspm_trigger,
6155 .pointer = snd_hdspm_hw_pointer,
Takashi Iwai763f3562005-06-03 11:25:34 +02006156 .page = snd_pcm_sgbuf_ops_page,
6157};
6158
Takashi Iwai98274f02005-11-17 14:52:34 +01006159static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
6160 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006161{
Takashi Iwai98274f02005-11-17 14:52:34 +01006162 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02006163 int err;
6164
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006165 err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw);
6166 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006167 return err;
6168
6169 hdspm->hwdep = hw;
6170 hw->private_data = hdspm;
6171 strcpy(hw->name, "HDSPM hwdep interface");
6172
Adrian Knoth0dca1792011-01-26 19:32:14 +01006173 hw->ops.open = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006174 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006175 hw->ops.release = snd_hdspm_hwdep_dummy_op;
Takashi Iwai763f3562005-06-03 11:25:34 +02006176
6177 return 0;
6178}
6179
6180
6181/*------------------------------------------------------------
Adrian Knoth0dca1792011-01-26 19:32:14 +01006182 memory interface
Takashi Iwai763f3562005-06-03 11:25:34 +02006183 ------------------------------------------------------------*/
Adrian Knoth0dca1792011-01-26 19:32:14 +01006184static int __devinit snd_hdspm_preallocate_memory(struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006185{
6186 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01006187 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006188 size_t wanted;
6189
6190 pcm = hdspm->pcm;
6191
Remy Bruno3cee5a62006-10-16 12:46:32 +02006192 wanted = HDSPM_DMA_AREA_BYTES;
Takashi Iwai763f3562005-06-03 11:25:34 +02006193
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006194 err =
Takashi Iwai763f3562005-06-03 11:25:34 +02006195 snd_pcm_lib_preallocate_pages_for_all(pcm,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006196 SNDRV_DMA_TYPE_DEV_SG,
Takashi Iwai763f3562005-06-03 11:25:34 +02006197 snd_dma_pci_data(hdspm->pci),
6198 wanted,
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006199 wanted);
6200 if (err < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006201 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006202
6203 return err;
6204 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006205 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02006206
6207 return 0;
6208}
6209
Adrian Knoth0dca1792011-01-26 19:32:14 +01006210
6211static void hdspm_set_sgbuf(struct hdspm *hdspm,
Takashi Iwai77a23f22008-08-21 13:00:13 +02006212 struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02006213 unsigned int reg, int channels)
6214{
6215 int i;
Adrian Knoth0dca1792011-01-26 19:32:14 +01006216
6217 /* continuous memory segment */
Takashi Iwai763f3562005-06-03 11:25:34 +02006218 for (i = 0; i < (channels * 16); i++)
6219 hdspm_write(hdspm, reg + 4 * i,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006220 snd_pcm_sgbuf_get_addr(substream, 4096 * i));
Takashi Iwai763f3562005-06-03 11:25:34 +02006221}
6222
Adrian Knoth0dca1792011-01-26 19:32:14 +01006223
Takashi Iwai763f3562005-06-03 11:25:34 +02006224/* ------------- ALSA Devices ---------------------------- */
Takashi Iwai98274f02005-11-17 14:52:34 +01006225static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006226 struct hdspm *hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006227{
Takashi Iwai98274f02005-11-17 14:52:34 +01006228 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02006229 int err;
6230
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006231 err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm);
6232 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006233 return err;
6234
6235 hdspm->pcm = pcm;
6236 pcm->private_data = hdspm;
6237 strcpy(pcm->name, hdspm->card_name);
6238
6239 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
6240 &snd_hdspm_playback_ops);
6241 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
6242 &snd_hdspm_capture_ops);
6243
6244 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
6245
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006246 err = snd_hdspm_preallocate_memory(hdspm);
6247 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006248 return err;
6249
6250 return 0;
6251}
6252
Takashi Iwai98274f02005-11-17 14:52:34 +01006253static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006254{
6255 snd_hdspm_flush_midi_input(hdspm, 0);
6256 snd_hdspm_flush_midi_input(hdspm, 1);
6257}
6258
Takashi Iwai98274f02005-11-17 14:52:34 +01006259static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
6260 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006261{
Adrian Knoth0dca1792011-01-26 19:32:14 +01006262 int err, i;
Takashi Iwai763f3562005-06-03 11:25:34 +02006263
6264 snd_printdd("Create card...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006265 err = snd_hdspm_create_pcm(card, hdspm);
6266 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006267 return err;
6268
Adrian Knoth0dca1792011-01-26 19:32:14 +01006269 i = 0;
6270 while (i < hdspm->midiPorts) {
6271 err = snd_hdspm_create_midi(card, hdspm, i);
6272 if (err < 0) {
6273 return err;
6274 }
6275 i++;
6276 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006277
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006278 err = snd_hdspm_create_controls(card, hdspm);
6279 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006280 return err;
6281
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006282 err = snd_hdspm_create_hwdep(card, hdspm);
6283 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006284 return err;
6285
6286 snd_printdd("proc init...\n");
6287 snd_hdspm_proc_init(hdspm);
6288
6289 hdspm->system_sample_rate = -1;
6290 hdspm->last_external_sample_rate = -1;
6291 hdspm->last_internal_sample_rate = -1;
6292 hdspm->playback_pid = -1;
6293 hdspm->capture_pid = -1;
6294 hdspm->capture_substream = NULL;
6295 hdspm->playback_substream = NULL;
6296
6297 snd_printdd("Set defaults...\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006298 err = snd_hdspm_set_defaults(hdspm);
6299 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006300 return err;
6301
6302 snd_printdd("Update mixer controls...\n");
6303 hdspm_update_simple_mixer_controls(hdspm);
6304
6305 snd_printdd("Initializeing complete ???\n");
6306
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006307 err = snd_card_register(card);
6308 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006309 snd_printk(KERN_ERR "HDSPM: error registering card\n");
6310 return err;
6311 }
6312
6313 snd_printdd("... yes now\n");
6314
6315 return 0;
6316}
6317
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006318static int __devinit snd_hdspm_create(struct snd_card *card,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006319 struct hdspm *hdspm) {
6320
Takashi Iwai763f3562005-06-03 11:25:34 +02006321 struct pci_dev *pci = hdspm->pci;
6322 int err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006323 unsigned long io_extent;
6324
6325 hdspm->irq = -1;
Takashi Iwai763f3562005-06-03 11:25:34 +02006326 hdspm->card = card;
6327
6328 spin_lock_init(&hdspm->lock);
6329
Takashi Iwai763f3562005-06-03 11:25:34 +02006330 pci_read_config_word(hdspm->pci,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006331 PCI_CLASS_REVISION, &hdspm->firmware_rev);
Remy Bruno3cee5a62006-10-16 12:46:32 +02006332
Takashi Iwai763f3562005-06-03 11:25:34 +02006333 strcpy(card->mixername, "Xilinx FPGA");
Adrian Knoth0dca1792011-01-26 19:32:14 +01006334 strcpy(card->driver, "HDSPM");
6335
6336 switch (hdspm->firmware_rev) {
6337 case HDSPM_MADI_REV:
6338 hdspm->io_type = MADI;
6339 hdspm->card_name = "RME MADI";
6340 hdspm->midiPorts = 3;
6341 break;
6342 case HDSPM_RAYDAT_REV:
6343 hdspm->io_type = RayDAT;
6344 hdspm->card_name = "RME RayDAT";
6345 hdspm->midiPorts = 2;
6346 break;
6347 case HDSPM_AIO_REV:
6348 hdspm->io_type = AIO;
6349 hdspm->card_name = "RME AIO";
6350 hdspm->midiPorts = 1;
6351 break;
6352 case HDSPM_MADIFACE_REV:
6353 hdspm->io_type = MADIface;
6354 hdspm->card_name = "RME MADIface";
6355 hdspm->midiPorts = 1;
6356 break;
6357 case HDSPM_AES_REV:
6358 hdspm->io_type = AES32;
6359 hdspm->card_name = "RME AES32";
6360 hdspm->midiPorts = 2;
6361 break;
Remy Bruno3cee5a62006-10-16 12:46:32 +02006362 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006363
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006364 err = pci_enable_device(pci);
6365 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006366 return err;
6367
6368 pci_set_master(hdspm->pci);
6369
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006370 err = pci_request_regions(pci, "hdspm");
6371 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006372 return err;
6373
6374 hdspm->port = pci_resource_start(pci, 0);
6375 io_extent = pci_resource_len(pci, 0);
6376
6377 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006378 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006379
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006380 hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
6381 if (!hdspm->iobase) {
6382 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006383 "unable to remap region 0x%lx-0x%lx\n",
6384 hdspm->port, hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006385 return -EBUSY;
6386 }
6387 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006388 (unsigned long)hdspm->iobase, hdspm->port,
6389 hdspm->port + io_extent - 1);
Takashi Iwai763f3562005-06-03 11:25:34 +02006390
6391 if (request_irq(pci->irq, snd_hdspm_interrupt,
Adrian Knoth0dca1792011-01-26 19:32:14 +01006392 IRQF_SHARED, "hdspm", hdspm)) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006393 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
6394 return -EBUSY;
6395 }
6396
6397 snd_printdd("use IRQ %d\n", pci->irq);
6398
6399 hdspm->irq = pci->irq;
Takashi Iwai763f3562005-06-03 11:25:34 +02006400
Andrew Mortone2eba3e2006-01-20 14:07:13 +01006401 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Adrian Knoth0dca1792011-01-26 19:32:14 +01006402 sizeof(struct hdspm_mixer));
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006403 hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
6404 if (!hdspm->mixer) {
6405 snd_printk(KERN_ERR "HDSPM: "
Adrian Knoth0dca1792011-01-26 19:32:14 +01006406 "unable to kmalloc Mixer memory of %d Bytes\n",
6407 (int)sizeof(struct hdspm_mixer));
Takashi Iwai763f3562005-06-03 11:25:34 +02006408 return err;
6409 }
6410
Adrian Knoth0dca1792011-01-26 19:32:14 +01006411 hdspm->port_names_in = NULL;
6412 hdspm->port_names_out = NULL;
6413
6414 switch (hdspm->io_type) {
6415 case AES32:
Adrian Knoth432d2502011-02-23 11:43:08 +01006416 hdspm->ss_in_channels = hdspm->ss_out_channels = 16;
6417 hdspm->ds_in_channels = hdspm->ds_out_channels = 16;
6418 hdspm->qs_in_channels = hdspm->qs_out_channels = 16;
6419
6420 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6421 channel_map_aes32;
6422 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6423 channel_map_aes32;
6424 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6425 channel_map_aes32;
6426 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6427 texts_ports_aes32;
6428 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6429 texts_ports_aes32;
6430 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6431 texts_ports_aes32;
6432
6433 hdspm->max_channels_out = hdspm->max_channels_in = 16;
6434 hdspm->port_names_in = hdspm->port_names_out =
6435 texts_ports_aes32;
6436 hdspm->channel_map_in = hdspm->channel_map_out =
6437 channel_map_aes32;
6438
Adrian Knoth0dca1792011-01-26 19:32:14 +01006439 break;
6440
6441 case MADI:
6442 case MADIface:
6443 hdspm->ss_in_channels = hdspm->ss_out_channels =
6444 MADI_SS_CHANNELS;
6445 hdspm->ds_in_channels = hdspm->ds_out_channels =
6446 MADI_DS_CHANNELS;
6447 hdspm->qs_in_channels = hdspm->qs_out_channels =
6448 MADI_QS_CHANNELS;
6449
6450 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6451 channel_map_unity_ss;
6452 hdspm->channel_map_in_ds = hdspm->channel_map_out_ss =
6453 channel_map_unity_ss;
6454 hdspm->channel_map_in_qs = hdspm->channel_map_out_ss =
6455 channel_map_unity_ss;
6456
6457 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6458 texts_ports_madi;
6459 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6460 texts_ports_madi;
6461 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6462 texts_ports_madi;
6463 break;
6464
6465 case AIO:
6466 if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
6467 snd_printk(KERN_INFO "HDSPM: AEB input board found, but not supported\n");
6468 }
6469
6470 hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
6471 hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
6472 hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
6473 hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS;
6474 hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
6475 hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
6476
6477 hdspm->channel_map_out_ss = channel_map_aio_out_ss;
6478 hdspm->channel_map_out_ds = channel_map_aio_out_ds;
6479 hdspm->channel_map_out_qs = channel_map_aio_out_qs;
6480
6481 hdspm->channel_map_in_ss = channel_map_aio_in_ss;
6482 hdspm->channel_map_in_ds = channel_map_aio_in_ds;
6483 hdspm->channel_map_in_qs = channel_map_aio_in_qs;
6484
6485 hdspm->port_names_in_ss = texts_ports_aio_in_ss;
6486 hdspm->port_names_out_ss = texts_ports_aio_out_ss;
6487 hdspm->port_names_in_ds = texts_ports_aio_in_ds;
6488 hdspm->port_names_out_ds = texts_ports_aio_out_ds;
6489 hdspm->port_names_in_qs = texts_ports_aio_in_qs;
6490 hdspm->port_names_out_qs = texts_ports_aio_out_qs;
6491
6492 break;
6493
6494 case RayDAT:
6495 hdspm->ss_in_channels = hdspm->ss_out_channels =
6496 RAYDAT_SS_CHANNELS;
6497 hdspm->ds_in_channels = hdspm->ds_out_channels =
6498 RAYDAT_DS_CHANNELS;
6499 hdspm->qs_in_channels = hdspm->qs_out_channels =
6500 RAYDAT_QS_CHANNELS;
6501
6502 hdspm->max_channels_in = RAYDAT_SS_CHANNELS;
6503 hdspm->max_channels_out = RAYDAT_SS_CHANNELS;
6504
6505 hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
6506 channel_map_raydat_ss;
6507 hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
6508 channel_map_raydat_ds;
6509 hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
6510 channel_map_raydat_qs;
6511 hdspm->channel_map_in = hdspm->channel_map_out =
6512 channel_map_raydat_ss;
6513
6514 hdspm->port_names_in_ss = hdspm->port_names_out_ss =
6515 texts_ports_raydat_ss;
6516 hdspm->port_names_in_ds = hdspm->port_names_out_ds =
6517 texts_ports_raydat_ds;
6518 hdspm->port_names_in_qs = hdspm->port_names_out_qs =
6519 texts_ports_raydat_qs;
6520
6521
6522 break;
6523
6524 }
6525
6526 /* TCO detection */
6527 switch (hdspm->io_type) {
6528 case AIO:
6529 case RayDAT:
6530 if (hdspm_read(hdspm, HDSPM_statusRegister2) &
6531 HDSPM_s2_tco_detect) {
6532 hdspm->midiPorts++;
6533 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6534 GFP_KERNEL);
6535 if (NULL != hdspm->tco) {
6536 hdspm_tco_write(hdspm);
6537 }
6538 snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n");
6539 } else {
6540 hdspm->tco = NULL;
6541 }
6542 break;
6543
6544 case MADI:
6545 if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
6546 hdspm->midiPorts++;
6547 hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
6548 GFP_KERNEL);
6549 if (NULL != hdspm->tco) {
6550 hdspm_tco_write(hdspm);
6551 }
6552 snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n");
6553 } else {
6554 hdspm->tco = NULL;
6555 }
6556 break;
6557
6558 default:
6559 hdspm->tco = NULL;
6560 }
6561
6562 /* texts */
6563 switch (hdspm->io_type) {
6564 case AES32:
6565 if (hdspm->tco) {
6566 hdspm->texts_autosync = texts_autosync_aes_tco;
6567 hdspm->texts_autosync_items = 10;
6568 } else {
6569 hdspm->texts_autosync = texts_autosync_aes;
6570 hdspm->texts_autosync_items = 9;
6571 }
6572 break;
6573
6574 case MADI:
6575 if (hdspm->tco) {
6576 hdspm->texts_autosync = texts_autosync_madi_tco;
6577 hdspm->texts_autosync_items = 4;
6578 } else {
6579 hdspm->texts_autosync = texts_autosync_madi;
6580 hdspm->texts_autosync_items = 3;
6581 }
6582 break;
6583
6584 case MADIface:
6585
6586 break;
6587
6588 case RayDAT:
6589 if (hdspm->tco) {
6590 hdspm->texts_autosync = texts_autosync_raydat_tco;
6591 hdspm->texts_autosync_items = 9;
6592 } else {
6593 hdspm->texts_autosync = texts_autosync_raydat;
6594 hdspm->texts_autosync_items = 8;
6595 }
6596 break;
6597
6598 case AIO:
6599 if (hdspm->tco) {
6600 hdspm->texts_autosync = texts_autosync_aio_tco;
6601 hdspm->texts_autosync_items = 6;
6602 } else {
6603 hdspm->texts_autosync = texts_autosync_aio;
6604 hdspm->texts_autosync_items = 5;
6605 }
6606 break;
6607
6608 }
6609
6610 tasklet_init(&hdspm->midi_tasklet,
6611 hdspm_midi_tasklet, (unsigned long) hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +02006612
6613 snd_printdd("create alsa devices.\n");
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006614 err = snd_hdspm_create_alsa_devices(card, hdspm);
6615 if (err < 0)
Takashi Iwai763f3562005-06-03 11:25:34 +02006616 return err;
6617
6618 snd_hdspm_initialize_midi_flush(hdspm);
6619
6620 return 0;
6621}
6622
Adrian Knoth0dca1792011-01-26 19:32:14 +01006623
Takashi Iwai98274f02005-11-17 14:52:34 +01006624static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02006625{
6626
6627 if (hdspm->port) {
6628
6629 /* stop th audio, and cancel all interrupts */
6630 hdspm->control_register &=
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006631 ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
Adrian Knoth0dca1792011-01-26 19:32:14 +01006632 HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable |
6633 HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable);
Takashi Iwai763f3562005-06-03 11:25:34 +02006634 hdspm_write(hdspm, HDSPM_controlRegister,
6635 hdspm->control_register);
6636 }
6637
6638 if (hdspm->irq >= 0)
6639 free_irq(hdspm->irq, (void *) hdspm);
6640
Jesper Juhlfc584222005-10-24 15:11:28 +02006641 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02006642
6643 if (hdspm->iobase)
6644 iounmap(hdspm->iobase);
6645
Takashi Iwai763f3562005-06-03 11:25:34 +02006646 if (hdspm->port)
6647 pci_release_regions(hdspm->pci);
6648
6649 pci_disable_device(hdspm->pci);
6650 return 0;
6651}
6652
Adrian Knoth0dca1792011-01-26 19:32:14 +01006653
Takashi Iwai98274f02005-11-17 14:52:34 +01006654static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02006655{
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006656 struct hdspm *hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006657
6658 if (hdspm)
6659 snd_hdspm_free(hdspm);
6660}
6661
Adrian Knoth0dca1792011-01-26 19:32:14 +01006662
Takashi Iwai763f3562005-06-03 11:25:34 +02006663static int __devinit snd_hdspm_probe(struct pci_dev *pci,
6664 const struct pci_device_id *pci_id)
6665{
6666 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01006667 struct hdspm *hdspm;
6668 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02006669 int err;
6670
6671 if (dev >= SNDRV_CARDS)
6672 return -ENODEV;
6673 if (!enable[dev]) {
6674 dev++;
6675 return -ENOENT;
6676 }
6677
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006678 err = snd_card_create(index[dev], id[dev],
Adrian Knoth0dca1792011-01-26 19:32:14 +01006679 THIS_MODULE, sizeof(struct hdspm), &card);
Takashi Iwaie58de7b2008-12-28 16:44:30 +01006680 if (err < 0)
6681 return err;
Takashi Iwai763f3562005-06-03 11:25:34 +02006682
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006683 hdspm = card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02006684 card->private_free = snd_hdspm_card_free;
6685 hdspm->dev = dev;
6686 hdspm->pci = pci;
6687
Takashi Iwaic187c042007-02-19 15:27:33 +01006688 snd_card_set_dev(card, &pci->dev);
6689
Adrian Knoth0dca1792011-01-26 19:32:14 +01006690 err = snd_hdspm_create(card, hdspm);
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006691 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006692 snd_card_free(card);
6693 return err;
6694 }
6695
Adrian Knoth0dca1792011-01-26 19:32:14 +01006696 if (hdspm->io_type != MADIface) {
6697 sprintf(card->shortname, "%s_%x",
6698 hdspm->card_name,
6699 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
6700 sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d",
6701 hdspm->card_name,
6702 (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF,
6703 hdspm->port, hdspm->irq);
6704 } else {
6705 sprintf(card->shortname, "%s", hdspm->card_name);
6706 sprintf(card->longname, "%s at 0x%lx, irq %d",
6707 hdspm->card_name, hdspm->port, hdspm->irq);
6708 }
Takashi Iwai763f3562005-06-03 11:25:34 +02006709
Takashi Iwaief5fa1a2007-07-27 16:52:46 +02006710 err = snd_card_register(card);
6711 if (err < 0) {
Takashi Iwai763f3562005-06-03 11:25:34 +02006712 snd_card_free(card);
6713 return err;
6714 }
6715
6716 pci_set_drvdata(pci, card);
6717
6718 dev++;
6719 return 0;
6720}
6721
6722static void __devexit snd_hdspm_remove(struct pci_dev *pci)
6723{
6724 snd_card_free(pci_get_drvdata(pci));
6725 pci_set_drvdata(pci, NULL);
6726}
6727
6728static struct pci_driver driver = {
6729 .name = "RME Hammerfall DSP MADI",
Takashi Iwai763f3562005-06-03 11:25:34 +02006730 .id_table = snd_hdspm_ids,
6731 .probe = snd_hdspm_probe,
6732 .remove = __devexit_p(snd_hdspm_remove),
6733};
6734
6735
6736static int __init alsa_card_hdspm_init(void)
6737{
6738 return pci_register_driver(&driver);
6739}
6740
6741static void __exit alsa_card_hdspm_exit(void)
6742{
6743 pci_unregister_driver(&driver);
6744}
6745
6746module_init(alsa_card_hdspm_init)
6747module_exit(alsa_card_hdspm_exit)